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
;
19 memcached_string_reset(value
);
21 rc
= memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, server_key
);
23 if (rc
== MEMCACHED_SUCCESS
)
29 string_ptr
+= 6; /* "VALUE " */
36 for (; isalnum(*string_ptr
); string_ptr
++)
43 else /* Skip characters */
44 for (; isalnum(*string_ptr
); string_ptr
++);
46 if (end_ptr
== string_ptr
)
49 /* Flags fetch move past space */
51 if (end_ptr
== string_ptr
)
53 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
54 *flags
= (uint16_t)strtol(next_ptr
, &string_ptr
, 10);
56 if (end_ptr
== string_ptr
)
59 /* Length fetch move past space*/
61 if (end_ptr
== string_ptr
)
64 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
65 value_length
= (size_t)strtoll(next_ptr
, &string_ptr
, 10);
67 if (end_ptr
== string_ptr
)
71 if (*string_ptr
== '\r')
73 /* Skip past the \r\n */
79 for (next_ptr
= string_ptr
; isdigit(*string_ptr
); string_ptr
++);
81 *cas
= (size_t)strtoll(next_ptr
, &string_ptr
, 10);
84 if (end_ptr
< string_ptr
)
93 /* We add two bytes so that we can walk the \r\n */
94 rc
= memcached_string_check(value
, value_length
+2);
95 if (rc
!= MEMCACHED_SUCCESS
)
98 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
101 value_ptr
= memcached_string_value(value
);
104 We read the \r\n into the string since not doing so is more
105 cycles then the waster of memory to do so.
107 We are null terminating through, which will most likely make
108 some people lazy about using the return length.
110 to_read
= (value_length
) + 2;
112 read_length
= memcached_io_read(ptr
, server_key
,
115 if (read_length
!= (size_t)(value_length
+ 2))
120 /* This next bit blows the API, but this is internal....*/
123 char_ptr
= memcached_string_value(value
);;
124 char_ptr
[value_length
]= 0;
125 char_ptr
[value_length
+ 1]= 0;
126 memcached_string_set_length(value
, value_length
);
129 return MEMCACHED_SUCCESS
;
132 else if (rc
== MEMCACHED_END
)
133 rc
= MEMCACHED_NOTFOUND
;
138 return MEMCACHED_PARTIAL_READ
;
142 What happens if no servers exist?
144 char *memcached_get(memcached_st
*ptr
, char *key
, size_t key_length
,
145 size_t *value_length
,
147 memcached_return
*error
)
149 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
150 char *buf_ptr
= buffer
;
151 unsigned int server_key
;
152 memcached_string_st
*result_buffer
;
153 LIBMEMCACHED_MEMCACHED_GET_START();
157 *error
= MEMCACHED_NO_KEY_PROVIDED
;
161 if (ptr
->hosts
== NULL
|| ptr
->number_of_hosts
== 0)
163 *error
= MEMCACHED_NO_SERVERS
;
167 server_key
= memcached_generate_hash(ptr
, key
, key_length
);
168 result_buffer
= &ptr
->result_buffer
;
171 memcpy(buf_ptr
, "get ", 4);
173 memcpy(buf_ptr
, key
, key_length
);
174 buf_ptr
+= key_length
;
175 memcpy(buf_ptr
, "\r\n", 2);
178 *error
= memcached_do(ptr
, server_key
, buffer
, (size_t)(buf_ptr
- buffer
), 1);
179 if (*error
!= MEMCACHED_SUCCESS
)
182 *error
= memcached_value_fetch(ptr
, NULL
, NULL
, result_buffer
,
183 flags
, NULL
, server_key
);
184 *value_length
= memcached_string_length(result_buffer
);
185 if (*error
== MEMCACHED_END
&& *value_length
== 0)
187 *error
= MEMCACHED_NOTFOUND
;
190 else if (*error
== MEMCACHED_END
)
192 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
194 else if (*error
== MEMCACHED_SUCCESS
)
197 /* We need to read END */
198 rc
= memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, server_key
);
200 if (rc
!= MEMCACHED_END
)
202 *error
= MEMCACHED_PROTOCOL_ERROR
;
209 LIBMEMCACHED_MEMCACHED_GET_END();
211 return memcached_string_c_copy(result_buffer
);
216 LIBMEMCACHED_MEMCACHED_GET_END();
221 memcached_return
memcached_mget(memcached_st
*ptr
,
222 char **keys
, size_t *key_length
,
223 unsigned int number_of_keys
)
226 memcached_return rc
= MEMCACHED_NOTFOUND
;
227 char *get_command
= "get ";
228 uint8_t get_command_length
= 4
230 LIBMEMCACHED_MEMCACHED_MGET_START();
231 ptr
->cursor_server
= 0;
233 if (number_of_keys
== 0)
234 return MEMCACHED_NOTFOUND
;
236 if (ptr
->number_of_hosts
== 0)
237 return MEMCACHED_NO_SERVERS
;
239 if (ptr
->flags
& MEM_SUPPORT_CAS
)
241 get_command
= "gets ";
242 get_command_length
= 5;
245 for (x
= 0; x
< number_of_keys
; x
++)
247 unsigned int server_key
;
249 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
251 if (ptr
->hosts
[server_key
].cursor_active
== 0)
253 rc
= memcached_connect(ptr
, server_key
);
255 if ((memcached_io_write(ptr
, server_key
, get_command
, get_command_length
, 0)) == -1)
257 memcached_quit_server(ptr
, server_key
);
258 rc
= MEMCACHED_SOME_ERRORS
;
261 ptr
->hosts
[server_key
].cursor_active
= 1;
264 if ((memcached_io_write(ptr
, server_key
, keys
[x
], key_length
[x
], 0)) == -1)
266 ptr
->hosts
[server_key
].cursor_active
= 0;
267 memcached_quit_server(ptr
, server_key
);
268 rc
= MEMCACHED_SOME_ERRORS
;
272 if ((memcached_io_write(ptr
, server_key
, " ", 1, 0)) == -1)
274 ptr
->hosts
[server_key
].cursor_active
= 0;
275 memcached_quit_server(ptr
, server_key
);
276 rc
= MEMCACHED_SOME_ERRORS
;
283 Should we muddle on if some servers are dead?
285 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
287 if (ptr
->hosts
[x
].cursor_active
== 1)
289 /* We need to doo something about non-connnected hosts in the future */
290 if ((memcached_io_write(ptr
, x
, "\r\n", 2, 1)) == -1)
292 memcached_quit_server(ptr
, x
);
293 rc
= MEMCACHED_SOME_ERRORS
;
298 LIBMEMCACHED_MEMCACHED_MGET_END();
302 char *memcached_fetch(memcached_st
*ptr
, char *key
, size_t *key_length
,
303 size_t *value_length
,
305 memcached_return
*error
)
307 memcached_string_st
*result_buffer
;
308 result_buffer
= &ptr
->result_buffer
;
310 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
312 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
314 ptr
->cursor_server
++;
318 *error
= memcached_value_fetch(ptr
, key
, key_length
, result_buffer
,
319 flags
, NULL
, ptr
->cursor_server
);
320 *value_length
= memcached_string_length(result_buffer
);
322 if (*error
== MEMCACHED_NOTFOUND
)
324 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
325 ptr
->cursor_server
++;
327 else if (*error
== MEMCACHED_END
&& *value_length
== 0)
331 else if (*error
== MEMCACHED_END
)
333 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
337 else if (*error
!= MEMCACHED_SUCCESS
)
343 return memcached_string_c_copy(result_buffer
);
352 memcached_result_st
*memcached_fetch_result(memcached_st
*ptr
,
353 memcached_result_st
*result
,
354 memcached_return
*error
)
357 result
= memcached_result_create(ptr
, NULL
);
359 WATCHPOINT_ASSERT(result
->value
.is_allocated
!= MEMCACHED_USED
);
361 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
363 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
365 ptr
->cursor_server
++;
369 result
->cas
= 0; /* We do this so we do not send in any junk */
370 *error
= memcached_value_fetch(ptr
, result
->key
, &result
->key_length
,
376 if (*error
== MEMCACHED_NOTFOUND
)
378 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
379 ptr
->cursor_server
++;
381 else if (*error
== MEMCACHED_END
&& memcached_string_length((memcached_string_st
*)(&result
->value
)) == 0)
385 else if (*error
== MEMCACHED_END
)
387 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
390 else if (*error
!= MEMCACHED_SUCCESS
)
400 /* An error has occurred */
401 if (result
->is_allocated
== MEMCACHED_ALLOCATED
)
402 memcached_result_free(result
);
404 memcached_string_reset(&result
->value
);