merge upstream
authorTrond Norbye <trond.norbye@sun.com>
Sun, 14 Jun 2009 18:52:39 +0000 (20:52 +0200)
committerTrond Norbye <trond.norbye@sun.com>
Sun, 14 Jun 2009 18:52:39 +0000 (20:52 +0200)
1  2 
libmemcached/memcached.c
libmemcached/memcached.h
tests/function.c

diff --combined libmemcached/memcached.c
index b880d83377c493e9faeeea411218d5007507311e,5991aabb46ced3c685ed7a26fcf0f9a4ce40786e..4e8ec062bcf4f979f92d7aa86404baa640240ee6
@@@ -20,6 -20,9 +20,9 @@@ memcached_st *memcached_create(memcache
    {
      memset(ptr, 0, sizeof(memcached_st));
    }
+   memcached_set_memory_allocators(ptr, NULL, NULL, NULL, NULL);
    result_ptr= memcached_result_create(ptr, &ptr->result);
    WATCHPOINT_ASSERT(result_ptr);
    ptr->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
@@@ -45,20 -48,10 +48,10 @@@ void memcached_free(memcached_st *ptr
      ptr->on_cleanup(ptr);
  
    if (ptr->continuum)
-   {
-     if (ptr->call_free)
-       ptr->call_free(ptr, ptr->continuum);
-     else
-       free(ptr->continuum);
-   }
+     ptr->call_free(ptr, ptr->continuum);
  
    if (ptr->is_allocated)
-   {
-     if (ptr->call_free)
-       ptr->call_free(ptr, ptr);
-     else
-       free(ptr);
-   }
+     ptr->call_free(ptr, ptr);
    else
      memset(ptr, 0, sizeof(memcached_st));
  }
@@@ -105,13 -98,13 +98,14 @@@ memcached_st *memcached_clone(memcached
    new_clone->call_free= source->call_free;
    new_clone->call_malloc= source->call_malloc;
    new_clone->call_realloc= source->call_realloc;
+   new_clone->call_calloc= source->call_calloc;
    new_clone->get_key_failure= source->get_key_failure;
    new_clone->delete_trigger= source->delete_trigger;
    new_clone->server_failure_limit= source->server_failure_limit;
    new_clone->io_msg_watermark= source->io_msg_watermark;
    new_clone->io_bytes_watermark= source->io_bytes_watermark;
    new_clone->io_key_prefetch= source->io_key_prefetch;
 +  new_clone->number_of_replicas= source->number_of_replicas;
  
    if (source->hosts)
      rc= memcached_server_push(new_clone, source->hosts);
  
    return new_clone;
  }
+ void *memcached_get_user_data(memcached_st *ptr)
+ {
+   return ptr->user_data;
+ }
+ void *memcached_set_user_data(memcached_st *ptr, void *data)
+ {
+   void *ret= ptr->user_data;
+   ptr->user_data= data;
+   return ret;
+ }
diff --combined libmemcached/memcached.h
index 47cc4c564d069f42c112a30421d985c365c96121,607fb4b6000d7fdbc66fa00a89af47165aef0454..23f5d99a29101728985e3e2c9d44c553e1a4c319
@@@ -116,10 -116,10 +116,11 @@@ struct memcached_st 
    memcached_free_function call_free;
    memcached_malloc_function call_malloc;
    memcached_realloc_function call_realloc;
+   memcached_calloc_function call_calloc;
    memcached_trigger_key get_key_failure;
    memcached_trigger_delete_key delete_trigger;
    char prefix_key[MEMCACHED_PREFIX_KEY_MAX_SIZE];
 +  uint32_t number_of_replicas;
  };
  
  
@@@ -231,10 -231,29 +232,29 @@@ void *memcached_callback_get(memcached_
  memcached_return memcached_dump(memcached_st *ptr, memcached_dump_func *function, void *context, uint32_t number_of_callbacks);
  
  
+ memcached_return memcached_set_memory_allocators(memcached_st *ptr,
+                                                  memcached_malloc_function mem_malloc,
+                                                  memcached_free_function mem_free,
+                                                  memcached_realloc_function mem_realloc,
+                                                  memcached_calloc_function mem_calloc);
+ void memcached_get_memory_allocators(memcached_st *ptr,
+                                      memcached_malloc_function *mem_malloc,
+                                      memcached_free_function *mem_free,
+                                      memcached_realloc_function *mem_realloc,
+                                      memcached_calloc_function *mem_calloc);
+ void *memcached_get_user_data(memcached_st *ptr);
+ void *memcached_set_user_data(memcached_st *ptr, void *data);
  #ifdef __cplusplus
  }
  #endif
  
  #include <libmemcached/memcached_storage.h>
  
