6b76375cdb20bd62505f9ee5e5fcec5061af048e
[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 } memcached_storage_action;
18
19 /* Inline this */
20 #define storage_op_string(A) A == SET_OP ? "set" : ( A == REPLACE_OP ? "replace" : "add")
21
22 static memcached_return memcached_send(memcached_st *ptr,
23 char *key, size_t key_length,
24 char *value, size_t value_length,
25 time_t expiration,
26 uint16_t flags,
27 memcached_storage_action verb)
28 {
29 size_t write_length;
30 ssize_t sent_length;
31 memcached_return rc;
32 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
33 unsigned int server_key;
34
35 assert(value);
36 assert(value_length);
37
38 memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE);
39
40 /* Leaveing this assert in since only a library fubar could blow this */
41 assert(ptr->write_buffer_offset == 0);
42
43 server_key= memcached_generate_hash(ptr, key, key_length);
44
45 rc= memcached_connect(ptr, server_key);
46 if (rc != MEMCACHED_SUCCESS)
47 return rc;
48
49 write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
50 "%s %.*s %x %llu %zu\r\n", storage_op_string(verb),
51 (int)key_length, key, flags,
52 (unsigned long long)expiration, value_length);
53 if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
54 {
55 rc= MEMCACHED_WRITE_FAILURE;
56 goto error;
57 }
58
59 /*
60 We have to flush after sending the command. Memcached is not smart enough
61 to just keep reading from the socket :(
62 */
63 if ((sent_length= memcached_io_write(ptr, server_key, buffer, write_length, 1)) == -1)
64 {
65 rc= MEMCACHED_WRITE_FAILURE;
66 goto error;
67 }
68
69 if ((sent_length= memcached_io_write(ptr, server_key, value, value_length, 0)) == -1)
70 {
71 rc= MEMCACHED_WRITE_FAILURE;
72 goto error;
73 }
74
75 if ((sent_length= memcached_io_write(ptr, server_key, "\r\n", 2, 1)) == -1)
76 {
77 rc= MEMCACHED_WRITE_FAILURE;
78 goto error;
79 }
80
81 if ((ptr->flags & MEM_NO_BLOCK) && verb == SET_OP)
82 {
83 rc= MEMCACHED_SUCCESS;
84 ptr->stack_responses++;
85 }
86 else
87 {
88 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
89 }
90
91 if (rc == MEMCACHED_STORED)
92 return MEMCACHED_SUCCESS;
93 else
94 return rc;
95
96 error:
97 memcached_io_reset(ptr, server_key);
98
99 return rc;
100 }
101
102 memcached_return memcached_set(memcached_st *ptr, char *key, size_t key_length,
103 char *value, size_t value_length,
104 time_t expiration,
105 uint16_t flags)
106 {
107 memcached_return rc;
108 LIBMEMCACHED_MEMCACHED_SET_START();
109 rc= memcached_send(ptr, key, key_length, value, value_length,
110 expiration, flags, SET_OP);
111 LIBMEMCACHED_MEMCACHED_SET_END();
112 return rc;
113 }
114
115 memcached_return memcached_add(memcached_st *ptr, char *key, size_t key_length,
116 char *value, size_t value_length,
117 time_t expiration,
118 uint16_t flags)
119 {
120 memcached_return rc;
121 LIBMEMCACHED_MEMCACHED_ADD_START();
122 rc= memcached_send(ptr, key, key_length, value, value_length,
123 expiration, flags, ADD_OP);
124 LIBMEMCACHED_MEMCACHED_ADD_END();
125 return rc;
126 }
127
128 memcached_return memcached_replace(memcached_st *ptr, char *key, size_t key_length,
129 char *value, size_t value_length,
130 time_t expiration,
131 uint16_t flags)
132 {
133 memcached_return rc;
134 LIBMEMCACHED_MEMCACHED_REPLACE_START();
135 rc= memcached_send(ptr, key, key_length, value, value_length,
136 expiration, flags, REPLACE_OP);
137 LIBMEMCACHED_MEMCACHED_REPLACE_END();
138 return rc;
139 }