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-2015 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 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 #include <aerospike/as_config.h>
24 #include <aerospike/as_node.h>
25 #include <aerospike/as_partition.h>
26 #include <aerospike/as_policy.h>
27 #include <citrusleaf/cf_atomic.h>
28 #include "ck_pr.h"
29 
30 /******************************************************************************
31  * MACROS
32  *****************************************************************************/
33 
34 #define AS_NUM_BATCH_THREADS 6
35 #define AS_NUM_SCAN_THREADS 5
36 #define AS_NUM_QUERY_THREADS 5
37 
38 /******************************************************************************
39  * TYPES
40  *****************************************************************************/
41 
42 /**
43  * Seed host.
44  */
45 typedef struct as_seed_s {
46  /**
47  * Host name.
48  */
49  char* name;
50 
51  /**
52  * Host port.
53  */
54  in_port_t port;
55 } as_seed;
56 
57 /**
58  * @private
59  * Reference counted array of server node pointers.
60  */
61 typedef struct as_nodes_s {
62  /**
63  * @private
64  * Reference count of node array.
65  */
66  uint32_t ref_count;
67 
68  /**
69  * @private
70  * Length of node array.
71  */
72  uint32_t size;
73 
74  /**
75  * @private
76  * Server node array.
77  */
78  as_node* array[];
79 } as_nodes;
80 
81 /**
82  * @private
83  * Reference counted release function definition.
84  */
85 typedef void (*as_release_fn) (void* value);
86 
87 /**
88  * @private
89  * Reference counted data to be garbage collected.
90  */
91 typedef struct as_gc_item_s {
92  /**
93  * @private
94  * Reference counted data to be garbage collected.
95  */
96  void* data;
97 
98  /**
99  * @private
100  * Release function.
101  */
103 } as_gc_item;
104 
105 /**
106  * Cluster of server nodes.
107  */
108 typedef struct as_cluster_s {
109  /**
110  * @private
111  * Active nodes in cluster.
112  */
114 
115  /**
116  * @private
117  * Hints for best node for a partition.
118  */
120 
121  /**
122  * @private
123  * Batch process queue.
124  */
125  cf_queue* batch_q;
126 
127  /**
128  * @private
129  * Scan process queue.
130  */
131  cf_queue* scan_q;
132 
133  /**
134  * @private
135  * Query process queue.
136  */
137  cf_queue* query_q;
138 
139  /**
140  * @private
141  * Nodes to be garbage collected.
142  */
143  as_vector* /* <as_gc_item> */ gc;
144 
145  /**
146  * @private
147  * Shared memory implementation of cluster.
148  */
149  struct as_shm_info_s* shm_info;
150 
151  /**
152  * @private
153  * User name in UTF-8 encoded bytes.
154  */
155  char* user;
156 
157  /**
158  * @private
159  * Password in hashed format in bytes.
160  */
161  char* password;
162 
163  /**
164  * @private
165  * Initial seed nodes specified by user.
166  */
168 
169  /**
170  * @private
171  * Length of seeds array.
172  */
173  uint32_t seeds_size;
174 
175  /**
176  * @private
177  * Length of ip_map array.
178  */
179  uint32_t ip_map_size;
180 
181  /**
182  * @private
183  * A IP translation table is used in cases where different clients use different server
184  * IP addresses. This may be necessary when using clients from both inside and outside
185  * a local area network. Default is no translation.
186  *
187  * The key is the IP address returned from friend info requests to other servers. The
188  * value is the real IP address used to connect to the server.
189  */
191 
192  /**
193  * @private
194  * Lock for the tend thread to wait on with the tend interval as timeout.
195  * Normally locked, resulting in waiting a full interval between
196  * tend iterations. Upon cluster shutdown, unlocked by the main
197  * thread, allowing a fast termination of the tend thread.
198  */
199  pthread_mutex_t tend_lock;
200 
201  /**
202  * @private
203  * Tend thread identifier to be used with tend_lock.
204  */
205  pthread_cond_t tend_cond;
206 
207  /**
208  * @private
209  * Milliseconds between cluster tends.
210  */
211  uint32_t tend_interval;
212 
213  /**
214  * @private
215  * Size of node's synchronous connection pool.
216  */
217  uint32_t conn_queue_size;
218 
219  /**
220  * @private
221  * Initial connection timeout in milliseconds.
222  */
223  uint32_t conn_timeout_ms;
224 
225  /**
226  * @private
227  * Maximum socket idle in seconds.
228  */
229  uint32_t max_socket_idle;
230 
231  /**
232  * @private
233  * Random node index.
234  */
235  uint32_t node_index;
236 
237  /**
238  * @private
239  * Batch initialize indicator.
240  */
242 
243  /**
244  * @private
245  * Scan initialize indicator.
246  */
248 
249  /**
250  * @private
251  * Query initialize indicator.
252  */
254 
255  /**
256  * @private
257  * Total number of data partitions used by cluster.
258  */
259  cl_partition_id n_partitions;
260 
261  /**
262  * @private
263  * Should continue to tend cluster.
264  */
265  volatile bool valid;
266 
267  /**
268  * @private
269  * Batch transaction lock.
270  */
271  pthread_mutex_t batch_init_lock;
272 
273  /**
274  * @private
275  * Cluster tend thread.
276  */
277  pthread_t tend_thread;
278 
279  /**
280  * @private
281  * Batch process threads.
282  */
283  pthread_t batch_threads[AS_NUM_BATCH_THREADS];
284 
285  /**
286  * @private
287  * Scan process threads.
288  */
289  pthread_t scan_threads[AS_NUM_SCAN_THREADS];
290 
291  /**
292  * @private
293  * Query process threads.
294  */
295  pthread_t query_threads[AS_NUM_QUERY_THREADS];
296 } as_cluster;
297 
298 /******************************************************************************
299  * FUNCTIONS
300  ******************************************************************************/
301 
302 /**
303  * Create and initialize cluster.
304  */
305 int
306 as_cluster_create(as_config* config, as_cluster** cluster);
307 
308 /**
309  * Close all connections and release memory associated with cluster.
310  */
311 void
313 
314 /**
315  * Is cluster connected to any server nodes.
316  */
317 bool
319 
320 /**
321  * Get all node names in cluster.
322  */
323 void
324 as_cluster_get_node_names(as_cluster* cluster, int* n_nodes, char** node_names);
325 
326 /**
327  * Reserve reference counted access to cluster nodes.
328  */
329 static inline as_nodes*
331 {
332  as_nodes* nodes = (as_nodes *)ck_pr_load_ptr(&cluster->nodes);
333  //ck_pr_fence_acquire();
334  ck_pr_inc_32(&nodes->ref_count);
335  return nodes;
336 }
337 
338 /**
339  * Release reference counted access to cluster nodes.
340  */
341 static inline void
343 {
344  //ck_pr_fence_release();
345 
346  bool destroy;
347  ck_pr_dec_32_zero(&nodes->ref_count, &destroy);
348 
349  if (destroy) {
350  cf_free(nodes);
351  }
352 }
353 
354 /**
355  * @private
356  * Change user and password that is used to authenticate with cluster servers.
357  */
358 void
359 as_cluster_change_password(as_cluster* cluster, const char* user, const char* password);
360 
361 /**
362  * @private
363  * Get random node in the cluster.
364  * as_nodes_release() must be called when done with node.
365  */
366 as_node*
368 
369 /**
370  * @private
371  * Get node given node name.
372  * as_nodes_release() must be called when done with node.
373  */
374 as_node*
375 as_node_get_by_name(as_cluster* cluster, const char* name);
376 
377 /**
378  * @private
379  * Reserve reference counted access to partition tables.
380  * as_partition_tables_release() must be called when done with tables.
381  */
382 static inline as_partition_tables*
384 {
385  as_partition_tables* tables = (as_partition_tables *)ck_pr_load_ptr(&cluster->partition_tables);
386  ck_pr_inc_32(&tables->ref_count);
387  return tables;
388 }
389 
390 /**
391  * @private
392  * Release reference counted access to partition tables.
393  */
394 static inline void
396 {
397  bool destroy;
398  ck_pr_dec_32_zero(&tables->ref_count, &destroy);
399 
400  if (destroy) {
401  cf_free(tables);
402  }
403 }
404 
405 /**
406  * @private
407  * Get partition table given namespace.
408  */
409 static inline as_partition_table*
411 {
412  // Partition tables array size does not currently change after first cluster tend.
413  // Also, there is a one second delayed garbage collection coupled with as_partition_tables_get()
414  // being very fast. Reference counting the tables array is not currently necessary, but do it
415  // anyway in case the server starts supporting dynamic namespaces.
417  as_partition_table* table = as_partition_tables_get(tables, ns);
419  return table;
420 }
421 
422 /**
423  * @private
424  * Get mapped node given digest key and partition table. If there is no mapped node, a random
425  * node is used instead.
426  * as_nodes_release() must be called when done with node.
427  */
428 as_node*
429 as_partition_table_get_node(as_cluster* cluster, as_partition_table* table, const cf_digest* d, bool write, as_policy_replica replica);
430 
431 /**
432  * @private
433  * Get shared memory mapped node given digest key. If there is no mapped node, a random node is used instead.
434  * as_nodes_release() must be called when done with node.
435  */
436 as_node*
437 as_shm_node_get(as_cluster* cluster, const char* ns, const cf_digest* d, bool write, as_policy_replica replica);
438 
439 /**
440  * @private
441  * Get mapped node given digest key. If there is no mapped node, a random node is used instead.
442  * as_nodes_release() must be called when done with node.
443  */
444 static inline as_node*
445 as_node_get(as_cluster* cluster, const char* ns, const cf_digest* d, bool write, as_policy_replica replica)
446 {
447  if (cluster->shm_info) {
448  return as_shm_node_get(cluster, ns, d, write, replica);
449  }
450  else {
452  return as_partition_table_get_node(cluster, table, d, write, replica);
453  }
454 }
455 
456 #ifdef __cplusplus
457 } // end extern "C"
458 #endif