+ #ifdef MEMCACHED_INTERNAL
+ #include <libmemcached/memcached_internal.h>
+ #endif
  #endif /* __MEMCACHED_H__ */
diff --combined tests/function.c
index 3113fb1f5943aa98f186b4d5751611e2e99547df,99ad776aecc1bc8154c4dc58cca229b885fd925c..7b13b1b6d9b462dd1ff856b0355eabb9567fd13c
@@@ -215,6 -215,7 +215,7 @@@ static test_return  clone_test(memcache
      assert(clone->call_free == memc->call_free);
      assert(clone->call_malloc == memc->call_malloc);
      assert(clone->call_realloc == memc->call_realloc);
+     assert(clone->call_calloc == memc->call_calloc);
      assert(clone->connect_timeout == memc->connect_timeout);
      assert(clone->delete_trigger == memc->delete_trigger);
      assert(clone->distribution == memc->distribution);
      assert(clone->server_failure_limit == memc->server_failure_limit);
      assert(clone->snd_timeout == memc->snd_timeout);
      assert(clone->user_data == memc->user_data);
 +    assert(clone->number_of_replicas == memc->number_of_replicas);
  
      memcached_free(clone);
    }
    return 0;
  }
  
+ static test_return userdata_test(memcached_st *memc)
+ {
+   void* foo;
+   assert(memcached_set_user_data(memc, foo) == NULL);
+   assert(memcached_get_user_data(memc) == foo);
+   assert(memcached_set_user_data(memc, NULL) == foo);
+   
+   return TEST_SUCCESS;
+ }
  static test_return  connection_test(memcached_st *memc)
  {
    memcached_return rc;
@@@ -1542,9 -1552,6 +1553,9 @@@ static test_return  behavior_test(memca
    value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE);
    assert(value > 0);
  
 +  value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
 +  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, value + 1);
 +  assert((value + 1) == memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS));
    return 0;
  }
  
@@@ -3040,24 -3047,6 +3051,24 @@@ static memcached_return  pre_binary(mem
    return rc;
  }
  
 +static memcached_return pre_replication(memcached_st *memc)
 +{
 +  memcached_return rc= MEMCACHED_FAILURE;
 +  if (pre_binary(memc) == MEMCACHED_SUCCESS) 
 +  {
 +    /*
 +     * Make sure that we store the item on all servers 
 +     * (master + replicas == number of servers) 
 +     */
 +    rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 
 +                               memc->number_of_hosts - 1);
 +    assert(rc == MEMCACHED_SUCCESS);
 +    assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS) == memc->number_of_hosts - 1);
 +  }
 +
 +  return rc;
 +}
 +
  static void my_free(memcached_st *ptr __attribute__((unused)), void *mem)
  {
    free(mem);
  
  static void *my_malloc(memcached_st *ptr __attribute__((unused)), const size_t size)
  {
-   return calloc(1, size);
+   void *ret= malloc(size);
+   if (ret != NULL)
+     memset(ret, 0xff, size);
+   return ret;
  }
  
  static void *my_realloc(memcached_st *ptr __attribute__((unused)), void *mem, const size_t size)
    return realloc(mem, size);
  }
  
+ static void *my_calloc(memcached_st *ptr __attribute__((unused)), size_t nelem, const size_t size)
+ {
+   return calloc(nelem, size);
+ }
  static memcached_return set_prefix(memcached_st *memc)
  {
    memcached_return rc;
    return MEMCACHED_SUCCESS;
  }
  
- static memcached_return  set_memory_alloc(memcached_st *memc)
+ static memcached_return deprecated_set_memory_alloc(memcached_st *memc)
  {
    void *test_ptr= NULL;
    void *cb_ptr= NULL;
      assert(rc == MEMCACHED_SUCCESS);
      assert(test_ptr == cb_ptr);
    }
