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 0
4 * in the protocol library. You might want to have your copy of the protocol
5 * specification next to your coffee ;-)
8 #include "mem_config.h"
11 #include <sys/types.h>
19 #include <libmemcachedprotocol-0.0/handler.h>
20 #include <example/byteorder.h>
21 #include "example/memcached_light.h"
22 #include "example/storage.h"
23 #include "util/log.hpp"
26 using namespace datadifferential
;
28 static util::log_info_st
*log_file
= NULL
;
30 static protocol_binary_response_status
noop_command_handler(const void *cookie
,
31 protocol_binary_request_header
*header
,
32 memcached_binary_protocol_raw_response_handler response_handler
)
34 protocol_binary_response_no_extras response
;
35 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
37 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
38 response
.message
.header
.response
.opcode
= PROTOCOL_BINARY_CMD_NOOP
;
39 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
40 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
42 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
45 static protocol_binary_response_status
quit_command_handler(const void *cookie
,
46 protocol_binary_request_header
*header
,
47 memcached_binary_protocol_raw_response_handler response_handler
)
49 protocol_binary_response_no_extras response
;
50 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
52 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
53 response
.message
.header
.response
.opcode
= PROTOCOL_BINARY_CMD_QUIT
;
54 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
55 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
57 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_QUIT
)
59 response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
62 /* I need a better way to signal to close the connection */
63 return PROTOCOL_BINARY_RESPONSE_EINTERNAL
;
66 static protocol_binary_response_status
get_command_handler(const void *cookie
,
67 protocol_binary_request_header
*header
,
68 memcached_binary_protocol_raw_response_handler response_handler
)
70 uint8_t opcode
= header
->request
.opcode
;
71 union protocol_binary_response_get_un
{
72 protocol_binary_response_get response
;
76 protocol_binary_response_get_un msg
;
77 memset(&msg
, 0, sizeof(protocol_binary_response_get_un
));
79 msg
.response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
80 msg
.response
.message
.header
.response
.opcode
= opcode
;
81 msg
.response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
82 msg
.response
.message
.header
.response
.opaque
= header
->request
.opaque
;
84 struct item
*item
= get_item(header
+ 1, ntohs(header
->request
.keylen
));
87 msg
.response
.message
.body
.flags
= htonl(item
->flags
);
88 char *ptr
= (char*)(msg
.response
.bytes
+ sizeof(*header
) + 4);
90 msg
.response
.message
.header
.response
.cas
= example_htonll(item
->cas
);
91 if (opcode
== PROTOCOL_BINARY_CMD_GETK
|| opcode
== PROTOCOL_BINARY_CMD_GETKQ
)
93 memcpy(ptr
, item
->key
, item
->nkey
);
94 msg
.response
.message
.header
.response
.keylen
= htons((uint16_t)item
->nkey
);
96 bodysize
+= (uint32_t)item
->nkey
;
98 memcpy(ptr
, item
->data
, item
->size
);
99 bodysize
+= (uint32_t)item
->size
;
100 msg
.response
.message
.header
.response
.bodylen
= htonl(bodysize
);
101 msg
.response
.message
.header
.response
.extlen
= 4;
104 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&msg
);
106 else if (opcode
== PROTOCOL_BINARY_CMD_GET
|| opcode
== PROTOCOL_BINARY_CMD_GETK
)
108 msg
.response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
);
109 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&msg
);
112 /* Q shouldn't report a miss ;-) */
113 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
116 static protocol_binary_response_status
delete_command_handler(const void *cookie
,
117 protocol_binary_request_header
*header
,
118 memcached_binary_protocol_raw_response_handler response_handler
)
120 size_t keylen
= ntohs(header
->request
.keylen
);
122 char *key
= ((char*)header
) + sizeof(*header
);
123 protocol_binary_response_no_extras response
;
124 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
126 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
127 response
.message
.header
.response
.opcode
= header
->request
.opcode
;
128 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
130 if (delete_item(key
, keylen
) == false)
132 log_file
->write(util::VERBOSE_NOTICE
, "%s not found: %.*s", __func__
, keylen
, key
);
133 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
);
134 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
136 else if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_DELETE
)
138 log_file
->write(util::VERBOSE_NOTICE
, "%s not found: %.*s", __func__
, keylen
, key
);
139 /* DELETEQ doesn't want success response */
140 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
141 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
144 log_file
->write(util::VERBOSE_NOTICE
, "%s deleted: %.*s", __func__
, keylen
, key
);
146 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
149 static protocol_binary_response_status
flush_command_handler(const void *cookie
,
150 protocol_binary_request_header
*header
,
151 memcached_binary_protocol_raw_response_handler response_handler
)
153 uint8_t opcode
= header
->request
.opcode
;
155 /* @fixme sett inn when! */
158 if (opcode
== PROTOCOL_BINARY_CMD_FLUSH
)
160 protocol_binary_response_no_extras response
;
161 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
163 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
164 response
.message
.header
.response
.opcode
= opcode
;
165 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
166 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
168 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
171 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
174 static protocol_binary_response_status
arithmetic_command_handler(const void *cookie
,
175 protocol_binary_request_header
*header
,
176 memcached_binary_protocol_raw_response_handler response_handler
)
178 protocol_binary_request_incr
*req
= (protocol_binary_request_incr
*)header
;
179 protocol_binary_response_incr response
;
180 memset(&response
, 0, sizeof(protocol_binary_response_incr
));
182 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
183 response
.message
.header
.response
.opcode
= header
->request
.opcode
;
184 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
186 uint16_t keylen
= ntohs(header
->request
.keylen
);
187 uint64_t initial
= example_ntohll(req
->message
.body
.initial
);
188 uint64_t delta
= example_ntohll(req
->message
.body
.delta
);
189 uint32_t expiration
= ntohl(req
->message
.body
.expiration
);
191 void *key
= req
->bytes
+ sizeof(req
->bytes
);
192 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
194 uint64_t value
= initial
;
196 struct item
*item
= get_item(key
, keylen
);
199 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_INCREMENT
||
200 header
->request
.opcode
== PROTOCOL_BINARY_CMD_INCREMENTQ
)
202 value
= (*(uint64_t*)item
->data
) + delta
;
206 if (delta
> *(uint64_t*)item
->data
)
212 value
= *(uint64_t*)item
->data
- delta
;
215 expiration
= (uint32_t)item
->exp
;
219 delete_item(key
, keylen
);
222 item
= create_item(key
, keylen
, NULL
, sizeof(value
), flags
, (time_t)expiration
);
225 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
229 memcpy(item
->data
, &value
, sizeof(value
));
233 response
.message
.header
.response
.status
= htons(rval
);
234 if (rval
== PROTOCOL_BINARY_RESPONSE_SUCCESS
)
236 response
.message
.header
.response
.bodylen
= ntohl(8);
237 response
.message
.body
.value
= example_ntohll((*(uint64_t*)item
->data
));
238 response
.message
.header
.response
.cas
= example_ntohll(item
->cas
);
241 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_INCREMENTQ
||
242 header
->request
.opcode
== PROTOCOL_BINARY_CMD_DECREMENTQ
)
244 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
248 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
251 static protocol_binary_response_status
version_command_handler(const void *cookie
,
252 protocol_binary_request_header
*header
,
253 memcached_binary_protocol_raw_response_handler response_handler
)
255 const char *versionstring
= "1.0.0";
256 union protocol_binary_response_header_un
258 protocol_binary_response_header packet
;
262 protocol_binary_response_header_un response
;
263 memset(&response
, 0, sizeof(protocol_binary_response_header_un
));
265 response
.packet
.response
.magic
= PROTOCOL_BINARY_RES
;
266 response
.packet
.response
.opcode
= PROTOCOL_BINARY_CMD_VERSION
;
267 response
.packet
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
268 response
.packet
.response
.opaque
= header
->request
.opaque
;
269 response
.packet
.response
.cas
= 0;
270 response
.packet
.response
.bodylen
= htonl((uint32_t)strlen(versionstring
));
272 assert(sizeof(protocol_binary_response_header
) +strlen(versionstring
) <= 256);
273 memcpy(response
.buffer
+ sizeof(protocol_binary_response_header
), versionstring
, strlen(versionstring
));
275 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
278 static protocol_binary_response_status
concat_command_handler(const void *cookie
,
279 protocol_binary_request_header
*header
,
280 memcached_binary_protocol_raw_response_handler response_handler
)
282 protocol_binary_response_status rval
= PROTOCOL_BINARY_RESPONSE_SUCCESS
;
283 uint16_t keylen
= ntohs(header
->request
.keylen
);
284 uint64_t cas
= example_ntohll(header
->request
.cas
);
285 void *key
= header
+ 1;
286 uint32_t vallen
= ntohl(header
->request
.bodylen
) - keylen
;
287 void *val
= (char*)key
+ keylen
;
289 struct item
*item
= get_item(key
, keylen
);
290 struct item
*nitem
= NULL
;
294 rval
= PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
;
296 else if (cas
!= 0 && cas
!= item
->cas
)
298 rval
= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
;
300 else if ((nitem
= create_item(key
, keylen
, NULL
, item
->size
+ vallen
,
301 item
->flags
, item
->exp
)) == NULL
)
304 rval
= PROTOCOL_BINARY_RESPONSE_ENOMEM
;
308 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_APPEND
||
309 header
->request
.opcode
== PROTOCOL_BINARY_CMD_APPENDQ
)
311 memcpy(nitem
->data
, item
->data
, item
->size
);
312 memcpy(((char*)(nitem
->data
)) + item
->size
, val
, vallen
);
316 memcpy(nitem
->data
, val
, vallen
);
317 memcpy(((char*)(nitem
->data
)) + vallen
, item
->data
, item
->size
);
320 delete_item(key
, keylen
);
325 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_APPEND
||
326 header
->request
.opcode
== PROTOCOL_BINARY_CMD_PREPEND
)
328 protocol_binary_response_no_extras response
;
329 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
331 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
332 response
.message
.header
.response
.opcode
= header
->request
.opcode
;
333 response
.message
.header
.response
.status
= htons(rval
);
334 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
335 response
.message
.header
.response
.cas
= example_htonll(cas
);
337 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
344 static protocol_binary_response_status
set_command_handler(const void *cookie
,
345 protocol_binary_request_header
*header
,
346 memcached_binary_protocol_raw_response_handler response_handler
)
348 size_t keylen
= ntohs(header
->request
.keylen
);
349 size_t datalen
= ntohl(header
->request
.bodylen
) - keylen
- 8;
350 protocol_binary_request_replace
*request
= (protocol_binary_request_replace
*)header
;
351 uint32_t flags
= ntohl(request
->message
.body
.flags
);
352 time_t timeout
= (time_t)ntohl(request
->message
.body
.expiration
);
353 char *key
= ((char*)header
) + sizeof(*header
) + 8;
354 char *data
= key
+ keylen
;
356 protocol_binary_response_no_extras response
;
357 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
359 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
360 response
.message
.header
.response
.opcode
= header
->request
.opcode
;
361 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
362 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
364 if (header
->request
.cas
!= 0)
367 struct item
* item
= get_item(key
, keylen
);
370 if (item
->cas
!= example_ntohll(header
->request
.cas
))
373 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
);
374 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
380 delete_item(key
, keylen
);
381 struct item
* item
= create_item(key
, keylen
, data
, datalen
, flags
, timeout
);
384 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_ENOMEM
);
389 /* SETQ shouldn't return a message */
390 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_SET
)
392 response
.message
.header
.response
.cas
= example_htonll(item
->cas
);
394 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
398 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
401 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
404 static protocol_binary_response_status
add_command_handler(const void *cookie
,
405 protocol_binary_request_header
*header
,
406 memcached_binary_protocol_raw_response_handler response_handler
)
408 size_t keylen
= ntohs(header
->request
.keylen
);
409 size_t datalen
= ntohl(header
->request
.bodylen
) - keylen
- 8;
410 protocol_binary_request_add
*request
= (protocol_binary_request_add
*)header
;
411 uint32_t flags
= ntohl(request
->message
.body
.flags
);
412 time_t timeout
= (time_t)ntohl(request
->message
.body
.expiration
);
413 char *key
= ((char*)header
) + sizeof(*header
) + 8;
414 char *data
= key
+ keylen
;
416 protocol_binary_response_no_extras response
;
417 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
419 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
420 response
.message
.header
.response
.opcode
= header
->request
.opcode
;
421 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
422 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
424 struct item
* item
= get_item(key
, keylen
);
427 item
= create_item(key
, keylen
, data
, datalen
, flags
, timeout
);
429 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_ENOMEM
);
433 /* ADDQ shouldn't return a message */
434 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_ADD
)
436 response
.message
.header
.response
.cas
= example_htonll(item
->cas
);
438 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
441 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
447 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
);
450 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
453 static protocol_binary_response_status
replace_command_handler(const void *cookie
,
454 protocol_binary_request_header
*header
,
455 memcached_binary_protocol_raw_response_handler response_handler
)
457 size_t keylen
= ntohs(header
->request
.keylen
);
458 size_t datalen
= ntohl(header
->request
.bodylen
) - keylen
- 8;
459 protocol_binary_request_replace
*request
= (protocol_binary_request_replace
*)header
;
460 uint32_t flags
= ntohl(request
->message
.body
.flags
);
461 time_t timeout
= (time_t)ntohl(request
->message
.body
.expiration
);
462 char *key
= ((char*)header
) + sizeof(*header
) + 8;
463 char *data
= key
+ keylen
;
465 protocol_binary_response_no_extras response
;
466 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
468 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
469 response
.message
.header
.response
.opcode
= header
->request
.opcode
;
470 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
471 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
473 struct item
* item
= get_item(key
, keylen
);
476 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT
);
478 else if (header
->request
.cas
== 0 || example_ntohll(header
->request
.cas
) == item
->cas
)
481 delete_item(key
, keylen
);
482 item
= create_item(key
, keylen
, data
, datalen
, flags
, timeout
);
486 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_ENOMEM
);
491 /* REPLACEQ shouldn't return a message */
492 if (header
->request
.opcode
== PROTOCOL_BINARY_CMD_REPLACE
)
494 response
.message
.header
.response
.cas
= example_htonll(item
->cas
);
496 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
499 return PROTOCOL_BINARY_RESPONSE_SUCCESS
;
504 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS
);
508 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
511 static protocol_binary_response_status
stat_command_handler(const void *cookie
,
512 protocol_binary_request_header
*header
,
513 memcached_binary_protocol_raw_response_handler response_handler
)
515 /* Just send the terminating packet*/
516 protocol_binary_response_no_extras response
;
517 memset(&response
, 0, sizeof(protocol_binary_response_no_extras
));
519 response
.message
.header
.response
.magic
= PROTOCOL_BINARY_RES
;
520 response
.message
.header
.response
.opcode
= PROTOCOL_BINARY_CMD_STAT
;
521 response
.message
.header
.response
.status
= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS
);
522 response
.message
.header
.response
.opaque
= header
->request
.opaque
;
524 return response_handler(cookie
, header
, (protocol_binary_response_header
*)&response
);
527 memcached_binary_protocol_callback_st interface_v0_impl
;
529 void initialize_interface_v0_handler(util::log_info_st
& arg
)
533 interface_v0_impl
.interface_version
= MEMCACHED_PROTOCOL_HANDLER_V0
;
534 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GET
]= get_command_handler
;
535 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_SET
]= set_command_handler
;
536 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_ADD
]= add_command_handler
;
537 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_REPLACE
]= replace_command_handler
;
538 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DELETE
]= delete_command_handler
;
539 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_INCREMENT
]= arithmetic_command_handler
;
540 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DECREMENT
]= arithmetic_command_handler
;
541 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_QUIT
]= quit_command_handler
;
542 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_FLUSH
]= flush_command_handler
;
543 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETQ
]= get_command_handler
;
544 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_NOOP
]= noop_command_handler
;
545 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_VERSION
]= version_command_handler
;
546 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETK
]= get_command_handler
;
547 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_GETKQ
]= get_command_handler
;
548 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_APPEND
]= concat_command_handler
;
549 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_PREPEND
]= concat_command_handler
;
550 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_STAT
]= stat_command_handler
;
551 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_SETQ
]= set_command_handler
;
552 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_ADDQ
]= add_command_handler
;
553 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_REPLACEQ
]= replace_command_handler
;
554 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DELETEQ
]= delete_command_handler
;
555 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_INCREMENTQ
]= arithmetic_command_handler
;
556 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_DECREMENTQ
]= arithmetic_command_handler
;
557 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_QUITQ
]= quit_command_handler
;
558 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_FLUSHQ
]= flush_command_handler
;
559 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_APPENDQ
]= concat_command_handler
;
560 interface_v0_impl
.interface
.v0
.comcode
[PROTOCOL_BINARY_CMD_PREPENDQ
]= concat_command_handler
;