summaryrefslogtreecommitdiff
path: root/src/packet_storage.c
diff options
context:
space:
mode:
authorGravatar moon <moon@coffin.ir> 2025-09-13 23:13:07 +0330
committerGravatar moon <moon@coffin.ir> 2025-09-13 23:13:07 +0330
commit81440f9a4e2d8d105bade578bc1e11ec6780ca81 (patch)
tree5f5957256a61a7b604afd9c614bba42cbdedd108 /src/packet_storage.c
parentnew things (diff)
feature impls + directories
Diffstat (limited to 'src/packet_storage.c')
-rw-r--r--src/packet_storage.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/packet_storage.c b/src/packet_storage.c
new file mode 100644
index 0000000..1094afd
--- /dev/null
+++ b/src/packet_storage.c
@@ -0,0 +1,233 @@
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+// dependency: zlib
+#include <zlib.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)
+
+struct data_packet* load_packet(FILE* file) {
+ if (!file) { return NULL; }
+
+ fseek(file, 0, SEEK_END);
+ size_t file_size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ if (file_size == 0) {
+ fclose(file);
+ return NULL;
+ }
+
+ byte comp_buf[ file_size ];
+
+ size_t r = fread(comp_buf, 1, file_size, file);
+ fclose(file);
+ if (r != file_size) { return NULL; }
+
+ byte buffer[ PACKET_SIZE ];
+
+ uLongf dest_len = (uLongf) PACKET_SIZE;
+ int unres = uncompress(buffer, &dest_len, comp_buf, (uLongf) file_size);
+
+ if (unres != Z_OK || dest_len != (uLongf) PACKET_SIZE) { return NULL; }
+
+ bool success;
+ struct data_packet* packet = malloc(sizeof(struct data_packet));
+ if (!packet) { return NULL; }
+ *packet = s2data_packet(PACKET_SIZE, buffer, &success);
+
+ 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(const 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);
+ char filename[ 128 ];
+ sprintf(filename, "packets/" hash_fmt ".bin", hash_ref(_hash));
+ FILE* file = fopen(filename, "rb");
+
+ struct data_packet* packet = load_packet(file);
+
+ if (packet) {
+ uint64_t add_idx = set_data_packet(packet);
+ if (add_idx != minus_one) {
+ free(packet);
+ return &packet_storage[ add_idx ];
+ } else {
+ static __thread struct data_packet_entry temp_entry;
+ temp_entry.packet = *packet;
+ free(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;
+}