1 /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
3 * This file contains an implementation of the callback interface for level 1
4 * in the protocol library. If you compare the implementation with the one
5 * in interface_v0.c you will see that this implementation is much easier and
6 * hides all of the protocol logic and let you focus on the application
7 * logic. One "problem" with this layer is that it is synchronous, so that
8 * you will not receive the next command before a answer to the previous
9 * command is being sent.
13 #include <sys/types.h>
21 #include <libmemcached/protocol_handler.h>
22 #include <libmemcached/byteorder.h>
25 static protocol_binary_response_status
add_handler(const void *cookie
,
35 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
36 struct item
* item
= get_item(key
, keylen
);
39 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
42 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
53 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
59 static protocol_binary_response_status
append_handler(const void *cookie
,
68 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
70 struct item
*item
= get_item(key
, keylen
);
75 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
77 else if (cas
!= 0 && cas
!= item
->cas
)
79 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
81 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
82 item
->flags
, item
->exp
)) == NULL
)
85 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
89 memcpy(nitem
->data
, item
->data
, item
->size
);
90 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
92 delete_item(key
, keylen
);
94 *result_cas
= nitem
->cas
;
101 static protocol_binary_response_status
decrement_handler(const void *cookie
,
108 uint64_t *result_cas
) {
110 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
111 uint64_t val
= initial
;
112 struct item
*item
= get_item(key
, keylen
);
116 if (delta
> *(uint64_t*)item
->data
)
119 val
= *(uint64_t*)item
->data
- delta
;
121 expiration
= (uint32_t)item
->exp
;
123 delete_item(key
, keylen
);
126 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
129 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
133 memcpy(item
->data
, &val
, sizeof(val
));
136 *result_cas
= item
->cas
;
143 static protocol_binary_response_status
delete_handler(const void *cookie
,
148 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
152 struct item
*item
= get_item(key
, keylen
);
155 if (item
->cas
!= cas
)
158 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
164 if (!delete_item(key
, keylen
))
166 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
173 static protocol_binary_response_status
flush_handler(const void *cookie
,
178 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
181 static protocol_binary_response_status
get_handler(const void *cookie
,
184 memcached_binary_protocol_get_response_handler response_handler
) {
185 struct item
*item
= get_item(key
, keylen
);
189 return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
192 protocol_binary_response_status rc
;
193 rc
= response_handler(cookie
, key
, (uint16_t)keylen
,
194 item
->data
, (uint32_t)item
->size
, item
->flags
,
200 static protocol_binary_response_status
increment_handler(const void *cookie
,
207 uint64_t *result_cas
) {
209 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
210 uint64_t val
= initial
;
211 struct item
*item
= get_item(key
, keylen
);
215 val
= (*(uint64_t*)item
->data
) + delta
;
216 expiration
= (uint32_t)item
->exp
;
218 delete_item(key
, keylen
);
221 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
224 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
228 char buffer
[1024] = {0};
229 memcpy(buffer
, key
, keylen
);
230 memcpy(item
->data
, &val
, sizeof(val
));
233 *result_cas
= item
->cas
;
240 static protocol_binary_response_status
noop_handler(const void *cookie
) {
242 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
245 static protocol_binary_response_status
prepend_handler(const void *cookie
,
251 uint64_t *result_cas
) {
253 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
255 struct item
*item
= get_item(key
, keylen
);
256 struct item
*nitem
= NULL
;
260 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
262 else if (cas
!= 0 && cas
!= item
->cas
)
264 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
266 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
267 item
->flags
, item
->exp
)) == NULL
)
269 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
273 memcpy(nitem
->data
, val
, vallen
);
274 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
277 delete_item(key
, keylen
);
279 *result_cas
= nitem
->cas
;
291 static protocol_binary_response_status
quit_handler(const void *cookie
) {
293 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
296 static protocol_binary_response_status
replace_handler(const void *cookie
,
304 uint64_t *result_cas
) {
306 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
307 struct item
* item
= get_item(key
, keylen
);
311 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
313 else if (cas
== 0 || cas
== item
->cas
)
316 delete_item(key
, keylen
);
317 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
320 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
325 *result_cas
= item
->cas
;
331 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
338 static protocol_binary_response_status
set_handler(const void *cookie
,
346 uint64_t *result_cas
) {
348 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
352 struct item
* item
= get_item(key
, keylen
);
353 if (item
!= NULL
&& cas
!= item
->cas
)
355 /* Invalid CAS value */
357 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
361 delete_item(key
, keylen
);
362 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
365 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
370 *result_cas
= item
->cas
;
377 static protocol_binary_response_status
stat_handler(const void *cookie
,
380 memcached_binary_protocol_stat_response_handler response_handler
) {
383 /* Just return an empty packet */
384 return response_handler(cookie
, NULL
, 0, NULL
, 0);
387 static protocol_binary_response_status
version_handler(const void *cookie
,
388 memcached_binary_protocol_version_response_handler response_handler
) {
389 const char *version
= "0.1.1";
390 return response_handler(cookie
, version
, (uint32_t)strlen(version
));
393 memcached_binary_protocol_callback_st interface_v1_impl
= {
394 .interface_version
= MEMCACHED_PROTOCOL_HANDLER_V1
,
397 .append
= append_handler
,
398 .decrement
= decrement_handler
,
399 .delete= delete_handler
,
400 .flush
= flush_handler
,
402 .increment
= increment_handler
,
404 .prepend
= prepend_handler
,
406 .replace
= replace_handler
,
409 .version
= version_handler