Merge lp:~tangent-org/libmemcached/1.0-build/ Build: jenkins-Libmemcached-187
[m6w6/libmemcached] / libmemcachedprotocol / common.h
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Libmemcached library
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * * The names of its contributors may not be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 #pragma once
38
39 #include "mem_config.h"
40 #include <assert.h>
41
42 #include <libmemcachedprotocol-0.0/handler.h>
43 #include <libmemcachedprotocol/cache.h>
44 #include <libmemcached/byteorder.h>
45 #include <libmemcached/socket.hpp>
46
47 /*
48 * I don't really need the following two functions as function pointers
49 * in the instance handle, but I don't want to put them in the global
50 * namespace for those linking statically (personally I don't like that,
51 * but some people still do). If it ever shows up as a performance thing
52 * I'll look into optimizing this ;-)
53 */
54 typedef bool (*drain_func)(memcached_protocol_client_st *client);
55 typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
56 const void *data,
57 size_t length);
58
59 /**
60 * Definition of the per instance structure.
61 */
62 struct memcached_protocol_st {
63 memcached_binary_protocol_callback_st *callback;
64 memcached_protocol_recv_func recv;
65 memcached_protocol_send_func send;
66
67 /*
68 * I really don't need these as funciton pointers, but I don't want
69 * to clutter the namespace if someone links statically.
70 */
71 drain_func drain;
72 spool_func spool;
73
74 /*
75 * To avoid keeping a buffer in each client all the time I have a
76 * bigger buffer in the instance that I read to initially, and then
77 * I try to parse and execute as much from the buffer. If I wasn't able
78 * to process all data I'll keep that in a per-connection buffer until
79 * the next time I can read from the socket.
80 */
81 uint8_t *input_buffer;
82 size_t input_buffer_size;
83
84 bool pedantic;
85 /* @todo use multiple sized buffers */
86 cache_t *buffer_cache;
87 };
88
89 struct chunk_st {
90 /* Pointer to the data */
91 char *data;
92 /* The offset to the first byte into the buffer that is used */
93 size_t offset;
94 /* The offset into the buffer for the first free byte */
95 size_t nbytes;
96 /* The number of bytes in the buffer */
97 size_t size;
98 /* Pointer to the next buffer in the chain */
99 struct chunk_st *next;
100 };
101
102 #define CHUNK_BUFFERSIZE 2048
103
104 typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
105
106 enum ascii_cmd {
107 GET_CMD,
108 GETS_CMD,
109 SET_CMD,
110 ADD_CMD,
111 REPLACE_CMD,
112 CAS_CMD,
113 APPEND_CMD,
114 PREPEND_CMD,
115 DELETE_CMD,
116 INCR_CMD,
117 DECR_CMD,
118 STATS_CMD,
119 FLUSH_ALL_CMD,
120 VERSION_CMD,
121 QUIT_CMD,
122 VERBOSITY_CMD,
123 UNKNOWN_CMD
124 };
125
126 struct memcached_protocol_client_st {
127 bool is_verbose;
128 memcached_protocol_st *root;
129 memcached_socket_t sock;
130 int error;
131
132 /* Linked list of data to send */
133 struct chunk_st *output;
134 struct chunk_st *output_tail;
135
136 /*
137 * While we process input data, this is where we spool incomplete commands
138 * if we need to receive more data....
139 * @todo use the buffercace
140 */
141 uint8_t *input_buffer;
142 size_t input_buffer_size;
143 size_t input_buffer_offset;
144
145 /* The callback to the protocol handler to use (ascii or binary) */
146 process_data work;
147
148 /*
149 * Should the spool data discard the data to send or not? (aka noreply in
150 * the ascii protocol..
151 */
152 bool mute;
153
154 /* Members used by the binary protocol */
155 protocol_binary_request_header *current_command;
156
157 /* Members used by the ascii protocol */
158 enum ascii_cmd ascii_command;
159 };
160
161 #include "ascii_handler.h"
162 #include "binary_handler.h"