Fixed bug where zero length key was provided.
[awesomized/libmemcached] / lib / memcached_auto.c
1 #include "common.h"
2
3 static memcached_return memcached_auto(memcached_st *ptr,
4 char *verb,
5 char *key, size_t key_length,
6 unsigned int offset,
7 uint64_t *value)
8 {
9 size_t send_length, sent_length;
10 memcached_return rc;
11 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
12 unsigned int server_key;
13
14 if (key_length == 0)
15 return MEMCACHED_NO_KEY_PROVIDED;
16
17 if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
18 return MEMCACHED_NO_SERVERS;
19
20 server_key= memcached_generate_hash(ptr, key, key_length);
21
22 if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS)
23 return rc;
24
25 send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
26 "%s %.*s %u\r\n", verb,
27 (int)key_length, key,
28 offset);
29 if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
30 return MEMCACHED_WRITE_FAILURE;
31 sent_length= memcached_io_write(ptr, server_key, buffer, send_length, 1);
32
33 if (sent_length == -1 || sent_length != send_length)
34 return MEMCACHED_WRITE_FAILURE;
35
36 memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE);
37
38 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
39
40 /*
41 So why recheck responce? Because the protocol is brain dead :)
42 The number returned might end up equaling one of the string
43 values. Less chance of a mistake with memcmp() so we will
44 use it. We still called memcached_response() though since it
45 worked its magic for non-blocking IO.
46 */
47 if (!memcmp(buffer, "ERROR\r\n", MEMCACHED_DEFAULT_COMMAND_SIZE))
48 {
49 *value= 0;
50 rc= MEMCACHED_PROTOCOL_ERROR;
51 }
52 else if (!memcmp(buffer, "NOT_FOUND\r\n", MEMCACHED_DEFAULT_COMMAND_SIZE))
53 {
54 *value= 0;
55 rc= MEMCACHED_NOTFOUND;
56 }
57 else
58 {
59 *value= (uint64_t)strtoll(buffer, (char **)NULL, 10);
60 rc= MEMCACHED_SUCCESS;
61 }
62
63 return rc;
64 }
65
66 memcached_return memcached_increment(memcached_st *ptr,
67 char *key, size_t key_length,
68 unsigned int offset,
69 uint64_t *value)
70 {
71 memcached_return rc;
72
73 LIBMEMCACHED_MEMCACHED_INCREMENT_START();
74 rc= memcached_auto(ptr, "incr", key, key_length, offset, value);
75 LIBMEMCACHED_MEMCACHED_INCREMENT_END();
76
77 return rc;
78 }
79
80 memcached_return memcached_decrement(memcached_st *ptr,
81 char *key, size_t key_length,
82 unsigned int offset,
83 uint64_t *value)
84 {
85 memcached_return rc;
86
87 LIBMEMCACHED_MEMCACHED_DECREMENT_START();
88 rc= memcached_auto(ptr, "decr", key, key_length, offset, value);
89 LIBMEMCACHED_MEMCACHED_DECREMENT_END();
90
91 return rc;
92 }