2a0f88d493f355df2e862af79dfd1c8d8b2b22af
[m6w6/libmemcached] / lib / memcached_storage.c
1 /*
2 Memcached library
3
4 memcached_set()
5 memcached_replace()
6 memcached_add()
7
8 */
9
10 #include "common.h"
11 #include "memcached_io.h"
12
13 typedef enum {
14 SET_OP,
15 REPLACE_OP,
16 ADD_OP,
17 PREPEND_OP,
18 APPEND_OP,
19 CAS_OP,
20 } memcached_storage_action;
21
22 /* Inline this */
23 static char *storage_op_string(memcached_storage_action verb)
24 {
25 switch (verb)
26 {
27 case SET_OP:
28 return "set";
29 case REPLACE_OP:
30 return "replace";
31 case ADD_OP:
32 return "add";
33 case PREPEND_OP:
34 return "prepend";
35 case APPEND_OP:
36 return "append";
37 case CAS_OP:
38 return "cas";
39 };
40
41 return SET_OP;
42 }
43
44 static inline memcached_return memcached_send(memcached_st *ptr,
45 char *master_key, size_t master_key_length,
46 char *key, size_t key_length,
47 char *value, size_t value_length,
48 time_t expiration,
49 uint32_t flags,
50 uint64_t cas,
51 memcached_storage_action verb)
52 {
53 char to_write;
54 size_t write_length;
55 ssize_t sent_length;
56 memcached_return rc[MEMCACHED_MAX_REPLICAS];
57 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
58 unsigned int server_key;
59 uint8_t replicas= 0;
60
61 unlikely (key_length == 0)
62 return MEMCACHED_NO_KEY_PROVIDED;
63
64 unlikely (ptr->number_of_hosts == 0)
65 return MEMCACHED_NO_SERVERS;
66
67 if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test(&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
68 return MEMCACHED_BAD_KEY_PROVIDED;
69
70 server_key= memcached_generate_hash(ptr, master_key, master_key_length);
71
72 if (cas)
73 write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
74 "%s %.*s %u %llu %zu %llu\r\n", storage_op_string(verb),
75 (int)key_length, key, flags,
76 (unsigned long long)expiration, value_length,
77 (unsigned long long)cas);
78 else
79 write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
80 "%s %.*s %u %llu %zu\r\n", storage_op_string(verb),
81 (int)key_length, key, flags,
82 (unsigned long long)expiration, value_length);
83
84 if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
85 return MEMCACHED_WRITE_FAILURE;
86
87 if ((ptr->flags & MEM_BUFFER_REQUESTS) && verb == SET_OP)
88 to_write= 0;
89 else
90 to_write= 1;
91
92 do
93 {
94 rc[replicas]= memcached_do(&ptr->hosts[server_key], buffer, write_length, 0);
95
96 if (rc[replicas] != MEMCACHED_SUCCESS)
97 goto error;
98
99 if ((sent_length= memcached_io_write(&ptr->hosts[server_key], value, value_length, 0)) == -1)
100 {
101 rc[replicas]= MEMCACHED_WRITE_FAILURE;
102 goto error;
103 }
104
105 if ((sent_length= memcached_io_write(&ptr->hosts[server_key], "\r\n", 2, to_write)) == -1)
106 {
107 rc[replicas]= MEMCACHED_WRITE_FAILURE;
108 goto error;
109 }
110
111 if (to_write == 0)
112 return MEMCACHED_BUFFERED;
113 else
114 rc[replicas]= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
115
116 /* On error we just jump to the next potential server */
117 error:
118 if (replicas > 1 && ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT)
119 {
120 if (server_key == (ptr->number_of_hosts - 1))
121 server_key= 0;
122 else
123 server_key++;
124 }
125 } while ((++replicas) < ptr->number_of_replicas);
126
127 /* As long as one object gets stored, we count this as a success */
128 while (replicas--)
129 {
130 if (rc[replicas] == MEMCACHED_STORED)
131 return MEMCACHED_SUCCESS;
132 }
133
134 return rc[0];
135 }
136
137 memcached_return memcached_set(memcached_st *ptr, char *key, size_t key_length,
138 char *value, size_t value_length,
139 time_t expiration,
140 uint32_t flags)
141 {
142 memcached_return rc;
143 LIBMEMCACHED_MEMCACHED_SET_START();
144 rc= memcached_send(ptr, key, key_length,
145 key, key_length, value, value_length,
146 expiration, flags, 0, SET_OP);
147 LIBMEMCACHED_MEMCACHED_SET_END();
148 return rc;
149 }
150
151 memcached_return memcached_add(memcached_st *ptr,
152 char *key, size_t key_length,
153 char *value, size_t value_length,
154 time_t expiration,
155 uint32_t flags)
156 {
157 memcached_return rc;
158 LIBMEMCACHED_MEMCACHED_ADD_START();
159 rc= memcached_send(ptr, key, key_length,
160 key, key_length, value, value_length,
161 expiration, flags, 0, ADD_OP);
162 LIBMEMCACHED_MEMCACHED_ADD_END();
163 return rc;
164 }
165
166 memcached_return memcached_replace(memcached_st *ptr,
167 char *key, size_t key_length,
168 char *value, size_t value_length,
169 time_t expiration,
170 uint32_t flags)
171 {
172 memcached_return rc;
173 LIBMEMCACHED_MEMCACHED_REPLACE_START();
174 rc= memcached_send(ptr, key, key_length,
175 key, key_length, value, value_length,
176 expiration, flags, 0, REPLACE_OP);
177 LIBMEMCACHED_MEMCACHED_REPLACE_END();
178 return rc;
179 }
180
181 memcached_return memcached_prepend(memcached_st *ptr,
182 char *key, size_t key_length,
183 char *value, size_t value_length,
184 time_t expiration,
185 uint32_t flags)
186 {
187 memcached_return rc;
188 rc= memcached_send(ptr, key, key_length,
189 key, key_length, value, value_length,
190 expiration, flags, 0, PREPEND_OP);
191 return rc;
192 }
193
194 memcached_return memcached_append(memcached_st *ptr,
195 char *key, size_t key_length,
196 char *value, size_t value_length,
197 time_t expiration,
198 uint32_t flags)
199 {
200 memcached_return rc;
201 rc= memcached_send(ptr, key, key_length,
202 key, key_length, value, value_length,
203 expiration, flags, 0, APPEND_OP);
204 return rc;
205 }
206
207 memcached_return memcached_cas(memcached_st *ptr,
208 char *key, size_t key_length,
209 char *value, size_t value_length,
210 time_t expiration,
211 uint32_t flags,
212 uint64_t cas)
213 {
214 memcached_return rc;
215 rc= memcached_send(ptr, key, key_length,
216 key, key_length, value, value_length,
217 expiration, flags, cas, CAS_OP);
218 return rc;
219 }
220
221 memcached_return memcached_set_by_key(memcached_st *ptr,
222 char *master_key, size_t master_key_length,
223 char *key, size_t key_length,
224 char *value, size_t value_length,
225 time_t expiration,
226 uint32_t flags)
227 {
228 memcached_return rc;
229 LIBMEMCACHED_MEMCACHED_SET_START();
230 rc= memcached_send(ptr, key, key_length,
231 key, key_length, value, value_length,
232 expiration, flags, 0, SET_OP);
233 LIBMEMCACHED_MEMCACHED_SET_END();
234 return rc;
235 }
236
237 memcached_return memcached_add_by_key(memcached_st *ptr,
238 char *master_key, size_t master_key_length,
239 char *key, size_t key_length,
240 char *value, size_t value_length,
241 time_t expiration,
242 uint32_t flags)
243 {
244 memcached_return rc;
245 LIBMEMCACHED_MEMCACHED_ADD_START();
246 rc= memcached_send(ptr, key, key_length,
247 key, key_length, value, value_length,
248 expiration, flags, 0, ADD_OP);
249 LIBMEMCACHED_MEMCACHED_ADD_END();
250 return rc;
251 }
252
253 memcached_return memcached_replace_by_key(memcached_st *ptr,
254 char *master_key, size_t master_key_length,
255 char *key, size_t key_length,
256 char *value, size_t value_length,
257 time_t expiration,
258 uint32_t flags)
259 {
260 memcached_return rc;
261 LIBMEMCACHED_MEMCACHED_REPLACE_START();
262 rc= memcached_send(ptr, key, key_length,
263 key, key_length, value, value_length,
264 expiration, flags, 0, REPLACE_OP);
265 LIBMEMCACHED_MEMCACHED_REPLACE_END();
266 return rc;
267 }
268
269 memcached_return memcached_prepend_by_key(memcached_st *ptr,
270 char *master_key, size_t master_key_length,
271 char *key, size_t key_length,
272 char *value, size_t value_length,
273 time_t expiration,
274 uint32_t flags)
275 {
276 memcached_return rc;
277 rc= memcached_send(ptr, key, key_length,
278 key, key_length, value, value_length,
279 expiration, flags, 0, PREPEND_OP);
280 return rc;
281 }
282
283 memcached_return memcached_append_by_key(memcached_st *ptr,
284 char *master_key, size_t master_key_length,
285 char *key, size_t key_length,
286 char *value, size_t value_length,
287 time_t expiration,
288 uint32_t flags)
289 {
290 memcached_return rc;
291 rc= memcached_send(ptr, key, key_length,
292 key, key_length, value, value_length,
293 expiration, flags, 0, APPEND_OP);
294 return rc;
295 }
296
297 memcached_return memcached_cas_by_key(memcached_st *ptr,
298 char *master_key, size_t master_key_length,
299 char *key, size_t key_length,
300 char *value, size_t value_length,
301 time_t expiration,
302 uint32_t flags,
303 uint64_t cas)
304 {
305 memcached_return rc;
306 rc= memcached_send(ptr, key, key_length,
307 key, key_length, value, value_length,
308 expiration, flags, cas, CAS_OP);
309 return rc;
310 }