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>
14 #include <sys/socket.h>
16 #include <netinet/tcp.h>
24 #include <libmemcached/protocol_handler.h>
25 #include <libmemcached/byteorder.h>
28 static protocol_binary_response_status
add_handler(const void *cookie
,
38 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
39 struct item
* item
= get_item(key
, keylen
);
42 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
45 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
56 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
62 static protocol_binary_response_status
append_handler(const void *cookie
,
68 uint64_t *result_cas
) {
70 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
72 struct item
*item
= get_item(key
, keylen
);
77 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
79 else if (cas
!= 0 && cas
!= item
->cas
)
81 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
83 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
84 item
->flags
, item
->exp
)) == NULL
)
87 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
91 memcpy(nitem
->data
, item
->data
, item
->size
);
92 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
94 delete_item(key
, keylen
);
96 *result_cas
= nitem
->cas
;
103 static protocol_binary_response_status
decrement_handler(const void *cookie
,
110 uint64_t *result_cas
) {
112 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
113 uint64_t val
= initial
;
114 struct item
*item
= get_item(key
, keylen
);
118 if (delta
> *(uint64_t*)item
->data
)
121 val
= *(uint64_t*)item
->data
- delta
;
123 expiration
= (uint32_t)item
->exp
;
125 delete_item(key
, keylen
);
128 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
131 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
135 memcpy(item
->data
, &val
, sizeof(val
));
138 *result_cas
= item
->cas
;
145 static protocol_binary_response_status
delete_handler(const void *cookie
,
150 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
154 struct item
*item
= get_item(key
, keylen
);
157 if (item
->cas
!= cas
)
160 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
166 if (!delete_item(key
, keylen
))
168 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
175 static protocol_binary_response_status
flush_handler(const void *cookie
,
180 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
183 static protocol_binary_response_status
get_handler(const void *cookie
,
186 memcached_binary_protocol_get_response_handler response_handler
) {
187 struct item
*item
= get_item(key
, keylen
);
191 return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
194 protocol_binary_response_status rc
;
195 rc
= response_handler(cookie
, key
, (uint16_t)keylen
,
196 item
->data
, (uint32_t)item
->size
, item
->flags
,
202 static protocol_binary_response_status
increment_handler(const void *cookie
,
209 uint64_t *result_cas
) {
211 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
212 uint64_t val
= initial
;
213 struct item
*item
= get_item(key
, keylen
);
217 val
= (*(uint64_t*)item
->data
) + delta
;
218 expiration
= (uint32_t)item
->exp
;
220 delete_item(key
, keylen
);
223 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
226 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
230 char buffer
[1024] = {0};
231 memcpy(buffer
, key
, keylen
);
232 memcpy(item
->data
, &val
, sizeof(val
));
235 *result_cas
= item
->cas
;
242 static protocol_binary_response_status
noop_handler(const void *cookie
) {
244 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
247 static protocol_binary_response_status
prepend_handler(const void *cookie
,
253 uint64_t *result_cas
) {
255 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
257 struct item
*item
= get_item(key
, keylen
);
258 struct item
*nitem
= NULL
;
262 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
264 else if (cas
!= 0 && cas
!= item
->cas
)
266 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
268 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
269 item
->flags
, item
->exp
)) == NULL
)
271 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
275 memcpy(nitem
->data
, val
, vallen
);
276 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
279 delete_item(key
, keylen
);
281 *result_cas
= nitem
->cas
;
293 static protocol_binary_response_status
quit_handler(const void *cookie
) {
295 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
298 static protocol_binary_response_status
replace_handler(const void *cookie
,
306 uint64_t *result_cas
) {
308 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
309 struct item
* item
= get_item(key
, keylen
);
313 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
315 else if (cas
== 0 || cas
== item
->cas
)
318 delete_item(key
, keylen
);
319 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
322 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
327 *result_cas
= item
->cas
;
333 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
340 static protocol_binary_response_status
set_handler(const void *cookie
,
348 uint64_t *result_cas
) {
350 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
354 struct item
* item
= get_item(key
, keylen
);
355 if (item
!= NULL
&& cas
!= item
->cas
)
357 /* Invalid CAS value */
359 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
363 delete_item(key
, keylen
);
364 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
367 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
372 *result_cas
= item
->cas
;
379 static protocol_binary_response_status
stat_handler(const void *cookie
,
382 memcached_binary_protocol_stat_response_handler response_handler
) {
385 /* Just return an empty packet */
386 return response_handler(cookie
, NULL
, 0, NULL
, 0);
389 static protocol_binary_response_status
version_handler(const void *cookie
,
390 memcached_binary_protocol_version_response_handler response_handler
) {
391 const char *version
= "0.1.1";
392 return response_handler(cookie
, version
, (uint32_t)strlen(version
));
395 memcached_binary_protocol_callback_st interface_v1_impl
= {
396 .interface_version
= 1,
399 .append
= append_handler
,
400 .decrement
= decrement_handler
,
401 .delete= delete_handler
,
402 .flush
= flush_handler
,
404 .increment
= increment_handler
,
406 .prepend
= prepend_handler
,
408 .replace
= replace_handler
,
411 .version
= version_handler