typedef struct memcached_server_st memcached_server_st;
typedef memcached_return (*clone_func)(memcached_st *parent, memcached_st *clone);
typedef memcached_return (*cleanup_func)(memcached_st *ptr);
-
+typedef void (*memcached_free_function)(memcached_st *ptr, void *mem);
+typedef void *(*memcached_malloc_function)(memcached_st *ptr, const size_t size);
+typedef void *(*memcached_realloc_function)(memcached_st *ptr, void *mem, const size_t size);
typedef enum {
MEMCACHED_DISTRIBUTION_MODULA,
MEMCACHED_CALLBACK_USER_DATA,
MEMCACHED_CALLBACK_CLEANUP_FUNCTION,
MEMCACHED_CALLBACK_CLONE_FUNCTION,
+ MEMCACHED_CALLBACK_MALLOC_FUNCTION,
+ MEMCACHED_CALLBACK_REALLOC_FUNCTION,
+ MEMCACHED_CALLBACK_FREE_FUNCTION,
} memcached_callback;
typedef enum {
unsigned int wheel[MEMCACHED_WHEEL_SIZE];
clone_func on_clone;
cleanup_func on_cleanup;
+ memcached_free_function call_free;
+ memcached_malloc_function call_malloc;
+ memcached_realloc_function call_realloc;
#ifdef NOT_USED /* Future Use */
uint8_t replicas;
memcached_return warning;
char *buffer,
memcached_result_st *result,
unsigned int server_key);
+void server_list_free(memcached_st *ptr, memcached_server_st *servers);
#endif /* __COMMON_H__ */
memcached_st *memcached_create(memcached_st *ptr)
{
memcached_result_st *result_ptr;
- if (!ptr)
+
+ if (ptr == NULL)
{
ptr= (memcached_st *)malloc(sizeof(memcached_st));
{
/* If we have anything open, lets close it now */
memcached_quit(ptr);
- memcached_server_list_free(ptr->hosts);
+ server_list_free(ptr, ptr->hosts);
memcached_result_free(&ptr->result);
if (ptr->on_cleanup)
ptr->on_cleanup(ptr);
if (ptr->is_allocated == MEMCACHED_ALLOCATED)
- free(ptr);
+ {
+ if (ptr->call_free)
+ ptr->call_free(ptr, ptr);
+ else
+ free(ptr);
+ }
else
ptr->is_allocated= MEMCACHED_USED;
}
new_clone->hash= ptr->hash;
new_clone->user_data= ptr->user_data;
+ new_clone->on_clone= ptr->on_clone;
+ new_clone->on_cleanup= ptr->on_cleanup;
+ new_clone->call_free= ptr->call_free;
+ new_clone->call_malloc= ptr->call_malloc;
+ new_clone->call_realloc= ptr->call_realloc;
+
if (ptr->on_clone)
ptr->on_clone(ptr, new_clone);
ptr->on_clone= func;
break;
}
+ case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
+ {
+ memcached_malloc_function func= (memcached_malloc_function)data;
+ ptr->call_malloc= func;
+ break;
+ }
+ case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
+ {
+ memcached_realloc_function func= (memcached_realloc_function)data;
+ ptr->call_realloc= func;
+ break;
+ }
+ case MEMCACHED_CALLBACK_FREE_FUNCTION:
+ {
+ memcached_free_function func= (memcached_free_function)data;
+ ptr->call_free= func;
+ break;
+ }
default:
return MEMCACHED_FAILURE;
}
*error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
return (void *)ptr->on_clone;
}
+ case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
+ {
+ *error= ptr->call_malloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+ return (void *)ptr->call_malloc;
+ }
+ case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
+ {
+ *error= ptr->call_realloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+ return (void *)ptr->call_realloc;
+ }
+ case MEMCACHED_CALLBACK_FREE_FUNCTION:
+ {
+ *error= ptr->call_free ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+ return (void *)ptr->call_free;
+ }
default:
WATCHPOINT_ASSERT(0);
*error= MEMCACHED_FAILURE;
host->sockaddr_inited= MEMCACHED_NOT_ALLOCATED;
}
+void server_list_free(memcached_st *ptr, memcached_server_st *servers)
+{
+ unsigned int x;
+
+ if (servers == NULL)
+ return;
+
+ for (x= 0; x < servers->count; x++)
+ if (servers[x].address_info)
+ freeaddrinfo(servers[x].address_info);
+
+ if (ptr && ptr->call_free)
+ ptr->call_free(ptr, servers);
+ else
+ free(servers);
+}
+
memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
{
unsigned int x;
count= list[0].count;
- new_host_list=
- (memcached_server_st *)realloc(ptr->hosts,
- sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
+ if (ptr->call_realloc)
+ new_host_list=
+ (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
+ sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
+ else
+ new_host_list=
+ (memcached_server_st *)realloc(ptr->hosts,
+ sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
if (!new_host_list)
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
LIBMEMCACHED_MEMCACHED_SERVER_ADD_START();
- new_host_list= (memcached_server_st *)realloc(ptr->hosts,
- sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
- if (!new_host_list)
+ if (ptr->call_realloc)
+ new_host_list= (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
+ sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
+ else
+ new_host_list= (memcached_server_st *)realloc(ptr->hosts,
+ sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
+ if (new_host_list == NULL)
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
ptr->hosts= new_host_list;
void memcached_server_list_free(memcached_server_st *ptr)
{
- unsigned int x;
-
- if (ptr == NULL)
- return;
-
- for (x= 0; x < ptr->count; x++)
- if (ptr[x].address_info)
- freeaddrinfo(ptr[x].address_info);
-
- free(ptr);
+ server_list_free(NULL, ptr);
}
}
else
{
- ptr= (memcached_result_st *)malloc(sizeof(memcached_result_st));
- if (!ptr)
+ if (memc->call_malloc)
+ ptr= (memcached_result_st *)memc->call_malloc(ptr->root, sizeof(memcached_result_st));
+ else
+ ptr= (memcached_result_st *)malloc(sizeof(memcached_result_st));
+
+ if (ptr == NULL)
return NULL;
memset(ptr, 0, sizeof(memcached_result_st));
ptr->is_allocated= MEMCACHED_ALLOCATED;
char *key, memcached_return *error)
{
char buffer[SMALL_STRING_LEN];
+ size_t length;
+ char *ret;
+
*error= MEMCACHED_SUCCESS;
if (!memcmp("pid", key, strlen("pid")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->pid);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->pid);
else if (!memcmp("uptime", key, strlen("uptime")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->uptime);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->uptime);
else if (!memcmp("time", key, strlen("time")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->time);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->time);
else if (!memcmp("version", key, strlen("version")))
- snprintf(buffer, SMALL_STRING_LEN,"%s", stat->version);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%s", stat->version);
else if (!memcmp("pointer_size", key, strlen("pointer_size")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->pointer_size);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->pointer_size);
else if (!memcmp("rusage_user", key, strlen("rusage_user")))
- snprintf(buffer, SMALL_STRING_LEN,"%u.%u", stat->rusage_user_seconds, stat->rusage_user_microseconds);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u.%u", stat->rusage_user_seconds, stat->rusage_user_microseconds);
else if (!memcmp("rusage_system", key, strlen("rusage_system")))
- snprintf(buffer, SMALL_STRING_LEN,"%u.%u", stat->rusage_system_seconds, stat->rusage_system_microseconds);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u.%u", stat->rusage_system_seconds, stat->rusage_system_microseconds);
else if (!memcmp("curr_items", key, strlen("curr_items")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->curr_items);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->curr_items);
else if (!memcmp("total_items", key, strlen("total_items")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->total_items);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->total_items);
else if (!memcmp("bytes", key, strlen("bytes")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->bytes);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->bytes);
else if (!memcmp("curr_connections", key, strlen("curr_connections")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->curr_connections);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->curr_connections);
else if (!memcmp("total_connections", key, strlen("total_connections")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->total_connections);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->total_connections);
else if (!memcmp("connection_structures", key, strlen("connection_structures")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->connection_structures);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->connection_structures);
else if (!memcmp("cmd_get", key, strlen("cmd_get")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->cmd_get);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->cmd_get);
else if (!memcmp("cmd_set", key, strlen("cmd_set")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->cmd_set);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->cmd_set);
else if (!memcmp("get_hits", key, strlen("get_hits")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->get_hits);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->get_hits);
else if (!memcmp("get_misses", key, strlen("get_misses")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->get_misses);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->get_misses);
else if (!memcmp("evictions", key, strlen("evictions")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->evictions);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->evictions);
else if (!memcmp("bytes_read", key, strlen("bytes_read")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->bytes_read);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->bytes_read);
else if (!memcmp("bytes_written", key, strlen("bytes_written")))
- snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->bytes_written);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)stat->bytes_written);
else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->limit_maxbytes);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->limit_maxbytes);
else if (!memcmp("threads", key, strlen("threads")))
- snprintf(buffer, SMALL_STRING_LEN,"%u", stat->threads);
+ length= snprintf(buffer, SMALL_STRING_LEN,"%u", stat->threads);
else
{
*error= MEMCACHED_NOTFOUND;
return NULL;
}
- return strdup(buffer);
+ if (ptr->call_malloc)
+ ret= ptr->call_malloc(ptr, length + 1);
+ else
+ ret= malloc(length + 1);
+ memcpy(ret, buffer, length);
+ ret[length]= '\0';
+
+ return ret;
}
static memcached_return memcached_stats_fetch(memcached_st *ptr,
memcached_return rc;
memcached_stat_st *stats;
- stats= (memcached_stat_st *)malloc(sizeof(memcached_stat_st)*(ptr->number_of_hosts));
+ if (ptr->call_malloc)
+ stats= (memcached_stat_st *)ptr->call_malloc(ptr, sizeof(memcached_stat_st)*(ptr->number_of_hosts));
+ else
+ stats= (memcached_stat_st *)malloc(sizeof(memcached_stat_st)*(ptr->number_of_hosts));
+
if (!stats)
{
*error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
- free(stats);
+ if (ptr->call_free)
+ ptr->call_free(ptr, stats);
+ else
+ free(stats);
+
return NULL;
}
memset(stats, 0, sizeof(memcached_stat_st)*(ptr->number_of_hosts));
{
char **list;
size_t length= sizeof(memcached_stat_keys);
- list= (char **)malloc(length);
+
+ if (ptr->call_malloc)
+ list= (char **)ptr->call_malloc(ptr, length);
+ else
+ list= (char **)malloc(length);
if (!list)
{
void memcached_stat_free(memcached_st *ptr, memcached_stat_st *stat)
{
- free(stat);
+ if (stat == NULL)
+ {
+ WATCHPOINT_ASSERT(0); /* Be polite, but when debugging catch this as an error */
+ return;
+ }
+
+ if (ptr && ptr->call_free)
+ ptr->call_free(ptr, stat);
+ else
+ free(stat);
}
if (new_size < need)
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
- new_value= (char *)realloc(string->string, new_size);
+ if (string->root->call_realloc)
+ new_value= (char *)string->root->call_realloc(string->root, string->string, new_size);
+ else
+ new_value= (char *)realloc(string->string, new_size);
if (new_value == NULL)
return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
}
else
{
- string= (memcached_string_st *)malloc(sizeof(memcached_string_st));
- if (!string)
+ if (ptr->call_malloc)
+ string= (memcached_string_st *)ptr->call_malloc(ptr, sizeof(memcached_string_st));
+ else
+ string= (memcached_string_st *)malloc(sizeof(memcached_string_st));
+
+ if (string == NULL)
return NULL;
memset(string, 0, sizeof(memcached_string_st));
string->is_allocated= MEMCACHED_ALLOCATED;
rc= memcached_string_check(string, initial_size);
if (rc != MEMCACHED_SUCCESS)
{
- free(string);
+ if (ptr->call_free)
+ ptr->call_free(ptr, string);
+ else
+ free(string);
+
return NULL;
}
WATCHPOINT_ASSERT(string->is_allocated != MEMCACHED_USED);
- c_ptr= (char *)malloc((memcached_string_length(string)+1) * sizeof(char));
- if (!c_ptr)
+ if (string->root->call_malloc)
+ c_ptr= (char *)string->root->call_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
+ else
+ c_ptr= (char *)malloc((memcached_string_length(string)+1) * sizeof(char));
+
+ if (c_ptr == NULL)
return NULL;
memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
return;
if (ptr->string)
- free(ptr->string);
+ {
+ if (ptr->root->call_free)
+ ptr->root->call_free(ptr->root, ptr->string);
+ else
+ free(ptr->string);
+ }
if (ptr->is_allocated == MEMCACHED_ALLOCATED)
- free(ptr);
+ {
+ if (ptr->root->call_free)
+ ptr->root->call_free(ptr->root, ptr);
+ else
+ free(ptr);
+ }
else
ptr->is_allocated= MEMCACHED_USED;
}
value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE);
assert(value > 0);
- {
- int x= 5;
- int *test_ptr;
-
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USER_DATA, &x);
- test_ptr= (int *)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_USER_DATA);
- assert(*test_ptr == x);
- }
-
return 0;
}
return MEMCACHED_SUCCESS;
}
+void my_free(memcached_st *ptr, void *mem)
+{
+ free(mem);
+}
+
+void *my_malloc(memcached_st *ptr, const size_t size)
+{
+ return malloc(size);
+}
+
+void *my_realloc(memcached_st *ptr, void *mem, const size_t size)
+{
+ return realloc(mem, size);
+}
+
+memcached_return set_memory_alloc(memcached_st *memc)
+{
+ {
+ memcached_malloc_function test_ptr;
+ memcached_return rc;
+
+ rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_MALLOC_FUNCTION, &my_malloc);
+ assert(rc == MEMCACHED_SUCCESS);
+ test_ptr= (memcached_malloc_function)memcached_callback_get(memc, MEMCACHED_CALLBACK_USER_DATA, &rc);
+ assert(test_ptr == (memcached_malloc_function)my_malloc);
+ }
+
+ {
+ memcached_realloc_function test_ptr;
+ memcached_return rc;
+
+ rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_REALLOC_FUNCTION, &my_realloc);
+ assert(rc == MEMCACHED_SUCCESS);
+ test_ptr= (memcached_realloc_function)memcached_callback_get(memc, MEMCACHED_CALLBACK_USER_DATA, &rc);
+ assert(test_ptr == my_realloc);
+ }
+
+ {
+ memcached_free_function test_ptr;
+ memcached_return rc;
+
+ rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_FREE_FUNCTION, my_free);
+ assert(rc == MEMCACHED_SUCCESS);
+ test_ptr= (memcached_free_function)memcached_callback_get(memc, MEMCACHED_CALLBACK_USER_DATA, &rc);
+ assert(test_ptr == my_free);
+ }
+
+ return MEMCACHED_SUCCESS;
+}
memcached_return enable_consistent(memcached_st *memc)
{
{"poll_timeout", poll_timeout, 0, tests},
{"gets", enable_cas, 0, tests},
{"consistent", enable_consistent, 0, tests},
+ {"memory_allocators", set_memory_alloc, 0, tests},
// {"udp", pre_udp, 0, tests},
{"version_1_2_3", check_for_1_2_3, 0, version_1_2_3},
{"string", 0, 0, string_tests},