Fixed binary mget so that it will always issue a NOOP after every
authorCurtis Hawthorne <curtis@thefjord.org>
Sat, 19 Sep 2009 12:24:37 +0000 (08:24 -0400)
committerCurtis Hawthorne <curtis@thefjord.org>
Sat, 19 Sep 2009 12:24:37 +0000 (08:24 -0400)
request, including requests for only one key.  This allows users
to check for MEMCACHED_END when they fetch.

libmemcached/memcached_get.c
tests/function.c

index ee4f68e7ecb0c006c4025f346340ba0941b41ca6..176be6ad5af2d388b10dc3978c673a409750d7bb 100644 (file)
@@ -14,6 +14,14 @@ char *memcached_get(memcached_st *ptr, const char *key,
                               flags, error);
 }
 
+static memcached_return memcached_mget_by_key_real(memcached_st *ptr, 
+                                       const char *master_key, 
+                                       size_t master_key_length,
+                                       const char **keys, 
+                                       size_t *key_length, 
+                                       size_t number_of_keys,
+                                      bool mget_mode);
+
 char *memcached_get_by_key(memcached_st *ptr, 
                            const char *master_key, 
                            size_t master_key_length, 
@@ -34,10 +42,10 @@ char *memcached_get_by_key(memcached_st *ptr,
   }
 
   /* Request the key */
-  *error= memcached_mget_by_key(ptr, 
+  *error= memcached_mget_by_key_real(ptr, 
                                 master_key, 
                                 master_key_length, 
-                                (const char **)&key, &key_length, 1);
+                                (const char **)&key, &key_length, 1, false);
 
   value= memcached_fetch(ptr, NULL, NULL, 
                          value_length, flags, error);
@@ -112,14 +120,16 @@ static memcached_return binary_mget_by_key(memcached_st *ptr,
                                            unsigned int master_server_key,
                                            bool is_master_key_set,
                                            const char **keys, size_t *key_length,
-                                           size_t number_of_keys);
+                                           size_t number_of_keys,
+                                          bool mget_mode);
 
