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 (; end_ptr
> string_ptr
&& *string_ptr
!= ' '; string_ptr
++)
44 else /* Skip characters */
45 for (; end_ptr
> string_ptr
&& *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
; end_ptr
> string_ptr
&& *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
; end_ptr
> string_ptr
&& *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
; end_ptr
> string_ptr
&& *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();
213 return memcached_string_c_copy(result_buffer
);
218 LIBMEMCACHED_MEMCACHED_GET_END();
223 memcached_return
memcached_mget(memcached_st
*ptr
,
224 char **keys
, size_t *key_length
,
225 unsigned int number_of_keys
)
228 memcached_return rc
= MEMCACHED_NOTFOUND
;
229 char *get_command
= "get ";
230 uint8_t get_command_length
= 4
232 LIBMEMCACHED_MEMCACHED_MGET_START();
233 ptr
->cursor_server
= 0;
235 if (number_of_keys
== 0)
236 return MEMCACHED_NOTFOUND
;
238 if (ptr
->number_of_hosts
== 0)
239 return MEMCACHED_NO_SERVERS
;
241 if (ptr
->flags
& MEM_SUPPORT_CAS
)
243 get_command
= "gets ";
244 get_command_length
= 5;
247 for (x
= 0; x
< number_of_keys
; x
++)
249 unsigned int server_key
;
251 server_key
= memcached_generate_hash(ptr
, keys
[x
], key_length
[x
]);
253 if (ptr
->hosts
[server_key
].cursor_active
== 0)
255 rc
= memcached_connect(ptr
, server_key
);
257 if ((memcached_io_write(ptr
, server_key
, get_command
, get_command_length
, 0)) == -1)
259 memcached_quit_server(ptr
, server_key
);
260 rc
= MEMCACHED_SOME_ERRORS
;
263 ptr
->hosts
[server_key
].cursor_active
= 1;
266 if ((memcached_io_write(ptr
, server_key
, keys
[x
], key_length
[x
], 0)) == -1)
268 ptr
->hosts
[server_key
].cursor_active
= 0;
269 memcached_quit_server(ptr
, server_key
);
270 rc
= MEMCACHED_SOME_ERRORS
;
274 if ((memcached_io_write(ptr
, server_key
, " ", 1, 0)) == -1)
276 ptr
->hosts
[server_key
].cursor_active
= 0;
277 memcached_quit_server(ptr
, server_key
);
278 rc
= MEMCACHED_SOME_ERRORS
;
285 Should we muddle on if some servers are dead?
287 for (x
= 0; x
< ptr
->number_of_hosts
; x
++)
289 if (ptr
->hosts
[x
].cursor_active
== 1)
291 /* We need to doo something about non-connnected hosts in the future */
292 if ((memcached_io_write(ptr
, x
, "\r\n", 2, 1)) == -1)
294 memcached_quit_server(ptr
, x
);
295 rc
= MEMCACHED_SOME_ERRORS
;
300 LIBMEMCACHED_MEMCACHED_MGET_END();
304 char *memcached_fetch(memcached_st
*ptr
, char *key
, size_t *key_length
,
305 size_t *value_length
,
307 memcached_return
*error
)
309 memcached_string_st
*result_buffer
;
310 result_buffer
= &ptr
->result_buffer
;
312 while (ptr
->cursor_server
< ptr
->number_of_hosts
)
314 if (!ptr
->hosts
[ptr
->cursor_server
].cursor_active
)
316 ptr
->cursor_server
++;
320 *error
= memcached_value_fetch(ptr
, key
, key_length
, result_buffer
,
321 flags
, NULL
, 1, ptr
->cursor_server
);
322 *value_length
= memcached_string_length(result_buffer
);
324 if (*error
== MEMCACHED_NOTFOUND
)
326 ptr
->hosts
[ptr
->cursor_server
].cursor_active
= 0;
327 ptr
->cursor_server
++;
329 else if (*error
== MEMCACHED_END
&& *value_length
== 0)
333 else if (*error
== MEMCACHED_END
)
335 WATCHPOINT_ASSERT(0); /* If this happens we have somehow messed up the fetch */
339 else if (*error
!= MEMCACHED_SUCCESS
)
345 return memcached_string_c_copy(result_buffer
);
354 memcached_result_st
*memcached_fetch_result(memcached_st
*ptr
,
355 memcached_result_st
*result
,
356 memcached_return
*error
)
359 result
= memcached_result_create(ptr
, NULL
);
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
,
374 1, ptr
->cursor_server
);
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
)