4 memcached_response() is used to determine the return result
5 from an issued command.
9 #include "memcached_io.h"
11 static memcached_return
binary_response(memcached_server_st
*ptr
,
12 char *buffer
, size_t buffer_length
,
13 memcached_result_st
*result
);
15 memcached_return
memcached_response(memcached_server_st
*ptr
,
16 char *buffer
, size_t buffer_length
,
17 memcached_result_st
*result
)
22 unsigned int max_messages
;
26 /* UDP at the moment is odd...*/
27 if (ptr
->type
== MEMCACHED_CONNECTION_UDP
)
32 return MEMCACHED_SUCCESS
;
34 read_length
= memcached_io_read(ptr
, buffer
, 8);
37 /* We may have old commands in the buffer not set, first purge */
38 if (ptr
->root
->flags
& MEM_NO_BLOCK
)
39 (void)memcached_io_write(ptr
, NULL
, 0, 1);
41 if (ptr
->root
->flags
& MEM_BINARY_PROTOCOL
)
42 return binary_response(ptr
, buffer
, buffer_length
, result
);
44 max_messages
= memcached_server_response_count(ptr
);
45 for (x
= 0; x
< max_messages
; x
++)
47 size_t total_length
= 0;
55 read_length
= memcached_io_read(ptr
, buffer_ptr
, 1);
56 WATCHPOINT_ASSERT(*buffer_ptr
!= '\0');
60 memcached_io_reset(ptr
);
61 return MEMCACHED_UNKNOWN_READ_FAILURE
;
64 if (*buffer_ptr
== '\n')
70 WATCHPOINT_ASSERT(total_length
<= buffer_length
);
72 if (total_length
>= buffer_length
)
74 memcached_io_reset(ptr
);
75 return MEMCACHED_PROTOCOL_ERROR
;
81 memcached_server_response_decrement(ptr
);
86 case 'V': /* VALUE || VERSION */
87 if (buffer
[1] == 'A') /* VALUE */
91 /* We add back in one because we will need to search for END */
92 memcached_server_response_increment(ptr
);
94 rc
= value_fetch(ptr
, buffer
, result
);
96 rc
= value_fetch(ptr
, buffer
, &ptr
->root
->result
);
100 else if (buffer
[1] == 'E') /* VERSION */
102 return MEMCACHED_SUCCESS
;
106 WATCHPOINT_STRING(buffer
);
107 WATCHPOINT_ASSERT(0);
108 memcached_io_reset(ptr
);
109 return MEMCACHED_UNKNOWN_READ_FAILURE
;
112 return MEMCACHED_SUCCESS
;
113 case 'S': /* STORED STATS SERVER_ERROR */
115 if (buffer
[2] == 'A') /* STORED STATS */
117 memcached_server_response_increment(ptr
);
118 return MEMCACHED_STAT
;
120 else if (buffer
[1] == 'E')
121 return MEMCACHED_SERVER_ERROR
;
122 else if (buffer
[1] == 'T')
123 return MEMCACHED_STORED
;
126 WATCHPOINT_STRING(buffer
);
127 WATCHPOINT_ASSERT(0);
128 memcached_io_reset(ptr
);
129 return MEMCACHED_UNKNOWN_READ_FAILURE
;
132 case 'D': /* DELETED */
133 return MEMCACHED_DELETED
;
134 case 'N': /* NOT_FOUND */
136 if (buffer
[4] == 'F')
137 return MEMCACHED_NOTFOUND
;
138 else if (buffer
[4] == 'S')
139 return MEMCACHED_NOTSTORED
;
142 memcached_io_reset(ptr
);
143 return MEMCACHED_UNKNOWN_READ_FAILURE
;
146 case 'E': /* PROTOCOL ERROR or END */
148 if (buffer
[1] == 'N')
149 return MEMCACHED_END
;
150 else if (buffer
[1] == 'R')
152 memcached_io_reset(ptr
);
153 return MEMCACHED_PROTOCOL_ERROR
;
155 else if (buffer
[1] == 'X')
157 memcached_io_reset(ptr
);
158 return MEMCACHED_DATA_EXISTS
;
162 memcached_io_reset(ptr
);
163 return MEMCACHED_UNKNOWN_READ_FAILURE
;
166 case 'C': /* CLIENT ERROR */
167 memcached_io_reset(ptr
);
168 return MEMCACHED_CLIENT_ERROR
;
171 unsigned long long auto_return_value
;
173 if (sscanf(buffer
, "%llu", &auto_return_value
) == 1)
174 return MEMCACHED_SUCCESS
;
176 memcached_io_reset(ptr
);
178 return MEMCACHED_UNKNOWN_READ_FAILURE
;
183 return MEMCACHED_SUCCESS
;
186 char *memcached_result_value(memcached_result_st
*ptr
)
188 memcached_string_st
*sptr
= &ptr
->value
;
189 return memcached_string_value(sptr
);
192 size_t memcached_result_length(memcached_result_st
*ptr
)
194 memcached_string_st
*sptr
= &ptr
->value
;
195 return memcached_string_length(sptr
);
199 * Read a given number of bytes from the server and place it into a specific
200 * buffer. Reset the IO channel or this server if an error occurs.
202 static memcached_return
safe_read(memcached_server_st
*ptr
, void *dta
,
208 while (offset
< size
)
210 ssize_t nread
= memcached_io_read(ptr
, data
+ offset
, size
- offset
);
213 memcached_io_reset(ptr
);
214 return MEMCACHED_UNKNOWN_READ_FAILURE
;
219 return MEMCACHED_SUCCESS
;
222 static memcached_return
binary_response(memcached_server_st
*ptr
,
224 size_t buffer_length
,
225 memcached_result_st
*result
)
227 protocol_binary_response_header header
;
228 memcached_server_response_decrement(ptr
);
230 unlikely (safe_read(ptr
, &header
.bytes
,
231 sizeof(header
.bytes
)) != MEMCACHED_SUCCESS
)
232 return MEMCACHED_UNKNOWN_READ_FAILURE
;
234 unlikely (header
.response
.magic
!= PROTOCOL_BINARY_RES
)
236 memcached_io_reset(ptr
);
237 return MEMCACHED_PROTOCOL_ERROR
;
241 ** Convert the header to host local endian!
243 header
.response
.keylen
= ntohs(header
.response
.keylen
);
244 header
.response
.status
= ntohs(header
.response
.status
);
245 header
.response
.bodylen
= ntohl(header
.response
.bodylen
);
246 header
.response
.cas
= ntohll(header
.response
.cas
);
247 uint32_t bodylen
= header
.response
.bodylen
;
249 if (header
.response
.status
== 0)
251 switch (header
.response
.opcode
)
253 case PROTOCOL_BINARY_CMD_GETK
:
254 case PROTOCOL_BINARY_CMD_GETKQ
:
256 uint16_t keylen
= header
.response
.keylen
;
257 memcached_result_reset(result
);
258 result
->cas
= header
.response
.cas
;
260 if (safe_read(ptr
, &result
->flags
,
261 sizeof(result
->flags
)) != MEMCACHED_SUCCESS
)
263 return MEMCACHED_UNKNOWN_READ_FAILURE
;
265 result
->flags
= ntohl(result
->flags
);
266 bodylen
-= header
.response
.extlen
;
268 result
->key_length
= keylen
;
269 if (safe_read(ptr
, result
->key
, keylen
) != MEMCACHED_SUCCESS
)
271 return MEMCACHED_UNKNOWN_READ_FAILURE
;
275 if (memcached_string_check(&result
->value
,
276 bodylen
) != MEMCACHED_SUCCESS
)
278 memcached_io_reset(ptr
);
279 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
282 char *vptr
= memcached_string_value(&result
->value
);
283 if (safe_read(ptr
, vptr
, bodylen
) != MEMCACHED_SUCCESS
)
285 return MEMCACHED_UNKNOWN_READ_FAILURE
;
288 memcached_string_set_length(&result
->value
, bodylen
);
291 case PROTOCOL_BINARY_CMD_INCREMENT
:
292 case PROTOCOL_BINARY_CMD_DECREMENT
:
294 if (bodylen
!= sizeof(uint64_t) || buffer_length
!= sizeof(uint64_t))
296 return MEMCACHED_PROTOCOL_ERROR
;
299 WATCHPOINT_ASSERT(bodylen
== buffer_length
);
301 if (safe_read(ptr
, &val
, sizeof(val
)) != MEMCACHED_SUCCESS
)
303 return MEMCACHED_UNKNOWN_READ_FAILURE
;
307 memcpy(buffer
, &val
, sizeof(val
));
310 case PROTOCOL_BINARY_CMD_VERSION
:
312 memset(buffer
, 0, buffer_length
);
313 if (bodylen
>= buffer_length
)
314 /* not enough space in buffer.. should not happen... */
315 return MEMCACHED_UNKNOWN_READ_FAILURE
;
317 safe_read(ptr
, buffer
, bodylen
);
320 case PROTOCOL_BINARY_CMD_FLUSH
:
321 case PROTOCOL_BINARY_CMD_QUIT
:
322 case PROTOCOL_BINARY_CMD_SET
:
323 case PROTOCOL_BINARY_CMD_ADD
:
324 case PROTOCOL_BINARY_CMD_REPLACE
:
325 case PROTOCOL_BINARY_CMD_APPEND
:
326 case PROTOCOL_BINARY_CMD_PREPEND
:
327 case PROTOCOL_BINARY_CMD_DELETE
:
329 WATCHPOINT_ASSERT(bodylen
== 0);
330 return MEMCACHED_SUCCESS
;
333 case PROTOCOL_BINARY_CMD_NOOP
:
335 WATCHPOINT_ASSERT(bodylen
== 0);
336 return MEMCACHED_END
;
339 case PROTOCOL_BINARY_CMD_STAT
:
342 return MEMCACHED_END
;
343 else if (bodylen
+ 1 > buffer_length
)
344 /* not enough space in buffer.. should not happen... */
345 return MEMCACHED_UNKNOWN_READ_FAILURE
;
348 size_t keylen
= header
.response
.keylen
;
349 memset(buffer
, 0, buffer_length
);
350 safe_read(ptr
, buffer
, keylen
);
351 safe_read(ptr
, buffer
+ keylen
+ 1, bodylen
- keylen
);
357 /* Command not implemented yet! */
358 WATCHPOINT_ASSERT(0);
359 memcached_io_reset(ptr
);
360 return MEMCACHED_PROTOCOL_ERROR
;
364 else if (header
.response
.bodylen
)
366 /* What should I do with the error message??? just discard it for now */
367 char buffer
[SMALL_STRING_LEN
];
370 size_t nr
= (bodylen
> SMALL_STRING_LEN
) ? SMALL_STRING_LEN
: bodylen
;
371 safe_read(ptr
, buffer
, nr
);
376 memcached_return rc
= MEMCACHED_SUCCESS
;
377 unlikely(header
.response
.status
!= 0)
378 switch (header
.response
.status
)
380 case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
:
381 rc
= MEMCACHED_NOTFOUND
;
383 case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
:
384 rc
= MEMCACHED_DATA_EXISTS
;
386 case PROTOCOL_BINARY_RESPONSE_E2BIG
:
387 case PROTOCOL_BINARY_RESPONSE_EINVAL
:
388 case PROTOCOL_BINARY_RESPONSE_NOT_STORED
:
389 case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND
:
390 case PROTOCOL_BINARY_RESPONSE_ENOMEM
:
392 /* @todo fix the error mappings */
393 rc
= MEMCACHED_PROTOCOL_ERROR
;