Convert storage over to use vector better.
[m6w6/libmemcached] / libmemcached / auto.cc
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Libmemcached library
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 * Copyright (C) 2006-2009 Brian Aker All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following disclaimer
17 * in the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * * The names of its contributors may not be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38 #include <libmemcached/common.h>
39
40 static memcached_return_t text_incr_decr(memcached_st *ptr,
41 const bool is_incr,
42 const char *group_key, size_t group_key_length,
43 const char *key, size_t key_length,
44 uint64_t offset,
45 uint64_t& numeric_value)
46 {
47 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
48 uint32_t server_key;
49 memcached_server_write_instance_st instance;
50
51 // Invert the logic to make it simpler to read the code
52 bool reply= (ptr->flags.no_reply) ? false : true;
53
54 if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
55 {
56 return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
57 }
58
59 server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
60 instance= memcached_server_instance_fetch(ptr, server_key);
61
62 int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
63 if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
64 {
65 return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
66 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
67 }
68
69 struct libmemcached_io_vector_st vector[]=
70 {
71 { memcached_literal_param("incr ") },
72 { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
73 { key, key_length },
74 { buffer, send_length },
75 { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
76 { memcached_literal_param("\r\n") }
77 };
78
79 if (is_incr == false)
80 {
81 vector[0].buffer= "decr ";
82 }
83
84 memcached_return_t rc= memcached_vdo(instance, vector, 6, true);
85 if (reply == false or memcached_failed(rc))
86 {
87 numeric_value= UINT64_MAX;
88 return rc;
89 }
90
91 rc= memcached_response(instance, buffer, sizeof(buffer), NULL, numeric_value);
92
93 return memcached_set_error(*instance, rc, MEMCACHED_AT);
94 }
95
96 static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
97 const char *group_key, size_t group_key_length,
98 const char *key, size_t key_length,
99 uint64_t offset, uint64_t initial,
100 uint32_t expiration,
101 uint64_t *value)
102 {
103 bool no_reply= ptr->flags.no_reply;
104
105 uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
106 memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
107
108 if (no_reply)
109 {
110 if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
111 {
112 cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
113 }
114
115 if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
116 {
117 cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
118 }
119 }
120 protocol_binary_request_incr request= {}; // = {.bytes= {0}};
121
122 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
123 request.message.header.request.opcode= cmd;
124 request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
125 request.message.header.request.extlen= 20;
126 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
127 request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace) +request.message.header.request.extlen));
128 request.message.body.delta= memcached_htonll(offset);
129 request.message.body.initial= memcached_htonll(initial);
130 request.message.body.expiration= htonl((uint32_t) expiration);
131
132 struct libmemcached_io_vector_st vector[]=
133 {
134 { request.bytes, sizeof(request.bytes) },
135 { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
136 { key, key_length }
137 };
138
139 memcached_return_t rc;
140 if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
141 {
142 memcached_io_reset(instance);
143 return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
144 }
145
146 if (no_reply)
147 {
148 return MEMCACHED_SUCCESS;
149 }
150
151 return memcached_response(instance, (char*)value, sizeof(*value), NULL);
152 }
153
154 memcached_return_t memcached_increment(memcached_st *ptr,
155 const char *key, size_t key_length,
156 uint32_t offset,
157 uint64_t *value)
158 {
159 return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
160 }
161
162 memcached_return_t memcached_decrement(memcached_st *ptr,
163 const char *key, size_t key_length,
164 uint32_t offset,
165 uint64_t *value)
166 {
167 return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
168 }
169
170 memcached_return_t memcached_increment_by_key(memcached_st *ptr,
171 const char *group_key, size_t group_key_length,
172 const char *key, size_t key_length,
173 uint64_t offset,
174 uint64_t *value)
175 {
176 memcached_return_t rc;
177 uint64_t local_value;
178 if (value == NULL)
179 {
180 value= &local_value;
181 }
182
183 if (memcached_failed(rc= initialize_query(ptr)))
184 {
185 return rc;
186 }
187
188 if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
189 {
190 return rc;
191 }
192
193 LIBMEMCACHED_MEMCACHED_INCREMENT_START();
194 if (ptr->flags.binary_protocol)
195 {
196 rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
197 group_key, group_key_length, key, key_length,
198 (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
199 value);
200 }
201 else
202 {
203 rc= text_incr_decr(ptr, true, group_key, group_key_length, key, key_length, offset, *value);
204 }
205
206 LIBMEMCACHED_MEMCACHED_INCREMENT_END();
207
208 return rc;
209 }
210
211 memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
212 const char *group_key, size_t group_key_length,
213 const char *key, size_t key_length,
214 uint64_t offset,
215 uint64_t *value)
216 {
217 uint64_t local_value;
218 if (value == NULL)
219 {
220 value= &local_value;
221 }
222
223 memcached_return_t rc;
224 if (memcached_failed(rc= initialize_query(ptr)))
225 {
226 return rc;
227 }
228
229 if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
230 {
231 return rc;
232 }
233
234
235 LIBMEMCACHED_MEMCACHED_DECREMENT_START();
236 if (ptr->flags.binary_protocol)
237 {
238 rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
239 group_key, group_key_length, key, key_length,
240 (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
241 value);
242 }
243 else
244 {
245 rc= text_incr_decr(ptr, false, group_key, group_key_length, key, key_length, offset, *value);
246 }
247
248 LIBMEMCACHED_MEMCACHED_DECREMENT_END();
249
250 return rc;
251 }
252
253 memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
254 const char *key,
255 size_t key_length,
256 uint64_t offset,
257 uint64_t initial,
258 time_t expiration,
259 uint64_t *value)
260 {
261 return memcached_increment_with_initial_by_key(ptr, key, key_length,
262 key, key_length,
263 offset, initial, expiration, value);
264 }
265
266 memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
267 const char *group_key,
268 size_t group_key_length,
269 const char *key,
270 size_t key_length,
271 uint64_t offset,
272 uint64_t initial,
273 time_t expiration,
274 uint64_t *value)
275 {
276 uint64_t local_value;
277 if (value == NULL)
278 {
279 value= &local_value;
280 }
281
282 memcached_return_t rc;
283 if (memcached_failed(rc= initialize_query(ptr)))
284 {
285 return rc;
286 }
287
288 if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
289 {
290 return rc;
291 }
292
293 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
294 if (ptr->flags.binary_protocol)
295 {
296 rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
297 group_key, group_key_length, key, key_length,
298 offset, initial, (uint32_t)expiration,
299 value);
300 }
301 else
302 {
303 rc= MEMCACHED_PROTOCOL_ERROR;
304 }
305
306 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
307
308 return rc;
309 }
310
311 memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
312 const char *key,
313 size_t key_length,
314 uint64_t offset,
315 uint64_t initial,
316 time_t expiration,
317 uint64_t *value)
318 {
319 return memcached_decrement_with_initial_by_key(ptr, key, key_length,
320 key, key_length,
321 offset, initial, expiration, value);
322 }
323
324 memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
325 const char *group_key,
326 size_t group_key_length,
327 const char *key,
328 size_t key_length,
329 uint64_t offset,
330 uint64_t initial,
331 time_t expiration,
332 uint64_t *value)
333 {
334 uint64_t local_value;
335 if (value == NULL)
336 {
337 value= &local_value;
338 }
339
340 memcached_return_t rc;
341 if (memcached_failed(rc= initialize_query(ptr)))
342 {
343 return rc;
344 }
345
346 if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
347 {
348 return rc;
349 }
350
351 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
352 if (ptr->flags.binary_protocol)
353 {
354 rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
355 group_key, group_key_length, key, key_length,
356 offset, initial, (uint32_t)expiration,
357 value);
358 }
359 else
360 {
361 rc= MEMCACHED_PROTOCOL_ERROR;
362 }
363
364 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
365
366 return rc;
367 }
368