Fix for reworked memcached_get() code.
This should solve the known issues with the protocol going weird while
using async.
* Fixed bug where in non-block mode all data might not have been sent on
close().
* Refactor of memcached_get() to use common code.
+ * Change in value fetch, MEMCACHED_END is now returned when keys are no
+ longer in the pipe.
0.11 Mon Nov 26 01:05:52 PST 2007
AC_INIT(src/memcat.c)
AC_CONFIG_AUX_DIR(config)
AM_CONFIG_HEADER(include/libmemcached_config.h)
+AC_CANONICAL_SYSTEM
MEMCACHED_LIBRARY_NAME=libmemcached
AC_SUBST(MEMCACHED_API_VERSION)
#shared library versioning
-MEMCACHED_LIBRARY_VERSION=1:1:0
+MEMCACHED_LIBRARY_VERSION=1:2:0
# | | |
# +------+ | +---+
# | | |
MEMCACHED_FAIL_UNIX_SOCKET,
MEMCACHED_NOT_SUPPORTED,
MEMCACHED_NO_KEY_PROVIDED,
+ MEMCACHED_FETCH_NOTFINISHED,
MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */
} memcached_return;
memcached_return memcached_do(memcached_st *ptr, unsigned int server_key, char *commmand,
size_t command_length, char with_flush);
memcached_return memcached_version(memcached_st *ptr);
+memcached_return memcached_finish_server(memcached_st *ptr, unsigned int server_key);
+void memcached_finish(memcached_st *ptr);
}
new_clone= memcached_create(clone);
+
+ if (new_clone == NULL)
+ return NULL;
-
- rc= memcached_server_push(new_clone, ptr->hosts);
+ if (ptr->hosts)
+ rc= memcached_server_push(new_clone, ptr->hosts);
if (rc != MEMCACHED_SUCCESS)
{
WATCHPOINT_ASSERT(command);
if (ptr->hosts[server_key].cursor_active)
- memcached_quit_server(ptr, server_key);
+ {
+ memcached_return rc;
+ rc= memcached_finish_server(ptr, server_key);
+ ptr->hosts[server_key].cursor_active= 0;
+ }
if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS)
return rc;
end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
- *flags= 0;
+ if (flags)
+ *flags= 0;
memcached_string_reset(value);
rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
+
if (rc == MEMCACHED_SUCCESS)
{
char *next_ptr;
if (end_ptr == string_ptr)
goto read_error;
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
- *flags= (uint16_t)strtol(next_ptr, &string_ptr, 10);
+ if (flags)
+ *flags= (uint16_t)strtol(next_ptr, &string_ptr, 10);
if (end_ptr == string_ptr)
goto read_error;
return MEMCACHED_SUCCESS;
}
}
- else if (rc == MEMCACHED_END)
- rc= MEMCACHED_NOTFOUND;
return rc;
value= memcached_fetch(ptr, NULL, NULL,
value_length, flags, error);
+ if (*error == MEMCACHED_END)
+ *error= MEMCACHED_NOTFOUND;
+
if (value == NULL)
return NULL;
get_command_length= 5;
}
+ memcached_finish(ptr);
+
for (x= 0; x < number_of_keys; x++)
{
unsigned int server_key;
if ((memcached_io_write(ptr, server_key, keys[x], key_length[x], 0)) == -1)
{
- ptr->hosts[server_key].cursor_active = 0;
+ ptr->hosts[server_key].cursor_active= 0;
memcached_quit_server(ptr, server_key);
rc= MEMCACHED_SOME_ERRORS;
continue;
if ((memcached_io_write(ptr, server_key, " ", 1, 0)) == -1)
{
- ptr->hosts[server_key].cursor_active = 0;
+ ptr->hosts[server_key].cursor_active= 0;
memcached_quit_server(ptr, server_key);
rc= MEMCACHED_SOME_ERRORS;
continue;
}
}
-
/*
Should we muddle on if some servers are dead?
*/
flags, NULL, ptr->cursor_server);
*value_length= memcached_string_length(result_buffer);
- if (*error == MEMCACHED_NOTFOUND)
+ if (*error == MEMCACHED_END) /* END means that we move on to the next */
{
- ptr->hosts[ptr->cursor_server].cursor_active = 0;
+ ptr->hosts[ptr->cursor_server].cursor_active= 0;
ptr->cursor_server++;
+ continue;
}
- else if (*error == MEMCACHED_END && *value_length == 0)
- {
- return NULL;
- }
- else if (*error == MEMCACHED_END)
- {
- WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
- *value_length= 0;
- return NULL;
- }
- else if (*error != MEMCACHED_SUCCESS)
- {
- return NULL;
- }
- else
- {
+ else if (*error == MEMCACHED_SUCCESS)
return memcached_string_c_copy(result_buffer);
- }
-
+ else
+ return NULL;
}
+ ptr->cursor_server= 0;
*value_length= 0;
return NULL;
}
&result->cas,
ptr->cursor_server);
- if (*error == MEMCACHED_NOTFOUND)
+ if (*error == MEMCACHED_END) /* END means that we move on to the next */
{
- ptr->hosts[ptr->cursor_server].cursor_active = 0;
+ ptr->hosts[ptr->cursor_server].cursor_active= 0;
ptr->cursor_server++;
+ continue;
}
- else if (*error == MEMCACHED_END && memcached_string_length((memcached_string_st *)(&result->value)) == 0)
- {
- break;
- }
- else if (*error == MEMCACHED_END)
- {
- WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
- break;
- }
- else if (*error != MEMCACHED_SUCCESS)
- {
- break;
- }
- else
- {
+ else if (*error == MEMCACHED_SUCCESS)
return result;
- }
+ else
+ return NULL;
}
/* An error has occurred */
else
memcached_string_reset(&result->value);
+ ptr->cursor_server= 0;
return NULL;
}
+
+memcached_return memcached_finish_server(memcached_st *ptr, unsigned int server_key)
+{
+ memcached_return rc;
+ memcached_string_st *result_buffer;
+
+ result_buffer= &ptr->result_buffer;
+
+ rc= MEMCACHED_SUCCESS;
+ while (rc == MEMCACHED_SUCCESS)
+ {
+ rc= memcached_value_fetch(ptr, NULL, NULL, result_buffer,
+ NULL, NULL, server_key);
+ }
+ ptr->hosts[server_key].cursor_active= 0;
+
+ return rc;
+}
+
+void memcached_finish(memcached_st *ptr)
+{
+ unsigned int x;
+
+ for (x= 0; x < ptr->number_of_hosts; x++)
+ {
+ if (ptr->hosts[x].cursor_active)
+ (void)memcached_finish_server(ptr, x);
+ }
+
+ ptr->cursor_server= 0;
+}
{
struct pollfd fds[1];
short flags= 0;
- struct timespec timer;
- timer.tv_sec= 1;
- timer.tv_nsec= 0;
if (read_or_write)
flags= POLLOUT | POLLERR;
else
memcached_return memcached_io_close(memcached_st *ptr, unsigned int server_key)
{
- struct pollfd fds[1];
- short flags= 0;
- struct timespec timer;
memcached_return rc;
- timer.tv_sec= 1;
- timer.tv_nsec= 0;
- flags= POLLHUP | POLLERR;
+ rc= MEMCACHED_SUCCESS;
+ if (ptr->flags & MEM_NO_BLOCK)
+ {
+ struct pollfd fds[1];
+ short flags= 0;
- memset(&fds, 0, sizeof(struct pollfd));
- fds[0].fd= ptr->hosts[server_key].fd;
- fds[0].events= flags;
- fds[0].revents= flags;
+ flags= POLLHUP | POLLERR;
- if (poll(fds, 1, ptr->poll_timeout) < 0)
- rc= MEMCACHED_FAILURE;
- else
- rc= MEMCACHED_SUCCESS;
+ memset(&fds, 0, sizeof(struct pollfd));
+ fds[0].fd= ptr->hosts[server_key].fd;
+ fds[0].events= flags;
+ fds[0].revents= 0;
+
+ if (poll(fds, 1, ptr->poll_timeout == -1 ? 100 : ptr->poll_timeout) < 0)
+ rc= MEMCACHED_FAILURE;
+ }
close(ptr->hosts[server_key].fd);
{
memcached_return rc;
rc= memcached_do(ptr, server_key, "quit\r\n", 6, 1);
- WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS);
+ WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_FETCH_NOTFINISHED);
memcached_io_close(ptr, server_key);
ptr->hosts[server_key].fd= -1;
total_length++;
WATCHPOINT_ASSERT(total_length < buffer_length);
+
+ if (total_length >= buffer_length)
+ return MEMCACHED_PROTOCOL_ERROR;
}
buffer_ptr++;
*buffer_ptr= 0;
return "COULD NOT OPEN UNIX SOCKET";
case MEMCACHED_NOT_SUPPORTED:
return "ACTION NOT SUPPORTED";
+ case MEMCACHED_FETCH_NOTFINISHED:
+ return "FETCH WAS NOT COMPLETED";
case MEMCACHED_NO_KEY_PROVIDED:
return "A KEY LENGTH OF ZERO WAS PROVIDED";
case MEMCACHED_MAXIMUM_RETURN:
pairs_st *execute_pairs;
unsigned int execute_number;
test_type test;
- memcached_server_st *servers;
+ memcached_st *memc;
};
struct conclusions_st {
void options_parse(int argc, char *argv[]);
void conclusions_print(conclusions_st *conclusion);
void scheduler(memcached_server_st *servers, conclusions_st *conclusion);
-pairs_st *load_create_data(memcached_server_st *servers, unsigned int number_of,
- unsigned int *actual_loaded);
-void flush_all(memcached_server_st *servers);
+pairs_st *load_create_data(memcached_st *memc, unsigned int number_of,
+ unsigned int *actual_loaded);
+void flush_all(memcached_st *memc);
static int opt_verbose= 0;
static int opt_flush= 0;
{
unsigned int x;
unsigned int actual_loaded;
+ memcached_st *memc;
struct timeval start_time, end_time;
pthread_t mainthread; /* Thread descriptor */
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED);
+ memc= memcached_create(NULL);
+ memcached_server_push(memc, servers);
+
if (opt_flush)
- flush_all(servers);
+ flush_all(memc);
if (opt_createial_load)
- pairs= load_create_data(servers, opt_createial_load, &actual_loaded);
+ pairs= load_create_data(memc, opt_createial_load, &actual_loaded);
+
+ /* We set this after we have loaded */
+ {
+ unsigned int value= 1;
+ if (opt_non_blocking_io)
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, &value);
+ if (opt_tcp_nodelay)
+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, &value);
+ }
+
pthread_mutex_lock(&counter_mutex);
thread_counter= 0;
context= (thread_context_st *)malloc(sizeof(thread_context_st));
memset(context, 0, sizeof(thread_context_st));
- context->servers= servers;
+ context->memc= memcached_clone(NULL, memc);
context->test= opt_test;
context->initial_pairs= pairs;
{
thread_context_st *context= (thread_context_st *)p;
memcached_st *memc;
- unsigned int value= 1;
- memc= memcached_create(NULL);
- WATCHPOINT_ASSERT(memc);
- if (opt_non_blocking_io)
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, &value);
- if (opt_tcp_nodelay)
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, &value);
-
- memcached_server_push(memc, context->servers);
+ memc= context->memc;
pthread_mutex_lock(&sleeper_mutex);
while (master_wakeup)
return NULL;
}
-void flush_all(memcached_server_st *servers)
+void flush_all(memcached_st *memc)
{
- memcached_st *memc;
-
- memc= memcached_create(NULL);
-
- memcached_server_push(memc, servers);
-
memcached_flush(memc, 0);
-
- memcached_free(memc);
}
-pairs_st *load_create_data(memcached_server_st *servers, unsigned int number_of,
- unsigned int *actual_loaded)
+pairs_st *load_create_data(memcached_st *memc, unsigned int number_of,
+ unsigned int *actual_loaded)
{
- memcached_st *memc;
+ memcached_st *clone;
pairs_st *pairs;
- memc= memcached_create(NULL);
+ clone= memcached_clone(NULL, memc);
/* We always used non-blocking IO for load since it is faster */
- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, NULL );
- memcached_server_push(memc, servers);
+ memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NO_BLOCK, NULL );
pairs= pairs_generate(number_of);
- *actual_loaded= execute_set(memc, pairs, number_of);
+ *actual_loaded= execute_set(clone, pairs, number_of);
- memcached_free(memc);
+ memcached_free(clone);
return pairs;
}
rc= memcached_set(memc, key, strlen(key),
value, strlen(value),
(time_t)0, (uint16_t)0);
- WATCHPOINT_ERROR(rc);
assert(rc == MEMCACHED_SUCCESS);
return 0;
while ((results= memcached_fetch_result(memc, &results_obj, &rc)) != NULL)
assert(!results);
- assert(rc == MEMCACHED_NOTFOUND);
+ assert(rc == MEMCACHED_END);
for (x= 0; x < 3; x++)
{
assert(results);
}
assert(!results);
- assert(rc == MEMCACHED_NOTFOUND);
+ assert(rc == MEMCACHED_END);
for (x= 0; x < 3; x++)
{
}
assert(!return_value);
assert(return_value_length == 0);
- assert(rc == MEMCACHED_NOTFOUND);
+ assert(rc == MEMCACHED_END);
for (x= 0; x < 3; x++)
{
&value_length, &flags, &rc)))
count++;
assert(count == 0);
- assert(rc == MEMCACHED_NOTFOUND);
+ assert(rc == MEMCACHED_END);
for (x= 0; x < 4; x++)
{
assert(rc == MEMCACHED_SUCCESS);
}
- for (x= 0; x < 10; x++)
+ for (x= 0; x < 2; x++)
{
value= memcached_get(memc, keys[0], key_length[0],
&value_length, &flags, &rc);
{
value= memcached_fetch(memc, return_key, &return_key_length,
&value_length, &flags, &rc);
- memcmp(value, insert_data, value_length);
+ assert(rc == MEMCACHED_SUCCESS);
+ assert(!(memcmp(value, insert_data, value_length)));
assert(value_length);
free(value);
- assert(rc == MEMCACHED_SUCCESS);
}
}
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time
Error 26 -> COULD NOT OPEN UNIX SOCKET
Error 27 -> ACTION NOT SUPPORTED
Error 28 -> A KEY LENGTH OF ZERO WAS PROVIDED
+Error 29 -> FETCH WAS NOT COMPLETED
Found key pid
Found key uptime
Found key time