Fix problem with bumping the command counter _before_ connecting to the server
[m6w6/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 if (ptr->flags.binary_protocol)
17 return memcached_version_binary(ptr);
18 else
19 return memcached_version_textual(ptr);
20 }
21
22 static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
23 {
24 unsigned int x;
25 size_t send_length;
26 memcached_return_t rc;
27 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
28 char *response_ptr;
29 const char *command= "version\r\n";
30
31 send_length= strlen(command);
32
33 rc= MEMCACHED_SUCCESS;
34 for (x= 0; x < ptr->number_of_hosts; x++)
35 {
36 memcached_return_t rrc;
37
38 rrc= memcached_do(&ptr->hosts[x], command, send_length, 1);
39 if (rrc != MEMCACHED_SUCCESS)
40 {
41 rc= MEMCACHED_SOME_ERRORS;
42 continue;
43 }
44
45 rrc= memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
46 if (rrc != MEMCACHED_SUCCESS)
47 {
48 rc= MEMCACHED_SOME_ERRORS;
49 continue;
50 }
51
52 /* Find the space, and then move one past it to copy version */
53 response_ptr= index(buffer, ' ');
54 response_ptr++;
55
56 ptr->hosts[x].major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
57 response_ptr= index(response_ptr, '.');
58 response_ptr++;
59 ptr->hosts[x].minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
60 response_ptr= index(response_ptr, '.');
61 response_ptr++;
62 ptr->hosts[x].micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
63 }
64
65 return rc;
66 }
67
68 static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
69 {
70 memcached_return_t rc;
71 unsigned int x;
72 protocol_binary_request_version request= { .bytes= {0}};
73 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
74 request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
75 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
76
77 rc= MEMCACHED_SUCCESS;
78 for (x= 0; x < ptr->number_of_hosts; x++)
79 {
80 memcached_return_t rrc;
81
82 rrc= memcached_do(&ptr->hosts[x], request.bytes, sizeof(request.bytes), 1);
83 if (rrc != MEMCACHED_SUCCESS)
84 {
85 memcached_io_reset(&ptr->hosts[x]);
86 rc= MEMCACHED_SOME_ERRORS;
87 continue;
88 }
89 }
90
91 for (x= 0; x < ptr->number_of_hosts; x++)
92 if (memcached_server_response_count(&ptr->hosts[x]) > 0)
93 {
94 memcached_return_t rrc;
95 char buffer[32];
96 char *p;
97
98 rrc= memcached_response(&ptr->hosts[x], buffer, sizeof(buffer), NULL);
99 if (rrc != MEMCACHED_SUCCESS)
100 {
101 memcached_io_reset(&ptr->hosts[x]);
102 rc= MEMCACHED_SOME_ERRORS;
103 continue;
104 }
105
106 ptr->hosts[x].major_version= (uint8_t)strtol(buffer, &p, 10);
107 ptr->hosts[x].minor_version= (uint8_t)strtol(p + 1, &p, 10);
108 ptr->hosts[x].micro_version= (uint8_t)strtol(p + 1, NULL, 10);
109 }
110
111 return rc;
112 }