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