skip_list_handler.c
Go to the documentation of this file.
1 /******************************************************************************/
35 /******************************************************************************/
36 
37 #include "skip_list_handler.h"
38 
62  ion_key_t key,
63  ion_value_t value
64 ) {
65  return sl_get((ion_skiplist_t *) dictionary->instance, key, value);
66 }
67 
82  ion_dict_cursor_t *cursor,
83  ion_record_t *record
84 ) {
85  ion_sldict_cursor_t *sl_cursor = (ion_sldict_cursor_t *) cursor;
86 
87  if (cursor->status == cs_cursor_uninitialized) {
88  return cursor->status;
89  }
90  else if (cursor->status == cs_end_of_results) {
91  return cursor->status;
92  }
93  else if ((cursor->status == cs_cursor_initialized) || (cursor->status == cs_cursor_active)) {
94  if (cursor->status == cs_cursor_active) {
95  if ((NULL == sl_cursor->current) || (test_predicate(cursor, sl_cursor->current->key) == boolean_false)) {
96  cursor->status = cs_end_of_results;
97  return cursor->status;
98  }
99  }
100  else {
101  /* The status is cs_cursor_initialized */
102  cursor->status = cs_cursor_active;
103  }
104 
105  /*Copy both key and value into user provided struct */
106  memcpy(record->key, sl_cursor->current->key, cursor->dictionary->instance->record.key_size);
107  memcpy(record->value, sl_cursor->current->value, cursor->dictionary->instance->record.value_size);
108 
109  sl_cursor->current = sl_cursor->current->next[0];
110  return cursor->status;
111  }
112 
113  return cs_invalid_cursor;
114 }
115 
124 ion_err_t
127 ) {
128  UNUSED(dictionary);
129  return err_not_implemented;
130 }
131 
142 void
144  ion_dict_cursor_t **cursor
145 ) {
146  (*cursor)->predicate->destroy(&(*cursor)->predicate);
147  free(*cursor);
148  *cursor = NULL;
149 }
150 
167 ion_err_t
171  ion_dict_cursor_t **cursor
172 ) {
173  *cursor = malloc(sizeof(ion_sldict_cursor_t));
174 
175  ion_skiplist_t *skip_list = (ion_skiplist_t *) dictionary->instance;
176 
177  if (NULL == *cursor) {
178  return err_out_of_memory;
179  }
180 
181  (*cursor)->dictionary = dictionary;
182  (*cursor)->status = cs_cursor_uninitialized;
183 
184  (*cursor)->destroy = sldict_destroy_cursor;
185  (*cursor)->next = sldict_next;
186 
187  (*cursor)->predicate = malloc(sizeof(ion_predicate_t));
188 
189  if (NULL == (*cursor)->predicate) {
190  free(*cursor);
191  return err_out_of_memory;
192  }
193 
194  (*cursor)->predicate->type = predicate->type;
195  (*cursor)->predicate->destroy = predicate->destroy;
196 
197  ion_key_size_t key_size = dictionary->instance->record.key_size;
198 
199  switch (predicate->type) {
200  case predicate_equality: {
201  ion_key_t target_key = predicate->statement.equality.equality_value;
202 
203  (*cursor)->predicate->statement.equality.equality_value = malloc(key_size);
204 
205  if (NULL == (*cursor)->predicate->statement.equality.equality_value) {
206  free((*cursor)->predicate);
207  free(*cursor);
208  return err_out_of_memory;
209  }
210 
211  memcpy((*cursor)->predicate->statement.equality.equality_value, target_key, key_size);
212 
213  ion_sl_node_t *loc = sl_find_node((ion_skiplist_t *) dictionary->instance, target_key);
214 
215  if ((NULL == loc->key) || (dictionary->instance->compare(loc->key, target_key, key_size) != 0)) {
216  /* If this happens, that means the target key doesn't exist */
217  (*cursor)->status = cs_end_of_results;
218  return err_ok;
219  }
220  else {
221  (*cursor)->status = cs_cursor_initialized;
222 
223  ion_sldict_cursor_t *sl_cursor = (ion_sldict_cursor_t *) (*cursor);
224 
225  sl_cursor->current = loc;
226  return err_ok;
227  }
228 
229  break;
230  }
231 
232  case predicate_range: {
233  (*cursor)->predicate->statement.range.lower_bound = malloc(key_size);
234 
235  if (NULL == (*cursor)->predicate->statement.range.lower_bound) {
236  free((*cursor)->predicate);
237  free(*cursor);
238  return err_out_of_memory;
239  }
240 
241  memcpy((*cursor)->predicate->statement.range.lower_bound, predicate->statement.range.lower_bound, key_size);
242 
243  (*cursor)->predicate->statement.range.upper_bound = malloc(key_size);
244 
245  if (NULL == (*cursor)->predicate->statement.range.upper_bound) {
246  free((*cursor)->predicate->statement.range.lower_bound);
247  free((*cursor)->predicate);
248  free(*cursor);
249  return err_out_of_memory;
250  }
251 
252  memcpy((*cursor)->predicate->statement.range.upper_bound, predicate->statement.range.upper_bound, key_size);
253 
254  /* Try to find the node containing the upper bound. */
255  ion_sl_node_t *loc = sl_find_node((ion_skiplist_t *) dictionary->instance, (*cursor)->predicate->statement.range.upper_bound);
256 
257  if ((NULL == loc->key) || (dictionary->instance->compare(loc->key, (*cursor)->predicate->statement.range.lower_bound, key_size) < 0)) {
258  /* This means the returned node is smaller than the lower bound, which means that there are no valid records to return */
259  (*cursor)->status = cs_end_of_results;
260  return err_ok;
261  }
262  else {
263  loc = sl_find_node((ion_skiplist_t *) dictionary->instance, (*cursor)->predicate->statement.range.lower_bound);
264 
265  if (NULL == loc->key) {
266  /* If this happens, then we hit the head node. Just move to the first valid data item (if exists) */
267  loc = loc->next[0];
268  }
269 
270  /* Increment the location until we hit valid data. It is impossible to fall through here, since we just confirmed previously */
271  /* that there does indeed exist valid data (See above check). */
272  while (NULL != loc && (dictionary->instance->compare(loc->key, (*cursor)->predicate->statement.range.lower_bound, key_size) < 0)) {
273  loc = loc->next[0];
274  }
275 
276  /* We sanity check this anyways just in case. */
277  if (NULL == loc) {
278  (*cursor)->status = cs_end_of_results;
279  return err_ok;
280  }
281 
282  (*cursor)->status = cs_cursor_initialized;
283 
284  ion_sldict_cursor_t *sl_cursor = (ion_sldict_cursor_t *) (*cursor);
285 
286  sl_cursor->current = loc;
287  return err_ok;
288  }
289 
290  break;
291  }
292 
293  case predicate_all_records: {
294  ion_sldict_cursor_t *sl_cursor = (ion_sldict_cursor_t *) (*cursor);
295 
296  if (NULL == skip_list->head->next[0]) {
297  (*cursor)->status = cs_end_of_results;
298  }
299  else {
300  sl_cursor->current = skip_list->head->next[0];
301  (*cursor)->status = cs_cursor_initialized;
302  }
303 
304  return err_ok;
305  break;
306  }
307 
308  case predicate_predicate: {
309  break;
310  }
311 
312  default: {
313  return err_invalid_predicate;
314  break;
315  }
316  }
317 
318  return err_ok;
319 }
320 
336 ion_err_t
338  ion_dictionary_handler_t *handler,
342 ) {
343  UNUSED(handler);
344  UNUSED(dictionary);
345  UNUSED(config);
346  UNUSED(compare);
347  return err_not_implemented;
348 }
349 
350 void
352  ion_dictionary_handler_t *handler
353 ) {
354  handler->insert = sldict_insert;
355  handler->get = sldict_get;
357  handler->remove = sldict_delete;
360  handler->update = sldict_update;
361  handler->find = sldict_find;
364 }
365 
369  ion_key_t key,
370  ion_value_t value
371 ) {
372  return sl_insert((ion_skiplist_t *) dictionary->instance, key, value);
373 }
374 
375 ion_err_t
378  ion_key_type_t key_type,
379  ion_key_size_t key_size,
380  ion_value_size_t value_size,
381  ion_dictionary_size_t dictionary_size,
382  ion_dictionary_compare_t compare,
383  ion_dictionary_handler_t *handler,
385 ) {
386  UNUSED(id);
387 
388  int pnum, pden;
389 
390  dictionary->instance = malloc(sizeof(ion_skiplist_t));
391 
392  if (NULL == dictionary->instance) {
393  return err_out_of_memory;
394  }
395 
396  dictionary->instance->compare = compare;
398 
399  pnum = 1;
400  pden = 4;
401 
402  ion_err_t result = sl_initialize((ion_skiplist_t *) dictionary->instance, key_type, key_size, value_size, dictionary_size, pnum, pden);
403 
404  if ((err_ok == result) && (NULL != handler)) {
405  dictionary->handler = handler;
406  }
407 
408  return result;
409 }
410 
414  ion_key_t key
415 ) {
416  return sl_delete((ion_skiplist_t *) dictionary->instance, key);
417 }
418 
419 ion_err_t
422 ) {
423  ion_err_t result = sl_destroy((ion_skiplist_t *) dictionary->instance);
424 
425  free(dictionary->instance);
426  dictionary->instance = NULL;
427  return result;
428 }
429 
430 ion_err_t
433 ) {
434  UNUSED(id);
435  return err_not_implemented;
436 }
437 
441  ion_key_t key,
442  ion_value_t value
443 ) {
444  return sl_update((ion_skiplist_t *) dictionary->instance, key, value);
445 }
ion_status_t sl_insert(ion_skiplist_t *skiplist, ion_key_t key, ion_value_t value)
Inserts a key value pair into the skiplist.
Definition: skip_list.c:115
ion_status_t(* insert)(ion_dictionary_t *, ion_key_t, ion_value_t)
ion_value_t value
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_record_info_t record
ion_status_t sl_delete(ion_skiplist_t *skiplist, ion_key_t key)
Attempts to delete all key/value pairs stored at the given key.
Definition: skip_list.c:261
ion_err_t sldict_find(ion_dictionary_t *dictionary, ion_predicate_t *predicate, ion_dict_cursor_t **cursor)
Finds multiple keys based on the provided predicate.
ion_status_t sl_get(ion_skiplist_t *skiplist, ion_key_t key, ion_value_t value)
Requests the value stored at the given key.
Definition: skip_list.c:206
int ion_value_size_t
The size (length) of a dictionary value in bytes.
Definition: kv_system.h:256
Handler liaison between dictionary API and skiplist implementation.
Struct of the Skiplist, holds metadata and the entry point into the skiplist.
ion_status_t sldict_update(ion_dictionary_t *dictionary, ion_key_t key, ion_value_t value)
Updates the value stored at a given key.
ion_predicate_statement_t statement
ion_dictionary_handler_t * handler
ion_dictionary_parent_t * instance
ion_err_t sl_initialize(ion_skiplist_t *skiplist, ion_key_type_t key_type, int key_size, int value_size, int maxheight, int pnum, int pden)
Initializes an in-memory skiplist.
Definition: skip_list.c:41
struct sl_node ** next
ion_value_t value
Definition: kv_system.h:318
ion_status_t(* remove)(ion_dictionary_t *, ion_key_t)
ion_dictionary_t * dictionary
ion_err_t(* destroy_dictionary)(ion_dictionary_id_t id)
Struct used to maintain key and value.
Definition: kv_system.h:315
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_err_t sldict_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.
ion_cursor_status_t status
#define key(k)
Definition: bpp_tree.c:75
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
ion_sl_node_t * head
ion_key_t key
Definition: kv_system.h:316
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
Struct of a node in the skiplist.
void * ion_key_t
A dictionary key.
Definition: kv_system.h:241
ion_err_t sldict_close_dictionary(ion_dictionary_t *dictionary)
Closes a skiplist instance of a dictionary.
void(* destroy)(ion_predicate_t **)
ion_status_t(* update)(ion_dictionary_t *, ion_key_t, ion_value_t)
ion_equality_statement_t equality
void sldict_destroy_cursor(ion_dict_cursor_t **cursor)
Destroys the cursor.
void * ion_value_t
A dictionary value.
Definition: kv_system.h:246
ion_status_t sldict_delete(ion_dictionary_t *dictionary, ion_key_t key)
Deletes the key and associated value from the given dictionary instance.
A dictionary contains information regarding an instance of the storage element and the associated han...
ion_err_t sldict_destroy_dictionary(ion_dictionary_id_t id)
Deletes an instance of a closed dictionary.
ion_predicate_type_t type
A supertype for dictionary cursor objects.
ion_err_t(* close_dictionary)(ion_dictionary_t *)
ion_err_t(* open_dictionary)(ion_dictionary_handler_t *, ion_dictionary_t *, ion_dictionary_config_info_t *, ion_dictionary_compare_t)
ion_key_t key
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_err_t(* delete_dictionary)(ion_dictionary_t *)
ion_key_size_t key_size
Definition: kv_system.h:307
ion_status_t sldict_insert(ion_dictionary_t *dictionary, ion_key_t key, ion_value_t value)
Inserts a key and value pair into the dictionary.
A supertype for cursor predicate objects.
ion_dictionary_type_t type
ion_sl_node_t * current
ion_err_t(* find)(ion_dictionary_t *, ion_predicate_t *, ion_dict_cursor_t **)
ion_sl_node_t * sl_find_node(ion_skiplist_t *skiplist, ion_key_t key)
Searches for a node with the given key. Used in conjunction with sl_query to perform key lookups...
Definition: skip_list.c:317
#define UNUSED(x)
Definition: kv_system.h:102
ion_err_t sl_destroy(ion_skiplist_t *skiplist)
Destroys the skiplist in memory.
Definition: skip_list.c:95
ion_dictionary_compare_t compare
ion_err_t sldict_delete_dictionary(ion_dictionary_t *dictionary)
Deletes an instance of a dictionary and its associated data.
int ion_key_size_t
The size (length) of a dictionary key in bytes.
Definition: kv_system.h:251
ion_cursor_status_t sldict_next(ion_dict_cursor_t *cursor, ion_record_t *record)
Next function queries and retrieves the next key/value pair that satisfies the predicate of the curso...
ion_status_t sldict_get(ion_dictionary_t *dictionary, ion_key_t key, ion_value_t value)
Queries a dictionary instance for a given key and returns the corresponding value.
ion_range_statement_t range
void sldict_init(ion_dictionary_handler_t *handler)
Registers a skiplist handler to a dictionary instance.
ion_dictionary_status_t status
ion_err_t sldict_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 skiplist instance of a dictionary.
ion_value_size_t value_size
Definition: kv_system.h:309
ion_status_t(* get)(ion_dictionary_t *, ion_key_t, ion_value_t)
A dictionary_handler is responsible for dealing with the specific interface for an underlying diction...
char ion_cursor_status_t
A type for the status of a cursor.
ion_status_t sl_update(ion_skiplist_t *skiplist, ion_key_t key, ion_value_t value)
Updates the value stored at key with the new value.
Definition: skip_list.c:225
A status object that describes the result of a dictionary operation.
Definition: kv_system.h:290