Merge ct/devel to see if there are any problems...

This commit is contained in:
Fischlurch 2008-05-20 04:58:16 +02:00
commit 6310e9789b
62 changed files with 4258 additions and 411 deletions

View file

@ -33,6 +33,8 @@ SUBDIRS =
include $(top_srcdir)/admin/Makefile.am
# core
include $(top_srcdir)/src/proc/Makefile.am
include $(top_srcdir)/src/common/Makefile.am
include $(top_srcdir)/src/lib/Makefile.am
include $(top_srcdir)/src/backend/Makefile.am
@ -40,6 +42,8 @@ include $(top_srcdir)/src/backend/Makefile.am
#include $(top_srcdir)/src...
# tests
include $(top_srcdir)/tests/common/Makefile.am
include $(top_srcdir)/tests/components/Makefile.am
include $(top_srcdir)/tests/Makefile.am
include $(top_srcdir)/tests/plugin/Makefile.am

View file

@ -18,7 +18,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define _GNU_SOURCE
/*
just place any problematic calls where valgrind whines about in main (with comments please)

View file

@ -23,6 +23,8 @@ AC_COPYRIGHT([
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
])
AC_GNU_SOURCE
#
# Required programs
#
@ -37,11 +39,12 @@ AC_PROG_LIBTOOL
# test for headers
#
AC_STDC_HEADERS
AC_CHECK_HEADER([nobug.h], AC_DEFINE(HAVE_NOBUG_H))
AC_CHECK_HEADER([execinfo.h], AC_DEFINE(HAVE_EXECINFO_H))
# there is a warning in nobug, disabled til fixed AC_CHECK_HEADER([valgrind/valgrind.h], AC_DEFINE(HAVE_VALGRIND_VALGRIND_H))
ACX_PTHREAD
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
##AM_CONDITIONAL([HAVE_THREADING], [test x"$acx_pthread_ok" = xyes])
@ -71,9 +74,62 @@ AC_ARG_ENABLE(release, AC_HELP_STRING([--enable-release], [select NoBug RELEASE
nobug_level=alpha
AC_DEFINE(EBUG_ALPHA)
)])])
AC_MSG_RESULT([NoBug build level: $nobug_level])
# END NoBug
# C headers and libraries
AC_LANG_PUSH([C])
AC_CHECK_HEADER([nobug.h],
AC_DEFINE(HAVE_NOBUG_H),
AC_MSG_ERROR([NoBug header missing (http://www.pipapo.org/pipawiki/NoBug)])
)
AC_CHECK_LIB([nobugmt], nobug_thread_id_get,
,
AC_MSG_ERROR([NoBug multithreading library missing (http://www.pipapo.org/pipawiki/NoBug)])
)
AC_CHECK_HEADER([execinfo.h], AC_DEFINE(HAVE_EXECINFO_H))
# there is a warning in nobug, disabled til fixed AC_CHECK_HEADER([valgrind/valgrind.h], AC_DEFINE(HAVE_VALGRIND_VALGRIND_H))
AC_LANG_POP([C])
# C++ headers and libraries
AC_LANG_PUSH([C++])
AC_CHECK_HEADER([tr1/memory],
,
AC_MSG_ERROR([std::tr1 proposed standard extension for shared_ptr missing])
)
AC_CHECK_HEADER([boost/shared_ptr.hpp],
,
AC_MSG_ERROR([boost::shared_ptr missing (http://www.boost.org/)])
)
AC_CHECK_HEADER([boost/program_options.hpp],
,
AC_MSG_ERROR([boost::program_options missing (http://www.boost.org/)])
)
# checking for library left out, name contains compiler version here (libboost_program_options-gcc42-mt-1_34_1.so.1.34.1) any ides how to use that?
AC_CHECK_HEADER([boost/regex.hpp],
,
AC_MSG_ERROR([boost::regex missing (http://www.boost.org/)])
)
AC_LANG_POP([C++])
# Print a summary
AC_MSG_RESULT([
Configuration Summary:])
AC_MSG_RESULT([ NoBug build level: $nobug_level])
# Add more summary results here
AC_MSG_RESULT([
Configuration complete, you can now build Lumiera with 'make'
])
AC_CONFIG_FILES(Makefile)
AC_OUTPUT

View file

@ -21,17 +21,20 @@ noinst_LIBRARIES += liblumibackend.a
liblumibackend_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
liblumibackend_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumibackend_a_SOURCES = \
$(liblumibackend_a_srcdir)/backend.c \
$(liblumibackend_a_srcdir)/file.c \
$(liblumibackend_a_srcdir)/filehandle.c \
$(liblumibackend_a_srcdir)/filedescriptor.c \
liblumibackend_a_SOURCES = \
$(liblumibackend_a_srcdir)/mediaaccessfacade.cpp \
$(liblumibackend_a_srcdir)/backend.c \
$(liblumibackend_a_srcdir)/file.c \
$(liblumibackend_a_srcdir)/filehandle.c \
$(liblumibackend_a_srcdir)/filedescriptor.c \
$(liblumibackend_a_srcdir)/filehandlecache.c
noinst_HEADERS += \
$(liblumibackend_a_srcdir)/backend.h \
$(liblumibackend_a_srcdir)/file.h \
$(liblumibackend_a_srcdir)/filehandle.h \
$(liblumibackend_a_srcdir)/filedescriptor.h \
noinst_HEADERS += \
$(liblumibackend_a_srcdir)/mediaaccessfacade.cpp \
$(liblumibackend_a_srcdir)/backend.h \
$(liblumibackend_a_srcdir)/file.h \
$(liblumibackend_a_srcdir)/filehandle.h \
$(liblumibackend_a_srcdir)/filedescriptor.h \
$(liblumibackend_a_srcdir)/filehandlecache.h

53
src/backend/backend.c Normal file
View file

@ -0,0 +1,53 @@
/*
backend - common lumiera backend things
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "backend/backend.h"
#include "backend/filehandlecache.h"
#include "backend/filedescriptor.h"
//NOBUG_DEFINE_FLAG_PARENT (backend, lumiera); TODO
NOBUG_DEFINE_FLAG (backend);
NOBUG_DEFINE_FLAG_PARENT (file_all, backend);
int
lumiera_backend_init (void)
{
NOBUG_INIT_FLAG (backend);
NOBUG_INIT_FLAG (file_all);
NOBUG_INIT_FLAG (file);
TRACE (backend);
lumiera_filedescriptor_registry_init ();
int max_entries = 10; TODO("determine by sysconf (_SC_OPEN_MAX) minus some (big) safety margin "
"add some override to run tests with few filehandles");
lumiera_filehandlecache_new (max_entries);
return 0;
}
void
lumiera_backend_destroy (void)
{
TRACE (backend);
lumiera_filedescriptor_registry_destroy ();
lumiera_filehandlecache_delete ();
}

36
src/backend/backend.h Normal file
View file

@ -0,0 +1,36 @@
/*
backend - common lumiera backend things
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_BACKEND_H
#define LUMIERA_BACKEND_H
#include <nobug.h>
NOBUG_DECLARE_FLAG (backend);
NOBUG_DECLARE_FLAG (file_all);
NOBUG_DECLARE_FLAG (file);
int
lumiera_backend_init (void);
void
lumiera_backend_destroy (void);
#endif

130
src/backend/file.c Normal file
View file

@ -0,0 +1,130 @@
/*
file.c - file handling
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/mutex.h"
#include "lib/safeclib.h"
#include "backend/file.h"
#include "backend/filehandlecache.h"
#include "backend/filedescriptor.h"
#include <limits.h>
#include <unistd.h>
NOBUG_DEFINE_FLAG_PARENT (file, file_all);
LUMIERA_ERROR_DEFINE(FILE_CHANGED, "File changed unexpected");
LumieraFile
lumiera_file_init (LumieraFile self, const char* name, int flags)
{
TRACE (file);
if (!(self->descriptor = lumiera_filedescriptor_acquire (name, flags)))
return NULL;
self->name = lumiera_strndup (name, PATH_MAX);
return self;
}
LumieraFile
lumiera_file_destroy (LumieraFile self)
{
TRACE (file);
lumiera_filedescriptor_release (self->descriptor);
free ((void*)self->name);
return self;
}
LumieraFile
lumiera_file_new (const char* name, int flags)
{
TRACE (file);
LumieraFile self = lumiera_malloc (sizeof (lumiera_file));
return lumiera_file_init (self, name, flags);
}
void
lumiera_file_delete (LumieraFile self)
{
TRACE (file);
free (lumiera_file_destroy (self));
}
int
lumiera_file_handle_acquire (LumieraFile self)
{
TRACE (file);
REQUIRE (self);
REQUIRE (self->descriptor);
REQUIRE (lumiera_fhcache);
LUMIERA_MUTEX_SECTION (file, self->descriptor->rh, &self->descriptor->lock)
{
if (!self->descriptor->handle)
/* no handle yet, get a new one */
lumiera_filehandlecache_handle_acquire (lumiera_fhcache, self->descriptor);
else
lumiera_filehandlecache_checkout (lumiera_fhcache, self->descriptor->handle);
if (self->descriptor->handle->fd == -1)
{
int fd;
fd = open (self->name, self->descriptor->flags & LUMIERA_FILE_MASK);
if (fd == -1)
{
LUMIERA_ERROR_SET (file, ERRNO);
}
else
{
struct stat st;
if (fstat (fd, &st) == -1)
{
close (fd);
LUMIERA_ERROR_SET (file, ERRNO);
}
else if (self->descriptor->stat.st_dev != st.st_dev || self->descriptor->stat.st_ino != st.st_ino)
{
close (fd);
/* Woops this is not the file we expected to use */
LUMIERA_ERROR_SET (file, FILE_CHANGED);
}
}
self->descriptor->handle->fd = fd;
}
}
return self->descriptor->handle->fd;
}
void
lumiera_file_handle_release (LumieraFile self)
{
TRACE (file);
LUMIERA_MUTEX_SECTION (file, self->descriptor->rh, &self->descriptor->lock)
{
lumiera_filehandlecache_checkin (lumiera_fhcache, self->descriptor->handle);
}
}

123
src/backend/file.h Normal file
View file

@ -0,0 +1,123 @@
/*
file.h - interface to files by filename
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_FILE_H
#define LUMIERA_FILE_H
#include "lib/mutex.h"
#include "lib/llist.h"
#include "lib/error.h"
NOBUG_DECLARE_FLAG (file);
LUMIERA_ERROR_DECLARE(FILE_CHANGED);
/**
* @file
* File management
* Handling Files is splitted into different classes:
* 1. The 'lumiera_file' class which acts as interface to the outside for managing files.
* 'lumiera_file' is addressed by the name of the file. Since files can have more than one name (hardlinks)
* many 'lumiera_file' can point to a single 'lumiera_filedescriptor'
* 2. The 'lumiera_filedescriptor' class which does the real work managing the file in the back.
* 3. Since OS-filehandles are a limited resource we access the lazily as 'lumiera_filehandle' which are
* managed in a 'lumiera_filehandlecache'
*/
typedef struct lumiera_file_struct lumiera_file;
typedef lumiera_file* LumieraFile;
#include "backend/filehandle.h"
#include "backend/filedescriptor.h"
#define LUMIERA_FILE_READONLY (O_RDONLY | O_LARGEFILE | O_NOATIME)
#define LUMIERA_FILE_READWRITE (O_RDWR | O_LARGEFILE | O_NOATIME)
#define LUMIERA_FILE_CREATE (O_RDWR | O_LARGEFILE | O_NOATIME | O_CREAT | O_EXCL)
#define LUMIERA_FILE_RECREATE (O_RDWR | O_LARGEFILE | O_NOATIME | O_CREAT | O_TRUNC)
/* creat and excl flags will be masked out for descriptor lookup */
#define LUMIERA_FILE_MASK ~(O_CREAT | O_EXCL | O_TRUNC)
struct lumiera_file_struct
{
const char* name;
LumieraFiledescriptor descriptor;
};
/**
* Initialize a file structure.
* @param self pointer to the file structure
* @param name filename
* @param flags open flags
* @return self
*/
LumieraFile
lumiera_file_init (LumieraFile self, const char* name, int flags);
/**
* Destroy a file structure.
* frees all associated resources, releases the filedescriptor etc.
* @param self file structure to be destroyed
* @return self
*/
LumieraFile
lumiera_file_destroy (LumieraFile self);
/**
* Allocate a new file structure.
* @param name filename
* @param flags open flags
* @return new file structure
*/
LumieraFile
lumiera_file_new (const char* name, int flags);
/**
* Frees a file structure.
* @param self file structure to be freed
*/
void
lumiera_file_delete (LumieraFile self);
/**
* Get a POSIX filehandle for a file.
* Filehandles are opened on demand and must be acquired for use.
* Using filehandles is refcounted and might be nested.
* After using them they must be released which puts them back into filehandlecache aging.
* @param self file structure
* @return POSIX filehandle or -1 on error, check lumiera_error() to retrieve the errorcode
* Currently only LUMIERA_ERROR_ERRNO will be raised but this might change in future.
* Opening files can fail for many reasons and at any time!
*/
int
lumiera_file_handle_acquire (LumieraFile self);
/**
* Put filehandle back into cache aging.
* @param self file which handle to be released
*/
void
lumiera_file_handle_release (LumieraFile self);
#endif

View file

@ -0,0 +1,240 @@
/*
filedescriptor.c - file handling
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/mutex.h"
#include "lib/safeclib.h"
#include "lib/cuckoo.h"
#include "backend/file.h"
#include "backend/filedescriptor.h"
#include "backend/filehandle.h"
#include "backend/filehandlecache.h"
#include <sys/types.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
NOBUG_DEFINE_FLAG_PARENT (filedescriptor, file_all);
/*
Filedescriptor registry
This registry stores all acquired filedescriptors for lookup, they will be freed when not referenced anymore.
*/
static Cuckoo 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)
{
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);
}
void
lumiera_filedescriptor_registry_init (void)
{
NOBUG_INIT_FLAG (filedescriptor);
TRACE (filedescriptor);
REQUIRE (!registry);
registry = cuckoo_new (h1, h2, h3, cmp,
sizeof (LumieraFiledescriptor),
3);
if (!registry)
LUMIERA_DIE (NO_MEMORY);
}
void
lumiera_filedescriptor_registry_destroy (void)
{
TRACE (filedescriptor);
REQUIRE (!cuckoo_nelements (registry));
if (registry)
cuckoo_free (registry);
registry = NULL;
}
LumieraFiledescriptor
lumiera_filedescriptor_acquire (const char* name, int flags)
{
TRACE (filedescriptor, "%s", name);
REQUIRE (registry, "not initialized");
lumiera_mutexacquirer registry_lock;
lumiera_mutexacquirer_init_mutex (&registry_lock, &registry_mutex, LUMIERA_LOCKED);
lumiera_filedescriptor fdesc;
fdesc.flags = flags;
if (stat (name, &fdesc.stat) != 0)
{
if (errno == ENOENT && flags&O_CREAT)
{
char* dir = lumiera_tmpbuf_strndup (name, PATH_MAX);
char* slash = dir;
while ((slash = strchr (slash+1, '/')))
{
*slash = '\0';
INFO (filedescriptor, "try creating dir: %s", dir);
if (mkdir (dir, 0777) == -1 && errno != EEXIST)
{
LUMIERA_ERROR_SET (filedescriptor, ERRNO);
goto efile;
}
*slash = '/';
}
int fd;
INFO (filedescriptor, "try creating file: %s", name);
fd = creat (name, 0777);
if (fd == -1)
{
LUMIERA_ERROR_SET (filedescriptor, ERRNO);
goto efile;
}
close (fd);
if (stat (name, &fdesc.stat) != 0)
{
/* finally, no luck */
LUMIERA_ERROR_SET (filedescriptor, ERRNO);
goto efile;
}
}
}
/* lookup/create descriptor */
LumieraFiledescriptor dest = &fdesc;
LumieraFiledescriptor* found = cuckoo_find (registry, &dest);
if (!found)
{
TRACE (filedescriptor, "Descriptor not found");
dest = lumiera_filedescriptor_new (&fdesc);
if (!dest)
goto ecreate;
cuckoo_insert (registry, &dest);
}
else
{
TRACE (filedescriptor, "Descriptor already existing");
dest = *found;
++dest->refcount;
}
lumiera_mutexacquirer_unlock (&registry_lock);
return dest;
efile:
ecreate:
lumiera_mutexacquirer_unlock (&registry_lock);
return NULL;
}
void
lumiera_filedescriptor_release (LumieraFiledescriptor self)
{
TRACE (filedescriptor);
if (!--self->refcount)
lumiera_filedescriptor_delete (self);
}
LumieraFiledescriptor
lumiera_filedescriptor_new (LumieraFiledescriptor template)
{
LumieraFiledescriptor self = lumiera_malloc (sizeof (lumiera_filedescriptor));
TRACE (filedescriptor, "at %p", self);
self->stat = template->stat;
self->flags = template->flags;
lumiera_mutex_init (&self->lock);
self->refcount = 1;
self->handle = 0;
const char* type = "mutex";
const char* name = "filedescriptor";
RESOURCE_ANNOUNCE (filedescriptor, type, name, self, self->rh);
return self;
}
void
lumiera_filedescriptor_delete (LumieraFiledescriptor self)
{
TRACE (filedescriptor, "%p", self);
lumiera_mutexacquirer registry_lock;
lumiera_mutexacquirer_init_mutex (&registry_lock, &registry_mutex, LUMIERA_LOCKED);
REQUIRE (self->refcount == 0);
RESOURCE_FORGET (filedescriptor, self->rh);
cuckoo_remove (registry, cuckoo_find (registry, &self));
TODO ("destruct other members (WIP)");
TODO ("release filehandle");
lumiera_mutex_destroy (&self->lock);
free (self);
lumiera_mutexacquirer_unlock (&registry_lock);
}

