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