1 | /* |
2 | * secondary_index.h |
3 | * |
4 | * Copyright (C) 2012-2015 Aerospike, Inc. |
5 | * |
6 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
7 | * license agreements. |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify it under |
10 | * the terms of the GNU Affero General Public License as published by the Free |
11 | * Software Foundation, either version 3 of the License, or (at your option) any |
12 | * later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
17 | * details. |
18 | * |
19 | * You should have received a copy of the GNU Affero General Public License |
20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
21 | */ |
22 | |
23 | /* |
24 | * SYNOPSIS |
25 | * Abstraction to support secondary indexes with multiple implementations. |
26 | */ |
27 | |
28 | #pragma once |
29 | |
30 | #include "base/datamodel.h" |
31 | #include "base/monitor.h" |
32 | #include "base/proto.h" |
33 | #include "base/smd.h" |
34 | #include "base/transaction.h" |
35 | #include "fabric/partition.h" |
36 | |
37 | #include "citrusleaf/cf_atomic.h" |
38 | #include "citrusleaf/cf_digest.h" |
39 | #include "citrusleaf/cf_ll.h" |
40 | |
41 | #include "dynbuf.h" |
42 | #include "hist.h" |
43 | #include <pthread.h> |
44 | #include <stdbool.h> |
45 | #include <stddef.h> |
46 | #include <stdint.h> |
47 | #include "storage/storage.h" |
48 | |
49 | |
50 | /* |
51 | * HARD LIMIT ON SIZES |
52 | */ |
53 | // ************************************************************************************************** |
54 | #define AS_SINDEX_MAX_STRING_KSIZE 2048 |
55 | #define AS_SINDEX_MAX_GEOJSON_KSIZE (1024 * 1024) |
56 | #define OLD_SINDEX_SMD_KEY_SIZE AS_ID_INAME_SZ + AS_ID_NAMESPACE_SZ |
57 | #define SINDEX_SMD_KEY_SIZE (AS_ID_NAMESPACE_SZ + AS_SET_NAME_MAX_SIZE + AS_SINDEX_MAX_PATH_LENGTH + 1 + 2 + 2) |
58 | #define SINDEX_SMD_VALUE_SIZE (AS_SMD_MAJORITY_CONSENSUS_KEYSIZE) |
59 | #define AS_SINDEX_MAX_PATH_LENGTH 256 |
60 | #define AS_SINDEX_MAX_DEPTH 10 |
61 | #define AS_SINDEX_TYPE_STR_SIZE 20 // LIST / MAPKEYS / MAPVALUES / DEFAULT(NONE) |
62 | #define AS_SINDEXDATA_STR_SIZE AS_SINDEX_MAX_PATH_LENGTH + 1 + 8 // binpath + separator (,) + keytype (string/numeric) |
63 | #define AS_INDEX_KEYS_ARRAY_QUEUE_HIGHWATER 512 |
64 | #define AS_INDEX_KEYS_PER_ARR 51 |
65 | // ************************************************************************************************** |
66 | |
67 | /* |
68 | * Return status codes for index object functions. |
69 | * |
70 | * NB: When adding error code add the string in the as_sindex_err_str |
71 | * in secondary_index.c |
72 | * |
73 | * Negative > 10 are the ones which show up and goes till client |
74 | * |
75 | * Positive are < 10 are something which are internal |
76 | */ |
77 | // ************************************************************************************************** |
78 | typedef enum { |
79 | AS_SINDEX_ERR_INAME_MAXLEN = -17, |
80 | AS_SINDEX_ERR_MAXCOUNT = -16, |
81 | AS_SINDEX_ERR_SET_MISMATCH = -15, |
82 | AS_SINDEX_ERR_UNKNOWN_KEYTYPE = -14, |
83 | AS_SINDEX_ERR_BIN_NOTFOUND = -13, |
84 | AS_SINDEX_ERR_TYPE_MISMATCH = -11, |
85 | |
86 | // Needed when attempting index create/query |
87 | AS_SINDEX_ERR_FOUND = -6, |
88 | AS_SINDEX_ERR_NOTFOUND = -5, |
89 | AS_SINDEX_ERR_NO_MEMORY = -4, |
90 | AS_SINDEX_ERR_PARAM = -3, |
91 | AS_SINDEX_ERR_NOT_READABLE = -2, |
92 | AS_SINDEX_ERR = -1, |
93 | AS_SINDEX_OK = 0, |
94 | |
95 | // Internal Not needed |
96 | AS_SINDEX_CONTINUE = 1, |
97 | AS_SINDEX_DONE = 2, |
98 | // Needed when inserting object in the btree. |
99 | AS_SINDEX_KEY_FOUND = 3, |
100 | AS_SINDEX_KEY_NOTFOUND = 4 |
101 | } as_sindex_status; |
102 | // ************************************************************************************************** |
103 | |
104 | /* |
105 | * SINDEX OP TYPES. |
106 | */ |
107 | // ************************************************************************************************** |
108 | typedef enum { |
109 | AS_SINDEX_OP_UPDATE = 0, |
110 | AS_SINDEX_OP_DELETE = 1, |
111 | AS_SINDEX_OP_INSERT = 2, |
112 | AS_SINDEX_OP_READ = 3 |
113 | } as_sindex_op; |
114 | // ************************************************************************************************** |
115 | |
116 | /* |
117 | * SINDEX GC RETURN ENUMS |
118 | */ |
119 | // ************************************************************************************************** |
120 | typedef enum { |
121 | AS_SINDEX_GC_OK = 0, |
122 | AS_SINDEX_GC_ERROR = 1, |
123 | AS_SINDEX_GC_SKIP_ITERATION = 2 |
124 | } as_sindex_gc_status; |
125 | // ************************************************************************************************** |
126 | |
127 | /* |
128 | * SECONDARY INDEX KEY TYPES same as COL_TYPE* |
129 | */ |
130 | // ************************************************************************************************** |
131 | typedef uint8_t as_sindex_ktype; |
132 | // ************************************************************************************************** |
133 | |
134 | /* |
135 | * SINDEX TYPES. |
136 | * THEY WOULD BE IN SYNC WITH THE CLIENTS. |
137 | * Do not change the order of this enum |
138 | */ |
139 | // ************************************************************************************************** |
140 | typedef enum { |
141 | AS_SINDEX_ITYPE_DEFAULT = 0, |
142 | AS_SINDEX_ITYPE_LIST = 1, |
143 | AS_SINDEX_ITYPE_MAPKEYS = 2, |
144 | AS_SINDEX_ITYPE_MAPVALUES = 3, |
145 | AS_SINDEX_ITYPE_MAX = 4 |
146 | } as_sindex_type; |
147 | #define AS_SINDEX_ITYPE_MAX_TO_STR_SZ 2 |
148 | // ************************************************************************************************** |
149 | |
150 | /* |
151 | * STRUCTURES FROM ALCHEMY |
152 | */ |
153 | // ***************************** |
154 | struct btree; |
155 | // ************************************************************************************************** |
156 | |
157 | /* |
158 | * STATS AND CONFIG STRUCTURE |
159 | * Stats are collected about memory utilization based on simple index |
160 | * overhead. Any insert delete from the secondary index would update |
161 | * this number and the memory management folks has to use this info. |
162 | */ |
163 | // ************************************************************************************************** |
164 | typedef struct as_sindex_stat_s { |
165 | cf_atomic64 n_objects; |
166 | int n_keys; |
167 | cf_atomic64 mem_used; |
168 | |
169 | cf_atomic64 n_reads; |
170 | cf_atomic64 read_errs; |
171 | |
172 | cf_atomic64 n_writes; |
173 | cf_atomic64 write_errs; |
174 | histogram * _write_hist; // Histogram to track time spend writing to the sindex |
175 | histogram * _si_prep_hist; |
176 | |
177 | cf_atomic64 n_deletes; |
178 | cf_atomic64 delete_errs; |
179 | histogram * _delete_hist; // Histogram to track time spend deleting from sindex |
180 | |
181 | // Background thread stats |
182 | cf_atomic64 loadtime; |
183 | cf_atomic64 recs_pending; |
184 | |
185 | cf_atomic64 n_defrag_records; |
186 | cf_atomic64 defrag_time; |
187 | |
188 | // Query Stats |
189 | histogram * _query_hist; // Histogram to track query latency |
190 | histogram * _query_batch_lookup; // Histogram to track latency of batch request from sindex tree. |
191 | histogram * _query_batch_io; // Histogram to track time spend doing I/O per batch |
192 | // --aggregation stats |
193 | cf_atomic64 n_aggregation; |
194 | cf_atomic64 agg_response_size; |
195 | cf_atomic64 agg_num_records; |
196 | cf_atomic64 agg_errs; |
197 | // --lookup stats |
198 | cf_atomic64 n_lookup; |
199 | cf_atomic64 lookup_response_size; |
200 | cf_atomic64 lookup_num_records; |
201 | cf_atomic64 lookup_errs; |
202 | |
203 | histogram * _query_rcnt_hist; // Histogram to track record counts from queries |
204 | histogram * _query_diff_hist; // Histogram to track the false positives found by queries |
205 | } as_sindex_stat; |
206 | |
207 | typedef struct as_sindex_config_s { |
208 | volatile uint16_t flag; // TODO change_name |
209 | } as_sindex_config; |
210 | |
211 | // ************************************************************************************************** |
212 | |
213 | |
214 | /* |
215 | * SINDEX METADATAS |
216 | */ |
217 | // ************************************************************************************************** |
218 | typedef struct as_sindex_physical_metadata_s { |
219 | pthread_rwlock_t slock; |
220 | struct btree *ibtr; |
221 | } as_sindex_pmetadata; |
222 | |
223 | |
224 | typedef struct as_sindex_path_s { |
225 | as_particle_type type; // MAP/LIST |
226 | union { |
227 | int index; // For index of lists. |
228 | char * key_str; // For string type keys in maps. |
229 | uint64_t key_int; // For integer type keys in maps. |
230 | } value; |
231 | as_particle_type mapkey_type; // This could be either string or integer type |
232 | } as_sindex_path; |
233 | |
234 | typedef struct as_sindex_metadata_s { |
235 | pthread_rwlock_t slock; |
236 | // Protected by lock |
237 | as_sindex_pmetadata * pimd; |
238 | uint32_t flag; |
239 | |
240 | // Static Data. Does not need protection |
241 | struct as_sindex_s * si; |
242 | char * ns_name; |
243 | char * set; |
244 | char * iname; |
245 | char * bname; |
246 | uint32_t binid; // Redundant info to aid search |
247 | as_sindex_ktype sktype; // Same as Aerospike Index type |
248 | as_sindex_type itype; |
249 | as_sindex_path path[AS_SINDEX_MAX_DEPTH]; |
250 | int path_length; |
251 | char * path_str; |
252 | int nprts; // Aerospike Index Number of Index partitions |
253 | } as_sindex_metadata; |
254 | |
255 | /* |
256 | * This structure right now hangs from the namespace structure for the |
257 | * Aerospike Index B-tree. |
258 | */ |
259 | typedef struct as_sindex_s { |
260 | int simatch; //self, shash match by name |
261 | // Protected by SI_GWLOCK |
262 | uint8_t state; |
263 | |
264 | // TODO : shift to imd |
265 | volatile uint16_t flag; |
266 | // No need to be volatile; little stale info |
267 | // about this is ok. And it is not checked |
268 | // in busy loop |
269 | bool enable_histogram; // default false; |
270 | |
271 | as_namespace *ns; |
272 | |
273 | // Protected by si reference |
274 | struct as_sindex_metadata_s *imd; |
275 | struct as_sindex_metadata_s *recreate_imd; |
276 | |
277 | as_sindex_stat stats; |
278 | as_sindex_config config; |
279 | } as_sindex; |
280 | |
281 | // ************************************************************************************************** |
282 | /* |
283 | * SBINS STRUCTURES |
284 | */ |
285 | typedef struct sbin_value_pool_s{ |
286 | uint32_t used_sz; |
287 | uint8_t *value; |
288 | } sbin_value_pool; |
289 | |
290 | #define AS_SINDEX_VALUESZ_ON_STACK 16 * 1000 |
291 | #define SINDEX_BINS_SETUP(skey_bin, size) \ |
292 | sbin_value_pool value_pool; \ |
293 | value_pool.value = alloca(AS_SINDEX_VALUESZ_ON_STACK); \ |
294 | value_pool.used_sz = 0; \ |
295 | as_sindex_bin skey_bin[(size)]; \ |
296 | for (int id = 0; id < (size); id++) { \ |
297 | skey_bin[id].si = NULL; \ |
298 | skey_bin[id].stack_buf = &value_pool; \ |
299 | } |
300 | |
301 | /* |
302 | * Used as structure to call into secondary indexes sindex_* interface |
303 | * TODO: as_sindex_bin is not appropriate name for this structure. |
304 | * maybe as_sindex_transaction |
305 | */ |
306 | typedef struct as_sindex_bin_s { |
307 | union { // we use this if we need to store only one value inside sbin. |
308 | int64_t int_val; // accessing this is much faster than accessing any other value |
309 | cf_digest str_val; // value on the stack. |
310 | } value; |
311 | uint64_t num_values; |
312 | void * values; // If there are more than 1 value in the sbin, we use this to |
313 | as_particle_type type; // point to them. the type of data which is going to get indexed |
314 | as_sindex_op op; // (STRING or INTEGER). Should we delete or insert this values |
315 | bool to_free; // from/into the secondary index tree. If the values are malloced. |
316 | as_sindex * si; // simatch of the si this bin is pointing to. |
317 | sbin_value_pool * stack_buf; |
318 | uint32_t heap_capacity; |
319 | } as_sindex_bin; |
320 | |
321 | // TODO: Reorganise this structure. |
322 | // No need of union. |
323 | typedef struct as_sindex_bin_data_s { |
324 | uint32_t id; |
325 | as_particle_type type; // this type is citrusleaf type |
326 | // Union is to support sindex for other datatypes in future. |
327 | // Currently sindex is supported for only int64 and string. |
328 | union { |
329 | int64_t i64; |
330 | } u; |
331 | cf_digest digest; |
332 | } as_sindex_bin_data; |
333 | |
334 | // Caution: Using this will waste 12 bytes per long type skey |
335 | typedef struct as_sindex_key_s { |
336 | union { |
337 | cf_digest str_key; |
338 | uint64_t int_key; |
339 | } key; |
340 | } as_sindex_key; |
341 | // ************************************************************************************************** |
342 | |
343 | |
344 | // ************************************************************************************************** |
345 | |
346 | /* |
347 | * STRUCTUES FOR QUERY MODULE |
348 | */ |
349 | // ************************************************************************************************** |
350 | struct ai_obj; |
351 | typedef struct as_sindex_query_context_s { |
352 | uint64_t bsize; |
353 | cf_ll *recl; |
354 | uint64_t n_bdigs; |
355 | |
356 | int range_index; |
357 | |
358 | // Physical Tree offset |
359 | bool new_ibtr; // If new tree |
360 | int pimd_idx; |
361 | |
362 | // IBTR offset |
363 | bool nbtr_done; // If nbtr was finished |
364 | // next iteration starts |
365 | // from key next to bkey |
366 | struct ai_obj *bkey; // offset in ibtr |
367 | |
368 | // NBTR offset |
369 | cf_digest bdig; |
370 | |
371 | // If true all query-able partitions will be reserved before processing the query |
372 | bool partitions_pre_reserved; |
373 | // Cache information about query-able partitions |
374 | bool can_partition_query[AS_PARTITIONS]; |
375 | } as_sindex_qctx; |
376 | |
377 | /* |
378 | * The range structure used to define the lower and upper limit |
379 | * along with the key types. |
380 | * |
381 | * [0, endl] |
382 | * [startl, -1(inf)] |
383 | * [startl, endl] |
384 | */ |
385 | typedef struct as_sindex_range_s { |
386 | uint8_t num_binval; |
387 | bool isrange; |
388 | as_sindex_bin_data start; |
389 | as_sindex_bin_data end; |
390 | as_sindex_type itype; |
391 | char bin_path[AS_SINDEX_MAX_PATH_LENGTH]; |
392 | uint64_t cellid; // target of regions-containing-point query |
393 | geo_region_t region; // target of points-in-region query |
394 | } as_sindex_range; |
395 | |
396 | /* |
397 | * sindex_keys are used by Secondary index queries to validate the keys against |
398 | * the values of bins |
399 | * ALl the jobs which runs over these queries also uses them |
400 | * Like - Aggregation Query |
401 | */ |
402 | typedef struct as_index_keys_arr_s { |
403 | uint32_t num; |
404 | cf_digest pindex_digs[AS_INDEX_KEYS_PER_ARR]; |
405 | as_sindex_key sindex_keys[AS_INDEX_KEYS_PER_ARR]; |
406 | } __attribute__ ((packed)) as_index_keys_arr; |
407 | |
408 | typedef struct as_index_keys_ll_element_s { |
409 | cf_ll_element ele; |
410 | as_index_keys_arr * keys_arr; |
411 | } as_index_keys_ll_element; |
412 | |
413 | |
414 | // ************************************************************************************************** |
415 | |
416 | |
417 | // APIs exposed to other modules |
418 | // TODO return values is actually enum. |
419 | |
420 | /* |
421 | * MODULE INIT AND SHUTDOWN |
422 | */ |
423 | // ************************************************************************************************** |
424 | |
425 | /* Index abstraction layer functions. */ |
426 | /* |
427 | * Initialize an instantiation of the index abstraction layer |
428 | * using the array of index type-specific parameters passed in. |
429 | * |
430 | * All indexes created during this instantiation will use these type-specific |
431 | * parameters (e.g., maximum data structure sizes, allocation policies, and any |
432 | * other tuning parameters.) |
433 | * |
434 | * Call once before creating any type of index object. |
435 | */ |
436 | extern int as_sindex_init(as_namespace *ns); |
437 | |
438 | /* |
439 | * Terminate an instantiation of the index abstraction layer. |
440 | * |
441 | * Do not use any "sindex" functions after calling this function, so free your indexes beforehand. |
442 | */ |
443 | extern int as_sindex_reinit(char *name, char *params, cf_dyn_buf *db); |
444 | // ************************************************************************************************** |
445 | |
446 | /* |
447 | * INDEX BOOT |
448 | */ |
449 | // ************************************************************************************************** |
450 | extern int as_sindex_populate_done(as_sindex *si); |
451 | extern int as_sindex_boot_populateall_done(as_namespace *ns); |
452 | extern int as_sindex_boot_populateall(); |
453 | // ************************************************************************************************** |
454 | |
455 | /* |
456 | * DDL AND METADATA QUERY |
457 | * |
458 | */ |
459 | // ************************************************************************************************** |
460 | extern int as_sindex_create(as_namespace *ns, as_sindex_metadata *imd); |
461 | extern int as_sindex_destroy(as_namespace *ns, as_sindex_metadata *imd); |
462 | extern int as_sindex_recreate(as_sindex_metadata *imd); |
463 | extern void as_sindex_destroy_pmetadata(as_sindex *si); |
464 | // ************************************************************************************************** |
465 | |
466 | |
467 | /* |
468 | * CREATION AND UPDATION OF SINDEX BIN |
469 | */ |
470 | // ************************************************************************************************** |
471 | extern int as_sindex_sbins_from_rd(as_storage_rd *rd, uint16_t from_bin, uint16_t to_bin, |
472 | as_sindex_bin sbins[], as_sindex_op op); |
473 | extern int as_sindex_sbins_from_bin(as_namespace *ns, const char *set, const as_bin *b, |
474 | as_sindex_bin * start_sbin, as_sindex_op op); |
475 | extern int as_sindex_update_by_sbin(as_namespace *ns, const char *set, as_sindex_bin *start_sbin, |
476 | int num_sbins, cf_digest * pkey); |
477 | extern uint32_t as_sindex_sbins_populate(as_sindex_bin *sbins, as_namespace *ns, const char *set_name, |
478 | const as_bin *b_old, const as_bin *b_new); |
479 | // ************************************************************************************************** |
480 | |
481 | |
482 | /* |
483 | * DMLs USING RECORDS |
484 | */ |
485 | // ************************************************************************************************** |
486 | int as_sindex_put_rd(as_sindex *si, as_storage_rd *rd); |
487 | void as_sindex_putall_rd(as_namespace *ns, as_storage_rd *rd); |
488 | // ************************************************************************************************** |
489 | |
490 | |
491 | /* |
492 | * UTILS |
493 | */ |
494 | // ************************************************************************************************** |
495 | extern int as_sindex_ns_has_sindex(as_namespace *ns); |
496 | extern const char * as_sindex_err_str(int err_code); |
497 | extern uint8_t as_sindex_err_to_clienterr(int err, char *fname, int lineno); |
498 | extern bool as_sindex_isactive(as_sindex *si); |
499 | extern int as_sindex_get_err(int op_code, char *filename, int lineno); |
500 | extern as_sindex_status as_sindex__delete_from_set_binid_hash(as_namespace * ns, |
501 | as_sindex_metadata * imd); |
502 | extern as_val * (as_sindex_metadata * imd, as_val * v); |
503 | extern as_sindex_gc_status as_sindex_can_defrag_record(as_namespace *ns, cf_digest *keyd); |
504 | extern as_sindex_status (as_sindex_metadata * imd, char * path_str); |
505 | int as_sindex_create_check_params(as_namespace* ns, as_sindex_metadata* imd); |
506 | bool as_sindex_delete_checker(as_namespace *ns, as_sindex_metadata *imd); |
507 | as_particle_type as_sindex_pktype(as_sindex_metadata * imd); |
508 | extern const char * as_sindex_ktype_str(as_sindex_ktype type); |
509 | extern as_sindex_ktype as_sindex_ktype_from_string(const char * type_str); |
510 | int as_sindex_arr_lookup_by_set_binid_lockfree(as_namespace * ns, |
511 | const char *set, int binid, as_sindex ** si_arr); |
512 | void as_sindex_delete_set(as_namespace * ns, char * set_name); |
513 | // ************************************************************************************************** |
514 | |
515 | /* |
516 | * INFO AND CONFIGS |
517 | */ |
518 | // ************************************************************************************************** |
519 | extern int as_sindex_list_str(as_namespace *ns, cf_dyn_buf *db); |
520 | extern int as_sindex_stats_str(as_namespace *ns, char * iname, cf_dyn_buf *db); |
521 | extern int as_sindex_set_config(as_namespace *ns, as_sindex_metadata *imd, char *params); |
522 | extern void as_sindex_dump(char *nsname, char *iname, char *fname, bool verbose); |
523 | extern void as_sindex_gconfig_default(struct as_config_s *c); |
524 | extern int as_info_parse_params_to_sindex_imd(char* params, as_sindex_metadata *imd, cf_dyn_buf* db, |
525 | bool is_create, bool *is_smd_op, char * cmd); |
526 | void as_sindex__config_default(as_sindex *si); |
527 | void as_sindex_ticker_start(as_namespace * ns, as_sindex * si); |
528 | void as_sindex_ticker(as_namespace * ns, as_sindex * si, uint64_t n_obj_scanned, uint64_t start_time); |
529 | void as_sindex_ticker_done(as_namespace * ns, as_sindex * si, uint64_t start_time); |
530 | // ************************************************************************************************** |
531 | |
532 | /* |
533 | * HISTOGRAMS |
534 | */ |
535 | // ************************************************************************************************** |
536 | extern int as_sindex_histogram_enable(as_namespace *ns, char * iname, bool enable); |
537 | extern int as_sindex_histogram_dumpall(as_namespace *ns); |
538 | #define SINDEX_HIST_INSERT_DATA_POINT(si, type, start_time_ns) \ |
539 | do { \ |
540 | if (si->enable_histogram && start_time_ns != 0) { \ |
541 | if (si->stats._ ##type) { \ |
542 | histogram_insert_data_point(si->stats._ ##type, start_time_ns); \ |
543 | } \ |
544 | } \ |
545 | } while(0); |
546 | |
547 | #define SINDEX_HIST_INSERT_RAW(si, type, value) \ |
548 | do { \ |
549 | if (si->enable_histogram) { \ |
550 | if (si->stats._ ##type) { \ |
551 | histogram_insert_raw(si->stats._ ##type, value); \ |
552 | } \ |
553 | } \ |
554 | } while(0); |
555 | |
556 | |
557 | // ************************************************************************************************** |
558 | |
559 | /* |
560 | * UTILS FOR QUERIES |
561 | */ |
562 | // ************************************************************************************************** |
563 | extern int as_sindex_query(as_sindex *si, as_sindex_range *range, as_sindex_qctx *qctx); |
564 | extern int as_sindex_range_free(as_sindex_range **srange); |
565 | extern int as_sindex_rangep_from_msg(as_namespace *ns, as_msg *msgp, as_sindex_range **srange); |
566 | extern int as_sindex_range_from_msg(as_namespace *ns, as_msg *msgp, as_sindex_range *srange); |
567 | extern bool as_sindex_can_query(as_sindex *si); |
568 | extern as_sindex * as_sindex_from_msg(as_namespace *ns, as_msg *msgp); |
569 | extern as_sindex * as_sindex_from_range(as_namespace *ns, char *set, as_sindex_range *srange); |
570 | extern int as_index_keys_reduce_fn(cf_ll_element *ele, void *udata); |
571 | extern void as_index_keys_destroy_fn(cf_ll_element *ele); |
572 | // ************************************************************************************************** |
573 | |
574 | |
575 | /* |
576 | * RESERVE, RELEASE AND FREE |
577 | */ |
578 | // ************************************************************************************************** |
579 | #define AS_SINDEX_RESERVE(si) \ |
580 | as_sindex_reserve((si), __FILE__, __LINE__); |
581 | #define AS_SINDEX_RELEASE(si) \ |
582 | as_sindex_release((si), __FILE__, __LINE__); |
583 | extern int as_sindex_reserve(as_sindex *si, char *fname, int lineno); |
584 | extern void as_sindex_release(as_sindex *si, char *fname, int lineno); |
585 | extern int as_sindex_imd_free(as_sindex_metadata *imd); |
586 | extern int as_sindex_sbin_free(as_sindex_bin *sbin); |
587 | extern int as_sindex_sbin_freeall(as_sindex_bin *sbin, int numval); |
588 | void as_sindex_release_arr(as_sindex *si_arr[], int si_arr_sz); |
589 | // ************************************************************************************************** |
590 | |
591 | /* |
592 | * SINDEX LOCKS |
593 | */ |
594 | // ************************************************************************************************** |
595 | extern pthread_rwlock_t g_sindex_rwlock; |
596 | #define SINDEX_GRLOCK() \ |
597 | do { \ |
598 | int ret = pthread_rwlock_rdlock(&g_sindex_rwlock); \ |
599 | if (ret) cf_warning(AS_SINDEX, "GRLOCK(%d) %s:%d",ret, __FILE__, __LINE__); \ |
600 | } while (0); |
601 | |
602 | #define SINDEX_GWLOCK() \ |
603 | do { \ |
604 | int ret = pthread_rwlock_wrlock(&g_sindex_rwlock); \ |
605 | if (ret) cf_warning(AS_SINDEX, "GWLOCK(%d) %s:%d", ret, __FILE__, __LINE__); \ |
606 | } while (0); |
607 | |
608 | #define SINDEX_GRUNLOCK() \ |
609 | do { \ |
610 | int ret = pthread_rwlock_unlock(&g_sindex_rwlock); \ |
611 | if (ret) cf_warning(AS_SINDEX, "GRUNLOCK (%d) %s:%d",ret, __FILE__, __LINE__); \ |
612 | } while (0); |
613 | |
614 | #define SINDEX_GWUNLOCK() \ |
615 | do { \ |
616 | int ret = pthread_rwlock_unlock(&g_sindex_rwlock); \ |
617 | if (ret) cf_warning(AS_SINDEX, "GWUNLOCK (%d) %s:%d",ret, __FILE__, __LINE__); \ |
618 | } while (0); |
619 | |
620 | #define PIMD_RLOCK(l) \ |
621 | do { \ |
622 | int ret = pthread_rwlock_rdlock((l)); \ |
623 | if (ret) cf_warning(AS_SINDEX, "RLOCK_ONLY (%d) %s:%d", ret, __FILE__, __LINE__); \ |
624 | } while(0); |
625 | |
626 | #define PIMD_WLOCK(l) \ |
627 | do { \ |
628 | int ret = pthread_rwlock_wrlock((l)); \ |
629 | if (ret) cf_warning(AS_SINDEX, "WLOCK_ONLY (%d) %s:%d",ret, __FILE__, __LINE__); \ |
630 | } while(0); |
631 | |
632 | #define PIMD_RUNLOCK(l) \ |
633 | do { \ |
634 | int ret = pthread_rwlock_unlock((l)); \ |
635 | if (ret) cf_warning(AS_SINDEX, "RUNLOCK_ONLY (%d) %s:%d",ret, __FILE__, __LINE__); \ |
636 | } while(0); |
637 | |
638 | #define PIMD_WUNLOCK(l) \ |
639 | do { \ |
640 | int ret = pthread_rwlock_unlock((l)); \ |
641 | if (ret) cf_warning(AS_SINDEX, "WUNLOCK_ONLY (%d) %s:%d",ret, __FILE__, __LINE__); \ |
642 | } while(0); |
643 | |
644 | // ************************************************************************************************** |
645 | |
646 | /* |
647 | * APIs for SMD |
648 | */ |
649 | // ************************************************************************************************** |
650 | extern void as_sindex_init_smd(); |
651 | extern void as_sindex_imd_to_smd_key(const as_sindex_metadata *imd, char *smd_key); |
652 | extern bool as_sindex_delete_imd_to_smd_key(as_namespace *ns, as_sindex_metadata *imd, char *smd_key); |
653 | extern void as_sindex_smd_accept_cb(const cf_vector *items, as_smd_accept_type accept_type); |
654 | // ************************************************************************************************** |
655 | |
656 | /* |
657 | * QUERY MACROS |
658 | */ |
659 | // ************************************************************************************************** |
660 | #define AS_QUERY_OK AS_SINDEX_OK |
661 | #define AS_QUERY_ERR AS_SINDEX_ERR |
662 | #define AS_QUERY_CONTINUE AS_SINDEX_CONTINUE |
663 | #define AS_QUERY_DONE AS_SINDEX_DONE |
664 | // ************************************************************************************************** |
665 | |
666 | /* |
667 | * QUERY APIs exposed to other modules |
668 | */ |
669 | // ************************************************************************************************** |
670 | extern void as_query_init(); |
671 | extern int as_query(as_transaction *tr, as_namespace *ns); |
672 | extern int as_query_reinit(int set_size, int *actual_size); |
673 | extern int as_query_worker_reinit(int set_size, int *actual_size); |
674 | extern int as_query_list(char *name, cf_dyn_buf *db); |
675 | extern int as_query_kill(uint64_t trid); |
676 | extern void as_query_gconfig_default(struct as_config_s *c); |
677 | extern as_mon_jobstat * as_query_get_jobstat(uint64_t trid); |
678 | extern as_mon_jobstat * as_query_get_jobstat_all(int * size); |
679 | extern int as_query_set_priority(uint64_t trid, uint32_t priority); |
680 | extern void as_query_histogram_dumpall(); |
681 | extern as_index_keys_arr * as_index_get_keys_arr(); |
682 | extern void as_index_keys_release_arr_to_queue(as_index_keys_arr *v); |
683 | extern int as_index_keys_ll_reduce_fn(cf_ll_element *ele, void *udata); |
684 | extern void as_index_keys_ll_destroy_fn(cf_ll_element *ele); |
685 | |
686 | extern cf_atomic32 g_query_short_running; |
687 | extern cf_atomic32 g_query_long_running; |
688 | // ************************************************************************************************** |
689 | |