diff options
Diffstat (limited to 'src/libdisfluid/disfluid-cache-entry.h')
-rw-r--r-- | src/libdisfluid/disfluid-cache-entry.h | 439 |
1 files changed, 282 insertions, 157 deletions
diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h index 76de29a..ca4f743 100644 --- a/src/libdisfluid/disfluid-cache-entry.h +++ b/src/libdisfluid/disfluid-cache-entry.h @@ -6,228 +6,353 @@ # include <stdbool.h> MAYBE_UNUSED static int -db_mark_cache_entry (const char *db_root, const string_desc_t * id); - -MAYBE_UNUSED static int -db_read_cache_entry (const char *db_root, const string_desc_t * id, +ao_cache_entry_read (int fd, size_t offset, struct timespec *request_date, - struct timespec *response_date, bool *invalidated, - string_desc_t * key_id, - string_desc_t * response_header_id, - string_desc_t * response_body_id); + struct timespec *response_date, + bool *invalidated, + bool read_key, + bool read_response_header, + bool read_response_body, + string_desc_t * key, + string_desc_t * response_header, + string_desc_t * response_body); MAYBE_UNUSED static int -db_write_cache_entry (const char *db_root, string_desc_t * id, - const struct timespec *request_date, - const struct timespec *response_date, bool invalidated, - const string_desc_t * key_id, - const string_desc_t * response_header_id, - const string_desc_t * response_body_id); +ao_cache_entry_push (int fd, size_t *offset, + const struct timespec *request_date, + const struct timespec *response_date, + bool invalidated, + const string_desc_t key, + const string_desc_t response_header, + const string_desc_t response_body); -# include "disfluid-db.h" +# include "disfluid-append-only-file.h" # include "safe-alloc.h" -MAYBE_UNUSED static int -db_mark_cache_entry (const char *db_root, const string_desc_t * id) -{ - struct timespec request_date = { 0 }, response_date = { 0 }; - bool invalidated = false; - string_desc_t key = { 0 }, header = { 0 }, body = { 0 }; - int error = db_read_cache_entry (db_root, id, &request_date, &response_date, - &invalidated, &key, &header, &body); - if (error < 0) - { - goto cleanup; - } - int key_error = db_mark_leaf (db_root, &key); - int header_error = db_mark_leaf (db_root, &header); - int body_error = db_mark_leaf (db_root, &body); - if (key_error < 0 || header_error < 0 || body_error < 0) - { - error = -1; - } -cleanup: - FREE (key._data); - FREE (header._data); - FREE (body._data); - return error; -} - /* The cache entry file is organized as follows: - - on 16 bytes, "disfluid c.entry", - on 8 bytes, the request date (timestamp in seconds), - on 4 bytes, the request date (number of nanoseconds), - on 8 bytes, the response date (timestamp in seconds), - on 4 bytes, the response date (number of nanoseconds), - - on 32 bytes, the key digest, - - on 32 bytes, the header digest, - - on 32 bytes, the body digest, + - on 8 bytes, the size of the key, + - on 8 bytes, the offset of the key, + - on 8 bytes, the size of the header, + - on 8 bytes, the offset of the header, + - on 8 bytes, the size of the body, + - on 8 bytes, the offset of the body, - 80 if the entry has been artificially invalidated, 00 otherwise. + - 7 bytes reserved. */ +struct cache_entry_header +{ + struct timespec request_date; + struct timespec response_date; + size_t key_size; + size_t key_offset; + size_t header_size; + size_t header_offset; + size_t body_size; + size_t body_offset; + bool invalidated; +}; + static int -parse_timespec (const char *data, struct timespec *ts) +ao_cache_entry_timespec_from_bytes (const uint8_t * bytes, + struct timespec *date) { - ts->tv_sec = 0; - ts->tv_nsec = 0; + date->tv_sec = 0; + date->tv_nsec = 0; for (size_t i = 0; i < 8; i++) { - ts->tv_sec *= 256; - ts->tv_sec += (uint8_t) data[i]; + date->tv_sec *= 256; + date->tv_sec += bytes[i]; } - for (size_t i = 0; i < 4; i++) + for (size_t j = 8; j < 12; j++) { - ts->tv_nsec *= 256; - ts->tv_nsec += (uint8_t) data[8 + i]; + date->tv_nsec *= 256; + date->tv_nsec += bytes[j]; } - if (ts->tv_nsec < 1000000000) + if (date->tv_nsec >= 1000000000) { - return 0; + return -1; } - return -1; + return 0; } static int -represent_timespec (char *data, const struct timespec *ts) +ao_cache_entry_timespec_to_bytes (const struct timespec *date, + uint8_t * bytes) { - struct timespec cp = {.tv_sec = ts->tv_sec,.tv_nsec = ts->tv_nsec }; + if (date->tv_nsec >= 1000000000) + { + return -1; + } + uint64_t date_sec = date->tv_sec; + uint32_t date_nsec = date->tv_nsec; for (size_t i = 8; i-- > 0;) { - data[i] = (char) (uint8_t) cp.tv_sec % 256; - cp.tv_sec /= 256; + bytes[i] = date_sec % 256; + date_sec /= 256; } - for (size_t i = 4; i-- > 0;) + for (size_t i = 12; i-- > 8;) { - data[8 + i] = (char) (uint8_t) cp.tv_nsec % 256; - cp.tv_nsec /= 256; + bytes[i] = date_nsec % 256; + date_nsec /= 256; } + return 0; } -MAYBE_UNUSED static int -db_read_cache_entry (const char *db_root, const string_desc_t * id, - struct timespec *request_date, - struct timespec *response_date, bool *invalidated, - string_desc_t * key_id, - string_desc_t * response_header_id, - string_desc_t * response_body_id) +static int +ao_cache_entry_offset_from_bytes (const uint8_t * bytes, size_t *length, + size_t *offset) { - string_desc_t file_data = { 0 }; - request_date->tv_sec = 0; - request_date->tv_nsec = 0; - response_date->tv_sec = 0; - response_date->tv_nsec = 0; - *invalidated = false; - assert (key_id->_data == NULL); - assert (response_header_id->_data == NULL); - assert (response_body_id->_data == NULL); - key_id->_nbytes = 0; - response_header_id->_nbytes = 0; - response_body_id->_nbytes = 0; - int error = db_read (db_root, id, &file_data); - if (error < 0) + *length = 0; + *offset = 0; + for (size_t i = 0; i < 8; i++) { - goto cleanup; + *length *= 256; + *length += bytes[i]; } - if (file_data._nbytes != 16 + 8 + 4 + 8 + 4 + 32 + 32 + 32 + 1) + for (size_t j = 8; j < 16; j++) { - error = -1; - goto cleanup; + *offset *= 256; + *offset += bytes[j]; } - if (memcmp (file_data._data, "disfluid c.entry", 16) != 0) + return 0; +} + +static int +ao_cache_entry_offset_to_bytes (size_t length, size_t offset, uint8_t * bytes) +{ + for (size_t i = 8; i-- > 0;) { - error = -1; - goto cleanup; + bytes[i] = length % 256; + length /= 256; } - const char *data = file_data._data + 16; - error = parse_timespec (data, request_date); - data += 12; - if (error != 0) + for (size_t i = 16; i-- > 8;) { - goto cleanup; + bytes[i] = offset % 256; + offset /= 256; } - error = parse_timespec (data, response_date); - data += 12; - if (error != 0) + return 0; +} + +static int +ao_cache_entry_from_bytes (const uint8_t * bytes, + struct cache_entry_header *entry) +{ + if (ao_cache_entry_timespec_from_bytes (bytes, &(entry->request_date)) < 0) { - goto cleanup; + return -1; } - if (ALLOC_N (key_id->_data, 32) < 0) + bytes += 12; + if (ao_cache_entry_timespec_from_bytes (bytes, &(entry->response_date)) < 0) { - error = -2; - goto cleanup; + return -1; } - key_id->_nbytes = 32; - memcpy (key_id->_data, data, 32); - data += 32; - if (ALLOC_N (response_header_id->_data, 32) < 0) + bytes += 12; + if (ao_cache_entry_offset_from_bytes + (bytes, &(entry->key_size), &(entry->key_offset)) < 0) { - error = -2; - goto cleanup; + return -1; } - response_header_id->_nbytes = 32; - memcpy (response_header_id->_data, data, 32); - data += 32; - if (ALLOC_N (response_body_id->_data, 32) < 0) + bytes += 16; + if (ao_cache_entry_offset_from_bytes + (bytes, &(entry->header_size), &(entry->header_offset)) < 0) { - error = -2; - goto cleanup; + return -1; + } + bytes += 16; + if (ao_cache_entry_offset_from_bytes + (bytes, &(entry->body_size), &(entry->body_offset)) < 0) + { + return -1; } - response_body_id->_nbytes = 32; - memcpy (response_body_id->_data, data, 32); - data += 32; - switch (*data) + bytes += 16; + if (*bytes >= 128) { - case 0: - break; - case 80: - *invalidated = true; - break; - default: - error = -1; - goto cleanup; + entry->invalidated = true; } -cleanup: - if (error != 0) + else { - FREE (key_id->_data); - FREE (response_header_id->_data); - FREE (response_body_id->_data); + entry->invalidated = false; } - FREE (file_data._data); - return error; + return 0; } -MAYBE_UNUSED static int -db_write_cache_entry (const char *db_root, string_desc_t * id, - const struct timespec *request_date, - const struct timespec *response_date, bool invalidated, - const string_desc_t * key_id, - const string_desc_t * response_header_id, - const string_desc_t * response_body_id) +static int +ao_cache_entry_to_bytes (const struct cache_entry_header *header, + uint8_t * dest) { - char file_data[16 + 8 + 4 + 8 + 4 + 32 + 32 + 32 + 1]; - if (key_id->_nbytes != 32 || response_header_id->_nbytes != 32 - || response_body_id->_nbytes != 32) + if (ao_cache_entry_timespec_to_bytes (&(header->request_date), dest) < 0) + { + return -1; + } + dest += 12; + if (ao_cache_entry_timespec_to_bytes (&(header->response_date), dest) < 0) { return -1; } - memcpy (file_data, "disfluid c.entry", 16); - represent_timespec (file_data + 16, request_date); - represent_timespec (file_data + 16 + 12, response_date); - memcpy (file_data + 16 + 12 + 12, key_id->_data, 32); - memcpy (file_data + 16 + 12 + 12 + 32, response_header_id->_data, 32); - memcpy (file_data + 16 + 12 + 12 + 32 + 32, response_body_id->_data, 32); - file_data[16 + 12 + 12 + 32 + 32 + 32] = 0; - if (invalidated) + dest += 12; + if (ao_cache_entry_offset_to_bytes + (header->key_size, header->key_offset, dest) < 0) { - file_data[16 + 12 + 12 + 32 + 32 + 32] = 80; + return -1; } - const string_desc_t sd_data = { - ._nbytes = sizeof (file_data), - ._data = file_data + dest += 16; + if (ao_cache_entry_offset_to_bytes + (header->header_size, header->header_offset, dest) < 0) + { + return -1; + } + dest += 16; + if (ao_cache_entry_offset_to_bytes + (header->body_size, header->body_offset, dest) < 0) + { + return -1; + } + dest += 16; + *dest = 0; + if (header->invalidated) + { + *dest = 128; + } + dest += 1; + for (size_t i = 0; i < 7; i++) + { + dest[i] = 0; + } + return 0; +} + +static int +ao_cache_entry_read (int fd, size_t offset, + struct timespec *request_date, + struct timespec *response_date, + bool *invalidated, + bool read_key, + bool read_response_header, + bool read_response_body, + string_desc_t * key, + string_desc_t * response_header, + string_desc_t * response_body) +{ + struct cache_entry_header header; + uint8_t header_bytes[12 * 2 + 16 * 3 + 1 + 7] = { 0 }; + string_desc_t data = {._nbytes = sizeof (header_bytes),._data = header_bytes }; - return db_write (db_root, id, &sd_data); + key->_data = NULL; + response_header->_data = NULL; + response_body->_data = NULL; + *invalidated = false; + request_date->tv_sec = request_date->tv_nsec = 0; + response_date->tv_sec = response_date->tv_nsec = 0; + if (ao_file_read (fd, offset, data) < 0) + { + return -1; + } + if (ao_cache_entry_from_bytes (header_bytes, &header) < 0) + { + return -1; + } + request_date->tv_sec = header.request_date.tv_sec; + request_date->tv_nsec = header.request_date.tv_nsec; + response_date->tv_sec = header.response_date.tv_sec; + response_date->tv_nsec = header.response_date.tv_nsec; + *invalidated = header.invalidated; + key->_nbytes = header.key_size; + response_header->_nbytes = header.header_size; + response_body->_nbytes = header.body_size; + if (read_key) + { + if (ALLOC_N (key->_data, key->_nbytes) < 0) + { + goto on_error; + } + if (ao_file_read (fd, header.key_offset, *key) < 0) + { + goto on_error; + } + } + if (read_response_header) + { + if (ALLOC_N (response_header->_data, response_header->_nbytes) < 0) + { + goto on_error; + } + if (ao_file_read (fd, header.header_offset, *response_header) < 0) + { + goto on_error; + } + } + if (read_response_body) + { + if (ALLOC_N (response_body->_data, response_body->_nbytes) < 0) + { + goto on_error; + } + if (ao_file_read (fd, header.body_offset, *response_body) < 0) + { + goto on_error; + } + } + return 0; + /* Unsuccessful exit: */ +on_error: + FREE (key->_data); + FREE (response_header->_data); + FREE (response_body->_data); + return -1; } +static int +ao_cache_entry_push (int fd, size_t *offset, + const struct timespec *request_date, + const struct timespec *response_date, + bool invalidated, + const string_desc_t key, + const string_desc_t response_header, + const string_desc_t response_body) +{ + struct cache_entry_header header = { + .request_date = { + .tv_sec = request_date->tv_sec, + .tv_nsec = request_date->tv_nsec}, + .response_date = { + .tv_sec = response_date->tv_sec, + .tv_nsec = response_date->tv_nsec}, + .key_size = key._nbytes, + .header_size = response_header._nbytes, + .body_size = response_body._nbytes, + .invalidated = invalidated + }; + if (ao_file_push_data (fd, key, &(header.key_offset)) < 0) + { + return -1; + } + if (ao_file_push_data (fd, response_header, &(header.header_offset)) < 0) + { + return -1; + } + if (ao_file_push_data (fd, response_body, &(header.body_offset)) < 0) + { + return -1; + } + uint8_t header_bytes[12 * 2 + 16 * 3 + 1 + 7] = { 0 }; + if (ao_cache_entry_to_bytes (&header, header_bytes) < 0) + { + return -1; + } + string_desc_t header_str = { + ._nbytes = sizeof (header_bytes), + ._data = header_bytes + }; + if (ao_file_push_data (fd, header_str, offset) < 0) + { + return -1; + } + return 0; +} #endif /* DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED */ |