Portability patches from Kevin Dalley for Freebsd 4.0.
[m6w6/libmemcached] / lib / memcached_fetch.c
1 #include "common.h"
2 #include "memcached_io.h"
3
4 memcached_return value_fetch(memcached_st *ptr,
5 char *buffer,
6 memcached_result_st *result,
7 unsigned int server_key)
8 {
9 memcached_return rc;
10 char *string_ptr;
11 char *end_ptr;
12 char *next_ptr;
13 size_t value_length;
14
15 end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
16
17 result->key_length= 0;
18 result->flags= 0;
19 memcached_string_reset(&result->value);
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 }
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, server_key,
107 value_ptr, to_read);
108
109 if (read_length != (size_t)(value_length + 2))
110 {
111 goto read_error;
112 }
113
114 /* This next bit blows the API, but this is internal....*/
115 {
116 char *char_ptr;
117 char_ptr= memcached_string_value(&result->value);;
118 char_ptr[value_length]= 0;
119 char_ptr[value_length + 1]= 0;
120 memcached_string_set_length(&result->value, value_length);
121 }
122
123 return MEMCACHED_SUCCESS;
124 }
125
126 return rc;
127
128 read_error:
129 return MEMCACHED_PARTIAL_READ;
130 }
131
132 char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length,
133 size_t *value_length,
134 uint32_t *flags,
135 memcached_return *error)
136 {
137 memcached_result_st *result_buffer= &ptr->result;
138
139 while (ptr->cursor_server < ptr->number_of_hosts)
140 {
141 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
142
143 if (memcached_server_response_count(ptr, ptr->cursor_server) == 0)
144 {
145 ptr->cursor_server++;
146 continue;
147 }
148
149 *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result_buffer, ptr->cursor_server);
150
151 if (*error == MEMCACHED_END) /* END means that we move on to the next */
152 {
153 memcached_server_response_reset(ptr, ptr->cursor_server);
154 ptr->cursor_server++;
155 continue;
156 }
157 else if (*error == MEMCACHED_SUCCESS)
158 {
159 *value_length= memcached_string_length(&result_buffer->value);
160
161 if (key)
162 {
163 strncpy(key, result_buffer->key, result_buffer->key_length);
164 *key_length= result_buffer->key_length;
165 }
166 *flags= result_buffer->flags;
167
168 return memcached_string_c_copy(&result_buffer->value);
169 }
170 else
171 {
172 *value_length= 0;
173 return NULL;
174 }
175 }
176
177 ptr->cursor_server= 0;
178 *value_length= 0;
179 return NULL;
180 }
181
182 memcached_result_st *memcached_fetch_result(memcached_st *ptr,
183 memcached_result_st *result,
184 memcached_return *error)
185 {
186 if (result == NULL)
187 result= memcached_result_create(ptr, NULL);
188
189 WATCHPOINT_ASSERT(result->value.is_allocated != MEMCACHED_USED);
190
191 if (ptr->flags & MEM_NO_BLOCK)
192 memcached_io_preread(ptr);
193
194 while (ptr->cursor_server < ptr->number_of_hosts)
195 {
196 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
197
198 if (memcached_server_response_count(ptr, ptr->cursor_server) == 0)
199 {
200 ptr->cursor_server++;
201 continue;
202 }
203
204 *error= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, result, ptr->cursor_server);
205
206 if (*error == MEMCACHED_END) /* END means that we move on to the next */
207 {
208 memcached_server_response_reset(ptr, ptr->cursor_server);
209 ptr->cursor_server++;
210 continue;
211 }
212 else if (*error == MEMCACHED_SUCCESS)
213 return result;
214 else
215 return NULL;
216 }
217
218 /* We have completed reading data */
219 if (result->is_allocated == MEMCACHED_ALLOCATED)
220 memcached_result_free(result);
221 else
222 memcached_string_reset(&result->value);
223
224 ptr->cursor_server= 0;
225 return NULL;
226 }