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