kv.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. package storage
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "strings"
  7. "sync"
  8. "time"
  9. )
  10. // KVClient represents a connection to PizzaKV.
  11. type KVClient struct {
  12. conn net.Conn
  13. reader *bufio.Reader
  14. writer *bufio.Writer
  15. mu sync.Mutex
  16. }
  17. // NewKVClient creates a new KV client connected to the given address.
  18. func NewKVClient(addr string) (*KVClient, error) {
  19. conn, err := net.Dial("tcp", addr)
  20. if err != nil {
  21. return nil, fmt.Errorf("failed to connect to PizzaKV: %w", err)
  22. }
  23. return &KVClient{
  24. conn: conn,
  25. reader: bufio.NewReader(conn),
  26. writer: bufio.NewWriter(conn),
  27. }, nil
  28. }
  29. // Close closes the connection.
  30. func (c *KVClient) Close() error {
  31. c.mu.Lock()
  32. defer c.mu.Unlock()
  33. if c.conn != nil {
  34. return c.conn.Close()
  35. }
  36. return nil
  37. }
  38. // SetDeadline sets the read/write deadline.
  39. func (c *KVClient) SetDeadline(t time.Time) error {
  40. return c.conn.SetDeadline(t)
  41. }
  42. // Write stores a key-value pair.
  43. func (c *KVClient) Write(key, value string) error {
  44. c.mu.Lock()
  45. defer c.mu.Unlock()
  46. cmd := fmt.Sprintf("write %s|%s\r", key, value)
  47. fmt.Printf("[DEBUG KV] Write command (len=%d): key=%q, value_len=%d\n", len(cmd), key, len(value))
  48. if _, err := c.writer.WriteString(cmd); err != nil {
  49. return fmt.Errorf("write command failed: %w", err)
  50. }
  51. if err := c.writer.Flush(); err != nil {
  52. return fmt.Errorf("flush failed: %w", err)
  53. }
  54. resp, err := c.reader.ReadString('\r')
  55. if err != nil {
  56. return fmt.Errorf("read response failed: %w", err)
  57. }
  58. fmt.Printf("[DEBUG KV] Write response: %q\n", resp)
  59. resp = strings.TrimSuffix(resp, "\r")
  60. if resp != "success" {
  61. return fmt.Errorf("write failed: %s", resp)
  62. }
  63. return nil
  64. }
  65. // Read retrieves a value by key.
  66. func (c *KVClient) Read(key string) (string, error) {
  67. c.mu.Lock()
  68. defer c.mu.Unlock()
  69. cmd := fmt.Sprintf("read %s\r", key)
  70. fmt.Printf("[DEBUG KV] Read command: %q\n", cmd)
  71. if _, err := c.writer.WriteString(cmd); err != nil {
  72. return "", fmt.Errorf("read command failed: %w", err)
  73. }
  74. if err := c.writer.Flush(); err != nil {
  75. return "", fmt.Errorf("flush failed: %w", err)
  76. }
  77. resp, err := c.reader.ReadString('\r')
  78. if err != nil {
  79. return "", fmt.Errorf("read response failed: %w", err)
  80. }
  81. fmt.Printf("[DEBUG KV] Read raw response: %q\n", resp)
  82. resp = strings.TrimSuffix(resp, "\r")
  83. if resp == "error" {
  84. return "", ErrKeyNotFound
  85. }
  86. return resp, nil
  87. }
  88. // Delete removes a key.
  89. func (c *KVClient) Delete(key string) error {
  90. c.mu.Lock()
  91. defer c.mu.Unlock()
  92. cmd := fmt.Sprintf("delete %s\r", key)
  93. if _, err := c.writer.WriteString(cmd); err != nil {
  94. return fmt.Errorf("delete command failed: %w", err)
  95. }
  96. if err := c.writer.Flush(); err != nil {
  97. return fmt.Errorf("flush failed: %w", err)
  98. }
  99. resp, err := c.reader.ReadString('\r')
  100. if err != nil {
  101. return fmt.Errorf("read response failed: %w", err)
  102. }
  103. resp = strings.TrimSuffix(resp, "\r")
  104. if resp != "success" && resp != "error" {
  105. return fmt.Errorf("delete failed: %s", resp)
  106. }
  107. return nil
  108. }
  109. // Reads retrieves all values with a key prefix.
  110. func (c *KVClient) Reads(prefix string) ([]string, error) {
  111. c.mu.Lock()
  112. defer c.mu.Unlock()
  113. cmd := fmt.Sprintf("reads %s\r", prefix)
  114. fmt.Printf("[DEBUG KV] Reads command: %q\n", cmd)
  115. if _, err := c.writer.WriteString(cmd); err != nil {
  116. return nil, fmt.Errorf("reads command failed: %w", err)
  117. }
  118. if err := c.writer.Flush(); err != nil {
  119. return nil, fmt.Errorf("flush failed: %w", err)
  120. }
  121. resp, err := c.reader.ReadString('\r')
  122. if err != nil {
  123. fmt.Printf("[DEBUG KV] Reads response error: %v\n", err)
  124. return nil, fmt.Errorf("read response failed: %w", err)
  125. }
  126. fmt.Printf("[DEBUG KV] Reads raw response: %q (len=%d)\n", resp, len(resp))
  127. resp = strings.TrimSuffix(resp, "\r")
  128. if resp == "" {
  129. fmt.Printf("[DEBUG KV] Reads: empty response, returning nil\n")
  130. return nil, nil
  131. }
  132. values := strings.Split(resp, "\n")
  133. fmt.Printf("[DEBUG KV] Reads: split into %d parts\n", len(values))
  134. // Filter out empty strings
  135. result := make([]string, 0, len(values))
  136. for i, v := range values {
  137. fmt.Printf("[DEBUG KV] Reads value[%d]: %q\n", i, v)
  138. if v != "" {
  139. result = append(result, v)
  140. }
  141. }
  142. fmt.Printf("[DEBUG KV] Reads: returning %d values\n", len(result))
  143. return result, nil
  144. }
  145. // IsAlive checks if the connection is still alive.
  146. func (c *KVClient) IsAlive() bool {
  147. c.mu.Lock()
  148. defer c.mu.Unlock()
  149. if c.conn == nil {
  150. return false
  151. }
  152. // Try to set a short deadline and do a no-op check
  153. c.conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
  154. defer c.conn.SetReadDeadline(time.Time{})
  155. one := make([]byte, 1)
  156. c.conn.SetReadDeadline(time.Now().Add(1 * time.Millisecond))
  157. _, err := c.conn.Read(one)
  158. if err != nil {
  159. if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
  160. return true // Timeout is expected
  161. }
  162. return false
  163. }
  164. return true
  165. }
  166. // ErrKeyNotFound is returned when a key doesn't exist.
  167. var ErrKeyNotFound = fmt.Errorf("key not found")
  168. // KVPool manages a pool of KV client connections.
  169. type KVPool struct {
  170. addr string
  171. pool chan *KVClient
  172. size int
  173. timeout time.Duration
  174. mu sync.Mutex
  175. closed bool
  176. }
  177. // NewKVPool creates a new connection pool.
  178. func NewKVPool(addr string, size int, timeout time.Duration) (*KVPool, error) {
  179. p := &KVPool{
  180. addr: addr,
  181. pool: make(chan *KVClient, size),
  182. size: size,
  183. timeout: timeout,
  184. }
  185. // Pre-create connections
  186. for i := 0; i < size; i++ {
  187. client, err := NewKVClient(addr)
  188. if err != nil {
  189. // Close any created connections
  190. p.Close()
  191. return nil, fmt.Errorf("failed to create connection pool: %w", err)
  192. }
  193. p.pool <- client
  194. }
  195. return p, nil
  196. }
  197. // Get retrieves a connection from the pool.
  198. func (p *KVPool) Get() (*KVClient, error) {
  199. p.mu.Lock()
  200. if p.closed {
  201. p.mu.Unlock()
  202. return nil, fmt.Errorf("pool is closed")
  203. }
  204. p.mu.Unlock()
  205. select {
  206. case client := <-p.pool:
  207. // Validate connection
  208. if client != nil && client.conn != nil {
  209. if p.timeout > 0 {
  210. client.SetDeadline(time.Now().Add(p.timeout))
  211. }
  212. return client, nil
  213. }
  214. // Create new connection if stale
  215. return NewKVClient(p.addr)
  216. default:
  217. // Pool empty, create new connection
  218. return NewKVClient(p.addr)
  219. }
  220. }
  221. // Put returns a connection to the pool.
  222. func (p *KVPool) Put(client *KVClient) {
  223. if client == nil {
  224. return
  225. }
  226. p.mu.Lock()
  227. if p.closed {
  228. p.mu.Unlock()
  229. client.Close()
  230. return
  231. }
  232. p.mu.Unlock()
  233. // Clear deadline
  234. client.SetDeadline(time.Time{})
  235. select {
  236. case p.pool <- client:
  237. // Returned to pool
  238. default:
  239. // Pool full, close connection
  240. client.Close()
  241. }
  242. }
  243. // Close closes all connections in the pool.
  244. func (p *KVPool) Close() error {
  245. p.mu.Lock()
  246. if p.closed {
  247. p.mu.Unlock()
  248. return nil
  249. }
  250. p.closed = true
  251. p.mu.Unlock()
  252. close(p.pool)
  253. for client := range p.pool {
  254. if client != nil {
  255. client.Close()
  256. }
  257. }
  258. return nil
  259. }
  260. // WithClient executes a function with a pooled connection.
  261. func (p *KVPool) WithClient(fn func(*KVClient) error) error {
  262. client, err := p.Get()
  263. if err != nil {
  264. return err
  265. }
  266. defer p.Put(client)
  267. return fn(client)
  268. }