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