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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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 |