e810b64ae326608c0d222699d9f4c72271f98be6
[awesomized/libmemcached] / libmemcached / memcached_fetch.c
1 #include "common.h"
2 #include "memcached_io.h"
3
4 memcached_return value_fetch(memcached_server_st *ptr,
5 char *buffer,
6 memcached_result_st *result)
7 {
8 memcached_return rc= MEMCACHED_SUCCESS;
9 char *string_ptr;
10 char *end_ptr;
11 char *next_ptr;
12 size_t value_length;
13 size_t read_length;
14 size_t to_read;
15 char *value_ptr;
16
17 if (ptr->root->flags & MEM_USE_UDP)
18 return MEMCACHED_NOT_SUPPORTED;
19
20 WATCHPOINT_ASSERT(ptr->root);
21 end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
22
23 memcached_result_reset(result);
24
25 string_ptr= buffer;
26 string_ptr+= 6; /* "VALUE " */
27
28
29 /* We load the key */
30 {
31 char *key;
32 size_t prefix_length;
33
34 key= result->key;
35 result->key_length= 0;
36
37 for (prefix_length= ptr->root->prefix_key_length; !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
38 {
39 if (prefix_length == 0)
40 {
41 *key= *string_ptr;
42 key++;
43 result->key_length++;
44 }
45 else
46 prefix_length--;
47 }
48 result->key[result->key_length]= 0;
49 }
50
51 if (end_ptr == string_ptr)
52 goto read_error;
53
54 /* Flags fetch move past space */
55 string_ptr++;
56 if (end_ptr == string_ptr)
57 goto read_error;
58 for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
59 result->flags= strtoul(next_ptr, &string_ptr, 10);
60
61 if (end_ptr == string_ptr)
62 goto read_error;
63
64 /* Length fetch move past space*/
65 string_ptr++;
66 if (end_ptr == string_ptr)
67 goto read_error;
68
69 for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
70 value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
71
72 if (end_ptr == string_ptr)
73 goto read_error;
74
75 /* Skip spaces */
76 if (*string_ptr == '\r')
77 {
78 /* Skip past the \r\n */
79 string_ptr+= 2;
80 }
81 else
82 {
83 string_ptr++;
84 for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
85 result->cas= strtoull(next_ptr, &string_ptr, 10);
86 }
87
88 if (end_ptr < string_ptr)
89 goto read_error;
90
91 /* We add two bytes so that we can walk the \r\n */
92 rc= memcached_string_check(&result->value, value_length+2);
93 if (rc != MEMCACHED_SUCCESS)
94 {
95 value_length= 0;
96 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
97 }
98
99 value_ptr= memcached_string_value(&result->value);
100 read_length= 0;
101 /*
102 We read the \r\n into the string since not doing so is more
103 cycles then the waster of memory to do so.
104
105 We are null terminating through, which will most likely make
106 some people lazy about using the return length.
107 */
108 to_read= (value_length) + 2;
109 read_length= memcached_io_read(ptr, value_ptr, to_read);
110 if (read_length != (size_t)(value_length + 2))
111 {
112 goto read_error;
113 }
114
115 /* This next bit blows the API, but this is internal....*/
116 {
117 char *char_ptr;
118 char_ptr= memcached_string_value(&result->value);;
119 char_ptr[value_length]= 0;
120 char_ptr[value_length + 1]= 0;
121 memcached_string_set_length(&result->value, value_length);
122 }
123
124 return MEMCACHED_SUCCESS;
125
126 read_error:
127 memcached_io_reset(ptr);
128
129 return MEMCACHED_PARTIAL_READ;
130 }
131
132 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
133 size_t *value_length,
134 uint32_t *flags,
135 memcached_return *error)
136 {
137 memcached_result_st *result_buffer= &ptr->result;
138
139 if (ptr->flags & MEM_USE_UDP)
140 {
141 *error= MEMCACHED_NOT_SUPPORTED;
142 return NULL;
143 }
144
145 while (ptr->cursor_server < ptr->number_of_hosts)
146 {
147 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
148
149 if (memcached_server_response_count(&ptr->hosts[ptr->cursor_server]) == 0)
150 {
151 ptr->cursor_server++;
152 continue;
153 }
154
155 *error= memcached_response(&ptr->hosts[ptr->cursor_server], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result_buffer);
156
157 if (*error == MEMCACHED_END) /* END means that we move on to the next */
158 {
159 memcached_server_response_reset(&ptr->hosts[ptr->cursor_server]);
160 ptr->cursor_server++;
161 continue;
162 }
163 else if (*error == MEMCACHED_SUCCESS)
164 {
165 *value_length= memcached_string_length(&result_buffer->value);
166
167 if (key)
168 {
169 strncpy(key, result_buffer->key, result_buffer->key_length);
170 *key_length= result_buffer->key_length;
171 }
172
173 if (result_buffer->flags)
174 *flags= result_buffer->flags;
175 else
176 *flags= 0;
177
178 return memcached_string_c_copy(&result_buffer->value);
179 }
180 else
181 {
182 *value_length= 0;
183 return NULL;
184 }
185 }
186
187 ptr->cursor_server= 0;
188 *value_length= 0;
189 return NULL;
190 }
191
192 memcached_result_st *memcached_fetch_result(memcached_st *ptr,
193 memcached_result_st *result,
194 memcached_return *error)
195 {
196
197 if (ptr->flags & MEM_USE_UDP)
198 {
199 *error= MEMCACHED_NOT_SUPPORTED;
200 return NULL;
201 }
202
203 if (result == NULL)
204 result= memcached_result_create(ptr, NULL);
205
206 #ifdef UNUSED
207 if (ptr->flags & MEM_NO_BLOCK)
208 memcached_io_preread(ptr);
209 #endif
210
211 while (ptr->cursor_server < ptr->number_of_hosts)
212 {
213 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
214
215 if (memcached_server_response_count(&ptr->hosts[ptr->cursor_server]) == 0)
216 {
217 ptr->cursor_server++;
218 continue;
219 }
220
221 *error= memcached_response(&ptr->hosts[ptr->cursor_server], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result);
222
223 if (*error == MEMCACHED_END) /* END means that we move on to the next */
224 {
225 memcached_server_response_reset(&ptr->hosts[ptr->cursor_server]);
226 ptr->cursor_server++;
227 continue;
228 }
229 else if (*error == MEMCACHED_SUCCESS)
230 return result;
231 else
232 return NULL;
233 }
234
235 /* We have completed reading data */
236 if (result->is_allocated)
237 memcached_result_free(result);
238 else
239 memcached_string_reset(&result->value);
240
241 ptr->cursor_server= 0;
242 return NULL;
243 }