New version update
[m6w6/libmemcached] / libmemcached / memcached_response.c
1 /*
2 Memcached library
3
4 memcached_response() is used to determine the return result
5 from an issued command.
6 */
7
8 #include "common.h"
9 #include "memcached_io.h"
10
11 memcached_return memcached_response(memcached_server_st *ptr,
12 char *buffer, size_t buffer_length,
13 memcached_result_st *result)
14 {
15 unsigned int x;
16 size_t send_length;
17 char *buffer_ptr;
18 unsigned int max_messages;
19
20
21 send_length= 0;
22 /* UDP at the moment is odd...*/
23 if (ptr->type == MEMCACHED_CONNECTION_UDP)
24 {
25 char buffer[8];
26 ssize_t read_length;
27
28 return MEMCACHED_SUCCESS;
29
30 read_length= memcached_io_read(ptr, buffer, 8);
31 }
32
33 /* We may have old commands in the buffer not set, first purge */
34 if (ptr->root->flags & MEM_NO_BLOCK)
35 (void)memcached_io_write(ptr, NULL, 0, 1);
36
37 max_messages= memcached_server_response_count(ptr);
38 for (x= 0; x < max_messages; x++)
39 {
40 size_t total_length= 0;
41 buffer_ptr= buffer;
42
43
44 while (1)
45 {
46 ssize_t read_length;
47
48 read_length= memcached_io_read(ptr, buffer_ptr, 1);
49 WATCHPOINT_ASSERT(isgraph(*buffer_ptr) || isspace(*buffer_ptr));
50
51 if (read_length != 1)
52 {
53 memcached_io_reset(ptr);
54 return MEMCACHED_UNKNOWN_READ_FAILURE;
55 }
56
57 if (*buffer_ptr == '\n')
58 break;
59 else
60 buffer_ptr++;
61
62 total_length++;
63 WATCHPOINT_ASSERT(total_length <= buffer_length);
64
65 if (total_length >= buffer_length)
66 {
67 memcached_io_reset(ptr);
68 return MEMCACHED_PROTOCOL_ERROR;
69 }
70 }
71 buffer_ptr++;
72 *buffer_ptr= 0;
73
74 memcached_server_response_decrement(ptr);
75 }
76
77 switch(buffer[0])
78 {
79 case 'V': /* VALUE || VERSION */
80 if (buffer[1] == 'A') /* VALUE */
81 {
82 memcached_return rc;
83
84 /* We add back in one because we will need to search for END */
85 memcached_server_response_increment(ptr);
86 if (result)
87 rc= value_fetch(ptr, buffer, result);
88 else
89 rc= value_fetch(ptr, buffer, &ptr->root->result);
90
91 return rc;
92 }
93 else if (buffer[1] == 'E') /* VERSION */
94 {
95 return MEMCACHED_SUCCESS;
96 }
97 else
98 {
99 WATCHPOINT_STRING(buffer);
100 WATCHPOINT_ASSERT(0);
101 memcached_io_reset(ptr);
102 return MEMCACHED_UNKNOWN_READ_FAILURE;
103 }
104 case 'O': /* OK */
105 return MEMCACHED_SUCCESS;
106 case 'S': /* STORED STATS SERVER_ERROR */
107 {
108 if (buffer[2] == 'A') /* STORED STATS */
109 {
110 memcached_server_response_increment(ptr);
111 return MEMCACHED_STAT;
112 }
113 else if (buffer[1] == 'E')
114 return MEMCACHED_SERVER_ERROR;
115 else if (buffer[1] == 'T')
116 return MEMCACHED_STORED;
117 else
118 {
119 WATCHPOINT_STRING(buffer);
120 WATCHPOINT_ASSERT(0);
121 memcached_io_reset(ptr);
122 return MEMCACHED_UNKNOWN_READ_FAILURE;
123 }
124 }
125 case 'D': /* DELETED */
126 return MEMCACHED_DELETED;
127 case 'N': /* NOT_FOUND */
128 {
129 if (buffer[4] == 'F')
130 return MEMCACHED_NOTFOUND;
131 else if (buffer[4] == 'S')
132 return MEMCACHED_NOTSTORED;
133 else
134 {
135 memcached_io_reset(ptr);
136 return MEMCACHED_UNKNOWN_READ_FAILURE;
137 }
138 }
139 case 'E': /* PROTOCOL ERROR or END */
140 {
141 if (buffer[1] == 'N')
142 return MEMCACHED_END;
143 else if (buffer[1] == 'R')
144 {
145 memcached_io_reset(ptr);
146 return MEMCACHED_PROTOCOL_ERROR;
147 }
148 else if (buffer[1] == 'X')
149 {
150 memcached_io_reset(ptr);
151 return MEMCACHED_DATA_EXISTS;
152 }
153 else
154 {
155 memcached_io_reset(ptr);
156 return MEMCACHED_UNKNOWN_READ_FAILURE;
157 }
158 }
159 case 'C': /* CLIENT ERROR */
160 memcached_io_reset(ptr);
161 return MEMCACHED_CLIENT_ERROR;
162 default:
163 memcached_io_reset(ptr);
164 return MEMCACHED_UNKNOWN_READ_FAILURE;
165
166 }
167
168 return MEMCACHED_SUCCESS;
169 }
170
171 char *memcached_result_value(memcached_result_st *ptr)
172 {
173 memcached_string_st *sptr= &ptr->value;
174 return memcached_string_value(sptr);
175 }
176
177 size_t memcached_result_length(memcached_result_st *ptr)
178 {
179 memcached_string_st *sptr= &ptr->value;
180 return memcached_string_length(sptr);
181 }