View file

@ -0,0 +1,113 @@
/*
filedescriptor.h - file handling
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_FILEDESCRIPTOR_H
#define LUMIERA_FILEDESCRIPTOR_H
#include "lib/mutex.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct lumiera_filedescriptor_struct lumiera_filedescriptor;
typedef lumiera_filedescriptor* LumieraFiledescriptor;
#include "backend/filehandle.h"
#include "backend/file.h"
/**
* @file
* Filedescriptors.
* Filedescriptors are the underlying working horse in accessing files.
* All information associated with managing a file is kept here.
*/
struct lumiera_filedescriptor_struct
{
struct stat stat; /* create after first open, maintained metadata, MUST BE FIRST! */
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 */
LumieraFilehandle handle;
//LumieraFileMap mappings;
//LumieraWriteBuffer writebuffer;
RESOURCE_HANDLE (rh);
};
/**
* Initialize the global filedescriptor registry.
* All filedescriptors are looked up by dev/ino/open-flags in a hashtable. Opening hardlinked
* files will be targeted to the same filedescriptor.
* This function never fails but dies on error.
*/
void
lumiera_filedescriptor_registry_init (void);
/**
* Destroy and free the global filedescriptor registry.
* Never fails.
*/
void
lumiera_filedescriptor_registry_destroy (void);
/**
* Find existing filedescriptor or create one
* @param name name of the file
* @param flags opening flags for the filedescriptor
* @return descriptor on success or NULL on error
*/
LumieraFiledescriptor
lumiera_filedescriptor_acquire (const char* name, int flags);
/**
* Release a filedescriptor.
* @param self filedescriptor to be released
*/
void
lumiera_filedescriptor_release (LumieraFiledescriptor self);
/**
* Allocate a new filedescriptor cloned from a template
* @param template the source filedescriptor
* @return the constrccted filedescriptor
*/
LumieraFiledescriptor
lumiera_filedescriptor_new (LumieraFiledescriptor template);
/**
* Delete a filedescriptor
* Called whenever its reference count drops to zero.
* @param self the filedescriptor to be deleted
*/
void
lumiera_filedescriptor_delete (LumieraFiledescriptor self);
#endif

70
src/backend/filehandle.c Normal file
View file

@ -0,0 +1,70 @@
/*
filehandle - filehandle management and caching
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/llist.h"
#include "lib/safeclib.h"
#include "backend/file.h"
#include "backend/filehandle.h"
#include "backend/filedescriptor.h"
#include <unistd.h>
NOBUG_DEFINE_FLAG_PARENT (filehandle, file_all);
LumieraFilehandle
lumiera_filehandle_new ()
{
LumieraFilehandle self = lumiera_malloc (sizeof (lumiera_filehandle));
TRACE (filehandle, "%p", self);
llist_init (&self->cachenode);
self->fd = -1;
self->use_cnt = 1;
self->descriptor = NULL;
return self;
}
void*
lumiera_filehandle_destroy_node (LList node)
{
TRACE (filehandle);
REQUIRE (llist_is_empty (node));
LumieraFilehandle self = (LumieraFilehandle)node;
REQUIRE (self->use_cnt == 0);
if (self->fd >= 0)
close (self->fd);
self->fd = -1;
self->descriptor = NULL;
return self;
}
int
lumiera_filehandle_get (LumieraFilehandle self)
{
REQUIRE (self->descriptor);
return -1;
}

69
src/backend/filehandle.h Normal file
View file

@ -0,0 +1,69 @@
/*
filehandle - filehandle management and caching
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_FILEHANDLE_H
#define LUMIERA_FILEHANDLE_H
#include "lib/error.h"
#include "lib/llist.h"
typedef struct lumiera_filehandle_struct lumiera_filehandle;
typedef lumiera_filehandle* LumieraFilehandle;
#include "backend/filedescriptor.h"
/**
* @file
* Filehandles.
* Filehandles manage the underlying POSIX filehandle for a filedescriptor.
* Since we want to support handling of more files than POSIX filehandles are available on a common system
* the filehandles are opened, cached and closed on demand, see 'filehandlecache'.
*/
/**
* File handles
*/
struct lumiera_filehandle_struct
{
llist cachenode;
int fd;
unsigned use_cnt;
LumieraFiledescriptor descriptor;
};
/**
* Allocate a new filehandle structure.
* @return new filehandle structure
*/
LumieraFilehandle
lumiera_filehandle_new ();
/**
* destroy the resources associated eith a filehandle structure.
* This function is used by the filehandlecache to recycle filehandle structs.
* @param node pointer to the cachenode member of a struct filehandle
* @return pointer to the start of the memory of the destroyed filehandle
*/
void*
lumiera_filehandle_destroy_node (LList node);
#endif

View file

@ -0,0 +1,138 @@
/*
filehandlecache - filehandle management and caching
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/safeclib.h"
#include "backend/file.h"
#include "backend/filehandlecache.h"
NOBUG_DEFINE_FLAG_PARENT (filehandlecache, file_all);
/* errors */
LUMIERA_ERROR_DEFINE (FILEHANDLECACHE_NOHANDLE, "No filehandle available");
LumieraFilehandlecache lumiera_fhcache = NULL;
void
lumiera_filehandlecache_new (int max_entries)
{
REQUIRE (!lumiera_fhcache, "Filehandlecache already initialized");
NOBUG_INIT_FLAG (filehandlecache);
lumiera_fhcache = lumiera_malloc (sizeof (lumiera_filehandlecache));
lumiera_mrucache_init (&lumiera_fhcache->cache, lumiera_filehandle_destroy_node);
lumiera_fhcache->available = max_entries;
lumiera_fhcache->checked_out = 0;
lumiera_mutex_init (&lumiera_fhcache->lock);
RESOURCE_ANNOUNCE (filehandlecache, "mutex", "filehandlecache", lumiera_fhcache, lumiera_fhcache->rh);
}
void
lumiera_filehandlecache_delete (void)
{
if (lumiera_fhcache)
{
REQUIRE (!lumiera_fhcache->checked_out, "Filehandles in use at shutdown");
RESOURCE_FORGET (filehandlecache, lumiera_fhcache->rh);
lumiera_mrucache_destroy (&lumiera_fhcache->cache);
lumiera_mutex_destroy (&lumiera_fhcache->lock);
free (lumiera_fhcache);
lumiera_fhcache = NULL;
}
}
LumieraFilehandle
lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFiledescriptor desc)
{
TRACE (filehandlecache);
LumieraFilehandle ret = NULL;
LUMIERA_MUTEX_SECTION (filehandlecache, self->rh, &self->lock)
{
if (self->available <= 0 && self->cache.cached)
{
/* pop a filehandle from cache */
ret = lumiera_mrucache_pop (&self->cache);
if (self->available < 0)
/* try to free overallocated filehandles */
self->available -= self->available + lumiera_mrucache_age (&self->cache, -self->available);
}
else
{
/* allocate new filehandle if we are below the limit or no cached handles are available (overallocating) */
ret = lumiera_filehandle_new ();
if (!ret)
LUMIERA_ERROR_SET (filehandlecache, FILEHANDLECACHE_NOHANDLE);
else
--self->available;
}
ret->use_cnt = 1;
ret->descriptor = desc;
desc->handle = ret;
++self->checked_out;
}
return ret;
}
LumieraFilehandle
lumiera_filehandlecache_checkout (LumieraFilehandlecache self, LumieraFilehandle handle)
{
REQUIRE (self);
REQUIRE (handle);
/* This function is called with the associated descriptor locked, nothing can modify 'handle' */
if (!handle->use_cnt)
{
/* lock cache and checkout */
LUMIERA_MUTEX_SECTION (filehandlecache, self->rh, &self->lock)
{
lumiera_mrucache_checkout (&self->cache, &handle->cachenode);
}
}
++handle->use_cnt;
++self->checked_out;
return handle;
}
void
lumiera_filehandlecache_checkin (LumieraFilehandlecache self, LumieraFilehandle handle)
{
REQUIRE (self);
REQUIRE (handle);
REQUIRE (handle->use_cnt);
/* This function is called with the associated descriptor locked, nothing can modify 'self' */
if (!--handle->use_cnt)
{
/* lock cache and checin */
LUMIERA_MUTEX_SECTION (filehandlecache, self->rh, &self->lock)
{
--self->checked_out;
lumiera_mrucache_checkin (&self->cache, &handle->cachenode);
}
}
}

View file

@ -0,0 +1,108 @@
/*
filehandlecache - filehandle management and caching
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_FILEHANDLECACHE_H
#define LUMIERA_FILEHANDLECACHE_H
#include "lib/error.h"
#include "lib/mrucache.h"
#include "lib/mutex.h"
typedef struct lumiera_filehandlecache_struct lumiera_filehandlecache;
typedef lumiera_filehandlecache* LumieraFilehandlecache;
#include "backend/filehandle.h"
/**
* @file
* Filehandle management and caching
* The number of filehandles a program can held open is usually limited, since we want to support
* using a less limited number of files and closing/opening for each operation is expensive, we
* provide a cache to keep the most frequent used files open and gracefully close/recycle unused filehandles.
* The filehandlecache defined here protects all operations on the cache with a mutex.
*/
/*
File handle cache manages file handles
*/
struct lumiera_filehandlecache_struct
{
lumiera_mrucache cache;
int available;
int checked_out;
lumiera_mutex lock;
RESOURCE_HANDLE (rh);
};
extern LumieraFilehandlecache lumiera_fhcache;
/**
* Initializes the filehandle cache.
* @param max_entries number how much filehandles shall be managed
* The number of elements the cache can hold is static and should be
* determined by sysconf (_SC_OPEN_MAX) minus some (big) safety margin.
*/
void
lumiera_filehandlecache_new (int max_entries);
/**
* Delete the filehandle cache.
* No filehandles in the cache must be locked, this would be a fatal error.
* The handles are closed automatically.
*/
void
lumiera_filehandlecache_delete (void);
/**
* Get a fresh filehandle.
* @param self pointer to the cache
* @return the new filehandle
*/
LumieraFilehandle
lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFiledescriptor desc);
/**
* Add filehande back to cache, the filehandle becomes subject of aging.
* @param self pointer to the cache
* @param handle filehandle to be put back
*/
void
lumiera_filehandlecache_add_filehandle (LumieraFilehandlecache self, LumieraFilehandle handle);
/**
* Remove a filehandle from cache aging
* Filehandles which are subject of cache aging must be checked out before they can be used.
* @param self the filehandlecache
* @param handle the filehandle to be checked out
*/
LumieraFilehandle
lumiera_filehandlecache_checkout (LumieraFilehandlecache self, LumieraFilehandle handle);
/**
* Put a filehandle into the cache
* Filehandles which are checked in are subject of cache aging and might get destroyed and reused.
* @param self the filehandlecache
* @param handle the filehandle to be checked in
*/
void
lumiera_filehandlecache_checkin (LumieraFilehandlecache self, LumieraFilehandle handle);
#endif

88
src/backend/mmap.h Normal file
View file

@ -0,0 +1,88 @@
/*
mmap.h - memory mapped acces to files
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_MMAP_H
#define LUMIERA_MMAP_H
#include "lib/llist.h"
typedef struct lumiera_mmap_struct lumiera_mmap;
typedef lumiera_mmap* LumieraMMap;
#include "backend/filedescriptor.h"
#include <nobug.h>
#include <sys/mman.h>
NOBUG_DECLARE_FLAG (mmap);
/**
* @file
* MMap objects cover a memory maped range in a file
*/
/**
* mmaped area
*
*/
struct lumiera_mmap_struct
{
/** used for the mrucache when checked in the cache OR for attaching owners when checked out **/
llist cachenode;
/** all mmaps of a file are chained in this list, used to find ranges **/
llist searchnode;
off_t start;
size_t size;
void* address;
/** array with refcounters per page **/
unsigned short* refmap;
/** 0 when this mmap is in cache, else the count of attached owners **/
unsigned use_cnt;
//RESOURCE_HANDLE (rh);
};
LumieraMMap
lumiera_mmap_init (LumieraMMap self, LumieraFile file, LList acquirer, off_t start, size_t size, size_t chunksize);
LumieraMMap
lumiera_mmap_new (LumieraFile file, LList acquirer, off_t start, size_t size, size_t chunksize);
void*
lumiera_mmap_destroy_node (LList node);
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

136
src/backend/mmapcache.h Normal file
View file

@ -0,0 +1,136 @@
/*
mmapcache.h - handle aging of mmap objects
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_MMAPCACHE_H
#define LUMIERA_MMAPCACHE_H
#include "lib/error.h"
#include "lib/mrucache.h"
#include "lib/mutex.h"
typedef struct lumiera_mmapcache_struct lumiera_mmapcache;
typedef lumiera_mmapcache* LumieraMMapcache;
#include "backend/mmap.h"
#include <nobug.h>
/**
* @file
* Mmapcache stores a MRU cache of all established mmaped memory regions which are currently not in use.
* The mmapcache also manages the upper limit about how much memory can be mmaped.
*/
struct lumiera_mmapcache_struct
{
lumiera_mrucache cache;
size_t limit;
size_t total;
size_t cached;
lumiera_mutex lock;
RESOURCE_HANDLE (rh);
};
extern LumieraMMapcache lumiera_mcache;
/**
* Initializes the mmapcache.
* @param limit the mmapcache will drop elements when the sum of all mmapings gives over limit
*/
void
lumiera_mmapcache_new (size_t limit);
/**
* Delete the mmap cache.
* No mmaps in the cache must be locked, this would be a fatal error.
* The handles are closed automatically.
*/
void
lumiera_mmapcache_delete (void);
/**
* Get a fresh mmap object.
* when mmaped_limit is reached, the oldest mmap object gets dropped else a new allocated object
* is returned
* @param self pointer to the cache
* @return the new mmap
*/
LumieraMMap
lumiera_mmapcache_mmap_acquire (LumieraMMapcache self);
/**
* Announce a new mmap object to the cache quotas.
* Update the statistics kept in the cache,
* the map object is still considered to be checked out
* @param self pointer to the cache
* @param map object to be announced
*/
void
lumiera_mmapcache_announce (LumieraMMapcache self, LumieraMMap map);
/**
* Remove a mmap object from the cache quotas.
* Update the statistics kept in the cache,
* called by mmap's destructor only
* @param self pointer to the cache
* @param map object to be removed
*/
void
lumiera_mmapcache_forget (LumieraMMapcache self, LumieraMMap map);
/**
* Destroy and free the nelem oldest elements.
* Used to free up resources and memory.
* @param self cache where to free elements.
* @return nelem-(numer of elements which got freed), that is 0 if all requested elements got freed
*/
int
lumiera_mmapcache_age (LumieraMMapcache self);
/**
* Remove a mmap from cache aging
* Mmaps which are subject of cache aging must be checked out before they can be used.
* @param self the mmapcache
* @param handle the mmap to be checked out
*/
LumieraMMap
lumiera_mmapcache_checkout (LumieraMMapcache self, LumieraMMap handle);
/**
* Put a mmap into the cache
* Mmaps which are checked in are subject of cache aging and might get destroyed and reused.
* @param self the mmapcache
* @param handle the mmap to be checked in
*/
void
lumiera_mmapcache_checkin (LumieraMMapcache self, LumieraMMap handle);
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

118
src/backend/mmapings.h Normal file
View file

