diff options
Diffstat (limited to 'packet_storage.c')
| -rw-r--r-- | packet_storage.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/packet_storage.c b/packet_storage.c new file mode 100644 index 0000000..e618490 --- /dev/null +++ b/packet_storage.c @@ -0,0 +1,236 @@ +#include <pthread.h> +#include <stdint.h> +#include <stdlib.h> +// +#include "common.c" + +const uint64_t max_storage = 1 << 16; + +#define hash_fmt \ + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \ + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + +#define hash_ref(_hash) \ + _hash[ 0 ], _hash[ 1 ], _hash[ 2 ], _hash[ 3 ], _hash[ 4 ], _hash[ 5 ], _hash[ 6 ], \ + _hash[ 7 ], _hash[ 8 ], _hash[ 9 ], _hash[ 10 ], _hash[ 11 ], _hash[ 12 ], _hash[ 13 ], \ + _hash[ 14 ], _hash[ 15 ], _hash[ 16 ], _hash[ 17 ], _hash[ 18 ], _hash[ 19 ], _hash[ 20 ], \ + _hash[ 21 ], _hash[ 22 ], _hash[ 23 ], _hash[ 24 ], _hash[ 25 ], _hash[ 26 ], _hash[ 27 ], \ + _hash[ 28 ], _hash[ 29 ], _hash[ 30 ], _hash[ 31 ] + +uint64_t current_packet_ptr = 0; +uint64_t packet_count = 0; +struct data_packet_entry { + struct data_packet packet; + uint64_t next; + uint64_t prev; + bool is_full; +}* packet_storage; + +// TODO: yes, i know it's weird, but this has to be zero +#define minus_one (uint64_t) 0 + +pthread_mutex_t packet_storage_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct data_packet* load_packet(const hash packet_hash) { + char filename[ 128 ]; + sprintf(filename, "packets/" hash_fmt ".bin", hash_ref(packet_hash)); + + FILE* file = fopen(filename, "rb"); + if (!file) { return NULL; } + + fseek(file, 0, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0, SEEK_SET); + + if (file_size != PACKET_SIZE) { + fclose(file); + return NULL; + } + + byte* buffer = malloc(file_size); + if (!buffer) { + fclose(file); + return NULL; + } + + size_t r = fread(buffer, 1, file_size, file); + fclose(file); + if (r != file_size) { + free(buffer); + return NULL; + } + + bool success; + struct data_packet* packet = malloc(sizeof(struct data_packet)); + if (!packet) { + free(buffer); + return NULL; + } + *packet = s2data_packet(file_size, buffer, &success); + free(buffer); + + if (!success) { + free(packet); + return NULL; + } + + return packet; +} + +uint64_t set_data_packet(struct data_packet* new_packet); + +struct data_packet_entry* get_data_packet(hash _hash) { + uint64_t hash_val; + memcpy(&hash_val, _hash, sizeof(uint64_t)); + uint64_t cur_index = hash_val % max_storage; + + pthread_mutex_lock(&packet_storage_mutex); + + struct data_packet_entry* current_entry = &packet_storage[ cur_index ]; + while (cur_index != minus_one) { + if (current_entry->is_full + && memcmp(current_entry->packet.hash, _hash, sizeof(hash)) == 0) { + pthread_mutex_unlock(&packet_storage_mutex); + return current_entry; + } + + cur_index = current_entry->next; + if (cur_index != minus_one) { current_entry = &packet_storage[ cur_index ]; } + } + + pthread_mutex_unlock(&packet_storage_mutex); + struct data_packet* packet = load_packet(_hash); + + if (packet) { + uint64_t add_idx = set_data_packet(packet); + + if (add_idx != minus_one) { + return &packet_storage[ add_idx ]; + } else { + static struct data_packet_entry temp_entry; + temp_entry.packet = *packet; + return &temp_entry; + } + } + + return NULL; +} + +uint64_t set_data_packet(struct data_packet* new_packet) { + pthread_mutex_lock(&packet_storage_mutex); + + uint64_t hash_val; + memcpy(&hash_val, new_packet->hash, sizeof(uint64_t)); + uint64_t start_index = hash_val % max_storage; + uint64_t cur_index = start_index; + + struct data_packet_entry* current_entry = &packet_storage[ cur_index ]; + + while (true) { + if (current_entry->is_full + && memcmp(current_entry->packet.hash, new_packet->hash, sizeof(hash)) == 0) { + memcpy(¤t_entry->packet, new_packet, sizeof(struct data_packet)); + pthread_mutex_unlock(&packet_storage_mutex); + return cur_index; + } + + if (current_entry->next == minus_one) break; + cur_index = current_entry->next; + current_entry = &packet_storage[ cur_index ]; + } + + if (!current_entry->is_full) { + memcpy(¤t_entry->packet, new_packet, sizeof(struct data_packet)); + current_entry->is_full = true; + current_entry->next = minus_one; + current_entry->prev = minus_one; + packet_count++; + pthread_mutex_unlock(&packet_storage_mutex); + return cur_index; + } + + uint64_t probes = 0; + uint64_t linear_probe_index = (cur_index + 1) % max_storage; + + while (probes < max_storage) { + struct data_packet_entry* empty_slot = &packet_storage[ linear_probe_index ]; + + if (!empty_slot->is_full) { + memcpy(&empty_slot->packet, new_packet, sizeof(struct data_packet)); + empty_slot->is_full = true; + empty_slot->next = minus_one; + empty_slot->prev = cur_index; + current_entry->next = linear_probe_index; + packet_count++; + pthread_mutex_unlock(&packet_storage_mutex); + return linear_probe_index; + } + + linear_probe_index = (linear_probe_index + 1) % max_storage; + probes++; + } + + // table full + pthread_mutex_unlock(&packet_storage_mutex); + return minus_one; +} + +#define overload __attribute__((overloadable)) + +bool _delete_at_index(uint64_t index); + +overload void delete_data_packet(hash _hash) { + pthread_mutex_lock(&packet_storage_mutex); + + uint64_t hash_val; + memcpy(&hash_val, _hash, sizeof(uint64_t)); + uint64_t start_index = hash_val % max_storage; + uint64_t cur_index = start_index; + + while (cur_index != minus_one) { + struct data_packet_entry* current_entry = &packet_storage[ cur_index ]; + if (current_entry->is_full + && memcmp(current_entry->packet.hash, _hash, sizeof(hash)) == 0) { + _delete_at_index(cur_index); + pthread_mutex_unlock(&packet_storage_mutex); + return; + } + + if (current_entry->next == minus_one) { + pthread_mutex_unlock(&packet_storage_mutex); + return; + } + cur_index = current_entry->next; + } + + pthread_mutex_unlock(&packet_storage_mutex); +} + +overload void delete_data_packet(uint64_t index) { + pthread_mutex_lock(&packet_storage_mutex); + _delete_at_index(index); + pthread_mutex_unlock(&packet_storage_mutex); +} + +// caller must already have a lock! +bool _delete_at_index(uint64_t index) { + if (index >= max_storage) return false; + struct data_packet_entry* current_entry = &packet_storage[ index ]; + if (!current_entry->is_full) return false; + + if (current_entry->prev != minus_one) { + struct data_packet_entry* prev_entry = &packet_storage[ current_entry->prev ]; + prev_entry->next = current_entry->next; + } + + if (current_entry->next != minus_one) { + struct data_packet_entry* next_entry = &packet_storage[ current_entry->next ]; + next_entry->prev = current_entry->prev; + } + + current_entry->is_full = false; + current_entry->next = minus_one; + current_entry->prev = minus_one; + + return true; +}
\ No newline at end of file |
