From: Trond Norbye Date: Tue, 20 Jan 2009 11:34:40 +0000 (+0100) Subject: Implement memcached_behavior_noreply X-Git-Tag: 0.26~17 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=b0e52309fcc12077506ff7d0d7d55311d64a073e;p=m6w6%2Flibmemcached Implement memcached_behavior_noreply --- diff --git a/docs/memcached_behavior.pod b/docs/memcached_behavior.pod index 2dc214ae..f4246556 100755 --- a/docs/memcached_behavior.pod +++ b/docs/memcached_behavior.pod @@ -159,6 +159,13 @@ at least 10 IO requests sent without reading the input buffer). Setting this value to high, may cause libmemcached to deadlock (trying to send data, but the send will block because the input buffer in the kernel is full). +=item MEMCACHED_BEHAVIOR_NOREPLY + +Set this value to specify that you really don't care about the result +from your storage commands (set, add, replace, append, prepend). With +this flag enabled, each storage request will be sent immediately to the +server overriding any setting of MEMCACHED_BEHAVIOR_BUFFER_REQUESTS. + =back =head1 RETURN diff --git a/libmemcached/common.h b/libmemcached/common.h index 760fb042..40787d38 100644 --- a/libmemcached/common.h +++ b/libmemcached/common.h @@ -75,7 +75,8 @@ typedef enum { /* 11 used for weighted ketama */ MEM_KETAMA_WEIGHTED= (1 << 11), MEM_BINARY_PROTOCOL= (1 << 12), - MEM_HASH_WITH_PREFIX_KEY= (1 << 13) + MEM_HASH_WITH_PREFIX_KEY= (1 << 13), + MEM_NOREPLY= (1 << 14) } memcached_flags; /* Hashing algo */ diff --git a/libmemcached/memcached_behavior.c b/libmemcached/memcached_behavior.c index fc785e25..3eca4eac 100644 --- a/libmemcached/memcached_behavior.c +++ b/libmemcached/memcached_behavior.c @@ -136,6 +136,9 @@ memcached_return memcached_behavior_set(memcached_st *ptr, case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: set_behavior_flag(ptr, MEM_HASH_WITH_PREFIX_KEY, data); break; + case MEMCACHED_BEHAVIOR_NOREPLY: + set_behavior_flag(ptr, MEM_NOREPLY, data); + break; } return MEMCACHED_SUCCESS; @@ -244,6 +247,9 @@ uint64_t memcached_behavior_get(memcached_st *ptr, case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: temp_flag= MEM_HASH_WITH_PREFIX_KEY; break; + case MEMCACHED_BEHAVIOR_NOREPLY: + temp_flag= MEM_NOREPLY; + break; } WATCHPOINT_ASSERT(temp_flag); /* Programming mistake if it gets this far */ diff --git a/libmemcached/memcached_constants.h b/libmemcached/memcached_constants.h index 7f5bbdab..fc47a3b6 100644 --- a/libmemcached/memcached_constants.h +++ b/libmemcached/memcached_constants.h @@ -96,7 +96,8 @@ typedef enum { MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK, MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK, - MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY + MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY, + MEMCACHED_BEHAVIOR_NOREPLY } memcached_behavior; typedef enum { diff --git a/libmemcached/memcached_storage.c b/libmemcached/memcached_storage.c index 1ac70d14..0f817c47 100644 --- a/libmemcached/memcached_storage.c +++ b/libmemcached/memcached_storage.c @@ -124,6 +124,19 @@ static inline memcached_return memcached_send(memcached_st *ptr, else to_write= 1; + if (ptr->flags & MEM_NOREPLY) + { + if (memcached_io_write(&ptr->hosts[server_key], " noreply\r\n", + 10, 1) == -1) + { + rc= MEMCACHED_WRITE_FAILURE; + goto error; + } + + memcached_server_response_decrement(&ptr->hosts[server_key]); + return MEMCACHED_SUCCESS; + } + if ((sent_length= memcached_io_write(&ptr->hosts[server_key], "\r\n", 2, to_write)) == -1) { rc= MEMCACHED_WRITE_FAILURE; @@ -378,6 +391,18 @@ static memcached_return memcached_send_binary(memcached_server_st* server, request.message.header.request.cas= htonll(cas); flush= ((server->root->flags & MEM_BUFFER_REQUESTS) && verb == SET_OP) ? 0 : 1; + + /* The binary protocol does not implement NOREPLY right now, so I need to + * parse the return message from the server. The problem we tried to solve + * is the fact that the async mode will buffer commands, and if we issue a + * lot of sets followed by a get we have to flush the send buffer before we + * can send the get command (and all those commands have to be executed). + * The workaround for the binary is that we send the command, but we await + * parsing of the result message until we really need to do it.. + */ + if (server->root->flags & MEM_NOREPLY) + flush=1; + /* write the header */ if ((memcached_do(server, (const char*)request.bytes, send_length, 0) != MEMCACHED_SUCCESS) || (memcached_io_write(server, key, key_length, 0) == -1) || @@ -387,9 +412,9 @@ static memcached_return memcached_send_binary(memcached_server_st* server, return MEMCACHED_WRITE_FAILURE; } - if (flush == 0) + if (flush == 0 || server->root->flags & MEM_NOREPLY) return MEMCACHED_BUFFERED; - + return memcached_response(server, NULL, 0, NULL); } diff --git a/tests/function.c b/tests/function.c index 4bc0be4e..e72dc7ee 100644 --- a/tests/function.c +++ b/tests/function.c @@ -3031,6 +3031,44 @@ static memcached_return poll_timeout(memcached_st *memc) return MEMCACHED_SUCCESS; } +static memcached_return noreply_test(memcached_st *memc) +{ + memcached_return ret; + ret= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1); + assert(ret == MEMCACHED_SUCCESS); + ret= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1); + assert(ret == MEMCACHED_SUCCESS); + assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NOREPLY) == 1); + assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS) == 1); + + for (int x= 0; x < 100; ++x) { + char key[10]; + size_t len= sprintf(key, "%d", x); + ret= memcached_set(memc, key, len, key, len, 0, 0); + assert(ret == MEMCACHED_SUCCESS || ret == MEMCACHED_BUFFERED); + } + + /* + ** NOTE: Don't ever do this in your code! this is not a supported use of the + ** API and is _ONLY_ done this way to verify that the library works the + ** way it is supposed to do!!!! + */ + int no_msg= 0; + for (int x= 0; x < memc->number_of_hosts; ++x) { + no_msg+= memc->hosts[x].cursor_active; + } + + /* + ** The binary protocol does not implement quiet commands yet. Fix this + ** test they are implemented! + */ + if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1) + assert(no_msg == 100); + else + assert(no_msg == 0); + + return MEMCACHED_SUCCESS; +} /* Clean the server before beginning testing */ test_st tests[] ={ @@ -3072,6 +3110,7 @@ test_st tests[] ={ {"memcached_server_cursor", 1, memcached_server_cursor_test }, {"read_through", 1, read_through }, {"delete_through", 1, delete_through }, + {"noreply", 1, noreply_test}, {0, 0, 0} };