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