2
0

kv.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. package storage
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "hash/crc32"
  7. "io"
  8. "net"
  9. "strings"
  10. "sync"
  11. "time"
  12. )
  13. const (
  14. headerSize = 32
  15. headerMagic = "PKBF"
  16. headerVersion = 1
  17. opPing = 1
  18. opStatus = 2
  19. opGet = 3
  20. opPut = 4
  21. opDelete = 5
  22. opExists = 6
  23. opMultiGet = 7
  24. opBatchWrite = 8
  25. opScanOpen = 9
  26. opScanNext = 10
  27. opScanClose = 11
  28. opCompareBatch = 12
  29. batchPut = 1
  30. batchDelete = 2
  31. statusOK = 0
  32. statusNotFound = 1
  33. statusError = 2
  34. maxKeySize = 1024 * 1024
  35. maxValueSize = 64 * 1024 * 1024
  36. maxTransactionSize = 64 * 1024 * 1024
  37. maxOperations = 65535
  38. maxFrameSize = maxKeySize + maxValueSize + 1024
  39. scanPageSize = 1024
  40. existsPipelineSize = 128
  41. )
  42. var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
  43. var (
  44. ErrKeyNotFound = errors.New("key not found")
  45. ErrProtocol = errors.New("pkbfi protocol error")
  46. )
  47. func crc32c(p []byte) uint32 {
  48. return crc32.Checksum(p, crc32cTable)
  49. }
  50. func putU16(b []byte, v uint16) {
  51. b[0] = byte(v)
  52. b[1] = byte(v >> 8)
  53. }
  54. func putU32(b []byte, v uint32) {
  55. b[0] = byte(v)
  56. b[1] = byte(v >> 8)
  57. b[2] = byte(v >> 16)
  58. b[3] = byte(v >> 24)
  59. }
  60. func putU64(b []byte, v uint64) {
  61. b[0] = byte(v)
  62. b[1] = byte(v >> 8)
  63. b[2] = byte(v >> 16)
  64. b[3] = byte(v >> 24)
  65. b[4] = byte(v >> 32)
  66. b[5] = byte(v >> 40)
  67. b[6] = byte(v >> 48)
  68. b[7] = byte(v >> 56)
  69. }
  70. func getU16(b []byte) uint16 {
  71. return uint16(b[0]) | uint16(b[1])<<8
  72. }
  73. func getU32(b []byte) uint32 {
  74. return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
  75. }
  76. func getU64(b []byte) uint64 {
  77. return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
  78. uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
  79. }
  80. func encodeFrame(opcode, flags uint16, requestID uint64, payload []byte) []byte {
  81. frame := make([]byte, headerSize+len(payload))
  82. copy(frame[0:4], headerMagic)
  83. putU16(frame[4:6], headerVersion)
  84. putU16(frame[6:8], 0)
  85. putU16(frame[8:10], opcode)
  86. putU16(frame[10:12], flags)
  87. putU64(frame[12:20], requestID)
  88. putU32(frame[20:24], uint32(len(payload)))
  89. putU32(frame[24:28], crc32c(payload))
  90. putU32(frame[28:32], 0)
  91. putU32(frame[28:32], crc32c(frame[0:32]))
  92. copy(frame[32:], payload)
  93. return frame
  94. }
  95. func readFrame(r *bufio.Reader) (uint16, uint16, uint64, []byte, error) {
  96. var header [headerSize]byte
  97. if _, err := io.ReadFull(r, header[:]); err != nil {
  98. return 0, 0, 0, nil, err
  99. }
  100. if string(header[0:4]) != headerMagic {
  101. return 0, 0, 0, nil, fmt.Errorf("%w: invalid magic", ErrProtocol)
  102. }
  103. if getU16(header[4:6]) != headerVersion {
  104. return 0, 0, 0, nil, fmt.Errorf("%w: incompatible version", ErrProtocol)
  105. }
  106. payloadLen := getU32(header[20:24])
  107. if payloadLen > maxFrameSize {
  108. return 0, 0, 0, nil, fmt.Errorf("%w: frame too large", ErrProtocol)
  109. }
  110. headerCRC := getU32(header[28:32])
  111. var headerCopy [headerSize]byte
  112. copy(headerCopy[:], header[:])
  113. putU32(headerCopy[28:32], 0)
  114. if crc32c(headerCopy[:]) != headerCRC {
  115. return 0, 0, 0, nil, fmt.Errorf("%w: header checksum mismatch", ErrProtocol)
  116. }
  117. payload := make([]byte, payloadLen)
  118. if _, err := io.ReadFull(r, payload); err != nil {
  119. return 0, 0, 0, nil, err
  120. }
  121. if crc32c(payload) != getU32(header[24:28]) {
  122. return 0, 0, 0, nil, fmt.Errorf("%w: payload checksum mismatch", ErrProtocol)
  123. }
  124. return getU16(header[8:10]), getU16(header[10:12]), getU64(header[12:20]), payload, nil
  125. }
  126. func encodeResponse(opcode uint16, requestID uint64, body []byte) []byte {
  127. return encodeFrame(opcode|0x8000, 1, requestID, body)
  128. }
  129. func oneKeyPayload(key []byte) []byte {
  130. payload := make([]byte, 4+len(key))
  131. putU32(payload[0:4], uint32(len(key)))
  132. copy(payload[4:], key)
  133. return payload
  134. }
  135. func validateKey(key []byte) error {
  136. if len(key) > maxKeySize {
  137. return fmt.Errorf("pkbfi: key exceeds %d bytes", maxKeySize)
  138. }
  139. return nil
  140. }
  141. func validateValue(value []byte) error {
  142. if len(value) > maxValueSize {
  143. return fmt.Errorf("pkbfi: value exceeds %d bytes", maxValueSize)
  144. }
  145. return nil
  146. }
  147. func parseOneKey(payload []byte) ([]byte, bool) {
  148. if len(payload) < 4 {
  149. return nil, false
  150. }
  151. length := getU32(payload[0:4])
  152. if length > maxKeySize || uint64(4)+uint64(length) != uint64(len(payload)) {
  153. return nil, false
  154. }
  155. return payload[4:], true
  156. }
  157. func errorBody(message string) []byte {
  158. body := make([]byte, 2+len(message))
  159. putU16(body[0:2], statusError)
  160. copy(body[2:], message)
  161. return body
  162. }
  163. type KVClient struct {
  164. conn net.Conn
  165. reader *bufio.Reader
  166. writer *bufio.Writer
  167. mu sync.Mutex
  168. nextID uint64
  169. requestTimeout time.Duration
  170. lastUsed time.Time
  171. }
  172. type KVResult struct {
  173. Value []byte
  174. LSN uint64
  175. Found bool
  176. }
  177. type KVEntry struct {
  178. Key []byte
  179. Value []byte
  180. LSN uint64
  181. }
  182. type BatchOp struct {
  183. Op byte
  184. Key []byte
  185. Value []byte
  186. }
  187. type CompareCheck struct {
  188. Key []byte
  189. LSN uint64
  190. }
  191. type ScanCursor struct {
  192. client *KVClient
  193. id uint64
  194. }
  195. func NewKVClient(addr string) (*KVClient, error) {
  196. network, target := parseAddr(addr)
  197. conn, err := net.Dial(network, target)
  198. if err != nil {
  199. return nil, fmt.Errorf("failed to connect to PizzaKV: %w", err)
  200. }
  201. return &KVClient{
  202. conn: conn,
  203. reader: bufio.NewReader(conn),
  204. writer: bufio.NewWriter(conn),
  205. nextID: 1,
  206. lastUsed: time.Now(),
  207. }, nil
  208. }
  209. func parseAddr(addr string) (string, string) {
  210. if strings.HasPrefix(addr, "unix:") {
  211. return "unix", strings.TrimPrefix(addr, "unix:")
  212. }
  213. return "tcp", addr
  214. }
  215. func (c *KVClient) Close() error {
  216. c.mu.Lock()
  217. defer c.mu.Unlock()
  218. if c.conn != nil {
  219. err := c.conn.Close()
  220. c.conn = nil
  221. return err
  222. }
  223. return nil
  224. }
  225. func (c *KVClient) SetDeadline(t time.Time) error {
  226. if c.conn == nil {
  227. return nil
  228. }
  229. return c.conn.SetDeadline(t)
  230. }
  231. func (c *KVClient) writeFrame(opcode, flags uint16, requestID uint64, payload []byte) error {
  232. frame := encodeFrame(opcode, flags, requestID, payload)
  233. if _, err := c.writer.Write(frame); err != nil {
  234. return err
  235. }
  236. return c.writer.Flush()
  237. }
  238. func (c *KVClient) request(opcode uint16, payload []byte) (uint16, []byte, error) {
  239. if c.requestTimeout > 0 {
  240. if err := c.conn.SetDeadline(time.Now().Add(c.requestTimeout)); err != nil {
  241. return 0, nil, err
  242. }
  243. }
  244. requestID := c.nextID
  245. c.nextID++
  246. if err := c.writeFrame(opcode, 0, requestID, payload); err != nil {
  247. return 0, nil, err
  248. }
  249. respOpcode, respFlags, respID, body, err := readFrame(c.reader)
  250. if err != nil {
  251. return 0, nil, err
  252. }
  253. if respOpcode != opcode|0x8000 {
  254. return 0, nil, fmt.Errorf("%w: unexpected response opcode %d", ErrProtocol, respOpcode)
  255. }
  256. if respFlags != 1 {
  257. return 0, nil, fmt.Errorf("%w: unexpected response flags %d", ErrProtocol, respFlags)
  258. }
  259. if respID != requestID {
  260. return 0, nil, fmt.Errorf("%w: response id %d does not match request %d", ErrProtocol, respID, requestID)
  261. }
  262. c.lastUsed = time.Now()
  263. if len(body) < 2 {
  264. return 0, nil, fmt.Errorf("%w: response too short", ErrProtocol)
  265. }
  266. status := getU16(body[0:2])
  267. if status == statusError {
  268. return status, nil, fmt.Errorf("pkbfi server error: %s", body[2:])
  269. }
  270. return status, body[2:], nil
  271. }
  272. func (c *KVClient) Put(key, value []byte) (uint64, error) {
  273. if err := validateKey(key); err != nil {
  274. return 0, err
  275. }
  276. if err := validateValue(value); err != nil {
  277. return 0, err
  278. }
  279. c.mu.Lock()
  280. defer c.mu.Unlock()
  281. payload := make([]byte, 8+len(key)+len(value))
  282. putU32(payload[0:4], uint32(len(key)))
  283. putU32(payload[4:8], uint32(len(value)))
  284. copy(payload[8:], key)
  285. copy(payload[8+len(key):], value)
  286. status, body, err := c.request(opPut, payload)
  287. if err != nil {
  288. return 0, err
  289. }
  290. if status != statusOK || len(body) != 8 {
  291. return 0, fmt.Errorf("%w: malformed put response", ErrProtocol)
  292. }
  293. return getU64(body[0:8]), nil
  294. }
  295. func (c *KVClient) Get(key []byte) (KVResult, error) {
  296. if err := validateKey(key); err != nil {
  297. return KVResult{}, err
  298. }
  299. c.mu.Lock()
  300. defer c.mu.Unlock()
  301. status, body, err := c.request(opGet, oneKeyPayload(key))
  302. if err != nil {
  303. return KVResult{}, err
  304. }
  305. if status == statusNotFound {
  306. return KVResult{}, ErrKeyNotFound
  307. }
  308. if status != statusOK || len(body) < 12 {
  309. return KVResult{}, fmt.Errorf("%w: malformed get response", ErrProtocol)
  310. }
  311. lsn := getU64(body[0:8])
  312. valueLen := getU32(body[8:12])
  313. if valueLen > maxValueSize || uint64(len(body)) != 12+uint64(valueLen) {
  314. return KVResult{}, fmt.Errorf("%w: malformed get value length", ErrProtocol)
  315. }
  316. return KVResult{Value: body[12:], LSN: lsn, Found: true}, nil
  317. }
  318. func (c *KVClient) Del(key []byte) (bool, error) {
  319. if err := validateKey(key); err != nil {
  320. return false, err
  321. }
  322. c.mu.Lock()
  323. defer c.mu.Unlock()
  324. status, body, err := c.request(opDelete, oneKeyPayload(key))
  325. if err != nil {
  326. return false, err
  327. }
  328. if status != statusOK || len(body) != 1 {
  329. return false, fmt.Errorf("%w: malformed delete response", ErrProtocol)
  330. }
  331. return body[0] != 0, nil
  332. }
  333. func (c *KVClient) Exists(key []byte) (bool, error) {
  334. if err := validateKey(key); err != nil {
  335. return false, err
  336. }
  337. c.mu.Lock()
  338. defer c.mu.Unlock()
  339. status, body, err := c.request(opExists, oneKeyPayload(key))
  340. if err != nil {
  341. return false, err
  342. }
  343. if status != statusOK || len(body) != 1 {
  344. return false, fmt.Errorf("%w: malformed exists response", ErrProtocol)
  345. }
  346. return body[0] != 0, nil
  347. }
  348. func (c *KVClient) ExistsMany(keys [][]byte) ([]bool, error) {
  349. if len(keys) > maxOperations {
  350. return nil, fmt.Errorf("pkbfi: too many keys")
  351. }
  352. for _, key := range keys {
  353. if err := validateKey(key); err != nil {
  354. return nil, err
  355. }
  356. }
  357. c.mu.Lock()
  358. defer c.mu.Unlock()
  359. results := make([]bool, len(keys))
  360. for start := 0; start < len(keys); start += existsPipelineSize {
  361. end := start + existsPipelineSize
  362. if end > len(keys) {
  363. end = len(keys)
  364. }
  365. ids := make([]uint64, end-start)
  366. if c.requestTimeout > 0 {
  367. if err := c.conn.SetDeadline(time.Now().Add(c.requestTimeout)); err != nil {
  368. return nil, err
  369. }
  370. }
  371. for i, key := range keys[start:end] {
  372. ids[i] = c.nextID
  373. c.nextID++
  374. if _, err := c.writer.Write(encodeFrame(opExists, 0, ids[i], oneKeyPayload(key))); err != nil {
  375. return nil, err
  376. }
  377. }
  378. if err := c.writer.Flush(); err != nil {
  379. return nil, err
  380. }
  381. for i, requestID := range ids {
  382. opcode, flags, responseID, body, err := readFrame(c.reader)
  383. if err != nil {
  384. return nil, err
  385. }
  386. if opcode != opExists|0x8000 || flags != 1 || responseID != requestID {
  387. return nil, fmt.Errorf("%w: malformed exists response frame", ErrProtocol)
  388. }
  389. if len(body) < 2 {
  390. return nil, fmt.Errorf("%w: response too short", ErrProtocol)
  391. }
  392. status := getU16(body[0:2])
  393. if status == statusError {
  394. return nil, fmt.Errorf("pkbfi server error: %s", body[2:])
  395. }
  396. if status != statusOK || len(body) != 3 {
  397. return nil, fmt.Errorf("%w: malformed exists response", ErrProtocol)
  398. }
  399. results[start+i] = body[2] != 0
  400. c.lastUsed = time.Now()
  401. }
  402. }
  403. return results, nil
  404. }
  405. func (c *KVClient) MultiGet(keys [][]byte) ([]KVResult, error) {
  406. if len(keys) > maxOperations {
  407. return nil, fmt.Errorf("pkbfi: too many keys")
  408. }
  409. payloadSize := 4
  410. for _, key := range keys {
  411. if err := validateKey(key); err != nil {
  412. return nil, err
  413. }
  414. payloadSize += 4 + len(key)
  415. if payloadSize > maxFrameSize {
  416. return nil, fmt.Errorf("pkbfi: multi_get request exceeds frame limit")
  417. }
  418. }
  419. c.mu.Lock()
  420. defer c.mu.Unlock()
  421. payload := make([]byte, 4, payloadSize)
  422. putU32(payload[0:4], uint32(len(keys)))
  423. for _, key := range keys {
  424. var length [4]byte
  425. putU32(length[:], uint32(len(key)))
  426. payload = append(payload, length[:]...)
  427. payload = append(payload, key...)
  428. }
  429. status, body, err := c.request(opMultiGet, payload)
  430. if err != nil {
  431. return nil, err
  432. }
  433. if status != statusOK || len(body) < 4 {
  434. return nil, fmt.Errorf("%w: malformed multi_get response", ErrProtocol)
  435. }
  436. count := getU32(body[0:4])
  437. if count != uint32(len(keys)) {
  438. return nil, fmt.Errorf("%w: multi_get count mismatch", ErrProtocol)
  439. }
  440. results := make([]KVResult, count)
  441. pos := 4
  442. for i := uint32(0); i < count; i++ {
  443. if len(body)-pos < 16 {
  444. return nil, fmt.Errorf("%w: truncated multi_get entry", ErrProtocol)
  445. }
  446. present := body[pos] != 0
  447. valueLen := getU32(body[pos+4 : pos+8])
  448. lsn := getU64(body[pos+8 : pos+16])
  449. pos += 16
  450. results[i] = KVResult{LSN: lsn, Found: present}
  451. if present {
  452. if valueLen > maxValueSize || len(body)-pos < int(valueLen) {
  453. return nil, fmt.Errorf("%w: multi_get value length", ErrProtocol)
  454. }
  455. results[i].Value = body[pos : pos+int(valueLen)]
  456. pos += int(valueLen)
  457. }
  458. }
  459. if pos != len(body) {
  460. return nil, fmt.Errorf("%w: multi_get trailing bytes", ErrProtocol)
  461. }
  462. return results, nil
  463. }
  464. func (c *KVClient) BatchWrite(ops []BatchOp, metadata []byte) (uint64, error) {
  465. if len(ops) == 0 || len(ops) > maxOperations {
  466. return 0, fmt.Errorf("pkbfi: invalid operation count")
  467. }
  468. if len(metadata) > maxTransactionSize-8 {
  469. return 0, fmt.Errorf("pkbfi: batch metadata exceeds transaction limit")
  470. }
  471. payloadSize := 8 + len(metadata)
  472. for _, op := range ops {
  473. if op.Op != batchPut && op.Op != batchDelete {
  474. return 0, fmt.Errorf("pkbfi: invalid batch opcode %d", op.Op)
  475. }
  476. if err := validateKey(op.Key); err != nil {
  477. return 0, err
  478. }
  479. if err := validateValue(op.Value); err != nil {
  480. return 0, err
  481. }
  482. if op.Op == batchDelete && len(op.Value) != 0 {
  483. return 0, fmt.Errorf("pkbfi: delete operation with value")
  484. }
  485. payloadSize += 12 + len(op.Key) + len(op.Value)
  486. if payloadSize > maxTransactionSize {
  487. return 0, fmt.Errorf("pkbfi: batch exceeds transaction limit")
  488. }
  489. }
  490. c.mu.Lock()
  491. defer c.mu.Unlock()
  492. payload := make([]byte, 8, payloadSize)
  493. putU32(payload[0:4], uint32(len(ops)))
  494. putU32(payload[4:8], uint32(len(metadata)))
  495. payload = append(payload, metadata...)
  496. for _, op := range ops {
  497. var header [12]byte
  498. header[0] = op.Op
  499. putU32(header[4:8], uint32(len(op.Key)))
  500. putU32(header[8:12], uint32(len(op.Value)))
  501. payload = append(payload, header[:]...)
  502. payload = append(payload, op.Key...)
  503. payload = append(payload, op.Value...)
  504. }
  505. status, body, err := c.request(opBatchWrite, payload)
  506. if err != nil {
  507. return 0, err
  508. }
  509. if status != statusOK || len(body) != 8 {
  510. return 0, fmt.Errorf("%w: malformed batch_write response", ErrProtocol)
  511. }
  512. return getU64(body[0:8]), nil
  513. }
  514. func (c *KVClient) CompareBatchWrite(checks []CompareCheck, ops []BatchOp, metadata []byte) (uint64, bool, error) {
  515. if len(ops) == 0 || len(ops) > maxOperations {
  516. return 0, false, fmt.Errorf("pkbfi: invalid operation count")
  517. }
  518. if len(checks) > maxOperations {
  519. return 0, false, fmt.Errorf("pkbfi: too many compare checks")
  520. }
  521. if len(metadata) > maxTransactionSize-16 {
  522. return 0, false, fmt.Errorf("pkbfi: batch metadata exceeds transaction limit")
  523. }
  524. payloadSize := 16 + len(metadata)
  525. for _, check := range checks {
  526. if err := validateKey(check.Key); err != nil {
  527. return 0, false, err
  528. }
  529. payloadSize += 16 + len(check.Key)
  530. if payloadSize > maxFrameSize {
  531. return 0, false, fmt.Errorf("pkbfi: compare batch exceeds frame limit")
  532. }
  533. }
  534. for _, op := range ops {
  535. if op.Op != batchPut && op.Op != batchDelete {
  536. return 0, false, fmt.Errorf("pkbfi: invalid batch opcode %d", op.Op)
  537. }
  538. if err := validateKey(op.Key); err != nil {
  539. return 0, false, err
  540. }
  541. if err := validateValue(op.Value); err != nil {
  542. return 0, false, err
  543. }
  544. if op.Op == batchDelete && len(op.Value) != 0 {
  545. return 0, false, fmt.Errorf("pkbfi: delete operation with value")
  546. }
  547. payloadSize += 12 + len(op.Key) + len(op.Value)
  548. if payloadSize > maxTransactionSize {
  549. return 0, false, fmt.Errorf("pkbfi: batch exceeds transaction limit")
  550. }
  551. }
  552. c.mu.Lock()
  553. defer c.mu.Unlock()
  554. payload := make([]byte, 16, payloadSize)
  555. putU32(payload[0:4], uint32(len(checks)))
  556. putU32(payload[4:8], uint32(len(ops)))
  557. putU32(payload[8:12], uint32(len(metadata)))
  558. for _, check := range checks {
  559. var header [16]byte
  560. putU32(header[0:4], uint32(len(check.Key)))
  561. putU64(header[8:16], check.LSN)
  562. payload = append(payload, header[:]...)
  563. payload = append(payload, check.Key...)
  564. }
  565. payload = append(payload, metadata...)
  566. for _, op := range ops {
  567. var header [12]byte
  568. header[0] = op.Op
  569. putU32(header[4:8], uint32(len(op.Key)))
  570. putU32(header[8:12], uint32(len(op.Value)))
  571. payload = append(payload, header[:]...)
  572. payload = append(payload, op.Key...)
  573. payload = append(payload, op.Value...)
  574. }
  575. status, body, err := c.request(opCompareBatch, payload)
  576. if err != nil {
  577. return 0, false, err
  578. }
  579. if status != statusOK || len(body) != 16 {
  580. return 0, false, fmt.Errorf("%w: malformed compare_batch_write response", ErrProtocol)
  581. }
  582. committed := body[0] != 0
  583. lsn := getU64(body[8:16])
  584. return lsn, committed, nil
  585. }
  586. func (c *KVClient) Scan(prefix []byte) (*ScanCursor, error) {
  587. return c.openScan(prefix, true, scanPageSize)
  588. }
  589. func (c *KVClient) ScanWithLimit(prefix []byte, pageSize uint32) (*ScanCursor, error) {
  590. return c.openScan(prefix, true, pageSize)
  591. }
  592. // ScanKeys opens a key-only scan: the server omits values from the returned
  593. // pages. It is used when only the key set (or its size) is needed, such as the
  594. // COUNT(*) fast path or bulk deletion, so a full-table scan does not pull row
  595. // values across the wire.
  596. func (c *KVClient) ScanKeys(prefix []byte) (*ScanCursor, error) {
  597. return c.openScan(prefix, false, scanPageSize)
  598. }
  599. func (c *KVClient) openScan(prefix []byte, includeValues bool, pageSize uint32) (*ScanCursor, error) {
  600. if err := validateKey(prefix); err != nil {
  601. return nil, err
  602. }
  603. if pageSize == 0 || pageSize > 4096 {
  604. return nil, fmt.Errorf("pkbfi: scan page size must be between 1 and 4096")
  605. }
  606. c.mu.Lock()
  607. defer c.mu.Unlock()
  608. payload := make([]byte, 12+len(prefix))
  609. if includeValues {
  610. payload[0] = 1
  611. }
  612. putU32(payload[4:8], pageSize)
  613. putU32(payload[8:12], uint32(len(prefix)))
  614. copy(payload[12:], prefix)
  615. status, body, err := c.request(opScanOpen, payload)
  616. if err != nil {
  617. return nil, err
  618. }
  619. if status != statusOK || len(body) != 8 {
  620. return nil, fmt.Errorf("%w: malformed scan_open response", ErrProtocol)
  621. }
  622. return &ScanCursor{client: c, id: getU64(body[0:8])}, nil
  623. }
  624. func (s *ScanCursor) Next() ([]KVEntry, bool, error) {
  625. s.client.mu.Lock()
  626. defer s.client.mu.Unlock()
  627. var payload [12]byte
  628. putU64(payload[0:8], s.id)
  629. putU32(payload[8:12], 0)
  630. status, body, err := s.client.request(opScanNext, payload[:])
  631. if err != nil {
  632. return nil, false, err
  633. }
  634. if status != statusOK || len(body) < 8 {
  635. return nil, false, fmt.Errorf("%w: malformed scan_next response", ErrProtocol)
  636. }
  637. done := body[0] != 0
  638. count := getU32(body[4:8])
  639. entries := make([]KVEntry, 0, count)
  640. pos := 8
  641. for i := uint32(0); i < count; i++ {
  642. if len(body)-pos < 16 {
  643. return nil, false, fmt.Errorf("%w: truncated scan entry", ErrProtocol)
  644. }
  645. keyLen := getU32(body[pos : pos+4])
  646. valueLen := getU32(body[pos+4 : pos+8])
  647. lsn := getU64(body[pos+8 : pos+16])
  648. pos += 16
  649. if keyLen > maxKeySize || valueLen > maxValueSize || len(body)-pos < int(keyLen)+int(valueLen) {
  650. return nil, false, fmt.Errorf("%w: scan entry length", ErrProtocol)
  651. }
  652. key := body[pos : pos+int(keyLen)]
  653. pos += int(keyLen)
  654. value := body[pos : pos+int(valueLen)]
  655. pos += int(valueLen)
  656. entries = append(entries, KVEntry{Key: key, Value: value, LSN: lsn})
  657. }
  658. if pos != len(body) {
  659. return nil, false, fmt.Errorf("%w: scan trailing bytes", ErrProtocol)
  660. }
  661. return entries, done, nil
  662. }
  663. func (s *ScanCursor) Close() error {
  664. s.client.mu.Lock()
  665. defer s.client.mu.Unlock()
  666. var payload [8]byte
  667. putU64(payload[0:8], s.id)
  668. status, body, err := s.client.request(opScanClose, payload[:])
  669. if err != nil {
  670. return err
  671. }
  672. if status != statusOK || len(body) != 1 {
  673. return fmt.Errorf("%w: malformed scan_close response", ErrProtocol)
  674. }
  675. return nil
  676. }
  677. func (c *KVClient) Write(key, value string) error {
  678. _, err := c.Put([]byte(key), []byte(value))
  679. return err
  680. }
  681. func (c *KVClient) Read(key string) (string, error) {
  682. res, err := c.Get([]byte(key))
  683. if err != nil {
  684. return "", err
  685. }
  686. return string(res.Value), nil
  687. }
  688. func (c *KVClient) Delete(key string) error {
  689. _, err := c.Del([]byte(key))
  690. return err
  691. }
  692. func (c *KVClient) Reads(prefix string) ([]string, error) {
  693. scan, err := c.Scan([]byte(prefix))
  694. if err != nil {
  695. return nil, err
  696. }
  697. defer scan.Close()
  698. values := make([]string, 0)
  699. for {
  700. entries, done, err := scan.Next()
  701. if err != nil {
  702. return nil, err
  703. }
  704. for _, entry := range entries {
  705. values = append(values, string(entry.Value))
  706. }
  707. if done {
  708. return values, nil
  709. }
  710. }
  711. }
  712. func (c *KVClient) IsAlive() bool {
  713. c.mu.Lock()
  714. defer c.mu.Unlock()
  715. if c.conn == nil {
  716. return false
  717. }
  718. c.conn.SetDeadline(time.Now().Add(500 * time.Millisecond))
  719. defer c.conn.SetDeadline(time.Time{})
  720. _, _, err := c.request(opPing, nil)
  721. return err == nil
  722. }
  723. type KVPool struct {
  724. addr string
  725. pool chan *KVClient
  726. size int
  727. timeout time.Duration
  728. mu sync.Mutex
  729. closed bool
  730. }
  731. func (p *KVPool) replacementClient() (*KVClient, error) {
  732. client, err := NewKVClient(p.addr)
  733. if err == nil {
  734. client.requestTimeout = p.timeout
  735. return client, nil
  736. }
  737. p.mu.Lock()
  738. if !p.closed {
  739. select {
  740. case p.pool <- nil:
  741. default:
  742. }
  743. }
  744. p.mu.Unlock()
  745. return nil, err
  746. }
  747. func NewKVPool(addr string, size int, timeout time.Duration) (*KVPool, error) {
  748. p := &KVPool{
  749. addr: addr,
  750. pool: make(chan *KVClient, size),
  751. size: size,
  752. timeout: timeout,
  753. }
  754. for i := 0; i < size; i++ {
  755. client, err := NewKVClient(addr)
  756. if err != nil {
  757. p.Close()
  758. return nil, fmt.Errorf("failed to create connection pool: %w", err)
  759. }
  760. p.pool <- client
  761. }
  762. return p, nil
  763. }
  764. func (p *KVPool) Get() (*KVClient, error) {
  765. p.mu.Lock()
  766. if p.closed {
  767. p.mu.Unlock()
  768. return nil, fmt.Errorf("pool is closed")
  769. }
  770. p.mu.Unlock()
  771. select {
  772. case client := <-p.pool:
  773. if client != nil && client.conn != nil {
  774. if client.lastUsed.IsZero() {
  775. client.lastUsed = time.Now()
  776. } else if time.Since(client.lastUsed) >= 20*time.Second && !client.IsAlive() {
  777. client.Close()
  778. return p.replacementClient()
  779. }
  780. client.requestTimeout = p.timeout
  781. return client, nil
  782. }
  783. return p.replacementClient()
  784. case <-time.After(30 * time.Second):
  785. return nil, fmt.Errorf("kv pool timeout: no connection available after 30s")
  786. }
  787. }
  788. func (p *KVPool) Put(client *KVClient) {
  789. if client == nil {
  790. return
  791. }
  792. p.mu.Lock()
  793. if p.closed {
  794. p.mu.Unlock()
  795. client.Close()
  796. return
  797. }
  798. p.mu.Unlock()
  799. client.requestTimeout = 0
  800. client.SetDeadline(time.Time{})
  801. select {
  802. case p.pool <- client:
  803. default:
  804. client.Close()
  805. }
  806. }
  807. func (p *KVPool) Close() error {
  808. p.mu.Lock()
  809. if p.closed {
  810. p.mu.Unlock()
  811. return nil
  812. }
  813. p.closed = true
  814. p.mu.Unlock()
  815. close(p.pool)
  816. for client := range p.pool {
  817. if client != nil {
  818. client.Close()
  819. }
  820. }
  821. return nil
  822. }
  823. func (p *KVPool) WithClient(fn func(*KVClient) error) error {
  824. client, err := p.Get()
  825. if err != nil {
  826. return err
  827. }
  828. if err := fn(client); err != nil {
  829. if !isConnectionError(err) {
  830. p.Put(client)
  831. return err
  832. }
  833. client.Close()
  834. p.mu.Lock()
  835. if !p.closed {
  836. select {
  837. case p.pool <- nil:
  838. default:
  839. }
  840. }
  841. p.mu.Unlock()
  842. return err
  843. }
  844. p.Put(client)
  845. return nil
  846. }
  847. func isConnectionError(err error) bool {
  848. var netErr net.Error
  849. if errors.As(err, &netErr) {
  850. return true
  851. }
  852. if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
  853. return true
  854. }
  855. return errors.Is(err, ErrProtocol)
  856. }