All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_scan.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 #pragma GCC diagnostic ignored "-Waddress"
19 
20 #include <aerospike/as_bin.h>
21 #include <aerospike/as_key.h>
22 #include <aerospike/as_predexp.h>
23 #include <aerospike/as_udf.h>
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /******************************************************************************
30  * MACROS
31  *****************************************************************************/
32 
33 /**
34  * Default value for as_scan.priority
35  */
36 #define AS_SCAN_PRIORITY_DEFAULT AS_SCAN_PRIORITY_AUTO
37 
38 /**
39  * Default value for as_scan.percent
40  */
41 #define AS_SCAN_PERCENT_DEFAULT 100
42 
43 /**
44  * Default value for as_scan.no_bins
45  */
46 #define AS_SCAN_NOBINS_DEFAULT false
47 
48 /**
49  * Default value for as_scan.concurrent
50  */
51 #define AS_SCAN_CONCURRENT_DEFAULT false
52 
53 /**
54  * Default value for as_scan.deserialize_list_map
55  */
56 #define AS_SCAN_DESERIALIZE_DEFAULT true
57 
58 /******************************************************************************
59  * TYPES
60  *****************************************************************************/
61 
62 /**
63  * Priority levels for a scan operation.
64  */
65 typedef enum as_scan_priority_e {
66 
67  /**
68  * The cluster will auto adjust the scan priority.
69  */
71 
72  /**
73  * Low priority scan.
74  */
76 
77  /**
78  * Medium priority scan.
79  */
81 
82  /**
83  * High priority scan.
84  */
86 
88 
89 /**
90  * The status of a particular background scan.
91  */
92 typedef enum as_scan_status_e {
93 
94  /**
95  * The scan status is undefined.
96  * This is likely due to the status not being properly checked.
97  */
99 
100  /**
101  * The scan is currently running.
102  */
104 
105  /**
106  * The scan was aborted. Due to failure or the user.
107  */
109 
110  /**
111  * The scan completed successfully.
112  */
114 
116 
117 /**
118  * Information about a particular background scan.
119  *
120  * @ingroup as_scan_object
121  */
122 typedef struct as_scan_info_s {
123 
124  /**
125  * Status of the scan.
126  */
128 
129  /**
130  * Progress estimate for the scan, as percentage.
131  */
132  uint32_t progress_pct;
133 
134  /**
135  * How many records have been scanned.
136  */
137  uint32_t records_scanned;
138 
139 } as_scan_info;
140 
141 /**
142  * Sequence of bins which should be selected during a scan.
143  *
144  * Entries can either be initialized on the stack or on the heap.
145  *
146  * Initialization should be performed via a query object, using:
147  * - as_scan_select_init()
148  * - as_scan_select_inita()
149  */
150 typedef struct as_scan_bins_s {
151 
152  /**
153  * @private
154  * If true, then as_scan_destroy() will free this instance.
155  */
156  bool _free;
157 
158  /**
159  * Number of entries allocated
160  */
161  uint16_t capacity;
162 
163  /**
164  * Number of entries used
165  */
166  uint16_t size;
167 
168  /**
169  * Sequence of entries
170  */
172 
173 } as_scan_bins;
174 
175 /**
176  * Sequence of predicate expressions to be applied to a scan.
177  *
178  * Entries can either be initialized on the stack or on the heap.
179  *
180  * Initialization should be performed via a scan object, using:
181  * - as_scan_predexp_init()
182  * - as_scan_predexp_inita()
183  */
184 typedef struct as_scan_predexp_s {
185 
186  /**
187  * @private
188  * If true, then as_scan_destroy() will free this instance.
189  */
190  bool _free;
191 
192  /**
193  * Number of entries allocated
194  */
195  uint16_t capacity;
196 
197  /**
198  * Number of entries used
199  */
200  uint16_t size;
201 
202  /**
203  * Sequence of entries
204  */
206 
208 
209 /**
210  * In order to execute a scan using the Scan API, an as_scan object
211  * must be initialized and populated.
212  *
213  * ## Initialization
214  *
215  * Before using an as_scan, it must be initialized via either:
216  * - as_scan_init()
217  * - as_scan_new()
218  *
219  * as_scan_init() should be used on a stack allocated as_scan. It will
220  * initialize the as_scan with the given namespace and set. On success,
221  * it will return a pointer to the initialized as_scan. Otherwise, NULL
222  * is returned.
223  *
224  * ~~~~~~~~~~{.c}
225  * as_scan scan;
226  * as_scan_init(&scan, "namespace", "set");
227  * ~~~~~~~~~~
228  *
229  * as_scan_new() should be used to allocate and initialize a heap allocated
230  * as_scan. It will allocate the as_scan, then initialized it with the
231  * given namespace and set. On success, it will return a pointer to the
232  * initialized as_scan. Otherwise, NULL is returned.
233  *
234  * ~~~~~~~~~~{.c}
235  * as_scan * scan = as_scan_new("namespace", "set");
236  * ~~~~~~~~~~
237  *
238  * ## Destruction
239  *
240  * When you are finished with the as_scan, you can destroy it and associated
241  * resources:
242  *
243  * ~~~~~~~~~~{.c}
244  * as_scan_destroy(scan);
245  * ~~~~~~~~~~
246  *
247  * ## Usage
248  *
249  * An initialized as_scan can be populated with additional fields.
250  *
251  * ### Selecting Bins
252  *
253  * as_scan_select() is used to specify the bins to be selected by the scan.
254  * If a scan specifies bins to be selected, then only those bins will be
255  * returned. If no bins are selected, then all bins will be returned.
256  *
257  * ~~~~~~~~~~{.c}
258  * as_scan_select(query, "bin1");
259  * as_scan_select(query, "bin2");
260  * ~~~~~~~~~~
261  *
262  * Before adding bins to select, the select structure must be initialized via
263  * either:
264  * - as_scan_select_inita() - Initializes the structure on the stack.
265  * - as_scan_select_init() - Initializes the structure on the heap.
266  *
267  * Both functions are given the number of bins to be selected.
268  *
269  * A complete example using as_scan_select_inita()
270  *
271  * ~~~~~~~~~~{.c}
272  * as_scan_select_inita(query, 2);
273  * as_scan_select(query, "bin1");
274  * as_scan_select(query, "bin2");
275  * ~~~~~~~~~~
276  *
277  * ### Returning only meta data
278  *
279  * A scan can return only record meta data, and exclude bins.
280  *
281  * ~~~~~~~~~~{.c}
282  * as_scan_set_nobins(scan, true);
283  * ~~~~~~~~~~
284  *
285  * ### Scan nodes in parallel
286  *
287  * A scan can be made to scan all the nodes in parallel
288  *
289  * ~~~~~~~~~~{.c}
290  * as_scan_set_concurrent(scan, true);
291  * ~~~~~~~~~~
292  *
293  * ### Scan a Percentage of Records
294  *
295  * A scan can define the percentage of record in the cluster to be scaned.
296  *
297  * ~~~~~~~~~~{.c}
298  * as_scan_set_percent(scan, 100);
299  * ~~~~~~~~~~
300  *
301  * ### Scan a Priority
302  *
303  * To set the priority of the scan, the set as_scan.priority.
304  *
305  * The priority of a scan can be defined as either:
306  * - `AS_SCAN_PRIORITY_AUTO`
307  * - `AS_SCAN_PRIORITY_LOW`
308  * - `AS_SCAN_PRIORITY_MEDIUM`
309  * - `AS_SCAN_PRIORITY_HIGH`
310  *
311  * ~~~~~~~~~~{.c}
312  * as_scan_set_priority(scan, AS_SCAN_PRIORITY_LOW);
313  * ~~~~~~~~~~
314  *
315  * ### Applying a UDF to each Record Scanned
316  *
317  * A UDF can be applied to each record scanned.
318  *
319  * To define the UDF for the scan, use as_scan_apply_each().
320  *
321  * ~~~~~~~~~~{.c}
322  * as_scan_apply_each(scan, "udf_module", "udf_function", arglist);
323  * ~~~~~~~~~~
324  *
325  * @ingroup client_objects
326  */
327 typedef struct as_scan_s {
328 
329  /**
330  * @private
331  * If true, then as_scan_destroy() will free this instance.
332  */
333  bool _free;
334 
335  /**
336  * Priority of scan.
337  *
338  * Default value is AS_SCAN_PRIORITY_DEFAULT.
339  */
341 
342  /**
343  * Percentage of the data to scan.
344  *
345  * Default value is AS_SCAN_PERCENT_DEFAULT.
346  */
347  uint8_t percent;
348 
349  /**
350  * Set to true if the scan should return only the metadata of the record.
351  *
352  * Default value is AS_SCAN_NOBINS_DEFAULT.
353  */
354  bool no_bins;
355 
356  /**
357  * Set to true if the scan should scan all the nodes in parallel
358  *
359  * Default value is AS_SCAN_CONCURRENT_DEFAULT.
360  */
362 
363  /**
364  * Set to true if the scan should deserialize list and map raw bytes.
365  * Set to false for backup programs that just need access to raw bytes.
366  *
367  * Default value is AS_SCAN_DESERIALIZE_DEFAULT.
368  */
370 
371  /**
372  * @memberof as_scan
373  * Namespace to be scanned.
374  *
375  * Should be initialized via either:
376  * - as_scan_init() - To initialize a stack allocated scan.
377  * - as_scan_new() - To heap allocate and initialize a scan.
378  *
379  */
381 
382  /**
383  * Set to be scanned.
384  *
385  * Should be initialized via either:
386  * - as_scan_init() - To initialize a stack allocated scan.
387  * - as_scan_new() - To heap allocate and initialize a scan.
388  *
389  */
391 
392  /**
393  * Name of bins to select.
394  *
395  * Use either of the following function to initialize:
396  * - as_scan_select_init() - To initialize on the heap.
397  * - as_scan_select_inita() - To initialize on the stack.
398  *
399  * Use as_scan_select() to populate.
400  */
402 
403  /**
404  * Predicate Expressions for filtering.
405  *
406  * Use either of the following function to initialize:
407  * - as_query_predexp_init() - To initialize on the heap.
408  * - as_query_predexp_inita() - To initialize on the stack.
409  *
410  * Use as_query_predexp() to populate.
411  */
413 
414  /**
415  * Apply the UDF for each record scanned on the server.
416  *
417  * Should be set via `as_scan_apply_each()`.
418  */
420 
421 } as_scan;
422 
423 /******************************************************************************
424  * INSTANCE FUNCTIONS
425  *****************************************************************************/
426 
427 /**
428  * Initializes a scan.
429  *
430  * ~~~~~~~~~~{.c}
431  * as_scan scan;
432  * as_scan_init(&scan, "test", "demo");
433  * ~~~~~~~~~~
434  *
435  * When you no longer require the scan, you should release the scan and
436  * related resources via `as_scan_destroy()`.
437  *
438  * @param scan The scan to initialize.
439  * @param ns The namespace to scan.
440  * @param set The set to scan.
441  *
442  * @returns On succes, the initialized scan. Otherwise NULL.
443  *
444  * @relates as_scan
445  * @ingroup as_scan_object
446  */
447 as_scan * as_scan_init(as_scan * scan, const as_namespace ns, const as_set set);
448 
449 /**
450  * Create and initializes a new scan on the heap.
451  *
452  * ~~~~~~~~~~{.c}
453  * as_scan * scan = as_scan_new("test","demo");
454  * ~~~~~~~~~~
455  *
456  * When you no longer require the scan, you should release the scan and
457  * related resources via `as_scan_destroy()`.
458  *
459  * @param ns The namespace to scan.
460  * @param set The set to scan.
461  *
462  * @returns On success, a new scan. Otherwise NULL.
463  *
464  * @relates as_scan
465  * @ingroup as_scan_object
466  */
467 as_scan * as_scan_new(const as_namespace ns, const as_set set);
468 
469 /**
470  * Releases all resources allocated to the scan.
471  *
472  * ~~~~~~~~~~{.c}
473  * as_scan_destroy(scan);
474  * ~~~~~~~~~~
475  *
476  * @relates as_scan
477  * @ingroup as_scan_object
478  */
479 void as_scan_destroy(as_scan * scan);
480 
481 /******************************************************************************
482  * SELECT FUNCTIONS
483  *****************************************************************************/
484 
485 /**
486  * Initializes `as_scan.select` with a capacity of `n` using `alloca`
487  *
488  * For heap allocation, use `as_scan_select_init()`.
489  *
490  * ~~~~~~~~~~{.c}
491  * as_scan_select_inita(&scan, 2);
492  * as_scan_select(&scan, "bin1");
493  * as_scan_select(&scan, "bin2");
494  * ~~~~~~~~~~
495  *
496  * @param __scan The scan to initialize.
497  * @param __n The number of bins to allocate.
498  *
499  * @ingroup as_scan_object
500  */
501 #define as_scan_select_inita(__scan, __n) \
502  do { \
503  if ( (__scan) != NULL && (__scan)->select.entries == NULL ) {\
504  (__scan)->select.entries = (as_bin_name*) alloca(sizeof(as_bin_name) * (__n));\
505  if ( (__scan)->select.entries ) { \
506  (__scan)->select._free = false;\
507  (__scan)->select.capacity = (__n);\
508  (__scan)->select.size = 0;\
509  }\
510  } \
511  } while(0)
512 
513 /**
514  * Initializes `as_scan.select` with a capacity of `n` using `malloc()`.
515  *
516  * For stack allocation, use `as_scan_select_inita()`.
517  *
518  * ~~~~~~~~~~{.c}
519  * as_scan_select_init(&scan, 2);
520  * as_scan_select(&scan, "bin1");
521  * as_scan_select(&scan, "bin2");
522  * ~~~~~~~~~~
523  *
524  * @param scan The scan to initialize.
525  * @param n The number of bins to allocate.
526  *
527  * @return On success, the initialized. Otherwise an error occurred.
528  *
529  * @relates as_scan
530  * @ingroup as_scan_object
531  */
532 bool as_scan_select_init(as_scan * scan, uint16_t n);
533 
534 /**
535  * Select bins to be projected from matching records.
536  *
537  * You have to ensure as_scan.select has sufficient capacity, prior to
538  * adding a bin. If capacity is insufficient then false is returned.
539  *
540  * ~~~~~~~~~~{.c}
541  * as_scan_select_init(&scan, 2);
542  * as_scan_select(&scan, "bin1");
543  * as_scan_select(&scan, "bin2");
544  * ~~~~~~~~~~
545  *
546  * @param scan The scan to modify.
547  * @param bin The name of the bin to select.
548  *
549  * @return On success, true. Otherwise an error occurred.
550  *
551  * @relates as_scan
552  * @ingroup as_scan_object
553  */
554 bool as_scan_select(as_scan * scan, const char * bin);
555 
556 
557 /******************************************************************************
558  * PREDEXP FUNCTIONS
559  *****************************************************************************/
560 
561 /**
562  * Initializes `as_scan.predexp` with a capacity of `n` using `alloca`
563  *
564  * For heap allocation, use `as_scan_predexp_init()`.
565  *
566  * ~~~~~~~~~~{.c}
567  * as_scan_predexp_inita(&scan, 3);
568  * as_scan_predexp_add(&scan, as_predexp_integer_value(90));
569  * as_scan_predexp_add(&scan, as_predexp_integer_bin("bin1"));
570  * as_scan_predexp_add(&scan, as_predexp_integer_greatereq());
571  * ~~~~~~~~~~
572  *
573  * @param __scan The scan to initialize.
574  * @param __n The number of predicate expression slots to allocate.
575  *
576  * @relates as_scan
577  * @ingroup as_scan_object
578  */
579 #define as_scan_predexp_inita(__scan, __n) \
580  if ( (__scan) != NULL && (__scan)->predexp.entries == NULL ) { \
581  (__scan)->predexp.entries = \
582  (as_predexp_base **) \
583  alloca(__n * sizeof(as_predexp_base *)); \
584  if ( (__scan)->predexp.entries ) { \
585  (__scan)->predexp._free = false; \
586  (__scan)->predexp.capacity = __n; \
587  (__scan)->predexp.size = 0; \
588  } \
589  }
590 
591 /**
592  * Initializes `as_scan.predexp` with a capacity of `n` using `malloc()`.
593  *
594  * For stack allocation, use `as_scan_predexp_inita()`.
595  *
596  * ~~~~~~~~~~{.c}
597  * as_scan_predexp_init(&scan, 3);
598  * as_scan_predexp_add(&scan, as_predexp_integer_value(90));
599  * as_scan_predexp_add(&scan, as_predexp_integer_bin("bin1"));
600  * as_scan_predexp_add(&scan, as_predexp_integer_greatereq());
601  * ~~~~~~~~~~
602  *
603  * @param scan The scan to initialize.
604  * @param n The number of predicate expression slots to allocate.
605  *
606  * @return On success, the initialized. Otherwise an error occurred.
607  *
608  * @relates as_scan
609  * @ingroup as_scan_object
610  */
611 bool as_scan_predexp_init(as_scan * scan, uint16_t n);
612 
613 /**
614  * Adds predicate expressions to a scan.
615  *
616  * You have to ensure as_scan.predexp has sufficient capacity, prior to
617  * adding a predexp. If capacity is sufficient then false is returned.
618  *
619  * ~~~~~~~~~~{.c}
620  * as_scan_predexp_inita(&scan, 3);
621  * as_scan_predexp_add(&scan, as_predexp_integer_value(90));
622  * as_scan_predexp_add(&scan, as_predexp_integer_bin("bin1"));
623  * as_scan_predexp_add(&scan, as_predexp_integer_greatereq());
624  * ~~~~~~~~~~
625  *
626  * @param scan The scan to modify.
627  * @param predexp Pointer to a constructed predicate expression.
628  *
629  * @return On success, true. Otherwise an error occurred.
630  *
631  * @relates as_scan
632  * @ingroup as_scan_object
633  */
634 bool as_scan_predexp_add(as_scan * scan, as_predexp_base * predexp);
635 
636 /******************************************************************************
637  * MODIFIER FUNCTIONS
638  *****************************************************************************/
639 
640 /**
641  * The percentage of data to scan.
642  *
643  * ~~~~~~~~~~{.c}
644  * as_scan_set_percent(&q, 100);
645  * ~~~~~~~~~~
646  *
647  * @param scan The scan to set the priority on.
648  * @param percent The percent to scan.
649  *
650  * @return On success, true. Otherwise an error occurred.
651  *
652  * @relates as_scan
653  * @ingroup as_scan_object
654  */
655 bool as_scan_set_percent(as_scan * scan, uint8_t percent);
656 
657 /**
658  * Set the priority for the scan.
659  *
660  * ~~~~~~~~~~{.c}
661  * as_scan_set_priority(&q, AS_SCAN_PRIORITY_LOW);
662  * ~~~~~~~~~~
663  *
664  * @param scan The scan to set the priority on.
665  * @param priority The priority for the scan.
666  *
667  * @return On success, true. Otherwise an error occurred.
668  *
669  * @relates as_scan
670  * @ingroup as_scan_object
671  */
672 bool as_scan_set_priority(as_scan * scan, as_scan_priority priority);
673 
674 /**
675  * Do not return bins. This will only return the metadata for the records.
676  *
677  * ~~~~~~~~~~{.c}
678  * as_scan_set_nobins(&q, true);
679  * ~~~~~~~~~~
680  *
681  * @param scan The scan to set the priority on.
682  * @param nobins If true, then do not return bins.
683  *
684  * @return On success, true. Otherwise an error occurred.
685  *
686  * @relates as_scan
687  * @ingroup as_scan_object
688  */
689 bool as_scan_set_nobins(as_scan * scan, bool nobins);
690 
691 /**
692  * Scan all the nodes in prallel
693  *
694  * ~~~~~~~~~~{.c}
695  * as_scan_set_concurrent(&q, true);
696  * ~~~~~~~~~~
697  *
698  * @param scan The scan to set the concurrency on.
699  * @param concurrent If true, scan all the nodes in parallel
700  *
701  * @return On success, true. Otherwise an error occurred.
702  */
703 bool as_scan_set_concurrent(as_scan * scan, bool concurrent);
704 
705 /**
706  * Apply a UDF to each record scanned on the server.
707  *
708  * ~~~~~~~~~~{.c}
709  * as_arraylist arglist;
710  * as_arraylist_init(&arglist, 2, 0);
711  * as_arraylist_append_int64(&arglist, 1);
712  * as_arraylist_append_int64(&arglist, 2);
713  *
714  * as_scan_apply_each(&q, "module", "func", (as_list *) &arglist);
715  *
716  * as_arraylist_destroy(&arglist);
717  * ~~~~~~~~~~
718  *
719  * @param scan The scan to apply the UDF to.
720  * @param module The module containing the function to execute.
721  * @param function The function to execute.
722  * @param arglist The arguments for the function.
723  *
724  * @return On success, true. Otherwise an error occurred.
725  *
726  * @relates as_scan
727  * @ingroup as_scan_object
728  */
729 bool as_scan_apply_each(as_scan * scan, const char * module, const char * function, as_list * arglist);
730 
731 #ifdef __cplusplus
732 } // end extern "C"
733 #endif