Bladeren bron

untested delete support

Brad Fitzpatrick 14 jaren geleden
bovenliggende
commit
1332296ec9
1 gewijzigde bestanden met toevoegingen van 65 en 25 verwijderingen
  1. 65 25
      memcache/memcache.go

+ 65 - 25
memcache/memcache.go

@@ -96,7 +96,8 @@ var (
 	resultNotStored = []byte("NOT_STORED\r\n")
 	resultExists    = []byte("EXISTS\r\n")
 	resultNotFound  = []byte("NOT_FOUND\r\n")
-	end             = []byte("END\r\n")
+	resultDeleted   = []byte("DELETED\r\n")
+	resultEnd       = []byte("END\r\n")
 )
 
 // New returns a memcache client using the provided server(s)
@@ -200,37 +201,54 @@ func (c *Client) onItem(item *Item, fn func(*Client, *bufio.ReadWriter, *Item) o
 // Get gets the item for the given key. ErrCacheMiss is returned for a
 // memcache cache miss. The key must be at most 250 bytes in length.
 func (c *Client) Get(key string) (item *Item, err os.Error) {
+	err = c.withKey(key, func(addr net.Addr) os.Error {
+		return c.getFromAddr(addr, []string{key}, func(it *Item) { item = it })
+	})
+	if err == nil && item == nil {
+		err = ErrCacheMiss
+	}
+	return
+}
+
+func (c *Client) withKey(key string, fn func(net.Addr) os.Error) (err os.Error) {
 	if !legalKey(key) {
-		return nil, ErrMalformedKey
+		return ErrMalformedKey
 	}
 	addr, err := c.selector.PickServer(key)
 	if err != nil {
-		return nil, err
-	}
-	err = c.getFromAddr(addr, []string{key}, func(it *Item) { item = it })
-	if err == nil && item == nil {
-		err = ErrCacheMiss
+		return err
 	}
-	return
+	return fn(addr)
 }
 
-func (c *Client) getFromAddr(addr net.Addr, keys []string, cb func(*Item)) os.Error {
+func (c *Client) withAddr(addr net.Addr, fn func(*bufio.ReadWriter) os.Error) (err os.Error) {
 	cn, err := c.getConn(addr)
 	if err != nil {
 		return err
 	}
 	defer cn.condRelease(&err)
+	return fn(cn.rw)
+}
 
-	if _, err = fmt.Fprintf(cn.rw, "gets %s\r\n", strings.Join(keys, " ")); err != nil {
-		return err
-	}
-	if err = cn.rw.Flush(); err != nil {
-		return err
-	}
-	if err = parseGetResponse(cn.rw.Reader, cb); err != nil {
-		return err
-	}
-	return nil
+func (c *Client) withKeyAddr(key string, fn func(*bufio.ReadWriter) os.Error) os.Error {
+	return c.withKey(key, func(addr net.Addr) os.Error {
+		return c.withAddr(addr, fn)
+	})
+}
+
+func (c *Client) getFromAddr(addr net.Addr, keys []string, cb func(*Item)) os.Error {
+	return c.withAddr(addr, func(rw *bufio.ReadWriter) os.Error {
+		if _, err := fmt.Fprintf(rw, "gets %s\r\n", strings.Join(keys, " ")); err != nil {
+			return err
+		}
+		if err := rw.Flush(); err != nil {
+			return err
+		}
+		if err := parseGetResponse(rw.Reader, cb); err != nil {
+			return err
+		}
+		return nil
+	})
 }
 
 // GetMulti is a batch version of Get. The returned map from keys to
@@ -282,7 +300,7 @@ func parseGetResponse(r *bufio.Reader, cb func(*Item)) os.Error {
 		if err != nil {
 			return err
 		}
-		if bytes.Equal(line, end) {
+		if bytes.Equal(line, resultEnd) {
 			return nil
 		}
 		it := new(Item)
@@ -342,7 +360,6 @@ func (c *Client) cas(rw *bufio.ReadWriter, item *Item) os.Error {
 	return c.populateOne(rw, "cas", item)
 }
 
-
 func (c *Client) populateOne(rw *bufio.ReadWriter, verb string, item *Item) os.Error {
 	if !legalKey(item.Key) {
 		return ErrMalformedKey
@@ -384,10 +401,33 @@ func (c *Client) populateOne(rw *bufio.ReadWriter, verb string, item *Item) os.E
 	return fmt.Errorf("memcache: unexpected response line from %q: %q", verb, string(line))
 }
 
-func (c *Client) Delete(key string) os.Error {
-	panic("noimpl")
+func writeExpectf(rw *bufio.ReadWriter, expect []byte, format string, args ...interface{}) os.Error {
+	_, err := fmt.Fprintf(rw, format, args...)
+	if err != nil {
+		return err
+	}
+	if err := rw.Flush(); err != nil {
+		return err
+	}
+	line, err := rw.ReadSlice('\n')
+	if err != nil {
+		return err
+	}
+	switch {
+	case bytes.Equal(line, expect):
+		return nil
+	case bytes.Equal(line, resultNotStored):
+		return ErrNotStored
+	case bytes.Equal(line, resultExists):
+		return ErrCASConflict
+	case bytes.Equal(line, resultNotFound):
+		return ErrCacheMiss
+	}
+	return fmt.Errorf("memcache: unexpected response line: %q", string(line))
 }
 
-func (c *Client) delete(rw *bufio.ReadWriter, item *Item) os.Error {
-	panic("noimpl")
+func (c *Client) Delete(key string) os.Error {
+	return c.withKeyAddr(key, func(rw *bufio.ReadWriter) os.Error {
+		return writeExpectf(rw, resultDeleted, "delete %s\r\n", key)
+	})
 }