e038196abffd52fe8d3052e7365ec10c2d0c9f79
[m6w6/libmemcached] / src / libmemcached / server.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "libmemcached/common.h"
17
18 static inline void _server_init(memcached_server_st *self, Memcached *root,
19 const memcached_string_t &hostname, in_port_t port, uint32_t weight,
20 memcached_connection_t type) {
21 self->options.is_shutting_down = false;
22 self->options.is_dead = false;
23 self->number_of_hosts = 0;
24 self->cursor_active = 0;
25 self->port = port;
26 self->io_bytes_sent = 0;
27 self->request_id = 0;
28 self->server_failure_counter = 0;
29 self->server_failure_counter_query_id = 0;
30 self->server_timeout_counter = 0;
31 self->server_timeout_counter_query_id = 0;
32 self->weight = weight ? weight : 1; // 1 is the default weight value
33 self->io_wait_count.read = 0;
34 self->io_wait_count.write = 0;
35 self->io_wait_count.timeouts = 0;
36 self->io_wait_count._bytes_read = 0;
37 self->major_version = UINT8_MAX;
38 self->micro_version = UINT8_MAX;
39 self->minor_version = UINT8_MAX;
40 self->type = type;
41 self->error_messages = NULL;
42
43 self->state = MEMCACHED_SERVER_STATE_NEW;
44 self->next_retry = 0;
45
46 self->root = root;
47 if (root) {
48 self->version = ++root->server_info.version;
49 } else {
50 self->version = UINT_MAX;
51 }
52 self->limit_maxbytes = 0;
53 memcpy(self->hostname, hostname.c_str, hostname.size);
54 self->hostname[hostname.size] = 0;
55 }
56
57 static memcached_server_st *_server_create(memcached_server_st *self, const Memcached *memc) {
58 if (self == NULL) {
59 self = libmemcached_xmalloc(memc, struct memcached_server_st);
60
61 if (self == NULL) {
62 return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
63 }
64
65 self->options.is_allocated = true;
66 } else {
67 self->options.is_allocated = false;
68 }
69
70 self->options.is_initialized = true;
71
72 return self;
73 }
74
75 memcached_server_st *__server_create_with(Memcached *memc, memcached_server_st *allocated_instance,
76 const memcached_string_t &hostname, const in_port_t port,
77 uint32_t weight, const memcached_connection_t type) {
78 if (memcached_is_valid_servername(hostname) == false) {
79 memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
80 memcached_literal_param("Invalid hostname provided"));
81 return NULL;
82 }
83
84 allocated_instance = _server_create(allocated_instance, memc);
85
86 if (allocated_instance == NULL) {
87 return NULL;
88 }
89
90 _server_init(allocated_instance, const_cast<Memcached *>(memc), hostname, port, weight, type);
91
92 return allocated_instance;
93 }
94
95 void __server_free(memcached_server_st *self) {
96 memcached_error_free(*self);
97
98 if (memcached_is_allocated(self)) {
99 libmemcached_free(self->root, self);
100 } else {
101 self->options.is_initialized = false;
102 }
103 }
104
105 void memcached_server_free(memcached_server_st *self) {
106 if (self == NULL) {
107 return;
108 }
109
110 if (memcached_server_list_count(self)) {
111 memcached_server_list_free(self);
112 return;
113 }
114
115 __server_free(self);
116 }
117
118 void memcached_server_error_reset(memcached_server_st *self) {
119 WATCHPOINT_ASSERT(self);
120 if (self == NULL) {
121 return;
122 }
123
124 memcached_error_free(*self);
125 }
126
127 uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count) {
128 WATCHPOINT_ASSERT(servers);
129 if (servers == NULL) {
130 return 0;
131 }
132
133 return servers->number_of_hosts = count;
134 }
135
136 uint32_t memcached_server_count(const memcached_st *self) {
137 WATCHPOINT_ASSERT(self);
138 if (self == NULL)
139 return 0;
140
141 return self->number_of_hosts;
142 }
143
144 const char *memcached_server_name(const memcached_instance_st *self) {
145 WATCHPOINT_ASSERT(self);
146 if (self) {
147 return self->_hostname;
148 }
149
150 return NULL;
151 }
152
153 in_port_t memcached_server_port(const memcached_instance_st *self) {
154 WATCHPOINT_ASSERT(self);
155 if (self == NULL) {
156 return 0;
157 }
158
159 return self->port();
160 }
161
162 in_port_t memcached_server_srcport(const memcached_instance_st *self) {
163 WATCHPOINT_ASSERT(self);
164 if (self == NULL || self->fd == INVALID_SOCKET
165 || (self->type != MEMCACHED_CONNECTION_TCP && self->type != MEMCACHED_CONNECTION_UDP))
166 {
167 return 0;
168 }
169
170 struct sockaddr_in sin;
171 socklen_t addrlen = sizeof(sin);
172 if (getsockname(self->fd, (struct sockaddr *) &sin, &addrlen) != -1) {
173 return ntohs(sin.sin_port);
174 }
175
176 return -1;
177 }
178
179 uint32_t memcached_server_response_count(const memcached_instance_st *self) {
180 WATCHPOINT_ASSERT(self);
181 if (self == NULL) {
182 return 0;
183 }
184
185 return self->cursor_active_;
186 }
187
188 const char *memcached_server_type(const memcached_instance_st *ptr) {
189 if (ptr) {
190 switch (ptr->type) {
191 case MEMCACHED_CONNECTION_TCP:
192 return "TCP";
193
194 case MEMCACHED_CONNECTION_UDP:
195 return "UDP";
196
197 case MEMCACHED_CONNECTION_UNIX_SOCKET:
198 return "SOCKET";
199 }
200 }
201
202 return "UNKNOWN";
203 }
204
205 uint8_t memcached_server_major_version(const memcached_instance_st *instance) {
206 if (instance) {
207 return instance->major_version;
208 }
209
210 return UINT8_MAX;
211 }
212
213 uint8_t memcached_server_minor_version(const memcached_instance_st *instance) {
214 if (instance) {
215 return instance->minor_version;
216 }
217
218 return UINT8_MAX;
219 }
220
221 uint8_t memcached_server_micro_version(const memcached_instance_st *instance) {
222 if (instance) {
223 return instance->micro_version;
224 }
225
226 return UINT8_MAX;
227 }