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