All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_node.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2016 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 #pragma once
18 
19 #include <aerospike/as_error.h>
20 #include <aerospike/as_event.h>
21 #include <aerospike/as_queue.h>
22 #include <aerospike/as_vector.h>
23 #include <citrusleaf/cf_queue.h>
24 #include <netinet/in.h>
25 #include <sys/uio.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 // Concurrency kit needs to be under extern "C" when compiling C++.
32 #include <aerospike/ck/ck_pr.h>
33 
34 /******************************************************************************
35  * MACROS
36  *****************************************************************************/
37 
38 /**
39  * Maximum size (including NULL byte) of a hostname.
40  */
41 #define AS_HOSTNAME_SIZE 256
42 
43 /**
44  * Maximum size of node name
45  */
46 #define AS_NODE_NAME_SIZE 20
47 
48 // Leave this is in for backwards compatibility.
49 #define AS_NODE_NAME_MAX_SIZE AS_NODE_NAME_SIZE
50 
51 /******************************************************************************
52  * TYPES
53  *****************************************************************************/
54 
55 /**
56  * Socket address information.
57  */
58 typedef struct as_address_s {
59  /**
60  * Socket IP address.
61  */
62  struct sockaddr_in addr;
63 
64  /**
65  * Socket IP address string representation (xxx.xxx.xxx.xxx).
66  */
67  char name[INET_ADDRSTRLEN];
68 } as_address;
69 
70 struct as_cluster_s;
71 
72 /**
73  * Server node representation.
74  */
75 typedef struct as_node_s {
76  /**
77  * @private
78  * Reference count of node.
79  */
80  uint32_t ref_count;
81 
82  /**
83  * @private
84  * Server's generation count for partition management.
85  */
87 
88  /**
89  * The name of the node.
90  */
91  char name[AS_NODE_NAME_SIZE];
92 
93  /**
94  * @private
95  * Primary host address index into addresses array.
96  */
97  uint32_t address_index;
98 
99  /**
100  * @private
101  * Vector of sockaddr_in which the host is currently known by.
102  * Only used by tend thread. Not thread-safe.
103  */
104  as_vector /* <as_address> */ addresses;
105 
106  /**
107  * @private
108  * Vector of aliases which the host is currently known by.
109  * Only used by tend thread. Not thread-safe.
110  */
111  as_vector /* <as_host> */ aliases;
112 
113  struct as_cluster_s* cluster;
114 
115  /**
116  * @private
117  * Pool of current, cached FDs.
118  */
119  cf_queue* conn_q;
120 
121  /**
122  * @private
123  * Array of connection pools used in async commands. There is one pool per node/event loop.
124  * Only used by event loop threads. Not thread-safe.
125  */
127 
128  /**
129  * @private
130  * Pool of connections used in pipelined async commands. Also not thread-safe.
131  */
133 
134  /**
135  * @private
136  * Socket used exclusively for cluster tend thread info requests.
137  */
138  int info_fd;
139 
140  /**
141  * @private
142  * Number of other nodes that consider this node a member of the cluster.
143  */
144  uint32_t conn_count;
145 
146  /**
147  * @private
148  * Number of other nodes that consider this node a member of the cluster.
149  */
150  uint32_t friends;
151 
152  /**
153  * @private
154  * Number of consecutive info request failures.
155  */
156  uint32_t failures;
157 
158  /**
159  * @private
160  * Shared memory node array index.
161  */
162  uint32_t index;
163 
164  /**
165  * @private
166  * Is node currently active.
167  */
168  uint8_t active;
169 
170  /**
171  * @private
172  * Does node support batch-index protocol?
173  */
175 
176  /**
177  * @private
178  * Does node support replicas-all info protocol?
179  */
181 
182  /**
183  * @private
184  * Does node support floating point type?
185  */
186  uint8_t has_double;
187 
188  /**
189  * @private
190  * Does node support geospatial queries?
191  */
192  uint8_t has_geo;
193 
194 } as_node;
195 
196 /**
197  * @private
198  * Node discovery information.
199  */
200 typedef struct as_node_info_s {
201  /**
202  * @private
203  * Node name.
204  */
205  char name[AS_NODE_NAME_SIZE];
206 
207  /**
208  * @private
209  * Validated socket.
210  */
211  int fd;
212 
213  /**
214  * @private
215  * Does node support batch-index protocol?
216  */
218 
219  /**
220  * @private
221  * Does node support replicas-all info protocol?
222  */
224 
225  /**
226  * @private
227  * Does node support floating point type?
228  */
229  uint8_t has_double;
230 
231  /**
232  * @private
233  * Does node support geospatial queries?
234  */
235  uint8_t has_geo;
236 
237 } as_node_info;
238 
239 /**
240  * @private
241  * Friend host address information.
242  */
243 typedef struct as_host_s {
244  /**
245  * @private
246  * Hostname or IP address string representation (xxx.xxx.xxx.xxx).
247  */
248  char name[AS_HOSTNAME_SIZE];
249 
250  /**
251  * @private
252  * Socket IP port.
253  */
254  in_port_t port;
255 
256 } as_host;
257 
258 /******************************************************************************
259  * FUNCTIONS
260  ******************************************************************************/
261 
262 /**
263  * @private
264  * Create new cluster node.
265  */
266 as_node*
267 as_node_create(struct as_cluster_s* cluster, as_host* host, struct sockaddr_in* addr, as_node_info* node_info);
268 
269 /**
270  * @private
271  * Close all connections in pool and free resources.
272  */
273 void
274 as_node_destroy(as_node* node);
275 
276 /**
277  * @private
278  * Set node to inactive.
279  */
280 static inline void
282 {
283  // Make volatile write so changes are reflected in other threads.
284  ck_pr_store_8(&node->active, false);
285 }
286 
287 /**
288  * @private
289  * Reserve existing cluster node.
290  */
291 static inline void
293 {
294  //ck_pr_fence_acquire();
295  ck_pr_inc_32(&node->ref_count);
296 }
297 
298 /**
299  * @private
300  * Release existing cluster node.
301  */
302 static inline void
304 {
305  //ck_pr_fence_release();
306 
307  bool destroy;
308  ck_pr_dec_32_zero(&node->ref_count, &destroy);
309 
310  if (destroy) {
311  as_node_destroy(node);
312  }
313 }
314 
315 /**
316  * @private
317  * Add socket address to node addresses.
318  */
319 void
320 as_node_add_address(as_node* node, as_host* host, struct sockaddr_in* addr);
321 
322 /**
323  * @private
324  * Get socket address and name.
325  */
326 static inline struct sockaddr_in*
328 {
329  as_address* address = (as_address *)as_vector_get(&node->addresses, node->address_index);
330  return &address->addr;
331 }
332 
333 /**
334  * Get socket address and name.
335  */
336 static inline as_address*
338 {
339  return (as_address *)as_vector_get(&node->addresses, node->address_index);
340 }
341 
342 /**
343  * @private
344  * Get a connection to the given node from pool and validate. Return 0 on success.
345  */
346 as_status
347 as_node_get_connection(as_error* err, as_node* node, uint64_t deadline_ms, int* fd);
348 
349 /**
350  * @private
351  * Close a node's connection and do not put back into pool.
352  */
353 static inline void
355  close(fd);
356  ck_pr_dec_32(&node->conn_count);
357 }
358 
359 /**
360  * @private
361  * Put connection back into pool.
362  */
363 static inline void
365 {
366  if (cf_queue_push(node->conn_q, &fd) != CF_QUEUE_OK) {
367  as_node_close_connection(node, fd);
368  }
369 }
370 
371 /**
372  * @private
373  * Are hosts equal.
374  */
375 static inline bool
377 {
378  return strcmp(h1->name, h2->name) == 0 && h1->port == h2->port;
379 }
380 
381 #ifdef __cplusplus
382 } // end extern "C"
383 #endif