+   return MEMCACHED_SUCCESS;
+ }
+ static memcached_return set_memory_alloc(memcached_st *memc)
+ {
+   memcached_return rc;
+   rc= memcached_set_memory_allocators(memc, NULL, my_free, 
+                                       my_realloc, my_calloc);
+   assert(rc == MEMCACHED_FAILURE);
+   rc= memcached_set_memory_allocators(memc, my_malloc, my_free, 
+                                       my_realloc, my_calloc);
+   
+   memcached_malloc_function mem_malloc;
+   memcached_free_function mem_free;
+   memcached_realloc_function mem_realloc;
+   memcached_calloc_function mem_calloc;
+   memcached_get_memory_allocators(memc, &mem_malloc, &mem_free, 
+                                   &mem_realloc, &mem_calloc);   
+   assert(mem_malloc == my_malloc);
+   assert(mem_realloc == my_realloc);
+   assert(mem_calloc == my_calloc);
+   assert(mem_free == my_free);
  
    return MEMCACHED_SUCCESS;
  }
@@@ -3520,175 -3542,6 +3564,175 @@@ static test_return connection_pool_test
  }
  #endif
  
 +static test_return replication_set_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +  memcached_st *clone= memcached_clone(NULL, memc);
 +  memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
 +
 +  rc= memcached_set(memc, "bubba", 5, "0", 1, 0, 0);
 +  assert(rc == MEMCACHED_SUCCESS);
 +
 +  /*
 +  ** "bubba" should now be stored on all of our servers. We don't have an
 +  ** easy to use API to address each individual server, so I'll just iterate
 +  ** through a bunch of "master keys" and I should most likely hit all of the
 +  ** servers...
 +  */
 +  for (int x= 'a'; x <= 'z'; ++x)
 +  {
 +    char key[2]= { [0]= (char)x };
 +    size_t len;
 +    uint32_t flags;
 +    char *val= memcached_get_by_key(clone, key, 1, "bubba", 5, 
 +                                    &len, &flags, &rc);
 +    assert(rc == MEMCACHED_SUCCESS);
 +    assert(val != NULL);
 +    free(val);
 +  }
 +
 +  memcached_free(clone);
 +
 +  return TEST_SUCCESS;
 +}
 +
 +static test_return replication_get_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +
 +  /*
 +   * Don't do the following in your code. I am abusing the internal details
 +   * within the library, and this is not a supported interface.
 +   * This is to verify correct behavior in the library
 +   */
 +  for (int host= 0; host < memc->number_of_hosts; ++host) {
 +    memcached_st *clone= memcached_clone(NULL, memc);
 +    clone->hosts[host].port= 0;
 +
 +    for (int x= 'a'; x <= 'z'; ++x)
 +    {
 +      char key[2]= { [0]= (char)x };
 +      size_t len;
 +      uint32_t flags;
 +      char *val= memcached_get_by_key(clone, key, 1, "bubba", 5, 
 +                                      &len, &flags, &rc);
 +      assert(rc == MEMCACHED_SUCCESS);
 +      assert(val != NULL);
 +      free(val);
 +    }
 +
 +    memcached_free(clone);
 +  }
 +
 +  return TEST_SUCCESS;
 +}
 +
 +static test_return replication_mget_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +  memcached_st *clone= memcached_clone(NULL, memc);
 +  memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
 +
 +  char *keys[]= { "bubba", "key1", "key2", "key3" };
 +  size_t len[]= { 5, 4, 4, 4 };
 +
 +  for (int x=0; x< 4; ++x)
 +  {
 +    rc= memcached_set(memc, keys[x], len[x], "0", 1, 0, 0);
 +    assert(rc == MEMCACHED_SUCCESS);
 +  }
 +
 +  /*
 +   * Don't do the following in your code. I am abusing the internal details
 +   * within the library, and this is not a supported interface.
 +   * This is to verify correct behavior in the library
 +   */
 +  memcached_result_st result_obj;
 +  for (int host= 0; host < clone->number_of_hosts; ++host) {
 +    memcached_st *clone= memcached_clone(NULL, memc);
 +    clone->hosts[host].port= 0;
 +
 +    for (int x= 'a'; x <= 'z'; ++x)
 +    {
 +      char key[2]= { [0]= (char)x };
 +
 +      rc= memcached_mget_by_key(clone, key, 1, keys, len, 4);
 +      assert(rc == MEMCACHED_SUCCESS);
 +
 +      memcached_result_st *results= memcached_result_create(clone, &result_obj);
 +      assert(results);
 +
 +      int hits= 0;
 +      while ((results= memcached_fetch_result(clone, &result_obj, &rc)) != NULL)
 +      {
 +        ++hits;
 +      }
 +      assert(hits == 4);
 +      memcached_result_free(&result_obj);
 +    }
 +
 +    memcached_free(clone);
 +  }
 +
 +  return TEST_SUCCESS;
 +}
 +
 +static test_return replication_delete_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +  memcached_st *clone= memcached_clone(NULL, memc);
 +  /* Delete the items from all of the servers except 1 */
 +  uint64_t repl= memcached_behavior_get(memc,
 +                                        MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
 +  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, --repl);
 +
 +  char *keys[]= { "bubba", "key1", "key2", "key3" };
 +  size_t len[]= { 5, 4, 4, 4 };
 +
 +  for (int x=0; x< 4; ++x)
 +  {
 +    rc= memcached_delete_by_key(memc, keys[0], len[0], keys[x], len[x], 0);
 +    assert(rc == MEMCACHED_SUCCESS);
 +  }
 +
 +  /*
 +   * Don't do the following in your code. I am abusing the internal details
 +   * within the library, and this is not a supported interface.
 +   * This is to verify correct behavior in the library
 +   */
 +  int hash= memcached_generate_hash(memc, keys[0], len[0]);
 +  for (int x= 0; x < (repl + 1); ++x) {
 +    clone->hosts[hash].port= 0;
 +    if (++hash == clone->number_of_hosts)
 +      hash= 0;
 +  }
 +
 +  memcached_result_st result_obj;
 +  for (int host= 0; host < clone->number_of_hosts; ++host) {
 +    for (int x= 'a'; x <= 'z'; ++x)
 +    {
 +      char key[2]= { [0]= (char)x };
 +
 +      rc= memcached_mget_by_key(clone, key, 1, keys, len, 4);
 +      assert(rc == MEMCACHED_SUCCESS);
 +
 +      memcached_result_st *results= memcached_result_create(clone, &result_obj);
 +      assert(results);
 +
 +      int hits= 0;
 +      while ((results= memcached_fetch_result(clone, &result_obj, &rc)) != NULL)
 +      {
 +        ++hits;
 +      }
 +      assert(hits == 4);
 +      memcached_result_free(&result_obj);
 +    }
 +  }
 +  memcached_free(clone);
 +
 +  return TEST_SUCCESS;
 +}
 +
  static void increment_request_id(uint16_t *id)
  {
    (*id)++;
@@@ -4288,6 -4141,7 +4332,7 @@@ test_st tests[] =
    {"connection_test", 0, connection_test},
    {"callback_test", 0, callback_test},
    {"behavior_test", 0, behavior_test},
+   {"userdata_test", 0, userdata_test},
    {"error", 0, error_test },
    {"set", 0, set_test },
    {"set2", 0, set_test2 },
@@@ -4393,14 -4247,6 +4438,14 @@@ test_st user_tests[] =
    {0, 0, 0}
  };
  
 +test_st replication_tests[]= {
 +  {"set", 1, replication_set_test },
 +  {"get", 0, replication_get_test },
 +  {"mget", 0, replication_mget_test },
 +  {"delete", 0, replication_delete_test },
 +  {0, 0, 0}
 +};
 +
  test_st generate_tests[] ={
    {"generate_pairs", 1, generate_pairs },
    {"generate_data", 1, generate_data },
@@@ -4484,6 -4330,7 +4529,7 @@@ collection_st collection[] =
    {"poll_timeout", poll_timeout, 0, tests},
    {"gets", enable_cas, 0, tests},
    {"consistent", enable_consistent, 0, tests},
+   {"deprecated_memory_allocators", deprecated_set_memory_alloc, 0, tests},
    {"memory_allocators", set_memory_alloc, 0, tests},
    {"prefix", set_prefix, 0, tests},
    {"version_1_2_3", check_for_1_2_3, 0, version_1_2_3},
    {"consistent_ketama", pre_behavior_ketama, 0, consistent_tests},
    {"consistent_ketama_weighted", pre_behavior_ketama_weighted, 0, consistent_weighted_tests},
    {"test_hashes", 0, 0, hash_tests},
 +  {"replication", pre_replication, 0, replication_tests},
    {0, 0, 0, 0}
  };