e2837c7d03c84e2f43248db2bfa5892375564227
[awesomized/libmemcached] / src / libmemcached / server.cc
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Libmemcached library
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 * Copyright (C) 2006-2009 Brian Aker All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following disclaimer
17 * in the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * * The names of its contributors may not be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38 /*
39 This is a partial implementation for fetching/creating memcached_server_st objects.
40 */
41 #include <libmemcached/common.h>
42
43 static inline void _server_init(memcached_server_st *self, Memcached *root,
44 const memcached_string_t& hostname,
45 in_port_t port,
46 uint32_t weight, memcached_connection_t type)
47 {
48 self->options.is_shutting_down= false;
49 self->options.is_dead= false;
50 self->number_of_hosts= 0;
51 self->cursor_active= 0;
52 self->port= port;
53 self->io_bytes_sent= 0;
54 self->request_id= 0;
55 self->server_failure_counter= 0;
56 self->server_failure_counter_query_id= 0;
57 self->server_timeout_counter= 0;
58 self->server_timeout_counter_query_id= 0;
59 self->weight= weight ? weight : 1; // 1 is the default weight value
60 self->io_wait_count.read= 0;
61 self->io_wait_count.write= 0;
62 self->io_wait_count.timeouts= 0;
63 self->io_wait_count._bytes_read= 0;
64 self->major_version= UINT8_MAX;
65 self->micro_version= UINT8_MAX;
66 self->minor_version= UINT8_MAX;
67 self->type= type;
68 self->error_messages= NULL;
69
70 self->state= MEMCACHED_SERVER_STATE_NEW;
71 self->next_retry= 0;
72
73 self->root= root;
74 if (root)
75 {
76 self->version= ++root->server_info.version;
77 }
78 else
79 {
80 self->version= UINT_MAX;
81 }
82 self->limit_maxbytes= 0;
83 memcpy(self->hostname, hostname.c_str, hostname.size);
84 self->hostname[hostname.size]= 0;
85 }
86
87 static memcached_server_st *_server_create(memcached_server_st *self, const Memcached *memc)
88 {
89 if (self == NULL)
90 {
91 self= libmemcached_xmalloc(memc, struct memcached_server_st);
92
93 if (self == NULL)
94 {
95 return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
96 }
97
98 self->options.is_allocated= true;
99 }
100 else
101 {
102 self->options.is_allocated= false;
103 }
104
105 self->options.is_initialized= true;
106
107 return self;
108 }
109
110 memcached_server_st *__server_create_with(Memcached *memc,
111 memcached_server_st* allocated_instance,
112 const memcached_string_t& hostname,
113 const in_port_t port,
114 uint32_t weight,
115 const memcached_connection_t type)
116 {
117 if (memcached_is_valid_servername(hostname) == false)
118 {
119 memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
120 return NULL;
121 }
122
123 allocated_instance= _server_create(allocated_instance, memc);
124
125 if (allocated_instance == NULL)
126 {
127 return NULL;
128 }
129
130 _server_init(allocated_instance, const_cast<Memcached *>(memc), hostname, port, weight, type);
131
132 return allocated_instance;
133 }
134
135 void __server_free(memcached_server_st *self)
136 {
137 memcached_error_free(*self);
138
139 if (memcached_is_allocated(self))
140 {
141 libmemcached_free(self->root, self);
142 }
143 else
144 {
145 self->options.is_initialized= false;
146 }
147 }
148
149 void memcached_server_free(memcached_server_st *self)
150 {
151 if (self == NULL)
152 {
153 return;
154 }
155
156 if (memcached_server_list_count(self))
157 {
158 memcached_server_list_free(self);
159 return;
160 }
161
162 __server_free(self);
163 }
164
165 void memcached_server_error_reset(memcached_server_st *self)
166 {
167 WATCHPOINT_ASSERT(self);
168 if (self == NULL)
169 {
170 return;
171 }
172
173 memcached_error_free(*self);
174 }
175
176 uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
177 {
178 WATCHPOINT_ASSERT(servers);
179 if (servers == NULL)
180 {
181 return 0;
182 }
183
184 return servers->number_of_hosts= count;
185 }
186
187 uint32_t memcached_server_count(const memcached_st *self)
188 {
189 WATCHPOINT_ASSERT(self);
190 if (self == NULL)
191 return 0;
192
193 return self->number_of_hosts;
194 }
195
196 const char *memcached_server_name(const memcached_instance_st * self)
197 {
198 WATCHPOINT_ASSERT(self);
199 if (self)
200 {
201 return self->_hostname;
202 }
203
204 return NULL;
205 }
206
207 in_port_t memcached_server_port(const memcached_instance_st * self)
208 {
209 WATCHPOINT_ASSERT(self);
210 if (self == NULL)
211 {
212 return 0;
213 }
214
215 return self->port();
216 }
217
218 in_port_t memcached_server_srcport(const memcached_instance_st * self)
219 {
220 WATCHPOINT_ASSERT(self);
221 if (self == NULL || self->fd == INVALID_SOCKET || (self->type != MEMCACHED_CONNECTION_TCP && self->type != MEMCACHED_CONNECTION_UDP))
222 {
223 return 0;
224 }
225
226 struct sockaddr_in sin;
227 socklen_t addrlen= sizeof(sin);
228 if (getsockname(self->fd, (struct sockaddr*)&sin, &addrlen) != -1)
229 {
230 return ntohs(sin.sin_port);
231 }
232
233 return -1;
234 }
235
236 uint32_t memcached_server_response_count(const memcached_instance_st * self)
237 {
238 WATCHPOINT_ASSERT(self);
239 if (self == NULL)
240 {
241 return 0;
242 }
243
244 return self->cursor_active_;
245 }
246
247 const char *memcached_server_type(const memcached_instance_st * ptr)
248 {
249 if (ptr)
250 {
251 switch (ptr->type)
252 {
253 case MEMCACHED_CONNECTION_TCP:
254 return "TCP";
255
256 case MEMCACHED_CONNECTION_UDP:
257 return "UDP";
258
259 case MEMCACHED_CONNECTION_UNIX_SOCKET:
260 return "SOCKET";
261 }
262 }
263
264 return "UNKNOWN";
265 }
266
267 uint8_t memcached_server_major_version(const memcached_instance_st * instance)
268 {
269 if (instance)
270 {
271 return instance->major_version;
272 }
273
274 return UINT8_MAX;
275 }
276
277 uint8_t memcached_server_minor_version(const memcached_instance_st * instance)
278 {
279 if (instance)
280 {
281 return instance->minor_version;
282 }
283
284 return UINT8_MAX;
285 }
286
287 uint8_t memcached_server_micro_version(const memcached_instance_st * instance)
288 {
289 if (instance)
290 {
291 return instance->micro_version;
292 }
293
294 return UINT8_MAX;
295 }