Add support for query_id, and fixes a few cases where programmer error can
[awesomized/libmemcached] / libmemcached / version.c
1 #include "common.h"
2
3 const char * memcached_lib_version(void)
4 {
5 return LIBMEMCACHED_VERSION_STRING;
6 }
7
8 static inline memcached_return_t memcached_version_binary(memcached_st *ptr);
9 static inline memcached_return_t memcached_version_textual(memcached_st *ptr);
10
11 memcached_return_t memcached_version(memcached_st *ptr)
12 {
13 if (ptr->flags.use_udp)
14 return MEMCACHED_NOT_SUPPORTED;
15
16 memcached_return_t rc;
17
18 if (ptr->flags.binary_protocol)
19 rc= memcached_version_binary(ptr);
20 else
21 rc= memcached_version_textual(ptr);
22
23 return rc;
24 }
25
26 static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
27 {
28 size_t send_length;
29 memcached_return_t rc;
30 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
31 char *response_ptr;
32 const char *command= "version\r\n";
33
34 send_length= sizeof("version\r\n") -1;
35
36 rc= MEMCACHED_SUCCESS;
37 for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
38 {
39 memcached_return_t rrc;
40 memcached_server_write_instance_st instance=
41 memcached_server_instance_fetch(ptr, x);
42
43 // Optimization, we only fetch version once.
44 if (instance->major_version != UINT8_MAX)
45 continue;
46
47 rrc= memcached_do(instance, command, send_length, true);
48 if (rrc != MEMCACHED_SUCCESS)
49 {
50 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
51 rc= MEMCACHED_SOME_ERRORS;
52 continue;
53 }
54
55 rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
56 if (rrc != MEMCACHED_SUCCESS)
57 {
58 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
59 rc= MEMCACHED_SOME_ERRORS;
60 continue;
61 }
62
63 /* Find the space, and then move one past it to copy version */
64 response_ptr= index(buffer, ' ');
65 response_ptr++;
66
67 instance->major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
68 if (errno == ERANGE)
69 {
70 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
71 rc= MEMCACHED_SOME_ERRORS;
72 continue;
73 }
74
75 response_ptr= index(response_ptr, '.');
76 response_ptr++;
77
78 instance->minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
79 if (errno == ERANGE)
80 {
81 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
82 rc= MEMCACHED_SOME_ERRORS;
83 continue;
84 }
85
86 response_ptr= index(response_ptr, '.');
87 response_ptr++;
88 instance->micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
89 if (errno == ERANGE)
90 {
91 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
92 rc= MEMCACHED_SOME_ERRORS;
93 continue;
94 }
95 }
96
97 return rc;
98 }
99
100 static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
101 {
102 memcached_return_t rc;
103 protocol_binary_request_version request= { .bytes= {0}};
104 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
105 request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
106 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
107
108 rc= MEMCACHED_SUCCESS;
109 for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
110 {
111 memcached_return_t rrc;
112
113 memcached_server_write_instance_st instance=
114 memcached_server_instance_fetch(ptr, x);
115
116 if (instance->major_version != UINT8_MAX)
117 continue;
118
119 rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
120 if (rrc != MEMCACHED_SUCCESS)
121 {
122 memcached_io_reset(instance);
123 rc= MEMCACHED_SOME_ERRORS;
124 continue;
125 }
126 }
127
128 for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
129 {
130 memcached_server_write_instance_st instance=
131 memcached_server_instance_fetch(ptr, x);
132
133 if (instance->major_version != UINT8_MAX)
134 continue;
135
136 if (memcached_server_response_count(instance) > 0)
137 {
138 memcached_return_t rrc;
139 char buffer[32];
140 char *p;
141
142 rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
143 if (rrc != MEMCACHED_SUCCESS)
144 {
145 memcached_io_reset(instance);
146 rc= MEMCACHED_SOME_ERRORS;
147 continue;
148 }
149
150 instance->major_version= (uint8_t)strtol(buffer, &p, 10);
151 if (errno == ERANGE)
152 {
153 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
154 rc= MEMCACHED_SOME_ERRORS;
155 continue;
156 }
157
158 instance->minor_version= (uint8_t)strtol(p + 1, &p, 10);
159 if (errno == ERANGE)
160 {
161 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
162 rc= MEMCACHED_SOME_ERRORS;
163 continue;
164 }
165
166 instance->micro_version= (uint8_t)strtol(p + 1, NULL, 10);
167 if (errno == ERANGE)
168 {
169 instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
170 rc= MEMCACHED_SOME_ERRORS;
171 continue;
172 }
173
174 }
175 }
176
177 return rc;
178 }