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// **************************************************************************************************
78typedef 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// **************************************************************************************************
108typedef 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// **************************************************************************************************
120typedef 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// **************************************************************************************************
131typedef 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// **************************************************************************************************
140typedef 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// *****************************
154struct 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// **************************************************************************************************
164typedef 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
207typedef 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// **************************************************************************************************
218typedef struct as_sindex_physical_metadata_s {
219 pthread_rwlock_t slock;
220 struct btree *ibtr;
221} as_sindex_pmetadata;
222
223
224typedef 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
234typedef 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 */
259typedef 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 */
285typedef 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 */
306typedef 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.
323typedef 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
335typedef 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// **************************************************************************************************
350struct ai_obj;
351typedef 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 */
385typedef 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 */
402typedef 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
408typedef 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 */
436extern 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 */
443extern int as_sindex_reinit(char *name, char *params, cf_dyn_buf *db);
444// **************************************************************************************************
445
446/*
447 * INDEX BOOT
448 */
449// **************************************************************************************************
450extern int as_sindex_populate_done(as_sindex *si);
451extern int as_sindex_boot_populateall_done(as_namespace *ns);
452extern int as_sindex_boot_populateall();
453// **************************************************************************************************
454
455/*
456 * DDL AND METADATA QUERY
457 *
458*/
459// **************************************************************************************************
460extern int as_sindex_create(as_namespace *ns, as_sindex_metadata *imd);
461extern int as_sindex_destroy(as_namespace *ns, as_sindex_metadata *imd);
462extern int as_sindex_recreate(as_sindex_metadata *imd);
463extern void as_sindex_destroy_pmetadata(as_sindex *si);
464// **************************************************************************************************
465
466
467/*
468 * CREATION AND UPDATION OF SINDEX BIN
469 */
470// **************************************************************************************************
471extern 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);
473extern 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);
475extern int as_sindex_update_by_sbin(as_namespace *ns, const char *set, as_sindex_bin *start_sbin,
476 int num_sbins, cf_digest * pkey);
477extern 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// **************************************************************************************************
486int as_sindex_put_rd(as_sindex *si, as_storage_rd *rd);
487void as_sindex_putall_rd(as_namespace *ns, as_storage_rd *rd);
488// **************************************************************************************************
489
490
491/*
492 * UTILS
493 */
494// **************************************************************************************************
495extern int as_sindex_ns_has_sindex(as_namespace *ns);
496extern const char * as_sindex_err_str(int err_code);
497extern uint8_t as_sindex_err_to_clienterr(int err, char *fname, int lineno);
498extern bool as_sindex_isactive(as_sindex *si);
499extern int as_sindex_get_err(int op_code, char *filename, int lineno);
500extern as_sindex_status as_sindex__delete_from_set_binid_hash(as_namespace * ns,
501 as_sindex_metadata * imd);
502extern as_val * as_sindex_extract_val_from_path(as_sindex_metadata * imd, as_val * v);
503extern as_sindex_gc_status as_sindex_can_defrag_record(as_namespace *ns, cf_digest *keyd);
504extern as_sindex_status as_sindex_extract_bin_path(as_sindex_metadata * imd, char * path_str);
505int as_sindex_create_check_params(as_namespace* ns, as_sindex_metadata* imd);
506bool as_sindex_delete_checker(as_namespace *ns, as_sindex_metadata *imd);
507as_particle_type as_sindex_pktype(as_sindex_metadata * imd);
508extern const char * as_sindex_ktype_str(as_sindex_ktype type);
509extern as_sindex_ktype as_sindex_ktype_from_string(const char * type_str);
510int as_sindex_arr_lookup_by_set_binid_lockfree(as_namespace * ns,
511 const char *set, int binid, as_sindex ** si_arr);
512void as_sindex_delete_set(as_namespace * ns, char * set_name);
513// **************************************************************************************************
514
515/*
516 * INFO AND CONFIGS
517 */
518// **************************************************************************************************
519extern int as_sindex_list_str(as_namespace *ns, cf_dyn_buf *db);
520extern int as_sindex_stats_str(as_namespace *ns, char * iname, cf_dyn_buf *db);
521extern int as_sindex_set_config(as_namespace *ns, as_sindex_metadata *imd, char *params);
522extern void as_sindex_dump(char *nsname, char *iname, char *fname, bool verbose);
523extern void as_sindex_gconfig_default(struct as_config_s *c);
524extern 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);
526void as_sindex__config_default(as_sindex *si);
527void as_sindex_ticker_start(as_namespace * ns, as_sindex * si);
528void as_sindex_ticker(as_namespace * ns, as_sindex * si, uint64_t n_obj_scanned, uint64_t start_time);
529void as_sindex_ticker_done(as_namespace * ns, as_sindex * si, uint64_t start_time);
530// **************************************************************************************************
531
532/*
533 * HISTOGRAMS
534 */
535// **************************************************************************************************
536extern int as_sindex_histogram_enable(as_namespace *ns, char * iname, bool enable);
537extern int as_sindex_histogram_dumpall(as_namespace *ns);
538#define SINDEX_HIST_INSERT_DATA_POINT(si, type, start_time_ns) \
539do { \
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) \
548do { \
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// **************************************************************************************************
563extern int as_sindex_query(as_sindex *si, as_sindex_range *range, as_sindex_qctx *qctx);
564extern int as_sindex_range_free(as_sindex_range **srange);
565extern int as_sindex_rangep_from_msg(as_namespace *ns, as_msg *msgp, as_sindex_range **srange);
566extern int as_sindex_range_from_msg(as_namespace *ns, as_msg *msgp, as_sindex_range *srange);
567extern bool as_sindex_can_query(as_sindex *si);
568extern as_sindex * as_sindex_from_msg(as_namespace *ns, as_msg *msgp);
569extern as_sindex * as_sindex_from_range(as_namespace *ns, char *set, as_sindex_range *srange);
570extern int as_index_keys_reduce_fn(cf_ll_element *ele, void *udata);
571extern 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__);
583extern int as_sindex_reserve(as_sindex *si, char *fname, int lineno);
584extern void as_sindex_release(as_sindex *si, char *fname, int lineno);
585extern int as_sindex_imd_free(as_sindex_metadata *imd);
586extern int as_sindex_sbin_free(as_sindex_bin *sbin);
587extern int as_sindex_sbin_freeall(as_sindex_bin *sbin, int numval);
588void as_sindex_release_arr(as_sindex *si_arr[], int si_arr_sz);
589// **************************************************************************************************
590
591/*
592 * SINDEX LOCKS
593 */
594// **************************************************************************************************
595extern pthread_rwlock_t g_sindex_rwlock;
596#define SINDEX_GRLOCK() \
597do { \
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() \
603do { \
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() \
609do { \
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() \
615do { \
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) \
621do { \
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) \
627do { \
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) \
633do { \
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) \
639do { \
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// **************************************************************************************************
650extern void as_sindex_init_smd();
651extern void as_sindex_imd_to_smd_key(const as_sindex_metadata *imd, char *smd_key);
652extern bool as_sindex_delete_imd_to_smd_key(as_namespace *ns, as_sindex_metadata *imd, char *smd_key);
653extern 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// **************************************************************************************************
670extern void as_query_init();
671extern int as_query(as_transaction *tr, as_namespace *ns);
672extern int as_query_reinit(int set_size, int *actual_size);
673extern int as_query_worker_reinit(int set_size, int *actual_size);
674extern int as_query_list(char *name, cf_dyn_buf *db);
675extern int as_query_kill(uint64_t trid);
676extern void as_query_gconfig_default(struct as_config_s *c);
677extern as_mon_jobstat * as_query_get_jobstat(uint64_t trid);
678extern as_mon_jobstat * as_query_get_jobstat_all(int * size);
679extern int as_query_set_priority(uint64_t trid, uint32_t priority);
680extern void as_query_histogram_dumpall();
681extern as_index_keys_arr * as_index_get_keys_arr();
682extern void as_index_keys_release_arr_to_queue(as_index_keys_arr *v);
683extern int as_index_keys_ll_reduce_fn(cf_ll_element *ele, void *udata);
684extern void as_index_keys_ll_destroy_fn(cf_ll_element *ele);
685
686extern cf_atomic32 g_query_short_running;
687extern cf_atomic32 g_query_long_running;
688// **************************************************************************************************
689