bpp_tree_handler.c
Go to the documentation of this file.
1 /******************************************************************************/
35 /******************************************************************************/
36 
37 #include "bpp_tree_handler.h"
38 
39 void
42  char *str
43 ) {
44  sprintf(str, "%d.val", id);
45 }
46 
75  ion_key_type_t key_type,
76  ion_key_size_t key_size,
77  ion_value_size_t value_size,
78  ion_dictionary_size_t dictionary_size,
80  ion_dictionary_handler_t *handler,
82 ) {
83  UNUSED(dictionary_size);
84 
85 /* if (key_size != sizeof(int)) {
86  return err_invalid_initial_size;
87  }*/
88 
89  ion_bpptree_t *bpptree;
90  ion_bpp_open_t info;
91 
92  bpptree = malloc(sizeof(ion_bpptree_t));
93 
94  if (NULL == bpptree) {
95  return err_out_of_memory;
96  }
97 
98  char value_filename[20];
99 
100  bpptree_get_filename(id, value_filename);
101  bpptree->values.file_handle = ion_fopen(value_filename);
102 
103  bpptree->values.next_empty = ION_FILE_NULL;
104 
105  char addr_filename[ION_MAX_FILENAME_LENGTH];
106 
107  int actual_filename_length = dictionary_get_filename(id, "bpt", addr_filename);
108 
109  if (actual_filename_length >= ION_MAX_FILENAME_LENGTH) {
110  return err_uninitialized;
111  }
112 
113  info.iName = addr_filename;
114  info.keySize = key_size;
115  info.dupKeys = boolean_false;
116  info.sectorSize = 256;
117  info.comp = compare;
118 
119  ion_bpp_err_t bErr = b_open(info, &(bpptree->tree));
120 
121  if (bErrOk != bErr) {
122  return err_uninitialized;
123  }
124 
125  if (NULL == handler) {
126  return err_uninitialized;
127  }
128 
129  dictionary->instance = (ion_dictionary_parent_t *) bpptree;
130  dictionary->instance->compare = compare;
131  dictionary->instance->key_type = key_type;
132  dictionary->instance->record.key_size = key_size;
133  dictionary->instance->record.value_size = value_size;
135  dictionary->handler = handler;
136 
137  return err_ok;
138 }
139 
154  ion_key_t key,
155  ion_value_t value
156 ) {
157  ion_bpptree_t *bpptree;
158  ion_bpp_err_t bErr;
159  ion_err_t err;
160  ion_file_offset_t offset;
161 
162  bpptree = (ion_bpptree_t *) dictionary->instance;
163 
164  offset = ION_FILE_NULL;
165  bErr = b_get(bpptree->tree, key, &offset);
166 
167  if (bErrKeyNotFound == bErr) {
168  offset = ION_FILE_NULL;
169  }
170 
171  err = lfb_put(&(bpptree->values), (ion_byte_t *) value, bpptree->super.record.value_size, offset, &offset);
172 
173  if (err_ok == err) {
174  if (bErrKeyNotFound == bErr) {
175  bErr = b_insert(bpptree->tree, key, offset);
176  }
177  else {
178  bErr = b_update(bpptree->tree, key, offset);
179  }
180 
181  if (bErrOk != bErr) {
183  }
184 
185  return ION_STATUS_OK(1);
186  }
187  else {
189  }
190 }
191 
219  ion_key_t key,
220  ion_value_t value
221 ) {
222  ion_bpptree_t *bpptree;
223  ion_file_offset_t offset;
225  ion_bpp_err_t bErr;
226  ion_err_t err;
227 
228  bpptree = (ion_bpptree_t *) dictionary->instance;
229 
230  bErr = b_get(bpptree->tree, key, &offset);
231 
232  if (bErrOk != bErr) {
234  }
235 
236  err = lfb_get(&(bpptree->values), offset, bpptree->super.record.value_size, (ion_byte_t *) value, &next);
237 
238  if (err_ok == err) {
239  return ION_STATUS_OK(1);
240  }
241 
242  return ION_STATUS_ERROR(err);
243 }
244 
258  ion_key_t key
259 ) {
260  ion_bpptree_t *bpptree;
261  ion_bpp_err_t bErr;
262  ion_file_offset_t offset;
263  ion_status_t status;
264 
265  status = ION_STATUS_INITIALIZE;
266 
267  bpptree = (ion_bpptree_t *) dictionary->instance;
268 
269  bErr = b_delete(bpptree->tree, key, &offset);
270 
271  if (bErrKeyNotFound != bErr) {
272  status.error = lfb_delete_all(&(bpptree->values), offset, &(status.count));
273  }
274  else {
275  status.error = err_item_not_found;
276  }
277 
278  return status;
279 }
280 
289 ion_err_t
292 ) {
293  ion_bpptree_t *bpptree;
294  ion_bpp_err_t bErr;
295 
296  bpptree = (ion_bpptree_t *) dictionary->instance;
297  bErr = b_close(bpptree->tree);
298  ion_fclose(bpptree->values.file_handle);
299  free(dictionary->instance);
300  dictionary->instance = NULL;
301 
302  if (bErrOk != bErr) {
304  }
305 
306  return err_ok;
307 }
308 
316 ion_err_t
319 ) {
321 
322  char addr_filename[ION_MAX_FILENAME_LENGTH];
323  char value_filename[ION_MAX_FILENAME_LENGTH];
324 
325  int actual_addr_filename_length = dictionary_get_filename(dictionary->instance->id, "bpt", addr_filename);
326  int actual_value_filename_length = dictionary_get_filename(dictionary->instance->id, "val", value_filename);
327 
328  if ((actual_addr_filename_length >= ION_MAX_FILENAME_LENGTH) || (actual_value_filename_length >= ION_MAX_FILENAME_LENGTH)) {
330  }
331 
332  error = bpptree_close_dictionary(dictionary);
333 
334  if (err_ok != error) {
335  return error;
336  }
337 
338  ion_fremove(addr_filename);
339  ion_fremove(value_filename);
340 
341  return err_ok;
342 }
343 
351 ion_err_t
354 ) {
355  char addr_filename[ION_MAX_FILENAME_LENGTH];
356  char value_filename[ION_MAX_FILENAME_LENGTH];
357 
358  int actual_addr_filename_length = dictionary_get_filename(id, "bpt", addr_filename);
359  int actual_value_filename_length = dictionary_get_filename(id, "val", value_filename);
360 
361  if ((actual_addr_filename_length >= ION_MAX_FILENAME_LENGTH) || (actual_value_filename_length >= ION_MAX_FILENAME_LENGTH)) {
363  }
364 
365  ion_fremove(addr_filename);
366  ion_fremove(value_filename);
367 
368  return err_ok;
369 }
370 
388  ion_key_t key,
389  ion_value_t value
390 ) {
391  ion_bpptree_t *bpptree;
392  ion_bpp_err_t bErr;
393  ion_file_offset_t offset;
394  ion_result_count_t count;
395 
396  count = 0;
397  bpptree = (ion_bpptree_t *) dictionary->instance;
398 
399  bErr = b_get(bpptree->tree, key, &offset);
400 
401  if (bErrKeyNotFound != bErr) {
402  lfb_update_all(&(bpptree->values), offset, bpptree->super.record.value_size, (ion_byte_t *) value, &count);
403  }
404  else {
405  return bpptree_insert(dictionary, key, value);
406  }
407 
408  return ION_STATUS_OK(count);
409 }
410 
425  ion_dict_cursor_t *cursor,
426  ion_record_t *record
427 ) {
428  ion_bpp_cursor_t *bCursor = (ion_bpp_cursor_t *) cursor;
429  ion_bpptree_t *bpptree = (ion_bpptree_t *) cursor->dictionary->instance;
430 
431  if (cursor->status == cs_cursor_uninitialized) {
432  return cursor->status;
433  }
434  else if (cursor->status == cs_end_of_results) {
435  return cursor->status;
436  }
437  else if ((cursor->status == cs_cursor_initialized) || (cursor->status == cs_cursor_active)) {
438  if (cursor->status == cs_cursor_active) {
439  ion_boolean_t is_valid = boolean_true;
440 
441  switch (cursor->predicate->type) {
442  case predicate_equality: {
443  if (-1 == bCursor->offset) {
444  /* End of results, we can quit */
445  is_valid = boolean_false;
446  }
447 
448  break;
449  }
450 
451  case predicate_range: {
452  /*do b_find_next_key then test_predicate */
453  if (-1 == bCursor->offset) {
454  ion_bpp_err_t bErr = b_find_next_key(bpptree->tree, bCursor->cur_key, &bCursor->offset);
455 
456  if ((bErrOk != bErr) || (boolean_false == test_predicate(cursor, bCursor->cur_key))) {
457  is_valid = boolean_false;
458  }
459  }
460 
461  break;
462  }
463 
464  case predicate_all_records: {
465  if (-1 == bCursor->offset) {
466  ion_bpp_err_t bErr = b_find_next_key(bpptree->tree, bCursor->cur_key, &bCursor->offset);
467 
468  if (bErrOk != bErr) {
469  is_valid = boolean_false;
470  }
471  }
472 
473  break;
474  }
475 
476  case predicate_predicate: {
477  break;
478  }
479  /*No default since we can assume the predicate is valid. */
480  }
481 
482  if (boolean_false == is_valid) {
483  cursor->status = cs_end_of_results;
484  return cursor->status;
485  }
486  }
487  else {
488  /* The status is cs_cursor_initialized */
489  cursor->status = cs_cursor_active;
490  }
491 
492  /* Get key */
493  memcpy(record->key, bCursor->cur_key, cursor->dictionary->instance->record.key_size);
494 
495  /* Get value */
496  lfb_get(&(bpptree->values), bCursor->offset, cursor->dictionary->instance->record.value_size, record->value, &bCursor->offset);
497  return cursor->status;
498  }
499 
500  return cs_invalid_cursor;
501 }
502 
515 void
517  ion_dict_cursor_t **cursor
518 ) {
519  (*cursor)->predicate->destroy(&(*cursor)->predicate);
520  free(((ion_bpp_cursor_t *) (*cursor))->cur_key);
521  free((*cursor));
522  *cursor = NULL;
523 }
524 
543 ion_err_t
547  ion_dict_cursor_t **cursor
548 ) {
549  ion_bpptree_t *bpptree = (ion_bpptree_t *) dictionary->instance;
550  ion_key_size_t key_size = dictionary->instance->record.key_size;
551 
552  *cursor = malloc(sizeof(ion_bpp_cursor_t));
553 
554  if (NULL == *cursor) {
555  return err_out_of_memory;
556  }
557 
558  ion_bpp_cursor_t *bCursor = (ion_bpp_cursor_t *) (*cursor);
559 
560  bCursor->cur_key = malloc(key_size);
561 
562  if (NULL == bCursor->cur_key) {
563  free(bCursor);
564  return err_out_of_memory;
565  }
566 
567  (*cursor)->dictionary = dictionary;
568  (*cursor)->status = cs_cursor_uninitialized;
569 
570  (*cursor)->destroy = bpptree_destroy_cursor;
571  (*cursor)->next = bpptree_next;
572 
573  (*cursor)->predicate = malloc(sizeof(ion_predicate_t));
574 
575  if (NULL == (*cursor)->predicate) {
576  free(bCursor->cur_key);
577  free(*cursor);
578  return err_out_of_memory;
579  }
580 
581  (*cursor)->predicate->type = predicate->type;
582  (*cursor)->predicate->destroy = predicate->destroy;
583 
584  switch (predicate->type) {
585  case predicate_equality: {
586  ion_key_t target_key = predicate->statement.equality.equality_value;
587 
588  (*cursor)->predicate->statement.equality.equality_value = malloc(key_size);
589 
590  if (NULL == (*cursor)->predicate->statement.equality.equality_value) {
591  free((*cursor)->predicate);
592  free(bCursor->cur_key);
593  free(*cursor);
594  return err_out_of_memory;
595  }
596 
597  memcpy((*cursor)->predicate->statement.equality.equality_value, target_key, key_size);
598 
599  memcpy(bCursor->cur_key, target_key, key_size);
600 
601  ion_bpp_err_t err = b_get(bpptree->tree, target_key, &bCursor->offset);
602 
603  if (bErrOk != err) {
604  /* If this happens, that means the target key doesn't exist */
605  (*cursor)->status = cs_end_of_results;
606  return err_ok;
607  }
608  else {
609  (*cursor)->status = cs_cursor_initialized;
610  return err_ok;
611  }
612 
613  break;
614  }
615 
616  case predicate_range: {
617  (*cursor)->predicate->statement.range.lower_bound = malloc(key_size);
618 
619  if (NULL == (*cursor)->predicate->statement.range.lower_bound) {
620  free((*cursor)->predicate);
621  free(bCursor->cur_key);
622  free(*cursor);
623  return err_out_of_memory;
624  }
625 
626  memcpy((*cursor)->predicate->statement.range.lower_bound, predicate->statement.range.lower_bound, key_size);
627 
628  (*cursor)->predicate->statement.range.upper_bound = malloc(key_size);
629 
630  if (NULL == (*cursor)->predicate->statement.range.upper_bound) {
631  free((*cursor)->predicate->statement.range.lower_bound);
632  free((*cursor)->predicate);
633  free(bCursor->cur_key);
634  free(*cursor);
635  return err_out_of_memory;
636  }
637 
638  memcpy((*cursor)->predicate->statement.range.upper_bound, predicate->statement.range.upper_bound, key_size);
639 
640  /* We search for the FGEQ of the Lower bound. */
641  b_find_first_greater_or_equal(bpptree->tree, (*cursor)->predicate->statement.range.lower_bound, bCursor->cur_key, &bCursor->offset);
642 
643  /* If the key returned doesn't satisfy the predicate, we can exit */
644  if (boolean_false == test_predicate(*cursor, bCursor->cur_key)) {
645  (*cursor)->status = cs_end_of_results;
646  return err_ok;
647  }
648  else {
649  (*cursor)->status = cs_cursor_initialized;
650  return err_ok;
651  }
652 
653  break;
654  }
655 
656  case predicate_all_records: {
657  ion_bpp_err_t err;
658 
659  /* We search for first key in B++ tree. */
660  err = b_find_first_key(bpptree->tree, bCursor->cur_key, &bCursor->offset);
661 
662  (*cursor)->status = cs_cursor_initialized;
663 
664  if (bErrOk != err) {
665  (*cursor)->status = cs_end_of_results;
666  }
667 
668  return err_ok;
669  break;
670  }
671 
672  case predicate_predicate: {
673  break;
674  }
675 
676  default: {
677  return err_invalid_predicate;
678  break;
679  }
680  }
681 
682  return err_ok;
683 }
684 
700 ion_err_t
702  ion_dictionary_handler_t *handler,
706 ) {
707  return bpptree_create_dictionary(config->id, config->type, config->key_size, config->value_size, config->dictionary_size, compare, handler, dictionary);
708 }
709 
710 void
712  ion_dictionary_handler_t *handler
713 ) {
714  handler->insert = bpptree_insert;
716  handler->get = bpptree_get;
717  handler->update = bpptree_update;
718  handler->find = bpptree_find;
719  handler->remove = bpptree_delete;
724 }
void bpptree_get_filename(ion_dictionary_id_t id, char *str)
ion_bpp_bool_t dupKeys
Definition: bpp_tree.h:92
ion_bpp_err_t b_close(ion_bpp_handle_t handle)
Definition: bpp_tree.c:1040
unsigned char ion_byte_t
A byte type.
Definition: kv_system.h:232
ion_status_t(* insert)(ion_dictionary_t *, ion_key_t, ion_value_t)
enum ION_BPP_ERR ion_bpp_err_t
#define ION_STATUS_ERROR(error)
Definition: kv_system.h:110
enum ION_KEY_TYPE ion_key_type_t
This is the available key types for ION_DB. All types will be based on system defines.
ion_bpp_err_t b_insert(ion_bpp_handle_t handle, void *key, ion_bpp_external_address_t rec)
Definition: bpp_tree.c:1167
ion_record_info_t record
ion_err_t lfb_update_all(ion_lfb_t *bag, ion_file_offset_t offset, unsigned int num_bytes, ion_byte_t *to_write, ion_result_count_t *count)
Attempt to update all records kept within a specific bag, starting at some record at a given offset...
ion_predicate_t * predicate
ion_err_t bpptree_close_dictionary(ion_dictionary_t *dictionary)
Closes a BppTree instance of a dictionary.
int ion_value_size_t
The size (length) of a dictionary value in bytes.
Definition: kv_system.h:256
#define next(b)
Definition: bpp_tree.c:82
The handler for a disk-backed B+ Tree.
ion_status_t bpptree_update(ion_dictionary_t *dictionary, ion_key_t key, ion_value_t value)
Updates the value for a given key.
ion_predicate_statement_t statement
ion_dictionary_handler_t * handler
ion_dictionary_parent_t * instance
ion_file_handle_t file_handle
ion_value_t value
Definition: kv_system.h:318
ion_status_t(* remove)(ion_dictionary_t *, ion_key_t)
ion_dictionary_parent_t super
ion_dictionary_t * dictionary
ion_err_t(* destroy_dictionary)(ion_dictionary_id_t id)
ion_err_t lfb_get(ion_lfb_t *bag, ion_file_offset_t offset, unsigned int num_bytes, ion_byte_t *write_to, ion_file_offset_t *next)
Add an item to the linked file bag.
Struct used to maintain key and value.
Definition: kv_system.h:315
ion_err_t bpptree_create_dictionary(ion_dictionary_id_t id, ion_key_type_t key_type, ion_key_size_t key_size, ion_value_size_t value_size, ion_dictionary_size_t dictionary_size, ion_dictionary_compare_t compare, ion_dictionary_handler_t *handler, ion_dictionary_t *dictionary)
Creates an instance of a dictionary.
unsigned int ion_dictionary_id_t
A type used to identify dictionaries, specifically in the master table.
unsigned int ion_dictionary_size_t
The implementation specific size of the dictionary.
Definition: kv_system.h:264
Struct containing details for opening a dictionary previously created.
ion_lfb_t values
ion_cursor_status_t status
ion_bpp_err_t b_get(ion_bpp_handle_t handle, void *key, ion_bpp_external_address_t *rec)
Definition: bpp_tree.c:1074
#define ION_STATUS_OK(count)
Definition: kv_system.h:113
#define key(k)
Definition: bpp_tree.c:75
ion_status_t bpptree_insert(ion_dictionary_t *dictionary, ion_key_t key, ion_value_t value)
Inserts a key and value into the dictionary.
size_t sectorSize
Definition: bpp_tree.h:93
ion_err_t error
Definition: kv_system.h:291
ion_err_t bpptree_find(ion_dictionary_t *dictionary, ion_predicate_t *predicate, ion_dict_cursor_t **cursor)
Finds multiple instances of a keys that satisfy the provided predicate in the dictionary.
ion_err_t bpptree_destroy_dictionary(ion_dictionary_id_t id)
Deletes a closed instance of the dictionary and associated data.
ion_boolean_t test_predicate(ion_dict_cursor_t *cursor, ion_key_t key)
Tests the supplied key against the predicate registered in the cursor. If the supplied cursor if of t...
Definition: dictionary.c:571
This is the super type for all dictionaries.
ion_status_t bpptree_get(ion_dictionary_t *dictionary, ion_key_t key, ion_value_t value)
Queries a dictionary instance for the given key and returns the associated value. ...
ion_key_t key
Definition: kv_system.h:316
ion_bpp_handle_t tree
char(* ion_dictionary_compare_t)(ion_key_t, ion_key_t, ion_key_size_t)
Function pointer type for dictionary comparison methods.
char ion_err_t
The error type used to store error codes.
Definition: kv_system.h:226
int dictionary_get_filename(ion_dictionary_id_t id, char *ext, char *filename)
Given the ID, implementation specific extension, and a buffer to write to, writes back the formatted ...
Definition: dictionary.c:41
void * ion_key_t
A dictionary key.
Definition: kv_system.h:241
void(* destroy)(ion_predicate_t **)
ion_status_t(* update)(ion_dictionary_t *, ion_key_t, ion_value_t)
ion_equality_statement_t equality
ion_bpp_comparison_t comp
Definition: bpp_tree.h:94
void * ion_value_t
A dictionary value.
Definition: kv_system.h:246
ion_file_handle_t ion_fopen(char *name)
Definition: ion_file.c:51
ion_bpp_err_t b_open(ion_bpp_open_t info, ion_bpp_handle_t *handle)
Definition: bpp_tree.c:899
A dictionary contains information regarding an instance of the storage element and the associated han...
ion_predicate_type_t type
ion_dictionary_id_t id
void bpptree_destroy_cursor(ion_dict_cursor_t **cursor)
Destroys the cursor.
A supertype for dictionary cursor objects.
ion_err_t ion_fremove(char *name)
Definition: ion_file.c:93
ion_err_t(* close_dictionary)(ion_dictionary_t *)
#define ION_MAX_FILENAME_LENGTH
Since the arduino conforms to 8.3 syntax, that's 8 + 3 = 11 + 1 (null terminator) characters...
Definition: kv_system.h:73
ion_err_t(* open_dictionary)(ion_dictionary_handler_t *, ion_dictionary_t *, ion_dictionary_config_info_t *, ion_dictionary_compare_t)
long ion_file_offset_t
Definition: ion_file.h:47
ion_result_count_t count
Definition: kv_system.h:293
ion_err_t(* create_dictionary)(ion_dictionary_id_t, ion_key_type_t, ion_key_size_t, ion_value_size_t, ion_dictionary_size_t, ion_dictionary_compare_t, ion_dictionary_handler_t *, ion_dictionary_t *)
ion_file_offset_t offset
ion_err_t ion_fclose(ion_file_handle_t file)
Definition: ion_file.c:80
ion_cursor_status_t bpptree_next(ion_dict_cursor_t *cursor, ion_record_t *record)
Next function to query and retrieve the next <K,V> that stratifies the predicate of the cursor...
ion_status_t bpptree_delete(ion_dictionary_t *dictionary, ion_key_t key)
Deletes the key and associated value from the dictionary instance.
ion_err_t(* delete_dictionary)(ion_dictionary_t *)
ion_file_offset_t next_empty
ion_key_size_t key_size
Definition: kv_system.h:307
A supertype for cursor predicate objects.
ion_bpp_err_t b_update(ion_bpp_handle_t handle, void *key, ion_bpp_external_address_t rec)
Definition: bpp_tree.c:1345
void bpptree_init(ion_dictionary_handler_t *handler)
Registers a specific handler for a dictionary instance.
ion_dictionary_type_t type
ion_err_t(* find)(ion_dictionary_t *, ion_predicate_t *, ion_dict_cursor_t **)
#define UNUSED(x)
Definition: kv_system.h:102
#define error(rc)
Definition: bpp_tree.c:151
ion_key_type_t key_type
ion_err_t lfb_delete_all(ion_lfb_t *bag, ion_file_offset_t offset, ion_result_count_t *count)
Attempt to delete all contents from the bag starting at a given offset.
ion_dictionary_compare_t compare
ion_err_t lfb_put(ion_lfb_t *bag, ion_byte_t *to_write, unsigned int num_bytes, ion_file_offset_t next, ion_file_offset_t *wrote_at)
Add an item to the linked file bag.
ion_dictionary_size_t dictionary_size
int ion_key_size_t
The size (length) of a dictionary key in bytes.
Definition: kv_system.h:251
char ion_boolean_t
A boolean type.
Definition: kv_system.h:269
int ion_result_count_t
A type for the number of results changed during an operation.
Definition: kv_system.h:284
ion_bpp_err_t b_find_first_key(ion_bpp_handle_t handle, void *key, ion_bpp_external_address_t *rec)
Definition: bpp_tree.c:1598
ion_bpp_err_t b_delete(ion_bpp_handle_t handle, void *key, ion_bpp_external_address_t *rec)
Definition: bpp_tree.c:1453
#define ION_FILE_NULL
Definition: ion_file.h:75
ion_range_statement_t range
ion_err_t bpptree_delete_dictionary(ion_dictionary_t *dictionary)
Deletes an instance of the dictionary and associated data.
ion_bpp_err_t b_find_first_greater_or_equal(ion_bpp_handle_t handle, void *key, void *mkey, ion_bpp_external_address_t *rec)
Definition: bpp_tree.c:1116
ion_dictionary_status_t status
char * iName
Definition: bpp_tree.h:90
ion_value_size_t value_size
Definition: kv_system.h:309
ion_err_t bpptree_open_dictionary(ion_dictionary_handler_t *handler, ion_dictionary_t *dictionary, ion_dictionary_config_info_t *config, ion_dictionary_compare_t compare)
Opens a specific BppTree instance of a dictionary.
ion_status_t(* get)(ion_dictionary_t *, ion_key_t, ion_value_t)
#define ION_STATUS_INITIALIZE
Definition: kv_system.h:107
A dictionary_handler is responsible for dealing with the specific interface for an underlying diction...
ion_bpp_err_t b_find_next_key(ion_bpp_handle_t handle, void *key, ion_bpp_external_address_t *rec)
Definition: bpp_tree.c:1669
char ion_cursor_status_t
A type for the status of a cursor.
A status object that describes the result of a dictionary operation.
Definition: kv_system.h:290