[memcached] sgrimm, r318: If a client tries to store an object tha...

commits at code.sixapart.com commits at code.sixapart.com
Wed Aug 23 19:33:44 UTC 2006


If a client tries to store an object that's too large for the cache (the
maximum is currently 1MB), print a more accurate error message than "out
of memory."


U   branches/facebook/items.c
U   branches/facebook/memcached.c
U   branches/facebook/memcached.h


Modified: branches/facebook/items.c
===================================================================
--- branches/facebook/items.c	2006-08-23 19:30:01 UTC (rev 317)
+++ branches/facebook/items.c	2006-08-23 19:33:43 UTC (rev 318)
@@ -36,15 +36,30 @@
 }
 
 
+/*
+ * Generates the variable-sized part of the header for an object.
+ *
+ * suffix  - Buffer for the "VALUE" line suffix (flags, size).
+ * nsuffix - The length of the suffix is stored here.
+ * keylen  - The length of the key plus any padding required to word-align the
+ *           "VALUE" suffix (which is done to speed up copying.)
+ *
+ * Returns the total size of the header.
+ */
+int item_make_header(char *key, int flags, int nbytes,
+                     char *suffix, int *nsuffix, int *keylen) {
+    *keylen = strlen(key) + 1; if(*keylen % 4) *keylen += 4 - (*keylen % 4);
+    *nsuffix = sprintf(suffix, " %u %u\r\n", flags, nbytes - 2);
+    return sizeof(item) + *keylen + *nsuffix + nbytes;
+}
+ 
 item *item_alloc(char *key, int flags, rel_time_t exptime, int nbytes) {
     int nsuffix, ntotal, len;
     item *it;
     unsigned int id;
     char suffix[40];
 
-    len = strlen(key) + 1; if(len % 4) len += 4 - (len % 4);
-    nsuffix = sprintf(suffix, " %u %u\r\n", flags, nbytes - 2);
-    ntotal = sizeof(item) + len + nsuffix + nbytes;
+    ntotal = item_make_header(key, flags, nbytes, suffix, &nsuffix, &len);
  
     id = slabs_clsid(ntotal);
     if (id == 0)
@@ -112,6 +127,18 @@
     slabs_free(it, ntotal);
 }
 
+/*
+ * Returns true if an item will fit in the cache (its size does not exceed
+ * the maximum for a cache entry.)
+ */
+int item_size_ok(char *key, int flags, int nbytes) {
+    char prefix[40];
+    int keylen, nsuffix;
+
+    return slabs_clsid(item_make_header(key, flags, nbytes,
+                                        prefix, &nsuffix, &keylen)) != 0;
+}
+
 void item_link_q(item *it) { /* item is the new head */
     item **head, **tail;
     assert(it->slabs_clsid <= LARGEST_ID);

Modified: branches/facebook/memcached.c
===================================================================
--- branches/facebook/memcached.c	2006-08-23 19:30:01 UTC (rev 317)
+++ branches/facebook/memcached.c	2006-08-23 19:33:43 UTC (rev 318)
@@ -817,7 +817,10 @@
         it = item_alloc(key, flags, realtime(expire), len+2);
 
         if (it == 0) {
-            out_string(c, "SERVER_ERROR out of memory");
+            if (! item_size_ok(key, flags, len + 2))
+                out_string(c, "SERVER_ERROR object too large for cache");
+            else
+                out_string(c, "SERVER_ERROR out of memory");
             /* swallow the data line */
             c->write_and_go = conn_swallow;
             c->sbytes = len+2;

Modified: branches/facebook/memcached.h
===================================================================
--- branches/facebook/memcached.h	2006-08-23 19:30:01 UTC (rev 317)
+++ branches/facebook/memcached.h	2006-08-23 19:33:43 UTC (rev 318)
@@ -268,6 +268,7 @@
 void item_init(void);
 item *item_alloc(char *key, int flags, rel_time_t exptime, int nbytes);
 void item_free(item *it);
+int item_size_ok(char *key, int flags, int nbytes);
 
 int item_link(item *it);    /* may fail if transgresses limits */
 void item_unlink(item *it);




More information about the memcached-commits mailing list