Fixed bug reported by Stuart Midgley about what happens when there are no
authorBrian Aker <brian@tangent.org>
Fri, 9 Nov 2007 18:11:09 +0000 (10:11 -0800)
committerBrian Aker <brian@tangent.org>
Fri, 9 Nov 2007 18:11:09 +0000 (10:11 -0800)
servers and you try to set/get values.

lib/memcached_auto.c
lib/memcached_connect.c
lib/memcached_delete.c
lib/memcached_flush.c
lib/memcached_get.c
lib/memcached_hash.c
lib/memcached_quit.c
lib/memcached_storage.c
tests/function.c

index 69b975c1603598296c8618bba6b532eb981e4ecc..25f9aaf9efb7f44a5348a46fc2e12bc4d790762c 100644 (file)
@@ -11,6 +11,9 @@ static memcached_return memcached_auto(memcached_st *ptr,
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   unsigned int server_key;
 
+  if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
   server_key= memcached_generate_hash(ptr, key, key_length);
 
   if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS)
index 68b9c9398b82dc49d3ef6bee7dea479942dac5d7..025fdf6e00e589532a69f33b50ee790d01eba68b 100644 (file)
@@ -134,10 +134,10 @@ memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key)
   memcached_return rc= MEMCACHED_NO_SERVERS;
   LIBMEMCACHED_MEMCACHED_CONNECT_START();
 
-  if (ptr->connected == ptr->number_of_hosts)
+  if (ptr->connected == ptr->number_of_hosts && ptr->number_of_hosts)
     return MEMCACHED_SUCCESS;
 
-  if (!ptr->hosts)
+  if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
     return MEMCACHED_NO_SERVERS;
 
   /* We need to clean up the multi startup piece */
index 6a8495335e17a10e5f30aa167043efe6ba5e9431..0ed6092a03f0b8114e003ea31d22149d467e9bcc 100644 (file)
@@ -11,6 +11,9 @@ memcached_return memcached_delete(memcached_st *ptr, char *key, size_t key_lengt
 
   LIBMEMCACHED_MEMCACHED_DELETE_START();
 
+  if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
   server_key= memcached_generate_hash(ptr, key, key_length);
 
   if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS)
index 8538aaa0cc753f7e6c963d542d140b1f8cb32a2a..58f5bff2d8919be99c7d7a09e738f984f109bf02 100644 (file)
@@ -10,6 +10,9 @@ memcached_return memcached_flush(memcached_st *ptr, time_t expiration)
 
   rc= memcached_connect(ptr, 0);
 
+  if (rc == MEMCACHED_NO_SERVERS)
+    return rc;
+
   if (rc != MEMCACHED_SUCCESS)
     rc= MEMCACHED_SOME_ERRORS;
 
index 01f388c91069e68ef9383de0fc00cfeed393f1f5..c0da409d9750f7539140e0f3a0c325f6c30732ef 100644 (file)
@@ -143,6 +143,12 @@ char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
   memcached_string_st *result_buffer;
   LIBMEMCACHED_MEMCACHED_GET_START();
 
+  if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+  {
+    *error= MEMCACHED_NO_SERVERS;
+    return NULL;
+  }
+
   server_key= memcached_generate_hash(ptr, key, key_length);
   result_buffer= &ptr->result_buffer;
 
