1043 lines
28 KiB
C
1043 lines
28 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <sys/file.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
#include "log.h"
|
|
#include "config_engine.h"
|
|
#include "libuv_dbus.h"
|
|
|
|
#define PROCESS_MUTEX_KEY ("/root/config_server.pid")
|
|
#define CFG_SYNC_TIME_OF_SECONDS (1)
|
|
|
|
|
|
static PCFG_ITEM __cfgAddItem(const char *pKeyName, const char *pKeyValue, int iType, int overWrite, int saveToDB, int* pErr);
|
|
|
|
typedef struct
|
|
{
|
|
char keyName[MAX_CFG_KEY_NAME];
|
|
uint32_t tmCached;
|
|
|
|
UT_hash_handle hh; ///< UT Hash handle
|
|
} CFG_CACHE_ITEM, *PCFG_CACHE_ITEM;
|
|
|
|
static sqlite3* g_pSqlFileDB = NULL;
|
|
static PCFG_ITEM g_pCfgItems = NULL;
|
|
static PCFG_CACHE_ITEM g_pCfgCacheItems = NULL;
|
|
static int g_bIsCfgSvr = FALSE;
|
|
static uv_rwlock_t g_uvHashRwLock;
|
|
static uv_rwlock_t g_uvCacheRwLock;
|
|
static uv_timer_t g_uvSyncSvr;
|
|
|
|
#if 0
|
|
#define INT_TBL_SQL_CMD ("CREATE TABLE IF NOT EXISTS integer(" \
|
|
"keyName TEXT PRIMARY KEY NOT NULL," \
|
|
"keyValue INTEGER NOT NULL," \
|
|
"keyModule INTEGER NOT NULL," \
|
|
"CreatedTime TimeStamp NOT NULL DEFAULT (datetime('now','localtime')));")
|
|
|
|
#define STRING_TBL_SQL_CMD ("CREATE TABLE IF NOT EXISTS string(" \
|
|
"keyName TEXT PRIMARY KEY NOT NULL," \
|
|
"keyValue TEXT NOT NULL," \
|
|
"keyModule INTEGER NOT NULL," \
|
|
"CreatedTime TimeStamp NOT NULL DEFAULT (datetime('now','localtime')));")
|
|
|
|
#define FLOAT_TBL_SQL_CMD ("CREATE TABLE IF NOT EXISTS double(" \
|
|
"keyName TEXT PRIMARY KEY NOT NULL," \
|
|
"keyValue NUMERIC NOT NULL," \
|
|
"keyModule INTEGER NOT NULL," \
|
|
"CreatedTime TimeStamp NOT NULL DEFAULT (datetime('now','localtime')));")
|
|
#endif
|
|
|
|
#define FIRMWARE_TBL_SQL_CMD ("CREATE TABLE IF NOT EXISTS %s (" \
|
|
"ID INTEGER PRIMARY KEY AUTOINCREMENT," \
|
|
"keyName TEXT UNIQUE NOT NULL," \
|
|
"keyValue TEXT NOT NULL," \
|
|
"keyType INTEGER NOT NULL);")
|
|
|
|
|
|
static const char* __cfgGetKeyTypeString(int keyType)
|
|
{
|
|
switch(keyType)
|
|
{
|
|
case 0:
|
|
return ("string");
|
|
case 1:
|
|
return ("integer");
|
|
case 2:
|
|
return ("double");
|
|
}
|
|
|
|
return ("Unknown Type");
|
|
}
|
|
|
|
|
|
static int __cfgItem2CfgRsp(PCFG_ITEM pCfgItem, PCFG_API_RSP pRsp)
|
|
{
|
|
if(pCfgItem == NULL || pRsp == NULL)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
memset(pRsp->keyValue, 0, MAX_CFG_KEY_VALUE);
|
|
pRsp->keyType = pCfgItem->keyType;
|
|
|
|
if(pCfgItem->keyType == CFG_TYPE_STRING)
|
|
{
|
|
strncpy(pRsp->keyValue, pCfgItem->pStrValue, MAX_CFG_KEY_VALUE);
|
|
}
|
|
else if(pCfgItem->keyType == CFG_TYPE_INT)
|
|
{
|
|
sprintf(pRsp->keyValue, "%d", pCfgItem->intValue);
|
|
}
|
|
else if(pCfgItem->keyType == CFG_TYPE_DOUBLE)
|
|
{
|
|
sprintf(pRsp->keyValue, "%f", pCfgItem->doubleValue);
|
|
}
|
|
|
|
pRsp->errNo = 0;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int __cfgMsg2CfgItem(int keyType, const char *pKeyName, const char *pKeyValue, PCFG_ITEM pCfgItem)
|
|
{
|
|
int iValue;
|
|
double dValue;
|
|
char *pEndPtr = NULL;
|
|
|
|
if(pKeyName == NULL || pKeyValue == NULL || pCfgItem == NULL)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
strcpy(pCfgItem->pKeyName, pKeyName);
|
|
pCfgItem->keyType = keyType;
|
|
pCfgItem->keyModule = DBusLibuvGetRuntime()->modName;
|
|
|
|
switch(keyType)
|
|
{
|
|
case CFG_TYPE_STRING:
|
|
strcpy(pCfgItem->pStrValue, pKeyValue);
|
|
break;
|
|
|
|
case CFG_TYPE_INT:
|
|
iValue = strtol(pKeyValue, NULL, 10);
|
|
|
|
if(errno == ERANGE || errno == EINVAL)
|
|
{
|
|
return (-ERR_STR_CONVERT);
|
|
}
|
|
else
|
|
{
|
|
pCfgItem->intValue = iValue;
|
|
}
|
|
break;
|
|
|
|
case CFG_TYPE_DOUBLE:
|
|
dValue = strtod(pKeyValue, &pEndPtr);
|
|
|
|
if((errno == ERANGE) || (dValue == 0 && (strcmp(pKeyValue, pEndPtr) == 0)))
|
|
{
|
|
return (-ERR_STR_CONVERT);
|
|
}
|
|
else
|
|
{
|
|
pCfgItem->doubleValue = dValue;
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
return (-ERR_UNKNOWN_TYPE);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int __cfgMsg2CfgItemV2(int keyType, const char *pKeyName, const char *pKeyValue, PCFG_ITEM* pItem)
|
|
{
|
|
int iSize;
|
|
PCFG_ITEM pCfgItem = (PCFG_ITEM)malloc(sizeof(CFG_ITEM));
|
|
char* pCache = NULL;
|
|
|
|
if(pKeyName == NULL || pKeyValue == NULL || pCfgItem == NULL)
|
|
{
|
|
free(pCfgItem);
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
switch(keyType)
|
|
{
|
|
case CFG_TYPE_STRING:
|
|
iSize += strlen(pKeyValue) + 1;
|
|
pCache = (char*)malloc(iSize);
|
|
memset(pCache, 0, iSize);
|
|
pCfgItem->pKeyName = pCache;
|
|
pCfgItem->pStrValue = pCache + strlen(pKeyName) + 1;
|
|
__cfgMsg2CfgItem(pCfgItem->keyType, pKeyName, pKeyValue, pCfgItem);;
|
|
break;
|
|
|
|
case CFG_TYPE_INT:
|
|
pCfgItem->pKeyName = (char*)malloc(iSize);
|
|
memset(pCfgItem->pKeyName, 0, iSize);
|
|
strcpy(pCfgItem->pKeyName, pKeyName);
|
|
__cfgMsg2CfgItem(pCfgItem->keyType, pKeyName, pKeyValue, pCfgItem);;
|
|
break;
|
|
|
|
case CFG_TYPE_DOUBLE:
|
|
pCfgItem->pKeyName = (char*)malloc(iSize);
|
|
memset(pCfgItem->pKeyName, 0, iSize);
|
|
strcpy(pCfgItem->pKeyName, pKeyName);
|
|
__cfgMsg2CfgItem(pCfgItem->keyType, pKeyName, pKeyValue, pCfgItem);;
|
|
break;
|
|
|
|
default:
|
|
free(pCfgItem);
|
|
return -ERR_UNKNOWN_TYPE;
|
|
}
|
|
|
|
*pItem = pCfgItem;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Sqlite3SyncDB(sqlite3* pSqlMemory, const char* pMemDbName, const char* pDBFilePath, const char* pFileDbName, int isSave)
|
|
{
|
|
int rc;
|
|
sqlite3* pSqlFile;
|
|
sqlite3_backup* pSqlBackup;
|
|
sqlite3* pSyncDest;
|
|
sqlite3* pSyncSrc;
|
|
|
|
rc = sqlite3_open(pDBFilePath, &pSqlFile);
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
return -ERR_OPEN_SQLITE3_DB;
|
|
}
|
|
|
|
if(pDBFilePath == NULL || strlen(pDBFilePath) == 0)
|
|
{
|
|
pMemDbName = "main";
|
|
}
|
|
|
|
if(pFileDbName == NULL || strlen(pFileDbName) == 0)
|
|
{
|
|
pFileDbName = "main";
|
|
}
|
|
|
|
pSyncSrc = isSave ? pSqlMemory : pSqlFile;
|
|
pSyncDest = isSave ? pSqlFile : pSqlMemory;
|
|
|
|
pSqlBackup = sqlite3_backup_init(pSyncDest, pMemDbName, pSyncSrc, pFileDbName);
|
|
|
|
if(pSqlBackup != NULL)
|
|
{
|
|
#if 1
|
|
do
|
|
{
|
|
rc = sqlite3_backup_step(pSqlBackup, 10);
|
|
|
|
if(rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED)
|
|
{
|
|
sqlite3_sleep(100);
|
|
}
|
|
} while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
|
|
#else
|
|
sqlite3_backup_step(pSqlBackup, -1);
|
|
#endif
|
|
sqlite3_backup_finish(pSqlBackup);
|
|
}
|
|
else
|
|
{
|
|
LOG_EX(LOG_Error, "Backup Database Error\n");
|
|
}
|
|
|
|
rc = sqlite3_errcode(pSyncDest);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int __sqlite3LoadCb(void* data, int argc, char** argv, char** azColName)
|
|
{
|
|
|
|
if(argc == 4)
|
|
{
|
|
int iSize;
|
|
PCFG_ITEM pCfgItem = (PCFG_ITEM)malloc(sizeof(CFG_ITEM));
|
|
char* pCache = NULL;
|
|
int ret = 0;
|
|
|
|
pCfgItem->keyType = atoi(argv[3]);
|
|
pCfgItem->keyModule = *(int*)data;
|
|
iSize = strlen(argv[1]) + 1;
|
|
|
|
switch(pCfgItem->keyType)
|
|
{
|
|
case CFG_TYPE_STRING:
|
|
iSize += strlen(argv[2]) + 1;
|
|
pCache = (char*)malloc(iSize);
|
|
memset(pCache, 0, iSize);
|
|
pCfgItem->pKeyName = pCache;
|
|
pCfgItem->pStrValue = pCache + strlen(argv[1]) + 1;
|
|
ret = __cfgMsg2CfgItem(pCfgItem->keyType, argv[1], argv[2], pCfgItem);;
|
|
break;
|
|
|
|
case CFG_TYPE_INT:
|
|
pCfgItem->pKeyName = (char*)malloc(iSize);
|
|
memset(pCfgItem->pKeyName, 0, iSize);
|
|
strcpy(pCfgItem->pKeyName, argv[1]);
|
|
ret = __cfgMsg2CfgItem(pCfgItem->keyType, argv[1], argv[2], pCfgItem);;
|
|
break;
|
|
|
|
case CFG_TYPE_DOUBLE:
|
|
pCfgItem->pKeyName = (char*)malloc(iSize);
|
|
memset(pCfgItem->pKeyName, 0, iSize);
|
|
strcpy(pCfgItem->pKeyName, argv[1]);
|
|
ret = __cfgMsg2CfgItem(pCfgItem->keyType, argv[1], argv[2], pCfgItem);;
|
|
break;
|
|
|
|
default:
|
|
free(pCfgItem);
|
|
return -ERR_UNKNOWN_TYPE;
|
|
}
|
|
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_ADD_STR(g_pCfgItems, pKeyName, pCfgItem);
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
|
|
if(ret == 0)
|
|
{
|
|
CfgItemPrint("Load Configure: ", pCfgItem);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOG_EX(LOG_Error, "argc = %d\n", argc);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __cfgLoadGlobalConfig(void)
|
|
{
|
|
int rc = 0;
|
|
char* pErrMsg = NULL;
|
|
char sqlCmd[1024];
|
|
PLIBUV_DBUS_PARAMS pContext = DBusLibuvGetRuntime();
|
|
|
|
memset(sqlCmd, 0, 1024);
|
|
sprintf(sqlCmd, "SELECT * FROM %s", MODULE_ALIAS_NAME(MODULE_CONFIGURE));
|
|
|
|
// get global configure
|
|
rc = sqlite3_exec(g_pSqlFileDB, sqlCmd, __sqlite3LoadCb, (void*)MODULE_CONFIGURE, &pErrMsg);
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
LOG_EX(LOG_Error, "SQLite3 Query Error: %s\n", pErrMsg);
|
|
return -ERR_SQL_QUERY;
|
|
}
|
|
|
|
if(pContext->modName != MODULE_CONFIGURE)
|
|
{
|
|
memset(sqlCmd, 0, 1024);
|
|
sprintf(sqlCmd, "SELECT * FROM %s", MODULE_ALIAS_NAME(pContext->modName));
|
|
|
|
// get local configure
|
|
rc = sqlite3_exec(g_pSqlFileDB, sqlCmd, __sqlite3LoadCb, (void*)&pContext->modName, &pErrMsg);
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
LOG_EX(LOG_Error, "SQLite3 Query Error: %s\n", pErrMsg);
|
|
sqlite3_free(pErrMsg);
|
|
return -ERR_SQL_QUERY;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void CfgItemPrint(const char* pPrefix, PCFG_ITEM pCfgItem)
|
|
{
|
|
if(pCfgItem == NULL)
|
|
{
|
|
fprintf(stderr, "CfgItemPrint: NULL\n");
|
|
return;
|
|
}
|
|
|
|
switch(pCfgItem->keyType)
|
|
{
|
|
case 0:
|
|
LOG_EX(LOG_Debug, "%s[%s] = \"%s\", \ttype = %s, \tmodule = %s\n", pPrefix ? pPrefix : "",
|
|
pCfgItem->pKeyName, pCfgItem->pStrValue, __cfgGetKeyTypeString(pCfgItem->keyType), ModuleNameToString(pCfgItem->keyModule));
|
|
break;
|
|
|
|
case 1:
|
|
LOG_EX(LOG_Debug, "%s[%s] = %d, \ttype = %s, \tmodule = %s\n", pPrefix ? pPrefix : "",
|
|
pCfgItem->pKeyName, pCfgItem->intValue, __cfgGetKeyTypeString(pCfgItem->keyType), ModuleNameToString(pCfgItem->keyModule));
|
|
break;
|
|
|
|
case 2:
|
|
LOG_EX(LOG_Debug, "%s[%s] = %f, \ttype = %s, \tmodule = %s\n", pPrefix ? pPrefix : "",
|
|
pCfgItem->pKeyName, pCfgItem->doubleValue, __cfgGetKeyTypeString(pCfgItem->keyType), ModuleNameToString(pCfgItem->keyModule));
|
|
break;
|
|
|
|
default:
|
|
LOG_EX(LOG_Error, "Unknown type = %d\n", pCfgItem->keyType);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
int CfgAddGlobalConfig(const char *pKeyName, const char *pKeyValue, CFG_DATA_TYPE keyType)
|
|
{
|
|
CFG_API_REQ req;
|
|
int ret;
|
|
|
|
if(pKeyName == NULL || pKeyValue == NULL || strlen(pKeyName) == 0 || strlen(pKeyValue) == 0)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(keyType < 0 || keyType > CFG_TYPE_DOUBLE)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
memset(&req, 0, sizeof(CFG_API_REQ));
|
|
|
|
strncpy(req.keyName, pKeyName, MAX_CFG_KEY_NAME);
|
|
strncpy(req.keyValue, pKeyValue, MAX_CFG_KEY_VALUE);
|
|
|
|
ret = DBusJsonSendToCommand(NULL,
|
|
g_pModInfoTable[MODULE_CONFIGURE].modAliase,
|
|
CMD_CFG_ADD_REQ,
|
|
JSON_ENGINE_CFG_REQ,
|
|
&req, TRUE);
|
|
|
|
if(ret == 0)
|
|
{
|
|
return (-ERR_CFG_WAIT_RSP);
|
|
}
|
|
else
|
|
{
|
|
return (ret);
|
|
}
|
|
}
|
|
|
|
int CfgAddKeyValue(const char *pKeyName, PCFG_ITEM pItem, int saveToDB)
|
|
{
|
|
int err = 0;
|
|
PCFG_ITEM pCfgItem = NULL;
|
|
|
|
if(pItem == NULL || pKeyName == NULL || strlen(pKeyName) == 0)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
uv_rwlock_rdlock(&g_uvHashRwLock);
|
|
HASH_FIND_STR(g_pCfgItems, pKeyName, pCfgItem);
|
|
uv_rwlock_rdunlock(&g_uvHashRwLock);
|
|
|
|
if(pCfgItem != NULL)
|
|
{
|
|
return (-ERR_CFG_ITEM_EXIST);
|
|
}
|
|
|
|
if(pItem->keyType == CFG_TYPE_STRING)
|
|
{
|
|
__cfgAddItem(pKeyName, (const char*)pItem->pStrValue, pItem->keyType, FALSE, saveToDB, &err);
|
|
}
|
|
else
|
|
{
|
|
char buf[256];
|
|
memset(buf, 0, 256);
|
|
|
|
if(pItem->keyType == CFG_TYPE_INT)
|
|
{
|
|
sprintf(buf, "%d", pItem->intValue);
|
|
}
|
|
else if(pItem->keyType == CFG_TYPE_DOUBLE)
|
|
{
|
|
sprintf(buf, "%f", pItem->doubleValue);
|
|
}
|
|
|
|
__cfgAddItem(pKeyName, (const char*)buf, pItem->keyType, FALSE, saveToDB, &err);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
int CfgChangeKeyValue(const char *pKeyName, PCFG_ITEM pItem, int saveToDB)
|
|
{
|
|
int err = 0;
|
|
PCFG_ITEM pCfgItem = NULL;
|
|
|
|
if(pItem == NULL || pKeyName == NULL || strlen(pKeyName) == 0)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
uv_rwlock_rdlock(&g_uvHashRwLock);
|
|
HASH_FIND_STR(g_pCfgItems, pKeyName, pCfgItem);
|
|
uv_rwlock_rdunlock(&g_uvHashRwLock);
|
|
|
|
if(pCfgItem == NULL)
|
|
{
|
|
return (-ERR_CFG_NOITEM);
|
|
}
|
|
|
|
HASH_DEL(g_pCfgItems, pCfgItem);
|
|
|
|
if(pItem->keyType == CFG_TYPE_STRING)
|
|
{
|
|
__cfgAddItem(pKeyName, (const char*)pItem->pStrValue, pItem->keyType, FALSE, saveToDB, &err);
|
|
}
|
|
else
|
|
{
|
|
char buf[256];
|
|
memset(buf, 0, 256);
|
|
|
|
if(pItem->keyType == CFG_TYPE_INT)
|
|
{
|
|
sprintf(buf, "%d", pItem->intValue);
|
|
}
|
|
else if(pItem->keyType == CFG_TYPE_DOUBLE)
|
|
{
|
|
sprintf(buf, "%f", pItem->doubleValue);
|
|
}
|
|
|
|
__cfgAddItem(pKeyName, (const char*)buf, pItem->keyType, FALSE, saveToDB, &err);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
int CfgGetKeyValue(const char* pKeyName, PCFG_ITEM* pItem)
|
|
{
|
|
PCFG_ITEM pCfgItem = NULL;
|
|
PLIBUV_DBUS_PARAMS pContext = DBusLibuvGetRuntime();
|
|
|
|
if(pItem == NULL || pKeyName == NULL || strlen(pKeyName) == 0)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
uv_rwlock_rdlock(&g_uvHashRwLock);
|
|
HASH_FIND_STR(g_pCfgItems, pKeyName, pCfgItem);
|
|
uv_rwlock_rdunlock(&g_uvHashRwLock);
|
|
|
|
if(pCfgItem == NULL)
|
|
{
|
|
if(pContext->modName == MODULE_CONFIGURE)
|
|
{
|
|
return (-ERR_CFG_NOITEM);
|
|
}
|
|
else
|
|
{
|
|
CFG_API_REQ req;
|
|
int ret = 0;
|
|
memset(&req, 0, sizeof(CFG_API_REQ));
|
|
strncpy(req.keyName, pKeyName, MAX_CFG_KEY_NAME);
|
|
ret = DBusJsonSendToCommand(NULL, g_pModInfoTable[MODULE_CONFIGURE].modAliase, CMD_CFG_GET_REQ, JSON_ENGINE_CFG_REQ, &req, TRUE);
|
|
|
|
if(ret == 0)
|
|
{
|
|
return (-ERR_CFG_WAIT_RSP);
|
|
}
|
|
else
|
|
{
|
|
return (ret);
|
|
}
|
|
}
|
|
}
|
|
|
|
*pItem = pCfgItem;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __cfgCreateCfgFile(const char* pCfgFilePath)
|
|
{
|
|
/*const char* pSqlIntDB = NULL;
|
|
const char* pSqlFloatDB = NULL;
|
|
const char* pSqlStringDB = NULL; */
|
|
char* pErrMsg = NULL;
|
|
int rc = 0;
|
|
int i = 0;
|
|
|
|
rc = sqlite3_open_v2(pCfgFilePath, &g_pSqlFileDB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
|
|
|
if(rc)
|
|
{
|
|
LOG_EX(LOG_Error, "sqlite3_open_v2 error: %s\n", pCfgFilePath);
|
|
return -ERR_OPEN_SQLITE3_DB;
|
|
}
|
|
|
|
for(i = 0; (i < sizeof(g_pModInfoTable) / sizeof(g_pModInfoTable[0])); i++)
|
|
{
|
|
char sqlBuf[1024];
|
|
|
|
memset(sqlBuf, 0, 1024);
|
|
|
|
sprintf(sqlBuf, FIRMWARE_TBL_SQL_CMD, MODULE_ALIAS_NAME(i));
|
|
|
|
rc = sqlite3_exec(g_pSqlFileDB, sqlBuf, NULL, 0, &pErrMsg);
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
uv_fs_t uvFs;
|
|
LOG_EX(LOG_Error, "Create Tbl[%d] Error: %s\n", i, pErrMsg);
|
|
sqlite3_free(pErrMsg);
|
|
uv_fs_unlink(GetDBusDefaultLoop(), &uvFs, pCfgFilePath, NULL);
|
|
return -ERR_SQLITE3_CREATE_TABLE;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
static void onSigTermProgressExit(int sign)
|
|
{
|
|
if(g_bIsCfgSvr)
|
|
{
|
|
}
|
|
|
|
kill(getpid(), SIGKILL);
|
|
}
|
|
|
|
static void onProgressExit(void)
|
|
{
|
|
onSigTermProgressExit(0);
|
|
}
|
|
#endif
|
|
|
|
|
|
static int __cfgCheckCfgSvrRun(void)
|
|
{
|
|
int rc;
|
|
int fd = open(PROCESS_MUTEX_KEY, O_CREAT | O_RDWR, 0666);
|
|
|
|
if(fd == -1)
|
|
{
|
|
LOG_EX(LOG_Debug, "Open File Error\n");
|
|
}
|
|
|
|
rc = flock(fd, LOCK_EX | LOCK_NB);
|
|
|
|
if(rc == -1)
|
|
{
|
|
LOG_EX(LOG_Debug, "Configure server running\n");
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
LOG_EX(LOG_Debug, "Configure server stoped\n");
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
static int __cfgAddToCache(const char *pKeyName)
|
|
{
|
|
PCFG_CACHE_ITEM pItem = NULL;
|
|
|
|
uv_rwlock_rdlock(&g_uvCacheRwLock);
|
|
HASH_FIND_STR(g_pCfgCacheItems, pKeyName, pItem);
|
|
uv_rwlock_rdunlock(&g_uvCacheRwLock);
|
|
|
|
if(pItem != NULL)
|
|
{
|
|
HASH_DEL(g_pCfgCacheItems, pItem);
|
|
free(pItem);
|
|
}
|
|
|
|
pItem = (PCFG_CACHE_ITEM)malloc(sizeof(CFG_CACHE_ITEM));
|
|
|
|
strncpy(pItem->keyName, pKeyName, MAX_CFG_KEY_NAME);
|
|
pItem->tmCached = LIBUV_CURRENT_TIME_MS();
|
|
|
|
uv_rwlock_wrlock(&g_uvCacheRwLock);
|
|
HASH_ADD_STR(g_pCfgCacheItems, keyName, pItem);
|
|
uv_rwlock_wrunlock(&g_uvCacheRwLock);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static PCFG_ITEM __cfgAddItem(const char *pKeyName, const char *pKeyValue, int iType, int overWrite, int saveToDB, int* pErr)
|
|
{
|
|
PCFG_ITEM pCfgItem = NULL;
|
|
int iSize = 0;
|
|
char *pCache = NULL;
|
|
|
|
uv_rwlock_rdlock(&g_uvHashRwLock);
|
|
HASH_FIND_STR(g_pCfgItems, pKeyName, pCfgItem);
|
|
uv_rwlock_rdunlock(&g_uvHashRwLock);
|
|
|
|
if(pCfgItem != NULL)
|
|
{
|
|
if(overWrite)
|
|
{
|
|
HASH_DEL(g_pCfgItems, pCfgItem);
|
|
free(pCfgItem->pKeyName);
|
|
free(pCfgItem);
|
|
}
|
|
else
|
|
{
|
|
if(pErr)
|
|
{
|
|
*pErr = -ERR_CFG_NOITEM;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if(iType == CFG_TYPE_STRING)
|
|
{
|
|
iSize = strlen(pKeyName) + strlen(pKeyValue) + 2;
|
|
}
|
|
else
|
|
{
|
|
iSize = strlen(pKeyName) + 1;
|
|
}
|
|
|
|
pCache = (char *)malloc(iSize);
|
|
|
|
memset(pCache, 0, iSize);
|
|
pCfgItem = (PCFG_ITEM)malloc(sizeof(CFG_ITEM));
|
|
|
|
|
|
pCfgItem->pKeyName = pCache;
|
|
|
|
if(iType == CFG_TYPE_STRING)
|
|
{
|
|
pCfgItem->pStrValue = pCache + strlen(pKeyName) + 1;
|
|
}
|
|
|
|
__cfgMsg2CfgItem(iType, pKeyName, pKeyValue, pCfgItem);
|
|
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_ADD_STR(g_pCfgItems, pKeyName, pCfgItem);
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
|
|
// if need save this configure item to database
|
|
if(saveToDB)
|
|
{
|
|
__cfgAddToCache(pKeyName);
|
|
}
|
|
|
|
if(pErr)
|
|
{
|
|
*pErr = 0;
|
|
}
|
|
|
|
return (pCfgItem);
|
|
}
|
|
|
|
static void __cfgSyncServer(void)
|
|
{
|
|
if(HASH_COUNT(g_pCfgCacheItems) > 0)
|
|
{
|
|
PCFG_CACHE_ITEM pItem = NULL, pTemp = NULL;
|
|
|
|
sqlite3_exec(g_pSqlFileDB, "BEGIN TRANSACTION;", NULL, NULL, NULL);
|
|
|
|
HASH_ITER(hh, g_pCfgCacheItems, pItem, pTemp)
|
|
{
|
|
PCFG_ITEM pCfgItem = NULL;
|
|
|
|
if(CfgGetKeyValue(pItem->keyName, &pCfgItem) == 0)
|
|
{
|
|
char* pSqlInsertCmd = (char*)malloc(1024 * 4);
|
|
char* pSqlUpgradeCmd = (char*)malloc(1024 * 4);
|
|
memset(pSqlInsertCmd, 0, 1024 * 4);
|
|
memset(pSqlUpgradeCmd, 0, 1024 * 4);
|
|
|
|
if(pCfgItem->keyType == CFG_TYPE_STRING)
|
|
{
|
|
sprintf(pSqlInsertCmd, "INSERT OR IGNORE INTO %s (keyName, keyValue, keyType) VALUES (\'%s\', \'%s\', %d)",
|
|
MODULE_ALIAS_NAME(pCfgItem->keyModule), pCfgItem->pKeyName, pCfgItem->pStrValue, pCfgItem->keyType);
|
|
|
|
sprintf(pSqlUpgradeCmd, "UPDATE %s SET keyValue = \'%s\', keyType = %d WHERE keyName = \'%s\'",
|
|
MODULE_ALIAS_NAME(pCfgItem->keyModule), pCfgItem->pStrValue, pCfgItem->keyType, pCfgItem->pKeyName);
|
|
}
|
|
else if(pCfgItem->keyType == CFG_TYPE_INT)
|
|
{
|
|
sprintf(pSqlInsertCmd, "INSERT OR IGNORE INTO %s (keyName, keyValue, keyType) VALUES (\'%s\', \'%d\', %d)",
|
|
MODULE_ALIAS_NAME(pCfgItem->keyModule), pCfgItem->pKeyName, pCfgItem->intValue, pCfgItem->keyType);
|
|
|
|
sprintf(pSqlUpgradeCmd, "UPDATE %s SET keyValue = \'%d\', keyType = %d WHERE keyName = \'%s\'",
|
|
MODULE_ALIAS_NAME(pCfgItem->keyModule), pCfgItem->intValue, pCfgItem->keyType, pCfgItem->pKeyName);
|
|
}
|
|
else if(pCfgItem->keyType == CFG_TYPE_DOUBLE)
|
|
{
|
|
sprintf(pSqlInsertCmd, "INSERT OR IGNORE INTO %s (keyName, keyValue, keyType) VALUES (\'%s\', \'%f\', %d)",
|
|
MODULE_ALIAS_NAME(pCfgItem->keyModule), pCfgItem->pKeyName, pCfgItem->doubleValue, pCfgItem->keyType);
|
|
|
|
sprintf(pSqlUpgradeCmd, "UPDATE %s SET keyValue = \'%f\', keyType = %d WHERE keyName = \'%s\'",
|
|
MODULE_ALIAS_NAME(pCfgItem->keyModule), pCfgItem->doubleValue, pCfgItem->keyType, pCfgItem->pKeyName);
|
|
}
|
|
|
|
if((sqlite3_exec(g_pSqlFileDB, pSqlInsertCmd, NULL, NULL, NULL) == SQLITE_OK)
|
|
&& (sqlite3_exec(g_pSqlFileDB, pSqlUpgradeCmd, NULL, NULL, NULL) == SQLITE_OK))
|
|
{
|
|
// Delete this Key
|
|
HASH_DEL(g_pCfgCacheItems, pItem);
|
|
LOG_EX(LOG_Debug, "Sync Configure %s To Database\n", pCfgItem->pKeyName);
|
|
}
|
|
else
|
|
{
|
|
free(pSqlInsertCmd);
|
|
free(pSqlUpgradeCmd);
|
|
return;
|
|
}
|
|
|
|
free(pSqlInsertCmd);
|
|
free(pSqlUpgradeCmd);
|
|
}
|
|
else
|
|
{
|
|
// Delete this Key
|
|
HASH_DEL(g_pCfgCacheItems, pItem);
|
|
}
|
|
}
|
|
|
|
sqlite3_exec(g_pSqlFileDB, "END TRANSACTION;", NULL, NULL, NULL);
|
|
}
|
|
}
|
|
static void __uvThreadSyncCfg(void *pParams)
|
|
{
|
|
while(TRUE)
|
|
{
|
|
__cfgSyncServer();
|
|
sleep(CFG_SYNC_TIME_OF_SECONDS);
|
|
}
|
|
|
|
pthread_detach(pthread_self());
|
|
}
|
|
|
|
static void __cfgStartSyncGlobalCfgSvr(void)
|
|
{
|
|
uv_thread_t uvSyncThread;
|
|
|
|
uv_rwlock_init(&g_uvCacheRwLock);
|
|
|
|
uv_thread_create(&uvSyncThread, __uvThreadSyncCfg, NULL);
|
|
}
|
|
|
|
static PCFG_ITEM __onCMD_CFG_GET_REQ(const char* pKeyName, int* pErr)
|
|
{
|
|
PCFG_ITEM pItem = NULL;
|
|
|
|
*pErr = CfgGetKeyValue(pKeyName, &pItem);
|
|
|
|
if(*pErr == 0)
|
|
{
|
|
return (pItem);
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
static int __onCMD_CFG_ADD_REQ(const char* pKeyName, const char* pKeyValue, int keyType)
|
|
{
|
|
PCFG_ITEM pCfgItem = NULL;
|
|
int ret;
|
|
|
|
if(pKeyName == NULL || pKeyValue == NULL || strlen(pKeyName) == 0 || strlen(pKeyValue) == 0)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(keyType < 0 || keyType > CFG_TYPE_DOUBLE)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
ret = __cfgMsg2CfgItemV2(keyType, pKeyName, pKeyValue, &pCfgItem);
|
|
|
|
if(ret != 0)
|
|
{
|
|
return (ret);
|
|
}
|
|
|
|
return CfgAddKeyValue(pKeyName, pCfgItem, TRUE);
|
|
}
|
|
|
|
static void __cfgSvrProcessCmd(DBUS_CMD cmd, const char* pKeyName, const char* pKeyValue, int keyType, PCFG_API_RSP pRsp)
|
|
{
|
|
PCFG_ITEM pItem = NULL;
|
|
int err;
|
|
|
|
memset(pRsp, 0, sizeof(CFG_API_RSP));
|
|
pRsp->errNo = -ERR_UNKNOWN_TYPE;
|
|
|
|
if(pKeyName == NULL)
|
|
{
|
|
pRsp->errNo = -ERR_INPUT_PARAMS;
|
|
return;
|
|
}
|
|
|
|
strncpy(pRsp->keyName, pKeyName, MAX_CFG_KEY_NAME);
|
|
|
|
switch(cmd)
|
|
{
|
|
case CMD_CFG_ADD_REQ:
|
|
err = __onCMD_CFG_ADD_REQ(pKeyName, pKeyValue, keyType);
|
|
|
|
pRsp->keyType = keyType;
|
|
pRsp->errNo = err;
|
|
strncpy(pRsp->keyName, pKeyName, MAX_CFG_KEY_NAME);
|
|
strncpy(pRsp->keyValue, pKeyValue, MAX_CFG_KEY_VALUE);
|
|
|
|
break;
|
|
|
|
case CMD_CFG_GET_REQ:
|
|
|
|
pItem = __onCMD_CFG_GET_REQ(pKeyName, &err);
|
|
|
|
if(pItem == NULL || err != 0)
|
|
{
|
|
pRsp->keyType = -1;
|
|
pRsp->errNo = err;
|
|
strncpy(pRsp->keyName, pKeyName, MAX_CFG_KEY_NAME);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
__cfgItem2CfgRsp(pItem, pRsp);
|
|
return;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int CfgGlobalEnvInit(void)
|
|
{
|
|
int rc = 0;
|
|
|
|
uv_rwlock_init(&g_uvHashRwLock);
|
|
|
|
rc = __cfgCreateCfgFile(GLOBAL_CFG_FILE_PATH);
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#if 0
|
|
rc = sqlite3_open_v2(":memory:", &g_pSqlMemDB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
LOG_EX(LOG_Error, "Create Memory SQLite3 DB Error\n");
|
|
return -ERR_CREATE_SQLITE3_DB;
|
|
}
|
|
|
|
//rc = sqlite3SyncDatabase(g_pSqlMemDB, GLOBAL_CFG_FILE_PATH, 0);
|
|
#endif
|
|
rc = __cfgLoadGlobalConfig();
|
|
|
|
if(rc != SQLITE_OK)
|
|
{
|
|
return (-ERR_OPEN_SQLITE3_DB);
|
|
//sqlite3_close(g_pSqlFileDB);
|
|
}
|
|
|
|
#if 0
|
|
g_bIsCfgSvr = cfgCheckCfgSvrRun();
|
|
|
|
if(atexit(onProgressExit) != 0)
|
|
{
|
|
fprintf(stderr, "atexit error\n");
|
|
}
|
|
|
|
signal(SIGINT, onSigTermProgressExit);
|
|
#endif
|
|
|
|
__cfgStartSyncGlobalCfgSvr();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void OnCfgMsgProcess(MODULE_NAME dest, DBUS_CMD busCmd, const char* pJsonStr)
|
|
{
|
|
CFG_API_RSP cfgRsp;
|
|
int err = 0;
|
|
PCFG_API_REQ pReq = NULL;
|
|
PCFG_API_RSP pRsp = NULL;
|
|
PLIBUV_DBUS_PARAMS pParams = DBusLibuvGetRuntime();
|
|
|
|
switch(busCmd)
|
|
{
|
|
case CMD_CFG_ADD_REQ:
|
|
case CMD_CFG_GET_REQ:
|
|
pReq = Json2Struct(pJsonStr, JSON_ENGINE_CFG_REQ, TRUE, &err);
|
|
|
|
if(pReq != NULL && err == 0)
|
|
{
|
|
pRsp = &cfgRsp;
|
|
__cfgSvrProcessCmd(busCmd, pReq->keyName, pReq->keyValue, pReq->keyType, pRsp);
|
|
DBusJsonSendToCommand(NULL, g_pModInfoTable[dest].modAliase, busCmd + 1, JSON_ENGINE_CFG_RSP, pRsp, TRUE);
|
|
}
|
|
|
|
free(pReq);
|
|
break;
|
|
#if 0
|
|
case CMD_CFG_GET_REQ:
|
|
pReq = Json2Struct(pJsonStr, JSON_ENGINE_CFG_REQ, TRUE, &err);
|
|
|
|
if(pReq != NULL && err == 0)
|
|
{
|
|
pRsp = &cfgRsp;
|
|
__cfgSvrProcessCmd(busCmd, pReq->keyName, NULL, pReq->keyType, pRsp);
|
|
DBusJsonSendToCommand(NULL, g_pModInfoTable[dest].modAliase, CMD_CFG_GET_RSP, JSON_ENGINE_CFG_RSP, pRsp, TRUE);
|
|
}
|
|
break;
|
|
#endif
|
|
case CMD_CFG_ADD_RSP:
|
|
case CMD_CFG_GET_RSP:
|
|
pRsp = Json2Struct(pJsonStr, JSON_ENGINE_CFG_RSP, TRUE, &err);
|
|
|
|
if(pRsp != NULL && err == 0 && pRsp->errNo == 0)
|
|
{
|
|
// Add to local Hash Table cache
|
|
PCFG_ITEM pCfgItem = __cfgAddItem(pRsp->keyName, pRsp->keyValue, pRsp->keyType, TRUE, FALSE, &err);
|
|
|
|
if(err == 0 && pCfgItem != NULL)
|
|
{
|
|
if(pParams->onCfgCb)
|
|
{
|
|
pParams->onCfgCb(busCmd, pCfgItem, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOG_EX(LOG_Error, "Add Configure {[%s]<%d> = \"%s\"} Error: %d\n",
|
|
pRsp->keyName, pRsp->keyValue, pRsp->keyType, err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pParams->onCfgCb)
|
|
{
|
|
pParams->onCfgCb(busCmd, NULL, (err == 0) ? pRsp->errNo : err);
|
|
}
|
|
|
|
LOG_EX(LOG_Error, "pRsp = %p, err = %d, rspErr = %d\n", pRsp, err, pRsp ? pRsp->errNo : -err);
|
|
}
|
|
|
|
free(pRsp);
|
|
break;
|
|
}
|
|
}
|