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-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_config.h>
20 #include <aerospike/as_node.h>
21 #include <aerospike/as_partition.h>
22 #include <aerospike/as_policy.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  * @private
38  * Reference counted array of server node pointers.
39  */
40 typedef struct as_nodes_s {
41  /**
42  * @private
43  * Reference count of node array.
44  */
45  uint32_t ref_count;
46 
47  /**
48  * @private
49  * Length of node array.
50  */
51  uint32_t size;
52 
53  /**
54  * @private
55  * Server node array.
56  */
57  as_node* array[];
58 } as_nodes;
59 
60 /**
61  * @private
62  * Reference counted release function definition.
63  */
64 typedef void (*as_release_fn) (void* value);
65 
66 /**
67  * @private
68  * Reference counted data to be garbage collected.
69  */
70 typedef struct as_gc_item_s {
71  /**
72  * @private
73  * Reference counted data to be garbage collected.
74  */
75  void* data;
76 
77  /**
78  * @private
79  * Release function.
80  */
82 } as_gc_item;
83 
84 /**
85  * Cluster of server nodes.
86  */
87 typedef struct as_cluster_s {
88  /**
89  * @private
90  * Active nodes in cluster.
91  */
93 
94  /**
95  * @private
96  * Hints for best node for a partition.
97  */
99 
100  /**
101  * @private
102  * Nodes to be garbage collected.
103  */
104  as_vector* /* <as_gc_item> */ gc;
105 
106  /**
107  * @private
108  * Shared memory implementation of cluster.
109  */
110  struct as_shm_info_s* shm_info;
111 
112  /**
113  * @private
114  * User name in UTF-8 encoded bytes.
115  */
116  char* user;
117 
118  /**
119  * @private
120  * Password in hashed format in bytes.
121  */
122  char* password;
123 
124  /**
125  * @private
126  * Expected cluster name for all nodes. May be null.
127  */
129 
130  /**
131  * @private
132  * Initial seed hosts specified by user.
133  */
134  as_vector* /* <as_host> */ seeds;
135 
136  /**
137  * @private
138  * A IP translation table is used in cases where different clients use different server
139  * IP addresses. This may be necessary when using clients from both inside and outside
140  * a local area network. Default is no translation.
141  *
142  * The key is the IP address returned from friend info requests to other servers. The
143  * value is the real IP address used to connect to the server.
144  */
145  as_vector* /* <as_addr_map> */ ip_map;
146 
147  /**
148  * @private
149  * TLS parameters
150  */
152 
153  /**
154  * @private
155  * Pool of threads used to query server nodes in parallel for batch, scan and query.
156  */
158 
159  /**
160  * @private
161  * Cluster tend thread.
162  */
163  pthread_t tend_thread;
164 
165  /**
166  * @private
167  * Lock for adding/removing seeds.
168  */
169  pthread_mutex_t seed_lock;
170 
171  /**
172  * @private
173  * Lock for the tend thread to wait on with the tend interval as timeout.
174  * Normally locked, resulting in waiting a full interval between
175  * tend iterations. Upon cluster shutdown, unlocked by the main
176  * thread, allowing a fast termination of the tend thread.
177  */
178  pthread_mutex_t tend_lock;
179 
180  /**
181  * @private
182  * Tend thread identifier to be used with tend_lock.
183  */
184  pthread_cond_t tend_cond;
185 
186  /**
187  * @private
188  * Configuration version. Incremented, when the configuration is changed.
189  */
190  uint32_t version;
191 
192  /**
193  * @private
194  * Milliseconds between cluster tends.
195  */
196  uint32_t tend_interval;
197 
198  /**
199  * @private
200  * Maximum number of synchronous connections allowed per server node.
201  */
203 
204  /**
205  * @private
206  * Maximum number of asynchronous (non-pipeline) connections allowed for each node.
207  * Async transactions will be rejected if the maximum async node connections would be exceeded.
208  * This variable is ignored if asynchronous event loops are not created.
209  */
211 
212  /**
213  * @private
214  * Maximum number of pipeline connections allowed for each node.
215  * Pipeline transactions will be rejected if the maximum pipeline node connections would be exceeded.
216  * This variable is ignored if asynchronous event loops are not created.
217  */
219 
220  /**
221  * @private
222  * Number of synchronous connection pools used for each node.
223  */
225 
226  /**
227  * @private
228  * Number of pending async commands (i.e., commands with an outstanding reply).
229  */
230  uint32_t async_pending;
231 
232  /**
233  * @private
234  * Number of active async pipeline and non-pipeline connections combined.
235  */
237 
238  /**
239  * @private
240  * Number of async connections in the pools.
241  */
242  uint32_t async_conn_pool;
243 
244  /**
245  * @private
246  * Initial connection timeout in milliseconds.
247  */
248  uint32_t conn_timeout_ms;
249 
250  /**
251  * @private
252  * Maximum socket idle in seconds.
253  */
254  uint32_t max_socket_idle;
255 
256  /**
257  * @private
258  * Random node index.
259  */
260  uint32_t node_index;
261 
262  /**
263  * @private
264  * Total number of data partitions used by cluster.
265  */
266  uint16_t n_partitions;
267 
268  /**
269  * @private
270  * If "services-alternate" should be used instead of "services"
271  */
273 
274  /**
275  * @private
276  * Should continue to tend cluster.
277  */
278  volatile bool valid;
279 } as_cluster;
280 
281 /******************************************************************************
282  * FUNCTIONS
283  ******************************************************************************/
284 
285 /**
286  * Create and initialize cluster.
287  */
288 as_status
289 as_cluster_create(as_config* config, as_error* err, as_cluster** cluster);
290 
291 /**
292  * Close all connections and release memory associated with cluster.
293  */
294 void
296 
297 /**
298  * Is cluster connected to any server nodes.
299  */
300 bool
302 
303 /**
304  * Get all node names in cluster.
305  */
306 void
307 as_cluster_get_node_names(as_cluster* cluster, int* n_nodes, char** node_names);
308 
309 /**
310  * Reserve reference counted access to cluster nodes.
311  */
312 static inline as_nodes*
314 {
315  as_nodes* nodes = (as_nodes *)ck_pr_load_ptr(&cluster->nodes);
316  //ck_pr_fence_acquire();
317  ck_pr_inc_32(&nodes->ref_count);
318  return nodes;
319 }
320 
321 /**
322  * Release reference counted access to cluster nodes.
323  */
324 static inline void
326 {
327  //ck_pr_fence_release();
328 
329  bool destroy;
330  ck_pr_dec_32_zero(&nodes->ref_count, &destroy);
331 
332  if (destroy) {
333  cf_free(nodes);
334  }
335 }
336 
337 /**
338  * Add seed to cluster.
339  */
340 void
341 as_cluster_add_seed(as_cluster* cluster, const char* hostname, const char* tls_name, uint16_t port);
342 
343 /**
344  * Remove seed from cluster.
345  */
346 void
347 as_cluster_remove_seed(as_cluster* cluster, const char* hostname, uint16_t port);
348 
349 /**
350  * Change maximum async connections per node.
351  */
352 void
353 as_cluster_set_async_max_conns_per_node(as_cluster* cluster, uint32_t async_size, uint32_t pipe_size);
354 
355 /**
356  * @private
357  * Change user and password that is used to authenticate with cluster servers.
358  */
359 void
360 as_cluster_change_password(as_cluster* cluster, const char* user, const char* password);
361 
362 /**
363  * @private
364  * Get random node in the cluster.
365  * as_nodes_release() must be called when done with node.
366  */
367 as_node*
369 
370 /**
371  * @private
372  * Get node given node name.
373  * as_nodes_release() must be called when done with node.
374  */
375 as_node*
376 as_node_get_by_name(as_cluster* cluster, const char* name);
377 
378 /**
379  * @private
380  * Reserve reference counted access to partition tables.
381  * as_partition_tables_release() must be called when done with tables.
382  */
383 static inline as_partition_tables*
385 {
386  as_partition_tables* tables = (as_partition_tables *)ck_pr_load_ptr(&cluster->partition_tables);
387  ck_pr_inc_32(&tables->ref_count);
388  return tables;
389 }
390 
391 /**
392  * @private
393  * Release reference counted access to partition tables.
394  */
395 static inline void
397 {
398  bool destroy;
399  ck_pr_dec_32_zero(&tables->ref_count, &destroy);
400 
401  if (destroy) {
402  cf_free(tables);
403  }
404 }
405 
406 /**
407  * @private
408  * Get partition table given namespace.
409  */
410 static inline as_partition_table*
412 {
413  // Partition tables array size does not currently change after first cluster tend.
414  // Also, there is a one second delayed garbage collection coupled with as_partition_tables_get()
415  // being very fast. Reference counting the tables array is not currently necessary, but do it
416  // anyway in case the server starts supporting dynamic namespaces.
418  as_partition_table* table = as_partition_tables_get(tables, ns);
420  return table;
421 }
422 
423 /**
424  * @private
425  * Get mapped node given digest key and partition table. If there is no mapped node, a random
426  * node is used instead.
427  * as_nodes_release() must be called when done with node.
428  */
429 as_node*
430 as_partition_table_get_node(as_cluster* cluster, as_partition_table* table, const uint8_t* digest, as_policy_replica replica, bool master);
431 
432 /**
433  * @private
434  * Get shared memory mapped node given digest key. If there is no mapped node, a random node is used instead.
435  * as_nodes_release() must be called when done with node.
436  */
437 as_node*
438 as_shm_node_get(as_cluster* cluster, const char* ns, const uint8_t* digest, as_policy_replica replica, bool master);
439 
440 /**
441  * @private
442  * Get mapped node given digest key. If there is no mapped node, a random node is used instead.
443  * as_nodes_release() must be called when done with node.
444  */
445 static inline as_node*
446 as_node_get(as_cluster* cluster, const char* ns, const uint8_t* digest, as_policy_replica replica, bool master)
447 {
448 #ifdef AS_TEST_PROXY
449  return as_node_get_random(cluster);
450 #else
451  if (cluster->shm_info) {
452  return as_shm_node_get(cluster, ns, digest, replica, master);
453  }
454  else {
456  return as_partition_table_get_node(cluster, table, digest, replica, master);
457  }
458 #endif
459 }
460 
461 #ifdef __cplusplus
462 } // end extern "C"
463 #endif