Bugfix for memcached_connect() so that it will not always start up servers.
[awesomized/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 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 *key, size_t key_length,
46 char *value, size_t value_length,
47 time_t expiration,
48 uint16_t flags,
49 uint64_t cas,
50 memcached_storage_action verb)
51 {
52 char to_write;
53 size_t write_length;
54 ssize_t sent_length;
55 memcached_return rc;
56 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
57 unsigned int server_key;
58
59 WATCHPOINT_ASSERT(!(value == NULL && value_length > 0));
60 WATCHPOINT_ASSERT(!(value && value_length == 0));
61
62 if (key_length == 0)
63 return MEMCACHED_NO_KEY_PROVIDED;
64
65 if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
66 return MEMCACHED_NO_SERVERS;
67
68 server_key= memcached_generate_hash(ptr, key, key_length);
69
70 rc= memcached_connect(ptr, server_key);
71 if (rc != MEMCACHED_SUCCESS)
72 return rc;
73
74
75 if (cas)
76 write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
77 "%s %.*s %u %llu %zu %llu\r\n", storage_op_string(verb),
78 (int)key_length, key, flags,
79 (unsigned long long)expiration, value_length,
80 (unsigned long long)cas);
81 else
82 write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
83 "%s %.*s %u %llu %zu\r\n", storage_op_string(verb),
84 (int)key_length, key, flags,
85 (unsigned long long)expiration, value_length);
86
87 if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
88 {
89 rc= MEMCACHED_WRITE_FAILURE;
90 goto error;
91 }
92
93 /*
94 We have to flush after sending the command. Memcached is not smart enough
95 to just keep reading from the socket :(
96 */
97 if ((sent_length= memcached_io_write(ptr, server_key, buffer, write_length, 0)) == -1)
98 {
99 rc= MEMCACHED_WRITE_FAILURE;
100 goto error;
101 }
102
103 if ((sent_length= memcached_io_write(ptr, server_key, value, value_length, 0)) == -1)
104 {
105 rc= MEMCACHED_WRITE_FAILURE;
106 goto error;
107 }
108
109 if ((ptr->flags & MEM_NO_BLOCK) && verb == SET_OP)
110 to_write= 0;
111 else
112 to_write= 1;
113
114 if ((sent_length= memcached_io_write(ptr, server_key, "\r\n", 2, to_write)) == -1)
115 {
116 memcached_quit_server(ptr, server_key);
117 rc= MEMCACHED_WRITE_FAILURE;
118 goto error;
119 }
120
121 if ((ptr->flags & MEM_NO_BLOCK) && verb == SET_OP)
122 {
123 rc= MEMCACHED_SUCCESS;
124 memcached_server_response_increment(ptr, server_key);
125 }
126 else
127 {
128 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
129 }
130 if (rc == MEMCACHED_STORED)
131 return MEMCACHED_SUCCESS;
132 else
133 return rc;
134
135 error:
136 memcached_io_reset(ptr, server_key);
137
138 return rc;
139 }
140
141 memcached_return memcached_set(memcached_st *ptr, char *key, size_t key_length,
142 char *value, size_t value_length,
143 time_t expiration,
144 uint16_t flags)
145 {
146 memcached_return rc;
147 LIBMEMCACHED_MEMCACHED_SET_START();
148 rc= memcached_send(ptr, key, key_length, value, value_length,
149 expiration, flags, 0, SET_OP);
150 LIBMEMCACHED_MEMCACHED_SET_END();
151 return rc;
152 }
153
154 memcached_return memcached_add(memcached_st *ptr,
155 char *key, size_t key_length,
156 char *value, size_t value_length,
157 time_t expiration,
158 uint16_t flags)
159 {
160 memcached_return rc;
161 LIBMEMCACHED_MEMCACHED_ADD_START();
162 rc= memcached_send(ptr, key, key_length, value, value_length,
163 expiration, flags, 0, ADD_OP);
164 LIBMEMCACHED_MEMCACHED_ADD_END();
165 return rc;
166 }
167
168 memcached_return memcached_replace(memcached_st *ptr,
169 char *key, size_t key_length,
170 char *value, size_t value_length,
171 time_t expiration,
172 uint16_t flags)
173 {
174 memcached_return rc;
175 LIBMEMCACHED_MEMCACHED_REPLACE_START();
176 rc= memcached_send(ptr, key, key_length, value, value_length,
177 expiration, flags, 0, REPLACE_OP);
178 LIBMEMCACHED_MEMCACHED_REPLACE_END();
179 return rc;
180 }
181
182 memcached_return memcached_prepend(memcached_st *ptr,
183 char *key, size_t key_length,
184 char *value, size_t value_length,
185 time_t expiration,
186 uint16_t flags)
187 {
188 memcached_return rc;
189 rc= memcached_send(ptr, 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 uint16_t flags)
199 {
200 memcached_return rc;
201 rc= memcached_send(ptr, key, key_length, value, value_length,
202 expiration, flags, 0, APPEND_OP);
203 return rc;
204 }
205
206 memcached_return memcached_cas(memcached_st *ptr,
207 char *key, size_t key_length,
208 char *value, size_t value_length,
209 time_t expiration,
210 uint16_t flags,
211 uint64_t cas)
212 {
213 memcached_return rc;
214 rc= memcached_send(ptr, key, key_length, value, value_length,
215 expiration, flags, cas, APPEND_OP);
216 return rc;
217 }