@ -0,0 +1,118 @@
/*
mmapings.h - manage ranges of mmaped areas on a filedescriptor
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_MMAPINGS_H
#define LUMIERA_MMAPINGS_H
#include "lib/mutex.h"
#include "lib/llist.h"
typedef struct lumiera_mmapings_struct lumiera_mmapings;
typedef lumiera_mmapings* LumieraMMapings;
#include "backend/filedescriptor.h"
#include "backend/mmap.h"
#include <nobug.h>
/**
* @file
* Keeps all mmaped areas
*
*/
struct lumiera_mmapings_struct
{
/** mmaped ranges are kept in an list sorted by the size of the mmaping, might be improved to a tree someday **/
llist mmaps;
/** sum of all mmaped areas, areas might be overlapping **/
// size_t vsz;
/**
* chunkssize is the smallest granularity which is used for mmapping files, it
* should reflect the intended file usage, that is 'pagesize' for small or non growing
* files and some MB for media files. Must be a 2's exponent of pagesize.
**/
size_t chunksize;
LumieraFiledescriptor descriptor;
lumiera_mutex lock;
RESOURCE_HANDLE (rh);
};
/**
* initialize mmapings container
*
*/
LumieraMMapings
lumiera_mmapings_init (LumieraMMapings self, LumieraFile file, size_t chunksize);
/**
* destroy mmapings container and free all resources.
*
*/
LumieraMMapings
lumiera_mmapings_destroy (LumieraMMapings self);
/**
* allocate and initialize new mmapings container
*
*/
LumieraMMapings
lumiera_mmapings_new (LumieraFile file, size_t chunksize);
/**
* destroy and free mmapings container and all its resources
*
*/
void
lumiera_mmapings_delete (LumieraMMapings self);
/**
* acquire a mmap which covers the given range
* @param self mmapings where to search
* @param acquirer list node of the new owner which will registered in the mmap
* @param start begin of the required range
* @param size requested size
* @return MMap object covering the requested range or NULL on error
*/
LumieraMMap
lumiera_mmapings_mmap_acquire (LumieraMMapings self, LumieraFile file, LList acquirer, off_t start, size_t size);
/**
* release a previously acquired MMap object
* @param self mmapings to which the map belongs
* @param acquirer holding node
* @param map object to be released
*/
void
lumiera_mmapings_release_mmap (LumieraMMapings self, LList acquirer, LumieraMMap map);
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

65
src/common/Makefile.am Normal file
View file

@ -0,0 +1,65 @@
# Copyright (C) Lumiera.org
# 2008, Christian Thaeter <ct@pipapo.org>
#
# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
# TODO use -Wextra -Werror
liblumicommon_a_srcdir = $(top_srcdir)/src/common
noinst_LIBRARIES += liblumicommon.a
liblumicommon_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumicommon_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumicommon_a_SOURCES = \
$(liblumicommon_a_srcdir)/time.cpp \
$(liblumicommon_a_srcdir)/util.cpp \
$(liblumicommon_a_srcdir)/visitor.cpp \
$(liblumicommon_a_srcdir)/cmdline.cpp \
$(liblumicommon_a_srcdir)/configrules.cpp \
$(liblumicommon_a_srcdir)/error.cpp \
$(liblumicommon_a_srcdir)/query.cpp \
$(liblumicommon_a_srcdir)/query/mockconfigrules.cpp \
$(liblumicommon_a_srcdir)/test/suite.cpp \
$(liblumicommon_a_srcdir)/test/testoption.cpp
noinst_HEADERS += \
$(liblumicommon_a_srcdir)/cmdline.hpp \
$(liblumicommon_a_srcdir)/factory.hpp \
$(liblumicommon_a_srcdir)/singleton.hpp \
$(liblumicommon_a_srcdir)/singletonpolicies.hpp \
$(liblumicommon_a_srcdir)/singletonpreconfigure.hpp \
$(liblumicommon_a_srcdir)/time.hpp \
$(liblumicommon_a_srcdir)/typelist.hpp \
$(liblumicommon_a_srcdir)/visitor.hpp \
$(liblumicommon_a_srcdir)/visitordispatcher.hpp \
$(liblumicommon_a_srcdir)/visitorpolicies.hpp \
$(liblumicommon_a_srcdir)/configrules.hpp \
$(liblumicommon_a_srcdir)/error.hpp \
$(liblumicommon_a_srcdir)/multithread.hpp \
$(liblumicommon_a_srcdir)/p.hpp \
$(liblumicommon_a_srcdir)/query.hpp \
$(liblumicommon_a_srcdir)/query/mockconfigrules.hpp \
$(liblumicommon_a_srcdir)/singletonfactory.hpp \
$(liblumicommon_a_srcdir)/singletonsubclass.hpp \
$(liblumicommon_a_srcdir)/typelistutil.hpp \
$(liblumicommon_a_srcdir)/util.hpp \
$(liblumicommon_a_srcdir)/test/mockinjector.hpp \
$(liblumicommon_a_srcdir)/test/suite.hpp \
$(liblumicommon_a_srcdir)/test/testoption.hpp \
$(liblumicommon_a_srcdir)/test/run.hpp

View file

@ -21,23 +21,30 @@ noinst_LIBRARIES += liblumi.a
liblumi_a_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror
liblumi_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumi_a_SOURCES = \
$(liblumi_a_srcdir)/plugin.c \
$(liblumi_a_srcdir)/error.c \
$(liblumi_a_srcdir)/framerate.c \
$(liblumi_a_srcdir)/mutex.c \
$(liblumi_a_srcdir)/rwlock.c \
$(liblumi_a_srcdir)/condition.c \
$(liblumi_a_srcdir)/references.c
noinst_HEADERS += \
$(liblumi_a_srcdir)/plugin.h \
$(liblumi_a_srcdir)/error.h \
$(liblumi_a_srcdir)/framerate.h \
$(liblumi_a_srcdir)/locking.h \
$(liblumi_a_srcdir)/mutex.h \
$(liblumi_a_srcdir)/rwlock.h \
$(liblumi_a_srcdir)/condition.h \
$(liblumi_a_srcdir)/references.h
liblumi_a_SOURCES = \
$(liblumi_a_srcdir)/plugin.c \
$(liblumi_a_srcdir)/error.c \
$(liblumi_a_srcdir)/mutex.c \
$(liblumi_a_srcdir)/rwlock.c \
$(liblumi_a_srcdir)/condition.c \
$(liblumi_a_srcdir)/references.c \
$(liblumi_a_srcdir)/uuid.c \
$(liblumi_a_srcdir)/safeclib.c \
$(liblumi_a_srcdir)/cuckoo.c \
$(liblumi_a_srcdir)/mrucache.c \
$(liblumi_a_srcdir)/appconfig.cpp
noinst_HEADERS += \
$(liblumi_a_srcdir)/plugin.h \
$(liblumi_a_srcdir)/error.h \
$(liblumi_a_srcdir)/locking.h \
$(liblumi_a_srcdir)/mutex.h \
$(liblumi_a_srcdir)/rwlock.h \
$(liblumi_a_srcdir)/condition.h \
$(liblumi_a_srcdir)/references.h \
$(liblumi_a_srcdir)/uuid.h \
$(liblumi_a_srcdir)/safeclib.h \
$(liblumi_a_srcdir)/cuckoo.h \
$(liblumi_a_srcdir)/mrucache.h \
$(liblumi_a_srcdir)/appconfig.hpp \
$(liblumi_a_srcdir)/lifecycleregistry.hpp

View file

