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.cc 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.
11 #include "mem_config.h"
19 #include <sys/types.h>
23 #include <libmemcachedprotocol-0.0/handler.h>
24 #include <example/byteorder.h>
25 #include "example/memcached_light.h"
26 #include "example/storage.h"
27 #include "util/log.hpp"
29 static datadifferential::util::log_info_st
*log_file
= NULL
;
31 static protocol_binary_response_status
add_handler(const void *cookie
,
41 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
42 struct item
* item
= get_item(key
, keylen
);
45 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
48 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
59 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
65 static protocol_binary_response_status
append_handler(const void *cookie
,
74 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
76 struct item
*item
= get_item(key
, keylen
);
81 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
83 else if (cas
!= 0 && cas
!= item
->cas
)
85 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
87 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
88 item
->flags
, item
->exp
)) == NULL
)
91 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
95 memcpy(nitem
->data
, item
->data
, item
->size
);
96 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
98 delete_item(key
, keylen
);
100 *result_cas
= nitem
->cas
;
107 static protocol_binary_response_status
decrement_handler(const void *cookie
,
114 uint64_t *result_cas
) {
116 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
117 uint64_t val
= initial
;
118 struct item
*item
= get_item(key
, keylen
);
122 if (delta
> *(uint64_t*)item
->data
)
125 val
= *(uint64_t*)item
->data
- delta
;
127 expiration
= (uint32_t)item
->exp
;
129 delete_item(key
, keylen
);
132 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
135 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
139 memcpy(item
->data
, &val
, sizeof(val
));
142 *result_cas
= item
->cas
;
149 static protocol_binary_response_status
delete_handler(const void *, // cookie
154 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
158 struct item
*item
= get_item(key
, keylen
);
161 if (item
->cas
!= cas
)
164 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
170 if (!delete_item(key
, keylen
))
172 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
179 static protocol_binary_response_status
flush_handler(const void * /* cookie */, uint32_t /* when */)
181 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
184 static protocol_binary_response_status
get_handler(const void *cookie
,
187 memcached_binary_protocol_get_response_handler response_handler
) {
188 struct item
*item
= get_item(key
, keylen
);
192 return PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
195 protocol_binary_response_status rc
;
196 rc
= response_handler(cookie
, key
, (uint16_t)keylen
,
197 item
->data
, (uint32_t)item
->size
, item
->flags
,
203 static protocol_binary_response_status
increment_handler(const void *cookie
,
210 uint64_t *result_cas
) {
212 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
213 uint64_t val
= initial
;
214 struct item
*item
= get_item(key
, keylen
);
218 val
= (*(uint64_t*)item
->data
) + delta
;
219 expiration
= (uint32_t)item
->exp
;
221 delete_item(key
, keylen
);
224 item
= create_item(key
, keylen
, NULL
, sizeof(initial
), 0, (time_t)expiration
);
227 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
231 char buffer
[1024] = {0};
232 memcpy(buffer
, key
, keylen
);
233 memcpy(item
->data
, &val
, sizeof(val
));
236 *result_cas
= item
->cas
;
243 static protocol_binary_response_status
noop_handler(const void *cookie
) {
245 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
248 static protocol_binary_response_status
prepend_handler(const void *cookie
,
254 uint64_t *result_cas
) {
256 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
258 struct item
*item
= get_item(key
, keylen
);
259 struct item
*nitem
= NULL
;
263 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
265 else if (cas
!= 0 && cas
!= item
->cas
)
267 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
269 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
270 item
->flags
, item
->exp
)) == NULL
)
272 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
276 memcpy(nitem
->data
, val
, vallen
);
277 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
280 delete_item(key
, keylen
);
282 *result_cas
= nitem
->cas
;
294 static protocol_binary_response_status
quit_handler(const void *) //cookie
296 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
299 static protocol_binary_response_status
replace_handler(const void *, // cookie
307 uint64_t *result_cas
)
309 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
310 struct item
* item
= get_item(key
, keylen
);
314 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
316 else if (cas
== 0 || cas
== item
->cas
)
319 delete_item(key
, keylen
);
320 item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
323 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
328 *result_cas
= item
->cas
;
334 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
341 static protocol_binary_response_status
set_handler(const void *cookie
,
349 uint64_t *result_cas
) {
351 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
355 struct item
* item
= get_item(key
, keylen
);
356 if (item
!= NULL
&& cas
!= item
->cas
)
358 /* Invalid CAS value */
360 return PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
364 delete_item(key
, keylen
);
365 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, (time_t)exptime
);
368 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
373 *result_cas
= item
->cas
;
380 static protocol_binary_response_status
stat_handler(const void *cookie
,
383 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
)
392 const char *version
= "0.1.1";
393 return response_handler(cookie
, version
, (uint32_t)strlen(version
));
396 memcached_binary_protocol_callback_st interface_v1_impl
;
398 void initialize_interface_v1_handler(datadifferential::util::log_info_st
& arg
)
401 memset(&interface_v1_impl
, 0, sizeof(memcached_binary_protocol_callback_st
));
403 interface_v1_impl
.interface_version
= MEMCACHED_PROTOCOL_HANDLER_V1
;
404 interface_v1_impl
.interface
.v1
.add
= add_handler
;
405 interface_v1_impl
.interface
.v1
.append
= append_handler
;
406 interface_v1_impl
.interface
.v1
.decrement
= decrement_handler
;
407 interface_v1_impl
.interface
.v1
.delete_object
= delete_handler
;
408 interface_v1_impl
.interface
.v1
.flush_object
= flush_handler
;
409 interface_v1_impl
.interface
.v1
.get
= get_handler
;
410 interface_v1_impl
.interface
.v1
.increment
= increment_handler
;
411 interface_v1_impl
.interface
.v1
.noop
= noop_handler
;
412 interface_v1_impl
.interface
.v1
.prepend
= prepend_handler
;
413 interface_v1_impl
.interface
.v1
.quit
= quit_handler
;
414 interface_v1_impl
.interface
.v1
.replace
= replace_handler
;
415 interface_v1_impl
.interface
.v1
.set
= set_handler
;
416 interface_v1_impl
.interface
.v1
.stat
= stat_handler
;
417 interface_v1_impl
.interface
.v1
.version
= version_handler
;