summaryrefslogtreecommitdiff
path: root/packet_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet_storage.c')
-rw-r--r--packet_storage.c236
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(&current_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(&current_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