dde59066083c970d3c21105babd0d84c959873de
[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 bool was_blocking= ptr->flags.no_block;
17 memcached_return_t rc;
18
19 ptr->flags.no_block= false;
20
21 if (ptr->flags.binary_protocol)
22 rc= memcached_version_binary(ptr);
23 else
24 rc= memcached_version_textual(ptr);
25
26 ptr->flags.no_block= was_blocking;
27
28 return rc;
29 }
30
31 static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
32 {
33 size_t send_length;
34 memcached_return_t rc;
35 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
36 char *response_ptr;
37 const char *command= "version\r\n";
38
39 send_length= strlen(command);
40
41 rc= MEMCACHED_SUCCESS;
42 for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
43 {
44 memcached_return_t rrc;
45 memcached_server_write_instance_st instance=
46 memcached_server_instance_fetch(ptr, x);
47
48 rrc= memcached_do(instance, command, send_length, true);
49 if (rrc != MEMCACHED_SUCCESS)
50 {
51 instance->major_version= instance->minor_version= instance->micro_version= 0;
52 rc= MEMCACHED_SOME_ERRORS;
53 continue;
54 }
55
56 rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
57 if (rrc != MEMCACHED_SUCCESS)
58 {
59 instance->major_version= instance->minor_version= instance->micro_version= 0;
60 rc= MEMCACHED_SOME_ERRORS;
61 continue;
62 }
63
64 /* Find the space, and then move one past it to copy version */
65 response_ptr= index(buffer, ' ');
66 response_ptr++;
67
68 instance->major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
69 if (errno == ERANGE)
70 {
71 instance->major_version= instance->minor_version= instance->micro_version= 0;
72 rc= MEMCACHED_SOME_ERRORS;
73 continue;
74 }
75
76 response_ptr= index(response_ptr, '.');
77 response_ptr++;
78
79 instance->minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
80 if (errno == ERANGE)
81 {
82 instance->major_version= instance->minor_version= instance->micro_version= 0;
83 rc= MEMCACHED_SOME_ERRORS;
84 continue;
85 }
86
87 response_ptr= index(response_ptr, '.');
88 response_ptr++;
89 instance->micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
90 if (errno == ERANGE)
91 {
92 instance->major_version= instance->minor_version= instance->micro_version= 0;
93 rc= MEMCACHED_SOME_ERRORS;
94 continue;
95 }
96 }
97
98 return rc;
99 }
100
101 static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
102 {
103 memcached_return_t rc;
104 protocol_binary_request_version request= { .bytes= {0}};
105 request.message.header.request.magic= PROTOCOL_BINARY_REQ;
106 request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
107 request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
108
109 rc= MEMCACHED_SUCCESS;
110 for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
111 {
112 memcached_return_t rrc;
113
114 memcached_server_write_instance_st instance=
115 memcached_server_instance_fetch(ptr, x);
116
117 rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
118 if (rrc != MEMCACHED_SUCCESS)
119 {
120 memcached_io_reset(instance);
121 rc= MEMCACHED_SOME_ERRORS;
122 continue;
123 }
124 }
125
126 for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
127 {
128 memcached_server_write_instance_st instance=
129 memcached_server_instance_fetch(ptr, x);
130
131 if (memcached_server_response_count(instance) > 0)
132 {
133 memcached_return_t rrc;
134 char buffer[32];
135 char *p;
136
137 rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
138 if (rrc != MEMCACHED_SUCCESS)
139 {
140 memcached_io_reset(instance);
141 rc= MEMCACHED_SOME_ERRORS;
142 continue;
143 }
144
145 instance->major_version= (uint8_t)strtol(buffer, &p, 10);
146 instance->minor_version= (uint8_t)strtol(p + 1, &p, 10);
147 instance->micro_version= (uint8_t)strtol(p + 1, NULL, 10);
148 }
149 }
150
151 return rc;
152 }