summaryrefslogtreecommitdiff
path: root/src/database.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/database.c b/src/database.c
new file mode 100644
index 0000000..c42cfb6
--- /dev/null
+++ b/src/database.c
@@ -0,0 +1,94 @@
+/*
+Copyright (C) 2017 Paweł Redman
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 3
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "shared.h"
+
+#define HASH_MAX 4095
+
+static size_t db_hash(uint32_t ipv4)
+{
+ // FIXME: Use an academically acclaimed hashing algorithm.
+ return (((ipv4 >> 16) ^ ipv4) * 3137) & HASH_MAX;
+}
+
+db_entry *database[HASH_MAX];
+pthread_mutex_t database_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Returns a pointer to the relevant db_entry (newly created if didn't exist).
+// This function locks the db_entry's mutex before returning.
+// Returns NULL if calloc fails.
+db_entry *db_find(uint32_t ipv4)
+{
+ size_t hash;
+ db_entry *entry;
+
+ hash = db_hash(ipv4);
+
+ pthread_mutex_lock(&database_mutex);
+ eli_for (entry, database[hash], ht_chain)
+ if (entry->ipv4 == ipv4)
+ break;
+
+ if (!entry) {
+ entry = calloc(1, sizeof(db_entry));
+ if (!entry)
+ goto out;
+ entry->ipv4 = ipv4;
+ pthread_mutex_init(&entry->mutex, NULL);
+ eli_append(database + hash, entry, ht_chain);
+ }
+
+ pthread_mutex_lock(&entry->mutex);
+out:
+ pthread_mutex_unlock(&database_mutex);
+ return entry;
+}
+
+static void destroy_entry(db_entry *entry)
+{
+ job_t *job, *next;
+
+ for (job = entry->waiting_jobs; job; job = next) {
+ next = job->waiting_list.next;
+ job_destroy(job);
+ }
+}
+
+// Frees all entries and resets the database.
+void db_destroy(void)
+{
+ size_t i;
+ db_entry *entry, *next;
+
+ pthread_mutex_lock(&database_mutex);
+
+ for (i = 0; i < HASH_MAX; i++) {
+ for (entry = database[i]; entry; entry = next) {
+ next = entry->ht_chain.next;
+
+ free(entry->revdns.data);
+ free(entry->whois.data);
+ destroy_entry(entry);
+ }
+
+ database[i] = NULL;
+ }
+
+ pthread_mutex_unlock(&database_mutex);
+}
+