@@ -218,6 +224,9 @@ memcached_return memcached_mget(memcached_st *ptr,
   if (number_of_keys == 0)
     return MEMCACHED_NOTFOUND;
 
+  if (ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
   cursor_key_exec= (char *)malloc(sizeof(char) * ptr->number_of_hosts);
   memset(cursor_key_exec, 0, sizeof(char) * ptr->number_of_hosts);
 
index 7e7814e6818be2802c50d8f25929897bac73e2c8..33c1055bbfd70ffd60aa1e902739367136b08705 100644 (file)
@@ -17,6 +17,8 @@ unsigned int memcached_generate_hash(memcached_st *ptr, char *key, size_t key_le
   uint64_t hash= 1; /* Just here to remove compile warning */
   unsigned int x;
 
+  WATCHPOINT_ASSERT(ptr->number_of_hosts);
+
   switch (ptr->hash)
   {
   case MEMCACHED_HASH_DEFAULT:
index 7670b06caabbf2bdaafd84cb1126fa0e179c28f8..20a76e2915e3eb482c9db123f7c289ce4c56fb8a 100644 (file)
 
 void memcached_quit_server(memcached_st *ptr, unsigned int server_key)
 {
+  if (ptr->hosts == NULL || 
+      ptr->number_of_hosts == 0 ||
+      server_key > ptr->number_of_hosts)
+    return;
+
   if (ptr->hosts[server_key].fd != -1)
   {
     if (ptr->flags & MEM_NO_BLOCK && ptr->hosts[server_key].stack_responses)
@@ -31,7 +36,7 @@ void memcached_quit(memcached_st *ptr)
 {
   unsigned int x;
 
-  if (ptr->hosts)
+  if (ptr->hosts && ptr->number_of_hosts)
   {
     for (x= 0; x < ptr->number_of_hosts; x++)
       memcached_quit_server(ptr, x);
index f9ba64d6db358467523f1098417c63d427c57bbe..70201489998f672249d0e6acae60e7d991c4c239 100644 (file)
@@ -41,6 +41,9 @@ static memcached_return memcached_send(memcached_st *ptr,
   if (!(ptr->flags & MEM_NO_BLOCK) && ptr->write_buffer_offset != 0)
     WATCHPOINT_ASSERT(0);
 #endif
+
+  if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
     
   server_key= memcached_generate_hash(ptr, key, key_length);
 
@@ -48,6 +51,7 @@ static memcached_return memcached_send(memcached_st *ptr,
   if (rc != MEMCACHED_SUCCESS)
     return rc;
 
+
   write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
                         "%s %.*s %x %llu %zu\r\n", storage_op_string(verb),
                         (int)key_length, key, flags, 
index 16c75073150058eb23e296e24a0940d00dd86bbe..6bac2d530d5ab946d2b44a434bb997421e12610c 100644 (file)
@@ -870,6 +870,74 @@ uint8_t user_supplied_bug3(memcached_st *memc)
   return 0;
 }
 
+/* Make sure we behave properly if server list has no values */
+uint8_t user_supplied_bug4(memcached_st *memc)
+{
+  memcached_return rc;
+  char *keys[]= {"fudge", "son", "food"};
+  size_t key_length[]= {5, 3, 4};
+  unsigned int x;
+  uint16_t flags;
+
+  /* Here we free everything before running a bunch of mget tests */
+  {
+    memcached_server_list_free(memc->hosts);
+    memc->hosts= NULL;
+    memc->number_of_hosts= 0;
+  }
+
+  char return_key[MEMCACHED_MAX_KEY];
+  size_t return_key_length;
+  char *return_value;
+  size_t return_value_length;
+
+  /* We need to empty the server before continueing test */
+  rc= memcached_flush(memc, 0);
+  WATCHPOINT_ERROR(rc);
+  assert(rc == MEMCACHED_NO_SERVERS);
+
+  rc= memcached_mget(memc, keys, key_length, 3);
+  assert(rc == MEMCACHED_NO_SERVERS);
+
+  while ((return_value= memcached_fetch(memc, return_key, &return_key_length, 
+                      &return_value_length, &flags, &rc)) != NULL)
+  {
+    assert(return_value);
+  }
+  assert(!return_value);
+  assert(return_value_length == 0);
+  assert(rc == MEMCACHED_NO_SERVERS);
+
+  WATCHPOINT;
+  for (x= 0; x < 3; x++)
+  {
+    rc= memcached_set(memc, keys[x], key_length[x], 
+                      keys[x], key_length[x],
+                      (time_t)50, (uint16_t)9);
+    assert(rc == MEMCACHED_NO_SERVERS);
+  }
+
+  WATCHPOINT;
+  rc= memcached_mget(memc, keys, key_length, 3);
+  assert(rc == MEMCACHED_NO_SERVERS);
+  WATCHPOINT;
+
+  x= 0;
+  while ((return_value= memcached_fetch(memc, return_key, &return_key_length, 
+                                        &return_value_length, &flags, &rc)))
+  {
+    WATCHPOINT;
+    assert(return_value);
+    assert(rc == MEMCACHED_SUCCESS);
+    assert(return_key_length == return_value_length);
+    assert(!memcmp(return_value, return_key, return_value_length));
+    free(return_value);
+    x++;
+  }
+
+  return 0;
+}
+
 uint8_t result_static(memcached_st *memc)
 {
   memcached_result_st result;
@@ -1258,6 +1326,7 @@ test_st user_tests[] ={
   {"user_supplied_bug1", 0, user_supplied_bug1 },
   {"user_supplied_bug2", 0, user_supplied_bug2 },
   {"user_supplied_bug3", 0, user_supplied_bug3 },
+  {"user_supplied_bug4", 0, user_supplied_bug4 },
   {0, 0, 0}
 };