37cec5d30366a857b9e99f7e7424170a5ff75326
[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 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 memcached_io_reset(ptr);
121
122 return MEMCACHED_PARTIAL_READ;
123 }
124
125 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
126 size_t *value_length,
127 uint32_t *flags,
128 memcached_return *error)
129 {
130 memcached_result_st *result_buffer= &ptr->result;
131
132 while (ptr->cursor_server < ptr->number_of_hosts)
133 {
134 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
135
136 if (memcached_server_response_count(&ptr->hosts[ptr->cursor_server]) == 0)
137 {
138 ptr->cursor_server++;
139 continue;
140 }
141
142 *error= memcached_response(&ptr->hosts[ptr->cursor_server], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result_buffer);
143
144 if (*error == MEMCACHED_END) /* END means that we move on to the next */
145 {
146 memcached_server_response_reset(&ptr->hosts[ptr->cursor_server]);
147 ptr->cursor_server++;
148 continue;
149 }
150 else if (*error == MEMCACHED_SUCCESS)
151 {
152 *value_length= memcached_string_length(&result_buffer->value);
153
154 if (key)
155 {
156 strncpy(key, result_buffer->key, result_buffer->key_length);
157 *key_length= result_buffer->key_length;
158 }
159
160 if (result_buffer->flags)
161 *flags= result_buffer->flags;
162 else
163 *flags= 0;
164
165 return memcached_string_c_copy(&result_buffer->value);
166 }
167 else
168 {
169 *value_length= 0;
170 return NULL;
171 }
172 }
173
174 ptr->cursor_server= 0;
175 *value_length= 0;
176 return NULL;
177 }
178
179 memcached_result_st *memcached_fetch_result(memcached_st *ptr,
180 memcached_result_st *result,
181 memcached_return *error)
182 {
183 if (result == NULL)
184 result= memcached_result_create(ptr, NULL);
185
186 WATCHPOINT_ASSERT(result->value.is_allocated != MEMCACHED_USED);
187
188 #ifdef UNUSED
189 if (ptr->flags & MEM_NO_BLOCK)
190 memcached_io_preread(ptr);
191 #endif
192
193 while (ptr->cursor_server < ptr->number_of_hosts)
194 {
195 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
196
197 if (memcached_server_response_count(&ptr->hosts[ptr->cursor_server]) == 0)
198 {
199 ptr->cursor_server++;
200 continue;
201 }
202
203 *error= memcached_response(&ptr->hosts[ptr->cursor_server], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result);
204
205 if (*error == MEMCACHED_END) /* END means that we move on to the next */
206 {
207 memcached_server_response_reset(&ptr->hosts[ptr->cursor_server]);
208 ptr->cursor_server++;
209 continue;
210 }
211 else if (*error == MEMCACHED_SUCCESS)
212 return result;
213 else
214 return NULL;
215 }
216
217 /* We have completed reading data */
218 if (result->is_allocated == MEMCACHED_ALLOCATED)
219 memcached_result_free(result);
220 else
221 memcached_string_reset(&result->value);
222
223 ptr->cursor_server= 0;
224 return NULL;
225 }