9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
18 memcached_st
*memcached_init(memcached_st
*ptr
)
22 ptr
= (memcached_st
*)malloc(sizeof(memcached_st
));
25 return NULL
; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
27 memset(ptr
, 0, sizeof(memcached_st
));
28 ptr
->is_allocated
= MEMCACHED_ALLOCATED
;
32 memset(ptr
, 0, sizeof(memcached_st
));
39 void memcached_server_add(memcached_st
*ptr
, char *server_name
, unsigned int port
)
43 static memcached_return
memcached_connect(memcached_st
*ptr
)
46 struct sockaddr_in localAddr
, servAddr
;
48 char *server_name
= "localhost";
51 return MEMCACHED_SUCCESS
;
54 if ((h
= gethostbyname(server_name
)) == NULL
)
56 fprintf(stderr
, "unknown host '%s'\n", server_name
);
57 return MEMCACHED_HOST_LOCKUP_FAILURE
;
60 servAddr
.sin_family
= h
->h_addrtype
;
61 memcpy((char *) &servAddr
.sin_addr
.s_addr
, h
->h_addr_list
[0], h
->h_length
);
62 servAddr
.sin_port
= htons(MEMCACHED_DEFAULT_PORT
);
64 /* Create the socket */
65 if ((ptr
->fd
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
67 fprintf(stderr
, "cannot open socket");
68 return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE
;
72 /* bind any port number */
73 localAddr
.sin_family
= AF_INET
;
74 localAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
75 localAddr
.sin_port
= htons(0);
77 if (bind(ptr
->fd
, (struct sockaddr
*) &localAddr
, sizeof(localAddr
)) < 0)
79 fprintf(stderr
, "cannot bind port TCP %u\n", MEMCACHED_DEFAULT_PORT
);
80 return(MEMCACHED_CONNECTION_BIND_FAILURE
);
83 /* connect to server */
84 if (connect(ptr
->fd
, (struct sockaddr
*) &servAddr
, sizeof(servAddr
)) < 0)
86 fprintf(stderr
, "cannot connect to host '%s'\n", server_name
);
87 return MEMCACHED_HOST_LOCKUP_FAILURE
;
92 return MEMCACHED_SUCCESS
;
95 static memcached_return
memcached_response(memcached_st
*ptr
,
96 char *buffer
, size_t buffer_length
)
99 send_length
= read(ptr
->fd
, buffer
, buffer_length
);
101 /* This should never happen, if it does it means that key must now be quite large. */
102 assert(send_length
!= buffer_length
);
107 case 'V': /* VALUE */
108 return MEMCACHED_SUCCESS
;
110 return MEMCACHED_SUCCESS
;
111 case 'S': /* STORED */
113 if (buffer
[1] == 'T')
114 return MEMCACHED_SUCCESS
;
115 else if (buffer
[1] == 'E')
116 return MEMCACHED_SERVER_ERROR
;
118 return MEMCACHED_UNKNOWN_READ_FAILURE
;
120 case 'D': /* DELETED */
121 return MEMCACHED_SUCCESS
;
122 case 'N': /* NOT_FOUND */
124 if (buffer
[4] == 'F')
125 return MEMCACHED_NOTFOUND
;
126 else if (buffer
[4] == 'S')
127 return MEMCACHED_NOTSTORED
;
129 return MEMCACHED_UNKNOWN_READ_FAILURE
;
131 case 'E': /* PROTOCOL ERROR */
132 return MEMCACHED_PROTOCOL_ERROR
;
133 case 'C': /* CLIENT ERROR */
134 return MEMCACHED_CLIENT_ERROR
;
136 return MEMCACHED_UNKNOWN_READ_FAILURE
;
139 return MEMCACHED_READ_FAILURE
;
142 static memcached_return
memcached_send(memcached_st
*ptr
,
143 char *key
, size_t key_length
,
144 char *value
, size_t value_length
,
151 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
153 rc
= memcached_connect(ptr
);
155 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
156 "%s %.*s %u %u %u\r\n", verb
,
157 key_length
, key
, flags
, expiration
, value_length
);
158 if ((send(ptr
->fd
, buffer
, send_length
, 0) == -1))
160 fprintf(stderr
, "failed set on %.*s TCP\n", key_length
+1, key
);
162 return MEMCACHED_WRITE_FAILURE
;
165 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
167 value_length
, value
);
168 if ((send(ptr
->fd
, buffer
, send_length
, 0) == -1))
170 fprintf(stderr
, "failed set on %.*s TCP\n", key_length
+1, key
);
172 return MEMCACHED_WRITE_FAILURE
;
175 send_length
= read(ptr
->fd
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
);
177 if (send_length
&& buffer
[0] == 'S') /* STORED */
178 return MEMCACHED_SUCCESS
;
179 else if (send_length
&& buffer
[0] == 'N') /* NOT_STORED */
180 return MEMCACHED_NOTSTORED
;
182 return MEMCACHED_READ_FAILURE
;
185 memcached_return
memcached_set(memcached_st
*ptr
, char *key
, size_t key_length
,
186 char *value
, size_t value_length
,
190 return memcached_send(ptr
, key
, key_length
, value
, value_length
,
191 expiration
, flags
, "set");
194 memcached_return
memcached_add(memcached_st
*ptr
, char *key
, size_t key_length
,
195 char *value
, size_t value_length
,
199 return memcached_send(ptr
, key
, key_length
, value
, value_length
,
200 expiration
, flags
, "add");
203 memcached_return
memcached_replace(memcached_st
*ptr
, char *key
, size_t key_length
,
204 char *value
, size_t value_length
,
208 return memcached_send(ptr
, key
, key_length
, value
, value_length
,
209 expiration
, flags
, "replace");
212 memcached_return
memcached_delete(memcached_st
*ptr
, char *key
, size_t key_length
,
217 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
219 rc
= memcached_connect(ptr
);
222 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
223 "delete %.*s %u\r\n", key_length
, key
, expiration
);
225 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
226 "delete %.*s\r\n", key_length
, key
);
227 if ((write(ptr
->fd
, buffer
, send_length
) == -1))
229 fprintf(stderr
, "failed set on %.*s TCP\n", key_length
+1, key
);
231 return MEMCACHED_WRITE_FAILURE
;
234 return memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
);
237 memcached_return
memcached_increment(memcached_st
*ptr
, char *key
, size_t key_length
,
240 return MEMCACHED_SUCCESS
;
243 memcached_return
memcached_decrement(memcached_st
*ptr
, char *key
, size_t key_length
,
246 return MEMCACHED_SUCCESS
;
249 memcached_return
memcached_stat(memcached_st
*ptr
, memcached_stat_st
*stat
)
253 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
255 rc
= memcached_connect(ptr
);
257 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
259 if ((send(ptr
->fd
, buffer
, send_length
, 0) == -1))
261 fprintf(stderr
, "failed on stats\n");
263 return MEMCACHED_WRITE_FAILURE
;
266 while((send_length
= read(ptr
->fd
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
)) > 0)
268 if (send_length
&& buffer
[0] == 'D') /* DELETED */
269 return MEMCACHED_SUCCESS
;
270 else if (send_length
&& buffer
[0] == 'N') /* NOT FOUND */
271 return MEMCACHED_NOTFOUND
;
272 else if (send_length
&& buffer
[0] == 'E') /* PROTOCOL ERROR */
273 return MEMCACHED_PROTOCOL_ERROR
;
274 else if (send_length
&& buffer
[0] == 'C') /* CLIENT ERROR */
275 return MEMCACHED_CLIENT_ERROR
;
276 else if (send_length
&& buffer
[0] == 'S') /* SERVER ERROR */
277 return MEMCACHED_SERVER_ERROR
;
278 else if (send_length
) /* UNKNOWN READ FAILURE */
280 fprintf(stderr
, "UNKNOWN %.*s\n", send_length
, buffer
);
281 return MEMCACHED_UNKNOWN_READ_FAILURE
;
284 return MEMCACHED_READ_FAILURE
;
288 memcached_return
memcached_flush(memcached_st
*ptr
, time_t expiration
)
292 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
294 rc
= memcached_connect(ptr
);
297 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
298 "flush_all %u\r\n", expiration
);
300 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
,
302 if ((send(ptr
->fd
, buffer
, send_length
, 0) == -1))
304 fprintf(stderr
, "failed flush_all TCP\n");
306 return MEMCACHED_WRITE_FAILURE
;
309 return memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
);
312 char *memcached_version(memcached_st
*ptr
, memcached_return
*error
)
314 return MEMCACHED_SUCCESS
;
317 memcached_return
memcached_verbosity(memcached_st
*ptr
, unsigned int verbosity
)
319 return MEMCACHED_SUCCESS
;
322 memcached_return
memcached_quit(memcached_st
*ptr
)
324 return MEMCACHED_SUCCESS
;
328 char *memcached_get(memcached_st
*ptr
, char *key
, size_t key_length
,
329 size_t *value_length
,
331 memcached_return
*error
)
334 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
337 *error
= memcached_connect(ptr
);
339 send_length
= snprintf(buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
, "get %.*s\r\n",
341 if (*error
!= MEMCACHED_SUCCESS
)
344 if ((send(ptr
->fd
, buffer
, send_length
, 0) == -1))
346 fprintf(stderr
, "failed fetch on %.*s TCP\n", key_length
+1, key
);
347 *error
= MEMCACHED_WRITE_FAILURE
;
351 memset(buffer
, 0, MEMCACHED_DEFAULT_COMMAND_SIZE
);
352 *error
= memcached_response(ptr
, buffer
, MEMCACHED_DEFAULT_COMMAND_SIZE
);
354 if (*error
== MEMCACHED_SUCCESS
)
359 string_ptr
+= 6; /* "VALUE " */
361 /* We do nothing with the key, since we only asked for one key */
362 for (end_ptr
= string_ptr
; *end_ptr
!= ' '; end_ptr
++);
365 string_ptr
= end_ptr
+ 1;
366 for (end_ptr
= string_ptr
; *end_ptr
!= ' '; end_ptr
++);
367 *flags
= (uint16_t)strtol(string_ptr
, &end_ptr
, 10);
370 string_ptr
= end_ptr
+ 1;
371 for (end_ptr
= string_ptr
; *end_ptr
!= ' '; end_ptr
++);
372 *value_length
= strtoll(string_ptr
, &end_ptr
, 10);
374 /* Skip past the \r\n */
375 string_ptr
= end_ptr
+2;
383 value
= (char *)malloc(*value_length
* sizeof(char));
387 *error
= MEMCACHED_MEMORY_ALLOCATION_FAILURE
;
391 need_to_copy
= (*value_length
< (size_t)(buffer
-string_ptr
))
393 : (size_t)(buffer
-string_ptr
) ;
395 pos_ptr
= memcpy(value
, string_ptr
, need_to_copy
);
397 if ( need_to_copy
> *value_length
)
402 need_to_read
= *value_length
- need_to_copy
;
404 read_length
= read(ptr
->fd
, pos_ptr
, need_to_read
);
405 if (read_length
!= need_to_read
)
408 *error
= MEMCACHED_PARTIAL_READ
;
421 void memcached_deinit(memcached_st
*ptr
)
426 if (ptr
->is_allocated
== MEMCACHED_ALLOCATED
)
429 memset(ptr
, 0, sizeof(memcached_st
));
432 char *memcached_strerror(memcached_st
*ptr
, memcached_return rc
)
436 case MEMCACHED_SUCCESS
:
438 case MEMCACHED_FAILURE
:
440 case MEMCACHED_HOST_LOCKUP_FAILURE
:
441 return "HOSTNAME LOOKUP FAILURE";
442 case MEMCACHED_CONNECTION_FAILURE
:
443 return "CONNECTION FAILURE";
444 case MEMCACHED_CONNECTION_BIND_FAILURE
:
445 return "CONNECTION BIND FAILURE";
446 case MEMCACHED_READ_FAILURE
:
447 return "READ FAILURE";
448 case MEMCACHED_UNKNOWN_READ_FAILURE
:
449 return "UNKNOWN READ FAILURE";
450 case MEMCACHED_PROTOCOL_ERROR
:
451 return "PROTOCOL ERROR";
452 case MEMCACHED_CLIENT_ERROR
:
453 return "CLIENT ERROR";
454 case MEMCACHED_SERVER_ERROR
:
455 return "SERVER ERROR";
456 case MEMCACHED_WRITE_FAILURE
:
457 return "WRITE FAILURE";
458 case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE
:
459 return "CONNECTION SOCKET CREATE FAILURE";
460 case MEMCACHED_DATA_EXISTS
:
461 return "CONNECTION DATA EXISTS";
462 case MEMCACHED_DATA_DOES_NOT_EXIST
:
463 return "CONNECTION DATA DOES NOT EXIST";
464 case MEMCACHED_NOTSTORED
:
466 case MEMCACHED_NOTFOUND
:
468 case MEMCACHED_MEMORY_ALLOCATION_FAILURE
:
469 return "MEMORY ALLOCATION FAILURE";
470 case MEMCACHED_PARTIAL_READ
:
471 return "PARTIAL READ";