diff --git a/aqhome/data/0BUILD b/aqhome/data/0BUILD index ebe657f..73cf137 100644 --- a/aqhome/data/0BUILD +++ b/aqhome/data/0BUILD @@ -30,6 +30,7 @@ value.t2d device.t2d + datafile.t2d @@ -56,7 +57,7 @@ storage.h - datafile.h + datafile_direct.h @@ -64,7 +65,7 @@ storage_p.h storage_readxml.h storage_writexml.h - datafile_p.h + datafile_direct_p.h @@ -74,7 +75,7 @@ storage.c storage_readxml.c storage_writexml.c - datafile.c + datafile_direct.c diff --git a/aqhome/data/datafile.c b/aqhome/data/datafile.c deleted file mode 100644 index 77a6d56..0000000 --- a/aqhome/data/datafile.c +++ /dev/null @@ -1,401 +0,0 @@ -/**************************************************************************** - * This file is part of the project Gwenhywfar. - * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved. - * - * The license for this file can be found in the file COPYING which you - * should have received along with this file. - ****************************************************************************/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "./datafile_p.h" - -#include -#include - -#include - - -GWEN_LIST_FUNCTIONS(AQH_DATAFILE, AQH_DataFile); - - - -/* ------------------------------------------------------------------------------------------------ - * forward declarations - * ------------------------------------------------------------------------------------------------ - */ - - -static int _readRecord(GWEN_SYNCIO *sio, uint64_t idx, uint64_t *pTimestamp, double *pValue); -static int _writeRecord(GWEN_SYNCIO *sio, uint64_t filePos, uint64_t timestamp, double value); - - - -/* ------------------------------------------------------------------------------------------------ - * implementations - * ------------------------------------------------------------------------------------------------ - */ - -AQH_DATAFILE *AQH_DataFile_new(const char *fileName, uint64_t valueId) -{ - AQH_DATAFILE *df; - - GWEN_NEW_OBJECT(AQH_DATAFILE, df); - GWEN_LIST_INIT(AQH_DATAFILE, df); - df->valueId=valueId; - df->fileName=fileName?strdup(fileName):NULL; - - return df; -} - - - -void AQH_DataFile_free(AQH_DATAFILE *df) -{ - if (df) { - GWEN_LIST_FINI(AQH_DATAFILE, df); - GWEN_SyncIo_free(df->sio); - free(df->fileName); - GWEN_FREE_OBJECT(df); - } -} - - - -const char *AQH_DataFile_GetFileName(const AQH_DATAFILE *df) -{ - return df?df->fileName:NULL; -} - - - -uint64_t AQH_DataFile_GetValueId(const AQH_DATAFILE *df) -{ - return df?df->valueId:0; -} - - - -uint64_t AQH_DataFile_GetNumberOfEntries(const AQH_DATAFILE *df) -{ - return df?df->numberOfEntries:0; -} - - - - -uint32_t AQH_DataFile_GetRuntimeFlags(const AQH_DATAFILE *df) -{ - return df?df->runtimeFlags:0; -} - - - -int AQH_DataFile_Create(AQH_DATAFILE *df) -{ - if (df) { - GWEN_SYNCIO *sio; - int rv; - - if (df->sio) { - DBG_ERROR(AQH_LOGDOMAIN, "File already open"); - return GWEN_ERROR_INVALID; - } - - sio=GWEN_SyncIo_File_new(df->fileName, GWEN_SyncIo_File_CreationMode_CreateNew); - GWEN_SyncIo_SetFlags(sio, - GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_READ | - GWEN_SYNCIO_FILE_FLAGS_UREAD | GWEN_SYNCIO_FILE_FLAGS_UWRITE); - rv=GWEN_SyncIo_Connect(sio); - if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error creating file \"%s\" (%d)", df->fileName, rv); - GWEN_SyncIo_free(sio); - return rv; - } - rv=_writeRecord(sio, 0, 0, 0.0); - if (rv<0) { - DBG_DEBUG(AQH_LOGDOMAIN, "Error adding first record to file \"%s\" (%d)", df->fileName, rv); - GWEN_SyncIo_free(sio); - return rv; - } - df->sio=sio; - df->numberOfEntries=1; /* we just added the 0-record */ - - DBG_INFO(AQH_LOGDOMAIN, "File \"%s\" created.", df->fileName); - return 0; - } - else { - DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); - return GWEN_ERROR_GENERIC; - } -} - - - -int AQH_DataFile_Open(AQH_DATAFILE *df) -{ - if (df) { - GWEN_SYNCIO *sio; - int rv; - int64_t len; - - if (df->sio) { - DBG_ERROR(AQH_LOGDOMAIN, "File already open"); - return GWEN_ERROR_INVALID; - } - - sio=GWEN_SyncIo_File_new(df->fileName, GWEN_SyncIo_File_CreationMode_OpenExisting); - GWEN_SyncIo_SetFlags(sio, GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_READ); - rv=GWEN_SyncIo_Connect(sio); - if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error opening file \"%s\" (%d)", df->fileName, rv); - GWEN_SyncIo_free(sio); - return rv; - } - - len=GWEN_SyncIo_File_Seek(sio, 0, GWEN_SyncIo_File_Whence_End); - if (len<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error seeking to end of file \"%s\" (%d)", df->fileName, rv); - GWEN_SyncIo_free(sio); - return rv; - } - if (len % AQH_DATAFILE_RECORDSIZE) { - DBG_ERROR(AQH_LOGDOMAIN, "Invalid file size of file \"%s\" (not a multiple of current record size)", df->fileName); - GWEN_SyncIo_Disconnect(sio); - GWEN_SyncIo_free(sio); - unlink(df->fileName); - return GWEN_ERROR_BAD_DATA; - } - df->numberOfEntries=len/AQH_DATAFILE_RECORDSIZE; - - len=GWEN_SyncIo_File_Seek(sio, 0, GWEN_SyncIo_File_Whence_Set); - if (len<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error seeking to begin of file \"%s\" (%d)", df->fileName, rv); - GWEN_SyncIo_free(sio); - return rv; - } - df->sio=sio; - return 0; - } - else { - DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); - return GWEN_ERROR_GENERIC; - } -} - - - -int AQH_DataFile_Close(AQH_DATAFILE *df) -{ - if (df) { - int rv; - - if (df->sio==NULL) { - DBG_ERROR(AQH_LOGDOMAIN, "File not open"); - return GWEN_ERROR_INVALID; - } - - rv=GWEN_SyncIo_Disconnect(df->sio); - if (rv<0) { - DBG_ERROR(AQH_LOGDOMAIN, "Error closing file \"%s\" (%d)", df->fileName, rv); - GWEN_SyncIo_free(df->sio); - df->sio=NULL; - df->numberOfEntries=0; - return rv; - } - GWEN_SyncIo_free(df->sio); - df->sio=NULL; - df->numberOfEntries=0; - return 0; - } - else { - DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); - return GWEN_ERROR_GENERIC; - } -} - - - - -int AQH_DataFile_ReadRecord(AQH_DATAFILE *df, uint64_t idx, uint64_t *pTimestamp, double *pValue) -{ - if (df) { - int rv; - - if (df->sio==NULL) { - DBG_ERROR(AQH_LOGDOMAIN, "File not open"); - return GWEN_ERROR_INVALID; - } - - rv=_readRecord(df->sio, idx, pTimestamp, pValue);; - if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error reading from file \"%s\" (%d)", df->fileName, rv); - return rv; - } - - return 0; - } - else { - DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); - return GWEN_ERROR_GENERIC; - } -} - - - -int AQH_DataFile_AppendRecord(AQH_DATAFILE *df, uint64_t timestamp, double value) -{ - if (df) { - int rv; - uint64_t filePos; - - if (df->sio==NULL) { - DBG_ERROR(AQH_LOGDOMAIN, "File not open"); - return GWEN_ERROR_INVALID; - } - - filePos=(df->numberOfEntries)*AQH_DATAFILE_RECORDSIZE; - rv=_writeRecord(df->sio, filePos, timestamp, value); - if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error writing to file \"%s\" (%d)", df->fileName, rv); - return rv; - } - - df->numberOfEntries++; - DBG_DEBUG(AQH_LOGDOMAIN, "File \"%s\" has now %lu entries", df->fileName, (unsigned long int) (df->numberOfEntries)); - return 0; - } - else { - DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); - return GWEN_ERROR_GENERIC; - } -} - - - -AQH_DATAFILE *AQH_DataFile_List_GetByValueId(AQH_DATAFILE_LIST *fileList, uint64_t id) -{ - if (fileList) { - AQH_DATAFILE *df; - - df=AQH_DataFile_List_First(fileList); - while(df) { - if (df->valueId==id) - return df; - df=AQH_DataFile_List_Next(df); - } - } - return NULL; -} - - - -int _readRecord(GWEN_SYNCIO *sio, uint64_t idx, uint64_t *pTimestamp, double *pValue) -{ - uint8_t record[AQH_DATAFILE_RECORDSIZE]; - union {double f; uint64_t i;} u; - uint64_t filePos; - int64_t retPos; - const uint8_t *ptr; - uint64_t v; - int rv; - - filePos=idx*AQH_DATAFILE_RECORDSIZE; - retPos=GWEN_SyncIo_File_Seek(sio, filePos, GWEN_SyncIo_File_Whence_Set); - if (retPos<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error seeking to pos %lu (%d)", (unsigned long int) filePos, (int) retPos); - return (int) retPos; - } - - rv=GWEN_SyncIo_ReadForced(sio, record, AQH_DATAFILE_RECORDSIZE); - if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error reading at pos %lu (%d)", (unsigned long int) filePos, rv); - return rv; - } - - ptr=record+AQH_DATAFILE_OFFSET_TIMESTAMP; - v=0; - v|=(uint64_t)(*(ptr++)); - v|=(uint64_t)(*(ptr++))<<8; - v|=(uint64_t)(*(ptr++))<<16; - v|=(uint64_t)(*(ptr++))<<24; - v|=(uint64_t)(*(ptr++))<<32; - v|=(uint64_t)(*(ptr++))<<40; - v|=(uint64_t)(*(ptr++))<<48; - v|=(uint64_t)(*(ptr++))<<56; - *pTimestamp=v; - - ptr=record+AQH_DATAFILE_OFFSET_VALUE; - v=0; - v|=(uint64_t)(*(ptr++)); - v|=(uint64_t)(*(ptr++))<<8; - v|=(uint64_t)(*(ptr++))<<16; - v|=(uint64_t)(*(ptr++))<<24; - v|=(uint64_t)(*(ptr++))<<32; - v|=(uint64_t)(*(ptr++))<<40; - v|=(uint64_t)(*(ptr++))<<48; - v|=(uint64_t)(*(ptr++))<<56; - u.i=v; - *pValue=u.f; - - return 0; -} - - - -int _writeRecord(GWEN_SYNCIO *sio, uint64_t filePos, uint64_t timestamp, double value) -{ - uint8_t record[AQH_DATAFILE_RECORDSIZE]; - union {double f; uint64_t i;} u; - uint8_t *ptr; - int64_t retPos; - uint64_t v; - int rv; - - ptr=record+AQH_DATAFILE_OFFSET_TIMESTAMP; - v=timestamp; - *(ptr++)=(v) & 0xff; - *(ptr++)=(v>>8) & 0xff; - *(ptr++)=(v>>16) & 0xff; - *(ptr++)=(v>>24) & 0xff; - *(ptr++)=(v>>32) & 0xff; - *(ptr++)=(v>>40) & 0xff; - *(ptr++)=(v>>48) & 0xff; - *(ptr++)=(v>>56) & 0xff; - - u.f=value; - v=u.i; - ptr=record+AQH_DATAFILE_OFFSET_VALUE; - *(ptr++)=(v) & 0xff; - *(ptr++)=(v>>8) & 0xff; - *(ptr++)=(v>>16) & 0xff; - *(ptr++)=(v>>24) & 0xff; - *(ptr++)=(v>>32) & 0xff; - *(ptr++)=(v>>40) & 0xff; - *(ptr++)=(v>>48) & 0xff; - *(ptr++)=(v>>56) & 0xff; - - retPos=GWEN_SyncIo_File_Seek(sio, filePos, GWEN_SyncIo_File_Whence_Set); - if (retPos<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error seeking to pos %lu (%d)", (unsigned long int) filePos, (int) retPos); - return (int) retPos; - } - rv=GWEN_SyncIo_WriteForced(sio, record, AQH_DATAFILE_RECORDSIZE); - if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error writing to file (%d)", rv); - return rv; - } - return 0; -} - - - - - - - - - - diff --git a/aqhome/data/datafile.h b/aqhome/data/datafile.h deleted file mode 100644 index 3a1b589..0000000 --- a/aqhome/data/datafile.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** - * This file is part of the project Gwenhywfar. - * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved. - * - * The license for this file can be found in the file COPYING which you - * should have received along with this file. - ****************************************************************************/ - -#ifndef AQH_DATAFILE_H -#define AQH_DATAFILE_H - - -#include "aqhome/data/storage.h" - -#include - - -typedef struct AQH_DATAFILE AQH_DATAFILE; -GWEN_LIST_FUNCTION_LIB_DEFS(AQH_DATAFILE, AQH_DataFile, AQHOME_API) - - -AQHOME_API AQH_DATAFILE *AQH_DataFile_new(const char *fileName, uint64_t valueId); -AQHOME_API void AQH_DataFile_free(AQH_DATAFILE *df); - -AQHOME_API int AQH_DataFile_Create(AQH_DATAFILE *df); -AQHOME_API int AQH_DataFile_Open(AQH_DATAFILE *df); -AQHOME_API int AQH_DataFile_Close(AQH_DATAFILE *df); - -AQHOME_API const char *AQH_DataFile_GetFileName(const AQH_DATAFILE *df); -AQHOME_API uint64_t AQH_DataFile_GetValueId(const AQH_DATAFILE *df); - -AQHOME_API uint64_t AQH_DataFile_GetNumberOfEntries(const AQH_DATAFILE *df); - -AQHOME_API uint32_t AQH_DataFile_GetRuntimeFlags(const AQH_DATAFILE *df); - -AQHOME_API int AQH_DataFile_ReadRecord(AQH_DATAFILE *df, uint64_t idx, uint64_t *pTimestamp, double *pValue); -AQHOME_API int AQH_DataFile_AppendRecord(AQH_DATAFILE *df, uint64_t timestamp, double value); - -AQHOME_API AQH_DATAFILE *AQH_DataFile_List_GetByValueId(AQH_DATAFILE_LIST *fileList, uint64_t id); - - -#endif - - diff --git a/aqhome/data/datafile.t2d b/aqhome/data/datafile.t2d new file mode 100644 index 0000000..360bc9c --- /dev/null +++ b/aqhome/data/datafile.t2d @@ -0,0 +1,154 @@ + + + + + + This class contains changelog information, + + + AQH_DATAFILE + AQH_DataFile + datafile + + + nocopy + nodup + with_inherit + with_list1 + with_refcount + + + +
aqhome/api.h
+
+ + + + + + +
+ + + + + + + + + + + + 0 + 0 + with_getbymember + public + + + + + + + + + + + + + + + public + int + GWEN_ERROR_NOT_IMPLEMENTED + + + + + + + + + public + int + GWEN_ERROR_NOT_IMPLEMENTED + + + + + + + + + public + int + GWEN_ERROR_NOT_IMPLEMENTED + + + + + + + + public + uint64_t + 0 + + + + + + + + public + int + GWEN_ERROR_NOT_IMPLEMENTED + + + + + + + + + + + + + + + + + + + + + + + + + public + int + GWEN_ERROR_NOT_IMPLEMENTED + + + + + + + + + + + + + + + + + + + +
+ +
+ diff --git a/aqhome/data/datafile_direct.c b/aqhome/data/datafile_direct.c new file mode 100644 index 0000000..44a8eb4 --- /dev/null +++ b/aqhome/data/datafile_direct.c @@ -0,0 +1,444 @@ +/**************************************************************************** + * This file is part of the project Gwenhywfar. + * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "./datafile_direct_p.h" + +#include +#include + +#include + + +GWEN_INHERIT(AQH_DATAFILE, AQH_DATAFILE_DIRECT); + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _cbFreeData(void *bp, void *p); + +static int _cbCreate(AQH_DATAFILE *df); +static int _cbOpen(AQH_DATAFILE *df); +static int _cbClose(AQH_DATAFILE *df); + +static uint64_t _cbGetNumberOfEntries(AQH_DATAFILE *df); + +static int _cbReadRecord(AQH_DATAFILE *df, uint64_t idx, uint64_t *pTimestamp, double *pValue); +static int _cbAppendRecord(AQH_DATAFILE *df, uint64_t timestamp, double value); + +static int _readRecord(GWEN_SYNCIO *sio, uint64_t idx, uint64_t *pTimestamp, double *pValue); +static int _writeRecord(GWEN_SYNCIO *sio, uint64_t filePos, uint64_t timestamp, double value); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +AQH_DATAFILE *AQH_DataFileDirect_new(const char *fileName, uint64_t valueId) +{ + AQH_DATAFILE *df; + AQH_DATAFILE_DIRECT *xdf; + + df=AQH_DataFile_new(); + AQH_DataFile_SetValueId(df, valueId); + + GWEN_NEW_OBJECT(AQH_DATAFILE_DIRECT, xdf); + xdf->fileName=fileName?strdup(fileName):NULL; + GWEN_INHERIT_SETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df, xdf, _cbFreeData); + + AQH_DataFile_SetCreateFn(df, _cbCreate); + AQH_DataFile_SetOpenFn(df, _cbOpen); + AQH_DataFile_SetCloseFn(df, _cbClose); + AQH_DataFile_SetGetNumberOfEntriesFn(df, _cbGetNumberOfEntries); + AQH_DataFile_SetReadRecordFn(df, _cbReadRecord); + AQH_DataFile_SetAppendRecordFn(df, _cbAppendRecord); + + return df; +} + + + +void _cbFreeData(void *bp, void *p) +{ + AQH_DATAFILE_DIRECT *xdf; + + xdf=(AQH_DATAFILE_DIRECT*)p; + GWEN_SyncIo_free(xdf->sio); + free(xdf->fileName); + GWEN_FREE_OBJECT(xdf); +} + + + +const char *_cbGetFileName(const AQH_DATAFILE *df) +{ + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + return xdf?xdf->fileName:NULL; +} + + + +uint64_t _cbGetNumberOfEntries(AQH_DATAFILE *df) +{ + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + return xdf?xdf->numberOfEntries:0; +} + + + + +int _cbCreate(AQH_DATAFILE *df) +{ + if (df) { + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + if (xdf) { + GWEN_SYNCIO *sio; + int rv; + + if (xdf->sio) { + DBG_ERROR(AQH_LOGDOMAIN, "File already open"); + return GWEN_ERROR_INVALID; + } + + sio=GWEN_SyncIo_File_new(xdf->fileName, GWEN_SyncIo_File_CreationMode_CreateNew); + GWEN_SyncIo_SetFlags(sio, + GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_READ | + GWEN_SYNCIO_FILE_FLAGS_UREAD | GWEN_SYNCIO_FILE_FLAGS_UWRITE); + rv=GWEN_SyncIo_Connect(sio); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error creating file \"%s\" (%d)", xdf->fileName, rv); + GWEN_SyncIo_free(sio); + return rv; + } + rv=_writeRecord(sio, 0, 0, 0.0); + if (rv<0) { + DBG_DEBUG(AQH_LOGDOMAIN, "Error adding first record to file \"%s\" (%d)", xdf->fileName, rv); + GWEN_SyncIo_free(sio); + return rv; + } + xdf->sio=sio; + xdf->numberOfEntries=1; /* we just added the 0-record */ + + DBG_INFO(AQH_LOGDOMAIN, "File \"%s\" created.", xdf->fileName); + return 0; + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Not of type AQH_DATAFILE_DIRECT"); + return GWEN_ERROR_GENERIC; + } + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); + return GWEN_ERROR_GENERIC; + } +} + + + +int _cbOpen(AQH_DATAFILE *df) +{ + if (df) { + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + if (xdf) { + GWEN_SYNCIO *sio; + int rv; + int64_t len; + + if (xdf->sio) { + DBG_ERROR(AQH_LOGDOMAIN, "File already open"); + return GWEN_ERROR_INVALID; + } + + sio=GWEN_SyncIo_File_new(xdf->fileName, GWEN_SyncIo_File_CreationMode_OpenExisting); + GWEN_SyncIo_SetFlags(sio, GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_READ); + rv=GWEN_SyncIo_Connect(sio); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error opening file \"%s\" (%d)", xdf->fileName, rv); + GWEN_SyncIo_free(sio); + return rv; + } + + len=GWEN_SyncIo_File_Seek(sio, 0, GWEN_SyncIo_File_Whence_End); + if (len<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error seeking to end of file \"%s\" (%d)", xdf->fileName, rv); + GWEN_SyncIo_free(sio); + return rv; + } + if (len % AQH_DATAFILE_RECORDSIZE) { + DBG_ERROR(AQH_LOGDOMAIN, "Invalid file size of file \"%s\" (not a multiple of current record size)", xdf->fileName); + GWEN_SyncIo_Disconnect(sio); + GWEN_SyncIo_free(sio); + unlink(xdf->fileName); + return GWEN_ERROR_BAD_DATA; + } + xdf->numberOfEntries=len/AQH_DATAFILE_RECORDSIZE; + + len=GWEN_SyncIo_File_Seek(sio, 0, GWEN_SyncIo_File_Whence_Set); + if (len<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error seeking to begin of file \"%s\" (%d)", xdf->fileName, rv); + GWEN_SyncIo_free(sio); + return rv; + } + xdf->sio=sio; + return 0; + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Not of type AQH_DATAFILE_DIRECT"); + return GWEN_ERROR_GENERIC; + } + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); + return GWEN_ERROR_GENERIC; + } +} + + + +int _cbClose(AQH_DATAFILE *df) +{ + if (df) { + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + if (xdf) { + int rv; + + if (xdf->sio==NULL) { + DBG_ERROR(AQH_LOGDOMAIN, "File not open"); + return GWEN_ERROR_INVALID; + } + + rv=GWEN_SyncIo_Disconnect(xdf->sio); + if (rv<0) { + DBG_ERROR(AQH_LOGDOMAIN, "Error closing file \"%s\" (%d)", xdf->fileName, rv); + GWEN_SyncIo_free(xdf->sio); + xdf->sio=NULL; + xdf->numberOfEntries=0; + return rv; + } + GWEN_SyncIo_free(xdf->sio); + xdf->sio=NULL; + xdf->numberOfEntries=0; + return 0; + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Not of type AQH_DATAFILE_DIRECT"); + return GWEN_ERROR_GENERIC; + } + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); + return GWEN_ERROR_GENERIC; + } +} + + + + +int _cbReadRecord(AQH_DATAFILE *df, uint64_t idx, uint64_t *pTimestamp, double *pValue) +{ + if (df) { + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + if (xdf) { + int rv; + + if (xdf->sio==NULL) { + DBG_ERROR(AQH_LOGDOMAIN, "File not open"); + return GWEN_ERROR_INVALID; + } + + rv=_readRecord(xdf->sio, idx, pTimestamp, pValue);; + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error reading from file \"%s\" (%d)", xdf->fileName, rv); + return rv; + } + + return 0; + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Not of type AQH_DATAFILE_DIRECT"); + return GWEN_ERROR_GENERIC; + } + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); + return GWEN_ERROR_GENERIC; + } +} + + + +int _cbAppendRecord(AQH_DATAFILE *df, uint64_t timestamp, double value) +{ + if (df) { + AQH_DATAFILE_DIRECT *xdf; + + xdf=GWEN_INHERIT_GETDATA(AQH_DATAFILE, AQH_DATAFILE_DIRECT, df); + if (xdf) { + int rv; + uint64_t filePos; + + if (xdf->sio==NULL) { + DBG_ERROR(AQH_LOGDOMAIN, "File not open"); + return GWEN_ERROR_INVALID; + } + + filePos=(xdf->numberOfEntries)*AQH_DATAFILE_RECORDSIZE; + rv=_writeRecord(xdf->sio, filePos, timestamp, value); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error writing to file \"%s\" (%d)", xdf->fileName, rv); + return rv; + } + + xdf->numberOfEntries++; + DBG_DEBUG(AQH_LOGDOMAIN, "File \"%s\" has now %lu entries", xdf->fileName, (unsigned long int) (xdf->numberOfEntries)); + return 0; + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Not of type AQH_DATAFILE_DIRECT"); + return GWEN_ERROR_GENERIC; + } + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "Nullpointer"); + return GWEN_ERROR_GENERIC; + } +} + + + + + + +int _readRecord(GWEN_SYNCIO *sio, uint64_t idx, uint64_t *pTimestamp, double *pValue) +{ + uint8_t record[AQH_DATAFILE_RECORDSIZE]; + union {double f; uint64_t i;} u; + uint64_t filePos; + int64_t retPos; + const uint8_t *ptr; + uint64_t v; + int rv; + + filePos=idx*AQH_DATAFILE_RECORDSIZE; + retPos=GWEN_SyncIo_File_Seek(sio, filePos, GWEN_SyncIo_File_Whence_Set); + if (retPos<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error seeking to pos %lu (%d)", (unsigned long int) filePos, (int) retPos); + return (int) retPos; + } + + rv=GWEN_SyncIo_ReadForced(sio, record, AQH_DATAFILE_RECORDSIZE); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error reading at pos %lu (%d)", (unsigned long int) filePos, rv); + return rv; + } + + ptr=record+AQH_DATAFILE_OFFSET_TIMESTAMP; + v=0; + v|=(uint64_t)(*(ptr++)); + v|=(uint64_t)(*(ptr++))<<8; + v|=(uint64_t)(*(ptr++))<<16; + v|=(uint64_t)(*(ptr++))<<24; + v|=(uint64_t)(*(ptr++))<<32; + v|=(uint64_t)(*(ptr++))<<40; + v|=(uint64_t)(*(ptr++))<<48; + v|=(uint64_t)(*(ptr++))<<56; + *pTimestamp=v; + + ptr=record+AQH_DATAFILE_OFFSET_VALUE; + v=0; + v|=(uint64_t)(*(ptr++)); + v|=(uint64_t)(*(ptr++))<<8; + v|=(uint64_t)(*(ptr++))<<16; + v|=(uint64_t)(*(ptr++))<<24; + v|=(uint64_t)(*(ptr++))<<32; + v|=(uint64_t)(*(ptr++))<<40; + v|=(uint64_t)(*(ptr++))<<48; + v|=(uint64_t)(*(ptr++))<<56; + u.i=v; + *pValue=u.f; + + return 0; +} + + + +int _writeRecord(GWEN_SYNCIO *sio, uint64_t filePos, uint64_t timestamp, double value) +{ + uint8_t record[AQH_DATAFILE_RECORDSIZE]; + union {double f; uint64_t i;} u; + uint8_t *ptr; + int64_t retPos; + uint64_t v; + int rv; + + ptr=record+AQH_DATAFILE_OFFSET_TIMESTAMP; + v=timestamp; + *(ptr++)=(v) & 0xff; + *(ptr++)=(v>>8) & 0xff; + *(ptr++)=(v>>16) & 0xff; + *(ptr++)=(v>>24) & 0xff; + *(ptr++)=(v>>32) & 0xff; + *(ptr++)=(v>>40) & 0xff; + *(ptr++)=(v>>48) & 0xff; + *(ptr++)=(v>>56) & 0xff; + + u.f=value; + v=u.i; + ptr=record+AQH_DATAFILE_OFFSET_VALUE; + *(ptr++)=(v) & 0xff; + *(ptr++)=(v>>8) & 0xff; + *(ptr++)=(v>>16) & 0xff; + *(ptr++)=(v>>24) & 0xff; + *(ptr++)=(v>>32) & 0xff; + *(ptr++)=(v>>40) & 0xff; + *(ptr++)=(v>>48) & 0xff; + *(ptr++)=(v>>56) & 0xff; + + retPos=GWEN_SyncIo_File_Seek(sio, filePos, GWEN_SyncIo_File_Whence_Set); + if (retPos<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error seeking to pos %lu (%d)", (unsigned long int) filePos, (int) retPos); + return (int) retPos; + } + rv=GWEN_SyncIo_WriteForced(sio, record, AQH_DATAFILE_RECORDSIZE); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "Error writing to file (%d)", rv); + return rv; + } + return 0; +} + + + + + + + + + + diff --git a/aqhome/data/datafile_direct.h b/aqhome/data/datafile_direct.h new file mode 100644 index 0000000..ecf4aaa --- /dev/null +++ b/aqhome/data/datafile_direct.h @@ -0,0 +1,26 @@ +/**************************************************************************** + * This file is part of the project Gwenhywfar. + * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_DATAFILE_H +#define AQH_DATAFILE_H + + +#include "aqhome/data/storage.h" +#include "aqhome/data/datafile.h" + +#include + + +AQHOME_API AQH_DATAFILE *AQH_DataFileDirect_new(const char *fileName, uint64_t valueId); + +AQHOME_API const char *AQH_DataFileDirect_GetFileName(const AQH_DATAFILE *df); + + +#endif + + diff --git a/aqhome/data/datafile_p.h b/aqhome/data/datafile_direct_p.h similarity index 77% rename from aqhome/data/datafile_p.h rename to aqhome/data/datafile_direct_p.h index bb71eba..903ec4b 100644 --- a/aqhome/data/datafile_p.h +++ b/aqhome/data/datafile_direct_p.h @@ -6,11 +6,11 @@ * should have received along with this file. ****************************************************************************/ -#ifndef AQH_DATAFILE_P_H -#define AQH_DATAFILE_P_H +#ifndef AQH_DATAFILE_DIRECT_P_H +#define AQH_DATAFILE_DIRECT_P_H -#include "./datafile.h" +#include "./datafile_direct.h" #include @@ -20,14 +20,11 @@ #define AQH_DATAFILE_OFFSET_VALUE 8 -struct AQH_DATAFILE { - GWEN_LIST_ELEMENT(AQH_DATAFILE); - +typedef struct AQH_DATAFILE_DIRECT AQH_DATAFILE_DIRECT; +struct AQH_DATAFILE_DIRECT { char *fileName; - uint64_t valueId; GWEN_SYNCIO *sio; uint64_t numberOfEntries; - uint32_t runtimeFlags; }; diff --git a/aqhome/data/storage.c b/aqhome/data/storage.c index 722a89a..1d3d968 100644 --- a/aqhome/data/storage.c +++ b/aqhome/data/storage.c @@ -13,6 +13,7 @@ #include "aqhome/data/storage_p.h" #include "aqhome/data/storage_readxml.h" #include "aqhome/data/storage_writexml.h" +#include "aqhome/data/datafile_direct.h" #include #include @@ -353,7 +354,7 @@ int AQH_Storage_Fini(AQH_STORAGE *sto) AQH_DataFile_List_Del(df); rv=AQH_DataFile_Close(df); if (rv<0) { - DBG_INFO(AQH_LOGDOMAIN, "Error closing file \"%s\"", AQH_DataFile_GetFileName(df)); + DBG_INFO(AQH_LOGDOMAIN, "Error closing file \"%lu\"", AQH_DataFile_GetValueId(df)); errors++; } AQH_DataFile_free(df); @@ -625,7 +626,7 @@ AQH_DATAFILE *_openOrCreateDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId) int rv; nameBuf=_getDataFilePathForValueId(sto, valueId); - df=AQH_DataFile_new(GWEN_Buffer_GetStart(nameBuf), valueId); + df=AQH_DataFileDirect_new(GWEN_Buffer_GetStart(nameBuf), valueId); rv=GWEN_Directory_GetPath(GWEN_Buffer_GetStart(nameBuf), GWEN_PATH_FLAGS_CHECKROOT |