Merge in additional test for increment with namespace key.
[awesomized/libmemcached] / libmemcached / protocol / 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 "config.h"
40 #if !defined(__cplusplus)
41 # include <stdbool.h>
42 #endif
43 #include <assert.h>
44
45 #include <libmemcached/visibility.h>
46 #include <libmemcached/protocol_handler.h>
47 #include <libmemcached/protocol/cache.h>
48
49 /*
50 * I don't really need the following two functions as function pointers
51 * in the instance handle, but I don't want to put them in the global
52 * namespace for those linking statically (personally I don't like that,
53 * but some people still do). If it ever shows up as a performance thing
54 * I'll look into optimizing this ;-)
55 */
56 typedef bool (*drain_func)(memcached_protocol_client_st *client);
57 typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
58 const void *data,
59 size_t length);
60
61 /**
62 * Definition of the per instance structure.
63 */
64 struct memcached_protocol_st {
65 memcached_binary_protocol_callback_st *callback;
66 memcached_protocol_recv_func recv;
67 memcached_protocol_send_func send;
68
69 /*
70 * I really don't need these as funciton pointers, but I don't want
71 * to clutter the namespace if someone links statically.
72 */
73 drain_func drain;
74 spool_func spool;
75
76 /*
77 * To avoid keeping a buffer in each client all the time I have a
78 * bigger buffer in the instance that I read to initially, and then
79 * I try to parse and execute as much from the buffer. If I wasn't able
80 * to process all data I'll keep that in a per-connection buffer until
81 * the next time I can read from the socket.
82 */
83 uint8_t *input_buffer;
84 size_t input_buffer_size;
85
86 bool pedantic;
87 /* @todo use multiple sized buffers */
88 cache_t *buffer_cache;
89 };
90
91 struct chunk_st {
92 /* Pointer to the data */
93 char *data;
94 /* The offset to the first byte into the buffer that is used */
95 size_t offset;
96 /* The offset into the buffer for the first free byte */
97 size_t nbytes;
98 /* The number of bytes in the buffer */
99 size_t size;
100 /* Pointer to the next buffer in the chain */
101 struct chunk_st *next;
102 };
103
104 #define CHUNK_BUFFERSIZE 2048
105
106 typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
107
108 enum ascii_cmd {
109 GET_CMD,
110 GETS_CMD,
111 SET_CMD,
112 ADD_CMD,
113 REPLACE_CMD,
114 CAS_CMD,
115 APPEND_CMD,
116 PREPEND_CMD,
117 DELETE_CMD,
118 INCR_CMD,
119 DECR_CMD,
120 STATS_CMD,
121 FLUSH_ALL_CMD,
122 VERSION_CMD,
123 QUIT_CMD,
124 VERBOSITY_CMD,
125 UNKNOWN_CMD
126 };
127
128 struct memcached_protocol_client_st {
129 memcached_protocol_st *root;
130 memcached_socket_t sock;
131 int error;
132
133 /* Linked list of data to send */
134 struct chunk_st *output;
135 struct chunk_st *output_tail;
136
137 /*
138 * While we process input data, this is where we spool incomplete commands
139 * if we need to receive more data....
140 * @todo use the buffercace
141 */
142 uint8_t *input_buffer;
143 size_t input_buffer_size;
144 size_t input_buffer_offset;
145
146 /* The callback to the protocol handler to use (ascii or binary) */
147 process_data work;
148
149 /*
150 * Should the spool data discard the data to send or not? (aka noreply in
151 * the ascii protocol..
152 */
153 bool mute;
154
155 /* Members used by the binary protocol */
156 protocol_binary_request_header *current_command;
157
158 /* Members used by the ascii protocol */
159 enum ascii_cmd ascii_command;
160 };
161
162 #include "ascii_handler.h"
163 #include "binary_handler.h"