From 3916d5b17296a95839e9993940bd494545f2c767 Mon Sep 17 00:00:00 2001 From: Date: Thu, 3 Jan 2008 17:26:32 -0500 Subject: [PATCH 01/16] Fix to doc for memcached_server_add_unix_socket --- docs/memcached_servers.pod | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/memcached_servers.pod b/docs/memcached_servers.pod index c72e7d64..d417dfd1 100755 --- a/docs/memcached_servers.pod +++ b/docs/memcached_servers.pod @@ -22,8 +22,7 @@ C Client Library for memcached (libmemcached, -lmemcached) memcached_return memcached_server_add_unix_socket (memcached_st *ptr, - char *hostname, - unsigned int port); + char *socket); memcached_return memcached_server_push (memcached_st *ptr, -- 2.30.2 From edeb3965773b750c0cf454e8b1494fd030ba0369 Mon Sep 17 00:00:00 2001 From: Date: Sat, 5 Jan 2008 00:01:45 -0800 Subject: [PATCH 02/16] memcached_behavior() causes commands to be buffered until they are flushed to the remote connection. --- ChangeLog | 3 +++ docs/memcached_behavior.pod | 6 ++++++ include/memcached.h | 2 ++ lib/common.h | 1 + lib/memcached_behavior.c | 5 +++++ lib/memcached_delete.c | 24 ++++-------------------- lib/memcached_storage.c | 8 ++++---- lib/memcached_strerror.c | 2 ++ tests/function.c | 29 +++++++++++++++++++++++++++++ 9 files changed, 56 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index a8e87a7d..6260ba04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,9 @@ * Added memcached_fetch_execute() method * Found a bug where memcached_fetch() was not null terminating the result value. + * memcached_behavior() now has the ability to set "buffering" so that + data is not automatically flushed. + * Behavior change, buffered commands now return MEMCACHED_BUFFERED 0.12 Tue Dec 11 15:20:55 PST 2007 * Updates for consistent hashing diff --git a/docs/memcached_behavior.pod b/docs/memcached_behavior.pod index e5058de3..b76ae054 100755 --- a/docs/memcached_behavior.pod +++ b/docs/memcached_behavior.pod @@ -73,6 +73,12 @@ Support CAS operations (this is not enabled by default at this point in the serv Modify the timeout value that is used by poll(). The default value is -1. An signed int pointer must be passed to memcached_behavior_set() to change this value. For memcached_behavior_get() a signed int value will be cast and returned as the unsigned long long. +=item MEMCACHED_BUFFERED + +Enabling buffered IO causes commands to "buffer" instead of being sent. Any +action that gets data causes this buffer to be be sent to the remote +connection. Quiting the connection or closing down the connection will also +cause the buffered data to be pushed to the remote connection. =back diff --git a/include/memcached.h b/include/memcached.h index 1cbdcf68..fb836284 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -69,6 +69,7 @@ typedef enum { MEMCACHED_NO_KEY_PROVIDED, MEMCACHED_FETCH_NOTFINISHED, MEMCACHED_TIMEOUT, + MEMCACHED_BUFFERED, MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */ } memcached_return; @@ -88,6 +89,7 @@ typedef enum { MEMCACHED_BEHAVIOR_SUPPORT_CAS, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, MEMCACHED_BEHAVIOR_DISTRIBUTION, + MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, } memcached_behavior; typedef enum { diff --git a/lib/common.h b/lib/common.h index 395b80ef..35775ba8 100644 --- a/lib/common.h +++ b/lib/common.h @@ -60,6 +60,7 @@ typedef enum { MEM_USE_CRC= (1 << 5), MEM_USE_CACHE_LOOKUPS= (1 << 6), MEM_SUPPORT_CAS= (1 << 7), + MEM_BUFFER_REQUESTS= (1 << 8), } memcached_flags; /* Hashing algo */ diff --git a/lib/memcached_behavior.c b/lib/memcached_behavior.c index 853a33b3..c54d93fc 100644 --- a/lib/memcached_behavior.c +++ b/lib/memcached_behavior.c @@ -31,6 +31,8 @@ memcached_return memcached_behavior_set(memcached_st *ptr, break; case MEMCACHED_BEHAVIOR_NO_BLOCK: set_behavior_flag(ptr, MEM_NO_BLOCK, data); + case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: + set_behavior_flag(ptr, MEM_BUFFER_REQUESTS, data); break; case MEMCACHED_BEHAVIOR_TCP_NODELAY: set_behavior_flag(ptr, MEM_TCP_NODELAY, data); @@ -89,6 +91,9 @@ unsigned long long memcached_behavior_get(memcached_st *ptr, case MEMCACHED_BEHAVIOR_NO_BLOCK: temp_flag= MEM_NO_BLOCK; break; + case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: + temp_flag= MEM_BUFFER_REQUESTS; + break; case MEMCACHED_BEHAVIOR_TCP_NODELAY: temp_flag= MEM_TCP_NODELAY; break; diff --git a/lib/memcached_delete.c b/lib/memcached_delete.c index 4fe29421..a7298141 100644 --- a/lib/memcached_delete.c +++ b/lib/memcached_delete.c @@ -42,18 +42,15 @@ memcached_return memcached_delete_by_key(memcached_st *ptr, goto error; } - if ((ptr->flags & MEM_NO_BLOCK)) - to_write= 0; - else - to_write= 1; + to_write= (ptr->flags & MEM_BUFFER_REQUESTS) ? 0 : 1; rc= memcached_do(ptr, server_key, buffer, send_length, to_write); if (rc != MEMCACHED_SUCCESS) goto error; - if ((ptr->flags & MEM_NO_BLOCK)) + if ((ptr->flags & MEM_BUFFER_REQUESTS)) { - rc= MEMCACHED_SUCCESS; + rc= MEMCACHED_BUFFERED; } else { @@ -118,18 +115,5 @@ memcached_return memcached_mdelete_by_key(memcached_st *ptr, (void)memcached_do(ptr, server_key, buffer, send_length, 0); } - for (x= 0; x < ptr->number_of_hosts; x++) - { - if (memcached_server_response_count(ptr, x)) - { - /* We need to do something about non-connnected hosts in the future */ - if ((memcached_io_write(ptr, x, NULL, 0, 1)) == -1) - { - rc= MEMCACHED_SOME_ERRORS; - } - } - } - - LIBMEMCACHED_MEMCACHED_DELETE_END(); - return rc; + return MEMCACHED_BUFFERED; } diff --git a/lib/memcached_storage.c b/lib/memcached_storage.c index 43a96636..38d6d0db 100644 --- a/lib/memcached_storage.c +++ b/lib/memcached_storage.c @@ -96,7 +96,7 @@ static inline memcached_return memcached_send(memcached_st *ptr, goto error; } - if ((ptr->flags & MEM_NO_BLOCK) && verb == SET_OP) + if ((ptr->flags & MEM_BUFFER_REQUESTS) && verb == SET_OP) to_write= 0; else to_write= 1; @@ -108,9 +108,9 @@ static inline memcached_return memcached_send(memcached_st *ptr, } if (to_write == 0) - rc= MEMCACHED_SUCCESS; - else - rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL, server_key); + return MEMCACHED_BUFFERED; + + rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL, server_key); if (rc == MEMCACHED_STORED) return MEMCACHED_SUCCESS; diff --git a/lib/memcached_strerror.c b/lib/memcached_strerror.c index f04f2289..8b8438bb 100644 --- a/lib/memcached_strerror.c +++ b/lib/memcached_strerror.c @@ -64,6 +64,8 @@ char *memcached_strerror(memcached_st *ptr, memcached_return rc) return "FETCH WAS NOT COMPLETED"; case MEMCACHED_NO_KEY_PROVIDED: return "A KEY LENGTH OF ZERO WAS PROVIDED"; + case MEMCACHED_BUFFERED: + return "ACTION QUEUED"; case MEMCACHED_TIMEOUT: return "A TIMEOUT OCCURRED"; case MEMCACHED_MAXIMUM_RETURN: diff --git a/tests/function.c b/tests/function.c index 54bbceaa..46005ce7 100644 --- a/tests/function.c +++ b/tests/function.c @@ -1686,6 +1686,17 @@ uint8_t generate_data(memcached_st *memc) return 0; } +uint8_t generate_buffer_data(memcached_st *memc) +{ + int latch= 0; + + latch= 1; + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, &latch); + generate_data(memc); + + return 0; +} + #ifdef NOT_DONE uint8_t mset_data(memcached_st *memc) { @@ -1809,6 +1820,22 @@ uint8_t delete_generate(memcached_st *memc) return 0; } +uint8_t delete_buffer_generate(memcached_st *memc) +{ + int latch= 0; + unsigned int x; + + latch= 1; + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, &latch); + + for (x= 0; x < GLOBAL_COUNT; x++) + { + (void)memcached_delete(memc, global_keys[x], global_keys_length[x], (time_t)0); + } + + return 0; +} + uint8_t mdelete_generate(memcached_st *memc) { memcached_return rc; @@ -2115,6 +2142,8 @@ test_st generate_tests[] ={ {"generate_data", 0, generate_data }, {"get_read", 0, get_read }, {"delete_generate", 0, delete_generate }, + {"generate_buffer_data", 0, generate_buffer_data }, + {"delete_buffer", 0, delete_buffer_generate}, {"generate_data", 0, generate_data }, {"mget_read", 0, mget_read }, {"mget_read_result", 0, mget_read_result }, -- 2.30.2 From e4dbb63d6df3b1d756c863c502cb4d33cc49cb18 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Sat, 5 Jan 2008 00:54:50 -0800 Subject: [PATCH 03/16] Fix for bad error in execute. Hard flushes in generate tests. --- src/execute.c | 2 +- tests/function.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/execute.c b/src/execute.c index 69b106d2..e623825c 100644 --- a/src/execute.c +++ b/src/execute.c @@ -17,7 +17,7 @@ unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int numbe rc= memcached_set(memc, pairs[x].key, pairs[x].key_length, pairs[x].value, pairs[x].value_length, 0, 0); - if (rc != MEMCACHED_SUCCESS) + if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) fprintf(stderr, "Failured on insert of %.*s\n", (unsigned int)pairs[x].key_length, pairs[x].key); else diff --git a/tests/function.c b/tests/function.c index 46005ce7..62331226 100644 --- a/tests/function.c +++ b/tests/function.c @@ -2139,17 +2139,17 @@ test_st user_tests[] ={ }; test_st generate_tests[] ={ - {"generate_data", 0, generate_data }, + {"generate_data", 1, generate_data }, {"get_read", 0, get_read }, {"delete_generate", 0, delete_generate }, - {"generate_buffer_data", 0, generate_buffer_data }, + {"generate_buffer_data", 1, generate_buffer_data }, {"delete_buffer", 0, delete_buffer_generate}, - {"generate_data", 0, generate_data }, + {"generate_data", 1, 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 }, + {"cleanup", 1, cleanup_pairs }, {0, 0, 0} }; -- 2.30.2 From f250762372cfc46d9d92814f1ea223b36b0b2a40 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Sat, 5 Jan 2008 01:33:01 -0800 Subject: [PATCH 04/16] Test fixes for new return code on buffered calls. I've also added an ASSERT during debug for read() calls of zero. I would like to determine if there is anything broken in the protocol. --- lib/memcached_io.c | 4 +++- tests/function.c | 43 +++++++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/lib/memcached_io.c b/lib/memcached_io.c index 38580638..05974ed5 100644 --- a/lib/memcached_io.c +++ b/lib/memcached_io.c @@ -118,7 +118,9 @@ ssize_t memcached_io_read(memcached_st *ptr, unsigned int server_key, } else if (data_read) break; - /* If zero, just keep looping */ + /* If zero, just keep looping unless testing, then assert() */ + else + WATCHPOINT_ASSERT(0); } ptr->hosts[server_key].read_data_length= data_read; diff --git a/tests/function.c b/tests/function.c index 62331226..5343ab76 100644 --- a/tests/function.c +++ b/tests/function.c @@ -139,7 +139,7 @@ uint8_t set_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); return 0; } @@ -358,7 +358,7 @@ uint8_t add_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); memcached_quit(memc); rc= memcached_add(memc, key, strlen(key), value, strlen(value), @@ -401,10 +401,10 @@ uint8_t delete_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); rc= memcached_delete(memc, key, strlen(key), (time_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); return 0; } @@ -428,7 +428,7 @@ uint8_t get_test(memcached_st *memc) uint32_t flags; rc= memcached_delete(memc, key, strlen(key), (time_t)0); - assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOTFOUND); + assert(rc == MEMCACHED_BUFFERED || rc == MEMCACHED_NOTFOUND); string= memcached_get(memc, key, strlen(key), &string_length, &flags, &rc); @@ -452,7 +452,7 @@ uint8_t get_test2(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); string= memcached_get(memc, key, strlen(key), &string_length, &flags, &rc); @@ -480,7 +480,7 @@ uint8_t set_test2(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, value_length, (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } return 0; @@ -505,7 +505,7 @@ uint8_t set_test3(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, value_length, (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } free(value); @@ -533,7 +533,7 @@ uint8_t get_test3(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, value_length, (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); string= memcached_get(memc, key, strlen(key), &string_length, &flags, &rc); @@ -569,7 +569,7 @@ uint8_t get_test4(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, value_length, (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); for (x= 0; x < 10; x++) { @@ -610,7 +610,7 @@ uint8_t increment_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); rc= memcached_increment(memc, key, strlen(key), 1, &new_number); @@ -635,7 +635,7 @@ uint8_t decrement_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); rc= memcached_decrement(memc, key, strlen(key), 1, &new_number); @@ -659,13 +659,13 @@ uint8_t quit_test(memcached_st *memc) rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)10, (uint32_t)3); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); memcached_quit(memc); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)50, (uint32_t)9); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); return 0; } @@ -705,7 +705,7 @@ uint8_t mget_result_test(memcached_st *memc) rc= memcached_set(memc, keys[x], key_length[x], keys[x], key_length[x], (time_t)50, (uint32_t)9); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } rc= memcached_mget(memc, keys, key_length, 3); @@ -755,7 +755,7 @@ uint8_t mget_result_alloc_test(memcached_st *memc) rc= memcached_set(memc, keys[x], key_length[x], keys[x], key_length[x], (time_t)50, (uint32_t)9); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } rc= memcached_mget(memc, keys, key_length, 3); @@ -803,7 +803,7 @@ uint8_t mget_result_function(memcached_st *memc) rc= memcached_set(memc, keys[x], key_length[x], keys[x], key_length[x], (time_t)50, (uint32_t)9); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } rc= memcached_mget(memc, keys, key_length, 3); @@ -852,7 +852,7 @@ uint8_t mget_test(memcached_st *memc) rc= memcached_set(memc, keys[x], key_length[x], keys[x], key_length[x], (time_t)50, (uint32_t)9); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } rc= memcached_mget(memc, keys, key_length, 3); @@ -1037,10 +1037,10 @@ uint8_t user_supplied_bug1(memcached_st *memc) rc = memcached_set(memc, key, strlen(key), randomstuff, strlen(randomstuff), 10, 0); /* If we fail, lets try again */ - if (rc != MEMCACHED_SUCCESS) + if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) rc = memcached_set(memc, key, strlen(key), randomstuff, strlen(randomstuff), 10, 0); - assert(rc == MEMCACHED_SUCCESS); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); } return 0; @@ -1492,7 +1492,7 @@ uint8_t user_supplied_bug10(memcached_st *memc) { rc= memcached_set(mclone, key, key_len,value, value_length, 0, 0); - assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_WRITE_FAILURE); + assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_WRITE_FAILURE || rc == MEMCACHED_BUFFERED); if (rc == MEMCACHED_WRITE_FAILURE) x--; @@ -1538,7 +1538,6 @@ uint8_t user_supplied_bug11(memcached_st *memc) rc= memcached_set(mclone, key, key_len,value, value_length, 0, 0); WATCHPOINT_IFERROR(rc); - //assert(rc == MEMCACHED_SUCCESS); } free(value); -- 2.30.2 From 4a302893e1e1dbd22355a287b55fafa861963cd2 Mon Sep 17 00:00:00 2001 From: Date: Mon, 7 Jan 2008 11:14:42 -0800 Subject: [PATCH 05/16] Patch by Toru Maesaka for stats comparison --- ChangeLog | 1 + lib/memcached_stats.c | 55 +++++++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6260ba04..75f3362c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * Toru Maesaka patch for stats mismatch * Fix for when CRC return 0 * Fixed uint16_t issues around flags. Turns out the documentation on the protocol was wrong. diff --git a/lib/memcached_stats.c b/lib/memcached_stats.c index a20426a6..7c61890f 100644 --- a/lib/memcached_stats.c +++ b/lib/memcached_stats.c @@ -32,28 +32,33 @@ static char *memcached_stat_keys[] = { static void set_data(memcached_stat_st *stat, char *key, char *value) { - if (!memcmp("pid", key, strlen("pid"))) + + if(strlen(key) < 1) + { + fprintf(stderr, "Invalid key %s\n", key); + } + else if (!strcmp("pid", key)) { stat->pid= strtol(value, (char **)NULL, 10); } - else if (!memcmp("uptime", key, strlen("uptime"))) + else if (!strcmp("uptime", key)) { stat->uptime= strtol(value, (char **)NULL, 10); } - else if (!memcmp("time", key, strlen("time"))) + else if (!strcmp("time", key)) { stat->time= strtol(value, (char **)NULL, 10); } - else if (!memcmp("version", key, strlen("version"))) + else if (!strcmp("version", key)) { memcpy(stat->version, value, strlen(value)); stat->version[strlen(value)]= 0; } - else if (!memcmp("pointer_size", key, strlen("pointer_size"))) + else if (!strcmp("pointer_size", key)) { stat->pointer_size= strtol(value, (char **)NULL, 10); } - else if (!memcmp("rusage_user", key, strlen("rusage_user"))) + else if (!strcmp("rusage_user", key)) { char *walk_ptr; for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++); @@ -62,7 +67,7 @@ static void set_data(memcached_stat_st *stat, char *key, char *value) stat->rusage_user_seconds= strtol(value, (char **)NULL, 10); stat->rusage_user_microseconds= strtol(walk_ptr, (char **)NULL, 10); } - else if (!memcmp("rusage_system", key, strlen("rusage_system"))) + else if (!strcmp("rusage_system", key)) { char *walk_ptr; for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++); @@ -71,63 +76,63 @@ static void set_data(memcached_stat_st *stat, char *key, char *value) stat->rusage_system_seconds= strtol(value, (char **)NULL, 10); stat->rusage_system_microseconds= strtol(walk_ptr, (char **)NULL, 10); } - else if (!memcmp("curr_items", key, strlen("curr_items"))) + else if (!strcmp("curr_items", key)) { stat->curr_items= strtol(value, (char **)NULL, 10); } - else if (!memcmp("total_items", key, strlen("total_items"))) + else if (!strcmp("total_items", key)) { stat->total_items= strtol(value, (char **)NULL, 10); } - else if (!memcmp("bytes", key, strlen("bytes"))) + else if (!strcmp("bytes", key)) { - //stat->bytes= strtoll(value, (char **)NULL, 10); + stat->bytes= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("curr_connections", key, strlen("curr_connections"))) + else if (!strcmp("curr_connections", key)) { - //stat->curr_connections= strtoll(value, (char **)NULL, 10); + stat->curr_connections= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("total_connections", key, strlen("total_connections"))) + else if (!strcmp("total_connections", key)) { - //stat->total_connections= strtoll(value, (char **)NULL, 10); + stat->total_connections= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("connection_structures", key, strlen("connection_structures"))) + else if (!strcmp("connection_structures", key)) { stat->connection_structures= strtol(value, (char **)NULL, 10); } - else if (!memcmp("cmd_get", key, strlen("cmd_get"))) + else if (!strcmp("cmd_get", key)) { stat->cmd_get= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("cmd_set", key, strlen("cmd_set"))) + else if (!strcmp("cmd_set", key)) { stat->cmd_set= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("get_hits", key, strlen("get_hits"))) + else if (!strcmp("get_hits", key)) { stat->get_hits= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("get_misses", key, strlen("get_misses"))) + else if (!strcmp("get_misses", key)) { stat->get_misses= (uint64_t)strtoll(value, (char **)NULL, 10); } - else if (!memcmp("evictions", key, strlen("evictions"))) + else if (!strcmp("evictions", key)) { stat->evictions= (uint64_t)strtoll(value, (char **)NULL, 10); } - else if (!memcmp("bytes_read", key, strlen("bytes_read"))) + else if (!strcmp("bytes_read", key)) { stat->bytes_read= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("bytes_written", key, strlen("bytes_written"))) + else if (!strcmp("bytes_written", key)) { stat->bytes_written= strtoll(value, (char **)NULL, 10); } - else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes"))) + else if (!strcmp("limit_maxbytes", key)) { stat->limit_maxbytes= strtol(value, (char **)NULL, 10); } - else if (!memcmp("threads", key, strlen("threads"))) + else if (!strcmp("threads", key)) { stat->threads= strtol(key, (char **)NULL, 10); } -- 2.30.2 From 434db1f50f8d36ff2d5d52973ccfd963392470f7 Mon Sep 17 00:00:00 2001 From: Date: Tue, 8 Jan 2008 09:48:42 -0800 Subject: [PATCH 06/16] Removing dead code. --- lib/memcached_hosts.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/memcached_hosts.c b/lib/memcached_hosts.c index 6f49b270..88c255a5 100644 --- a/lib/memcached_hosts.c +++ b/lib/memcached_hosts.c @@ -13,9 +13,6 @@ static void rebalance_wheel(memcached_st *ptr) unsigned int x; unsigned int y; unsigned int latch; - unsigned int range; - - range= (MEMCACHED_WHEEL_SIZE / ptr->number_of_hosts); /* Seed the Wheel */ memset(ptr->wheel, 0, sizeof(unsigned int) * MEMCACHED_WHEEL_SIZE); -- 2.30.2 From 7440e41da7475141f68195d678abcabd8fc3db23 Mon Sep 17 00:00:00 2001 From: Date: Tue, 8 Jan 2008 11:12:56 -0800 Subject: [PATCH 07/16] Removing all of the multi-set bits (aka the buffer code is faster, so why bother). --- lib/Makefile.am | 1 - lib/memcached_delete.c | 54 ------ lib/memcached_multistorage.c | 328 ----------------------------------- tests/function.c | 14 +- 4 files changed, 1 insertion(+), 396 deletions(-) delete mode 100644 lib/memcached_multistorage.c diff --git a/lib/Makefile.am b/lib/Makefile.am index 38c6e8f4..d63ef583 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,7 +41,6 @@ libmemcached_la_SOURCES = crc.c \ memcached_hosts.c \ memcached_io.c \ md5.c \ - memcached_multistorage.c \ memcached_quit.c \ memcached_parse.c \ memcached_response.c \ diff --git a/lib/memcached_delete.c b/lib/memcached_delete.c index a7298141..f0ff9ba6 100644 --- a/lib/memcached_delete.c +++ b/lib/memcached_delete.c @@ -63,57 +63,3 @@ error: LIBMEMCACHED_MEMCACHED_DELETE_END(); return rc; } - -memcached_return memcached_mdelete(memcached_st *ptr, - char **key, size_t *key_length, - unsigned int number_of_keys, - time_t expiration) -{ - return memcached_mdelete_by_key(ptr, NULL, 0, - key, key_length, - number_of_keys, expiration); - -} - -memcached_return memcached_mdelete_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - unsigned int number_of_keys, - time_t expiration) -{ - size_t send_length; - memcached_return rc= MEMCACHED_SUCCESS; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - unsigned int master_server_key= 0; - unsigned int x; - - LIBMEMCACHED_MEMCACHED_DELETE_START(); - - if (ptr->hosts == NULL || ptr->number_of_hosts == 0) - return MEMCACHED_NO_SERVERS; - - if (master_key && master_key_length) - master_server_key= memcached_generate_hash(ptr, master_key, master_key_length); - - for (x= 0; x < number_of_keys; x++) - { - unsigned int server_key; - - if (master_key && master_key_length) - server_key= master_server_key; - else - server_key= memcached_generate_hash(ptr, key[x], key_length[x]); - - if (expiration) - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "delete %.*s %llu\r\n", (int)(key_length[x]), key[x], - (unsigned long long)expiration); - else - send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "delete %.*s\r\n", (int)(key_length[x]), key[x]); - - (void)memcached_do(ptr, server_key, buffer, send_length, 0); - } - - return MEMCACHED_BUFFERED; -} diff --git a/lib/memcached_multistorage.c b/lib/memcached_multistorage.c deleted file mode 100644 index da093c9d..00000000 --- a/lib/memcached_multistorage.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - Memcached library - - memcached_set() - memcached_replace() - memcached_add() - -*/ - -#include "common.h" -#include "memcached_io.h" - -typedef enum { - SET_OP, - REPLACE_OP, - ADD_OP, - PREPEND_OP, - APPEND_OP, - CAS_OP, -} memcached_storage_action; - -/* Inline this */ -static char *storage_op_string(memcached_storage_action verb) -{ - switch (verb) - { - case SET_OP: - return "set"; - case REPLACE_OP: - return "replace"; - case ADD_OP: - return "add"; - case PREPEND_OP: - return "prepend"; - case APPEND_OP: - return "append"; - case CAS_OP: - return "cas"; - }; - - return SET_OP; -} - -static memcached_return memcached_msend(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags, - uint64_t cas, - memcached_storage_action verb) -{ - size_t write_length; - ssize_t sent_length; - char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; - unsigned int x; - unsigned int master_server_key= 0; - memcached_return rc= MEMCACHED_SUCCESS; - - WATCHPOINT_ASSERT(key && key_length && value && value_length); - - if (key_length == 0) - return MEMCACHED_NO_KEY_PROVIDED; - - if (ptr->number_of_hosts == 0) - return MEMCACHED_NO_SERVERS; - - if (master_key && master_key_length) - master_server_key= memcached_generate_hash(ptr, master_key, master_key_length); - - for (x= 0; x < number_of_keys; x++) - { - unsigned int server_key; - memcached_return tried; - - if (master_server_key) - server_key= master_server_key; - else - server_key= memcached_generate_hash(ptr, key[x], key_length[x]); - - - if (cas) - write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "%s %.*s %u %llu %zu %llu\r\n", storage_op_string(verb), - (int)key_length[x], key[x], flags, - (unsigned long long)expiration, value_length[x], - (unsigned long long)cas); - else - write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, - "%s %.*s %u %llu %zu\r\n", storage_op_string(verb), - (int)key_length[x], key[x], flags, - (unsigned long long)expiration, value_length[x]); - - if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE) - goto error; - - tried= memcached_do(ptr, server_key, buffer, write_length, 0); - if (tried != MEMCACHED_SUCCESS) - goto error; - - if ((sent_length= memcached_io_write(ptr, server_key, value[x], value_length[x], 0)) == -1) - goto error; - - if ((sent_length= memcached_io_write(ptr, server_key, "\r\n", 2, 0)) == -1) - goto error; - - continue; - -error: - memcached_quit_server(ptr, server_key, 1); - continue; - } - - for (x= 0; x < ptr->number_of_hosts; x++) - { - if (memcached_server_response_count(ptr, x)) - { - /* We need to do something about non-connnected hosts in the future */ - if ((memcached_io_write(ptr, x, NULL, 0, 1)) == -1) - { - rc= MEMCACHED_SOME_ERRORS; - } - } - } - - return rc; -} - -memcached_return memcached_mset(memcached_st *ptr, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - LIBMEMCACHED_MEMCACHED_SET_START(); - rc= memcached_msend(ptr, NULL, 0, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, SET_OP); - LIBMEMCACHED_MEMCACHED_SET_END(); - return rc; -} - -memcached_return memcached_madd(memcached_st *ptr, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - LIBMEMCACHED_MEMCACHED_ADD_START(); - rc= memcached_msend(ptr, NULL, 0, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, ADD_OP); - LIBMEMCACHED_MEMCACHED_ADD_END(); - return rc; -} - -memcached_return memcached_mreplace(memcached_st *ptr, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - LIBMEMCACHED_MEMCACHED_REPLACE_START(); - rc= memcached_msend(ptr, NULL, 0, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, REPLACE_OP); - LIBMEMCACHED_MEMCACHED_REPLACE_END(); - return rc; -} - -memcached_return memcached_mprepend(memcached_st *ptr, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - rc= memcached_msend(ptr, NULL, 0, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, PREPEND_OP); - return rc; -} - -memcached_return memcached_mappend(memcached_st *ptr, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - rc= memcached_msend(ptr, NULL, 0, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, APPEND_OP); - return rc; -} - -memcached_return memcached_mcas(memcached_st *ptr, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags, - uint64_t cas) -{ - memcached_return rc; - rc= memcached_msend(ptr, NULL, 0, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, cas, APPEND_OP); - return rc; -} - -memcached_return memcached_mset_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - LIBMEMCACHED_MEMCACHED_SET_START(); - rc= memcached_msend(ptr, master_key, master_key_length, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, SET_OP); - LIBMEMCACHED_MEMCACHED_SET_END(); - return rc; -} - -memcached_return memcached_madd_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - LIBMEMCACHED_MEMCACHED_ADD_START(); - rc= memcached_msend(ptr, master_key, master_key_length, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, ADD_OP); - LIBMEMCACHED_MEMCACHED_ADD_END(); - return rc; -} - -memcached_return memcached_mreplace_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - LIBMEMCACHED_MEMCACHED_REPLACE_START(); - rc= memcached_msend(ptr, master_key, master_key_length, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, REPLACE_OP); - LIBMEMCACHED_MEMCACHED_REPLACE_END(); - return rc; -} - -memcached_return memcached_mprepend_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - rc= memcached_msend(ptr, master_key, master_key_length, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, PREPEND_OP); - return rc; -} - -memcached_return memcached_mappend_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags) -{ - memcached_return rc; - rc= memcached_msend(ptr, master_key, master_key_length, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, 0, APPEND_OP); - return rc; -} - -memcached_return memcached_mcas_by_key(memcached_st *ptr, - char *master_key, size_t master_key_length, - char **key, size_t *key_length, - char **value, size_t *value_length, - unsigned int number_of_keys, - time_t expiration, - uint32_t flags, - uint64_t cas) -{ - memcached_return rc; - rc= memcached_msend(ptr, master_key, master_key_length, - key, key_length, value, value_length, - number_of_keys, - expiration, flags, cas, APPEND_OP); - return rc; -} diff --git a/tests/function.c b/tests/function.c index 5343ab76..0ecd7b14 100644 --- a/tests/function.c +++ b/tests/function.c @@ -29,8 +29,6 @@ static pairs_st *global_pairs; static char *global_keys[GLOBAL_COUNT]; static size_t global_keys_length[GLOBAL_COUNT]; -static char *global_values[GLOBAL_COUNT]; -static size_t global_values_length[GLOBAL_COUNT]; uint8_t init_test(memcached_st *not_used) { @@ -363,6 +361,7 @@ uint8_t add_test(memcached_st *memc) rc= memcached_add(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); + WATCHPOINT_ERROR(rc); assert(rc == MEMCACHED_NOTSTORED); return 0; @@ -1835,16 +1834,6 @@ uint8_t delete_buffer_generate(memcached_st *memc) return 0; } -uint8_t mdelete_generate(memcached_st *memc) -{ - memcached_return rc; - - rc= memcached_mdelete(memc, global_keys, global_keys_length, GLOBAL_COUNT, 0); - - return 0; -} - - uint8_t free_data(memcached_st *memc) { pairs_free(global_pairs); @@ -2147,7 +2136,6 @@ test_st generate_tests[] ={ {"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", 1, cleanup_pairs }, {0, 0, 0} }; -- 2.30.2 From 9caad97a2b8b11488b2ba3583922864ac3ccbb09 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Tue, 8 Jan 2008 12:00:21 -0800 Subject: [PATCH 08/16] Kevin Dalley's patch for EOF --- lib/memcached_io.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/memcached_io.c b/lib/memcached_io.c index 05974ed5..299d4390 100644 --- a/lib/memcached_io.c +++ b/lib/memcached_io.c @@ -83,6 +83,7 @@ ssize_t memcached_io_read(memcached_st *ptr, unsigned int server_key, while (length) { + uint8_t found_eof= 0; if (!ptr->hosts[server_key].read_buffer_length) { size_t data_read; @@ -120,7 +121,11 @@ ssize_t memcached_io_read(memcached_st *ptr, unsigned int server_key, break; /* If zero, just keep looping unless testing, then assert() */ else + { WATCHPOINT_ASSERT(0); + found_eof= 1; + break; + } } ptr->hosts[server_key].read_data_length= data_read; @@ -148,6 +153,9 @@ ssize_t memcached_io_read(memcached_st *ptr, unsigned int server_key, ptr->hosts[server_key].read_buffer_length--; buffer_ptr++; } + + if (found_eof) + break; } return (size_t)(buffer_ptr - buffer); -- 2.30.2 From 85a43151d5f1cd4548e4ceda5230a2171e06a2c2 Mon Sep 17 00:00:00 2001 From: Date: Tue, 8 Jan 2008 23:08:48 -0800 Subject: [PATCH 09/16] Incorrect polltimeout set on test (Patch by Kevin) --- tests/function.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/function.c b/tests/function.c index 0ecd7b14..db224f95 100644 --- a/tests/function.c +++ b/tests/function.c @@ -1480,7 +1480,7 @@ uint8_t user_supplied_bug10(memcached_st *memc) memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_NO_BLOCK, &set); memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_TCP_NODELAY, &set); timeout= 2; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, &timeout); + memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, &timeout); value = (char*)malloc(value_length * sizeof(char)); @@ -1521,7 +1521,7 @@ uint8_t user_supplied_bug11(memcached_st *memc) memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_NO_BLOCK, &set); memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_TCP_NODELAY, &set); timeout= -1; - memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, &timeout); + memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, &timeout); timeout= (int32_t)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT); -- 2.30.2 From 09ee2606fece278264ef65660e12c606f5936347 Mon Sep 17 00:00:00 2001 From: Date: Wed, 9 Jan 2008 08:08:44 -0800 Subject: [PATCH 10/16] Patch by Marc Rossi to add --hash to command line tools. Fixed bug in freeing of memory on exit (it could be causing crashes on end of program). --- ChangeLog | 1 + src/client_options.h | 1 + src/memcat.c | 13 +++++++++++-- src/memcp.c | 10 +++++++++- src/memrm.c | 11 ++++++++++- src/utilities.c | 39 ++++++++++++++++++++++++++++++++++++++- src/utilities.h | 1 + 7 files changed, 71 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75f3362c..2de07f39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * Patch from Marc Rossi to add --hash option for memcp, memrm, and memcat. * Toru Maesaka patch for stats mismatch * Fix for when CRC return 0 * Fixed uint16_t issues around flags. Turns out the documentation on the diff --git a/src/client_options.h b/src/client_options.h index 9242884e..b7ba5a96 100644 --- a/src/client_options.h +++ b/src/client_options.h @@ -21,6 +21,7 @@ typedef enum { OPT_SLAP_NON_BLOCK, OPT_SLAP_TCP_NODELAY, OPT_FLUSH, + OPT_HASH, } memcached_options; #endif /* CLIENT_OPTIONS */ diff --git a/src/memcat.c b/src/memcat.c index 4aaffb95..2db0c8ee 100644 --- a/src/memcat.c +++ b/src/memcat.c @@ -16,7 +16,8 @@ void options_parse(int argc, char *argv[]); static int opt_verbose= 0; static int opt_displayflag= 0; -static char *opt_servers; +static char *opt_servers= NULL; +static char *opt_hash= NULL; int main(int argc, char *argv[]) { @@ -40,6 +41,7 @@ int main(int argc, char *argv[]) } memc= memcached_create(NULL); + process_hash_option(memc, opt_hash); servers= memcached_servers_parse(opt_servers); @@ -80,7 +82,10 @@ int main(int argc, char *argv[]) memcached_free(memc); - free(opt_servers); + if (opt_servers) + free(opt_servers); + if (opt_hash) + free(opt_hash); return 0; } @@ -104,6 +109,7 @@ void options_parse(int argc, char *argv[]) {"debug", no_argument, &opt_verbose, OPT_DEBUG}, {"servers", required_argument, NULL, OPT_SERVERS}, {"flag", no_argument, &opt_displayflag, OPT_FLAG}, + {"hash", required_argument, NULL, OPT_HASH}, {0, 0, 0, 0}, }; @@ -130,6 +136,9 @@ void options_parse(int argc, char *argv[]) case OPT_SERVERS: /* --servers or -s */ opt_servers= strdup(optarg); break; + case OPT_HASH: + opt_hash= strdup(optarg); + break; case '?': /* getopt_long already printed an error message. */ exit(1); diff --git a/src/memcp.c b/src/memcp.c index f1054ea9..57d0a70d 100644 --- a/src/memcp.c +++ b/src/memcp.c @@ -24,6 +24,7 @@ void options_parse(int argc, char *argv[]); static int opt_verbose= 0; static char *opt_servers= NULL; +static char *opt_hash= NULL; static int opt_method= OPT_SET; static uint32_t opt_flags= 0; static time_t opt_expires= 0; @@ -37,6 +38,7 @@ int main(int argc, char *argv[]) options_parse(argc, argv); memc= memcached_create(NULL); + process_hash_option(memc, opt_hash); if (!opt_servers) { @@ -131,7 +133,10 @@ int main(int argc, char *argv[]) memcached_free(memc); - free(opt_servers); + if (opt_servers) + free(opt_servers); + if (opt_hash) + free(opt_hash); return 0; } @@ -158,6 +163,7 @@ void options_parse(int argc, char *argv[]) {"set", no_argument, NULL, OPT_SET}, {"add", no_argument, NULL, OPT_ADD}, {"replace", no_argument, NULL, OPT_REPLACE}, + {"hash", required_argument, NULL, OPT_HASH}, {0, 0, 0, 0}, }; @@ -200,6 +206,8 @@ void options_parse(int argc, char *argv[]) break; case OPT_ADD: opt_method= OPT_ADD; + case OPT_HASH: + opt_hash= strdup(optarg); break; case '?': /* getopt_long already printed an error message. */ diff --git a/src/memrm.c b/src/memrm.c index 09f58ea4..2a79933a 100644 --- a/src/memrm.c +++ b/src/memrm.c @@ -9,6 +9,7 @@ static int opt_verbose= 0; static time_t opt_expire= 0; static char *opt_servers= NULL; +static char *opt_hash= NULL; #define PROGRAM_NAME "memrm" #define PROGRAM_DESCRIPTION "Erase a key or set of keys from a memcached cluster." @@ -35,6 +36,7 @@ int main(int argc, char *argv[]) } memc= memcached_create(NULL); + process_hash_option(memc, opt_hash); servers= memcached_servers_parse(opt_servers); memcached_server_push(memc, servers); @@ -60,7 +62,10 @@ int main(int argc, char *argv[]) memcached_free(memc); - free(opt_servers); + if (opt_servers) + free(opt_servers); + if (opt_hash) + free(opt_hash); return 0; } @@ -81,6 +86,7 @@ void options_parse(int argc, char *argv[]) {"debug", no_argument, &opt_verbose, OPT_DEBUG}, {"servers", required_argument, NULL, OPT_SERVERS}, {"expire", required_argument, NULL, OPT_EXPIRE}, + {"hash", required_argument, NULL, OPT_HASH}, {0, 0, 0, 0}, }; int option_index= 0; @@ -112,6 +118,9 @@ void options_parse(int argc, char *argv[]) case OPT_EXPIRE: /* --expire */ opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10); break; + case OPT_HASH: + opt_hash= strdup(optarg); + break; case '?': /* getopt_long already printed an error message. */ exit(1); diff --git a/src/utilities.c b/src/utilities.c index 1dfd60b2..2094d218 100644 --- a/src/utilities.c +++ b/src/utilities.c @@ -42,9 +42,11 @@ char *lookup_help(memcached_options option) case OPT_SLAP_NON_BLOCK: return("Set TCP up to use non-blocking IO."); case OPT_SLAP_TCP_NODELAY: return("Set TCP socket up to use nodelay."); case OPT_FLUSH: return("Flush servers before running tests."); + case OPT_HASH: return("Select hash type."); }; - return "forgot to document this one :)"; + WATCHPOINT_ASSERT(0); + return "forgot to document this function :)"; } void help_command(char *command_name, char *description, @@ -70,3 +72,38 @@ void help_command(char *command_name, char *description, printf("\n"); exit(0); } + +void process_hash_option(memcached_st *memc, char *opt_hash) +{ + unsigned int set; + memcached_return rc; + + if (opt_hash == NULL) + return; + + if (!strcasecmp(opt_hash, "CRC")) + set= MEMCACHED_HASH_CRC; + else if (!strcasecmp(opt_hash, "FNV1_64")) + set= MEMCACHED_HASH_FNV1_64; + else if (!strcasecmp(opt_hash, "FNV1A_64")) + set= MEMCACHED_HASH_FNV1A_64; + else if (!strcasecmp(opt_hash, "FNV1_32")) + set= MEMCACHED_HASH_FNV1_32; + else if (!strcasecmp(opt_hash, "FNV1A_32")) + set= MEMCACHED_HASH_FNV1A_32; + else if (!strcasecmp(opt_hash, "KETAMA")) + set= MEMCACHED_HASH_KETAMA; + else + { + fprintf(stderr, "hash: type not recognized %s\n", opt_hash); + exit(1); + } + + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, &set); + if (rc != MEMCACHED_SUCCESS) + { + fprintf(stderr, "hash: memcache error %s\n", memcached_strerror(memc, rc)); + exit(1); + } +} + diff --git a/src/utilities.h b/src/utilities.h index 1fba99bf..cdec1ae6 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -28,3 +28,4 @@ void version_command(char *command_name); void help_command(char *command_name, char *description, const struct option *long_options, memcached_programs_help_st *options); +void process_hash_option(memcached_st *memc, char *opt_hash); -- 2.30.2 From f7cf48062dc8410ebeabf0a575eeb8e1b5201a6b Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 9 Jan 2008 10:10:34 -0800 Subject: [PATCH 11/16] Documentation and Changlog information. --- ChangeLog | 1 + docs/memcached_get.pod | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 75f3362c..a17e370a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * Kevin's patch for fixing EOF issues during a read. * Toru Maesaka patch for stats mismatch * Fix for when CRC return 0 * Fixed uint16_t issues around flags. Turns out the documentation on the diff --git a/docs/memcached_get.pod b/docs/memcached_get.pod index f2f2033c..f87d47ba 100755 --- a/docs/memcached_get.pod +++ b/docs/memcached_get.pod @@ -92,7 +92,9 @@ 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. +you supply the calling function. Currently only one value is being passed +to each function call. In the future there will be an option to allow this +to be an array. 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 -- 2.30.2 From da9995411e75f3a984672e926fd5bca406b13562 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 9 Jan 2008 12:21:22 -0800 Subject: [PATCH 12/16] More timeout cleanup --- lib/memcached_behavior.c | 2 +- src/utilities.h | 1 + tests/function.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/memcached_behavior.c b/lib/memcached_behavior.c index c54d93fc..31d8f052 100644 --- a/lib/memcached_behavior.c +++ b/lib/memcached_behavior.c @@ -51,7 +51,7 @@ memcached_return memcached_behavior_set(memcached_st *ptr, break; case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: { - unsigned int timeout= (*((unsigned int *)data)); + int32_t timeout= (*((int32_t *)data)); ptr->poll_timeout= timeout; break; diff --git a/src/utilities.h b/src/utilities.h index cdec1ae6..6d4d72d4 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -1,5 +1,6 @@ #include #include +#include #include "client_options.h" #include "libmemcached_config.h" diff --git a/tests/function.c b/tests/function.c index db224f95..5ba9f1f4 100644 --- a/tests/function.c +++ b/tests/function.c @@ -1523,7 +1523,7 @@ uint8_t user_supplied_bug11(memcached_st *memc) timeout= -1; memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, &timeout); - timeout= (int32_t)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT); + timeout= (int32_t)memcached_behavior_get(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT); assert(timeout == -1); -- 2.30.2 From e66e77d11b06d6076b986db0709124bc03bfc6c4 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 9 Jan 2008 13:51:14 -0800 Subject: [PATCH 13/16] Test Cleanup. --- tests/function.c | 3 --- tests/output.res | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/function.c b/tests/function.c index 5ba9f1f4..f52bf783 100644 --- a/tests/function.c +++ b/tests/function.c @@ -361,7 +361,6 @@ uint8_t add_test(memcached_st *memc) rc= memcached_add(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); - WATCHPOINT_ERROR(rc); assert(rc == MEMCACHED_NOTSTORED); return 0; @@ -1535,8 +1534,6 @@ uint8_t user_supplied_bug11(memcached_st *memc) for (x= 1; x <= 100000; ++x) { rc= memcached_set(mclone, key, key_len,value, value_length, 0, 0); - - WATCHPOINT_IFERROR(rc); } free(value); diff --git a/tests/output.res b/tests/output.res index 7da758fb..15d5c06f 100644 --- a/tests/output.res +++ b/tests/output.res @@ -36,6 +36,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -111,6 +112,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -186,6 +188,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -261,6 +264,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -336,6 +340,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -411,6 +416,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -486,6 +492,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -561,6 +568,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -636,6 +644,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -711,6 +720,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -786,6 +796,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -861,6 +872,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -936,6 +948,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -1011,6 +1024,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time @@ -1086,6 +1100,7 @@ Error 27 -> ACTION NOT SUPPORTED Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED Error 29 -> FETCH WAS NOT COMPLETED Error 30 -> A TIMEOUT OCCURRED +Error 31 -> ACTION QUEUED Found key pid Found key uptime Found key time -- 2.30.2 From 51ccc3f82cc9bab7cf05e3b07b8a8b319349bde0 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 9 Jan 2008 16:39:38 -0800 Subject: [PATCH 14/16] Fix for connect() to invalidate socket on failure. --- ChangeLog | 1 + configure.ac | 2 +- lib/memcached_connect.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81ab5c1d..ed7a8148 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ 0.13 + * Fix for failure to connect to invalidate socket. * Patch from Marc Rossi to add --hash option for memcp, memrm, and memcat. * Kevin's patch for fixing EOF issues during a read. * Toru Maesaka patch for stats mismatch diff --git a/configure.ac b/configure.ac index 0cf13db9..01c1312b 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ MEMCACHED_API_VERSION=1.0 AC_SUBST(MEMCACHED_API_VERSION) #shared library versioning -MEMCACHED_LIBRARY_VERSION=2:2:1 +MEMCACHED_LIBRARY_VERSION=2:0:0 # | | | # +------+ | +---+ # | | | diff --git a/lib/memcached_connect.c b/lib/memcached_connect.c index 42390a9a..278f9da3 100644 --- a/lib/memcached_connect.c +++ b/lib/memcached_connect.c @@ -10,7 +10,6 @@ static memcached_return set_hostinfo(memcached_server_st *server) sprintf(str_port, "%u", server->port); memset(&hints, 0, sizeof(hints)); - hints.ai_family= AF_INET; hints.ai_socktype= SOCK_STREAM; hints.ai_protocol= 0; @@ -219,6 +218,8 @@ test_connect: default: ptr->cached_errno= errno; WATCHPOINT_ERRNO(ptr->cached_errno); + close(ptr->hosts[server_key].fd); + ptr->hosts[server_key].fd= -1; return MEMCACHED_ERRNO; } ptr->connected++; -- 2.30.2 From b1daf61bf1665041f30fff7c96d61de4658f8db3 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Fri, 11 Jan 2008 13:43:36 -0800 Subject: [PATCH 15/16] MEMCACHED_BEHAVIOR_USER_DATA work. This allows a client application to store a pointer set of data into the library. --- ChangeLog | 1 + docs/memcached_behavior.pod | 8 +++++++- include/memcached.h | 2 ++ lib/memcached.c | 1 + lib/memcached_behavior.c | 5 +++++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ed7a8148..46f277c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,5 @@ 0.13 + * MEMCACHED_BEHAVIOR_USER_DATA added to store user pointer. * Fix for failure to connect to invalidate socket. * Patch from Marc Rossi to add --hash option for memcp, memrm, and memcat. * Kevin's patch for fixing EOF issues during a read. diff --git a/docs/memcached_behavior.pod b/docs/memcached_behavior.pod index b76ae054..bd8c85a7 100755 --- a/docs/memcached_behavior.pod +++ b/docs/memcached_behavior.pod @@ -73,7 +73,13 @@ Support CAS operations (this is not enabled by default at this point in the serv Modify the timeout value that is used by poll(). The default value is -1. An signed int pointer must be passed to memcached_behavior_set() to change this value. For memcached_behavior_get() a signed int value will be cast and returned as the unsigned long long. -=item MEMCACHED_BUFFERED +=item MEMCACHED_BEHAVIOR_USER_DATA + +This allows you to store a pointer to a specifc piece of data. This can be +retrieved from inside of memcached_fetch_exectue(). Cloning a memcached_st +will copy the pointer to the clone. + +=item MEMCACHED_BEHAVIOR_BUFFER_REQUESTS Enabling buffered IO causes commands to "buffer" instead of being sent. Any action that gets data causes this buffer to be be sent to the remote diff --git a/include/memcached.h b/include/memcached.h index fb836284..d73a16be 100644 --- a/include/memcached.h +++ b/include/memcached.h @@ -90,6 +90,7 @@ typedef enum { MEMCACHED_BEHAVIOR_POLL_TIMEOUT, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, + MEMCACHED_BEHAVIOR_USER_DATA, } memcached_behavior; typedef enum { @@ -199,6 +200,7 @@ struct memcached_st { memcached_result_st result; memcached_hash hash; memcached_server_distribution distribution; + void *user_data; unsigned int wheel[MEMCACHED_WHEEL_SIZE]; #ifdef NOT_USED /* Future Use */ uint8_t replicas; diff --git a/lib/memcached.c b/lib/memcached.c index 24c3b8bc..25a287ad 100644 --- a/lib/memcached.c +++ b/lib/memcached.c @@ -82,6 +82,7 @@ memcached_st *memcached_clone(memcached_st *clone, memcached_st *ptr) new_clone->poll_timeout= ptr->poll_timeout; new_clone->distribution= ptr->distribution; new_clone->hash= ptr->hash; + new_clone->user_data= ptr->user_data; return new_clone; } diff --git a/lib/memcached_behavior.c b/lib/memcached_behavior.c index 31d8f052..55b9da67 100644 --- a/lib/memcached_behavior.c +++ b/lib/memcached_behavior.c @@ -49,6 +49,9 @@ memcached_return memcached_behavior_set(memcached_st *ptr, case MEMCACHED_BEHAVIOR_KETAMA: set_behavior_flag(ptr, MEM_USE_KETAMA, data); break; + case MEMCACHED_BEHAVIOR_USER_DATA: + ptr->user_data= data; + break; case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: { int32_t timeout= (*((int32_t *)data)); @@ -104,6 +107,8 @@ unsigned long long memcached_behavior_get(memcached_st *ptr, case MEMCACHED_BEHAVIOR_KETAMA: temp_flag= MEM_USE_KETAMA; break; + case MEMCACHED_BEHAVIOR_USER_DATA: + return (unsigned long long)ptr->user_data; case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: { return (unsigned long long)ptr->poll_timeout; -- 2.30.2 From 0656f7d7ed52b56cd62af7086352a71ca0877cf7 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Sun, 13 Jan 2008 06:52:08 -0800 Subject: [PATCH 16/16] Adding date for release --- ChangeLog | 2 +- support/libmemcached.spec.in | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 46f277c5..d8c98d1f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -0.13 +0.13 Sun Jan 13 06:51:50 PST 2008 * MEMCACHED_BEHAVIOR_USER_DATA added to store user pointer. * Fix for failure to connect to invalidate socket. * Patch from Marc Rossi to add --hash option for memcp, memrm, and memcat. diff --git a/support/libmemcached.spec.in b/support/libmemcached.spec.in index 1d72454c..8e71d7da 100644 --- a/support/libmemcached.spec.in +++ b/support/libmemcached.spec.in @@ -54,8 +54,8 @@ memerror - Creates human readable messages from libmemecached error codes. %{_libdir}/libmemcached.a %{_libdir}/libmemcached.la %{_libdir}/libmemcached.so -%{_libdir}/libmemcached.so.1 -%{_libdir}/libmemcached.so.1.1.2 +%{_libdir}/libmemcached.so.2 +%{_libdir}/libmemcached.so.2.0.0 %{_libdir}/pkgconfig/libmemcached.pc %{_mandir}/man1/memcat.1.gz %{_mandir}/man1/memcp.1.gz -- 2.30.2