Remove exposed C++ namespace.
[awesomized/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 void auto_response(memcached_instance_st* instance, const bool reply, memcached_return_t& rc, uint64_t* value)
41 {
42 // If the message was successfully sent, then get the response, otherwise
43 // fail.
44 if (memcached_success(rc))
45 {
46 if (reply == false)
47 {
48 *value= UINT64_MAX;
49 return;
50 }
51
52 rc= memcached_response(instance, &instance->root->result);
53 }
54
55 if (memcached_fatal(rc))
56 {
57 assert(memcached_last_error(instance->root) != MEMCACHED_SUCCESS);
58 *value= UINT64_MAX;
59 }
60 else
61 {
62 *value= instance->root->result.numeric_value;
63 }
64 }
65
66 static memcached_return_t text_incr_decr(memcached_instance_st* instance,
67 const bool is_incr,
68 const char *key, size_t key_length,
69 const uint64_t offset,
70 const bool reply)
71 {
72 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
73
74 int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
75 if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
76 {
77 return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
78 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
79 }
80
81 libmemcached_io_vector_st vector[]=
82 {
83 { NULL, 0 },
84 { memcached_literal_param("incr ") },
85 { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
86 { key, key_length },
87 { buffer, size_t(send_length) },
88 { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
89 { memcached_literal_param("\r\n") }
90 };
91
92 if (is_incr == false)
93 {
94 vector[1].buffer= "decr ";
95 }
96
97 return memcached_vdo(instance, vector, 7, true);
98 }
99
100 static memcached_return_t binary_incr_decr(memcached_instance_st* instance,
101 protocol_binary_command cmd,
102 const char *key, const size_t key_length,
103 const uint64_t offset,
104 const uint64_t initial,
105 const uint32_t expiration,
106 const bool reply)
107 {
108 if (reply == false)
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 initialize_binary_request(instance, request.message.header);
123
124 request.message.header.request.opcode= cmd;
125 request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
126 request.message.header.request.extlen= 20;
127 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
128 request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
129 request.message.body.delta= memcached_htonll(offset);
130 request.message.body.initial= memcached_htonll(initial);
131 request.message.body.expiration= htonl((uint32_t) expiration);
132
133 libmemcached_io_vector_st vector[]=
134 {
135 { NULL, 0 },
136 { request.bytes, sizeof(request.bytes) },
137 { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
138 { key, key_length }
139 };
140
141 return memcached_vdo(instance, vector, 4, true);
142 }
143
144 memcached_return_t memcached_increment(memcached_st *memc,
145 const char *key, size_t key_length,
146 uint32_t offset,
147 uint64_t *value)
148 {
149 return memcached_increment_by_key(memc, key, key_length, key, key_length, offset, value);
150 }
151
152 static memcached_return_t increment_decrement_by_key(const protocol_binary_command command,
153 Memcached *memc,
154 const char *group_key, size_t group_key_length,
155 const char *key, size_t key_length,
156 uint64_t offset,
157 uint64_t *value)
158 {
159 uint64_t local_value;
160 if (value == NULL)
161 {
162 value= &local_value;
163 }
164
165 memcached_return_t rc;
166 if (memcached_failed(rc= initialize_query(memc, true)))
167 {
168 return rc;
169 }
170
171 if (memcached_is_encrypted(memc))
172 {
173 return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT,
174 memcached_literal_param("Operation not allowed while encyrption is enabled"));
175 }
176
177 if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
178 {
179 return memcached_last_error(memc);
180 }
181
182 uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
183 memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
184
185 bool reply= memcached_is_replying(instance->root);
186
187 if (memcached_is_binary(memc))
188 {
189 rc= binary_incr_decr(instance, command,
190 key, key_length,
191 uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
192 reply);
193 }
194 else
195 {
196 rc= text_incr_decr(instance,
197 command == PROTOCOL_BINARY_CMD_INCREMENT ? true : false,
198 key, key_length,
199 offset, reply);
200 }
201
202 auto_response(instance, reply, rc, value);
203
204 return rc;
205 }
206
207 static memcached_return_t increment_decrement_with_initial_by_key(const protocol_binary_command command,
208 Memcached *memc,
209 const char *group_key,
210 size_t group_key_length,
211 const char *key,
212 size_t key_length,
213 uint64_t offset,
214 uint64_t initial,
215 time_t expiration,
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(memc, true)))
226 {
227 return rc;
228 }
229
230 if (memcached_is_encrypted(memc))
231 {
232 return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT,
233 memcached_literal_param("Operation not allowed while encyrption is enabled"));
234 }
235
236 if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
237 {
238 return memcached_last_error(memc);
239 }
240
241 uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
242 memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
243
244 bool reply= memcached_is_replying(instance->root);
245
246 if (memcached_is_binary(memc))
247 {
248 rc= binary_incr_decr(instance, command,
249 key, key_length,
250 offset, initial, uint32_t(expiration),
251 reply);
252
253 }
254 else
255 {
256 rc= memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
257 memcached_literal_param("memcached_increment_with_initial_by_key() is not supported via the ASCII protocol"));
258 }
259
260 auto_response(instance, reply, rc, value);
261
262 return rc;
263 }
264
265 memcached_return_t memcached_decrement(memcached_st *memc,
266 const char *key, size_t key_length,
267 uint32_t offset,
268 uint64_t *value)
269 {
270 return memcached_decrement_by_key(memc, key, key_length, key, key_length, offset, value);
271 }
272
273
274 memcached_return_t memcached_increment_by_key(memcached_st *shell,
275 const char *group_key, size_t group_key_length,
276 const char *key, size_t key_length,
277 uint64_t offset,
278 uint64_t *value)
279 {
280 Memcached* memc= memcached2Memcached(shell);
281 LIBMEMCACHED_MEMCACHED_INCREMENT_START();
282 memcached_return_t rc= increment_decrement_by_key(PROTOCOL_BINARY_CMD_INCREMENT,
283 memc,
284 group_key, group_key_length,
285 key, key_length,
286 offset, value);
287
288 LIBMEMCACHED_MEMCACHED_INCREMENT_END();
289
290 return rc;
291 }
292
293 memcached_return_t memcached_decrement_by_key(memcached_st *shell,
294 const char *group_key, size_t group_key_length,
295 const char *key, size_t key_length,
296 uint64_t offset,
297 uint64_t *value)
298 {
299 Memcached* memc= memcached2Memcached(shell);
300 LIBMEMCACHED_MEMCACHED_DECREMENT_START();
301 memcached_return_t rc= increment_decrement_by_key(PROTOCOL_BINARY_CMD_DECREMENT,
302 memc,
303 group_key, group_key_length,
304 key, key_length,
305 offset, value);
306 LIBMEMCACHED_MEMCACHED_DECREMENT_END();
307
308 return rc;
309 }
310
311 memcached_return_t memcached_increment_with_initial(memcached_st *memc,
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_increment_with_initial_by_key(memc, key, key_length,
320 key, key_length,
321 offset, initial, expiration, value);
322 }
323
324 memcached_return_t memcached_increment_with_initial_by_key(memcached_st *shell,
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 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
335 Memcached* memc= memcached2Memcached(shell);
336 memcached_return_t rc= increment_decrement_with_initial_by_key(PROTOCOL_BINARY_CMD_INCREMENT,
337 memc,
338 group_key, group_key_length,
339 key, key_length,
340 offset, initial, expiration, value);
341 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
342
343 return rc;
344 }
345
346 memcached_return_t memcached_decrement_with_initial(memcached_st *memc,
347 const char *key,
348 size_t key_length,
349 uint64_t offset,
350 uint64_t initial,
351 time_t expiration,
352 uint64_t *value)
353 {
354 return memcached_decrement_with_initial_by_key(memc, key, key_length,
355 key, key_length,
356 offset, initial, expiration, value);
357 }
358
359 memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *shell,
360 const char *group_key,
361 size_t group_key_length,
362 const char *key,
363 size_t key_length,
364 uint64_t offset,
365 uint64_t initial,
366 time_t expiration,
367 uint64_t *value)
368 {
369 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
370 Memcached* memc= memcached2Memcached(shell);
371 memcached_return_t rc= increment_decrement_with_initial_by_key(PROTOCOL_BINARY_CMD_DECREMENT,
372 memc,
373 group_key, group_key_length,
374 key, key_length,
375 offset, initial, expiration, value);
376
377 LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
378
379 return rc;
380 }