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