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 uint64_t val
= initial
;
109 struct item
*item
= get_item(key
, keylen
);
113 if (delta
> *(uint64_t*)item
->data
)
116 val
= *(uint64_t*)item
->data
- delta
;
118 expiration
= (uint32_t)item
->exp
;
119 delete_item(key
, keylen
);
122 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, expiration
);
125 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
129 memcpy(item
->data
, &val
, sizeof(val
));
132 *result_cas
= item
->cas
;
138 static protocol_binary_response_status
delete_handler(const void *cookie
,
143 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
147 struct item
*item
= get_item(key
, keylen
);
148 if (item
!= NULL
&& item
->cas
!= cas
)
150 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
154 if (!delete_item(key
, keylen
))
156 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
163 static protocol_binary_response_status
flush_handler(const void *cookie
,
168 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
171 static protocol_binary_response_status
get_handler(const void *cookie
,
174 memcached_binary_protocol_get_response_handler response_handler
) {
175 struct item
*item
= get_item(key
, keylen
);
179 return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
182 return response_handler(cookie
, key
, (uint16_t)keylen
,
183 item
->data
, (uint32_t)item
->size
, item
->flags
,
187 static protocol_binary_response_status
increment_handler(const void *cookie
,
194 uint64_t *result_cas
) {
196 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
197 uint64_t val
= initial
;
198 struct item
*item
= get_item(key
, keylen
);
202 val
= (*(uint64_t*)item
->data
) + delta
;
203 expiration
= (uint32_t)item
->exp
;
204 delete_item(key
, keylen
);
207 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, expiration
);
210 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
214 char buffer
[1024] = {0};
215 memcpy(buffer
, key
, keylen
);
216 memcpy(item
->data
, &val
, sizeof(val
));
219 *result_cas
= item
->cas
;
225 static protocol_binary_response_status
noop_handler(const void *cookie
) {
227 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
230 static protocol_binary_response_status
prepend_handler(const void *cookie
,
236 uint64_t *result_cas
) {
238 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
240 struct item
*item
= get_item(key
, keylen
);
244 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
246 else if (cas
!= 0 && cas
!= item
->cas
)
248 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
250 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
251 item
->flags
, item
->exp
)) == NULL
)
253 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
257 memcpy(nitem
->data
, val
, vallen
);
258 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
259 delete_item(key
, keylen
);
261 *result_cas
= nitem
->cas
;
267 static protocol_binary_response_status
quit_handler(const void *cookie
) {
269 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
272 static protocol_binary_response_status
replace_handler(const void *cookie
,
280 uint64_t *result_cas
) {
282 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
283 struct item
* item
= get_item(key
, keylen
);
287 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
289 else if (cas
== 0 || cas
== item
->cas
)
291 delete_item(key
, keylen
);
292 item
= create_item(key
, keylen
, data
, datalen
, flags
, exptime
);
295 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
300 *result_cas
= item
->cas
;
305 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
311 static protocol_binary_response_status
set_handler(const void *cookie
,
319 uint64_t *result_cas
) {
321 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
325 struct item
* item
= get_item(key
, keylen
);
326 if (item
!= NULL
&& cas
!= item
->cas
)
328 /* Invalid CAS value */
329 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
333 delete_item(key
, keylen
);
334 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, exptime
);
337 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
342 *result_cas
= item
->cas
;
348 static protocol_binary_response_status
stat_handler(const void *cookie
,
351 memcached_binary_protocol_stat_response_handler response_handler
) {
354 /* Just return an empty packet */
355 return response_handler(cookie
, NULL
, 0, NULL
, 0);
358 static protocol_binary_response_status
version_handler(const void *cookie
,
359 memcached_binary_protocol_version_response_handler response_handler
) {
360 const char *version
= "0.1.1";
361 return response_handler(cookie
, version
, (uint32_t)strlen(version
));
364 struct memcached_binary_protocol_callback_st interface_v1_impl
= {
365 .interface_version
= 1,
368 .append
= append_handler
,
369 .decrement
= decrement_handler
,
370 .delete= delete_handler
,
371 .flush
= flush_handler
,
373 .increment
= increment_handler
,
375 .prepend
= prepend_handler
,
377 .replace
= replace_handler
,
380 .version
= version_handler