4 memcached_response() is used to determine the return result
5 from an issued command.
9 #include "memcached_io.h"
11 static memcached_return
textual_read_one_response(memcached_server_st
*ptr
,
12 char *buffer
, size_t buffer_length
,
13 memcached_result_st
*result
);
14 static memcached_return
binary_read_one_response(memcached_server_st
*ptr
,
15 char *buffer
, size_t buffer_length
,
16 memcached_result_st
*result
);
18 memcached_return
memcached_read_one_response(memcached_server_st
*ptr
,
19 char *buffer
, size_t buffer_length
,
20 memcached_result_st
*result
)
22 memcached_server_response_decrement(ptr
);
25 if (ptr
->root
->flags
& MEM_BINARY_PROTOCOL
)
26 rc
= binary_read_one_response(ptr
, buffer
, buffer_length
, result
);
28 rc
= textual_read_one_response(ptr
, buffer
, buffer_length
, result
);
30 unlikely(rc
== MEMCACHED_UNKNOWN_READ_FAILURE
||
31 rc
== MEMCACHED_PROTOCOL_ERROR
||
32 rc
== MEMCACHED_CLIENT_ERROR
||
33 rc
== MEMCACHED_MEMORY_ALLOCATION_FAILURE
)
34 memcached_io_reset(ptr
);
39 memcached_return
memcached_response(memcached_server_st
*ptr
,
40 char *buffer
, size_t buffer_length
,
41 memcached_result_st
*result
)
43 /* We may have old commands in the buffer not set, first purge */
44 if (ptr
->root
->flags
& MEM_NO_BLOCK
)
45 (void)memcached_io_write(ptr
, NULL
, 0, 1);
48 * The previous implementation purged all pending requests and just
49 * returned the last one. Purge all pending messages to ensure backwards
52 if ((ptr
->root
->flags
& MEM_BINARY_PROTOCOL
) == 0)
53 while (memcached_server_response_count(ptr
) > 1) {
54 memcached_return rc
= memcached_read_one_response(ptr
, buffer
, buffer_length
, result
);
56 unlikely (rc
!= MEMCACHED_END
&&
57 rc
!= MEMCACHED_STORED
&&
58 rc
!= MEMCACHED_SUCCESS
&&
59 rc
!= MEMCACHED_STAT
&&
60 rc
!= MEMCACHED_DELETED
&&
61 rc
!= MEMCACHED_NOTFOUND
&&
62 rc
!= MEMCACHED_NOTSTORED
&&
63 rc
!= MEMCACHED_DATA_EXISTS
)
67 return memcached_read_one_response(ptr
, buffer
, buffer_length
, result
);
70 static memcached_return
memcached_readline(memcached_server_st
*ptr
,
74 bool line_complete
= false;
75 char *buffer_ptr
= buffer
;
78 while (!line_complete
)
80 if (memcached_io_read(ptr
, buffer_ptr
, 1) != 1)
81 return MEMCACHED_UNKNOWN_READ_FAILURE
;
83 WATCHPOINT_ASSERT(*buffer_ptr
!= '\0');
84 if (*buffer_ptr
== '\n')
93 return MEMCACHED_PROTOCOL_ERROR
;
96 return MEMCACHED_SUCCESS
;
99 static memcached_return
textual_read_one_response(memcached_server_st
*ptr
,
100 char *buffer
, size_t buffer_length
,
101 memcached_result_st
*result
)
103 memcached_return rc
=memcached_readline(ptr
, buffer
, buffer_length
);
104 if (rc
!= MEMCACHED_SUCCESS
)
109 case 'V': /* VALUE || VERSION */
110 if (buffer
[1] == 'A') /* VALUE */
114 /* We add back in one because we will need to search for END */
115 memcached_server_response_increment(ptr
);
117 rc
= value_fetch(ptr
, buffer
, result
);
119 rc
= value_fetch(ptr
, buffer
, &ptr
->root
->result
);
123 else if (buffer
[1] == 'E') /* VERSION */
125 return MEMCACHED_SUCCESS
;
129 WATCHPOINT_STRING(buffer
);
130 WATCHPOINT_ASSERT(0);
131 return MEMCACHED_UNKNOWN_READ_FAILURE
;
134 return MEMCACHED_SUCCESS
;
135 case 'S': /* STORED STATS SERVER_ERROR */
137 if (buffer
[2] == 'A') /* STORED STATS */
139 memcached_server_response_increment(ptr
);
140 return MEMCACHED_STAT
;
142 else if (buffer
[1] == 'E')
143 return MEMCACHED_SERVER_ERROR
;
144 else if (buffer
[1] == 'T')
145 return MEMCACHED_STORED
;
148 WATCHPOINT_STRING(buffer
);
149 WATCHPOINT_ASSERT(0);
150 return MEMCACHED_UNKNOWN_READ_FAILURE
;
153 case 'D': /* DELETED */
154 return MEMCACHED_DELETED
;
155 case 'N': /* NOT_FOUND */
157 if (buffer
[4] == 'F')
158 return MEMCACHED_NOTFOUND
;
159 else if (buffer
[4] == 'S')
160 return MEMCACHED_NOTSTORED
;
162 return MEMCACHED_UNKNOWN_READ_FAILURE
;
164 case 'E': /* PROTOCOL ERROR or END */
166 if (buffer
[1] == 'N')
167 return MEMCACHED_END
;
168 else if (buffer
[1] == 'R')
169 return MEMCACHED_PROTOCOL_ERROR
;
170 else if (buffer
[1] == 'X')
171 return MEMCACHED_DATA_EXISTS
;
173 return MEMCACHED_UNKNOWN_READ_FAILURE
;
175 case 'C': /* CLIENT ERROR */
176 return MEMCACHED_CLIENT_ERROR
;
179 unsigned long long auto_return_value
;
181 if (sscanf(buffer
, "%llu", &auto_return_value
) == 1)
182 return MEMCACHED_SUCCESS
;
184 return MEMCACHED_UNKNOWN_READ_FAILURE
;
188 return MEMCACHED_SUCCESS
;
191 char *memcached_result_value(memcached_result_st
*ptr
)
193 memcached_string_st
*sptr
= &ptr
->value
;
194 return memcached_string_value(sptr
);
197 size_t memcached_result_length(memcached_result_st
*ptr
)
199 memcached_string_st
*sptr
= &ptr
->value
;
200 return memcached_string_length(sptr
);
203 static memcached_return
binary_read_one_response(memcached_server_st
*ptr
,
204 char *buffer
, size_t buffer_length
,
205 memcached_result_st
*result
)
207 protocol_binary_response_header header
;
209 unlikely (memcached_safe_read(ptr
, &header
.bytes
,
210 sizeof(header
.bytes
)) != MEMCACHED_SUCCESS
)
211 return MEMCACHED_UNKNOWN_READ_FAILURE
;
213 unlikely (header
.response
.magic
!= PROTOCOL_BINARY_RES
)
214 return MEMCACHED_PROTOCOL_ERROR
;
217 ** Convert the header to host local endian!
219 header
.response
.keylen
= ntohs(header
.response
.keylen
);
220 header
.response
.status
= ntohs(header
.response
.status
);
221 header
.response
.bodylen
= ntohl(header
.response
.bodylen
);
222 header
.response
.cas
= ntohll(header
.response
.cas
);
223 uint32_t bodylen
= header
.response
.bodylen
;
225 if (header
.response
.status
== 0)
227 switch (header
.response
.opcode
)
229 case PROTOCOL_BINARY_CMD_GETK
:
230 case PROTOCOL_BINARY_CMD_GETKQ
:
232 uint16_t keylen
= header
.response
.keylen
;
233 memcached_result_reset(result
);
234 result
->cas
= header
.response
.cas
;
236 if (memcached_safe_read(ptr
, &result
->flags
,
237 sizeof (result
->flags
)) != MEMCACHED_SUCCESS
)
238 return MEMCACHED_UNKNOWN_READ_FAILURE
;
240 result
->flags
= ntohl(result
->flags
);
241 bodylen
-= header
.response
.extlen
;
243 result
->key_length
= keylen
;
244 if (memcached_safe_read(ptr
, result
->key
, keylen
) != MEMCACHED_SUCCESS
)
245 return MEMCACHED_UNKNOWN_READ_FAILURE
;
248 if (memcached_string_check(&result
->value
,
249 bodylen
) != MEMCACHED_SUCCESS
)
250 return MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
252 char *vptr
= memcached_string_value(&result
->value
);
253 if (memcached_safe_read(ptr
, vptr
, bodylen
) != MEMCACHED_SUCCESS
)
254 return MEMCACHED_UNKNOWN_READ_FAILURE
;
256 memcached_string_set_length(&result
->value
, bodylen
);
259 case PROTOCOL_BINARY_CMD_INCREMENT
:
260 case PROTOCOL_BINARY_CMD_DECREMENT
:
262 if (bodylen
!= sizeof(uint64_t) || buffer_length
!= sizeof(uint64_t))
263 return MEMCACHED_PROTOCOL_ERROR
;
265 WATCHPOINT_ASSERT(bodylen
== buffer_length
);
267 if (memcached_safe_read(ptr
, &val
, sizeof(val
)) != MEMCACHED_SUCCESS
)
268 return MEMCACHED_UNKNOWN_READ_FAILURE
;
271 memcpy(buffer
, &val
, sizeof(val
));
274 case PROTOCOL_BINARY_CMD_VERSION
:
276 memset(buffer
, 0, buffer_length
);
277 if (bodylen
>= buffer_length
)
278 /* not enough space in buffer.. should not happen... */
279 return MEMCACHED_UNKNOWN_READ_FAILURE
;
280 else if (memcached_safe_read(ptr
, buffer
, bodylen
) != MEMCACHED_SUCCESS
)
281 return MEMCACHED_UNKNOWN_READ_FAILURE
;
284 case PROTOCOL_BINARY_CMD_FLUSH
:
285 case PROTOCOL_BINARY_CMD_QUIT
:
286 case PROTOCOL_BINARY_CMD_SET
:
287 case PROTOCOL_BINARY_CMD_ADD
:
288 case PROTOCOL_BINARY_CMD_REPLACE
:
289 case PROTOCOL_BINARY_CMD_APPEND
:
290 case PROTOCOL_BINARY_CMD_PREPEND
:
291 case PROTOCOL_BINARY_CMD_DELETE
:
293 WATCHPOINT_ASSERT(bodylen
== 0);
294 return MEMCACHED_SUCCESS
;
297 case PROTOCOL_BINARY_CMD_NOOP
:
299 WATCHPOINT_ASSERT(bodylen
== 0);
300 return MEMCACHED_END
;
303 case PROTOCOL_BINARY_CMD_STAT
:
306 return MEMCACHED_END
;
307 else if (bodylen
+ 1 > buffer_length
)
308 /* not enough space in buffer.. should not happen... */
309 return MEMCACHED_UNKNOWN_READ_FAILURE
;
312 size_t keylen
= header
.response
.keylen
;
313 memset(buffer
, 0, buffer_length
);
314 if (memcached_safe_read(ptr
, buffer
, keylen
) != MEMCACHED_SUCCESS
||
315 memcached_safe_read(ptr
, buffer
+ keylen
+ 1,
316 bodylen
- keylen
) != MEMCACHED_SUCCESS
)
317 return MEMCACHED_UNKNOWN_READ_FAILURE
;
323 /* Command not implemented yet! */
324 WATCHPOINT_ASSERT(0);
325 return MEMCACHED_PROTOCOL_ERROR
;
329 else if (header
.response
.bodylen
)
331 /* What should I do with the error message??? just discard it for now */
332 char buffer
[SMALL_STRING_LEN
];
335 size_t nr
= (bodylen
> SMALL_STRING_LEN
) ? SMALL_STRING_LEN
: bodylen
;
336 if (memcached_safe_read(ptr
, buffer
, nr
) != MEMCACHED_SUCCESS
)
337 return MEMCACHED_UNKNOWN_READ_FAILURE
;
342 memcached_return rc
= MEMCACHED_SUCCESS
;
343 unlikely(header
.response
.status
!= 0)
344 switch (header
.response
.status
)
346 case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
:
347 rc
= MEMCACHED_NOTFOUND
;
349 case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
:
350 rc
= MEMCACHED_DATA_EXISTS
;
352 case PROTOCOL_BINARY_RESPONSE_E2BIG
:
353 case PROTOCOL_BINARY_RESPONSE_EINVAL
:
354 case PROTOCOL_BINARY_RESPONSE_NOT_STORED
:
355 case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND
:
356 case PROTOCOL_BINARY_RESPONSE_ENOMEM
:
358 /* @todo fix the error mappings */
359 rc
= MEMCACHED_PROTOCOL_ERROR
;