From cfe8176feba42fc63e8f627f9ac613a12a368b92 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Fri, 21 Dec 2007 17:00:28 -0800 Subject: [PATCH] NEw code for the memcached_fetch_execute() function. Callbacks are in the house :) --- ChangeLog | 3 +- docs/Makefile.am | 4 +++ docs/libmemcached.pod | 2 +- docs/memcached_get.pod | 14 ++++++++ include/memcached.h | 6 ++++ lib/Makefile.am | 1 + lib/memcached_fetch.c | 2 +- lib/memcached_fetch_execute.c | 48 +++++++++++++++++++++++++++ support/libmemcached.spec.in | 1 + tests/function.c | 61 +++++++++++++++++++++++++++++++++++ 10 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 lib/memcached_fetch_execute.c diff --git a/ChangeLog b/ChangeLog index 094b807d..68671ae4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,7 +6,8 @@ * Added multi delete functions. * All get key returns have C style null termination * If memcached_server_list_append is passed NULLs instead of pointers it - returns NULL. + returns NULL. + * Added memcached_fetch_execute() method 0.12 Tue Dec 11 15:20:55 PST 2007 * Updates for consistent hashing diff --git a/docs/Makefile.am b/docs/Makefile.am index bfcf66ee..f92f77f9 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -46,6 +46,7 @@ man_MANS = libmemcached.3\ memcached_delete.3\ memcached_delete_by_key.3\ memcached_fetch.3\ + memcached_fetch_execute.3\ memcached_fetch_result.3\ memcached_free.3\ memcached_get.3\ @@ -150,6 +151,9 @@ memcached_get_by_key.3: memcached_get.pod memcached_fetch_result.3: memcached_get.pod pod2man -c "libmemcached" -r "" -s 3 memcached_get.pod > memcached_fetch_result.3 +memcached_fetch_execute.3: memcached_get.pod + pod2man -c "libmemcached" -r "" -s 3 memcached_get.pod > memcached_fetch_execute.3 + memcached_mget.3: memcached_get.pod pod2man -c "libmemcached" -r "" -s 3 memcached_get.pod > memcached_mget.3 diff --git a/docs/libmemcached.pod b/docs/libmemcached.pod index c46ad157..9a0626d1 100755 --- a/docs/libmemcached.pod +++ b/docs/libmemcached.pod @@ -73,7 +73,7 @@ Brian Aker, Ebrian@tangent.orgE =head1 SEE ALSO -memcached(1) libmemcached_examples(3) libmemcached(1) memcat(1) memcp(1) memflush(1) memrm(1) memslap(1) memstat(1) memcached_fetch(3) memcached_replace(3) memcached_server_list_free(3) libmemcached_examples(3) memcached_clone(3) memcached_free(3) memcached_server_add(3) memcached_server_push(3) memcached_add(3) memcached_get(3) memcached_server_count(3) memcached_servers_parse(3) memcached_create(3) memcached_increment(3) memcached_server_list(3) memcached_set(3) memcached_decrement(3) memcached_mget(3) memcached_server_list_append(3) memcached_strerror(3) memcached_delete(3) memcached_quit(3) memcached_server_list_count(3) memcached_verbosity(3) memcached_server_add_unix_socket(3) memcahed_result_create(3) memcached_result_free(3) memcached_result_key_value(3) memcached_result_key_length(3) memcached_result_value(3) memcached_result_length(3) memcached_result_flags(3) memcached_result_cas(3) memcached_result_st(3) memcached_append(3) memcached_prepend(3) memcached_fetch_result(3) memerror(1) memcached_get_by_key(3) memcached_mget_by_key(3) memcached_delete_by_key(3) +memcached(1) libmemcached_examples(3) libmemcached(1) memcat(1) memcp(1) memflush(1) memrm(1) memslap(1) memstat(1) memcached_fetch(3) memcached_replace(3) memcached_server_list_free(3) libmemcached_examples(3) memcached_clone(3) memcached_free(3) memcached_server_add(3) memcached_server_push(3) memcached_add(3) memcached_get(3) memcached_server_count(3) memcached_servers_parse(3) memcached_create(3) memcached_increment(3) memcached_server_list(3) memcached_set(3) memcached_decrement(3) memcached_mget(3) memcached_server_list_append(3) memcached_strerror(3) memcached_delete(3) memcached_quit(3) memcached_server_list_count(3) memcached_verbosity(3) memcached_server_add_unix_socket(3) memcahed_result_create(3) memcached_result_free(3) memcached_result_key_value(3) memcached_result_key_length(3) memcached_result_value(3) memcached_result_length(3) memcached_result_flags(3) memcached_result_cas(3) memcached_result_st(3) memcached_append(3) memcached_prepend(3) memcached_fetch_result(3) memerror(1) memcached_get_by_key(3) memcached_mget_by_key(3) memcached_delete_by_key(3) memcached_fetch_execute(3) =cut diff --git a/docs/memcached_get.pod b/docs/memcached_get.pod index 111a3b61..f2f2033c 100755 --- a/docs/memcached_get.pod +++ b/docs/memcached_get.pod @@ -44,6 +44,12 @@ C Client Library for memcached (libmemcached, -lmemcached) size_t *value_length, uint16_t *flags, memcached_return *error); + memcached_return + memcached_fetch_execute(memcached_st *ptr, + unsigned int (*callback[])(memcached_st *ptr, memcached_result_st *result, void *context), + void *context, + unsigned int number_of_callbacks + ) =head1 DESCRIPTION @@ -80,6 +86,14 @@ to the server. For more information please refer to the memcached_result_st(3) help. This function will dynamically allocate a result structure for you if you do not pass one to the function. +memcached_fetch_execute() is a callback function for result sets. Instead +of returning the results to you for processing, it passes each of the +result sets to the list of functions you provide. It passes to the function +a memcached_st that can be cloned for use in called the cluster (it can not +be used directly). It also passed a result set which does not need to be freed. +Finally it passes a "context". This is just a pointer to a memory reference +you supply the calling function. + memcached_get_by_key() and memcached_mget_by_key() behave in a similar nature as memcached_get() and memcached_mget(). The difference is that they take a master key that is used for determining which server an object was stored diff --git a/include/memcached.h b/include/memcached.h index 666e9e6b..1cbdcf68 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -373,6 +373,12 @@ memcached_return memcached_mdelete_by_key(memcached_st *ptr, unsigned int number_of_keys, time_t expiration); +memcached_return memcached_fetch_execute(memcached_st *ptr, + unsigned int (*callback[])(memcached_st *ptr, memcached_result_st *result, void *context), + void *context, + unsigned int number_of_callbacks + ); + /* Result Struct */ void memcached_result_free(memcached_result_st *result); memcached_result_st *memcached_result_create(memcached_st *ptr, diff --git a/lib/Makefile.am b/lib/Makefile.am index 0c632f0d..38c6e8f4 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -34,6 +34,7 @@ libmemcached_la_SOURCES = crc.c \ memcached_delete.c \ memcached_do.c \ memcached_fetch.c \ + memcached_fetch_execute.c \ memcached_flush.c \ memcached_get.c \ memcached_hash.c \ diff --git a/lib/memcached_fetch.c b/lib/memcached_fetch.c index 257bfbc4..f88ff02b 100644 --- a/lib/memcached_fetch.c +++ b/lib/memcached_fetch.c @@ -6,7 +6,7 @@ memcached_return value_fetch(memcached_st *ptr, memcached_result_st *result, unsigned int server_key) { - memcached_return rc; + memcached_return rc= MEMCACHED_SUCCESS; char *string_ptr; char *end_ptr; char *next_ptr; diff --git a/lib/memcached_fetch_execute.c b/lib/memcached_fetch_execute.c new file mode 100644 index 00000000..c1245d4f --- /dev/null +++ b/lib/memcached_fetch_execute.c @@ -0,0 +1,48 @@ +#include "common.h" + +memcached_return memcached_fetch_execute(memcached_st *ptr, + unsigned int (*callback[])(memcached_st *ptr, memcached_result_st *result, void *context), + void *context, + unsigned int number_of_callbacks + ) +{ + memcached_result_st *result= &ptr->result; + + while (ptr->cursor_server < ptr->number_of_hosts) + { + memcached_return rc; + + char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; + + if (memcached_server_response_count(ptr, ptr->cursor_server) == 0) + { + ptr->cursor_server++; + continue; + } + + rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result, ptr->cursor_server); + + if (rc == MEMCACHED_END) /* END means that we move on to the next */ + { + memcached_server_response_reset(ptr, ptr->cursor_server); + ptr->cursor_server++; + continue; + } + else if (rc == MEMCACHED_SUCCESS) + { + unsigned int x; + + for (x= 0; x < number_of_callbacks; x++) + { + unsigned int iferror; + + iferror= (*callback[x])(ptr, result, context); + + if (iferror) + continue; + } + } + } + + return MEMCACHED_SUCCESS; +} diff --git a/support/libmemcached.spec.in b/support/libmemcached.spec.in index 13340f42..1d72454c 100644 --- a/support/libmemcached.spec.in +++ b/support/libmemcached.spec.in @@ -81,6 +81,7 @@ memerror - Creates human readable messages from libmemecached error codes. %{_mandir}/man3/memcached_delete_by_key.3.gz %{_mandir}/man3/memcached_fetch.3.gz %{_mandir}/man3/memcached_fetch_result.3.gz +%{_mandir}/man3/memcached_fetch_execute.3.gz %{_mandir}/man3/memcached_free.3.gz %{_mandir}/man3/memcached_get.3.gz %{_mandir}/man3/memcached_get_by_key.3.gz diff --git a/tests/function.c b/tests/function.c index 3b1e6d45..54bbceaa 100644 --- a/tests/function.c +++ b/tests/function.c @@ -777,6 +777,47 @@ uint8_t mget_result_alloc_test(memcached_st *memc) return 0; } +/* Count the results */ +unsigned int callback_counter(memcached_st *ptr, memcached_result_st *result, void *context) +{ + unsigned int *counter= (unsigned int *)context; + + *counter= *counter + 1; + + return 0; +} + +uint8_t mget_result_function(memcached_st *memc) +{ + memcached_return rc; + char *keys[]= {"fudge", "son", "food"}; + size_t key_length[]= {5, 3, 4}; + unsigned int x; + unsigned int counter; + unsigned int (*callbacks[1])(memcached_st *, memcached_result_st *, void *); + + /* We need to empty the server before continueing test */ + rc= memcached_flush(memc, 0); + for (x= 0; x < 3; x++) + { + rc= memcached_set(memc, keys[x], key_length[x], + keys[x], key_length[x], + (time_t)50, (uint32_t)9); + assert(rc == MEMCACHED_SUCCESS); + } + + rc= memcached_mget(memc, keys, key_length, 3); + assert(rc == MEMCACHED_SUCCESS); + + callbacks[0]= &callback_counter; + counter= 0; + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + + assert(counter == 3); + + return 0; +} + uint8_t mget_test(memcached_st *memc) { memcached_return rc; @@ -1645,6 +1686,7 @@ uint8_t generate_data(memcached_st *memc) return 0; } +#ifdef NOT_DONE uint8_t mset_data(memcached_st *memc) { unsigned long long x; @@ -1660,6 +1702,7 @@ uint8_t mset_data(memcached_st *memc) return 0; } +#endif uint8_t get_read(memcached_st *memc) { @@ -1738,6 +1781,22 @@ uint8_t mget_read_result(memcached_st *memc) return 0; } +uint8_t mget_read_function(memcached_st *memc) +{ + memcached_return rc; + unsigned int counter; + unsigned int (*callbacks[1])(memcached_st *, memcached_result_st *, void *); + + rc= memcached_mget(memc, global_keys, global_keys_length, GLOBAL_COUNT); + assert(rc == MEMCACHED_SUCCESS); + + callbacks[0]= &callback_counter; + counter= 0; + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + + return 0; +} + uint8_t delete_generate(memcached_st *memc) { unsigned int x; @@ -1999,6 +2058,7 @@ test_st tests[] ={ {"mget", 1, mget_test }, {"mget_result", 1, mget_result_test }, {"mget_result_alloc", 1, mget_result_alloc_test }, + {"mget_result_function", 1, mget_result_function }, {"get_stats", 0, get_stats }, {"add_host_test", 0, add_host_test }, {"get_stats_keys", 0, get_stats_keys }, @@ -2058,6 +2118,7 @@ test_st generate_tests[] ={ {"generate_data", 0, generate_data }, {"mget_read", 0, mget_read }, {"mget_read_result", 0, mget_read_result }, + {"mget_read_function", 0, mget_read_function }, {"mdelete_generate", 0, mdelete_generate }, {"cleanup", 0, cleanup_pairs }, {0, 0, 0} -- 2.30.2