All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_cluster.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_config.h>
20 #include <aerospike/as_node.h>
21 #include <aerospike/as_partition.h>
22 #include <aerospike/as_policy.h>
23 #include <aerospike/as_thread_pool.h>
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 // Concurrency kit needs to be under extern "C" when compiling C++.
30 #include <aerospike/ck/ck_pr.h>
31 
32 /******************************************************************************
33  * TYPES
34  *****************************************************************************/
35 
36 /**
37  * Seed host.
38  */
39 typedef struct as_seed_s {
40  /**
41  * Host name.
42  */
43  char* name;
44 
45  /**
46  * Host port.
47  */
48  in_port_t port;
49 } as_seed;
50 
51 /**
52  * @private
53  * Reference counted array of seed hosts.
54  */
55 typedef struct as_seeds_s {
56  /**
57  * @private
58  * Reference count.
59  */
60  uint32_t ref_count;
61 
62  /*
63  * @private
64  * Length of seed array.
65  */
66  uint32_t size;
67 
68  /**
69  * @private
70  * Seed array.
71  */
72  as_seed array[];
73 } as_seeds;
74 
75 /**
76  * @private
77  * Reference counted array of server node pointers.
78  */
79 typedef struct as_nodes_s {
80  /**
81  * @private
82  * Reference count of node array.
83  */
84  uint32_t ref_count;
85 
86  /**
87  * @private
88  * Length of node array.
89  */
90  uint32_t size;
91 
92  /**
93  * @private
94  * Server node array.
95  */
96  as_node* array[];
97 } as_nodes;
98 
99 
100 /**
101  * @private
102  * Reference counted array of address maps.
103  */
104 typedef struct as_addr_maps_s {
105  /**
106  * @private
107  * Reference count.
108  */
109  uint32_t ref_count;
110 
111  /*
112  * @private
113  * Length of address map array.
114  */
115  uint32_t size;
116 
117  /**
118  * @private
119  * tAddress map array.
120  */
121  as_addr_map array[];
122 } as_addr_maps;
123 
124 /**
125  * @private
126  * Reference counted release function definition.
127  */
128 typedef void (*as_release_fn) (void* value);
129 
130 /**
131  * @private
132  * Reference counted data to be garbage collected.
133  */
134 typedef struct as_gc_item_s {
135  /**
136  * @private
137  * Reference counted data to be garbage collected.
138  */
139  void* data;
140 
141  /**
142  * @private
143  * Release function.
144  */
146 } as_gc_item;
147 
148 /**
149  * Cluster of server nodes.
150  */
151 typedef struct as_cluster_s {
152  /**
153  * @private
154  * Active nodes in cluster.
155  */
157 
158  /**
159  * @private
160  * Hints for best node for a partition.
161  */
163 
164  /**
165  * @private
166  * Nodes to be garbage collected.
167  */
168  as_vector* /* <as_gc_item> */ gc;
169 
170  /**
171  * @private
172  * Shared memory implementation of cluster.
173  */
174  struct as_shm_info_s* shm_info;
175 
176  /**
177  * @private
178  * User name in UTF-8 encoded bytes.
179  */
180  char* user;
181 
182  /**
183  * @private
184  * Password in hashed format in bytes.
185  */
186  char* password;
187 
188  /**
189  * @private
190  * Initial seed nodes specified by user.
191  */
193 
194  /**
195  * @private
196  * Configuration version. Incremented, when the configuration is changed.
197  */
198  uint32_t version;
199 
200  /**
201  * @private
202  * A IP translation table is used in cases where different clients use different server
203  * IP addresses. This may be necessary when using clients from both inside and outside
204  * a local area network. Default is no translation.
205  *
206  * The key is the IP address returned from friend info requests to other servers. The
207  * value is the real IP address used to connect to the server.
208  */
210 
211  /**
212  * @private
213  * Pool of threads used to query server nodes in parallel for batch, scan and query.
214  */
215  as_thread_pool thread_pool;
216 
217  /**
218  * @private
219  * Cluster tend thread.
220  */
221  pthread_t tend_thread;
222 
223  /**
224  * @private
225  * Lock for the tend thread to wait on with the tend interval as timeout.
226  * Normally locked, resulting in waiting a full interval between
227  * tend iterations. Upon cluster shutdown, unlocked by the main
228  * thread, allowing a fast termination of the tend thread.
229  */
230  pthread_mutex_t tend_lock;
231 
232  /**
233  * @private
234  * Tend thread identifier to be used with tend_lock.
235  */
236  pthread_cond_t tend_cond;
237 
238  /**
239  * @private
240  * Milliseconds between cluster tends.
241  */
242  uint32_t tend_interval;
243 
244  /**
245  * @private
246  * Size of node's synchronous connection pool.
247  */
248  uint32_t conn_queue_size;
249 
250  /**
251  * @private
252  * Maximum number of asynchronous (non-pipeline) connections allowed for each node.
253  * Async transactions will be rejected if the maximum async node connections would be exceeded.
254  * This variable is ignored if asynchronous event loops are not created.
255  */
257 
258  /**
259  * @private
260  * Initial capacity for asynchronous (non-pipeline) connection pools. There is one pool for
261  * each node/event loop combination. This variable is ignored if asynchronous event loops are
262  * not created.
263  */
265 
266  /**
267  * @private
268  * Maximum number of pipeline connections allowed for each node.
269  * Pipeline transactions will be rejected if the maximum pipeline node connections would be exceeded.
270  * This variable is ignored if asynchronous event loops are not created.
271  */
273 
274  /**
275  * @private
276  * Initial capacity for pipeline connection pools. There is one pool for each node/event loop
277  * combination. This variable is ignored if asynchronous event loops are not created.
278  */
280 
281  /**
282  * @private
283  * Number of pending async commands (i.e., commands with an outstanding reply).
284  */
285  uint32_t async_pending;
286 
287  /**
288  * @private
289  * Number of active async pipeline and non-pipeline connections combined.
290  */
292 
293  /**
294  * @private
295  * Number of async connections in the pools.
296  */
297  uint32_t async_conn_pool;
298 
299  /**
300  * @private
301  * Initial connection timeout in milliseconds.
302  */
303  uint32_t conn_timeout_ms;
304 
305  /**
306  * @private
307  * Maximum socket idle in seconds.
308  */
309  uint32_t max_socket_idle;
310 
311  /**
312  * @private
313  * Random node index.
314  */
315  uint32_t node_index;
316 
317  /**
318  * @private
319  * Total number of data partitions used by cluster.
320  */
321  uint16_t n_partitions;
322 
323  /**
324  * @private
325  * If "services-alternate" should be used instead of "services"
326  */
328 
329  /**
330  * @private
331  * Should continue to tend cluster.
332  */
333  volatile bool valid;
334 } as_cluster;
335 
336 /******************************************************************************
337  * FUNCTIONS
338  ******************************************************************************/
339 
340 /**
341  * Create and initialize cluster.
342  */
343 as_status
344 as_cluster_create(as_config* config, as_error* err, as_cluster** cluster);
345 
346 /**
347  * Close all connections and release memory associated with cluster.
348  */
349 void
351 
352 /**
353  * Is cluster connected to any server nodes.
354  */
355 bool
357 
358 /**
359  * Get all node names in cluster.
360  */
361 void
362 as_cluster_get_node_names(as_cluster* cluster, int* n_nodes, char** node_names);
363 
364 /**
365  * Reserve reference counted access to cluster nodes.
366  */
367 static inline as_nodes*
369 {
370  as_nodes* nodes = (as_nodes *)ck_pr_load_ptr(&cluster->nodes);
371  //ck_pr_fence_acquire();
372  ck_pr_inc_32(&nodes->ref_count);
373  return nodes;
374 }
375 
376 /**
377  * Release reference counted access to cluster nodes.
378  */
379 static inline void
381 {
382  //ck_pr_fence_release();
383 
384  bool destroy;
385  ck_pr_dec_32_zero(&nodes->ref_count, &destroy);
386 
387  if (destroy) {
388  cf_free(nodes);
389  }
390 }
391 
392 /**
393  * Reserve reference counted access to seeds.
394  */
395 static inline as_seeds*
397 {
398  as_seeds* seeds = (as_seeds *)ck_pr_load_ptr(&cluster->seeds);
399  ck_pr_inc_32(&seeds->ref_count);
400  return seeds;
401 }
402 
403 /**
404  * Release reference counted access to seeds.
405  */
406 static inline void
408 {
409  bool destroy;
410  ck_pr_dec_32_zero(&seeds->ref_count, &destroy);
411 
412  if (destroy) {
413  for (uint32_t i = 0; i < seeds->size; i++) {
414  cf_free(seeds->array[i].name);
415  }
416 
417  cf_free(seeds);
418  }
419 }
420 
421 /**
422  * Add seeds to the cluster.
423  */
424 void
425 as_seeds_add(as_cluster* cluster, as_seed* seed_list, uint32_t size);
426 
427 /**
428  * Replace the seeds of the cluster.
429  */
430 void
431 as_seeds_update(as_cluster* cluster, as_seed* seed_list, uint32_t size);
432 
433 /**
434  * Reserve reference counted access to IP map.
435  */
436 static inline as_addr_maps*
438 {
439  as_addr_maps* ip_map = (as_addr_maps *)ck_pr_load_ptr(&cluster->ip_map);
440 
441  if (ip_map == NULL) {
442  return NULL;
443  }
444 
445  ck_pr_inc_32(&ip_map->ref_count);
446  return ip_map;
447 }
448 
449 /**
450  * Release reference counted access to IP map.
451  */
452 static inline void
454 {
455  bool destroy;
456  ck_pr_dec_32_zero(&ip_map->ref_count, &destroy);
457 
458  if (destroy) {
459  for (uint32_t i = 0; i < ip_map->size; i++) {
460  cf_free(ip_map->array[i].orig);
461  cf_free(ip_map->array[i].alt);
462  }
463 
464  cf_free(ip_map);
465  }
466 }
467 
468 /**
469  * Replace the IP address map of the cluster.
470  */
471 void
472 as_ip_map_update(as_cluster* cluster, as_addr_map* ip_map_list, uint32_t size);
473 
474 /**
475  * Change maximum async connections per node.
476  */
477 void
478 as_cluster_set_async_max_conns_per_node(as_cluster* cluster, uint32_t async_size, uint32_t pipe_size);
479 
480 /**
481  * @private
482  * Change user and password that is used to authenticate with cluster servers.
483  */
484 void
485 as_cluster_change_password(as_cluster* cluster, const char* user, const char* password);
486 
487 /**
488  * @private
489  * Get random node in the cluster.
490  * as_nodes_release() must be called when done with node.
491  */
492 as_node*
494 
495 /**
496  * @private
497  * Get node given node name.
498  * as_nodes_release() must be called when done with node.
499  */
500 as_node*
501 as_node_get_by_name(as_cluster* cluster, const char* name);
502 
503 /**
504  * @private
505  * Reserve reference counted access to partition tables.
506  * as_partition_tables_release() must be called when done with tables.
507  */
508 static inline as_partition_tables*
510 {
511  as_partition_tables* tables = (as_partition_tables *)ck_pr_load_ptr(&cluster->partition_tables);
512  ck_pr_inc_32(&tables->ref_count);
513  return tables;
514 }
515 
516 /**
517  * @private
518  * Release reference counted access to partition tables.
519  */
520 static inline void
522 {
523  bool destroy;
524  ck_pr_dec_32_zero(&tables->ref_count, &destroy);
525 
526  if (destroy) {
527  cf_free(tables);
528  }
529 }
530 
531 /**
532  * @private
533  * Get partition table given namespace.
534  */
535 static inline as_partition_table*
537 {
538  // Partition tables array size does not currently change after first cluster tend.
539  // Also, there is a one second delayed garbage collection coupled with as_partition_tables_get()
540  // being very fast. Reference counting the tables array is not currently necessary, but do it
541  // anyway in case the server starts supporting dynamic namespaces.
543  as_partition_table* table = as_partition_tables_get(tables, ns);
545  return table;
546 }
547 
548 /**
549  * @private
550  * Get mapped node given digest key and partition table. If there is no mapped node, a random
551  * node is used instead.
552  * as_nodes_release() must be called when done with node.
553  */
554 as_node*
555 as_partition_table_get_node(as_cluster* cluster, as_partition_table* table, const uint8_t* digest, bool write, as_policy_replica replica);
556 
557 /**
558  * @private
559  * Get shared memory mapped node given digest key. If there is no mapped node, a random node is used instead.
560  * as_nodes_release() must be called when done with node.
561  */
562 as_node*
563 as_shm_node_get(as_cluster* cluster, const char* ns, const uint8_t* digest, bool write, as_policy_replica replica);
564 
565 /**
566  * @private
567  * Get mapped node given digest key. If there is no mapped node, a random node is used instead.
568  * as_nodes_release() must be called when done with node.
569  */
570 static inline as_node*
571 as_node_get(as_cluster* cluster, const char* ns, const uint8_t* digest, bool write, as_policy_replica replica)
572 {
573 #ifdef AS_TEST_PROXY
574  return as_node_get_random(cluster);
575 #else
576  if (cluster->shm_info) {
577  return as_shm_node_get(cluster, ns, digest, write, replica);
578  }
579  else {
581  return as_partition_table_get_node(cluster, table, digest, write, replica);
582  }
583 #endif
584 }
585 
586 #ifdef __cplusplus
587 } // end extern "C"
588 #endif