p9y
[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 #include "p9y/socket.hpp"
18
19 static inline void _server_init(memcached_server_st *self, Memcached *root,
20 const memcached_string_t &hostname, in_port_t port, uint32_t weight,
21 memcached_connection_t type) {
22 self->options.is_shutting_down = false;
23 self->options.is_dead = false;
24 self->number_of_hosts = 0;
25 self->cursor_active = 0;
26 self->port = port;
27 self->io_bytes_sent = 0;
28 self->request_id = 0;
29 self->server_failure_counter = 0;
30 self->server_failure_counter_query_id = 0;
31 self->server_timeout_counter = 0;
32 self->server_timeout_counter_query_id = 0;
33 self->weight = weight ? weight : 1; // 1 is the default weight value
34 self->io_wait_count.read = 0;
35 self->io_wait_count.write = 0;
36 self->io_wait_count.timeouts = 0;
37 self->io_wait_count._bytes_read = 0;
38 self->major_version = UINT8_MAX;
39 self->micro_version = UINT8_MAX;
40 self->minor_version = UINT8_MAX;
41 self->type = type;
42 self->error_messages = NULL;
43
44 self->state = MEMCACHED_SERVER_STATE_NEW;
45 self->next_retry = 0;
46
47 self->root = root;
48 if (root) {
49 self->version = ++root->server_info.version;
50 } else {
51 self->version = UINT_MAX;
52 }
53 self->limit_maxbytes = 0;
54 memcpy(self->hostname, hostname.c_str, hostname.size);
55 self->hostname[hostname.size] = 0;
56 }
57
58 static memcached_server_st *_server_create(memcached_server_st *self, const Memcached *memc) {
59 if (self == NULL) {
60 self = libmemcached_xmalloc(memc, struct memcached_server_st);
61
62 if (self == NULL) {
63 return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
64 }
65
66 self->options.is_allocated = true;
67 } else {
68 self->options.is_allocated = false;
69 }
70
71 self->options.is_initialized = true;
72
73 return self;
74 }
75
76 memcached_server_st *__server_create_with(Memcached *memc, memcached_server_st *allocated_instance,
77 const memcached_string_t &hostname, const in_port_t port,
78 uint32_t weight, const memcached_connection_t type) {
79 if (memcached_is_valid_servername(hostname) == false) {
80 memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
81 memcached_literal_param("Invalid hostname provided"));
82 return NULL;
83 }
84
85 allocated_instance = _server_create(allocated_instance, memc);
86
87 if (allocated_instance == NULL) {
88 return NULL;
89 }
90
91 _server_init(allocated_instance, const_cast<Memcached *>(memc), hostname, port, weight, type);
92
93 return allocated_instance;
94 }
95
96 void __server_free(memcached_server_st *self) {
97 memcached_error_free(*self);
98
99 if (memcached_is_allocated(self)) {
100 libmemcached_free(self->root, self);
101 } else {
102 self->options.is_initialized = false;
103 }
104 }
105
106 void memcached_server_free(memcached_server_st *self) {
107 if (self == NULL) {
108 return;
109 }
110
111 if (memcached_server_list_count(self)) {
112 memcached_server_list_free(self);
113 return;
114 }
115
116 __server_free(self);
117 }
118
119 void memcached_server_error_reset(memcached_server_st *self) {
120 WATCHPOINT_ASSERT(self);
121 if (self == NULL) {
122 return;
123 }
124
125 memcached_error_free(*self);
126 }
127
128 uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count) {
129 WATCHPOINT_ASSERT(servers);
130 if (servers == NULL) {
131 return 0;
132 }
133
134 return servers->number_of_hosts = count;
135 }
136
137 uint32_t memcached_server_count(const memcached_st *self) {
138 WATCHPOINT_ASSERT(self);
139 if (self == NULL)
140 return 0;
141
142 return self->number_of_hosts;
143 }
144
145 const char *memcached_server_name(const memcached_instance_st *self) {
146 WATCHPOINT_ASSERT(self);
147 if (self) {
148 return self->_hostname;
149 }
150
151 return NULL;
152 }
153
154 in_port_t memcached_server_port(const memcached_instance_st *self) {
155 WATCHPOINT_ASSERT(self);
156 if (self == NULL) {
157 return 0;
158 }
159
160 return self->port();
161 }
162
163 in_port_t memcached_server_srcport(const memcached_instance_st *self) {
164 WATCHPOINT_ASSERT(self);
165 if (self == NULL || self->fd == INVALID_SOCKET
166 || (self->type != MEMCACHED_CONNECTION_TCP && self->type != MEMCACHED_CONNECTION_UDP))
167 {
168 return 0;
169 }
170
171 struct sockaddr_in sin;
172 socklen_t addrlen = sizeof(sin);
173 if (getsockname(self->fd, (struct sockaddr *) &sin, &addrlen) != -1) {
174 return ntohs(sin.sin_port);
175 }
176
177 return -1;
178 }
179
180 uint32_t memcached_server_response_count(const memcached_instance_st *self) {
181 WATCHPOINT_ASSERT(self);
182 if (self == NULL) {
183 return 0;
184 }
185
186 return self->cursor_active_;
187 }
188
189 const char *memcached_server_type(const memcached_instance_st *ptr) {
190 if (ptr) {
191 switch (ptr->type) {
192 case MEMCACHED_CONNECTION_TCP:
193 return "TCP";
194
195 case MEMCACHED_CONNECTION_UDP:
196 return "UDP";
197
198 case MEMCACHED_CONNECTION_UNIX_SOCKET:
199 return "SOCKET";
200 }
201 }
202
203 return "UNKNOWN";
204 }
205
206 uint8_t memcached_server_major_version(const memcached_instance_st *instance) {
207 if (instance) {
208 return instance->major_version;
209 }
210
211 return UINT8_MAX;
212 }
213
214 uint8_t memcached_server_minor_version(const memcached_instance_st *instance) {
215 if (instance) {
216 return instance->minor_version;
217 }
218
219 return UINT8_MAX;
220 }
221
222 uint8_t memcached_server_micro_version(const memcached_instance_st *instance) {
223 if (instance) {
224 return instance->micro_version;
225 }
226
227 return UINT8_MAX;
228 }