use psplay trees for the filedescriptor registry

This commit is contained in:
Christian Thaeter 2008-08-12 11:39:35 +02:00
parent c3e2941eb8
commit a1bd3ee1f5
4 changed files with 87 additions and 47 deletions

View file

@ -21,7 +21,6 @@
#include "lib/mutex.h" #include "lib/mutex.h"
#include "lib/safeclib.h" #include "lib/safeclib.h"
#include "lib/cuckoo.h"
#include "backend/file.h" #include "backend/file.h"
#include "backend/filedescriptor.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. 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}; 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 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 a = (const LumieraFiledescriptor)keya;
const LumieraFiledescriptor b = *(const LumieraFiledescriptor*)keyb; 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); 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 void
lumiera_filedescriptor_registry_init (void) lumiera_filedescriptor_registry_init (void)
{ {
@ -89,9 +92,7 @@ lumiera_filedescriptor_registry_init (void)
TRACE (filedescriptor); TRACE (filedescriptor);
REQUIRE (!registry); REQUIRE (!registry);
registry = cuckoo_new (h1, h2, h3, cmp, registry = psplay_new (cmp_fn, key_fn, delete_fn);
sizeof (LumieraFiledescriptor),
3);
if (!registry) if (!registry)
LUMIERA_DIE (NO_MEMORY); LUMIERA_DIE (NO_MEMORY);
@ -103,12 +104,12 @@ void
lumiera_filedescriptor_registry_destroy (void) lumiera_filedescriptor_registry_destroy (void)
{ {
TRACE (filedescriptor); TRACE (filedescriptor);
REQUIRE (!cuckoo_nelements (registry)); REQUIRE (!psplay_nelements (registry));
RESOURCE_FORGET (filedescriptor, registry_mutex.rh); RESOURCE_FORGET (filedescriptor, registry_mutex.rh);
if (registry) if (registry)
cuckoo_free (registry); psplay_destroy (registry);
registry = NULL; registry = NULL;
} }
@ -162,10 +163,9 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
} }
/* lookup/create descriptor */ /* lookup/create descriptor */
dest = &fdesc; dest = (LumieraFiledescriptor) psplay_find (registry, &fdesc, 100);
LumieraFiledescriptor* found = cuckoo_find (registry, &dest);
if (!found) if (!dest)
{ {
TRACE (filedescriptor, "Descriptor not found"); TRACE (filedescriptor, "Descriptor not found");
@ -173,12 +173,11 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
if (!dest) if (!dest)
goto error; goto error;
cuckoo_insert (registry, &dest); psplay_insert (registry, &dest->node, 100);
} }
else else
{ {
TRACE (filedescriptor, "Descriptor already existing"); TRACE (filedescriptor, "Descriptor already existing");
dest = *found;
++dest->refcount; ++dest->refcount;
} }
error: ; error: ;
@ -191,7 +190,7 @@ lumiera_filedescriptor_acquire (const char* name, int flags)
void void
lumiera_filedescriptor_release (LumieraFiledescriptor self) lumiera_filedescriptor_release (LumieraFiledescriptor self)
{ {
TRACE (filedescriptor); TRACE (filedescriptor, "%p", self);
if (!--self->refcount) if (!--self->refcount)
lumiera_filedescriptor_delete (self); lumiera_filedescriptor_delete (self);
} }
@ -203,6 +202,7 @@ lumiera_filedescriptor_new (LumieraFiledescriptor template)
LumieraFiledescriptor self = lumiera_malloc (sizeof (lumiera_filedescriptor)); LumieraFiledescriptor self = lumiera_malloc (sizeof (lumiera_filedescriptor));
TRACE (filedescriptor, "at %p", self); TRACE (filedescriptor, "at %p", self);
psplaynode_init (&self->node);
self->stat = template->stat; self->stat = template->stat;
self->flags = template->flags; self->flags = template->flags;
@ -224,7 +224,7 @@ lumiera_filedescriptor_delete (LumieraFiledescriptor self)
{ {
REQUIRE (self->refcount == 0); REQUIRE (self->refcount == 0);
cuckoo_remove (registry, cuckoo_find (registry, &self)); psplay_remove (registry, &self->node);
TODO ("destruct other members (WIP)"); TODO ("destruct other members (WIP)");

View file

@ -23,6 +23,7 @@
#define LUMIERA_FILEDESCRIPTOR_H #define LUMIERA_FILEDESCRIPTOR_H
#include "lib/mutex.h" #include "lib/mutex.h"
#include "lib/psplay.h"
#include <sys/types.h> #include <sys/types.h>
@ -47,7 +48,8 @@ typedef lumiera_filedescriptor* LumieraFiledescriptor;
struct lumiera_filedescriptor_struct 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 */ int flags; /* open flags, must be masked for reopen */
lumiera_mutex lock; /* locks operations on this file descriptor */ lumiera_mutex lock; /* locks operations on this file descriptor */
unsigned refcount; /* reference counter, all users sans registry */ unsigned refcount; /* reference counter, all users sans registry */

View file

@ -13,6 +13,18 @@ END
rm ,tmp_testfile rm ,tmp_testfile
echo testdata > ,tmp_testfile1
echo testdata > ,tmp_testfile2
echo testdata > ,tmp_testfile3
TEST "acquire 3 files" acquire_existing_3files <<END
return: 0
END
rm ,tmp_testfile1
rm ,tmp_testfile2
rm ,tmp_testfile3
TEST "acquire file, creating it" acquire_create <<END TEST "acquire file, creating it" acquire_create <<END
return: 0 return: 0
END END

View file

@ -57,6 +57,32 @@ TEST ("acquire_existing_again")
return 1; return 1;
} }
TEST ("acquire_existing_3files")
{
lumiera_backend_init ();
LumieraFiledescriptor descriptor1 = lumiera_filedescriptor_acquire (",tmp_testfile1", LUMIERA_FILE_READONLY);
LumieraFiledescriptor descriptor2 = lumiera_filedescriptor_acquire (",tmp_testfile2", LUMIERA_FILE_READONLY);
LumieraFiledescriptor descriptor3 = lumiera_filedescriptor_acquire (",tmp_testfile3", LUMIERA_FILE_READONLY);
if (descriptor1)
lumiera_filedescriptor_release (descriptor1);
if (descriptor2)
lumiera_filedescriptor_release (descriptor2);
if (descriptor3)
lumiera_filedescriptor_release (descriptor3);
if (descriptor1 && descriptor2 && descriptor3)
{
lumiera_backend_destroy ();
return 0;
}
else
return 1;
}
TEST ("acquire_create") TEST ("acquire_create")
{ {
lumiera_backend_init (); lumiera_backend_init ();