2 #include "memcached_io.h"
4 static memcached_return
memcached_value_fetch(memcached_st
*ptr
, char *key
, size_t *key_length
,
5 memcached_string_st
*value
,
8 unsigned int server_key
)
11 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
15 end_ptr
= buffer
+ MEMCACHED_DEFAULT_COMMAND_SIZE
;
20 memcached_string_reset(value
);
22 rc
= memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, server_key
);
25 if (rc
== MEMCACHED_SUCCESS
)
31 string_ptr
+= 6; /* "VALUE " */
38 for (; isalnum(*string_ptr
); string_ptr
++)
45 else /* Skip characters */
46 for (; isalnum(*string_ptr
); string_ptr
++);
48 if (end_ptr
== string_ptr
)
51 /* Flags fetch move past space */
53 if (end_ptr
== string_ptr
)
55 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
57 *flags
= (uint16_t)strtol(next_ptr
, &string_ptr
, 10);
59 if (end_ptr
== string_ptr
)
62 /* Length fetch move past space*/
64 if (end_ptr
== string_ptr
)
67 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
68 value_length
= (size_t)strtoll(next_ptr
, &string_ptr
, 10);
70 if (end_ptr
== string_ptr
)
74 if (*string_ptr
== '\r')
76 /* Skip past the \r\n */
82 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
84 *cas
= (size_t)strtoll(next_ptr
, &string_ptr
, 10);
87 if (end_ptr
< string_ptr
)
96 /* We add two bytes so that we can walk the \r\n */
97 rc
= memcached_string_check(value
, value_length
+2);
98 if (rc
!= MEMCACHED_SUCCESS
)
101 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
104 value_ptr
= memcached_string_value(value
);
107 We read the \r\n into the string since not doing so is more
108 cycles then the waster of memory to do so.
110 We are null terminating through, which will most likely make
111 some people lazy about using the return length.
113 to_read
= (value_length
) + 2;
115 read_length
= memcached_io_read(ptr
, server_key
,
118 if (read_length
!= (size_t)(value_length
+ 2))
123 /* This next bit blows the API, but this is internal....*/
126 char_ptr
= memcached_string_value(value
);;
127 char_ptr
[value_length
]= 0;
128 char_ptr
[value_length
+ 1]= 0;
129 memcached_string_set_length(value
, value_length
);
132 return MEMCACHED_SUCCESS
;
139 return MEMCACHED_PARTIAL_READ
;
143 What happens if no servers exist?
145 char *memcached_get(memcached_st
*ptr
, char *key
, size_t key_length
,
146 size_t *value_length
,
148 memcached_return
*error
)
153 uint16_t dummy_flags
;
154 memcached_return dummy_error
;
156 /* Request the key */
157 *error
= memcached_mget(ptr
, &key
, &key_length
, 1);
159 value
= memcached_fetch(ptr
, NULL
, NULL
,
160 value_length
, flags
, error
);
162 if (*error
== MEMCACHED_END
)
163 *error
= MEMCACHED_NOTFOUND
;
168 /* We do a second read to clean the cursor */
169 dummy_value
= memcached_fetch(ptr
, NULL
, NULL
,
170 &dummy_length
, &dummy_flags
,
173 /* Something is really wrong if this happens */
174 WATCHPOINT_ASSERT(dummy_value
== NULL
);
181 memcached_return
memcached_mget(memcached_st
*ptr
,
182 char **keys
, size_t *key_length
,
183 unsigned int number_of_keys
)
186 memcached_return rc
= MEMCACHED_NOTFOUND
;
187 char *get_command
= "get ";
188 uint8_t get_command_length
= 4
190 LIBMEMCACHED_MEMCACHED_MGET_START();
191 ptr
->cursor_server
= 0;
193 if (number_of_keys
== 0)
194 return MEMCACHED_NOTFOUND
;
196 if (ptr
->number_of_hosts
== 0)
197 return MEMCACHED_NO_SERVERS
;
199 if (ptr
->flags
& MEM_SUPPORT_CAS
)
201 get_command
= "gets ";
202 get_command_length
= 5;
205 memcached_finish(ptr
);
207 for (x
= 0; x
< number_of_keys
; x
++)
209 unsigned int server_key
;
211 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
213 if (ptr
->hosts
[server_key
].cursor_active
== 0)
215 rc
= memcached_connect(ptr
, server_key
);
217 if ((memcached_io_write(ptr
, server_key
, get_command
, get_command_length
, 0)) == -1)
219 memcached_quit_server(ptr
, server_key
);
220 rc
= MEMCACHED_SOME_ERRORS
;
223 ptr
->hosts
[server_key
].cursor_active
= 1;
226 if ((memcached_io_write(ptr
, server_key
, keys
[x
], key_length
[x
], 0)) == -1)
228 ptr
->hosts
[server_key
].cursor_active
= 0;
229 memcached_quit_server(ptr
, server_key
);
230 rc
= MEMCACHED_SOME_ERRORS
;
234 if ((memcached_io_write(ptr
, server_key
, " ", 1, 0)) == -1)
236 ptr
->hosts
[server_key
].cursor_active
= 0;
237 memcached_quit_server(ptr
, server_key
);
238 rc
= MEMCACHED_SOME_ERRORS
;
244 Should we muddle on if some servers are dead?
246 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
248 if (ptr
->hosts
[x
].cursor_active
== 1)
250 /* We need to doo something about non-connnected hosts in the future */
251 if ((memcached_io_write(ptr
, x
, "\r\n", 2, 1)) == -1)
253 memcached_quit_server(ptr
, x
);
254 rc
= MEMCACHED_SOME_ERRORS
;
259 LIBMEMCACHED_MEMCACHED_MGET_END();
263 char *memcached_fetch(memcached_st
*ptr
, char *key
, size_t *key_length
,
264 size_t *value_length
,
266 memcached_return
*error
)
268 memcached_string_st
*result_buffer
;
269 result_buffer
= &ptr
->result_buffer
;
271 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
273 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
275 ptr
->cursor_server
++;
279 *error
= memcached_value_fetch(ptr
, key
, key_length
, result_buffer
,
280 flags
, NULL
, ptr
->cursor_server
);
281 *value_length
= memcached_string_length(result_buffer
);
283 if (*error
== MEMCACHED_END
) /* END means that we move on to the next */
285 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
286 ptr
->cursor_server
++;
289 else if (*error
== MEMCACHED_SUCCESS
)
290 return memcached_string_c_copy(result_buffer
);
295 ptr
->cursor_server
= 0;
300 memcached_result_st
*memcached_fetch_result(memcached_st
*ptr
,
301 memcached_result_st
*result
,
302 memcached_return
*error
)
305 result
= memcached_result_create(ptr
, NULL
);
307 WATCHPOINT_ASSERT(result
->value
.is_allocated
!= MEMCACHED_USED
);
309 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
311 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
313 ptr
->cursor_server
++;
317 result
->cas
= 0; /* We do this so we do not send in any junk */
318 *error
= memcached_value_fetch(ptr
, result
->key
, &result
->key_length
,
324 if (*error
== MEMCACHED_END
) /* END means that we move on to the next */
326 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
327 ptr
->cursor_server
++;
330 else if (*error
== MEMCACHED_SUCCESS
)
336 /* An error has occurred */
337 if (result
->is_allocated
== MEMCACHED_ALLOCATED
)
338 memcached_result_free(result
);
340 memcached_string_reset(&result
->value
);
342 ptr
->cursor_server
= 0;
346 memcached_return
memcached_finish_server(memcached_st
*ptr
, unsigned int server_key
)
349 memcached_string_st
*result_buffer
;
351 result_buffer
= &ptr
->result_buffer
;
353 rc
= MEMCACHED_SUCCESS
;
354 while (rc
== MEMCACHED_SUCCESS
)
356 rc
= memcached_value_fetch(ptr
, NULL
, NULL
, result_buffer
,
357 NULL
, NULL
, server_key
);
359 ptr
->hosts
[server_key
].cursor_active
= 0;
364 void memcached_finish(memcached_st
*ptr
)
368 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
370 if (ptr
->hosts
[x
].cursor_active
)
371 (void)memcached_finish_server(ptr
, x
);
374 ptr
->cursor_server
= 0;