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
)
152 uint16_t dummy_flags
;
153 memcached_return dummy_error
;
155 /* Request the key */
156 *error
= memcached_mget(ptr
, &key
, &key_length
, 1);
158 value
= memcached_fetch(ptr
, NULL
, NULL
,
159 value_length
, flags
, error
);
164 /* We do a second read to clean the cursor */
165 dummy_value
= memcached_fetch(ptr
, NULL
, NULL
,
166 &dummy_length
, &dummy_flags
,
169 /* Something is really wrong if this happens */
170 WATCHPOINT_ASSERT(dummy_value
== NULL
);
177 memcached_return
memcached_mget(memcached_st
*ptr
,
178 char **keys
, size_t *key_length
,
179 unsigned int number_of_keys
)
182 memcached_return rc
= MEMCACHED_NOTFOUND
;
183 char *get_command
= "get ";
184 uint8_t get_command_length
= 4
186 LIBMEMCACHED_MEMCACHED_MGET_START();
187 ptr
->cursor_server
= 0;
189 if (number_of_keys
== 0)
190 return MEMCACHED_NOTFOUND
;
192 if (ptr
->number_of_hosts
== 0)
193 return MEMCACHED_NO_SERVERS
;
195 if (ptr
->flags
& MEM_SUPPORT_CAS
)
197 get_command
= "gets ";
198 get_command_length
= 5;
201 for (x
= 0; x
< number_of_keys
; x
++)
203 unsigned int server_key
;
205 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
207 if (ptr
->hosts
[server_key
].cursor_active
== 0)
209 rc
= memcached_connect(ptr
, server_key
);
211 if ((memcached_io_write(ptr
, server_key
, get_command
, get_command_length
, 0)) == -1)
213 memcached_quit_server(ptr
, server_key
);
214 rc
= MEMCACHED_SOME_ERRORS
;
217 ptr
->hosts
[server_key
].cursor_active
= 1;
220 if ((memcached_io_write(ptr
, server_key
, keys
[x
], key_length
[x
], 0)) == -1)
222 ptr
->hosts
[server_key
].cursor_active
= 0;
223 memcached_quit_server(ptr
, server_key
);
224 rc
= MEMCACHED_SOME_ERRORS
;
228 if ((memcached_io_write(ptr
, server_key
, " ", 1, 0)) == -1)
230 ptr
->hosts
[server_key
].cursor_active
= 0;
231 memcached_quit_server(ptr
, server_key
);
232 rc
= MEMCACHED_SOME_ERRORS
;
239 Should we muddle on if some servers are dead?
241 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
243 if (ptr
->hosts
[x
].cursor_active
== 1)
245 /* We need to doo something about non-connnected hosts in the future */
246 if ((memcached_io_write(ptr
, x
, "\r\n", 2, 1)) == -1)
248 memcached_quit_server(ptr
, x
);
249 rc
= MEMCACHED_SOME_ERRORS
;
254 LIBMEMCACHED_MEMCACHED_MGET_END();
258 char *memcached_fetch(memcached_st
*ptr
, char *key
, size_t *key_length
,
259 size_t *value_length
,
261 memcached_return
*error
)
263 memcached_string_st
*result_buffer
;
264 result_buffer
= &ptr
->result_buffer
;
266 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
268 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
270 ptr
->cursor_server
++;
274 *error
= memcached_value_fetch(ptr
, key
, key_length
, result_buffer
,
275 flags
, NULL
, ptr
->cursor_server
);
276 *value_length
= memcached_string_length(result_buffer
);
278 if (*error
== MEMCACHED_NOTFOUND
)
280 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
281 ptr
->cursor_server
++;
283 else if (*error
== MEMCACHED_END
&& *value_length
== 0)
287 else if (*error
== MEMCACHED_END
)
289 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
293 else if (*error
!= MEMCACHED_SUCCESS
)
299 return memcached_string_c_copy(result_buffer
);
308 memcached_result_st
*memcached_fetch_result(memcached_st
*ptr
,
309 memcached_result_st
*result
,
310 memcached_return
*error
)
313 result
= memcached_result_create(ptr
, NULL
);
315 WATCHPOINT_ASSERT(result
->value
.is_allocated
!= MEMCACHED_USED
);
317 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
319 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
321 ptr
->cursor_server
++;
325 result
->cas
= 0; /* We do this so we do not send in any junk */
326 *error
= memcached_value_fetch(ptr
, result
->key
, &result
->key_length
,
332 if (*error
== MEMCACHED_NOTFOUND
)
334 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
335 ptr
->cursor_server
++;
337 else if (*error
== MEMCACHED_END
&& memcached_string_length((memcached_string_st
*)(&result
->value
)) == 0)
341 else if (*error
== MEMCACHED_END
)
343 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
346 else if (*error
!= MEMCACHED_SUCCESS
)
356 /* An error has occurred */
357 if (result
->is_allocated
== MEMCACHED_ALLOCATED
)
358 memcached_result_free(result
);
360 memcached_string_reset(&result
->value
);