diff options
Diffstat (limited to 'src/database.c')
-rw-r--r-- | src/database.c | 94 |
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); +} + |