Fix for non-blocking IO error. The refactoring bit broke some cases where
[m6w6/libmemcached] / lib / 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
23 /* We may have old commands in the buffer not set, first purge */
24 if (ptr->root->flags & MEM_NO_BLOCK)
25 (void)memcached_io_write(ptr, NULL, 0, 1);
26
27 max_messages= memcached_server_response_count(ptr);
28 for (x= 0; x < max_messages; x++)
29 {
30 size_t total_length= 0;
31 buffer_ptr= buffer;
32
33 while (1)
34 {
35 ssize_t read_length;
36
37 read_length= memcached_io_read(ptr, buffer_ptr, 1);
38 WATCHPOINT_ASSERT(isgraph(*buffer_ptr) || isspace(*buffer_ptr));
39
40 if (read_length != 1)
41 return MEMCACHED_UNKNOWN_READ_FAILURE;
42
43 if (*buffer_ptr == '\n')
44 break;
45 else
46 buffer_ptr++;
47
48 total_length++;
49 WATCHPOINT_ASSERT(total_length <= buffer_length);
50
51 if (total_length >= buffer_length)
52 return MEMCACHED_PROTOCOL_ERROR;
53 }
54 buffer_ptr++;
55 *buffer_ptr= 0;
56
57 memcached_server_response_decrement(ptr);
58 }
59
60 switch(buffer[0])
61 {
62 case 'V': /* VALUE || VERSION */
63 if (buffer[1] == 'A') /* VALUE */
64 {
65 memcached_return rc;
66
67 /* We add back in one because we will need to search for END */
68 memcached_server_response_increment(ptr);
69 if (result)
70 rc= value_fetch(ptr, buffer, result);
71 else
72 rc= value_fetch(ptr, buffer, &ptr->root->result);
73
74 return rc;
75 }
76 else if (buffer[1] == 'E') /* VERSION */
77 {
78 return MEMCACHED_SUCCESS;
79 }
80 else
81 {
82 WATCHPOINT_STRING(buffer);
83 WATCHPOINT_ASSERT(0);
84 return MEMCACHED_UNKNOWN_READ_FAILURE;
85 }
86 case 'O': /* OK */
87 return MEMCACHED_SUCCESS;
88 case 'S': /* STORED STATS SERVER_ERROR */
89 {
90 if (buffer[2] == 'A') /* STORED STATS */
91 {
92 memcached_server_response_increment(ptr);
93 return MEMCACHED_STAT;
94 }
95 else if (buffer[1] == 'E')
96 return MEMCACHED_SERVER_ERROR;
97 else if (buffer[1] == 'T')
98 return MEMCACHED_STORED;
99 else
100 {
101 WATCHPOINT_STRING(buffer);
102 WATCHPOINT_ASSERT(0);
103 return MEMCACHED_UNKNOWN_READ_FAILURE;
104 }
105 }
106 case 'D': /* DELETED */
107 return MEMCACHED_DELETED;
108 case 'N': /* NOT_FOUND */
109 {
110 if (buffer[4] == 'F')
111 return MEMCACHED_NOTFOUND;
112 else if (buffer[4] == 'S')
113 return MEMCACHED_NOTSTORED;
114 else
115 return MEMCACHED_UNKNOWN_READ_FAILURE;
116 }
117 case 'E': /* PROTOCOL ERROR or END */
118 {
119 if (buffer[1] == 'N')
120 return MEMCACHED_END;
121 else if (buffer[1] == 'R')
122 return MEMCACHED_PROTOCOL_ERROR;
123 else
124 return MEMCACHED_UNKNOWN_READ_FAILURE;
125 }
126 case 'C': /* CLIENT ERROR */
127 return MEMCACHED_CLIENT_ERROR;
128 default:
129 return MEMCACHED_UNKNOWN_READ_FAILURE;
130
131 }
132
133 return MEMCACHED_SUCCESS;
134 }
135
136 char *memcached_result_value(memcached_result_st *ptr)
137 {
138 memcached_string_st *sptr= &ptr->value;
139 return memcached_string_value(sptr);
140 }
141
142 size_t memcached_result_length(memcached_result_st *ptr)
143 {
144 memcached_string_st *sptr= &ptr->value;
145 return memcached_string_length(sptr);
146 }