Files
sicspsi/sqlitelog.c

125 lines
3.4 KiB
C

/*
This is a module which implements output of the log to a sqlite database.
The database is much easier for searching the log
copyright: see file COPYRIGHT
Mark Koennecke, February 2016
*/
#include <stdio.h>
#include <logv2.h>
#include <sqlite3.h>
#include <sicsutil.h>
#include <sics.h>
static sqlite3 *db = NULL;
static char sqliteFile[1024];
static unsigned int lineCount = 0;
static unsigned int sqlActive = 0;
/*----------------------------------------------------------------------------------*/
static void SqlFlush(void)
{
char *err;
if(sqlActive == 1 && db != NULL){
sqlite3_exec(db,"END TRANSACTION",NULL,NULL,&err);
lineCount = 0;
}
}
/*----------------------------------------------------------------------------------
The callback function for entering data into the log
------------------------------------------------------------------------------------*/
static void SqliteCallback(unsigned int severity, const char *timeStamp,
const char *subsystem,
const char *message, void *userData)
{
double tVal = DoubleTime();
char sql[2024];
int status;
char *err;
if(logFilter(severity,subsystem,message) == 1) {
return;
}
if(lineCount == 0){
sqlite3_exec(db,"BEGIN TRANSACTION",NULL,NULL,&err);
}
sqlite3_snprintf(sizeof(sql),sql,"INSERT into log VALUES(%f,\"%s\",%d,\"%s\",\"%w\")",
tVal,timeStamp,severity,subsystem,message);
status = sqlite3_exec(db,sql,NULL,NULL,&err);
if(status != SQLITE_OK){
printf("Sqlite logging error: %s from %s\n", err, sql);
sqlite3_free(err);
}
lineCount++;
if(lineCount >= 1000){
SqlFlush();
}
}
/*-----------------------------------------------------------------------------------*/
static void SqlClose(void *data)
{
char *err;
if(sqlActive == 1 && db != NULL){
sqlite3_exec(db,"END TRANSACTION",NULL,NULL,&err);
sqlite3_close(db);
RemoveLogCallback(SqliteCallback);
sqlActive = 0;
}
}
/*------------------------------------------------------------------------------------*/
static int SQLLogConfigAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
int status;
if(argc < 2) {
SCWrite(pCon,"ERROR: need keyword", eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"open") == 0){
if(argc < 3){
SCWrite(pCon,"ERROR: need dbfilename parameter for open",eError);
return 0;
}
strncpy(sqliteFile,argv[2],sizeof(sqliteFile));
status = sqlite3_open(sqliteFile,&db);
if(status){
SCPrintf(pCon,eError,"ERROR: failed to open database %s", argv[2]);
sqlite3_close(db);
return 0;
} else {
RegisterLogCallback(SqliteCallback,NULL);
sqlActive = 1;
SCSendOK(pCon);
}
} else if(strcmp(argv[1],"close") == 0) {
SqlClose(NULL);
SCSendOK(pCon);
} else if(strcmp(argv[1],"flush") == 0) {
SqlFlush();
SCSendOK(pCon);
} else if(strcmp(argv[1],"filename") == 0) {
SCPrintf(pCon,eValue,"sqlitedb = %s", sqliteFile);
} else {
SCPrintf(pCon,eError,"ERROR: keyword %s not recognised", argv[1]);
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------------*/
void SqliteLogInit(void)
{
AddCommand(pServ->pSics,"sqlconfig", SQLLogConfigAction,
SqlClose, NULL);
}