summaryrefslogtreecommitdiff
path: root/src/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache.c')
-rw-r--r--src/cache.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/cache.c b/src/cache.c
new file mode 100644
index 0000000..6a31a16
--- /dev/null
+++ b/src/cache.c
@@ -0,0 +1,74 @@
+/*
+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 cache_hash(uint32_t ipv4)
+{
+ // FIXME: Use an academically acclaimed hashing algorithm.
+ return (((ipv4 >> 16) ^ ipv4) * 3137) & HASH_MAX;
+}
+
+static cache_entry_t *cache_ht[HASH_MAX];
+static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Returns an entry with its mutex locked.
+cache_entry_t *cache_find(uint32_t ipv4)
+{
+ cache_entry_t *entry;
+ size_t hash;
+
+ hash = cache_hash(ipv4);
+
+ pthread_mutex_lock(&cache_mutex);
+ eli_for (entry, cache_ht[hash], ht_list)
+ if (entry->ipv4 == ipv4)
+ break;
+
+ if (!entry) {
+ entry = calloc(1, sizeof(cache_entry_t));
+ entry->ipv4 = ipv4;
+ pthread_mutex_init(&entry->mutex, NULL);
+ eli_append(cache_ht + hash, entry, ht_list);
+ }
+
+ pthread_mutex_lock(&entry->mutex);
+ pthread_mutex_unlock(&cache_mutex);
+
+ return entry;
+}
+
+void cache_destroy(void)
+{
+ size_t i;
+ cache_entry_t *entry, *next;
+
+ for (i = 0; i < HASH_MAX; i++) {
+ for (entry = cache_ht[i]; entry; entry = next) {
+ next = entry->ht_list.next;
+
+ free(entry->revdns);
+ free(entry->whois);
+ free(entry);
+ }
+
+ cache_ht[i] = NULL;
+ }
+}