| 1 | /* |
| 2 | * cdt.h |
| 3 | * |
| 4 | * Copyright (C) 2015-2018 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 | #pragma once |
| 24 | |
| 25 | #include <stdarg.h> |
| 26 | #include <stddef.h> |
| 27 | #include <stdint.h> |
| 28 | |
| 29 | #include "aerospike/as_msgpack.h" |
| 30 | |
| 31 | #include "base/datamodel.h" |
| 32 | #include "base/proto.h" |
| 33 | |
| 34 | #include "dynbuf.h" |
| 35 | |
| 36 | |
| 37 | //========================================================== |
| 38 | // Typedefs & constants. |
| 39 | // |
| 40 | |
| 41 | //#define CDT_DEBUG_VERIFY |
| 42 | |
| 43 | #define CDT_MAX_PACKED_INT_SZ (sizeof(uint64_t) + 1) |
| 44 | #define CDT_MAX_STACK_OBJ_SZ (1024 * 1024) |
| 45 | #define CDT_MAX_PARAM_LIST_COUNT (1024 * 1024) |
| 46 | |
| 47 | typedef struct rollback_alloc_s { |
| 48 | cf_ll_buf *ll_buf; |
| 49 | size_t malloc_list_sz; |
| 50 | size_t malloc_list_cap; |
| 51 | bool malloc_ns; |
| 52 | void *malloc_list[]; |
| 53 | } rollback_alloc; |
| 54 | |
| 55 | #define define_rollback_alloc(__name, __alloc_buf, __rollback_size, __malloc_ns) \ |
| 56 | uint8_t __name ## __mem[sizeof(rollback_alloc) + sizeof(void *) * (__alloc_buf ? 0 : __rollback_size)]; \ |
| 57 | rollback_alloc * const __name = (rollback_alloc *)__name ## __mem; \ |
| 58 | __name->ll_buf = __alloc_buf; \ |
| 59 | __name->malloc_list_sz = 0; \ |
| 60 | __name->malloc_list_cap = (__alloc_buf ? 0 : __rollback_size); \ |
| 61 | __name->malloc_ns = __malloc_ns; |
| 62 | |
| 63 | typedef struct cdt_process_state_s { |
| 64 | as_cdt_optype type; |
| 65 | as_unpacker pk; |
| 66 | uint32_t ele_count; |
| 67 | } cdt_process_state; |
| 68 | |
| 69 | typedef struct cdt_payload_s { |
| 70 | const uint8_t *ptr; |
| 71 | uint32_t sz; |
| 72 | } cdt_payload; |
| 73 | |
| 74 | typedef struct cdt_result_data_s { |
| 75 | as_bin *result; |
| 76 | rollback_alloc *alloc; |
| 77 | result_type_t type; |
| 78 | as_cdt_op_flags flags; |
| 79 | bool is_multi; |
| 80 | } cdt_result_data; |
| 81 | |
| 82 | typedef struct cdt_mem_s { |
| 83 | uint8_t type; |
| 84 | uint32_t sz; |
| 85 | uint8_t data[]; |
| 86 | } __attribute__ ((__packed__)) cdt_mem; |
| 87 | |
| 88 | typedef struct { |
| 89 | uint32_t data_offset; // 0 starts at cdt_mem->data[0] |
| 90 | uint32_t data_sz; |
| 91 | uint32_t idx; |
| 92 | uint8_t type; |
| 93 | uint8_t *idx_mem; |
| 94 | } cdt_ctx_list_stack_entry; |
| 95 | |
| 96 | typedef struct cdt_context_s { |
| 97 | as_bin *b; |
| 98 | as_particle *orig; |
| 99 | rollback_alloc *alloc_buf; |
| 100 | uint32_t data_offset; // 0 starts at cdt_mem->data[0] |
| 101 | uint32_t data_sz; // 0 means no sub-context |
| 102 | |
| 103 | uint32_t stack_idx; |
| 104 | uint32_t stack_cap; |
| 105 | cdt_ctx_list_stack_entry stack[2]; |
| 106 | cdt_ctx_list_stack_entry *pstack; |
| 107 | |
| 108 | uint32_t top_content_sz; |
| 109 | uint32_t top_content_off; // 0 means no top level indexes |
| 110 | uint32_t top_ele_count; |
| 111 | |
| 112 | int32_t delta_off; |
| 113 | int32_t delta_sz; |
| 114 | } cdt_context; |
| 115 | |
| 116 | typedef bool (*cdt_subcontext_fn)(cdt_context *ctx, as_unpacker *val); |
| 117 | |
| 118 | typedef struct cdt_op_mem_s { |
| 119 | cdt_context ctx; |
| 120 | cdt_result_data result; |
| 121 | rollback_alloc *alloc_idx; |
| 122 | int ret_code; |
| 123 | } cdt_op_mem; |
| 124 | |
| 125 | typedef struct cdt_container_builder_s { |
| 126 | as_particle *particle; |
| 127 | uint8_t *write_ptr; |
| 128 | uint32_t *sz; |
| 129 | uint32_t ele_count; |
| 130 | } cdt_container_builder; |
| 131 | |
| 132 | typedef struct cdt_op_table_entry_s { |
| 133 | uint32_t count; |
| 134 | uint32_t opt_args; |
| 135 | const char *name; |
| 136 | const as_cdt_paramtype *args; |
| 137 | } cdt_op_table_entry; |
| 138 | |
| 139 | typedef struct cdt_calc_delta_s { |
| 140 | int64_t incr_int; |
| 141 | double incr_double; |
| 142 | |
| 143 | as_val_t type; |
| 144 | |
| 145 | int64_t value_int; |
| 146 | double value_double; |
| 147 | } cdt_calc_delta; |
| 148 | |
| 149 | typedef struct msgpacked_index_s { |
| 150 | uint8_t *ptr; |
| 151 | uint32_t ele_sz; |
| 152 | uint32_t ele_count; |
| 153 | } msgpacked_index; |
| 154 | |
| 155 | typedef struct offset_index_s { |
| 156 | msgpacked_index _; |
| 157 | |
| 158 | const uint8_t *contents; |
| 159 | uint32_t content_sz; |
| 160 | bool is_partial; |
| 161 | } offset_index; |
| 162 | |
| 163 | // Value order index. |
| 164 | typedef struct order_index_s { |
| 165 | msgpacked_index _; |
| 166 | uint32_t max_idx; |
| 167 | } order_index; |
| 168 | |
| 169 | typedef struct order_index_find_s { |
| 170 | uint32_t start; |
| 171 | uint32_t count; |
| 172 | uint32_t target; |
| 173 | uint32_t result; |
| 174 | bool found; |
| 175 | } order_index_find; |
| 176 | |
| 177 | typedef msgpack_compare_t (*order_heap_compare_fn)(const void *ptr, uint32_t index0, uint32_t index1); |
| 178 | |
| 179 | // Value order heap. |
| 180 | typedef struct order_heap_s { |
| 181 | order_index _; |
| 182 | const void *userdata; |
| 183 | order_heap_compare_fn cmp_fn; |
| 184 | msgpack_compare_t cmp; |
| 185 | uint32_t filled; |
| 186 | } order_heap; |
| 187 | |
| 188 | typedef struct cdt_packed_op_s { |
| 189 | // Input. |
| 190 | const uint8_t *packed; |
| 191 | uint32_t packed_sz; |
| 192 | |
| 193 | // Parsed. |
| 194 | uint32_t ele_count; |
| 195 | const uint8_t *contents; |
| 196 | uint32_t content_sz; |
| 197 | |
| 198 | // Result. |
| 199 | uint32_t new_ele_count; |
| 200 | } cdt_packed_op; |
| 201 | |
| 202 | struct order_index_adjust_s; |
| 203 | typedef uint32_t (*order_index_adjust_func)(const struct order_index_adjust_s *via, uint32_t src); |
| 204 | |
| 205 | typedef struct order_index_adjust_s { |
| 206 | order_index_adjust_func f; |
| 207 | uint32_t upper; |
| 208 | uint32_t lower; |
| 209 | int32_t delta; |
| 210 | } order_index_adjust; |
| 211 | |
| 212 | typedef enum { |
| 213 | CDT_FIND_ITEMS_IDXS_FOR_LIST_VALUE, |
| 214 | CDT_FIND_ITEMS_IDXS_FOR_MAP_KEY, |
| 215 | CDT_FIND_ITEMS_IDXS_FOR_MAP_VALUE |
| 216 | } cdt_find_items_idxs_type; |
| 217 | |
| 218 | #define define_offset_index(__name, __contents, __content_sz, __ele_count, __alloc) \ |
| 219 | offset_index __name; \ |
| 220 | offset_index_init(&__name, NULL, __ele_count, __contents, __content_sz); \ |
| 221 | uint8_t __name ## __vlatemp[1 + offset_index_vla_sz(&__name)]; \ |
| 222 | offset_index_alloc_temp(&__name, __name ## __vlatemp, __alloc) |
| 223 | |
| 224 | // NULL if !__cond |
| 225 | #define definep_cond_order_index2(__name, __max_idx, __alloc_count, __cond, __alloc) \ |
| 226 | uint8_t __name ## __vlatemp[(__cond) ? sizeof(order_index) + cdt_vla_sz(order_index_calc_size(__max_idx, __alloc_count)) : 1]; \ |
| 227 | order_index *__name = NULL; \ |
| 228 | if (__cond) { \ |
| 229 | __name = (order_index *)__name ## __vlatemp; \ |
| 230 | order_index_init2_temp(__name, __name ## __vlatemp + sizeof(order_index), __alloc, __max_idx, __alloc_count); \ |
| 231 | } |
| 232 | |
| 233 | #define define_order_index(__name, __ele_count, __alloc) \ |
| 234 | order_index __name; \ |
| 235 | uint8_t __name ## __vlatemp[1 + cdt_vla_sz(order_index_calc_size(__ele_count, __ele_count))]; \ |
| 236 | order_index_init2_temp(&__name, __name ## __vlatemp, __alloc, __ele_count, __ele_count) |
| 237 | |
| 238 | #define define_order_index2(__name, __max_idx, __alloc_count, __alloc) \ |
| 239 | order_index __name; \ |
| 240 | uint8_t __name ## __vlatemp[1 + cdt_vla_sz(order_index_calc_size(__max_idx, __alloc_count))]; \ |
| 241 | order_index_init2_temp(&__name, __name ## __vlatemp, __alloc, __max_idx, __alloc_count) |
| 242 | |
| 243 | #define define_int_list_builder(__name, __alloc, __count) \ |
| 244 | cdt_container_builder __name; \ |
| 245 | cdt_int_list_builder_start(&__name, __alloc, __count) |
| 246 | |
| 247 | #define define_cdt_idx_mask(__name, __ele_count, __alloc) \ |
| 248 | uint64_t __name ## __vla[cdt_idx_vla_mask_count(__ele_count)]; \ |
| 249 | uint64_t *__name = __name ## __vla; \ |
| 250 | cdt_idx_mask_init_temp(&__name, __ele_count, __alloc) |
| 251 | |
| 252 | #define define_cond_cdt_idx_mask(__name, __ele_count, __cond, __alloc) \ |
| 253 | uint64_t __name ## __vla[__cond ? cdt_idx_vla_mask_count(__ele_count) : 1]; \ |
| 254 | uint64_t *__name = __name ## __vla; \ |
| 255 | if (__cond) { \ |
| 256 | cdt_idx_mask_init_temp(&__name, __ele_count, __alloc); \ |
| 257 | } |
| 258 | |
| 259 | #define define_build_order_heap_by_range(__name, __idx, __count, __ele_count, __udata, __cmp_fn, __success, __alloc) \ |
| 260 | order_heap __name; \ |
| 261 | uint8_t __name ## __order_heap_mem__[1 + cdt_vla_sz(order_index_calc_size(__ele_count, __ele_count))]; \ |
| 262 | bool __success = order_heap_init_build_by_range_temp(&__name, __name ## __order_heap_mem__, __alloc, __idx, __count, __ele_count, __cmp_fn, __udata) |
| 263 | |
| 264 | #define VA_NARGS_SEQ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 |
| 265 | #define (_9, _8, _7, _6, _5, _4, _3, _2, _1, _0, N, ...) N |
| 266 | #define VA_NARGS_SEQ2N(...) VA_NARGS_EXTRACT_N(__VA_ARGS__) |
| 267 | #define VA_NARGS(...) VA_NARGS_SEQ2N(_, ##__VA_ARGS__, VA_NARGS_SEQ) |
| 268 | |
| 269 | // Get around needing to pass last named arg to va_start(). |
| 270 | #define CDT_OP_TABLE_GET_PARAMS(state, ...) cdt_process_state_get_params(state, VA_NARGS(__VA_ARGS__), __VA_ARGS__) |
| 271 | |
| 272 | static const uint8_t msgpack_nil[1] = {0xC0}; |
| 273 | |
| 274 | |
| 275 | //========================================================== |
| 276 | // Function declarations. |
| 277 | // |
| 278 | |
| 279 | bool calc_index_count(int64_t in_index, uint64_t in_count, uint32_t ele_count, uint32_t *out_index, uint32_t *out_count, bool is_multi); |
| 280 | void calc_rel_index_count(int64_t in_index, uint64_t in_count, uint32_t rel_index, int64_t *out_index, uint64_t *out_count); |
| 281 | |
| 282 | bool cdt_check_storage_list_contents(const uint8_t *buf, uint32_t sz, uint32_t count); |
| 283 | |
| 284 | // cdt_result_data |
| 285 | bool result_data_set_not_found(cdt_result_data *rd, int64_t index); |
| 286 | void result_data_set_list_int2x(cdt_result_data *rd, int64_t i1, int64_t i2); |
| 287 | int result_data_set_index_rank_count(cdt_result_data *rd, uint32_t start, uint32_t count, uint32_t ele_count); |
| 288 | int result_data_set_range(cdt_result_data *rd, uint32_t start, uint32_t count, uint32_t ele_count); |
| 289 | void result_data_set_by_irc(cdt_result_data *rd, const order_index *ordidx, const order_index *idx_map, uint32_t total_count); |
| 290 | void result_data_set_by_itemlist_irc(cdt_result_data *rd, const order_index *items_ord, order_index *ranks, uint32_t total_count); |
| 291 | void result_data_set_int_list_by_mask(cdt_result_data *rd, const uint64_t *mask, uint32_t count, uint32_t ele_count); |
| 292 | |
| 293 | // as_bin |
| 294 | void as_bin_set_int(as_bin *b, int64_t value); |
| 295 | void as_bin_set_double(as_bin *b, double value); |
| 296 | void as_bin_set_unordered_empty_list(as_bin *b, rollback_alloc *alloc_buf); |
| 297 | void as_bin_set_empty_packed_map(as_bin *b, rollback_alloc *alloc_buf, uint8_t flags); |
| 298 | |
| 299 | // cdt_delta_value |
| 300 | bool cdt_calc_delta_init(cdt_calc_delta *cdv, const cdt_payload *delta_value, bool is_decrement); |
| 301 | bool cdt_calc_delta_add(cdt_calc_delta *cdv, as_unpacker *pk_value); |
| 302 | void cdt_calc_delta_pack_and_result(cdt_calc_delta *cdv, cdt_payload *value, as_bin *result); |
| 303 | |
| 304 | // cdt_payload |
| 305 | bool cdt_payload_is_int(const cdt_payload *payload); |
| 306 | int64_t cdt_payload_get_int64(const cdt_payload *payload); |
| 307 | void cdt_payload_pack_int(cdt_payload *packed, int64_t value); |
| 308 | void cdt_payload_pack_double(cdt_payload *packed, double value); |
| 309 | |
| 310 | // cdt_process_state |
| 311 | bool cdt_process_state_init(cdt_process_state *cdt_state, const as_msg_op *op); |
| 312 | bool cdt_process_state_get_params(cdt_process_state *state, size_t n, ...); |
| 313 | const char *cdt_process_state_get_op_name(const cdt_process_state *state); |
| 314 | |
| 315 | // cdt_process_state_packed_list |
| 316 | bool cdt_process_state_packed_list_modify_optype(cdt_process_state *state, cdt_op_mem *com); |
| 317 | bool cdt_process_state_packed_list_read_optype(cdt_process_state *state, cdt_op_mem *com); |
| 318 | |
| 319 | void cdt_container_builder_add(cdt_container_builder *builder, const uint8_t *buf, uint32_t sz); |
| 320 | void cdt_container_builder_add_n(cdt_container_builder *builder, const uint8_t *buf, uint32_t count, uint32_t sz); |
| 321 | void cdt_container_builder_add_int64(cdt_container_builder *builder, int64_t value); |
| 322 | void cdt_container_builder_add_int_range(cdt_container_builder *builder, uint32_t start, uint32_t count, uint32_t ele_count, bool reverse); |
| 323 | void cdt_container_builder_set_result(cdt_container_builder *builder, cdt_result_data *result); |
| 324 | |
| 325 | void cdt_list_builder_start(cdt_container_builder *builder, rollback_alloc *alloc_buf, uint32_t ele_count, uint32_t max_sz); |
| 326 | void cdt_map_builder_start(cdt_container_builder *builder, rollback_alloc *alloc_buf, uint32_t ele_count, uint32_t content_max_sz, uint8_t flags); |
| 327 | |
| 328 | // cdt_process_state_packed_map |
| 329 | bool cdt_process_state_packed_map_modify_optype(cdt_process_state *state, cdt_op_mem *com); |
| 330 | bool cdt_process_state_packed_map_read_optype(cdt_process_state *state, cdt_op_mem *com); |
| 331 | |
| 332 | // cdt_process_state_context_eval |
| 333 | bool cdt_process_state_context_eval(cdt_process_state *state, cdt_op_mem *com); |
| 334 | |
| 335 | // rollback_alloc |
| 336 | void rollback_alloc_push(rollback_alloc *packed_alloc, void *ptr); |
| 337 | uint8_t *rollback_alloc_reserve(rollback_alloc *alloc_buf, size_t sz); |
| 338 | void rollback_alloc_rollback(rollback_alloc *alloc_buf); |
| 339 | bool rollback_alloc_from_msgpack(rollback_alloc *alloc_buf, as_bin *b, const cdt_payload *seg); |
| 340 | |
| 341 | // msgpacked_index |
| 342 | void msgpacked_index_set(msgpacked_index *idxs, uint32_t index, uint32_t value); |
| 343 | void msgpacked_index_incr(msgpacked_index *idxs, uint32_t index); |
| 344 | void msgpacked_index_set_ptr(msgpacked_index *idxs, uint8_t *ptr); |
| 345 | void *msgpacked_index_get_mem(const msgpacked_index *idxs, uint32_t index); |
| 346 | uint32_t msgpacked_index_size(const msgpacked_index *idxs); |
| 347 | uint32_t msgpacked_index_ptr2value(const msgpacked_index *idxs, const void *ptr); |
| 348 | uint32_t msgpacked_index_get(const msgpacked_index *idxs, uint32_t index); |
| 349 | void msgpacked_index_print(const msgpacked_index *idxs, const char *name); |
| 350 | |
| 351 | // offset_index |
| 352 | void offset_index_init(offset_index *offidx, uint8_t *idx_mem_ptr, uint32_t ele_count, const uint8_t *contents, uint32_t content_sz); |
| 353 | void offset_index_set(offset_index *offidx, uint32_t index, uint32_t value); |
| 354 | bool offset_index_set_next(offset_index *offidx, uint32_t index, uint32_t value); |
| 355 | void offset_index_set_filled(offset_index *offidx, uint32_t ele_filled); |
| 356 | void offset_index_set_ptr(offset_index *offidx, uint8_t *idx_mem, const uint8_t *packed_mem); |
| 357 | void offset_index_copy(offset_index *dest, const offset_index *src, uint32_t d_start, uint32_t s_start, uint32_t count, int delta); |
| 358 | void offset_index_move_ele(offset_index *dest, const offset_index *src, uint32_t ele_idx, uint32_t to_idx); |
| 359 | void offset_index_append_size(offset_index *offidx, uint32_t delta); |
| 360 | |
| 361 | bool offset_index_find_items(offset_index *full_offidx, cdt_find_items_idxs_type find_type, as_unpacker *items_pk, order_index *items_ordidx_r, bool inverted, uint64_t *rm_mask, uint32_t *rm_count_r, order_index *rm_ranks_r, rollback_alloc *alloc); |
| 362 | |
| 363 | void *offset_index_get_mem(const offset_index *offidx, uint32_t index); |
| 364 | uint32_t offset_index_size(const offset_index *offidx); |
| 365 | bool offset_index_is_null(const offset_index *offidx); |
| 366 | bool offset_index_is_valid(const offset_index *offidx); |
| 367 | bool offset_index_is_full(const offset_index *offidx); |
| 368 | uint32_t offset_index_get_const(const offset_index *offidx, uint32_t idx); |
| 369 | uint32_t offset_index_get_delta_const(const offset_index *offidx, uint32_t index); |
| 370 | uint32_t offset_index_get_filled(const offset_index *offidx); |
| 371 | |
| 372 | bool offset_index_check_order_and_fill(offset_index *offidx, bool pairs); |
| 373 | |
| 374 | uint32_t offset_index_vla_sz(const offset_index *offidx); |
| 375 | void offset_index_alloc_temp(offset_index *offidx, uint8_t *mem_temp, rollback_alloc *alloc); |
| 376 | |
| 377 | void offset_index_print(const offset_index *offidx, const char *name); |
| 378 | void offset_index_delta_print(const offset_index *offidx, const char *name); |
| 379 | |
| 380 | // order_index |
| 381 | void order_index_init(order_index *ordidx, uint8_t *ptr, uint32_t ele_count); |
| 382 | void order_index_init2(order_index *ordidx, uint8_t *ptr, uint32_t max_idx, uint32_t ele_count); |
| 383 | void order_index_init2_temp(order_index *ordidx, uint8_t *mem_temp, rollback_alloc *alloc_idx, uint32_t max_idx, uint32_t ele_count); |
| 384 | void order_index_init_ref(order_index *dst, const order_index *src, uint32_t start, uint32_t count); |
| 385 | void order_index_set(order_index *ordidx, uint32_t index, uint32_t value); |
| 386 | void order_index_set_ptr(order_index *ordidx, uint8_t *ptr); |
| 387 | void order_index_incr(order_index *ordidx, uint32_t index); |
| 388 | void order_index_clear(order_index *ordidx); |
| 389 | bool order_index_sorted_mark_dup_eles(order_index *ordidx, const offset_index *full_offidx, uint32_t *count_r, uint32_t *sz_r); |
| 390 | |
| 391 | uint32_t order_index_size(const order_index *ordidx); |
| 392 | bool order_index_is_null(const order_index *ordidx); |
| 393 | bool order_index_is_valid(const order_index *ordidx); |
| 394 | bool order_index_is_filled(const order_index *ordidx); |
| 395 | |
| 396 | void *order_index_get_mem(const order_index *ordidx, uint32_t index); |
| 397 | uint32_t order_index_ptr2value(const order_index *ordidx, const void *ptr); |
| 398 | uint32_t order_index_get(const order_index *ordidx, uint32_t index); |
| 399 | |
| 400 | void order_index_find_rank_by_value(const order_index *ordidx, const cdt_payload *value, const offset_index *full_offidx, order_index_find *find, bool skip_key); |
| 401 | |
| 402 | uint32_t order_index_get_ele_size(const order_index *ordidx, uint32_t count, const offset_index *full_offidx); |
| 403 | uint8_t *order_index_write_eles(const order_index *ordidx, uint32_t count, const offset_index *full_offidx, uint8_t *ptr, bool invert); |
| 404 | |
| 405 | uint32_t order_index_adjust_value(const order_index_adjust *via, uint32_t src); |
| 406 | void order_index_copy(order_index *dest, const order_index *src, uint32_t d_start, uint32_t s_start, uint32_t count, const order_index_adjust *adjust); |
| 407 | size_t order_index_calc_size(uint32_t max_idx, uint32_t ele_count); |
| 408 | |
| 409 | void order_index_print(const order_index *ordidx, const char *name); |
| 410 | |
| 411 | // order_heap |
| 412 | bool order_heap_init_build_by_range_temp(order_heap *heap, uint8_t *heap_mem, rollback_alloc *alloc_idx, uint32_t idx, uint32_t count, uint32_t ele_count, order_heap_compare_fn cmp_fn, const void *udata); |
| 413 | void order_heap_swap(order_heap *heap, uint32_t index1, uint32_t index2); |
| 414 | bool order_heap_remove_top(order_heap *heap); |
| 415 | bool order_heap_replace_top(order_heap *heap, uint32_t value); |
| 416 | bool order_heap_heapify(order_heap *heap, uint32_t index); |
| 417 | bool order_heap_build(order_heap *heap, bool init); |
| 418 | bool order_heap_order_at_end(order_heap *heap, uint32_t count); |
| 419 | void order_heap_reverse_end(order_heap *heap, uint32_t count); |
| 420 | |
| 421 | void order_heap_print(const order_heap *heap); |
| 422 | |
| 423 | // cdt_idx_mask |
| 424 | void cdt_idx_mask_init_temp(uint64_t **mask, uint32_t ele_count, rollback_alloc *alloc); |
| 425 | void cdt_idx_mask_set(uint64_t *mask, uint32_t idx); |
| 426 | void cdt_idx_mask_set_by_ordidx(uint64_t *mask, const order_index *ordidx, uint32_t start, uint32_t count, bool inverted); |
| 427 | void cdt_idx_mask_set_by_irc(uint64_t *mask, const order_index *rankcount, const order_index *idx_map, bool inverted); |
| 428 | void cdt_idx_mask_invert(uint64_t *mask, uint32_t ele_count); |
| 429 | |
| 430 | uint64_t cdt_idx_mask_get(const uint64_t *mask, uint32_t idx); |
| 431 | size_t cdt_idx_mask_bit_count(const uint64_t *mask, uint32_t ele_count); |
| 432 | |
| 433 | bool cdt_idx_mask_is_set(const uint64_t *mask, uint32_t idx); |
| 434 | |
| 435 | uint32_t cdt_idx_mask_find(const uint64_t *mask, uint32_t start, uint32_t end, bool is_find0); |
| 436 | uint8_t *cdt_idx_mask_write_eles(const uint64_t *mask, uint32_t count, const offset_index *full_offidx, uint8_t *ptr, bool invert); |
| 437 | uint32_t cdt_idx_mask_get_content_sz(const uint64_t *mask, uint32_t count, const offset_index *full_offidx); |
| 438 | |
| 439 | void cdt_idx_mask_print(const uint64_t *mask, uint32_t ele_count, const char *name); |
| 440 | |
| 441 | // list |
| 442 | bool list_full_offset_index_fill_all(offset_index *offidx); |
| 443 | bool list_order_index_sort(order_index *ordidx, const offset_index *full_offidx, as_cdt_sort_flags flags); |
| 444 | |
| 445 | bool list_param_parse(const cdt_payload *items, as_unpacker *pk, uint32_t *count_r); |
| 446 | |
| 447 | bool list_subcontext_by_index(cdt_context *ctx, as_unpacker *val); |
| 448 | bool list_subcontext_by_rank(cdt_context *ctx, as_unpacker *val); |
| 449 | bool list_subcontext_by_key(cdt_context *ctx, as_unpacker *val); |
| 450 | bool list_subcontext_by_value(cdt_context *ctx, as_unpacker *val); |
| 451 | |
| 452 | void cdt_context_unwind_list(cdt_context *ctx, cdt_ctx_list_stack_entry *p); |
| 453 | |
| 454 | // map |
| 455 | bool map_subcontext_by_index(cdt_context *ctx, as_unpacker *val); |
| 456 | bool map_subcontext_by_rank(cdt_context *ctx, as_unpacker *val); |
| 457 | bool map_subcontext_by_key(cdt_context *ctx, as_unpacker *val); |
| 458 | bool map_subcontext_by_value(cdt_context *ctx, as_unpacker *val); |
| 459 | |
| 460 | void cdt_context_unwind_map(cdt_context *ctx, cdt_ctx_list_stack_entry *p); |
| 461 | |
| 462 | // cdt_context |
| 463 | uint32_t cdt_context_get_sz(cdt_context *ctx); |
| 464 | const uint8_t *cdt_context_get_data(cdt_context *ctx); |
| 465 | uint8_t *cdt_context_create_new_particle(cdt_context *ctx, uint32_t subctx_sz); |
| 466 | |
| 467 | cdt_ctx_list_stack_entry *cdt_context_push(cdt_context *ctx, uint32_t idx, uint8_t *idx_mem); |
| 468 | |
| 469 | static inline bool |
| 470 | cdt_context_is_toplvl(const cdt_context *ctx) |
| 471 | { |
| 472 | return ctx->data_sz == 0; |
| 473 | } |
| 474 | |
| 475 | // Debugging support |
| 476 | bool cdt_verify(cdt_context *ctx); |
| 477 | bool list_verify(const cdt_context *ctx); |
| 478 | bool map_verify(const cdt_context *ctx); |
| 479 | |
| 480 | void print_hex(const uint8_t *packed, uint32_t packed_sz, char *buf, uint32_t buf_sz); |
| 481 | void print_packed(const uint8_t *packed, uint32_t sz, const char *name); |
| 482 | void cdt_bin_print(const as_bin *b, const char *name); |
| 483 | void cdt_context_print(const cdt_context *ctx, const char *name); |
| 484 | |
| 485 | |
| 486 | //========================================================== |
| 487 | // Inline functions. |
| 488 | // |
| 489 | |
| 490 | static inline bool |
| 491 | result_data_is_inverted(cdt_result_data *rd) |
| 492 | { |
| 493 | return (rd->flags & AS_CDT_OP_FLAG_INVERTED) != 0; |
| 494 | } |
| 495 | |
| 496 | static inline void |
| 497 | result_data_set(cdt_result_data *rd, uint64_t result_type, bool is_multi) |
| 498 | { |
| 499 | rd->type = (result_type_t)(result_type & AS_CDT_OP_FLAG_RESULT_MASK); |
| 500 | rd->flags = (as_cdt_op_flags)(result_type & (~AS_CDT_OP_FLAG_RESULT_MASK)); |
| 501 | rd->is_multi = is_multi; |
| 502 | } |
| 503 | |
| 504 | static inline void |
| 505 | result_data_set_int(cdt_result_data *rd, int64_t value) |
| 506 | { |
| 507 | if (rd) { |
| 508 | as_bin_set_int(rd->result, value); |
| 509 | } |
| 510 | } |
| 511 | |
| 512 | static inline bool |
| 513 | result_data_is_return_elements(const cdt_result_data *rd) |
| 514 | { |
| 515 | return (rd->type == RESULT_TYPE_KEY || rd->type == RESULT_TYPE_VALUE || |
| 516 | rd->type == RESULT_TYPE_MAP); |
| 517 | } |
| 518 | |
| 519 | static inline bool |
| 520 | result_data_is_return_index(const cdt_result_data *rd) |
| 521 | { |
| 522 | return (rd->type == RESULT_TYPE_INDEX || rd->type == RESULT_TYPE_REVINDEX); |
| 523 | } |
| 524 | |
| 525 | static inline bool |
| 526 | result_data_is_return_index_range(const cdt_result_data *rd) |
| 527 | { |
| 528 | return (rd->type == RESULT_TYPE_INDEX_RANGE || |
| 529 | rd->type == RESULT_TYPE_REVINDEX_RANGE); |
| 530 | } |
| 531 | |
| 532 | static inline bool |
| 533 | result_data_is_return_rank(const cdt_result_data *rd) |
| 534 | { |
| 535 | return (rd->type == RESULT_TYPE_REVRANK || rd->type == RESULT_TYPE_RANK); |
| 536 | } |
| 537 | |
| 538 | static inline bool |
| 539 | result_data_is_return_rank_range(const cdt_result_data *rd) |
| 540 | { |
| 541 | return (rd->type == RESULT_TYPE_REVRANK_RANGE || |
| 542 | rd->type == RESULT_TYPE_RANK_RANGE); |
| 543 | } |
| 544 | |
| 545 | static inline void |
| 546 | order_heap_set(order_heap *heap, uint32_t index, uint32_t value) |
| 547 | { |
| 548 | order_index_set((order_index *)heap, index, value); |
| 549 | } |
| 550 | |
| 551 | static inline uint32_t |
| 552 | order_heap_get(const order_heap *heap, uint32_t index) |
| 553 | { |
| 554 | return order_index_get((const order_index *)heap, index); |
| 555 | } |
| 556 | |
| 557 | // Calculate index given index and max_index. |
| 558 | static inline int64_t |
| 559 | calc_index(int64_t index, uint32_t max_index) |
| 560 | { |
| 561 | return index < 0 ? (int64_t)max_index + index : index; |
| 562 | } |
| 563 | |
| 564 | static inline bool |
| 565 | cdt_context_is_modify(const cdt_context *ctx) |
| 566 | { |
| 567 | return ctx->alloc_buf != NULL; |
| 568 | } |
| 569 | |
| 570 | static inline bool |
| 571 | cdt_op_is_modify(const cdt_op_mem *com) |
| 572 | { |
| 573 | return cdt_context_is_modify(&com->ctx); |
| 574 | } |
| 575 | |
| 576 | static inline void |
| 577 | cdt_int_list_builder_start(cdt_container_builder *builder, |
| 578 | rollback_alloc *alloc_buf, uint32_t ele_count) |
| 579 | { |
| 580 | cdt_list_builder_start(builder, alloc_buf, ele_count, |
| 581 | CDT_MAX_PACKED_INT_SZ * ele_count); |
| 582 | } |
| 583 | |
| 584 | static inline uint32_t |
| 585 | cdt_vla_sz(uint32_t sz) |
| 586 | { |
| 587 | return sz > CDT_MAX_STACK_OBJ_SZ ? 0 : sz; |
| 588 | } |
| 589 | |
| 590 | // cdt_idx_mask |
| 591 | static inline uint32_t |
| 592 | cdt_idx_mask_count(uint32_t ele_count) |
| 593 | { |
| 594 | return (ele_count + 63) / 64; |
| 595 | } |
| 596 | |
| 597 | static inline uint32_t |
| 598 | cdt_idx_vla_mask_count(uint32_t ele_count) |
| 599 | { |
| 600 | uint32_t count = cdt_idx_mask_count(ele_count); |
| 601 | |
| 602 | return (count == 0 || count * sizeof(uint64_t) > CDT_MAX_STACK_OBJ_SZ) ? |
| 603 | 1 : count; |
| 604 | } |
| 605 | |