Fixed bug reported by Stuart Midgley about what happens when there are no
[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 char to_write;
30 size_t write_length;
31 ssize_t sent_length;
32 memcached_return rc;
33 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
34 unsigned int server_key;
35
36 WATCHPOINT_ASSERT(value);
37 WATCHPOINT_ASSERT(value_length);
38
39 /* Leaving this WATCHPOINT_ASSERT in since only a library fubar could blow this */
40 #ifdef NOT_DONE
41 if (!(ptr->flags & MEM_NO_BLOCK) && ptr->write_buffer_offset != 0)
42 WATCHPOINT_ASSERT(0);
43 #endif
44
45 if (ptr->hosts == NULL || ptr->number_of_hosts == 0)
46 return MEMCACHED_NO_SERVERS;
47
48 server_key= memcached_generate_hash(ptr, key, key_length);
49
50 rc= memcached_connect(ptr, server_key);
51 if (rc != MEMCACHED_SUCCESS)
52 return rc;
53
54
55 write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
56 "%s %.*s %x %llu %zu\r\n", storage_op_string(verb),
57 (int)key_length, key, flags,
58 (unsigned long long)expiration, value_length);
59 if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
60 {
61 rc= MEMCACHED_WRITE_FAILURE;
62 goto error;
63 }
64
65 /*
66 We have to flush after sending the command. Memcached is not smart enough
67 to just keep reading from the socket :(
68 */
69 if ((sent_length= memcached_io_write(ptr, server_key, buffer, write_length, 0)) == -1)
70 {
71 rc= MEMCACHED_WRITE_FAILURE;
72 goto error;
73 }
74
75 if ((sent_length= memcached_io_write(ptr, server_key, value, value_length, 0)) == -1)
76 {
77 rc= MEMCACHED_WRITE_FAILURE;
78 goto error;
79 }
80
81 if ((ptr->flags & MEM_NO_BLOCK) && verb == SET_OP)
82 to_write= 0;
83 else
84 to_write= 1;
85
86 if ((sent_length= memcached_io_write(ptr, server_key, "\r\n", 2, to_write)) == -1)
87 {
88 memcached_quit_server(ptr, server_key);
89 rc= MEMCACHED_WRITE_FAILURE;
90 goto error;
91 }
92
93 if ((ptr->flags & MEM_NO_BLOCK) && verb == SET_OP)
94 {
95 rc= MEMCACHED_SUCCESS;
96 memcached_server_response_increment(ptr, server_key);
97 }
98 else
99 {
100 rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
101 }
102
103 if (rc == MEMCACHED_STORED)
104 return MEMCACHED_SUCCESS;
105 else
106 return rc;
107
108 error:
109 memcached_io_reset(ptr, server_key);
110
111 return rc;
112 }
113
114 memcached_return memcached_set(memcached_st *ptr, char *key, size_t key_length,
115 char *value, size_t value_length,
116 time_t expiration,
117 uint16_t flags)
118 {
119 memcached_return rc;
120 LIBMEMCACHED_MEMCACHED_SET_START();
121 rc= memcached_send(ptr, key, key_length, value, value_length,
122 expiration, flags, SET_OP);
123 LIBMEMCACHED_MEMCACHED_SET_END();
124 return rc;
125 }
126
127 memcached_return memcached_add(memcached_st *ptr, char *key, size_t key_length,
128 char *value, size_t value_length,
129 time_t expiration,
130 uint16_t flags)
131 {
132 memcached_return rc;
133 LIBMEMCACHED_MEMCACHED_ADD_START();
134 rc= memcached_send(ptr, key, key_length, value, value_length,
135 expiration, flags, ADD_OP);
136 LIBMEMCACHED_MEMCACHED_ADD_END();
137 return rc;
138 }
139
140 memcached_return memcached_replace(memcached_st *ptr, char *key, size_t key_length,
141 char *value, size_t value_length,
142 time_t expiration,
143 uint16_t flags)
144 {
145 memcached_return rc;
146 LIBMEMCACHED_MEMCACHED_REPLACE_START();
147 rc= memcached_send(ptr, key, key_length, value, value_length,
148 expiration, flags, REPLACE_OP);
149 LIBMEMCACHED_MEMCACHED_REPLACE_END();
150 return rc;
151 }