diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index eb1053837..7540f1445 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -30,6 +30,7 @@ liblumierabackend_la_SOURCES = \ $(liblumierabackend_la_srcdir)/filedescriptorregistry.c \ $(liblumierabackend_la_srcdir)/filehandle.c \ $(liblumierabackend_la_srcdir)/filehandlecache.c \ + $(liblumierabackend_la_srcdir)/fileheader.c \ $(liblumierabackend_la_srcdir)/mediaaccessfacade.cpp \ $(liblumierabackend_la_srcdir)/mmap.c \ $(liblumierabackend_la_srcdir)/mmapcache.c \ @@ -49,10 +50,12 @@ noinst_HEADERS += \ $(liblumierabackend_la_srcdir)/filedescriptorregistry.h \ $(liblumierabackend_la_srcdir)/filehandle.h \ $(liblumierabackend_la_srcdir)/filehandlecache.h \ + $(liblumierabackend_la_srcdir)/fileheader.h \ $(liblumierabackend_la_srcdir)/mmap.h \ $(liblumierabackend_la_srcdir)/mmapcache.h \ $(liblumierabackend_la_srcdir)/mmapings.h \ $(liblumierabackend_la_srcdir)/resourcecollector.h \ + $(liblumierabackend_la_srcdir)/resourcecollector.h \ $(liblumierabackend_la_srcdir)/threadpool.h \ $(liblumierabackend_la_srcdir)/threads.h diff --git a/src/backend/fileheader.c b/src/backend/fileheader.c index 2e8123043..5bbe8c4e5 100644 --- a/src/backend/fileheader.c +++ b/src/backend/fileheader.c @@ -166,7 +166,6 @@ lumiera_fileheader_version (LumieraFileheader self) - /** * check if all flags given from some sets are either set or not. */ diff --git a/src/backend/fileheader.h b/src/backend/fileheader.h new file mode 100644 index 000000000..4918281f5 --- /dev/null +++ b/src/backend/fileheader.h @@ -0,0 +1,156 @@ +/* + fileheader.h - Definitions of generic lumiera fileheaders and identification + + Copyright (C) Lumiera.org + 2010, Christian Thaeter + + 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_FILEHEADER_H +#define LUMIERA_FILEHEADER_H + +#include "lib/error.h" + +LUMIERA_ERROR_DECLARE (FILEHEADER_NOWRITE); +LUMIERA_ERROR_DECLARE (FILEHEADER_HEADER); + + +typedef struct lumiera_fileheader_struct lumiera_fileheader; +typedef lumiera_fileheader* LumieraFileheader; + +typedef struct lumiera_fileheader_raw_struct lumiera_fileheader_raw; +typedef lumiera_fileheader_raw* LumieraFileheaderRaw; + +typedef struct lumiera_fileheaderext_struct lumiera_fileheaderext; +typedef lumiera_fileheaderext* LumieraFileheaderext; + +typedef struct lumiera_fileheaderext_raw_struct lumiera_fileheaderext_raw; +typedef lumiera_fileheaderext_raw* LumieraFileheaderextRaw; + + +#include "backend/file.h" + + +#include +#include + + +/** + * @file + * + * Lumiera creates some files on itself, caches, indexes and so on. + * Here we define a unified header format for identifying and handling these files. + * + * Most of this files store binary data in host order for performance reasons an are not yet + * intended to be transfered between computers. While the transferability depends on the + * concrete implementation later and is not contstrained here. + * + */ + + +#ifndef LUMIERA_PACKED +#define LUMIERA_PACKED __attribute__((__packed__)) +#endif + +/** + * A basic fileheader + * On-Disk representation starts with 32 bytes identifying the file. + * The first 32 bytes are human readable text. + */ +struct LUMIERA_PACKED lumiera_fileheader_raw_struct +{ + /** four character codes identifying this file type */ + char fourcc[4]; + /** decimal digits, right bound space filled, denoting the file version, 0 is reserved for experimental things */ + char version[3]; + /** always '\n' */ + char newline1; + /** freeform string, comment or so on, initialized to spaces */ + char meta[22]; + /** always '\n' */ + char newline2; + /** always '\0' */ + char null; +}; + +/** + * A fileheader object encapsulates the underlying mmap object which keeps the + * raw header data in memory and and the dereferenced thereof. + */ +struct lumiera_fileheader_struct +{ + LumieraFileheaderRaw header; + LumieraMMap map; +}; + + +/** + * Create a fileheader on a file open for writing. + * This overwrites any existing date, take care. The created fileheader is mmaped into memory + * and must be closed after use. The File should be locked for operations on the fileheader. + * @param file The file on which to create the header. + * @param fourcc pointer to a string of length 4 + * @param version version number for the header (should be incremented after changes) + * the value '0' is reserved for experimental versions. + * @param size The actual size of all header data, including following format specific data. + * @return A lumiera_fileheader object by value, .header and .map are set to NULL on error. + */ +lumiera_fileheader +lumiera_fileheader_create (LumieraFile file, char* fourcc, int version, size_t size); + + +/** + * Open an existing fileheader. + * The underlying file might be readonly. The opened fileheader is mmaped into memory + * and must be closed after use. The File should be locked for operations on the fileheader. + * @param file The file on which to open the header. + * @param fourcc pointer to a string of length 4 with the expected identifier for the file + * @param size The actual size of all header data, including following format specific data. + * @return A lumiera_fileheader object by value, .header and .map are set to NULL on error. + */ +lumiera_fileheader +lumiera_fileheader_open (LumieraFile file, char* fourcc, size_t size); + + +/** + * Closes a previously created or opened fileheader. + * @param self the fileheader to close. + * no errors, no nothing returned + */ +void +lumiera_fileheader_close (LumieraFileheader self); + + +/** + * Queries the version of a fileheader. + * @param self the fileheader to query + * @return the version stored in the fileheader or -1 on error. + */ +int +lumiera_fileheader_version (LumieraFileheader self); + + + + + +#endif +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/include/logging.h b/src/include/logging.h index 5990d52a5..d2420b0f8 100644 --- a/src/include/logging.h +++ b/src/include/logging.h @@ -85,6 +85,7 @@ NOBUG_CPP_DEFINE_FLAG_PARENT ( mmapings_dbg, backend_dbg); NOBUG_CPP_DEFINE_FLAG_PARENT ( thread_dbg, backend_dbg); NOBUG_CPP_DEFINE_FLAG_PARENT ( threads_dbg, thread_dbg); NOBUG_CPP_DEFINE_FLAG_PARENT ( threadpool_dbg, thread_dbg); +NOBUG_CPP_DEFINE_FLAG_PARENT ( fileheader_dbg, backend_dbg); /** base of debug logging for the proc layer */ NOBUG_CPP_DEFINE_FLAG_PARENT ( proc_dbg, debugging); @@ -124,6 +125,7 @@ NOBUG_CPP_DEFINE_FLAG_PARENT ( mmap, backend); NOBUG_CPP_DEFINE_FLAG_PARENT ( thread, backend); //starting/stopping threads NOBUG_CPP_DEFINE_FLAG_PARENT ( threads, thread); NOBUG_CPP_DEFINE_FLAG_PARENT ( threadpool, thread); +NOBUG_CPP_DEFINE_FLAG_PARENT ( fileheader, backend); /** progress log for the proc layer */ NOBUG_CPP_DEFINE_FLAG_PARENT ( proc, progress); /** progress log for proc-layer command dispatch */ diff --git a/tests/31fileheader.tests b/tests/31fileheader.tests new file mode 100644 index 000000000..d8eb8c832 --- /dev/null +++ b/tests/31fileheader.tests @@ -0,0 +1,31 @@ +TESTING "fileheader access" ./test-fileheader + +TEST "fileheader, basic creation" create_basic </dev/null diff --git a/tests/Makefile.am b/tests/Makefile.am index df85c18a4..f42027dd4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -76,6 +76,13 @@ test_filemmap_LDADD = $(LUMIERA_LIBS) liblumierabackend.la liblumieracommon.la l #test_resourcecollector_SOURCES = $(tests_srcdir)/backend/test-resourcecollector.c #test_resourcecollector_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ #test_resourcecollector_LDADD = $(LUMIERA_LIBS) liblumiera.la liblumierabackend.la liblumieraproc.la liblumieracommon.la + +check_PROGRAMS += test-fileheader +test_fileheader_SOURCES = $(tests_srcdir)/backend/test-fileheader.c +test_fileheader_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ +test_fileheader_LDADD = $(LUMIERA_LIBS) liblumierabackend.la liblumieracommon.la liblumieraproc.la +# FIXME stray dependencies on proc + # FIXME stray dependencies on proc check_PROGRAMS += test-slist diff --git a/tests/backend/test-fileheader.c b/tests/backend/test-fileheader.c new file mode 100644 index 000000000..b5f4a099d --- /dev/null +++ b/tests/backend/test-fileheader.c @@ -0,0 +1,123 @@ +/* + test-fileheader.c - File identification + + Copyright (C) Lumiera.org + 2010, Christian Thaeter + + 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/fileheader.h" + +#include "tests/test.h" + +#include "backend/filehandlecache.h" +extern LumieraFilehandlecache lumiera_fhcache; + +TESTS_BEGIN + + +TEST (create_basic) +{ + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-fileheader", LUMIERA_FILE_RECREATE); + + LUMIERA_FILE_WRLOCK_SECTION (NOBUG_ON, file) + { + lumiera_fileheader header = lumiera_fileheader_create (file, "TEST", 0, sizeof (lumiera_fileheader_raw)); + + CHECK (lumiera_error_peek() == NULL); + + ECHO ("fileheader: %s:", (char*)header.header); + + lumiera_fileheader_close (&header); + } + + lumiera_file_delete (file); + lumiera_backend_destroy (); +} + + + +TEST (create_nowrite) +{ + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-fileheader", LUMIERA_FILE_READONLY); + REQUIRE(file); + + LUMIERA_FILE_RDLOCK_SECTION (NOBUG_ON, file) + { + lumiera_fileheader header = lumiera_fileheader_create (file, "TEST", 0, sizeof (lumiera_fileheader)); + + CHECK(lumiera_error() == LUMIERA_ERROR_FILEHEADER_NOWRITE); + + lumiera_fileheader_close (&header); + } + + lumiera_file_delete (file); + lumiera_backend_destroy (); +} + + + +TEST (acquire_wrongheader) +{ + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-fileheader", LUMIERA_FILE_READONLY); + + LUMIERA_FILE_RDLOCK_SECTION (NOBUG_ON, file) + { + lumiera_fileheader header = lumiera_fileheader_open (file, "BADH", sizeof (lumiera_fileheader)); + + CHECK(!header.header); + CHECK(lumiera_error() == LUMIERA_ERROR_FILEHEADER_HEADER); + + lumiera_fileheader_close (&header); + } + + lumiera_file_delete (file); + lumiera_backend_destroy (); +} + + + +TEST (acquire_basic) +{ + lumiera_backend_init (); + LumieraFile file = lumiera_file_new (",tmp-fileheader", LUMIERA_FILE_READONLY); + + LUMIERA_FILE_RDLOCK_SECTION (NOBUG_ON, file) + { + lumiera_fileheader header = lumiera_fileheader_open (file, "TEST", sizeof (lumiera_fileheader)); + + CHECK(header.header); + CHECK(!lumiera_error()); + + CHECK (lumiera_fileheader_version (&header) == 0); + + ECHO ("fileheader: %s:", (char*)header.header); + + lumiera_fileheader_close (&header); + } + + lumiera_file_delete (file); + lumiera_backend_destroy (); + +} + + + +TESTS_END