From a1bd3ee1f5ecc181dbb542b33c8cf4981fa867f1 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 12 Aug 2008 11:39:35 +0200 Subject: [PATCH] use psplay trees for the filedescriptor registry --- src/backend/filedescriptor.c | 92 ++++++++++++++-------------- src/backend/filedescriptor.h | 4 +- tests/20filedescriptor.tests | 12 ++++ tests/backend/test-filedescriptors.c | 26 ++++++++ 4 files changed, 87 insertions(+), 47 deletions(-) diff --git a/src/backend/filedescriptor.c b/src/backend/filedescriptor.c index fee877dfd..4daa04f3e 100644 --- a/src/backend/filedescriptor.c +++ b/src/backend/filedescriptor.c @@ -21,7 +21,6 @@ #include "lib/mutex.h" #include "lib/safeclib.h" -#include "lib/cuckoo.h" #include "backend/file.h" #include "backend/filedescriptor.h" @@ -42,46 +41,50 @@ NOBUG_DEFINE_FLAG_PARENT (filedescriptor, file_all); This registry stores all acquired filedescriptors for lookup, they will be freed when not referenced anymore. */ -static Cuckoo registry = NULL; +static PSplay registry = NULL; static lumiera_mutex registry_mutex = {PTHREAD_MUTEX_INITIALIZER}; -/* - * setup hashing and compare functions for cuckoo hashing - */ -static size_t -h1 (const void* item, const uint32_t r) -{ - const LumieraFiledescriptor i = *(const LumieraFiledescriptor*)item; - return i->stat.st_dev^i->stat.st_ino^(i->flags&LUMIERA_FILE_MASK) - ^((i->stat.st_dev^i->stat.st_ino^(i->flags&LUMIERA_FILE_MASK))>>7)^r; -} - -static size_t -h2 (const void* item, const uint32_t r) -{ - const LumieraFiledescriptor i = *(const LumieraFiledescriptor*)item; - return i->stat.st_dev^i->stat.st_ino^(i->flags&LUMIERA_FILE_MASK) - ^((i->stat.st_dev^i->stat.st_ino^(i->flags&LUMIERA_FILE_MASK))>>5)^r; -} - -static size_t -h3 (const void* item, const uint32_t r) -{ - const LumieraFiledescriptor i = *(const LumieraFiledescriptor*)item; - return i->stat.st_dev^i->stat.st_ino^(i->flags&LUMIERA_FILE_MASK) - ^((i->stat.st_dev^i->stat.st_ino^(i->flags&LUMIERA_FILE_MASK))>>3)^r; -} - static int -cmp (const void* keya, const void* keyb) +cmp_fn (const void* keya, const void* keyb) { - const LumieraFiledescriptor a = *(const LumieraFiledescriptor*)keya; - const LumieraFiledescriptor b = *(const LumieraFiledescriptor*)keyb; - return a->stat.st_dev == b->stat.st_dev && a->stat.st_ino == b->stat.st_ino - && (a->flags&LUMIERA_FILE_MASK) == (b->flags&LUMIERA_FILE_MASK); + const LumieraFiledescriptor a = (const LumieraFiledescriptor)keya; + const LumieraFiledescriptor b = (const LumieraFiledescriptor)keyb; + + if (a->stat.st_dev < b->stat.st_dev) + return -1; + else if (a->stat.st_dev > b->stat.st_dev) + return 1; + + if (a->stat.st_ino < b->stat.st_ino) + return -1; + else if (a->stat.st_ino > b->stat.st_ino) + return 1; + + if ((a->flags&LUMIERA_FILE_MASK) < (b->flags&LUMIERA_FILE_MASK)) + return -1; + else if ((a->flags&LUMIERA_FILE_MASK) > (b->flags&LUMIERA_FILE_MASK)) + return 1; + + return 0; } + +static void +delete_fn (PSplaynode node) +{ + lumiera_filedescriptor_delete ((LumieraFiledescriptor) node); +} + + +static const void* +key_fn (const PSplaynode node) +{ + return node; +} + + + void lumiera_filedescriptor_registry_init (void) { @@ -89,9 +92,7 @@ lumiera_filedescriptor_registry_init (void) TRACE (filedescriptor); REQUIRE (!registry); - registry = cuckoo_new (h1, h2, h3, cmp, - sizeof (LumieraFiledescriptor), - 3); + registry = psplay_new (cmp_fn, key_fn, delete_fn); if (!registry) LUMIERA_DIE (NO_MEMORY); @@ -103,12 +104,12 @@ void lumiera_filedescriptor_registry_destroy (void) { TRACE (filedescriptor); - REQUIRE (!cuckoo_nelements (registry)); + REQUIRE (!psplay_nelements (registry)); RESOURCE_FORGET (filedescriptor, registry_mutex.rh); if (registry) - cuckoo_free (registry); + psplay_destroy (registry); registry = NULL; } @@ -162,10 +163,9 @@ lumiera_filedescriptor_acquire (const char* name, int flags) } /* lookup/create descriptor */ - dest = &fdesc; - LumieraFiledescriptor* found = cuckoo_find (registry, &dest); + dest = (LumieraFiledescriptor) psplay_find (registry, &fdesc, 100); - if (!found) + if (!dest) { TRACE (filedescriptor, "Descriptor not found"); @@ -173,12 +173,11 @@ lumiera_filedescriptor_acquire (const char* name, int flags) if (!dest) goto error; - cuckoo_insert (registry, &dest); + psplay_insert (registry, &dest->node, 100); } else { TRACE (filedescriptor, "Descriptor already existing"); - dest = *found; ++dest->refcount; } error: ; @@ -191,7 +190,7 @@ lumiera_filedescriptor_acquire (const char* name, int flags) void lumiera_filedescriptor_release (LumieraFiledescriptor self) { - TRACE (filedescriptor); + TRACE (filedescriptor, "%p", self); if (!--self->refcount) lumiera_filedescriptor_delete (self); } @@ -203,6 +202,7 @@ lumiera_filedescriptor_new (LumieraFiledescriptor template) LumieraFiledescriptor self = lumiera_malloc (sizeof (lumiera_filedescriptor)); TRACE (filedescriptor, "at %p", self); + psplaynode_init (&self->node); self->stat = template->stat; self->flags = template->flags; @@ -224,7 +224,7 @@ lumiera_filedescriptor_delete (LumieraFiledescriptor self) { REQUIRE (self->refcount == 0); - cuckoo_remove (registry, cuckoo_find (registry, &self)); + psplay_remove (registry, &self->node); TODO ("destruct other members (WIP)"); diff --git a/src/backend/filedescriptor.h b/src/backend/filedescriptor.h index 668419b10..d91296956 100644 --- a/src/backend/filedescriptor.h +++ b/src/backend/filedescriptor.h @@ -23,6 +23,7 @@ #define LUMIERA_FILEDESCRIPTOR_H #include "lib/mutex.h" +#include "lib/psplay.h" #include @@ -47,7 +48,8 @@ typedef lumiera_filedescriptor* LumieraFiledescriptor; struct lumiera_filedescriptor_struct { - struct stat stat; /* create after first open, maintained metadata, MUST BE FIRST! */ + psplaynode node; /* node for the lookup tree */ + struct stat stat; /* create after first open, maintained metadata */ int flags; /* open flags, must be masked for reopen */ lumiera_mutex lock; /* locks operations on this file descriptor */ unsigned refcount; /* reference counter, all users sans registry */ diff --git a/tests/20filedescriptor.tests b/tests/20filedescriptor.tests index 78639e7b8..03d6fb2ac 100644 --- a/tests/20filedescriptor.tests +++ b/tests/20filedescriptor.tests @@ -13,6 +13,18 @@ END rm ,tmp_testfile +echo testdata > ,tmp_testfile1 +echo testdata > ,tmp_testfile2 +echo testdata > ,tmp_testfile3 + +TEST "acquire 3 files" acquire_existing_3files <