-memcached_return memcached_mget_by_key(memcached_st *ptr, 
+static memcached_return memcached_mget_by_key_real(memcached_st *ptr, 
                                        const char *master_key, 
                                        size_t master_key_length,
                                        const char **keys, 
                                        size_t *key_length, 
-                                       size_t number_of_keys)
+                                       size_t number_of_keys,
+                                      bool mget_mode)
 {
   unsigned int x;
   memcached_return rc= MEMCACHED_NOTFOUND;
@@ -173,7 +183,7 @@ memcached_return memcached_mget_by_key(memcached_st *ptr,
   
   if (ptr->flags & MEM_BINARY_PROTOCOL)
     return binary_mget_by_key(ptr, master_server_key, is_master_key_set, keys, 
-                              key_length, number_of_keys);
+                              key_length, number_of_keys, mget_mode);
 
   if (ptr->flags & MEM_SUPPORT_CAS)
   {
@@ -256,11 +266,22 @@ memcached_return memcached_mget_by_key(memcached_st *ptr,
   return rc;
 }
 
+memcached_return memcached_mget_by_key(memcached_st *ptr, 
+                                       const char *master_key, 
+                                       size_t master_key_length,
+                                       const char **keys, 
+                                       size_t *key_length, 
+                                       size_t number_of_keys)
+{
+  return memcached_mget_by_key_real(ptr, master_key, master_key_length, keys, 
+                                    key_length, number_of_keys, true);
+}
+
 static memcached_return simple_binary_mget(memcached_st *ptr,
                                            unsigned int master_server_key,
                                            bool is_master_key_set,
                                            const char **keys, size_t *key_length, 
-                                           size_t number_of_keys)
+                                           size_t number_of_keys, bool mget_mode)
 {
   memcached_return rc= MEMCACHED_NOTFOUND;
   uint32_t x;
@@ -289,10 +310,10 @@ static memcached_return simple_binary_mget(memcached_st *ptr,
      
     protocol_binary_request_getk request= {.bytes= {0}};
     request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-    if (number_of_keys == 1)
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
-    else
+    if (mget_mode)
       request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
+    else
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
 
     memcached_return vk;
     vk= memcached_validate_key_length(key_length[x],
@@ -323,7 +344,7 @@ static memcached_return simple_binary_mget(memcached_st *ptr,
       rc= MEMCACHED_SOME_ERRORS;
   }
 
-  if (number_of_keys > 1
+  if (mget_mode
   {
     /*
      * Send a noop command to flush the buffers
@@ -361,7 +382,7 @@ static memcached_return simple_binary_mget(memcached_st *ptr,
 static memcached_return replication_binary_mget(memcached_st *ptr,
                                              uint32_t* hash, bool* dead_servers,
                                              const char **keys, size_t *key_length,
-                                             size_t number_of_keys)
+                                             size_t number_of_keys, bool mget_mode)
 {
   memcached_return rc= MEMCACHED_NOTFOUND;
   uint32_t x;
@@ -398,10 +419,10 @@ static memcached_return replication_binary_mget(memcached_st *ptr,
 
       protocol_binary_request_getk request= {.bytes= {0}};
       request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-      if (number_of_keys == 1)
-        request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
-      else
+      if (mget_mode)
         request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
+      else
+        request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
 
       request.message.header.request.keylen= htons((uint16_t)key_length[x]);
       request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
@@ -420,7 +441,7 @@ static memcached_return replication_binary_mget(memcached_st *ptr,
       memcached_server_response_increment(&ptr->hosts[server]);
     }
 
-    if (number_of_keys > 1)
+    if (mget_mode)
     {
       /*
        * Send a noop command to flush the buffers
@@ -460,14 +481,14 @@ static memcached_return binary_mget_by_key(memcached_st *ptr,
                                            unsigned int master_server_key,
                                            bool is_master_key_set,
                                            const char **keys, size_t *key_length,
-                                           size_t number_of_keys)
+                                           size_t number_of_keys, bool mget_mode)
 {
   memcached_return rc;
 
   if (ptr->number_of_replicas == 0) 
   {
     rc= simple_binary_mget(ptr, master_server_key, is_master_key_set,
-                           keys, key_length, number_of_keys);
+                           keys, key_length, number_of_keys, mget_mode);
   } 
   else 
   {
@@ -492,7 +513,7 @@ static memcached_return binary_mget_by_key(memcached_st *ptr,
         hash[x]= memcached_generate_hash(ptr, keys[x], key_length[x]);
 
     rc= replication_binary_mget(ptr, hash, dead_servers, keys, 
-                                key_length, number_of_keys);
+                                key_length, number_of_keys, mget_mode);
 
     ptr->call_free(ptr, hash);
     ptr->call_free(ptr, dead_servers);
index d3b67f0ff4b320f59b6af25bfce78df785e3cafd..27af67369c5729de9442e37d03061a6968bb05f4 100644 (file)
@@ -1042,6 +1042,70 @@ static test_return get_test5(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static test_return  mget_end(memcached_st *memc)
+{
+  const char *keys[] = { "foo", "foo2" };
+  size_t lengths[] = { 3, 4 };
+  const char *values[] = { "fjord", "41" };
+
+  memcached_return rc;
+
+  // Set foo and foo2
+  for(int i = 0; i < 2; i++)
+  {
+    rc= memcached_set(memc, keys[i], lengths[i], values[i], strlen(values[i]),
+                     (time_t)0, (uint32_t)0);
+    assert(rc == MEMCACHED_SUCCESS);
+  }
+
+  char *string;
+  size_t string_length;
+  uint32_t flags;
+
+  // retrieve both via mget
+  rc= memcached_mget(memc, keys, lengths, 2);
+  assert(rc == MEMCACHED_SUCCESS);
+
+  char key[MEMCACHED_MAX_KEY];
+  size_t key_length;
+
+  // this should get both
+  for(int i = 0; i < 2; i++) {
+    string = memcached_fetch(memc, key, &key_length, &string_length,
+                             &flags, &rc);
+    assert(rc == MEMCACHED_SUCCESS);
+    int val = 0;
+    if(key_length == 4)
+      val = 1;
+    assert(string_length == strlen(values[val]));
+    assert(strncmp(values[val], string, string_length) == 0);
+    free(string);
+  }
+
+  // this should indicate end
+  string = memcached_fetch(memc, key, &key_length, &string_length, &flags, &rc);
+  assert(rc == MEMCACHED_END);
+
+  // now get just one
+  rc= memcached_mget(memc, keys, lengths, 1);
+  assert(rc == MEMCACHED_SUCCESS);
+
+  string = memcached_fetch(memc, key, &key_length, &string_length, &flags, &rc);
+  assert(key_length == lengths[0]);
+  assert(strncmp(keys[0], key, key_length) == 0);
+  assert(string_length == strlen(values[0]));
+  assert(strncmp(values[0], string, string_length) == 0);
+  assert(rc == MEMCACHED_SUCCESS);
+  free(string);
+
+  // this should indicate end
+  string = memcached_fetch(memc, key, &key_length, &string_length, &flags, &rc);
+  assert(rc != MEMCACHED_SUCCESS);
+  assert(rc == MEMCACHED_END);
+
+  return TEST_SUCCESS;
+}
+
 /* Do not copy the style of this code, I just access hosts to testthis function */
 static test_return  stats_servername_test(memcached_st *memc)
 {
@@ -4447,6 +4511,7 @@ test_st tests[] ={
   {"mget_result", 1, mget_result_test },
   {"mget_result_alloc", 1, mget_result_alloc_test },
   {"mget_result_function", 1, mget_result_function },
+  {"mget_end", 0, mget_end },
   {"get_stats", 0, get_stats },
   {"add_host_test", 0, add_host_test },
   {"add_host_test_1", 0, add_host_test1 },