Update for storage to now use vector
[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_server_write_instance_st instance,
41 const bool is_incr,
42 const char *key, size_t key_length,
43 const uint64_t offset,
44 const bool reply,
45 uint64_t& numeric_value)
46 {
47 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
48
49 int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
50 if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
51 {
52 return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
53 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
54 }
55
56 struct libmemcached_io_vector_st vector[]=
57 {
58 { memcached_literal_param("incr ") },
59 { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
60 { key, key_length },
61 { buffer, send_length },
62 { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
63 { memcached_literal_param("\r\n") }
64 };
65
66 if (is_incr == false)
67 {
68 vector[0].buffer= "decr ";
69 }
70
71 memcached_return_t rc= memcached_vdo(instance, vector, 6, true);
72
73 if (reply == false)
74 {
75 return MEMCACHED_SUCCESS;
76 }
77
78 if (memcached_failed(rc))
79 {
80 numeric_value= UINT64_MAX;
81 return rc;
82 }
83
84 rc= memcached_response(instance, buffer, sizeof(buffer), NULL, numeric_value);
85
86 return memcached_set_error(*instance, rc, MEMCACHED_AT);
87 }
88
89 static memcached_return_t binary_incr_decr(memcached_server_write_instance_st instance,
90 protocol_binary_command cmd,
91 const char *key, const size_t key_length,
92 const uint64_t offset,
93 const uint64_t initial,
94 const uint32_t expiration,
95 const bool reply,
96 uint64_t *value)
97 {
98 if (reply == false)
99 {
100 if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
101 {
102 cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
103 }
104
105 if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
106 {
107 cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
108 }
109 }
110 protocol_binary_request_incr request= {}; // = {.bytes= {0}};
111
112 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
113 request.message.header.request.opcode= cmd;
114 request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
115 request.message.header.request.extlen= 20;
116 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
117 request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
118 request.message.body.delta= memcached_htonll(offset);
119 request.message.body.initial= memcached_htonll(initial);
120 request.message.body.expiration= htonl((uint32_t) expiration);
121
122 struct libmemcached_io_vector_st vector[]=
123 {
124 { request.bytes, sizeof(request.bytes) },
125 { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
126 { key, key_length }
127 };
128
129 memcached_return_t rc;
130 if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
131 {
132 memcached_io_reset(instance);
133 return MEMCACHED_WRITE_FAILURE;
134 }
135
136 if (reply == false)
137 {
138 return MEMCACHED_SUCCESS;
139 }
140
141 return memcached_response(instance, (char*)value, sizeof(*value), NULL);
142 }
143
144 memcached_return_t memcached_increment(memcached_st *ptr,
145 const char *key, size_t key_length,
146 uint32_t offset,
147 uint64_t *value)
148 {
149 return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
150 }
151
152 memcached_return_t memcached_decrement(memcached_st *ptr,
153 const char *key, size_t key_length,
154 uint32_t offset,
155 uint64_t *value)
156 {
157 return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
158 }
159
160 memcached_return_t memcached_increment_by_key(memcached_st *ptr,
161 const char *group_key, size_t group_key_length,
162 const char *key, size_t key_length,
163 uint64_t offset,
164 uint64_t *value)
165 {
166 memcached_return_t rc;
167 uint64_t local_value;
168 if (value == NULL)
169 {
170 value= &local_value;
171 }
172
173 if (memcached_failed(rc= initialize_query(ptr)))
174 {
175 return rc;
176 }
177
178 if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
179 {
180 return rc;
181 }
182
183 if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
184 {
185 return memcached_set_error(*ptr, rc, MEMCACHED_AT);
186 }
187
188 uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
189 memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
190
191 bool reply= memcached_is_replying(instance->root);
192
193 LIBMEMCACHED_MEMCACHED_INCREMENT_START();
194 if (memcached_is_binary(ptr))
195 {
196 rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
197 key, key_length,
198 uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
199 reply,
200 value);
201 }
202 else
203 {
204 rc= text_incr_decr(instance, true, key, key_length, offset, reply, *value);
205 }
206
207 LIBMEMCACHED_MEMCACHED_INCREMENT_END();
208
209 return rc;
210 }
211
212 memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
213 const char *group_key, size_t group_key_length,
214 const char *key, size_t key_length,
215 uint64_t offset,
216 uint64_t *value)
217 {
218 uint64_t local_value;
219 if (value == NULL)
220 {
221 value= &local_value;
222 }
223
224 memcached_return_t rc;
225 if (memcached_failed(rc= initialize_query(ptr)))
226 {
227 return rc;
228 }
229
230 if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
231 {
232 return memcached_set_error(*ptr, rc, MEMCACHED_AT);
233 }
234
235
236 uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
237 memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
238
239 bool reply= memcached_is_replying(instance->root);
240
241 LIBMEMCACHED_MEMCACHED_DECREMENT_START();
242 if (memcached_is_binary(ptr))
243 {
244 rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
245 key, key_length,
246 offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
247 reply,
248 value);
249 }
250 else
251 {
252 rc= text_incr_decr(instance, false, key, key_length, offset, reply, *value);
253 }
254
255 LIBMEMCACHED_MEMCACHED_DECREMENT_END();
256
257 return rc;
258 }
259
260 memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
261 const char *key,
262 size_t key_length,
263 uint64_t offset,
264 uint64_t initial,
265 time_t expiration,
266 uint64_t *value)
267 {
268 return memcached_increment_with_initial_by_key(ptr, key, key_length,
269 key, key_length,
270 offset, initial, expiration, value);
271 }
272
273 memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
274 const char *group_key,
275 size_t group_key_length,
276 const char *key,
277 size_t key_length,
278 uint64_t offset,
279 uint64_t initial,
280 time_t expiration,
281 uint64_t *value)
282 {
283 uint64_t local_value;
284 if (value == NULL)
285 {
286 value= &local_value;
287 }
288
289 memcached_return_t rc;
290 if (memcached_failed(rc= initialize_query(ptr)))
291 {
292 return rc;
293 }
294
295 if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
296 {
297 return memcached_set_error(*ptr, rc, MEMCACHED_AT);
298 }
299
300 uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
301 memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
302
303 bool reply= memcached_is_replying(instance->root);
304
305 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
306 if (memcached_is_binary(ptr))
307 {
308 rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_INCREMENT,
309 key, key_length,
310 offset, initial, uint32_t(expiration),
311 reply,
312 value);
313 }
314 else
315 {
316 rc= MEMCACHED_PROTOCOL_ERROR;
317 }
318
319 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
320
321 return rc;
322 }
323
324 memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
325 const char *key,
326 size_t key_length,
327 uint64_t offset,
328 uint64_t initial,
329 time_t expiration,
330 uint64_t *value)
331 {
332 return memcached_decrement_with_initial_by_key(ptr, key, key_length,
333 key, key_length,
334 offset, initial, expiration, value);
335 }
336
337 memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
338 const char *group_key,
339 size_t group_key_length,
340 const char *key,
341 size_t key_length,
342 uint64_t offset,
343 uint64_t initial,
344 time_t expiration,
345 uint64_t *value)
346 {
347 uint64_t local_value;
348 if (value == NULL)
349 {
350 value= &local_value;
351 }
352
353 memcached_return_t rc;
354 if (memcached_failed(rc= initialize_query(ptr)))
355 {
356 return rc;
357 }
358
359 if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
360 {
361 return memcached_set_error(*ptr, rc, MEMCACHED_AT);
362 }
363
364 uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
365 memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
366
367 bool reply= memcached_is_replying(instance->root);
368
369
370 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
371 if (memcached_is_binary(ptr))
372 {
373 rc= binary_incr_decr(instance, PROTOCOL_BINARY_CMD_DECREMENT,
374 key, key_length,
375 offset, initial, uint32_t(expiration),
376 reply,
377 value);
378 }
379 else
380 {
381 rc= MEMCACHED_PROTOCOL_ERROR;
382 }
383
384 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
385
386 return rc;
387 }