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
, exptime
);
44 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
54 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
60 static protocol_binary_response_status
append_handler(const void *cookie
,
66 uint64_t *result_cas
) {
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
)
84 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
88 memcpy(nitem
->data
, item
->data
, item
->size
);
89 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
90 delete_item(key
, keylen
);
92 *result_cas
= nitem
->cas
;
98 static protocol_binary_response_status
decrement_handler(const void *cookie
,
105 uint64_t *result_cas
) {
107 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
108 struct item
*item
= get_item(key
, keylen
);
112 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, expiration
);
115 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
119 memcpy(item
->data
, &initial
, sizeof(initial
));
122 *result_cas
= item
->cas
;
127 if (delta
> *(uint64_t*)item
->data
)
129 *(uint64_t*)item
->data
= 0;
133 *(uint64_t*)item
->data
-= delta
;
135 *result
= (*(uint64_t*)item
->data
);
142 static protocol_binary_response_status
delete_handler(const void *cookie
,
147 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
151 struct item
*item
= get_item(key
, keylen
);
152 if (item
!= NULL
&& item
->cas
!= cas
)
154 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
158 if (!delete_item(key
, keylen
))
160 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
167 static protocol_binary_response_status
flush_handler(const void *cookie
,
172 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
175 static protocol_binary_response_status
get_handler(const void *cookie
,
178 memcached_binary_protocol_get_response_handler response_handler
) {
179 struct item
*item
= get_item(key
, keylen
);
183 return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
186 return response_handler(cookie
, key
, (uint16_t)keylen
,
187 item
->data
, (uint32_t)item
->size
, item
->flags
,
191 static protocol_binary_response_status
increment_handler(const void *cookie
,
198 uint64_t *result_cas
) {
200 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
201 struct item
*item
= get_item(key
, keylen
);
205 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, expiration
);
208 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
212 memcpy(item
->data
, &initial
, sizeof(initial
));
215 *result_cas
= item
->cas
;
220 (*(uint64_t*)item
->data
) += delta
;
221 *result
= (*(uint64_t*)item
->data
);
223 *result_cas
= item
->cas
;
229 static protocol_binary_response_status
noop_handler(const void *cookie
) {
231 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
234 static protocol_binary_response_status
prepend_handler(const void *cookie
,
240 uint64_t *result_cas
) {
242 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
244 struct item
*item
= get_item(key
, keylen
);
248 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
250 else if (cas
!= 0 && cas
!= item
->cas
)
252 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
254 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
255 item
->flags
, item
->exp
)) == NULL
)
257 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
261 memcpy(nitem
->data
, val
, vallen
);
262 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
263 delete_item(key
, keylen
);
265 *result_cas
= nitem
->cas
;
271 static protocol_binary_response_status
quit_handler(const void *cookie
) {
273 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
276 static protocol_binary_response_status
replace_handler(const void *cookie
,
284 uint64_t *result_cas
) {
286 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
287 struct item
* item
= get_item(key
, keylen
);
291 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
293 else if (cas
== 0 || cas
== item
->cas
)
295 delete_item(key
, keylen
);
296 item
= create_item(key
, keylen
, data
, datalen
, flags
, exptime
);
299 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
304 *result_cas
= item
->cas
;
309 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
315 static protocol_binary_response_status
set_handler(const void *cookie
,
323 uint64_t *result_cas
) {
325 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
329 struct item
* item
= get_item(key
, keylen
);
330 if (item
!= NULL
&& cas
!= item
->cas
)
332 /* Invalid CAS value */
333 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
337 delete_item(key
, keylen
);
338 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, exptime
);
341 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
346 *result_cas
= item
->cas
;
352 static protocol_binary_response_status
stat_handler(const void *cookie
,
355 memcached_binary_protocol_stat_response_handler response_handler
) {
358 /* Just return an empty packet */
359 return response_handler(cookie
, NULL
, 0, NULL
, 0);
362 static protocol_binary_response_status
version_handler(const void *cookie
,
363 memcached_binary_protocol_version_response_handler response_handler
) {
364 const char *version
= "0.1.1";
365 return response_handler(cookie
, version
, (uint32_t)strlen(version
));
368 struct memcached_binary_protocol_callback_st interface_v1_impl
= {
369 .interface_version
= 1,
372 .append
= append_handler
,
373 .decrement
= decrement_handler
,
374 .delete= delete_handler
,
375 .flush
= flush_handler
,
377 .increment
= increment_handler
,
379 .prepend
= prepend_handler
,
381 .replace
= replace_handler
,
384 .version
= version_handler