Deprecate MEMCACHED_NO_KEY_PROVIDED, and fixed key validation tests for the binary...
[awesomized/libmemcached] / libmemcached / memcached_auto.c
1 #include "common.h"
2
3 static memcached_return memcached_auto(memcached_st *ptr,
4 const char *verb,
5 const char *key, size_t key_length,
6 unsigned int offset,
7 uint64_t *value)
8 {
9 size_t send_length;
10 memcached_return rc;
11 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
12 unsigned int server_key;
13
14 unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
15 return MEMCACHED_NO_SERVERS;
16
17 if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test((char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
18 return MEMCACHED_BAD_KEY_PROVIDED;
19
20 server_key= memcached_generate_hash(ptr, key, key_length);
21
22 send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
23 "%s %s%.*s %u\r\n", verb,
24 ptr->prefix_key,
25 (int)key_length, key,
26 offset);
27 unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
28 return MEMCACHED_WRITE_FAILURE;
29
30 rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
31 if (rc != MEMCACHED_SUCCESS)
32 return rc;
33
34 rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
35
36 /*
37 So why recheck responce? Because the protocol is brain dead :)
38 The number returned might end up equaling one of the string
39 values. Less chance of a mistake with strncmp() so we will
40 use it. We still called memcached_response() though since it
41 worked its magic for non-blocking IO.
42 */
43 if (!strncmp(buffer, "ERROR\r\n", 7))
44 {
45 *value= 0;
46 rc= MEMCACHED_PROTOCOL_ERROR;
47 }
48 else if (!strncmp(buffer, "NOT_FOUND\r\n", 11))
49 {
50 *value= 0;
51 rc= MEMCACHED_NOTFOUND;
52 }
53 else
54 {
55 *value= strtoull(buffer, (char **)NULL, 10);
56 rc= MEMCACHED_SUCCESS;
57 }
58
59 return rc;
60 }
61
62 static memcached_return binary_incr_decr(memcached_st *ptr, uint8_t cmd,
63 const char *key, size_t key_length,
64 uint32_t offset, uint64_t *value)
65 {
66 unsigned int server_key;
67
68 unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
69 return MEMCACHED_NO_SERVERS;
70
71 server_key= memcached_generate_hash(ptr, key, key_length);
72
73 protocol_binary_request_incr request= {.bytes= {0}};
74
75 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
76 request.message.header.request.opcode= cmd;
77 request.message.header.request.keylen= htons((uint16_t)key_length);
78 request.message.header.request.extlen= 20;
79 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
80 request.message.header.request.bodylen= htonl(key_length + request.message.header.request.extlen);
81 request.message.body.delta= htonll(offset);
82
83 /* TODO: The binary protocol allows you to specify initial and expiry time */
84 if ((memcached_do(&ptr->hosts[server_key], request.bytes,
85 sizeof(request.bytes), 0)!=MEMCACHED_SUCCESS) ||
86 (memcached_io_write(&ptr->hosts[server_key], key, key_length, 1) == -1))
87 {
88 memcached_io_reset(&ptr->hosts[server_key]);
89 return MEMCACHED_WRITE_FAILURE;
90 }
91
92 return memcached_response(&ptr->hosts[server_key], (char*)value, sizeof(*value), NULL);
93 }
94
95 memcached_return memcached_increment(memcached_st *ptr,
96 const char *key, size_t key_length,
97 uint32_t offset,
98 uint64_t *value)
99 {
100 memcached_return rc= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL);
101 unlikely (rc != MEMCACHED_SUCCESS)
102 return rc;
103
104 LIBMEMCACHED_MEMCACHED_INCREMENT_START();
105 if (ptr->flags & MEM_BINARY_PROTOCOL)
106 rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT, key,
107 key_length, offset, value);
108 else
109 rc= memcached_auto(ptr, "incr", key, key_length, offset, value);
110
111 LIBMEMCACHED_MEMCACHED_INCREMENT_END();
112
113 return rc;
114 }
115
116 memcached_return memcached_decrement(memcached_st *ptr,
117 const char *key, size_t key_length,
118 uint32_t offset,
119 uint64_t *value)
120 {
121 memcached_return rc= memcached_validate_key_length(key_length, ptr->flags & MEM_BINARY_PROTOCOL);
122 unlikely (rc != MEMCACHED_SUCCESS)
123 return rc;
124
125 LIBMEMCACHED_MEMCACHED_DECREMENT_START();
126 if (ptr->flags & MEM_BINARY_PROTOCOL)
127 rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT, key,
128 key_length, offset, value);
129 else
130 rc= memcached_auto(ptr, "decr", key, key_length, offset, value);
131
132 LIBMEMCACHED_MEMCACHED_DECREMENT_END();
133
134 return rc;
135 }