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-2017 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_socket.h>
22 #include <aerospike/as_queue.h>
23 #include <aerospike/as_vector.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 #define AS_FEATURES_GEO (1 << 0)
52 #define AS_FEATURES_DOUBLE (1 << 1)
53 #define AS_FEATURES_BATCH_INDEX (1 << 2)
54 #define AS_FEATURES_REPLICAS_ALL (1 << 3)
55 #define AS_FEATURES_PIPELINING (1 << 4)
56 #define AS_FEATURES_PEERS (1 << 5)
57 #define AS_FEATURES_REPLICAS (1 << 6)
58 
59 #define AS_ADDRESS4_MAX 4
60 #define AS_ADDRESS6_MAX 8
61 
62 /******************************************************************************
63  * TYPES
64  *****************************************************************************/
65 
66 /**
67  * Socket address information.
68  */
69 typedef struct as_address_s {
70  /**
71  * Socket IP address.
72  */
73  struct sockaddr_storage addr;
74 
75  /**
76  * Socket IP address string representation including port.
77  */
78  char name[AS_IP_ADDRESS_SIZE];
79 
80 } as_address;
81 
82 /**
83  * @private
84  * Host address alias information.
85  */
86 typedef struct as_alias_s {
87  /**
88  * @private
89  * Hostname or IP address string representation.
90  */
91  char name[AS_HOSTNAME_SIZE];
92 
93  /**
94  * @private
95  * Socket IP port.
96  */
97  in_port_t port;
98 
99 } as_alias;
100 
101 /**
102  * @private
103  * Connection pool; not thread-safe.
104  */
105 typedef struct as_conn_pool_s {
106  /**
107  * @private
108  * Queue.
109  */
111 
112  /**
113  * @private
114  * Total number of connections associated with this pool, whether currently
115  * queued or not.
116  */
117  uint32_t total;
118 
119  /**
120  * @private
121  * The limit on the above total number of connections.
122  */
123  uint32_t limit;
124 
125 } as_conn_pool;
126 
127 /**
128  * @private
129  * Connection pool with lock.
130  */
131 typedef struct as_conn_pool_lock_s {
132  /**
133  * @private
134  * Mutex lock.
135  */
136  pthread_mutex_t lock;
137 
138  /**
139  * @private
140  * Actual pool.
141  */
143 
145 
146 struct as_cluster_s;
147 
148 /**
149  * Server node representation.
150  */
151 typedef struct as_node_s {
152  /**
153  * @private
154  * Reference count of node.
155  */
156  uint32_t ref_count;
157 
158  /**
159  * @private
160  * Server's generation count for partition management.
161  */
163 
164  /**
165  * @private
166  * TLS certificate name (needed for TLS only, NULL otherwise).
167  */
168  char* tls_name;
169 
170  /**
171  * The name of the node.
172  */
173  char name[AS_NODE_NAME_SIZE];
174 
175  /**
176  * @private
177  * Primary address index into addresses array.
178  */
179  uint32_t address_index;
180 
181  /**
182  * @private
183  * Number of IPv4 addresses.
184  */
185  uint32_t address4_size;
186 
187  /**
188  * @private
189  * Number of IPv6 addresses.
190  */
191  uint32_t address6_size;
192 
193  /**
194  * @private
195  * Array of IP addresses. Not thread-safe.
196  */
198 
199  /**
200  * @private
201  * Array of hostnames aliases. Not thread-safe.
202  */
203  as_vector /* <as_alias> */ aliases;
204 
205  struct as_cluster_s* cluster;
206 
207  /**
208  * @private
209  * Pools of current, cached sockets.
210  */
212 
213  /**
214  * @private
215  * Array of connection pools used in async commands. There is one pool per node/event loop.
216  * Only used by event loop threads. Not thread-safe.
217  */
219 
220  /**
221  * @private
222  * Pool of connections used in pipelined async commands. Also not thread-safe.
223  */
225 
226  /**
227  * @private
228  * Socket used exclusively for cluster tend thread info requests.
229  */
231 
232  /**
233  * @private
234  * Features supported by server. Stored in bitmap.
235  */
236  uint32_t features;
237 
238  /**
239  * @private
240  * Connection queue iterator. Not atomic by design.
241  */
242  uint32_t conn_iter;
243 
244  /**
245  * @private
246  * Server's generation count for peers.
247  */
249 
250  /**
251  * @private
252  * Number of peers returned by server node.
253  */
254  uint32_t peers_count;
255 
256  /**
257  * @private
258  * Number of other nodes that consider this node a member of the cluster.
259  */
260  uint32_t friends;
261 
262  /**
263  * @private
264  * Number of consecutive info request failures.
265  */
266  uint32_t failures;
267 
268  /**
269  * @private
270  * Shared memory node array index.
271  */
272  uint32_t index;
273 
274  /**
275  * @private
276  * Is node currently active.
277  */
278  uint8_t active;
279 
280  /**
281  * @private
282  * Did partition change in current cluster tend.
283  */
285 
286 } as_node;
287 
288 /**
289  * @private
290  * Node discovery information.
291  */
292 typedef struct as_node_info_s {
293  /**
294  * @private
295  * Node name.
296  */
297  char name[AS_NODE_NAME_SIZE];
298 
299  /**
300  * @private
301  * Features supported by server. Stored in bitmap.
302  */
303  uint32_t features;
304 
305  /**
306  * @private
307  * Validated socket.
308  */
310 
311 } as_node_info;
312 
313 /******************************************************************************
314  * FUNCTIONS
315  ******************************************************************************/
316 
317 /**
318  * @private
319  * Initialize a connection pool.
320  */
321 
322 static inline void
323 as_conn_pool_init(as_conn_pool* pool, uint32_t size, uint32_t limit)
324 {
325  pool->limit = limit;
326  pool->total = 0;
327 
328  as_queue_init(&pool->queue, size, limit);
329 }
330 
331 /**
332  * @private
333  * Destroy an empty connection pool.
334  */
335 static inline void
337 {
338  as_queue_destroy(&pool->queue);
339 }
340 
341 /**
342  * @private
343  * Reduce the total count of connections associated with this pool.
344  */
345 static inline void
347 {
348  pool->total--;
349 }
350 
351 /**
352  * @private
353  * Increase the total count of connections associated with this pool.
354  */
355 static inline bool
357 {
358  if (pool->total >= pool->limit) {
359  return false;
360  }
361 
362  pool->total++;
363  return true;
364 }
365 
366 /**
367  * @private
368  * Get a connection from the pool.
369  */
370 static inline bool
371 as_conn_pool_get(as_conn_pool* pool, void* conn)
372 {
373  return as_queue_pop(&pool->queue, conn);
374 }
375 
376 /**
377  * @private
378  * Return a connection to the pool.
379  */
380 static inline bool
381 as_conn_pool_put(as_conn_pool* pool, void* conn)
382 {
383  if (pool->total > pool->limit) {
384  return false;
385  }
386 
387  return as_queue_push(&pool->queue, conn);
388 }
389 
390 /**
391  * @private
392  * Create new cluster node.
393  */
394 as_node*
396  struct as_cluster_s* cluster, const char* hostname, const char* tls_name,
397  in_port_t port, bool is_alias, struct sockaddr* addr, as_node_info* node_info
398  );
399 
400 /**
401  * @private
402  * Close all connections in pool and free resources.
403  */
404 void
405 as_node_destroy(as_node* node);
406 
407 /**
408  * @private
409  * Set node to inactive.
410  */
411 static inline void
413 {
414  // Make volatile write so changes are reflected in other threads.
415  ck_pr_store_8(&node->active, false);
416 }
417 
418 /**
419  * @private
420  * Reserve existing cluster node.
421  */
422 static inline void
424 {
425  //ck_pr_fence_acquire();
426  ck_pr_inc_32(&node->ref_count);
427 }
428 
429 /**
430  * @private
431  * Release existing cluster node.
432  */
433 static inline void
435 {
436  //ck_pr_fence_release();
437 
438  bool destroy;
439  ck_pr_dec_32_zero(&node->ref_count, &destroy);
440 
441  if (destroy) {
442  as_node_destroy(node);
443  }
444 }
445 
446 /**
447  * @private
448  * Add socket address to node addresses.
449  */
450 void
451 as_node_add_address(as_node* node, struct sockaddr* addr);
452 
453 /**
454  * @private
455  * Add hostname to node aliases.
456  */
457 void
458 as_node_add_alias(as_node* node, const char* hostname, in_port_t port);
459 
460 /**
461  * Get primary socket address.
462  */
463 static inline as_address*
465 {
466  return &node->addresses[node->address_index];
467 }
468 
469 /**
470  * Get socket address as a string.
471  */
472 static inline const char*
474 {
475  return node->addresses[node->address_index].name;
476 }
477 
478 /**
479  * @private
480  * Attempt to authenticate given user and password.
481  */
482 as_status
483 as_node_authenticate_connection(struct as_cluster_s* cluster, const char* user, const char* password);
484 
485 /**
486  * @private
487  * Get a connection to the given node from pool and validate. Return 0 on success.
488  */
489 as_status
490 as_node_get_connection(as_error* err, as_node* node, uint32_t socket_timeout, uint64_t deadline_ms, as_socket* sock);
491 
492 /**
493  * @private
494  * Close a node's connection and do not put back into pool.
495  */
496 static inline void
498  as_conn_pool_lock* pool_lock = sock->pool_lock;
499  as_socket_close(sock);
500  pthread_mutex_lock(&pool_lock->lock);
501  as_conn_pool_dec(&pool_lock->pool);
502  pthread_mutex_unlock(&pool_lock->lock);
503 }
504 
505 /**
506  * @private
507  * Put connection back into pool.
508  */
509 static inline void
510 as_node_put_connection(as_socket* sock, uint32_t max_socket_idle)
511 {
512  // Save pool.
513  as_conn_pool_lock* pool_lock = sock->pool_lock;
514 
515  // TLS connections default to 55 seconds.
516  if (max_socket_idle == 0 && sock->ctx) {
517  max_socket_idle = 55;
518  }
519 
520  if (max_socket_idle > 0) {
521  sock->idle_check.max_socket_idle = max_socket_idle;
522  sock->idle_check.last_used = (uint32_t)cf_get_seconds();
523  }
524  else {
525  sock->idle_check.max_socket_idle = sock->idle_check.last_used = 0;
526  }
527 
528  // Put into pool.
529  pthread_mutex_lock(&pool_lock->lock);
530  bool status = as_conn_pool_put(&pool_lock->pool, sock);
531  pthread_mutex_unlock(&pool_lock->lock);
532 
533  if (! status) {
534  as_socket_close(sock);
535  pthread_mutex_lock(&pool_lock->lock);
536  as_conn_pool_dec(&pool_lock->pool);
537  pthread_mutex_unlock(&pool_lock->lock);
538  }
539 }
540 
541 /**
542  * @private
543  * Are hosts equal.
544  */
545 static inline bool
547 {
548  return strcmp(h1->name, h2->name) == 0 && h1->port == h2->port;
549 }
550 
551 #ifdef __cplusplus
552 } // end extern "C"
553 #endif