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.
12 #include <sys/types.h>
13 #include <sys/socket.h>
15 #include <netinet/tcp.h>
23 #include <libmemcached/protocol_handler.h>
24 #include <libmemcached/byteorder.h>
27 static protocol_binary_response_status
add_handler(const void *cookie
,
37 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
38 struct item
* item
= get_item(key
, keylen
);
41 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
44 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
55 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
61 static protocol_binary_response_status
append_handler(const void *cookie
,
67 uint64_t *result_cas
) {
69 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
71 struct item
*item
= get_item(key
, keylen
);
76 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
78 else if (cas
!= 0 && cas
!= item
->cas
)
80 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
82 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
83 item
->flags
, item
->exp
)) == NULL
)
86 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
90 memcpy(nitem
->data
, item
->data
, item
->size
);
91 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
93 delete_item(key
, keylen
);
95 *result_cas
= nitem
->cas
;
102 static protocol_binary_response_status
decrement_handler(const void *cookie
,
109 uint64_t *result_cas
) {
111 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
112 uint64_t val
= initial
;
113 struct item
*item
= get_item(key
, keylen
);
117 if (delta
> *(uint64_t*)item
->data
)
120 val
= *(uint64_t*)item
->data
- delta
;
122 expiration
= (uint32_t)item
->exp
;
124 delete_item(key
, keylen
);
127 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
130 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
134 memcpy(item
->data
, &val
, sizeof(val
));
137 *result_cas
= item
->cas
;
144 static protocol_binary_response_status
delete_handler(const void *cookie
,
149 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
153 struct item
*item
= get_item(key
, keylen
);
156 if (item
->cas
!= cas
)
159 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
165 if (!delete_item(key
, keylen
))
167 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
174 static protocol_binary_response_status
flush_handler(const void *cookie
,
179 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
182 static protocol_binary_response_status
get_handler(const void *cookie
,
185 memcached_binary_protocol_get_response_handler response_handler
) {
186 struct item
*item
= get_item(key
, keylen
);
190 return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
193 protocol_binary_response_status rc
;
194 rc
= response_handler(cookie
, key
, (uint16_t)keylen
,
195 item
->data
, (uint32_t)item
->size
, item
->flags
,
201 static protocol_binary_response_status
increment_handler(const void *cookie
,
208 uint64_t *result_cas
) {
210 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
211 uint64_t val
= initial
;
212 struct item
*item
= get_item(key
, keylen
);
216 val
= (*(uint64_t*)item
->data
) + delta
;
217 expiration
= (uint32_t)item
->exp
;
219 delete_item(key
, keylen
);
222 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
225 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
229 char buffer
[1024] = {0};
230 memcpy(buffer
, key
, keylen
);
231 memcpy(item
->data
, &val
, sizeof(val
));
234 *result_cas
= item
->cas
;
241 static protocol_binary_response_status
noop_handler(const void *cookie
) {
243 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
246 static protocol_binary_response_status
prepend_handler(const void *cookie
,
252 uint64_t *result_cas
) {
254 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
256 struct item
*item
= get_item(key
, keylen
);
257 struct item
*nitem
= NULL
;
261 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
263 else if (cas
!= 0 && cas
!= item
->cas
)
265 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
267 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
268 item
->flags
, item
->exp
)) == NULL
)
270 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
274 memcpy(nitem
->data
, val
, vallen
);
275 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
278 delete_item(key
, keylen
);
280 *result_cas
= nitem
->cas
;
292 static protocol_binary_response_status
quit_handler(const void *cookie
) {
294 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
297 static protocol_binary_response_status
replace_handler(const void *cookie
,
305 uint64_t *result_cas
) {
307 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
308 struct item
* item
= get_item(key
, keylen
);
312 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
314 else if (cas
== 0 || cas
== item
->cas
)
317 delete_item(key
, keylen
);
318 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
321 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
326 *result_cas
= item
->cas
;
332 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
339 static protocol_binary_response_status
set_handler(const void *cookie
,
347 uint64_t *result_cas
) {
349 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
353 struct item
* item
= get_item(key
, keylen
);
354 if (item
!= NULL
&& cas
!= item
->cas
)
356 /* Invalid CAS value */
358 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
362 delete_item(key
, keylen
);
363 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
366 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
371 *result_cas
= item
->cas
;
378 static protocol_binary_response_status
stat_handler(const void *cookie
,
381 memcached_binary_protocol_stat_response_handler response_handler
) {
384 /* Just return an empty packet */
385 return response_handler(cookie
, NULL
, 0, NULL
, 0);
388 static protocol_binary_response_status
version_handler(const void *cookie
,
389 memcached_binary_protocol_version_response_handler response_handler
) {
390 const char *version
= "0.1.1";
391 return response_handler(cookie
, version
, (uint32_t)strlen(version
));
394 struct memcached_binary_protocol_callback_st interface_v1_impl
= {
395 .interface_version
= 1,
398 .append
= append_handler
,
399 .decrement
= decrement_handler
,
400 .delete= delete_handler
,
401 .flush
= flush_handler
,
403 .increment
= increment_handler
,
405 .prepend
= prepend_handler
,
407 .replace
= replace_handler
,
410 .version
= version_handler