@ -22,9 +22,12 @@
#include "lib/condition.h"
/**
* @file Condition variables
* @file
* Condition variables
*/
LUMIERA_ERROR_DEFINE (CONDITION_DESTROY, "condition destroy failed");
/**
* Initialize a condition variable
* @param self is a pointer to the condition variable to be initialized
@ -53,9 +56,9 @@ lumiera_condition_destroy (LumieraCondition self)
if (self)
{
if (pthread_mutex_destroy (&self->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_DESTROY);
else if (pthread_cond_destroy (&self->cond))
LUMIERA_DIE;
LUMIERA_DIE (CONDITION_DESTROY);
}
return self;
}

View file

@ -25,9 +25,11 @@
#include "lib/locking.h"
/**
* @file Condition variables, header
* @file
* Condition variables, header
*/
LUMIERA_ERROR_DECLARE (CONDITION_DESTROY);
/**
* Condition variables.
@ -59,10 +61,10 @@ lumiera_condition_signal (LumieraCondition self)
{
REQUIRE (self);
if (pthread_mutex_lock (&self->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
pthread_cond_signal (&self->cond);
if (pthread_mutex_unlock (&self->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_UNLOCK);
}
/**
@ -74,10 +76,10 @@ lumiera_condition_broadcast (LumieraCondition self)
{
REQUIRE (self);
if (pthread_mutex_lock (&self->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
pthread_cond_broadcast (&self->cond);
if (pthread_mutex_unlock (&self->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_UNLOCK);
}
@ -124,7 +126,7 @@ lumiera_conditionacquirer_init (LumieraConditionacquirer self, LumieraCondition
self->state = state;
if (state == LUMIERA_LOCKED)
if (pthread_mutex_lock (&cond->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
return self;
}
@ -141,7 +143,7 @@ lumiera_conditionacquirer_lock (LumieraConditionacquirer self)
REQUIRE (self->state == LUMIERA_UNLOCKED, "mutex already locked");
if (pthread_mutex_lock (&self->cond->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
self->state = LUMIERA_LOCKED;
}
@ -166,13 +168,13 @@ lumiera_conditionacquirer_wait (LumieraConditionacquirer self)
* a conditionacquirer must be unlocked before leaving scope
* @param self conditionacquirer associated with a condition variable
*/
static inline int
static inline void
lumiera_conditionacquirer_unlock (LumieraConditionacquirer self)
{
REQUIRE (self);
REQUIRE (self->state == LUMIERA_LOCKED, "mutex was not locked");
if (pthread_mutex_unlock (&self->cond->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_UNLOCK);
self->state = LUMIERA_UNLOCKED;
}
@ -194,7 +196,7 @@ lumiera_conditionacquirer_signal (LumieraConditionacquirer self)
* signal all waiting threads
* @param self conditionacquirer associated with the condition variable to be signaled
*/
static inline int
static inline void
lumiera_conditionacquirer_broadcast (LumieraConditionacquirer self)
{
REQUIRE (self);

504
src/lib/cuckoo.c Normal file
View file

@ -0,0 +1,504 @@
/*
A cuckoo hash implementation
Copyright (C)
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cuckoo.h"
#include <string.h>
enum compact_state
{
COMPACTING_OFF,
COMPACTING_AUTO,
COMPACTED
};
struct cuckoo_struct
{
size_t size; /* t1 = 4*size; t2 = 2*size; t3 = size */
size_t itemsize;
cuckoo_hashfunc h1; /* hash function */
uint32_t r1; /* random, reset for each rehash */
cuckoo_hashfunc h2;
uint32_t r2;
cuckoo_hashfunc h3;
uint32_t r3;
cuckoo_cmpfunc cmp;
void* t1;
void* t2;
void* t3;
unsigned maxloops; /* sqrt (4 * size) */
enum compact_state autocompact;
size_t elements;
};
static inline uint32_t cuckoo_fast_prng ()
{
static uint32_t rnd = 0xbabeface;
return rnd = rnd<<1 ^ ((rnd>>30) & 1) ^ ((rnd>>2) & 1);
}
Cuckoo
cuckoo_init (Cuckoo self,
cuckoo_hashfunc h1,
cuckoo_hashfunc h2,
cuckoo_hashfunc h3,
cuckoo_cmpfunc cmp,
size_t itemsize,
unsigned startsize)
{
if (!self)
return NULL;
self->size = 1<<startsize;
self->itemsize = itemsize;
self->h1 = h1;
self->r1 = cuckoo_fast_prng ();
self->h2 = h2;
self->r2 = cuckoo_fast_prng ();
self->h3 = h3;
self->r3 = cuckoo_fast_prng ();
self->cmp = cmp;
self->t1 = calloc (self->size * 4, itemsize);
self->t2 = calloc (self->size * 2, itemsize);
self->t3 = calloc (self->size, itemsize);
if (!self->t1 || !self->t2 || !self->t3)
{
free (self->t1);
free (self->t2);
free (self->t3);
return NULL;
}
self->maxloops = 1;
while (self->maxloops * self->maxloops < self->size * 4)
++self->maxloops;
self->autocompact = COMPACTING_AUTO;
self->elements = 0;
return self;
}
Cuckoo
cuckoo_new (cuckoo_hashfunc h1,
cuckoo_hashfunc h2,
cuckoo_hashfunc h3,
cuckoo_cmpfunc cmp,
size_t itemsize,
unsigned startsize)
{
Cuckoo self = malloc (sizeof (struct cuckoo_struct));
if (!cuckoo_init (self, h1, h2, h3, cmp, itemsize, startsize))
{
free (self);
return NULL;
}
return self;
}
Cuckoo
cuckoo_destroy (Cuckoo self)
{
if (self)
{
free (self->t1);
free (self->t2);
free (self->t3);
}
return self;
}
void
cuckoo_free (Cuckoo self)
{
free (cuckoo_destroy (self));
}
static inline int
iszero (void* mem, size_t size)
{
while (size && !*(int*)mem)
{
size -= sizeof (int);
mem += sizeof (int);
}
return !size;
}
static inline void
xmemcpy (void* dst, void* src, size_t size)
{
while (size)
{
size -= sizeof (int);
*(int*)(dst + size) = *(int*)(src + size);
}
}
static int
cuckoo_insert_internal_ (Cuckoo self, void* item)
{
void* pos;
char tmp[self->itemsize];
for (unsigned n = 0; n < self->maxloops; ++n)
{
/* find nest */
pos = self->t1 + self->itemsize * (self->h1 (item, self->r1) % (4*self->size));
/* kick old egg out */
xmemcpy (tmp, pos, self->itemsize);
/* lay egg */
xmemcpy (pos, item, self->itemsize);
if (iszero (tmp, self->itemsize))
return 1;
/* find nest */
pos = self->t2 + self->itemsize * (self->h2 (tmp, self->r2) % (2*self->size));
/* kick old egg out */
xmemcpy (item, pos, self->itemsize);
/* lay egg */
xmemcpy (pos, tmp, self->itemsize);
if (iszero (item, self->itemsize))
return 1;
/* find nest */
pos = self->t3 + self->itemsize * (self->h3 (item, self->r3) % self->size);
/* kick old egg out */
xmemcpy (tmp, pos, self->itemsize);
/* lay egg */
xmemcpy (pos, item, self->itemsize);
if (iszero (tmp, self->itemsize))
return 1;
/* copy tmp to item, which will be reinserted on next interation / after rehashing */
xmemcpy (item, tmp, self->itemsize);
}
return 0;
}
size_t
cuckoo_nelements (Cuckoo self)
{
return self->elements;
}
static void
cuckoo_rehash (Cuckoo self)
{
retry1:
self->r1 = cuckoo_fast_prng ();
for (size_t i = 0; i < 4*self->size; ++i)
{
unsigned n;
void* pos = self->t1 + self->itemsize * i;
if (!iszero (pos, self->itemsize))
{
for (n = 0; n < self->maxloops; ++n)
{
unsigned hash = self->h1 (pos, self->r1) % (4*self->size);
if (hash != i)
{
char t[self->itemsize];
void* hpos = self->t1 + self->itemsize * hash;
xmemcpy (t, hpos, self->itemsize);
xmemcpy (hpos, pos, self->itemsize);
xmemcpy (pos, t, self->itemsize);
if (iszero (t, self->itemsize))
break;
}
else
break;
}
if (n == self->maxloops)
goto retry1;
}
}
retry2:
self->r2 = cuckoo_fast_prng ();
for (size_t i = 0; i < 2*self->size; ++i)
{
unsigned n;
void* pos = self->t2 + self->itemsize * i;
if (!iszero (pos, self->itemsize))
{
for (n = 0; n < self->maxloops; ++n)
{
unsigned hash = self->h2 (pos, self->r2) % (2*self->size);
if (hash != i)
{
char t[self->itemsize];
void* hpos = self->t2 + self->itemsize * hash;
xmemcpy (t, hpos, self->itemsize);
xmemcpy (hpos, pos, self->itemsize);
xmemcpy (pos, t, self->itemsize);
if (iszero (t, self->itemsize))
break;
}
else
break;
}
if (n == self->maxloops)
goto retry2;
}
}
retry3:
self->r3 = cuckoo_fast_prng ();
for (size_t i = 0; i < self->size; ++i)
{
unsigned n;
void* pos = self->t3 + self->itemsize * i;
if (!iszero (pos, self->itemsize))
{
for (n = 0; n < self->maxloops; ++n)
{
unsigned hash = self->h3 (pos, self->r3) % self->size;
if (hash != i)
{
char t[self->itemsize];
void* hpos = self->t3 + self->itemsize * hash;
xmemcpy (t, hpos, self->itemsize);
xmemcpy (hpos, pos, self->itemsize);
xmemcpy (pos, t, self->itemsize);
if (iszero (t, self->itemsize))
break;
}
else
break;
}
if (n == self->maxloops)
goto retry3;
}
}
}
static int
cuckoo_grow (Cuckoo self)
{
/* rotate hashfuncs, tables, randoms */
cuckoo_hashfunc th = self->h3;
self->h3 = self->h2;
self->h2 = self->h1;
self->h1 = th;
uint32_t tr = self->r3;
self->r3 = self->r2;
self->r2 = self->r1;
self->r1 = tr;
void* tt = self->t3;
self->t3 = self->t2;
self->t2 = self->t1;
/* double new base size */
self->size *= 2;
while (self->maxloops * self->maxloops < self->size * 4)
++self->maxloops;
/* alloc new t1 */
self->t1 = calloc (self->size * 4, self->itemsize);
if (!self->t1)
{
self->t1 = tt;
return 0;
}
/* reinsert tt */
size_t ttsize = self->size / 2;
for (size_t i = 0; i < ttsize; ++i)
{
void* pos = tt + i * self->itemsize;
if (!iszero (pos, self->itemsize))
{
while (!cuckoo_insert_internal_ (self, pos))
cuckoo_rehash (self);
}
}
free (tt);
self->autocompact = COMPACTING_AUTO;
return 1;
}
int
cuckoo_reserve (Cuckoo self, size_t more)
{
int ret = 1;
if (more)
while (self->elements+self->maxloops+more >= 6*self->size)
ret = cuckoo_grow (self);
self->autocompact = COMPACTING_OFF;
return ret;
}
int
cuckoo_compact (Cuckoo self)
{
if (self->autocompact == COMPACTED)
return 1;
if (self->size > 2 && self->elements < self->size * 3)
{
cuckoo_hashfunc th = self->h1;
self->h1 = self->h2;
self->h2 = self->h3;
self->h3 = th;
uint32_t tr = self->r1;
self->r1 = self->r2;
self->r2 = self->r3;
self->r3 = tr;
void* tt = self->t1;
self->t1 = self->t2;
self->t2 = self->t3;
/* halve base size */
self->size /= 2;
while (self->maxloops * self->maxloops >= self->size * 4)
--self->maxloops;
/* alloc new t3 */
self->t3 = calloc (self->size, self->itemsize);
if (!self->t3)
{
self->t3 = tt;
return 0;
}
/* reinsert tt */
size_t ttsize = self->size * 8;
for (size_t i = 0; i < ttsize; ++i)
{
void* pos = tt + i * self->itemsize;
if (!iszero (pos, self->itemsize))
{
--self->elements;
cuckoo_insert (self, pos);
}
}
free (tt);
self->autocompact = COMPACTED;
}
return 1;
}
int
cuckoo_insert (Cuckoo self, void* item)
{
char tmp[self->itemsize];
void* found;
if ((found = cuckoo_find (self, item)))
{
xmemcpy (found, item, self->itemsize);
return 1;
}
xmemcpy (tmp, item, self->itemsize);
for (unsigned n = 6; n; --n) /* rehash/grow loop */
{
if (cuckoo_insert_internal_ (self, tmp))
{
++self->elements;
return 1;
}
if (self->elements > n*self->size)
{
n = 6;
if (!cuckoo_grow (self))
return 0;
}
else
cuckoo_rehash (self);
}
return 0;
}
void*
cuckoo_find (Cuckoo self, void* item)
{
void* pos;
pos = self->t1 + self->itemsize * (self->h1 (item, self->r1) % (4*self->size));
if (!iszero (pos, self->itemsize) && self->cmp (item, pos))
return pos;
pos = self->t2 + self->itemsize * (self->h2 (item, self->r2) % (2*self->size));
if (!iszero (pos, self->itemsize) && self->cmp (item, pos))
return pos;
pos = self->t3 + self->itemsize * (self->h3 (item, self->r3) % self->size);
if (!iszero (pos, self->itemsize) && self->cmp (item, pos))
return pos;
return NULL;
}
void
cuckoo_remove (Cuckoo self, void* item)
{
if (item)
{
memset (item, 0, self->itemsize);
--self->elements;
if (self->autocompact == COMPACTING_AUTO && self->size > 2 && self->elements <= self->size*2)
cuckoo_compact (self);
}
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

175
src/lib/cuckoo.h Normal file
View file

@ -0,0 +1,175 @@
/*
A cuckoo hash implementation
Copyright (C)
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef CUCKOO_H
#define CUCKOO_H
/**
* @file
* Cuckoo hashing
* This hashing gives guaranteed O(1) lookup complexity and amortized O(1) insert and remove complexity.
* Hash tables by default grow and shrink automatically. It is posible to preallocate entries and turn
* automatic shrinking off taking out the memory management factors for insert and remove operations.
* This implementation uses 3 Tables which exponential growing sizes.
*/
#include <stdlib.h>
#include <stdint.h>
struct cuckoo_struct;
typedef struct cuckoo_struct * Cuckoo;
/**
* Hash function.
* User supplied universal hash function
* @param item address of the item to be hashed
* @param r pseudo random number, 31 significant bits, regenerated on each rehash
* @return hash value
*/
typedef size_t (*cuckoo_hashfunc)(const void* item, const uint32_t r);
/**
* Compare function.
* User supplied compare function
* @param item1 address of the first item
* @param item2 address of the second item
* @return 1 when the items are identical, 0 otherwise
*/
typedef int (*cuckoo_cmpfunc)(const void* item1, const void* item2);
/**
* Initialize a cuckoo hash.
* @param self pointer to a uninitialized cuckoo datastructure
* @param h1 hash function for the first table
* @param h2 hash function for the second table
* @param h3 hash function for the third table
* @param cmp function which compares two keys
* @param startsize initial size of table t3, as 2's exponent
* @return The initialized hashtable or NULL at allocation failure
*/
Cuckoo
cuckoo_init (Cuckoo self,
cuckoo_hashfunc h1,
cuckoo_hashfunc h2,
cuckoo_hashfunc h3,
cuckoo_cmpfunc cmp,
size_t itemsize,
unsigned startsize);
/**
* Allocate a new cuckoo hash.
* @param h1 hash function for the first table
* @param h2 hash function for the second table
* @param h3 hash function for the third table
* @param cmp function which compares two keys
* @param startsize initial size of table t3, as 2's exponent
* @return The initialized hashtable or NULL at allocation failure
*/
Cuckoo
cuckoo_new (cuckoo_hashfunc h1,
cuckoo_hashfunc h2,
cuckoo_hashfunc h3,
cuckoo_cmpfunc cmp,
size_t itemsize,
unsigned startsize);
/**
* Destroy a cuckoo hash.
* Frees internal used resources.
* @param self cuckoo hash to destroy
* @return The now uninitialized hashtable
*/
Cuckoo
cuckoo_destroy (Cuckoo self);
/**
* Deallocate a cuckoo hash.
* @param self handle of the hash table to be freed
*/
void
cuckoo_free (Cuckoo self);
/**
* Get the number of elements stored in a hash.
* @return number of elements, 0 when empty
*/
size_t
cuckoo_nelements (Cuckoo self);
/**
* Insert an element into a hash.
* amortized O(1) complexity because it may rarely rehash the tables or even grow them.
* see cuckoo_reserve() about how to preallocate entries to prevent the growing costs.
* @param self handle to the hash table
* @param item pointer to a item to be inserted
* @return 1 on successful insert, 0 on allocation failure
* Note: at failure there is one arbitary hash cell lost!
*/
int
cuckoo_insert (Cuckoo self, void* item);
/**
* Find a value by key in a hash.
* @param self handle to the hash table
* @param item pointer to an item to be looked up
* @return found object or NULL if not present
*/
void*
cuckoo_find (Cuckoo self, void* item);
/**
* Remove a item from a hash.
* amortized O(1) complexity when it automatically shrink its tables.
* guaranteed O(1) complexity when automatic shrinking is turned off.
* see cuckoo_reserve() about how turn automatic shrinking off.
* @param self handle to the hash table
* @param item pointer to the item to be removed
*/
void
cuckoo_remove (Cuckoo self, void* item);
/**
* Shrink the hash sizes when possible and turn autocompacting on.
* only useful when autmatic shrinking is turned off.
* see cuckoo_reserve() about how turn shrinking off.
* @param self handle to the hash table
*/
int
cuckoo_compact (Cuckoo self);
/**
* Prereserve hash entries and turn autocompacting off.
* @param self handle to the hash table
* @param more number of entries to be additionally reserved
* In rare circumstances inserting into a hash which has reserved some entries
* it may still need to rehash (or even rarer) to grow the table.
* While autocompacting is turned off, removing is completely O(1).
*/
int
cuckoo_reserve (Cuckoo self, size_t more);
#endif
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -24,7 +24,8 @@
#include "lib/error.h"
/**
* @file C Error handling in Lumiera.
* @file
* C Error handling in Lumiera.
*/

View file

@ -31,7 +31,8 @@ extern "C" {
#include <stdlib.h>
/**
* @file C Error handling in Lumiera, header.
* @file
* C Error handling in Lumiera, header.
*/
@ -39,7 +40,8 @@ extern "C" {
* Abort unconditionally with a 'Fatal Error!' message.
* This macro is used whenever the program end up in a invalid state from which no runtime recovery is possible
*/
#define LUMIERA_DIE do { NOBUG_ERROR(NOBUG_ON, "Fatal Error!"); abort(); } while(0)
#define LUMIERA_DIE(err) \
do { NOBUG_ERROR(NOBUG_ON, "Fatal Error: %s ", strchr(LUMIERA_ERROR_##err, ':')); abort(); } while(0)
/**
* Forward declare an error constant.
@ -58,7 +60,8 @@ extern const char* LUMIERA_ERROR_##err
#define LUMIERA_ERROR_DEFINE(err, msg) \
const char* LUMIERA_ERROR_##err = "LUMIERA_ERROR_" #err ":" msg
/** Helper macro to raise an error for the current thread.
/**
* Helper macro to raise an error for the current thread.
* This macro eases setting an error. It adds NoBug logging support to the low level error handling.
* @param flag NoBug flag describing the subsystem where the error was raised
* @param err name of the error without the 'LUMIERA_ERROR_' prefix (example: NO_MEMORY)

View file

@ -1,107 +0,0 @@
/*
framerate.h - framerate calculations
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_FRAMERATE_H
#define LUMIERA_FRAMERATE_H
#include <limits.h>
#include "lib/error.h"
/**
* @file Framerate calculations, header.
*/
/**
* framerates are defined as a rational number
* for example NTSC with 30000/1001fps
*/
struct lumiera_framerate_struct
{
unsigned n; //numerator
unsigned d; //denominator
};
typedef struct lumiera_framerate_struct lumiera_framerate;
typedef lumiera_framerate* LumieraFramerate;
typedef signed long lumiera_framepos;
LUMIERA_ERROR_DECLARE(FRAMERATE_ILLEGAL_TIME);
LUMIERA_ERROR_DECLARE(FRAMERATE_ILLEGAL_FRAME);
#define LUMIERA_FRAMEPOS_ERROR LONG_MIN
/**
* Get the frame number of a given time at a given frame rate.
* frame indexing starts with 1
* @param framerate is a pointer to the framerate used, defined as rational number. Must be given.
* @param time is a pointer to a lumiera_time which shall be converted.
* @return frame at the given time or LUMIERA_FRAMEPOS_ERROR on error.
*/
static inline lumiera_framepos
lumiera_framerate_frame_get_time (const LumieraFramerate framerate, LumieraTime time)
{
REQUIRE (framerate);
if (!time || time->tv_sec == (time_t)-1)
{
lumiera_error_set(LUMIERA_ERROR_FRAMERATE_ILLEGAL_TIME);
return LUMIERA_FRAMEPOS_ERROR;
}
/* we add a magic microsecond for rounding, because of integer truncation frames may be calculated at most 1us earlier,
the idea is to compensate odd framerates which fall out off microsecond precision.
*/
return ((time->tv_sec * 1000000ULL + time->tv_usec + /*magic*/1) * framerate->n)/(framerate->d * 1000000ULL) + 1;
}
/**
* Get the start time for a frame.
* frame indexing starts with 1
* @param framerate is a pointer to the framerate used, defined as rational number. Must be given.
* @param time is a pointer to a lumiera_time which shall take the result.
* @param frame frame number to be converted to time. This frame number must be greater than 0.
* @return the pointer given in time or NULL on error (or when it was given as time).
*/
static inline LumieraTime
lumiera_framerate_time_get_time_frame (const LumieraFramerate framerate,
LumieraTime time,
lumiera_framepos frame)
{
REQUIRE (framerate);
if (time)
{
if (frame < 1)
{
lumiera_error_set(LUMIERA_ERROR_FRAMERATE_ILLEGAL_FRAME);
return NULL;
}
unsigned long long usec = ((frame-1) * framerate->d * 1000000ULL - (/*magic*/frame>1?1:0)) / framerate->n;
time->tv_sec = usec / 1000000;
time->tv_usec = usec % 1000000;
}
return time;
}
#endif

View file

@ -27,7 +27,8 @@
#include <stddef.h>
/**
* @file Intrusive cyclic double linked list
* @file
* Intrusive cyclic double linked list
* There is only one node type which contains a forward and a backward pointer. In a empty initialized node,
* this pointers point to the node itself. Note that these pointers can never ever become NULL.
* This lists are used by using one node as 'root' node where its both pointers are the head/tail pointer to the actual list.
@ -88,6 +89,7 @@ typedef llist * LList;
typedef const llist * const_LList;
typedef llist ** LList_ref;
/**
* Macro to instantiate a local llist.
* @param name of the llist node
@ -95,6 +97,14 @@ typedef llist ** LList_ref;
#define LLIST_AUTO(name) llist name = {&name,&name}
/*
some macros for convenience
*/
#define llist_insert_head(list, element) llist_insert_next (list, element)
#define llist_insert_tail(list, element) llist_insert_prev (list, element)
#define llist_head llist_next
#define llist_tail llist_prev
/**
* cast back from a member of a structure to a pointer of the structure
*/
@ -129,6 +139,30 @@ typedef llist ** LList_ref;
! llist_is_end (node, list); \
llist_backward (&node))
/**
* Iterate forward over a range.
* @param start first node to be interated
* @param end node after the last node be iterated
* @param node pointer to the iterated node
*/
#define LLIST_FORRANGE(start, end, node) \
for (LList node = start; \
node != end; \
llist_forward (&node))
/**
* Iterate backward over a range.
* @param rstart first node to be interated
* @param rend node before the last node be iterated
* @param node pointer to the iterated node
*/
#define LLIST_FORRANGE_REV(rstart, rend, node) \
for (LList node = rstart; \
node != rend; \
llist_backward (&node))
/**
* Consume a list from head.
* The body of this statement should remove the head from the list, else it would be a infinite loop
@ -290,7 +324,7 @@ LLIST_FUNC (LList llist_insert_next (LList self, LList next),
/**
* Insert a node before another.
* @param self node before which we want to insert
* @param prev node which shall be inserted nefore self. Could already linked to a list from where it will be removed.
* @param prev node which shall be inserted before self. Could already linked to a list from where it will be removed.
* @return self
*/
LLIST_FUNC (LList llist_insert_prev (LList self, LList prev),
@ -314,10 +348,9 @@ LLIST_FUNC (LList llist_insertlist_next (LList self, LList next),
if (!llist_is_empty (next))
{
self->next->prev = next->prev;
self->next = next->next;
next->next->prev = self;
next->prev->next = self->next;
self->next = next->next;
next->next->prev = self;
next->prev = next->next = next;
}
@ -335,10 +368,9 @@ LLIST_FUNC (LList llist_insertlist_prev (LList self, LList prev),
if (!llist_is_empty (prev))
{
self->prev->next = prev->next;
self->prev = prev->prev;
prev->prev->next = self;
prev->next->prev = self->prev;
self->prev = prev->prev;
prev->prev->next = self;
prev->prev = prev->next = prev;
}
@ -494,20 +526,45 @@ LLIST_FUNC (LList llist_get_nth_stop (LList self, int n, const_LList stop),
return self;
);
/*
some macros for convenience
*/
#define llist_insert_head(list, element) llist_insert_next (list, element)
#define llist_insert_tail(list, element) llist_insert_prev (list, element)
#define llist_head llist_next
#define llist_tail llist_prev
/**
* Sort a list.
* @param self list to be sorted
* @param cmp function takeing 2 LLists
* simple recursive mergesort
*/
typedef int (*llist_cmpfn)(LList a, LList b);
LLIST_FUNC (LList llist_sort (LList self, llist_cmpfn cmp),
llist left;
llist right;
llist_init (&left);
llist_init (&right);
unsigned n = 0;
if (!llist_is_single (self))
{
LLIST_WHILE_HEAD (self, head)
llist_insert_prev (++n & 1 ? &left : &right, head);
llist_sort (&left, cmp);
llist_sort (&right, cmp);
while (!llist_is_empty (&left) && !llist_is_empty (&right))
llist_insert_prev (self, cmp (left.next, right.next) < 0 ? left.next : right.next);
if (!llist_is_empty (&left))
llist_insertlist_prev (self, &left);
if (!llist_is_empty (&right))
llist_insertlist_prev (self, &right);
}
return self;
)
#endif /* LLIST_H */
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// End:
// arch-tag: e8fe4a59-fd55-4c45-b860-5cd1e0771213
// end_of_file
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/

View file

@ -28,8 +28,14 @@
#include "lib/error.h"
LUMIERA_ERROR_DECLARE (MUTEX_LOCK);
LUMIERA_ERROR_DECLARE (MUTEX_UNLOCK);
LUMIERA_ERROR_DECLARE (MUTEX_DESTROY);
/**
* @file Shared declarations for all locking primitives.
* @file
* Shared declarations for all locking primitives.
*/
/**

58
src/lib/mrucache.c Normal file
View file

@ -0,0 +1,58 @@
/*
mrucache.h - most recent used cache
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/mrucache.h"
LumieraMruCache
lumiera_mrucache_init (LumieraMruCache self, lumiera_cache_destructor_fn destructor_cb)
{
REQUIRE (self);
llist_init (&self->cache_list);
self->cached = 0;
self->destructor_cb = destructor_cb;
return self;
}
LumieraMruCache
lumiera_mrucache_destroy (LumieraMruCache self)
{
LLIST_WHILE_TAIL (&self->cache_list, node)
{
llist_unlink (node);
if (self->destructor_cb)
free (self->destructor_cb (node));
else
free (node);
}
self->cached = 0;
return self;
}
int
lumiera_mrucache_age (LumieraMruCache self, int nelem)
{
REQUIRE (self);
while (self->cached && nelem--)
free (lumiera_mrucache_pop (self));
return nelem;
}

178
src/lib/mrucache.h Normal file
View file

@ -0,0 +1,178 @@
/*
mrucache.h - most recent used cache
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_CACHE_H
#define LUMIERA_CACHE_H
#include "lib/llist.h"
#include <nobug.h>
/**
* @file
* Most recent used cache
* Elements (addressed by a LList node) are either checked in the cache and thereby subject of aging
* or checked out under control of the user. Most operations require that the chache is locked. This locking
* must be done from elsewhere.
*/
/**
* Callback function used to destruct/cleanup aged elements.
* shall clean the element sufficiently up to be ready for being freed or reused,
* this callback function must be reentrant and prepared to be called twice.
* @param node the llist node used to link cache elements (will be empty at call)
* @return pointer to the begin of the element.
*/
typedef void* (*lumiera_cache_destructor_fn)(LList node);
struct lumiera_mrucache_struct
{
llist cache_list;
size_t cached;
lumiera_cache_destructor_fn destructor_cb;
};
typedef struct lumiera_mrucache_struct lumiera_mrucache;
typedef lumiera_mrucache* LumieraMruCache;
/**
* Initialize a cache.
* @param self cache to be initialized
* @param destructor_cb function for destructing a cache node, preparing for reuse.
* @return self
*/
LumieraMruCache
lumiera_mrucache_init (LumieraMruCache self, lumiera_cache_destructor_fn destructor_cb);
/**
* Destroy a cache.
* frees all checked in items.
* @param self cache to be destroyed
* @return self
*/
LumieraMruCache
lumiera_mrucache_destroy (LumieraMruCache self);
/**
* Add an element to a mrucache.
* When added the element is subject of aging and must not be accessed anymore.
* To acces elements they have to be checked out again.
* Checkin and checkout operations must be protected by a lock over the cache.
* @param self cache where to checkin
* @param node a llist member in the cached data which is used as queue in the cache
*/
static inline void
lumiera_mrucache_checkin (LumieraMruCache self, LList node)
{
REQUIRE (self);
REQUIRE (node && llist_is_empty (node));
llist_insert_head (&self->cache_list, node);
++self->cached;
}
/**
* Schedule an element for fast aging.
* When an element is not longer needed it can be placed at the end of the chache
* aging queue and thus become the first one to be reused when a new element is queried.
* This can be done on a checked out element as well as on an element which is in the cache.
* The cache must be locked for this operation.
* @param self cache
* @param node a llist member in the cached data which is used as queue in the cache
*/
static inline void
lumiera_mrucache_drop (LumieraMruCache self, LList node)
{
REQUIRE (self);
REQUIRE (node);
if (llist_is_empty (node))
{
/* was not in list, we need to count it */
++self->cached;
}
else
{
/* speedup loop warning :P, this check is costly */
REQUIRE (llist_is_member (&self->cache_list, node), "node must be empty or member of cache");
}
llist_insert_tail (&self->cache_list, node);
if (self->destructor_cb)
self->destructor_cb (node);
}
/**
* Checkout an element from a cache.
* A checked out element is not under cache control anymore until is gets checked in again.
* The code which checked the element out takes ownership of the element.
* The cache must be locked for this operation.
* @param self cache
* @param node a llist member in the cached data which is used as queue in the cache
*/
static inline void
lumiera_mrucache_checkout (LumieraMruCache self, LList node)
{
REQUIRE (self);
REQUIRE (node && llist_is_member (&self->cache_list, node)); /* speedup loop warning :P, this check is costly */
llist_unlink (node);
--self->cached;
}
/**
* Destroy the oldest element from the cache and return it.
* This function is used to get a new element by deleting the oldest least used one from the cache.
* The cache must be locked for this operation.
* @param self cache
* @return pointer to the uninitialized memory ready for being reused
*/
static inline void*
lumiera_mrucache_pop (LumieraMruCache self)
{
REQUIRE (self);
if (llist_is_empty (&self->cache_list))
return NULL;
LList node = llist_tail (&self->cache_list);
llist_unlink (node);
--self->cached;
if (self->destructor_cb)
return self->destructor_cb (node);
else
return node;
}
/**
* Destroy and free the nelem oldest elements.
* Used to free up resources and memory.
* @param self cache where to free elements.
* @param nelem number of elements wished to be freed
* @return nelem-(numer of elements which got freed), that is 0 if all requested elements got freed
*/
int
lumiera_mrucache_age (LumieraMruCache self, int nelem);
#endif

View file

@ -22,9 +22,14 @@
#include "lib/mutex.h"
/**
* @file Mutual exclusion locking.
* @file
* Mutual exclusion locking.
*/
LUMIERA_ERROR_DEFINE (MUTEX_LOCK, "Mutex locking failed");
LUMIERA_ERROR_DEFINE (MUTEX_UNLOCK, "Mutex unlocking failed");
LUMIERA_ERROR_DEFINE (MUTEX_DESTROY, "Mutex destroy failed");
/**
* Initialize a mutex variable
@ -52,7 +57,7 @@ lumiera_mutex_destroy (LumieraMutex self)
if (self)
{
if (pthread_mutex_destroy (&self->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_DESTROY);
}
return self;
}

View file

@ -25,8 +25,18 @@
#include "lib/locking.h"
/**
* @file Mutual exclusion locking, header.
* @file
* Mutual exclusion locking, header.
*/
#define LUMIERA_MUTEX_SECTION(flag, handle, mutex) \
RESOURCE_HANDLE (rh_##__LINE__##_); \
lumiera_mutexacquirer lock_##__LINE__##_; \
RESOURCE_ENTER (flag, handle, "acquire mutex", &lock_##__LINE__##_, \
NOBUG_RESOURCE_EXCLUSIVE, rh_##__LINE__##_); \
for (lumiera_mutexacquirer_init_mutex (&lock_##__LINE__##_, mutex, LUMIERA_LOCKED); \
lock_##__LINE__##_.state == LUMIERA_LOCKED; \
lumiera_mutexacquirer_unlock (&lock_##__LINE__##_), \
({RESOURCE_LEAVE(flag, rh_##__LINE__##_);}))
/**
@ -106,7 +116,7 @@ lumiera_mutexacquirer_init_mutex (LumieraMutexacquirer self, LumieraMutex mutex,
self->state = state;
if (state == LUMIERA_LOCKED)
if (pthread_mutex_lock (&mutex->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
return self;
}
@ -124,7 +134,7 @@ lumiera_mutexacquirer_lock (LumieraMutexacquirer self)
REQUIRE (self->state == LUMIERA_UNLOCKED, "mutex already locked");
if (pthread_mutex_lock (&self->mutex->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
self->state = LUMIERA_LOCKED;
}
@ -164,7 +174,7 @@ lumiera_mutexacquirer_try_mutex (LumieraMutexacquirer self, LumieraMutex mutex)
case EBUSY:
return LUMIERA_UNLOCKED;
default:
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_LOCK);
}
}
@ -180,7 +190,7 @@ lumiera_mutexacquirer_unlock (LumieraMutexacquirer self)
REQUIRE (self);
REQUIRE (self->state == LUMIERA_LOCKED, "mutex was not locked");
if (pthread_mutex_unlock (&self->mutex->mutex))
LUMIERA_DIE;
LUMIERA_DIE (MUTEX_UNLOCK);
self->state = LUMIERA_UNLOCKED;
}

View file

@ -25,11 +25,14 @@
#include <dlfcn.h>
#include <pthread.h>
#include <time.h>
#include <limits.h>
#include "plugin.h"
#include "safeclib.h"
/**
* @file Plugin loader.
* @file
* Plugin loader.
*/
@ -159,8 +162,8 @@ lumiera_plugin_lookup (struct lumiera_plugin* self, const char* path)
{
/* got it */
TRACE (lumiera_plugin, "found %s", pathname);
self->pathname = strdup (pathname);
if (!self->pathname) LUMIERA_DIE;
self->pathname = lumiera_strndup (pathname, PATH_MAX);
self->type = lumiera_plugin_extensions[i].type;
return 0;
}
@ -195,21 +198,20 @@ lumiera_interface_open (const char* name, const char* interface, size_t min_revi
plugin.name = name; /* for searching */
found = tsearch (&plugin, &lumiera_plugin_registry, lumiera_plugin_name_cmp);
if (!found) LUMIERA_DIE;
if (!found)
LUMIERA_DIE (NO_MEMORY);
if (*found == &plugin)
{
NOTICE (lumiera_plugin, "new plugin");
/* now really create new item */
*found = malloc (sizeof (struct lumiera_plugin));
if (!*found) LUMIERA_DIE;
*found = lumiera_malloc (sizeof (struct lumiera_plugin));
if (name) /* NULL is main app, no lookup needed */
{
/*lookup for $LUMIERA_PLUGIN_PATH*/
(*found)->name = strdup (name);
if (!(*found)->name) LUMIERA_DIE;
(*found)->name = lumiera_strndup (name, PATH_MAX);
if (!!lumiera_plugin_lookup (*found, getenv("LUMIERA_PLUGIN_PATH"))
#ifdef LUMIERA_PLUGIN_PATH

View file

@ -33,7 +33,8 @@ extern "C" {
#include "error.h"
/**
* @file Plugin loader, header.
* @file
* Plugin loader, header.
*/

View file

@ -19,9 +19,11 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/references.h"
#include "lib/safeclib.h"
/**
* @file Strong and Weak references
* @file
* Strong and Weak references
* Strong references keep some object alive while they existing
* Weak references become invalidated when the referenced object gets destroyed
*
@ -43,8 +45,7 @@
LumieraReference
lumiera_reference_strong_init_once (LumieraReference self, void* obj, void (*dtor)(void*))
{
LumieraReftarget target = malloc (sizeof(lumiera_reftarget));
if (!target) LUMIERA_DIE;
LumieraReftarget target = lumiera_malloc (sizeof(lumiera_reftarget));
target->object = obj;
target->dtor = dtor;

View file

@ -25,7 +25,8 @@
#include <nobug.h>
/**
* @file Strong and Weak references, header.
* @file
* Strong and Weak references, header.
*/

View file

@ -18,16 +18,19 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define _GNU_SOURCE
#include <errno.h>
#include "lib/rwlock.h"
LUMIERA_ERROR_DEFINE(RWLOCK_AGAIN, "maximum number of readlocks exceed");
LUMIERA_ERROR_DEFINE(RWLOCK_DEADLOCK, "deadlock detected");
LUMIERA_ERROR_DEFINE(RWLOCK_DESTROY, "destroy rwlock");
LUMIERA_ERROR_DEFINE(RWLOCK_UNLOCK, "unlock");
LUMIERA_ERROR_DEFINE(RWLOCK_RLOCK, "rlock");
LUMIERA_ERROR_DEFINE(RWLOCK_WLOCK, "wlock");
/**
* @file Read/write locks.
* @file
* Read/write locks.
*/
@ -57,7 +60,7 @@ lumiera_rwlock_destroy (LumieraRWLock self)
if (self)
{
if (pthread_rwlock_destroy (&self->rwlock))
LUMIERA_DIE;
LUMIERA_DIE (RWLOCK_DESTROY);
}
return self;
}
@ -95,7 +98,7 @@ lumiera_rwlockacquirer_init (LumieraRWLockacquirer self, LumieraRWLock rwlock, e
lumiera_error_set (LUMIERA_ERROR_RWLOCK_DEADLOCK);
return NULL;
default:
LUMIERA_DIE;
LUMIERA_DIE (RWLOCK_RLOCK);
}
case LUMIERA_WRLOCKED:
switch (pthread_rwlock_wrlock (&rwlock->rwlock))
@ -106,7 +109,7 @@ lumiera_rwlockacquirer_init (LumieraRWLockacquirer self, LumieraRWLock rwlock, e
lumiera_error_set (LUMIERA_ERROR_RWLOCK_DEADLOCK);
return NULL;
default:
LUMIERA_DIE;
LUMIERA_DIE (RWLOCK_WLOCK);
}
default:
break;
@ -138,7 +141,7 @@ lumiera_rwlockacquirer_rdlock (LumieraRWLockacquirer self)
lumiera_error_set (LUMIERA_ERROR_RWLOCK_DEADLOCK);
return NULL;
default:
LUMIERA_DIE;
LUMIERA_DIE (RWLOCK_RLOCK);
}
self->state = LUMIERA_RDLOCKED;
@ -166,7 +169,7 @@ lumiera_rwlockacquirer_wrlock (LumieraRWLockacquirer self)
lumiera_error_set (LUMIERA_ERROR_RWLOCK_DEADLOCK);
return NULL;
default:
LUMIERA_DIE;
LUMIERA_DIE (RWLOCK_WLOCK);
}
self->state = LUMIERA_WRLOCKED;

View file

@ -33,9 +33,14 @@
LUMIERA_ERROR_DECLARE(RWLOCK_AGAIN);
LUMIERA_ERROR_DECLARE(RWLOCK_DEADLOCK);
LUMIERA_ERROR_DECLARE(RWLOCK_DESTROY);
LUMIERA_ERROR_DECLARE(RWLOCK_UNLOCK);
LUMIERA_ERROR_DECLARE(RWLOCK_RLOCK);
LUMIERA_ERROR_DECLARE(RWLOCK_WLOCK);
/**
* @file Read/write locks, header.
* @file
* Read/write locks, header.
*/
@ -106,7 +111,7 @@ lumiera_rwlockacquirer_unlock (LumieraRWLockacquirer self)
REQUIRE (self);
REQUIRE (self->state != LUMIERA_UNLOCKED, "rwlock was not locked");
if (pthread_rwlock_unlock (&self->rwlock->rwlock))
LUMIERA_DIE;
LUMIERA_DIE (RWLOCK_UNLOCK);
self->state = LUMIERA_UNLOCKED;
}

225
src/lib/safeclib.c Normal file
View file

@ -0,0 +1,225 @@
/*
safe_clib.c - Portable and safe wrapers around some clib functions and some tools
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "error.h"
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <stdarg.h>
/**
* @file
* Portable and safe wrapers around some clib functions and some tools
*/
LUMIERA_ERROR_DEFINE (NO_MEMORY, "Out of Memory!");
/**
* Allocate memory.
* always succeeds or dies
* @param size memory to be allocated
* @return pointer to the allocated memory
*/
void*
lumiera_malloc (size_t size)
{
void* o = size ? malloc (size) : NULL;
if (!o)
LUMIERA_DIE (NO_MEMORY);
return o;
}
/**
* Allocate cleared memory for an array.
* always succeeds or dies
* @param n number of elements
* @param size memory to be allocated
* @return pointer to the allocated memory
*/
void*
lumiera_calloc (size_t n, size_t size)
{
void* o = (n&&size)? calloc (n, size) : NULL;
if (!o)
LUMIERA_DIE (NO_MEMORY);
return o;
}
/**
* Duplicate a C string.
* always succeeds or dies
* @param str string to be copied
* @param len maximal length to be copied
* @return pointer to the new string, "" if NULL was passed as str
*/
char*
lumiera_strndup (const char* str, size_t len)
{
char* o;
if (str)
o = strndup (str, len);
else
o = strdup ("");
if (!o)
LUMIERA_DIE (NO_MEMORY);
return o;
}
/**
* Compare two C strings.
* Handles NULL pointers as "", shortcut for same addresses
* @param a first string for comparsion
* @param b second string for comparsion
* @param len maximal length for the comparsion
* @return 0 if the strings are identical, -1 if smaller 1 if bigger.
*/
int
lumiera_strncmp (const char* a, const char* b, size_t len)
{
return a == b ? 0 : strncmp (a?a:"", b?b:"", len);
}
/**
* check 2 strings for identity.
* @param a first string for comparsion
* @param b second string for comparsion
* @return 1 when the strings are the the same, 0 if not.
*/
int
lumiera_streq (const char* a, const char* b)
{
return !lumiera_strncmp (a, b, SIZE_MAX);
}
/**
* Round robin temporary buffers.
* This provides 64 buffers per thread which are recycled with each use.
* The idea here is to have fast buffers for temporal data without need for explicit heap management.
*/
struct lumiera_tmpbuf_struct
{
void* buffers[64];
size_t sizes[64];
unsigned idx;
};
static pthread_once_t lumiera_tmpbuf_tls_once = PTHREAD_ONCE_INIT;
static pthread_key_t lumiera_tmpbuf_tls_key;
void
lumiera_tmpbuf_freeall (void);
static void
lumiera_tmpbuf_destroy (void* buf)
{
lumiera_tmpbuf_freeall ();
}
static void
lumiera_tmpbuf_init (void)
{
pthread_key_create (&lumiera_tmpbuf_tls_key, lumiera_tmpbuf_destroy);
}
/**
* free all buffers associated with this thread.
* This function is called automatically, usually one doesnt need to call it.
*/
void
lumiera_tmpbuf_freeall (void)
{
pthread_once (&lumiera_tmpbuf_tls_once, lumiera_tmpbuf_init);
struct lumiera_tmpbuf_struct* buf = pthread_getspecific (lumiera_tmpbuf_tls_key);
if (buf)
{
pthread_setspecific (lumiera_tmpbuf_tls_key, NULL);
for (int idx = 0; idx < 64; ++idx)
free (buf->buffers[idx]);
free (buf);
}
}
/**
* Query a thread local buffer.
* @param size minimal needed size for the buffer
* @return the buffer
*/
void*
lumiera_tmpbuf_provide (size_t size)
{
pthread_once (&lumiera_tmpbuf_tls_once, lumiera_tmpbuf_init);
struct lumiera_tmpbuf_struct* buf = pthread_getspecific (lumiera_tmpbuf_tls_key);
if (!buf)
pthread_setspecific (lumiera_tmpbuf_tls_key,
buf = lumiera_calloc (1, sizeof (struct lumiera_tmpbuf_struct)));
buf->idx = (buf->idx + 1) & 0x3f;
if (buf->sizes[buf->idx] < size || buf->sizes[buf->idx] > 8*size)
{
free (buf->buffers[buf->idx]);
buf->sizes[buf->idx] = (size+4*sizeof(long)) & ~(4*sizeof(long)-1);
buf->buffers[buf->idx] = lumiera_malloc (buf->sizes[buf->idx]);
}
return buf->buffers[buf->idx];
}
char*
lumiera_tmpbuf_strndup (const char* src, size_t size)
{
size_t len = strlen (src);
len = len > size ? size : len;
char* buf = lumiera_tmpbuf_provide (len + 1);
strncpy (buf, src, len);
buf[len] = '\0';
return buf;
}
char*
lumiera_tmpbuf_snprintf (size_t size, const char* fmt, ...)
{
va_list args;
va_start (args, fmt);
size_t len = vsnprintf (NULL, 0, fmt, args);
va_end (args);
len = len > size ? size : len;
char* buf = lumiera_tmpbuf_provide (len+1);
va_start (args, fmt);
vsnprintf (buf, len+1, fmt, args);
va_end (args);
return buf;
}

125
src/lib/safeclib.h Normal file
View file

@ -0,0 +1,125 @@
/*
safe_clib.h - Portable and safe wrapers around some clib functions and some tools
Copyright (C) CinelerraCV
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "error.h"
#include <stdlib.h>
/**
* @file
* Portable and safe wrapers around some clib functions and some tools
*/
LUMIERA_ERROR_DECLARE(NO_MEMORY);
/**
* Allocate memory.
* always succeeds or dies
* @param size memory to be allocated
* @return pointer to the allocated memory
*/
void*
lumiera_malloc (size_t sz);
/**
* Allocate cleared memory for an array.
* always succeeds or dies
* @param n number of elements
* @param size memory to be allocated
* @return pointer to the allocated memory
*/
void*
lumiera_calloc (size_t n, size_t size);
/**
* Duplicate a C string.
* always succeeds or dies
* @param str string to be copied
* @param len maximal length to be copied
* @return pointer to the new string, "" if NULL was passed as str
*/
char*
lumiera_strndup (const char* str, size_t len);
/**
* Compare two C strings.
* Handles NULL pointers as "", shortcut for same addresses
* @param a first string for comparsion
* @param b second string for comparsion
* @param len maximal length for the comparsion
* @return 0 if the strings are identical, -1 if smaller 1 if bigger.
*/
int
lumiera_strncmp (const char* a, const char* b, size_t len);
/**
* check 2 strings for identity.
* @param a first string for comparsion
* @param b second string for comparsion
* @return 1 when the strings are the the same, 0 if not.
*/
int
lumiera_streq (const char* a, const char* b);
/**
* Round robin temporary buffers.
* This provides 64 buffers per thread which are recycled with each use.
* The idea here is to have fast buffers for temporal data without need for explicit heap management.
*/
/**
* free all buffers associated with this thread.
* This function is called automatically, usually one doesnt need to call it.
*/
void
lumiera_tmpbuf_freeall (void);
/**
* Query a thread local tmpbuf.
* @param size minimal needed size for the tmpbuf
* @return the tmpbuf
*/
void*
lumiera_tmpbuf_provide (size_t size);
/**
* Duplicate string to a tmpbuf.
* @param src string to be duplicated
* @param size maximal length to be copied
* @return temporary buffer containing a copy of the string
*/
char*
lumiera_tmpbuf_strndup (const char* src, size_t size);
/**
* Construct a string in a tmpbuf.
* @param size maximal length for the string
* @param fmt printf like formatstring
* @param ... parameters
* @return temporary buffer containing the constructed of the string
*/
char*
lumiera_tmpbuf_snprintf (size_t size, const char* fmt, ...);

95
src/lib/uuid.c Normal file
View file

@ -0,0 +1,95 @@
/*
uuid - Universal unique identifiers
Copyright (C) CinelerraCV
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/uuid.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
void
lumiera_uuid_set_ptr (lumiera_uuid* uuid, void* ptr)
{
memset (uuid, 0, 16);
*(void**)uuid = ptr;
}
void*
lumiera_uuid_ptr_get (lumiera_uuid* uuid)
{
return *(void**)uuid;
}
void
lumiera_uuid_gen (lumiera_uuid* uuid)
{
static int fd = -2;
if (!uuid)
return;
if (fd == -2)
{
fd = open ("/dev/urandom", O_RDONLY);
if (fd == -1)
fd = open ("/dev/random", O_RDONLY);
if (fd >= 0)
fcntl (fd, F_SETFD, FD_CLOEXEC);
else
srand (getpid () + time (NULL));
}
if (fd < 0)
{
for (int i = 0; i < 16; ++i)
((unsigned char*)uuid)[i] = (unsigned char)(rand()>>7);
}
else
{
if (read (fd, uuid, 16) < 0)
abort ();
}
}
void
lumiera_uuid_copy (lumiera_uuid* dest, lumiera_uuid* src)
{
memcpy (dest, src, 16);
}
int
lumiera_uuid_eq (lumiera_uuid* uuida, lumiera_uuid* uuidb)
{
return !memcmp (uuida, uuidb, 16);
}
size_t
lumiera_uuid_hash (lumiera_uuid* uuid)
{
return *(size_t*)uuid;
}

67
src/lib/uuid.h Normal file
View file

@ -0,0 +1,67 @@
/*
uuid - Universal unique identifiers
Copyright (C) CinelerraCV
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LUMIERA_UUID_H
#define LUMIERA_UUID_H
#include <stdlib.h>
typedef unsigned char lumiera_uuid[16];
/**
* Retrieve a generic pointer stored in a uuid
*/
void*
lumiera_uuid_ptr_get (lumiera_uuid* uuid);
/**
* Generate a new uuid
*/
void
lumiera_uuid_gen (lumiera_uuid* uuid);
/**
* Store a generic pointer in a uuid
*/
void
lumiera_uuid_set_ptr (lumiera_uuid* uuid, void* ptr);
/**
* Copy an uuid
*/
void
lumiera_uuid_copy (lumiera_uuid* dest, lumiera_uuid* src);
/**
* Test 2 uuid's for equality
*/
int
lumiera_uuid_eq (lumiera_uuid* uuida, lumiera_uuid* uuidb);
/**
* Generate a hashsum over an uuid
*/
size_t
lumiera_uuid_hash (lumiera_uuid* uuid);
#endif

251
src/proc/Makefile.am Normal file
View file

@ -0,0 +1,251 @@
# Copyright (C) Lumiera.org
# 2008, Christian Thaeter <ct@pipapo.org>
#
# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
# TODO use -Wextra -Werror
liblumiproc_a_srcdir = $(top_srcdir)/src/proc
noinst_LIBRARIES += liblumiproc.a
liblumiproc_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiproc_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiproc_a_SOURCES = \
$(liblumiproc_a_srcdir)/controllerfacade.cpp \
$(liblumiproc_a_srcdir)/frame.cpp \
$(liblumiproc_a_srcdir)/stateproxy.cpp \
$(liblumiproc_a_srcdir)/asset.cpp \
$(liblumiproc_a_srcdir)/assetmanager.cpp \
$(liblumiproc_a_srcdir)/nobugcfg.cpp
liblumiprocasset_a_srcdir = $(top_srcdir)/src/proc/asset
noinst_LIBRARIES += liblumiprocasset.a
liblumiprocasset_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiprocasset_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiprocasset_a_SOURCES = \
$(liblumiprocasset_a_srcdir)/codec.cpp \
$(liblumiprocasset_a_srcdir)/compoundmedia.cpp \
$(liblumiprocasset_a_srcdir)/dataset.cpp \
$(liblumiprocasset_a_srcdir)/effect.cpp \
$(liblumiprocasset_a_srcdir)/preview.cpp \
$(liblumiprocasset_a_srcdir)/unknown.cpp \
$(liblumiprocasset_a_srcdir)/clip.cpp \
$(liblumiprocasset_a_srcdir)/meta.cpp \
$(liblumiprocasset_a_srcdir)/category.cpp \
$(liblumiprocasset_a_srcdir)/media.cpp \
$(liblumiprocasset_a_srcdir)/pipe.cpp \
$(liblumiprocasset_a_srcdir)/proc.cpp \
$(liblumiprocasset_a_srcdir)/procpatt.cpp \
$(liblumiprocasset_a_srcdir)/struct.cpp \
$(liblumiprocasset_a_srcdir)/track.cpp
liblumiprocengine_a_srcdir = $(top_srcdir)/src/proc/engine
noinst_LIBRARIES += liblumiprocengine.a
liblumiprocengine_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiprocengine_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiprocengine_a_SOURCES = \
$(liblumiprocengine_a_srcdir)/aframe.cpp \
$(liblumiprocengine_a_srcdir)/arender.cpp \
$(liblumiprocengine_a_srcdir)/codecadapter.cpp \
$(liblumiprocengine_a_srcdir)/exitnode.cpp \
$(liblumiprocengine_a_srcdir)/glbuf.cpp \
$(liblumiprocengine_a_srcdir)/glpipe.cpp \
$(liblumiprocengine_a_srcdir)/glrender.cpp \
$(liblumiprocengine_a_srcdir)/hub.cpp \
$(liblumiprocengine_a_srcdir)/link.cpp \
$(liblumiprocengine_a_srcdir)/mask.cpp \
$(liblumiprocengine_a_srcdir)/pluginadapter.cpp \
$(liblumiprocengine_a_srcdir)/processor.cpp \
$(liblumiprocengine_a_srcdir)/procnode.cpp \
$(liblumiprocengine_a_srcdir)/projector.cpp \
$(liblumiprocengine_a_srcdir)/renderengine.cpp \
$(liblumiprocengine_a_srcdir)/source.cpp \
$(liblumiprocengine_a_srcdir)/trafo.cpp \
$(liblumiprocengine_a_srcdir)/vframe.cpp \
$(liblumiprocengine_a_srcdir)/vrender.cpp
liblumiprocmobject_a_srcdir = $(top_srcdir)/src/proc/mobject
noinst_LIBRARIES += liblumiprocmobject.a
liblumiprocmobject_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiprocmobject_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiprocmobject_a_SOURCES = \
$(liblumiprocmobject_a_srcdir)/builderfacade.cpp \
$(liblumiprocmobject_a_srcdir)/interpolator.cpp \
$(liblumiprocmobject_a_srcdir)/mobject.cpp \
$(liblumiprocmobject_a_srcdir)/parameter.cpp \
$(liblumiprocmobject_a_srcdir)/paramprovider.cpp \
$(liblumiprocmobject_a_srcdir)/placement.cpp
liblumiprocmobjectbuilder_a_srcdir = $(top_srcdir)/src/proc/mobject/builder
noinst_LIBRARIES += liblumiprocmobjectbuilder.a
liblumiprocmobjectbuilder_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiprocmobjectbuilder_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiprocmobjectbuilder_a_SOURCES = \
$(liblumiprocmobjectbuilder_a_srcdir)/assembler.cpp \
$(liblumiprocmobjectbuilder_a_srcdir)/conmanager.cpp \
$(liblumiprocmobjectbuilder_a_srcdir)/nodecreatertool.cpp \
$(liblumiprocmobjectbuilder_a_srcdir)/segmentationtool.cpp \
$(liblumiprocmobjectbuilder_a_srcdir)/toolfactory.cpp
liblumiprocmobjectcontroller_a_srcdir = $(top_srcdir)/src/proc/mobject/controller
noinst_LIBRARIES += liblumiprocmobjectcontroller.a
liblumiprocmobjectcontroller_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiprocmobjectcontroller_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiprocmobjectcontroller_a_SOURCES = \
$(liblumiprocmobjectcontroller_a_srcdir)/pathmanager.cpp \
$(liblumiprocmobjectcontroller_a_srcdir)/renderstate.cpp
liblumiprocmobjectsession_a_srcdir = $(top_srcdir)/src/proc/mobject/session
noinst_LIBRARIES += liblumiprocmobjectsession.a
liblumiprocmobjectsession_a_CXXFLAGS = $(CXXFLAGS) -Wall
liblumiprocmobjectsession_a_CPPFLAGS = -I$(top_srcdir)/src/
liblumiprocmobjectsession_a_SOURCES = \
$(liblumiprocmobjectsession_a_srcdir)/abstractmo.cpp \
$(liblumiprocmobjectsession_a_srcdir)/allocation.cpp \
$(liblumiprocmobjectsession_a_srcdir)/auto.cpp \
$(liblumiprocmobjectsession_a_srcdir)/compoundclip.cpp \
$(liblumiprocmobjectsession_a_srcdir)/effect.cpp \
$(liblumiprocmobjectsession_a_srcdir)/fixedlocation.cpp \
$(liblumiprocmobjectsession_a_srcdir)/label.cpp \
$(liblumiprocmobjectsession_a_srcdir)/meta.cpp \
$(liblumiprocmobjectsession_a_srcdir)/relativelocation.cpp \
$(liblumiprocmobjectsession_a_srcdir)/segment.cpp \
$(liblumiprocmobjectsession_a_srcdir)/simpleclip.cpp \
$(liblumiprocmobjectsession_a_srcdir)/plug.cpp \
$(liblumiprocmobjectsession_a_srcdir)/sessionimpl.cpp \
$(liblumiprocmobjectsession_a_srcdir)/sessmanagerimpl.cpp \
$(liblumiprocmobjectsession_a_srcdir)/edl.cpp \
$(liblumiprocmobjectsession_a_srcdir)/session.cpp \
$(liblumiprocmobjectsession_a_srcdir)/track.cpp \
$(liblumiprocmobjectsession_a_srcdir)/clip.cpp \
$(liblumiprocmobjectsession_a_srcdir)/constraint.cpp \
$(liblumiprocmobjectsession_a_srcdir)/defsmanager.cpp \
$(liblumiprocmobjectsession_a_srcdir)/fixture.cpp \
$(liblumiprocmobjectsession_a_srcdir)/locatingpin.cpp \
$(liblumiprocmobjectsession_a_srcdir)/mobjectfactory.cpp \
$(liblumiprocmobjectsession_a_srcdir)/wish.cpp
noinst_HEADERS += \
$(liblumiproc_a_srcdir)/asset/category.hpp \
$(liblumiproc_a_srcdir)/asset/clip.hpp \
$(liblumiproc_a_srcdir)/asset/codec.hpp \
$(liblumiproc_a_srcdir)/asset/compoundmedia.hpp \
$(liblumiproc_a_srcdir)/asset/dataset.hpp \
$(liblumiproc_a_srcdir)/asset/effect.hpp \
$(liblumiproc_a_srcdir)/asset/preview.hpp \
$(liblumiproc_a_srcdir)/asset/db.hpp \
$(liblumiproc_a_srcdir)/asset/buildinstruct.hpp \
$(liblumiproc_a_srcdir)/asset/media.hpp \
$(liblumiproc_a_srcdir)/asset/meta.hpp \
$(liblumiproc_a_srcdir)/asset/pipe.hpp \
$(liblumiproc_a_srcdir)/asset/proc.hpp \
$(liblumiproc_a_srcdir)/asset/procpatt.hpp \
$(liblumiproc_a_srcdir)/asset/struct.hpp \
$(liblumiproc_a_srcdir)/asset/structfactoryimpl.hpp \
$(liblumiproc_a_srcdir)/asset/track.hpp \
$(liblumiproc_a_srcdir)/asset/unknown.hpp \
$(liblumiproc_a_srcdir)/controllerfacade.hpp \
$(liblumiproc_a_srcdir)/engine/aframe.hpp \
$(liblumiproc_a_srcdir)/engine/arender.hpp \
$(liblumiproc_a_srcdir)/engine/codecadapter.hpp \
$(liblumiproc_a_srcdir)/engine/exitnode.hpp \
$(liblumiproc_a_srcdir)/engine/glbuf.hpp \
$(liblumiproc_a_srcdir)/engine/glpipe.hpp \
$(liblumiproc_a_srcdir)/engine/glrender.hpp \
$(liblumiproc_a_srcdir)/engine/hub.hpp \
$(liblumiproc_a_srcdir)/engine/link.hpp \
$(liblumiproc_a_srcdir)/engine/mask.hpp \
$(liblumiproc_a_srcdir)/engine/pluginadapter.hpp \
$(liblumiproc_a_srcdir)/engine/procnode.hpp \
$(liblumiproc_a_srcdir)/engine/projector.hpp \
$(liblumiproc_a_srcdir)/engine/renderengine.hpp \
$(liblumiproc_a_srcdir)/engine/source.hpp \
$(liblumiproc_a_srcdir)/engine/trafo.hpp \
$(liblumiproc_a_srcdir)/engine/vframe.hpp \
$(liblumiproc_a_srcdir)/engine/vrender.hpp \
$(liblumiproc_a_srcdir)/engine/processor.hpp \
$(liblumiproc_a_srcdir)/frame.hpp \
$(liblumiproc_a_srcdir)/mobject/builder/assembler.hpp \
$(liblumiproc_a_srcdir)/mobject/builder/buildertool.hpp \
$(liblumiproc_a_srcdir)/mobject/builder/conmanager.hpp \
$(liblumiproc_a_srcdir)/mobject/builder/nodecreatertool.hpp \
$(liblumiproc_a_srcdir)/mobject/builder/segmentationtool.hpp \
$(liblumiproc_a_srcdir)/mobject/builder/toolfactory.hpp \
$(liblumiproc_a_srcdir)/mobject/builderfacade.hpp \
$(liblumiproc_a_srcdir)/mobject/controller/pathmanager.hpp \
$(liblumiproc_a_srcdir)/mobject/controller/renderstate.hpp \
$(liblumiproc_a_srcdir)/mobject/interpolator.hpp \
$(liblumiproc_a_srcdir)/mobject/parameter.hpp \
$(liblumiproc_a_srcdir)/mobject/paramprovider.hpp \
$(liblumiproc_a_srcdir)/mobject/session/abstractmo.hpp \
$(liblumiproc_a_srcdir)/mobject/session/allocation.hpp \
$(liblumiproc_a_srcdir)/mobject/session/auto.hpp \
$(liblumiproc_a_srcdir)/mobject/session/compoundclip.hpp \
$(liblumiproc_a_srcdir)/mobject/session/effect.hpp \
$(liblumiproc_a_srcdir)/mobject/session/fixedlocation.hpp \
$(liblumiproc_a_srcdir)/mobject/session/label.hpp \
$(liblumiproc_a_srcdir)/mobject/session/meta.hpp \
$(liblumiproc_a_srcdir)/mobject/session/relativelocation.hpp \
$(liblumiproc_a_srcdir)/mobject/session/simpleclip.hpp \
$(liblumiproc_a_srcdir)/mobject/session/mobjectfactory.hpp \
$(liblumiproc_a_srcdir)/mobject/session/segment.hpp \
$(liblumiproc_a_srcdir)/mobject/session/track.hpp \
$(liblumiproc_a_srcdir)/mobject/session/wish.hpp \
$(liblumiproc_a_srcdir)/mobject/session/clip.hpp \
$(liblumiproc_a_srcdir)/mobject/session/constraint.hpp \
$(liblumiproc_a_srcdir)/mobject/session/defsmanager.hpp \
$(liblumiproc_a_srcdir)/mobject/session/edl.hpp \
$(liblumiproc_a_srcdir)/mobject/session/fixture.hpp \
$(liblumiproc_a_srcdir)/mobject/session/locatingpin.hpp \
$(liblumiproc_a_srcdir)/mobject/session/plug.hpp \
$(liblumiproc_a_srcdir)/mobject/session/sessionimpl.hpp \
$(liblumiproc_a_srcdir)/mobject/session/defsregistry.hpp \
$(liblumiproc_a_srcdir)/mobject/explicitplacement.hpp \
$(liblumiproc_a_srcdir)/mobject/mobject.hpp \
$(liblumiproc_a_srcdir)/mobject/placement.hpp \
$(liblumiproc_a_srcdir)/mobject/session.hpp \
$(liblumiproc_a_srcdir)/stateproxy.hpp \
$(liblumiproc_a_srcdir)/asset.hpp \
$(liblumiproc_a_srcdir)/assetmanager.hpp \
$(liblumiproc_a_srcdir)/lumiera.hpp \
$(liblumiproc_a_srcdir)/nobugcfg.hpp

28
tests/15safeclib.tests Normal file
View file

@ -0,0 +1,28 @@
TESTING "Safe clib and tools" ./test-safeclib
TEST "Allocating 0 bytes" allocation0 <<END
return: 134
END
TEST "Allocating some memory" allocation1024 <<END
return: 0
END
TEST "Allocation error" allocationtoobig <<END
return: 134
END
TEST "string equal check" streq <<END
return: 0
END
TEST "temporary buffers" tmpbuf <<END
return: 0
END

15
tests/15uuid.tests Normal file
View file

@ -0,0 +1,15 @@
TESTING "UUID's" ./test-uuid
TEST "uuid generate" uuidgen_2 <<END
out: 0
END
TEST "uuid copy" uuidgen_copy <<END
out: 1
END
TEST "storing pointers" ptrs <<END
out: 1
END

View file

@ -0,0 +1,26 @@
TESTING "Filedescriptor management" ./test-filedescriptors
echo testdata > ,tmp_testfile
TEST "acquire existing file" acquire_existing <<END
return: 0
END
TEST "acquire existing file twice" acquire_existing_again <<END
return: 0
END
rm ,tmp_testfile
TEST "acquire file, creating it" acquire_create <<END
return: 0
END
rm ,tmp_testfile
TEST "acquire file, creating it, nested dir" acquire_create_dir <<END
return: 0
END
rm ,tmp_testdir -r

13
tests/20filehandle.tests Normal file
View file

@ -0,0 +1,13 @@
TESTING "Filehandle management" ./test-filehandles
TEST "basic filehandle usage" basic <<END
return: 0
END
rm -rf ,tmpdir
TEST "using many filehandles" more <<END
return: 0
END

View file

@ -62,7 +62,7 @@ out: caught error::Logic: LUMIERA_ERROR_FATAL:floundered (test-2).
out: caught error::Invalid: LUMIERA_ERROR_INVALID:invalid input or parameters (test-3).
out: caught lumiera::Error: LUMIERA_ERROR_EXTERNAL:failure in external service (test-4).
out: caught std::runtime_error: test-5
out: caught std::exception: St9exception
out: caught std::exception: std::exception
out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external service (test-7).....will rethrow as error::State
out: caught lumiera::Error: LUMIERA_ERROR_STATE:unforseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service (test-7).
out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external service (test-8).....will rethrow as error::State

View file

@ -1,5 +1,5 @@
# Copyright (C) Lumiera.org
# 2007, Christian Thaeter <ct@pipapo.org>
# 2007-2008, Christian Thaeter <ct@pipapo.org>
# Hermann Vosseler <Ichthyostega@web.de>
#
# This program is free software; you can redistribute it and/or
@ -36,14 +36,29 @@ test_llist_SOURCES = $(tests_srcdir)/library/test-llist.c
test_llist_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
test_llist_LDADD = liblumi.a -lnobugmt -lpthread -ldl -lm
check_PROGRAMS += test-safeclib
test_safeclib_SOURCES = $(tests_srcdir)/library/test-safeclib.c
test_safeclib_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
test_safeclib_LDADD = $(builddir)/liblumi.a -lnobugmt -lpthread -ldl -lm
check_PROGRAMS += test-uuid
test_uuid_SOURCES = $(tests_srcdir)/library/test-uuid.c
test_uuid_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
test_uuid_LDADD = $(builddir)/liblumi.a -lnobugmt -lpthread -ldl -lm
check_PROGRAMS += test-references
test_references_SOURCES = $(tests_srcdir)/library/test-references.c
test_references_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
test_references_LDADD = liblumi.a -lnobugmt -lpthread -ldl -lm -lrt
#check_PROGRAMS += test-filehandles
#test_filehandles_SOURCES = $(tests_srcdir)/backend/test-filehandles.c
#test_filehandles_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
#test_filehandles_LDADD = liblumibackend.a liblumi.a -lnobugmt -lpthread -ldl -lm
check_PROGRAMS += test-filedescriptors
test_filedescriptors_SOURCES = $(tests_srcdir)/backend/test-filedescriptors.c
test_filedescriptors_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
test_filedescriptors_LDADD = liblumibackend.a liblumi.a -lnobugmt -lpthread -ldl -lm
check_PROGRAMS += test-filehandles
test_filehandles_SOURCES = $(tests_srcdir)/backend/test-filehandles.c
test_filehandles_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/
test_filehandles_LDADD = liblumibackend.a liblumi.a -lnobugmt -lpthread -ldl -lm
TESTS = $(tests_srcdir)/test.sh

View file

@ -0,0 +1,89 @@
/*
test-filedescriptors.c
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/safeclib.h"
#include "backend/backend.h"
#include "backend/filedescriptor.h"
#include "tests/test.h"
TESTS_BEGIN
TEST ("acquire_existing")
{
lumiera_backend_init ();
LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY);
if (descriptor)
{
lumiera_filedescriptor_release (descriptor);
lumiera_backend_destroy ();
return 0;
}
else
return 1;
}
TEST ("acquire_existing_again")
{
lumiera_backend_init ();
LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY);
if (descriptor)
{
LumieraFiledescriptor descriptor2 = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_READONLY);
lumiera_filedescriptor_release (descriptor2);
lumiera_filedescriptor_release (descriptor);
lumiera_backend_destroy ();
return 0;
}
else
return 1;
}
TEST ("acquire_create")
{
lumiera_backend_init ();
LumieraFiledescriptor descriptor = lumiera_filedescriptor_acquire (",tmp_testfile", LUMIERA_FILE_CREATE);
if (descriptor)
{
lumiera_filedescriptor_release (descriptor);
lumiera_backend_destroy ();
return 0;
}
else
return 1;
}
TEST ("acquire_create_dir")
{
lumiera_backend_init ();
LumieraFiledescriptor descriptor =
lumiera_filedescriptor_acquire (",tmp_testdir/nested/,tmp_testfile", LUMIERA_FILE_CREATE);
if (descriptor)
{
lumiera_filedescriptor_release (descriptor);
lumiera_backend_destroy ();
return 0;
}
else
return 1;
}
TESTS_END

View file

@ -0,0 +1,87 @@
/*
test-filehandles.c - test filehandle management
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/llist.h"
#include "lib/safeclib.h"
#include "backend/backend.h"
#include "backend/filehandlecache.h"
#include "tests/test.h"
TESTS_BEGIN
TEST ("basic")
{
lumiera_backend_init ();
LumieraFile file = lumiera_file_new (",tmp_testfile", LUMIERA_FILE_CREATE);
/* get the filehandle */
int fd = lumiera_file_handle_acquire (file);
/* we now 'own'it and can use it */
ENSURE (fd > -1);
printf ("got filehandle #%d\n", fd);
/* put it into aging, can't use anymore */
lumiera_file_handle_release (file);
lumiera_file_delete (file);
lumiera_backend_destroy ();
}
TEST ("more")
{
lumiera_backend_init ();
LumieraFile files[100];
int fds[100];
/*create 100 files*/
for (int i=0; i<100; ++i)
{
files[i]= lumiera_file_new (lumiera_tmpbuf_snprintf (256, ",tmpdir/testfile%d", i), LUMIERA_FILE_CREATE);
}
/* get the filehandles, this gross overallocates filehandles */
for (int i=0; i<100; ++i)
{
fds[i] = lumiera_file_handle_acquire (files[i]);
ENSURE (fds[i] > -1);
printf ("got filehandle #%d\n", fds[i]);
}
/* put them into aging, can't use anymore */
for (int i=0; i<100; ++i)
{
lumiera_file_handle_release (files[i]);
}
/* cleanup */
for (int i=0; i<100; ++i)
{
lumiera_file_delete (files[i]);
}
lumiera_backend_destroy ();
}
TESTS_END

61
tests/common/Makefile.am Normal file
View file

@ -0,0 +1,61 @@
# Copyright (C) Lumiera.org
# 2008, Christian Thaeter <ct@pipapo.org>
# Hermann Vosseler <Ichthyostega@web.de>
#
# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
testcommon_srcdir = $(top_srcdir)/tests/common
check_PROGRAMS += test-common
test_common_CPPFLAGS = $(AM_CPPFLAGS) -Wall -I$(top_srcdir)/src -I$(testcommon_srcdir)
test_common_LDADD = \
liblumiproc.a \
liblumiprocengine.a \
liblumiprocmobjectbuilder.a \
liblumiprocmobjectsession.a \
liblumiprocasset.a \
liblumiprocmobject.a \
liblumiprocmobjectcontroller.a \
liblumi.a \
liblumicommon.a \
liblumibackend.a \
-lnobugmt -lpthread -ldl -lboost_program_options-mt -lboost_regex-mt
test_common_SOURCES = \
$(testcommon_srcdir)/appconfigtest.cpp \
$(testcommon_srcdir)/customsharedptrtest.cpp \
$(testcommon_srcdir)/exceptionerrortest.cpp \
$(testcommon_srcdir)/factoryspecialtest.cpp \
$(testcommon_srcdir)/factorytest.cpp \
$(testcommon_srcdir)/helloworldtest.cpp \
$(testcommon_srcdir)/lifecycletest.cpp \
$(testcommon_srcdir)/mainsuite.cpp \
$(testcommon_srcdir)/query/queryutilstest.cpp \
$(testcommon_srcdir)/removefromsettest.cpp \
$(testcommon_srcdir)/sanitizedidentifiertest.cpp \
$(testcommon_srcdir)/singletonsubclasstest.cpp \
$(testcommon_srcdir)/singletontest.cpp \
$(testcommon_srcdir)/singletontestmocktest.cpp \
$(testcommon_srcdir)/test/cmdlinewrappertest.cpp \
$(testcommon_srcdir)/test/testoptiontest.cpp \
$(testcommon_srcdir)/typelisttest.cpp \
$(testcommon_srcdir)/typelistutiltest.cpp \
$(testcommon_srcdir)/visitingtoolconcept.cpp \
$(testcommon_srcdir)/visitingtoolextendedtest.cpp \
$(testcommon_srcdir)/visitingtooltest.cpp
noinst_HEADERS += \
$(testcommon_srcdir)/query/querydiagnostics.hpp \
$(testcommon_srcdir)/testtargetobj.hpp

View file

@ -0,0 +1,72 @@
# Copyright (C) Lumiera.org
# 2008, Christian Thaeter <ct@pipapo.org>
# Hermann Vosseler <Ichthyostega@web.de>
#
# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
testcomponents_srcdir = $(top_srcdir)/tests/components
check_PROGRAMS += test-components
test_components_CPPFLAGS = $(AM_CPPFLAGS) -Wall -I$(top_srcdir)/src -I$(testcomponents_srcdir)
test_components_LDADD = \
liblumiproc.a \
liblumiprocengine.a \
liblumiprocmobjectbuilder.a \
liblumiprocmobjectsession.a \
liblumiprocasset.a \
liblumiprocmobject.a \
liblumiprocmobjectcontroller.a \
liblumi.a \
liblumicommon.a \
liblumibackend.a \
-lnobugmt -lpthread -ldl -lboost_program_options-mt -lboost_regex-mt
test_components_SOURCES = \
$(testcomponents_srcdir)/backend/mediaaccessmock.cpp \
$(testcomponents_srcdir)/backend/mediaaccessmocktest.cpp \
$(testcomponents_srcdir)/proc/asset/assetcategorytest.cpp \
$(testcomponents_srcdir)/proc/asset/compoundmediatest.cpp \
$(testcomponents_srcdir)/proc/asset/deleteassettest.cpp \
$(testcomponents_srcdir)/proc/asset/identityofassetstest.cpp \
$(testcomponents_srcdir)/proc/asset/mediastructurequerytest.cpp \
$(testcomponents_srcdir)/proc/asset/basicpipetest.cpp \
$(testcomponents_srcdir)/proc/asset/createassettest.cpp \
$(testcomponents_srcdir)/proc/asset/dependantassetstest.cpp \
$(testcomponents_srcdir)/proc/asset/makecliptest.cpp \
$(testcomponents_srcdir)/proc/asset/orderingofassetstest.cpp \
$(testcomponents_srcdir)/proc/asset/testasset.cpp \
$(testcomponents_srcdir)/proc/engine/sourcenodetest.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/buildsegmenttest.cpp \
$(testcomponents_srcdir)/proc/mobject/controller/rendersegmenttest.cpp \
$(testcomponents_srcdir)/proc/mobject/placementbasictest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/addcliptest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/deletecliptest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/rebuildfixturetest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/sessionmanagertest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/testclip.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defsmanagerimpltest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defsmanagertest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defsregistryimpltest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/sessionstructuretest.cpp \
$(testcomponents_srcdir)/mainsuite.cpp
noinst_HEADERS += \
$(testcomponents_srcdir)/backend/mediaaccessmock.hpp \
$(testcomponents_srcdir)/proc/asset/testclipasset.hpp \
$(testcomponents_srcdir)/proc/asset/assetdiagnostics.hpp \
$(testcomponents_srcdir)/proc/asset/testasset.hpp \
$(testcomponents_srcdir)/proc/mobject/session/testclip.hpp \
$(testcomponents_srcdir)/proc/mobject/session/testsession1.hpp

View file

@ -23,173 +23,166 @@
//#include <string.h>
#include "lib/llist.h"
#include "lib/error.h"
#include "tests/test.h"
TESTS_BEGIN
LUMIERA_ERROR_DEFINE(TEST, "test error");
int
main (int argc, char** argv)
TEST ("basic")
{
NOBUG_INIT;
LLIST_AUTO (node1);
if (argc == 1)
return 0;
llist node2;
llist_init (&node2);
if (!strcmp(argv[1], "basic"))
{
LLIST_AUTO (node1);
llist node2;
llist_init (&node2);
printf ("%d\n", llist_is_empty (&node1));
printf ("%d\n", llist_is_empty (&node2));
}
else if (!strcmp(argv[1], "nodeinsert"))
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
llist_insert_next (&list, &node1);
printf ("%d\n", llist_is_empty (&list));
printf ("%d\n", llist_is_empty (&node1));
printf ("%d\n", llist_is_single (&node1));
llist_insert_next (&node1, &node2);
printf ("%d\n", llist_is_single (&node1));
llist_insert_prev (&node1, &node3);
printf ("%d\n", llist_next (&list) == &node3);
printf ("%d\n", llist_next (&node3) == &node1);
printf ("%d\n", llist_next (&node1) == &node2);
printf ("%d\n", llist_prev (&list) == &node2);
printf ("%d\n", llist_count (&list));
}
else if (!strcmp(argv[1], "predicates"))
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
LLIST_AUTO (node4);
LLIST_AUTO (nil);
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
printf ("%d\n", llist_is_head (&list, &node1));
printf ("%d\n", llist_is_tail (&list, &node4));
printf ("%d\n", llist_is_head (&list, &node4));
printf ("%d\n", llist_is_tail (&list, &node1));
printf ("%d\n", llist_is_end (&list, &list));
printf ("%d\n", llist_is_member (&list, &node3));
printf ("%d\n", llist_is_member (&list, &nil));
printf ("%d\n", llist_is_before_after (&list, &node1, &node3));
printf ("%d\n", llist_is_before_after (&list, &node3, &node1));
printf ("%d\n", llist_is_before_after (&list, &node1, &nil));
}
else if (!strcmp(argv[1], "unlink"))
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
LLIST_AUTO (node4);
LLIST_AUTO (nil);
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
LLIST_FOREACH_REV (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
llist_unlink (&nil);
llist_unlink (&node2);
llist_unlink (&node3);
LLIST_FOREACH (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
printf ("%d\n", llist_is_empty (&node2));
printf ("%d\n", llist_is_empty (&node3));
printf ("%d\n", llist_is_empty (&nil));
}
else if (!strcmp(argv[1], "whiles"))
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
LLIST_AUTO (node4);
LLIST_AUTO (nil);
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
LLIST_FOREACH_REV (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
LLIST_WHILE_HEAD (&list, head)
llist_unlink (head);
LLIST_FOREACH (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
LLIST_WHILE_TAIL (&list, tail)
llist_unlink (tail);
LLIST_FOREACH (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
}
else
return 1;
return 0;
printf ("%d\n", llist_is_empty (&node1));
printf ("%d\n", llist_is_empty (&node2));
}
TEST ("nodeinsert")
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
llist_insert_next (&list, &node1);
printf ("%d\n", llist_is_empty (&list));
printf ("%d\n", llist_is_empty (&node1));
printf ("%d\n", llist_is_single (&node1));
llist_insert_next (&node1, &node2);
printf ("%d\n", llist_is_single (&node1));
llist_insert_prev (&node1, &node3);
printf ("%d\n", llist_next (&list) == &node3);
printf ("%d\n", llist_next (&node3) == &node1);
printf ("%d\n", llist_next (&node1) == &node2);
printf ("%d\n", llist_prev (&list) == &node2);
printf ("%d\n", llist_count (&list));
}
TEST ("predicates")
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
LLIST_AUTO (node4);
LLIST_AUTO (nil);
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
printf ("%d\n", llist_is_head (&list, &node1));
printf ("%d\n", llist_is_tail (&list, &node4));
printf ("%d\n", llist_is_head (&list, &node4));
printf ("%d\n", llist_is_tail (&list, &node1));
printf ("%d\n", llist_is_end (&list, &list));
printf ("%d\n", llist_is_member (&list, &node3));
printf ("%d\n", llist_is_member (&list, &nil));
printf ("%d\n", llist_is_before_after (&list, &node1, &node3));
printf ("%d\n", llist_is_before_after (&list, &node3, &node1));
printf ("%d\n", llist_is_before_after (&list, &node1, &nil));
}
TEST ("unlink")
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
LLIST_AUTO (node4);
LLIST_AUTO (nil);
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
LLIST_FOREACH_REV (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
llist_unlink (&nil);
llist_unlink (&node2);
llist_unlink (&node3);
LLIST_FOREACH (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
printf ("%d\n", llist_is_empty (&node2));
printf ("%d\n", llist_is_empty (&node3));
printf ("%d\n", llist_is_empty (&nil));
}
TEST ("whiles")
{
LLIST_AUTO (list);
LLIST_AUTO (node1);
LLIST_AUTO (node2);
LLIST_AUTO (node3);
LLIST_AUTO (node4);
LLIST_AUTO (nil);
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
LLIST_FOREACH_REV (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
LLIST_WHILE_HEAD (&list, head)
llist_unlink (head);
LLIST_FOREACH (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
llist_insert_tail (&list, &node2);
llist_insert_tail (&list, &node3);
llist_insert_tail (&list, &node4);
llist_insert_head (&list, &node1);
LLIST_WHILE_TAIL (&list, tail)
llist_unlink (tail);
LLIST_FOREACH (&list, itr)
{
if(itr == &node1) printf ("node1 ");
else if(itr == &node2) printf ("node2 ");
else if(itr == &node3) printf ("node3 ");
else if(itr == &node4) printf ("node4 ");
else printf ("unknown ");
}
printf (".\n");
}
TESTS_END

View file

@ -0,0 +1,85 @@
/*
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/safeclib.h"
#include "tests/test.h"
#include <sys/time.h>
#include <sys/resource.h>
TESTS_BEGIN
TEST ("allocation0")
{
lumiera_malloc (0);
NOTREACHED;
}
TEST ("allocation1024")
{
void* data[1024];
for (int i = 0; i < 1024; ++i)
{
data[i] = lumiera_malloc (1024);
ENSURE (data[i]);
}
for (int i = 0; i < 1024; ++i)
{
free (data[i]);
}
}
TEST ("allocationtoobig")
{
struct rlimit rl;
rl.rlim_cur = 100*1024*1024;
rl.rlim_max = 100*1024*1024;
setrlimit (RLIMIT_AS, &rl);
lumiera_malloc (200*1024*1024);
NOTREACHED;
}
TEST ("streq")
{
if (!lumiera_streq ("foo", "foo"))
LUMIERA_DIE (TEST);
if (!lumiera_streq (NULL, NULL))
LUMIERA_DIE (TEST);
if (!!lumiera_streq (NULL, "foo"))
LUMIERA_DIE (TEST);
if (!!lumiera_streq ("foo", NULL))
LUMIERA_DIE (TEST);
if (!!lumiera_streq ("foo", "bar"))
LUMIERA_DIE (TEST);
}
TEST ("tmpbuf")
{
for (int i = 0; i < 256; ++i)
{
char* buf = lumiera_tmpbuf_provide (1024);
for (int j = 0; j < 1024; ++j)
{
buf[j] = i;
}
}
}
TESTS_END

73
tests/library/test-uuid.c Normal file
View file

@ -0,0 +1,73 @@
/*
test-uuid.c - test the uuid lib
Copyright (C) CinelerraCV
2007, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//#include "cinelerra-config.h"
//#include <stdio.h>
#include "lib/uuid.h"
#include <nobug.h>
//CINELERRA_ERROR_DEFINE(TEST, "test error");
int
main (int argc, char** argv)
{
NOBUG_INIT;
if (argc == 1)
return 0;
if (!strcmp(argv[1], "uuidgen_2"))
{
lumiera_uuid uuid1;
lumiera_uuid uuid2;
lumiera_uuid_gen (&uuid1);
lumiera_uuid_gen (&uuid2);
printf ("%d\n", lumiera_uuid_eq (&uuid2, &uuid1));
}
else if (!strcmp(argv[1], "uuidgen_copy"))
{
lumiera_uuid uuid1;
lumiera_uuid uuid2;
lumiera_uuid_gen (&uuid1);
lumiera_uuid_copy (&uuid2, &uuid1);
printf ("%d\n", lumiera_uuid_eq (&uuid2, &uuid1));
}
else if (!strcmp(argv[1], "ptrs"))
{
lumiera_uuid uuid;
lumiera_uuid_set_ptr (&uuid, &uuid);
printf ("%d\n", lumiera_uuid_ptr_get (&uuid) == &uuid);
}
else
return 1;
return 0;
}

View file

@ -21,33 +21,21 @@
#include <stdio.h>
#include <string.h>
#include "lib/error.h"
LUMIERA_ERROR_DEFINE(TEST, "test error");
#include "tests/test.h"
int conditionforgotunlock ();
int mutexforgotunlock ();
TESTS_BEGIN
int
main (int argc, char** argv)
TEST ("conditionforgotunlock")
{
NOBUG_INIT;
if (argc == 1)
return 0;
if (!strcmp(argv[1], "conditionforgotunlock"))
{
return conditionforgotunlock ();
}
if (!strcmp(argv[1], "mutexforgotunlock"))
{
return mutexforgotunlock ();
}
else
return 1;
return 0;
return conditionforgotunlock ();
}
TEST ("mutexforgotunlock")
{
return mutexforgotunlock ();
}
TESTS_END

View file

@ -3,6 +3,7 @@
#include "lib/plugin.h"
#include "hello_interface.h"
LUMIERA_ERROR_DEFINE(FAILURE, "test failure");
int
main(int argc, char** argv)
@ -25,7 +26,7 @@ main(int argc, char** argv)
LUMIERA_INTERFACE_TYPE(hello, 1)* hello_de =
(LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin", "german_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1)));
if (!hello_de) LUMIERA_DIE;
if (!hello_de) LUMIERA_DIE (FAILURE);
hello_de->hello();
hello_de->goodbye(argv[1]);
@ -33,7 +34,7 @@ main(int argc, char** argv)
LUMIERA_INTERFACE_TYPE(hello, 1)* hello_en =
(LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin", "english_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1)));
if (!hello_en) LUMIERA_DIE;
if (!hello_en) LUMIERA_DIE (FAILURE);
hello_en->hello();
hello_en->goodbye(argv[1]);
@ -48,7 +49,7 @@ main(int argc, char** argv)
LUMIERA_INTERFACE_TYPE(hello, 1)* hello_de =
(LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin_cpp", "german_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1)));
if (!hello_de) LUMIERA_DIE;
if (!hello_de) LUMIERA_DIE (FAILURE);
hello_de->hello();
hello_de->goodbye(argv[1]);
@ -56,7 +57,7 @@ main(int argc, char** argv)
LUMIERA_INTERFACE_TYPE(hello, 1)* hello_en =
(LUMIERA_INTERFACE_TYPE(hello, 1)*) lumiera_interface_open ("example_plugin_cpp", "english_1", sizeof(LUMIERA_INTERFACE_TYPE(hello, 1)));
if (!hello_en) LUMIERA_DIE;
if (!hello_en) LUMIERA_DIE (FAILURE);
hello_en->hello();
hello_en->goodbye(argv[1]);

52
tests/test.h Normal file
View file

@ -0,0 +1,52 @@
/*
test.h - macros for running tests
Copyright (C) CinelerraCV
2008, Christian Thaeter <ct@pipapo.org>
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TEST_H
#define TEST_H
#include <nobug.h>
#include "lib/error.h"
LUMIERA_ERROR_DEFINE (TEST, "test error");
#define TESTS_BEGIN \
int \
main (int argc, char** argv) \
{ \
NOBUG_INIT; \
\
if (argc == 1) \
return 1;
#define TEST(name) \
else if (!strcmp(argv[1], name))
#define TESTS_END \
else \
return 1; \
\
return 0; \
}
#endif

View file

@ -2104,13 +2104,26 @@ if (oldText.indexOf(&quot;SplashScreen&quot;)==-1)
}
//}}}</pre>
</div>
<div title="StyleGuide" modifier="CehTeh" modified="200803261336" created="200803261258" changecount="4">
<div title="StyleGuide" modifier="CehTeh" modified="200803261924" created="200803261258" changecount="6">
<pre>! Source code formatting
http://www.gnu.org/prep/standards/html_node/Formatting.html#Formatting
We decided to use the 'gnu-style' for indenting (using spaces and never tabs!):
http://www.gnu.org/prep/standards/html_node/Formatting.html#Formatting
It is reasonable to be relaxed about soem formatting rules:
* line length might be longer when required
* inter expession spacing can be changed to the actual needed ex: (2*x + 2)
Things we are pedantic about:
* use never ever tab characters in C/C++ sources
* be consistent
* source files should end with a newline
* no trailing or bogus whitespaces
! Coding Practices
! Writing Tests
! Contibuting
! Tests
</pre>
</div>
<div title="StyleSheet" modifier="CehTeh" modified="200706090017" created="200701131624" tags="MPTWTheme" server.type="file" server.host="file:///home/ct/.homepage/home.html" server.page.revision="200706090017">

0
wiki/index.html Executable file → Normal file
View file

View file

@ -3344,6 +3344,15 @@ Someone might pickup a Doxygen-Maintainer. This is not writing actual documentat
<div title="video player mockup" modifier="Ichthyostega" modified="200804120416" created="200804090216" changecount="4">
<pre>Use the backend, gmerlin/avdecoder and a Player widget to playback videos. This should be a small application which can open and playback many videos from one instance in parallel. Later on scrubbing for this videos might be supported.
The idea here is to show and measure backend and scheduler performance
and beeing a proof of concept for the design. It will run
independent of the Proc layer but needs quite some work on the
backend to be done.
</pre>
</div>
<div title="video player mockup" modifier="CehTeh" modified="200804090218" created="200804090216" changecount="3">
<pre>Use the backend, gmerlin/avdecoder and a Player widget to playback videos. This should be a small application which can open and playback many videos from on instance in parallel. Later on scrubbing for this videos might be supported.
The idea here is to show and measure backend and scheduler performance and beeing a proof of concept for the design. It will run independent of the Proc layer but needs quite some work on the backend to be done.</pre>
</div>
</div>