flat_file.c
Go to the documentation of this file.
115 ion_err_t err = flat_file_scan(flat_file, -1, &loc, &row, ION_FLAT_FILE_SCAN_BACKWARDS, flat_file_predicate_not_empty);
167 ion_fpos_t end_offset = ION_FLAT_FILE_SCAN_FORWARDS == scan_direction ? flat_file->eof_position : flat_file->start_of_data;
178 /* If we're scanning backwards, bump the cur_offset up one record so that we read the record we're sitting on. */
180 if ((ION_FLAT_FILE_SCAN_BACKWARDS == scan_direction) && (cur_offset != flat_file->eof_position)) {
199 /* It's possible for this to do a partial read (if you're close to EOF), calculate how many we need to read */
202 num_records_to_process = records_left > (unsigned) flat_file->num_buffered ? (unsigned) flat_file->num_buffered : records_left;
204 if (num_records_to_process != fread(flat_file->buffer, flat_file->row_size, num_records_to_process, flat_file->data_file)) {
213 /* Move the offset pointer to the next read location, clamp it at start_of_file if we go too far. */
217 /* We know how many rows we went past the start of file, calculate it so we don't fread too much */
218 num_records_to_process = flat_file->num_buffered - (flat_file->start_of_data - cur_offset) / flat_file->row_size;
226 if (num_records_to_process != fread(flat_file->buffer, flat_file->row_size, num_records_to_process, flat_file->data_file)) {
234 flat_file->current_loaded_region = (prev_offset - flat_file->start_of_data) / flat_file->row_size;
239 for (i = ION_FLAT_FILE_SCAN_FORWARDS == scan_direction ? 0 : num_records_to_process - 1; ION_FLAT_FILE_SCAN_FORWARDS == scan_direction ? (size_t) i < num_records_to_process : i >= 0; ION_FLAT_FILE_SCAN_FORWARDS == scan_direction ? i++ : i--) {
245 row->value = &flat_file->buffer[cur_rec + sizeof(ion_flat_file_row_status_t) + flat_file->super.record.key_size];
287 return ION_FLAT_FILE_STATUS_OCCUPIED == row->row_status && 0 == flat_file->super.compare(target_key, row->key, flat_file->super.record.key_size);
299 return ION_FLAT_FILE_STATUS_OCCUPIED == row->row_status && flat_file->super.compare(row->key, lower_bound, flat_file->super.record.key_size) >= 0 && flat_file->super.compare(row->key, upper_bound, flat_file->super.record.key_size) <= 0;
330 if (0 != fseek(flat_file->data_file, flat_file->start_of_data + location * flat_file->row_size, SEEK_SET)) {
338 if ((NULL != row->key) && (1 != fwrite(row->key, flat_file->super.record.key_size, 1, flat_file->data_file))) {
342 if ((NULL != row->value) && (1 != fwrite(row->value, flat_file->super.record.value_size, 1, flat_file->data_file))) {
357 if ((flat_file->current_loaded_region != -1) && (location >= flat_file->current_loaded_region) && ((unsigned) location < flat_file->current_loaded_region + flat_file->num_in_buffer)) {
363 if (0 != fseek(flat_file->data_file, flat_file->start_of_data + location * flat_file->row_size, SEEK_SET)) {
371 if (1 != fread(flat_file->buffer + sizeof(row->row_status), flat_file->super.record.key_size, 1, flat_file->data_file)) {
375 if (1 != fread(flat_file->buffer + sizeof(row->row_status) + flat_file->super.record.key_size, flat_file->super.record.value_size, 1, flat_file->data_file)) {
380 row->row_status = *((ion_flat_file_row_status_t *) &flat_file->buffer[read_index * flat_file->row_size]);
381 row->key = &flat_file->buffer[read_index * flat_file->row_size + sizeof(ion_flat_file_row_status_t)];
382 row->value = &flat_file->buffer[read_index * flat_file->row_size + sizeof(ion_flat_file_row_status_t) + flat_file->super.record.key_size];
395 /* We can assume append-only insert here because our delete operation does a swap replacement, and
397 ion_fpos_t insert_loc = (flat_file->eof_position - flat_file->start_of_data) / flat_file->row_size;
400 ion_fpos_t last_record_loc = (flat_file->eof_position - flat_file->start_of_data) / flat_file->row_size - 1;
418 err = flat_file_write_row(flat_file, insert_loc, &(ion_flat_file_row_t) { ION_FLAT_FILE_STATUS_OCCUPIED, key, value });
450 err = flat_file_scan(flat_file, -1, &found_loc, &row, ION_FLAT_FILE_SCAN_FORWARDS, flat_file_predicate_key_match, key);
508 while (err_ok == (err = flat_file_scan(flat_file, loc, &loc, &row, ION_FLAT_FILE_SCAN_FORWARDS, flat_file_predicate_key_match, key))) {
511 ion_fpos_t last_record_index = (last_record_offset - flat_file->start_of_data) / flat_file->row_size;
514 /* If the last index and the loc are the same, then we can just move the eof position. Saves a read/write. */
532 row_err = flat_file_write_row(flat_file, last_record_index, &(ion_flat_file_row_t) { ION_FLAT_FILE_STATUS_EMPTY, NULL, NULL });
543 /* No location movement is done here, since we need to check the row we just swapped in to see if it is
597 while (err_ok == (err = flat_file_scan(flat_file, loc, &loc, &row, ION_FLAT_FILE_SCAN_FORWARDS, flat_file_predicate_key_match, key))) {
598 ion_err_t row_err = flat_file_write_row(flat_file, loc, &(ion_flat_file_row_t) { ION_FLAT_FILE_STATUS_OCCUPIED, key, value });
650 ion_fpos_t high_idx = (flat_file->eof_position - flat_file->start_of_data) / flat_file->row_size - 1;
667 char comp_result = flat_file->super.compare(target_key, row.key, flat_file->super.record.key_size);
688 } while (dup_idx >= 0 && 0 == flat_file->super.compare(row.key, target_key, flat_file->super.record.key_size));
695 /* If we reach here, then we fell through the loop - do check and adjust for LEQ as necessary */
ion_err_t flat_file_write_row(ion_flat_file_t *flat_file, ion_fpos_t location, ion_flat_file_row_t *row)
Writes the given row out to the data file.
Definition: flat_file.c:321
ion_status_t flat_file_get(ion_flat_file_t *flat_file, ion_key_t key, ion_value_t value)
Fetches the record stored with the given key.
Definition: flat_file.c:439
Definition: kv_system.h:276
Definition: kv_system.h:160
ion_err_t flat_file_binary_search(ion_flat_file_t *flat_file, ion_key_t target_key, ion_fpos_t *location)
Performs a binary search for the given target_key, returning to location the first-less-than-or-equal...
Definition: flat_file.c:638
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.
Container for the rows written in the flat file data file.
Definition: flat_file_types.h:107
Metadata container that holds flat file specific information.
Definition: flat_file_types.h:73
ion_err_t flat_file_destroy(ion_flat_file_t *flat_file)
Destroys and cleans up any implementation specific memory or files.
Definition: flat_file.c:134
ion_fpos_t current_loaded_region
Definition: flat_file_types.h:99
Definition: kv_system.h:215
ion_err_t flat_file_initialize(ion_flat_file_t *flat_file, 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)
Initializes the flat file implementation and creates all necessary files.
Definition: flat_file.c:40
ion_byte_t ion_flat_file_row_status_t
This type describes the status flag within a flat file row.
Definition: flat_file_types.h:50
ion_status_t flat_file_update(ion_flat_file_t *flat_file, ion_key_t key, ion_value_t value)
Updates all records stored with the given key to have value.
Definition: flat_file.c:560
Definition: kv_system.h:200
unsigned int ion_dictionary_id_t
A type used to identify dictionaries, specifically in the master table.
Definition: dictionary_types.h:51
unsigned int ion_dictionary_size_t
The implementation specific size of the dictionary.
Definition: kv_system.h:264
#define ION_FLAT_FILE_SCAN_BACKWARDS
Signals to flat_file_scan to scan in a backward direction.
Definition: flat_file_types.h:68
ion_boolean_t flat_file_predicate_within_bounds(ion_flat_file_t *flat_file, ion_flat_file_row_t *row, va_list *args)
Predicate function to return any row that has a key such that lower_bound <= key <= upper_bound holds...
Definition: flat_file.c:291
Definition: kv_system.h:188
#define ION_FLAT_FILE_STATUS_EMPTY
Signifies that this row in the flat file is currently empty and is okay to be overwritten.
Definition: flat_file_types.h:59
ion_status_t flat_file_delete(ion_flat_file_t *flat_file, ion_key_t key)
Deletes all records stored with the given key.
Definition: flat_file.c:495
ion_err_t flat_file_read_row(ion_flat_file_t *flat_file, ion_fpos_t location, ion_flat_file_row_t *row)
Reads the row specified by the given location into the buffer.
Definition: flat_file.c:350
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
Definition: kv_system.h:176
ion_flat_file_row_status_t row_status
Definition: flat_file_types.h:109
ion_err_t flat_file_scan(ion_flat_file_t *flat_file, ion_fpos_t start_location, ion_fpos_t *location, ion_flat_file_row_t *row, ion_byte_t scan_direction, ion_flat_file_predicate_t predicate,...)
Performs a linear scan of the flat file writing the first location seen that satisfies the given pred...
Definition: flat_file.c:157
Definition: kv_system.h:185
#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
Definition: kv_system.h:179
Definition: kv_system.h:218
ion_err_t flat_file_close(ion_flat_file_t *flat_file)
Closes and frees any memory associated with the flat file.
Definition: flat_file.c:624
Implementation specific declarations for the flat file store.
Definition: kv_system.h:197
Definition: kv_system.h:162
#define ION_FLAT_FILE_STATUS_OCCUPIED
Signifies that this row in the flat file is currently occupied and should not be overwritten.
Definition: flat_file_types.h:55
Definition: kv_system.h:182
#define ION_FLAT_FILE_SCAN_FORWARDS
Signals to flat_file_scan to scan in a forward direction.
Definition: flat_file_types.h:64
ion_boolean_t flat_file_predicate_key_match(ion_flat_file_t *flat_file, ion_flat_file_row_t *row, va_list *args)
Predicate function to return any row that has an exact match to the given target key.
Definition: flat_file.c:280
Definition: kv_system.h:212
ion_status_t flat_file_insert(ion_flat_file_t *flat_file, ion_key_t key, ion_value_t value)
Inserts the given record into the flat file store.
Definition: flat_file.c:388
Definition: kv_system.h:191
ion_boolean_t(* ion_flat_file_predicate_t)(ion_flat_file_t *, ion_flat_file_row_t *, va_list *args)
The function signature of a flat file predicate, used in searches.
Definition: flat_file_types.h:119
ion_boolean_t flat_file_predicate_not_empty(ion_flat_file_t *flat_file, ion_flat_file_row_t *row, va_list *args)
Predicate function to return any row that is not empty or deleted.
Definition: flat_file.c:268
A status object that describes the result of a dictionary operation.
Definition: kv_system.h:290