Better multi get keysupport.
typedef struct memcached_st memcached_st;
typedef struct memcached_stat_st memcached_stat_st;
+typedef struct memcached_string_st memcached_string_st;
typedef struct memcached_host_st memcached_host_st;
#define MEMCACHED_DEFAULT_PORT 11211
#define MEMCACHED_DEFAULT_COMMAND_SIZE 350
+#define SMALL_STRING_LEN 1024
#define HUGE_STRING_LEN 8196
#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
unsigned int limit_maxbytes;
};
+struct memcached_string_st {
+ char *string;
+ char *end;
+ size_t current_size;
+ size_t block_size;
+};
+
struct memcached_st {
memcached_allocated is_allocated;
memcached_host_st *hosts;
char *value, size_t value_length);
char ** memcached_stat_get_keys(memcached_stat_st *stat, memcached_return *error);
+/* String Struct */
+#define memcached_string_length(A, B) (size_t)(B->end - B->string)
+#define memcached_string_size(A, B) B->current_size
+#define memcached_string_value(A, B) B->string
+
+memcached_string_st *memcached_string_init(memcached_st *ptr, size_t initial_size);
+memcached_return memcached_string_append_character(memcached_st *ptr,
+ memcached_string_st *string,
+ char character);
+memcached_return memcached_string_append(memcached_st *ptr, memcached_string_st *string,
+ char *value, size_t length);
+size_t memcached_string_backspace(memcached_st *ptr, memcached_string_st *string, size_t remove);
+memcached_return memcached_string_reset(memcached_st *ptr, memcached_string_st *string);
+void memcached_string_free(memcached_st *ptr, memcached_string_st *string);
+
#ifdef __cplusplus
}
#endif
memcached_verbosity.c \\r
memcached_quit.c \\r
memcached_flush.c \\r
+ memcached_string.c \\r
memcached_stats.c\r
memcached_return memcached_server_add(memcached_st *ptr, char *hostname, unsigned int port)
{
+ memcached_host_st *new_host_list;
+ char *new_hostname;
+
if (!port)
port= MEMCACHED_DEFAULT_PORT;
hostname= "localhost";
- ptr->hosts= (memcached_host_st *)realloc(ptr->hosts, sizeof(memcached_host_st) * (ptr->number_of_hosts+1));
- ptr->hosts[ptr->number_of_hosts].hostname=
+ new_host_list= (memcached_host_st *)realloc(ptr->hosts, sizeof(memcached_host_st) * (ptr->number_of_hosts+1));
+ memset((new_host_list + (sizeof(memcached_host_st) * ptr->number_of_hosts)) - sizeof(memcached_host_st),
+ 0, sizeof(memcached_host_st));
+
+ if (!new_host_list)
+ return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+ ptr->hosts= new_host_list;
+
+ new_hostname=
(char *)malloc(sizeof(char) * (strlen(hostname)+1));
- memset(ptr->hosts[ptr->number_of_hosts].hostname, 0, strlen(hostname)+1);
- memcpy(ptr->hosts[ptr->number_of_hosts].hostname, hostname, strlen(hostname));
+ if (!new_hostname)
+ return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+ memset(new_hostname, 0, strlen(hostname)+1);
+ memcpy(new_hostname, hostname, strlen(hostname));
+ ptr->hosts[ptr->number_of_hosts].hostname= new_hostname;
ptr->hosts[ptr->number_of_hosts].port= port;
ptr->hosts[ptr->number_of_hosts].fd= -1;
ptr->number_of_hosts++;
if (rc != MEMCACHED_SUCCESS)
rc= MEMCACHED_SOME_ERRORS;
+ memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE);
for (x= 0; x < ptr->number_of_hosts; x++)
{
if (expiration)
unsigned int number_of_keys)
{
char buffer[HUGE_STRING_LEN];
- char *buffer_ptr;
unsigned int x;
memcached_return rc;
+ memcached_string_st **cursor_key_exec;
ptr->cursor_server= 0;
memset(buffer, 0, HUGE_STRING_LEN);
if (rc != MEMCACHED_SUCCESS)
return rc;
- memcpy(buffer, "get", strlen("get"));
- buffer_ptr= buffer;
- buffer_ptr+=strlen("get");
+ cursor_key_exec= (memcached_string_st **)malloc(sizeof(memcached_string_st *) * ptr->number_of_hosts);
+ memset(cursor_key_exec, 0, sizeof(memcached_string_st *) * ptr->number_of_hosts);
+
for (x= 0; x < number_of_keys; x++)
{
- *buffer_ptr= ' ';
- buffer_ptr++;
- memcpy(buffer_ptr, keys[x], key_length[x]);
- buffer_ptr+= key_length[x];
+ unsigned int server_key;
+
+ server_key= memcached_generate_hash(keys[x], key_length[x]) % ptr->number_of_hosts;
+
+ if (cursor_key_exec[server_key])
+ {
+ memcached_string_st *string= cursor_key_exec[server_key];
+
+ memcached_string_append_character(ptr, string, ' ');
+ memcached_string_append(ptr, string, keys[x], key_length[x]);
+ }
+ else
+ {
+ memcached_string_st *string= memcached_string_init(ptr, SMALL_STRING_LEN);
+
+ if (!string)
+ assert(0);
+
+ memcached_string_append(ptr, string, "get ", 4);
+ memcached_string_append(ptr, string, keys[x], key_length[x]);
+
+ cursor_key_exec[server_key]= string;
+ }
}
- memcpy(buffer_ptr, "\r\n", 2);
- buffer_ptr+=2;
/*
- This must be fixed. Right now we hit every server, and send keys
- to all servers. We should fix this quickly.
+ Should we muddle on if some servers are dead?
*/
for (x= 0; x < ptr->number_of_hosts; x++)
{
- if ((write(ptr->hosts[x].fd, buffer, (size_t)(buffer_ptr - buffer)) == -1))
+ if (cursor_key_exec[x])
{
- memcached_quit(ptr);
- rc= MEMCACHED_SOME_ERRORS;
+ memcached_string_st *string= cursor_key_exec[x];
+ memcached_string_append(ptr, string, "\r\n", 2);
+
+ if ((write(ptr->hosts[x].fd, string->string,
+ memcached_string_length(ptr, string)) == -1))
+ {
+ memcached_quit(ptr);
+ rc= MEMCACHED_SOME_ERRORS;
+ }
+ memcached_string_free(ptr, string);
}
}
+ free(cursor_key_exec);
+
return rc;
}
{
char **list= (char **)malloc(sizeof(memcached_stat_keys));
+ if (!list)
+ {
+ *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+ return NULL;
+ }
+
memcpy(list, memcached_stat_keys, sizeof(memcached_stat_keys));
+ *error= MEMCACHED_SUCCESS;
+
return list;
}
--- /dev/null
+#include <memcached.h>
+
+memcached_return memcached_string_check(memcached_string_st *string, size_t need)
+{
+ if (need > (string->current_size - (string->end - string->string)))
+ {
+ size_t current_offset= string->end - string->string;
+ char *new_value;
+
+ new_value= (char *)realloc(string->string, sizeof(char) * string->block_size);
+
+ if (!new_value)
+ return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+ string->string= new_value;
+ string->end= string->string + current_offset;
+
+ string->current_size+= string->block_size;
+
+ /* We zero the block structure we just realloced */
+ memset((string + string->current_size) - string->block_size , 0,
+ sizeof(char) * string->block_size);
+ }
+
+ return MEMCACHED_SUCCESS;
+}
+
+memcached_string_st *memcached_string_init(memcached_st *ptr, size_t initial_size)
+{
+ memcached_string_st *string;
+
+ /* Saving malloc calls :) */
+ string= (memcached_string_st *)malloc(sizeof(memcached_string_st) + (sizeof(char) * initial_size));
+ if (!string)
+ return NULL;
+ memset(string, 0, sizeof(memcached_string_st));
+ string->block_size= initial_size;
+ memcached_string_check(string, initial_size);
+
+ return string;
+}
+
+memcached_return memcached_string_append_character(memcached_st *ptr,
+ memcached_string_st *string,
+ char character)
+{
+ memcached_string_check(string, 1);
+ *string->end= ' ';
+ string->end++;
+
+ return MEMCACHED_SUCCESS;
+}
+
+memcached_return memcached_string_append(memcached_st *ptr, memcached_string_st *string,
+ char *value, size_t length)
+{
+ memcached_string_check(string, length);
+ memcpy(string->end, value, length);
+ string->end+= length;
+
+ return MEMCACHED_SUCCESS;
+}
+
+#ifdef CRAP
+size_t memcached_string_length(memcached_st *ptr, memcached_string_st *string)
+{
+ return (size_t)(string->end - string->string);
+}
+
+size_t memcached_string_size(memcached_st *ptr, memcached_string_st *string)
+{
+ return string->current_size;
+}
+#endif
+
+size_t memcached_string_backspace(memcached_st *ptr, memcached_string_st *string, size_t remove)
+{
+ if (string->end - string->string > remove)
+ {
+ size_t difference;
+
+ difference= string->end - string->string;
+ string->end= string->string;
+
+ return difference;
+ }
+ string->end-= remove;
+
+ return remove;
+}
+
+memcached_return memcached_string_reset(memcached_st *ptr, memcached_string_st *string)
+{
+ string->end= string->string;
+
+ return MEMCACHED_SUCCESS;
+}
+
+void memcached_string_free(memcached_st *ptr, memcached_string_st *string)
+{
+ free(string->string);
+ free(string);
+}