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