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