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
,
9 unsigned int server_key
)
12 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
16 end_ptr
= buffer
+ MEMCACHED_DEFAULT_COMMAND_SIZE
;
20 memcached_string_reset(value
);
22 rc
= memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, server_key
);
24 if (rc
== MEMCACHED_SUCCESS
)
30 string_ptr
+= 6; /* "VALUE " */
37 for (; isalnum(*string_ptr
); string_ptr
++)
44 else /* Skip characters */
45 for (; isalnum(*string_ptr
); string_ptr
++);
47 if (end_ptr
== string_ptr
)
50 /* Flags fetch move past space */
52 if (end_ptr
== string_ptr
)
54 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
55 *flags
= (uint16_t)strtol(next_ptr
, &string_ptr
, 10);
57 if (end_ptr
== string_ptr
)
60 /* Length fetch move past space*/
62 if (end_ptr
== string_ptr
)
65 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
66 value_length
= (size_t)strtoll(next_ptr
, &string_ptr
, 10);
68 if (end_ptr
== string_ptr
)
72 if (*string_ptr
== '\r')
74 /* Skip past the \r\n */
80 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
82 *cas
= (size_t)strtoll(next_ptr
, &string_ptr
, 10);
85 if (end_ptr
< string_ptr
)
94 /* We add two bytes so that we can walk the \r\n */
95 rc
= memcached_string_check(value
, value_length
+2);
96 if (rc
!= MEMCACHED_SUCCESS
)
99 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
102 value_ptr
= memcached_string_value(value
);
105 We read the \r\n into the string since not doing so is more
106 cycles then the waster of memory to do so.
108 We are null terminating through, which will most likely make
109 some people lazy about using the return length.
111 to_read
= (value_length
) + 2;
113 read_length
= memcached_io_read(ptr
, server_key
,
116 if (read_length
!= (size_t)(value_length
+ 2))
121 /* This next bit blows the API, but this is internal....*/
124 char_ptr
= memcached_string_value(value
);;
125 char_ptr
[value_length
]= 0;
126 char_ptr
[value_length
+ 1]= 0;
127 memcached_string_set_length(value
, value_length
);
130 return MEMCACHED_SUCCESS
;
133 else if (rc
== MEMCACHED_END
)
134 rc
= MEMCACHED_NOTFOUND
;
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
)
150 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
151 char *buf_ptr
= buffer
;
152 unsigned int server_key
;
153 memcached_string_st
*result_buffer
;
154 LIBMEMCACHED_MEMCACHED_GET_START();
158 *error
= MEMCACHED_NO_KEY_PROVIDED
;
162 if (ptr
->hosts
== NULL
|| ptr
->number_of_hosts
== 0)
164 *error
= MEMCACHED_NO_SERVERS
;
168 server_key
= memcached_generate_hash(ptr
, key
, key_length
);
169 result_buffer
= &ptr
->result_buffer
;
172 memcpy(buf_ptr
, "get ", 4);
174 memcpy(buf_ptr
, key
, key_length
);
175 buf_ptr
+= key_length
;
176 memcpy(buf_ptr
, "\r\n", 2);
179 *error
= memcached_do(ptr
, server_key
, buffer
, (size_t)(buf_ptr
- buffer
), 1);
180 if (*error
!= MEMCACHED_SUCCESS
)
183 *error
= memcached_value_fetch(ptr
, key
, &key_length
, result_buffer
,
184 flags
, NULL
, 0, server_key
);
185 *value_length
= memcached_string_length(result_buffer
);
186 if (*error
== MEMCACHED_END
&& *value_length
== 0)
188 *error
= MEMCACHED_NOTFOUND
;
191 else if (*error
== MEMCACHED_END
)
193 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
195 else if (*error
== MEMCACHED_SUCCESS
)
198 /* We need to read END */
199 rc
= memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, server_key
);
201 if (rc
!= MEMCACHED_END
)
203 *error
= MEMCACHED_PROTOCOL_ERROR
;
210 LIBMEMCACHED_MEMCACHED_GET_END();
212 return memcached_string_c_copy(result_buffer
);
217 LIBMEMCACHED_MEMCACHED_GET_END();
222 memcached_return
memcached_mget(memcached_st
*ptr
,
223 char **keys
, size_t *key_length
,
224 unsigned int number_of_keys
)
227 memcached_return rc
= MEMCACHED_NOTFOUND
;
228 char *get_command
= "get ";
229 uint8_t get_command_length
= 4
231 LIBMEMCACHED_MEMCACHED_MGET_START();
232 ptr
->cursor_server
= 0;
234 if (number_of_keys
== 0)
235 return MEMCACHED_NOTFOUND
;
237 if (ptr
->number_of_hosts
== 0)
238 return MEMCACHED_NO_SERVERS
;
240 if (ptr
->flags
& MEM_SUPPORT_CAS
)
242 get_command
= "gets ";
243 get_command_length
= 5;
246 for (x
= 0; x
< number_of_keys
; x
++)
248 unsigned int server_key
;
250 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
252 if (ptr
->hosts
[server_key
].cursor_active
== 0)
254 rc
= memcached_connect(ptr
, server_key
);
256 if ((memcached_io_write(ptr
, server_key
, get_command
, get_command_length
, 0)) == -1)
258 memcached_quit_server(ptr
, server_key
);
259 rc
= MEMCACHED_SOME_ERRORS
;
262 ptr
->hosts
[server_key
].cursor_active
= 1;
265 if ((memcached_io_write(ptr
, server_key
, keys
[x
], key_length
[x
], 0)) == -1)
267 ptr
->hosts
[server_key
].cursor_active
= 0;
268 memcached_quit_server(ptr
, server_key
);
269 rc
= MEMCACHED_SOME_ERRORS
;
273 if ((memcached_io_write(ptr
, server_key
, " ", 1, 0)) == -1)
275 ptr
->hosts
[server_key
].cursor_active
= 0;
276 memcached_quit_server(ptr
, server_key
);
277 rc
= MEMCACHED_SOME_ERRORS
;
284 Should we muddle on if some servers are dead?
286 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
288 if (ptr
->hosts
[x
].cursor_active
== 1)
290 /* We need to doo something about non-connnected hosts in the future */
291 if ((memcached_io_write(ptr
, x
, "\r\n", 2, 1)) == -1)
293 memcached_quit_server(ptr
, x
);
294 rc
= MEMCACHED_SOME_ERRORS
;
299 LIBMEMCACHED_MEMCACHED_MGET_END();
303 char *memcached_fetch(memcached_st
*ptr
, char *key
, size_t *key_length
,
304 size_t *value_length
,
306 memcached_return
*error
)
308 memcached_string_st
*result_buffer
;
309 result_buffer
= &ptr
->result_buffer
;
311 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
313 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
315 ptr
->cursor_server
++;
319 *error
= memcached_value_fetch(ptr
, key
, key_length
, result_buffer
,
320 flags
, NULL
, 1, ptr
->cursor_server
);
321 *value_length
= memcached_string_length(result_buffer
);
323 if (*error
== MEMCACHED_NOTFOUND
)
325 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
326 ptr
->cursor_server
++;
328 else if (*error
== MEMCACHED_END
&& *value_length
== 0)
332 else if (*error
== MEMCACHED_END
)
334 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
338 else if (*error
!= MEMCACHED_SUCCESS
)
344 return memcached_string_c_copy(result_buffer
);
353 memcached_result_st
*memcached_fetch_result(memcached_st
*ptr
,
354 memcached_result_st
*result
,
355 memcached_return
*error
)
358 result
= memcached_result_create(ptr
, NULL
);
360 WATCHPOINT_ASSERT(result
->value
.is_allocated
!= MEMCACHED_USED
);
362 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
364 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
366 ptr
->cursor_server
++;
370 result
->cas
= 0; /* We do this so we do not send in any junk */
371 *error
= memcached_value_fetch(ptr
, result
->key
, &result
->key_length
,
375 1, ptr
->cursor_server
);
377 if (*error
== MEMCACHED_NOTFOUND
)
379 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
380 ptr
->cursor_server
++;
382 else if (*error
== MEMCACHED_END
&& memcached_string_length((memcached_string_st
*)(&result
->value
)) == 0)
386 else if (*error
== MEMCACHED_END
)
388 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
391 else if (*error
!= MEMCACHED_SUCCESS
)
401 /* An error has occurred */
402 if (result
->is_allocated
== MEMCACHED_ALLOCATED
)
403 memcached_result_free(result
);
405 memcached_string_reset(&result
->value
);