metadata table cached in memory
[public/netxms.git] / src / server / core / config.cpp
CommitLineData
b81d7b7d 1/*
5039dede 2** NetXMS - Network Management System
f33d5471 3** Copyright (C) 2003-2016 Victor Kirhenshtein
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: config.cpp
20**
21**/
22
23#include "nxcore.h"
e6c91aac 24#include <nxconfig.h>
5039dede 25
69bb7f47
VK
26/**
27 * Externals
28 */
dda7c270 29extern char g_szCodePage[];
8fd95c92
VK
30extern TCHAR *g_moduleLoadList;
31extern TCHAR *g_pdsLoadList;
5039dede 32
69bb7f47
VK
33/**
34 * database connection parameters
35 */
b8c1ec69
VK
36TCHAR g_szDbDriver[MAX_PATH] = _T("");
37TCHAR g_szDbDrvParams[MAX_PATH] = _T("");
38TCHAR g_szDbServer[MAX_PATH] = _T("127.0.0.1");
39TCHAR g_szDbLogin[MAX_DB_LOGIN] = _T("netxms");
07ca7d19 40TCHAR g_szDbPassword[MAX_PASSWORD] = _T("");
b8c1ec69 41TCHAR g_szDbName[MAX_DB_NAME] = _T("netxms_db");
f3c30cf5 42TCHAR g_szDbSchema[MAX_DB_NAME] = _T("");
b8c1ec69 43
2df047f4
VK
44/**
45 * Debug level from config
46 */
47static UINT32 s_debugLevel = (UINT32)NXCONFIG_UNINITIALIZED_VALUE;
48
69bb7f47
VK
49/**
50 * Config file template
51 */
5039dede
AK
52static NX_CFG_TEMPLATE m_cfgTemplate[] =
53{
e95680e5 54 { _T("BackgroundLogWriter"), CT_BOOLEAN64, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_flags, NULL },
e2e66145 55 { _T("CodePage"), CT_MB_STRING, 0, 0, 256, 0, g_szCodePage, NULL },
e95680e5 56 { _T("CreateCrashDumps"), CT_BOOLEAN64, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_flags, NULL },
e5e015dd 57 { _T("DailyLogFileSuffix"), CT_STRING, 0, 0, 64, 0, g_szDailyLogFileSuffix, NULL },
db6a6b45 58 { _T("DataDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdDataDir, NULL },
e2e66145
VK
59 { _T("DBDriver"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDriver, NULL },
60 { _T("DBDrvParams"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDrvParams, NULL },
e2e66145
VK
61 { _T("DBLogin"), CT_STRING, 0, 0, MAX_DB_LOGIN, 0, g_szDbLogin, NULL },
62 { _T("DBName"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbName, NULL },
07ca7d19 63 { _T("DBPassword"), CT_STRING, 0, 0, MAX_PASSWORD, 0, g_szDbPassword, NULL },
64 { _T("DBEncryptedPassword"), CT_STRING, 0, 0, MAX_PASSWORD, 0, g_szDbPassword, NULL },
d010c10e 65 { _T("DBSchema"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbSchema, NULL },
e2e66145 66 { _T("DBServer"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbServer, NULL },
2df047f4 67 { _T("DebugLevel"), CT_LONG, 0, 0, 0, 0, &s_debugLevel, &s_debugLevel },
e2e66145 68 { _T("DumpDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDumpDir, NULL },
e95680e5 69 { _T("FullCrashDumps"), CT_BOOLEAN64, 0, 0, AF_WRITE_FULL_DUMP, 0, &g_flags, NULL },
db6a6b45 70 { _T("LibraryDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdLibDir, NULL },
e2e66145 71 { _T("ListenAddress"), CT_STRING, 0, 0, MAX_PATH, 0, g_szListenAddress, NULL },
e95680e5 72 { _T("LogFailedSQLQueries"), CT_BOOLEAN64, 0, 0, AF_LOG_SQL_ERRORS, 0, &g_flags, NULL },
e2e66145
VK
73 { _T("LogFile"), CT_STRING, 0, 0, MAX_PATH, 0, g_szLogFile, NULL },
74 { _T("LogHistorySize"), CT_LONG, 0, 0, 0, 0, &g_dwLogHistorySize, NULL },
75 { _T("LogRotationMode"), CT_LONG, 0, 0, 0, 0, &g_dwLogRotationMode, NULL },
76 { _T("MaxLogSize"), CT_LONG, 0, 0, 0, 0, &g_dwMaxLogSize, NULL },
8fd95c92
VK
77 { _T("Module"), CT_STRING_LIST, '\n', 0, 0, 0, &g_moduleLoadList, NULL },
78 { _T("PerfDataStorageDriver"), CT_STRING_LIST, '\n', 0, 0, 0, &g_pdsLoadList, NULL },
e2e66145
VK
79 { _T("ProcessAffinityMask"), CT_LONG, 0, 0, 0, 0, &g_processAffinityMask, NULL },
80 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL, NULL }
5039dede
AK
81};
82
f19168bd
VK
83/**
84 * Loaded server config
85 */
86Config g_serverConfig;
87
69bb7f47
VK
88/**
89 * Load and parse configuration file
90 * Returns TRUE on success and FALSE on failure
91 */
2df047f4 92bool NXCORE_EXPORTABLE LoadConfig(int *debugLevel)
5039dede 93{
35959841 94 bool bSuccess = false;
5039dede 95
5039dede
AK
96 if (!_tcscmp(g_szConfigFile, _T("{search}")))
97 {
1039d7ee
VK
98#ifdef _WIN32
99 TCHAR path[MAX_PATH];
100 GetNetXMSDirectory(nxDirEtc, path);
101 _tcscat(path, _T("\\netxmsd.conf"));
102 if (_taccess(path, 4) == 0)
103 {
104 _tcscpy(g_szConfigFile, path);
105 }
106 else
107 {
108 _tcscpy(g_szConfigFile, _T("C:\\netxmsd.conf"));
109 }
110#else
38ffd4b0
VK
111 const TCHAR *homeDir = _tgetenv(_T("NETXMS_HOME"));
112 if ((homeDir != NULL) && (*homeDir != 0))
113 {
114 TCHAR config[MAX_PATH];
115 _sntprintf(config, MAX_PATH, _T("%s/etc/netxmsd.conf"), homeDir);
116 if (_taccess(config, 4) == 0)
117 {
118 _tcscpy(g_szConfigFile, config);
119 goto stop_search;
120 }
121 }
b07c50cc 122 if (_taccess(PREFIX _T("/etc/netxmsd.conf"), 4) == 0)
5039dede 123 {
35f836fe 124 _tcscpy(g_szConfigFile, PREFIX _T("/etc/netxmsd.conf"));
5039dede 125 }
b07c50cc 126 else if (_taccess(_T("/usr/etc/netxmsd.conf"), 4) == 0)
5039dede 127 {
35f836fe 128 _tcscpy(g_szConfigFile, _T("/usr/etc/netxmsd.conf"));
5039dede
AK
129 }
130 else
131 {
35f836fe 132 _tcscpy(g_szConfigFile, _T("/etc/netxmsd.conf"));
5039dede 133 }
38ffd4b0
VK
134stop_search:
135 ;
5039dede 136#endif
1039d7ee 137 }
e1eed5b8 138
5039dede 139 if (IsStandalone())
35f836fe 140 _tprintf(_T("Using configuration file \"%s\"\n"), g_szConfigFile);
5039dede 141
f19168bd 142 if (g_serverConfig.loadConfig(g_szConfigFile, _T("server")) && g_serverConfig.parseTemplate(_T("server"), m_cfgTemplate))
5039dede 143 {
35f836fe
VK
144 if ((!_tcsicmp(g_szLogFile, _T("{EventLog}"))) ||
145 (!_tcsicmp(g_szLogFile, _T("{syslog}"))))
5039dede 146 {
c8076b19 147 g_flags |= AF_USE_SYSLOG;
5039dede
AK
148 }
149 else
150 {
c8076b19 151 g_flags &= ~AF_USE_SYSLOG;
5039dede 152 }
35959841 153 bSuccess = true;
5039dede 154 }
d96bd4c7 155
2df047f4
VK
156 if (*debugLevel == NXCONFIG_UNINITIALIZED_VALUE)
157 *debugLevel = (int)s_debugLevel;
158
d96bd4c7 159 // Decrypt password
07ca7d19 160 DecryptPassword(g_szDbLogin, g_szDbPassword, g_szDbPassword, MAX_PASSWORD);
5039dede
AK
161 return bSuccess;
162}
163
0fdb37c6
VK
164/**
165 * Metadata cache
166 */
167static StringMap s_metadataCache;
168static RWLOCK s_metadataCacheLock = RWLockCreate();
169
170/**
171 * Pre-load metadata
172 */
173void MetaDataPreLoad()
174{
175 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
176 DB_RESULT hResult = DBSelect(hdb, _T("SELECT var_name,var_value FROM metadata"));
177 if (hResult != NULL)
178 {
179 RWLockWriteLock(s_metadataCacheLock, INFINITE);
180 s_metadataCache.clear();
181 int count = DBGetNumRows(hResult);
182 for(int i = 0; i < count; i++)
183 {
184 s_metadataCache.setPreallocated(DBGetField(hResult, i, 0, NULL, 0), DBGetField(hResult, i, 1, NULL, 0));
185 }
186 RWLockUnlock(s_metadataCacheLock);
187 DBFreeResult(hResult);
188 }
189 DBConnectionPoolReleaseConnection(hdb);
190}
191
69bb7f47
VK
192/**
193 * Read string value from metadata table
194 */
0fdb37c6 195bool NXCORE_EXPORTABLE MetaDataReadStr(const TCHAR *name, TCHAR *buffer, int bufSize, const TCHAR *defaultValue)
28f5b9a4 196{
35959841 197 bool bSuccess = false;
28f5b9a4 198
0fdb37c6
VK
199 nx_strncpy(buffer, defaultValue, bufSize);
200 if (_tcslen(name) > 127)
35959841 201 return false;
28f5b9a4 202
0fdb37c6
VK
203 RWLockReadLock(s_metadataCacheLock, INFINITE);
204 const TCHAR *value = s_metadataCache.get(name);
205 if (value != NULL)
206 {
207 nx_strncpy(buffer, value, bufSize);
208 bSuccess = true;
209 }
210 RWLockUnlock(s_metadataCacheLock);
211
212 if (!bSuccess)
213 {
214 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
215 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM metadata WHERE var_name=?"));
216 if (hStmt != NULL)
217 {
218 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
219 DB_RESULT hResult = DBSelectPrepared(hStmt);
220 if (hResult != NULL)
221 {
222 if (DBGetNumRows(hResult) > 0)
223 {
224 DBGetField(hResult, 0, 0, buffer, bufSize);
225 RWLockWriteLock(s_metadataCacheLock, INFINITE);
226 s_metadataCache.setPreallocated(_tcsdup(name), DBGetField(hResult, 0, 0, NULL, 0));
227 RWLockUnlock(s_metadataCacheLock);
228 bSuccess = true;
229 }
230 DBFreeResult(hResult);
231 }
232 DBFreeStatement(hStmt);
233 }
234 DBConnectionPoolReleaseConnection(hdb);
235 }
28f5b9a4
VK
236 return bSuccess;
237}
238
40dedf5d
VK
239/**
240 * Read integer value from metadata table
241 */
242INT32 NXCORE_EXPORTABLE MetaDataReadInt(const TCHAR *var, UINT32 defaultValue)
243{
244 TCHAR buffer[256];
245 if (MetaDataReadStr(var, buffer, 256, _T("")))
246 {
247 TCHAR *eptr;
248 INT32 value = _tcstol(buffer, &eptr, 0);
249 return (*eptr == 0) ? value : defaultValue;
250 }
251 else
252 {
253 return defaultValue;
254 }
255}
256
e9902466
VK
257/**
258 * Write string value to metadata table
259 */
260bool NXCORE_EXPORTABLE MetaDataWriteStr(const TCHAR *varName, const TCHAR *value)
261{
262 if (_tcslen(varName) > 63)
263 return false;
264
0fdb37c6
VK
265 RWLockWriteLock(s_metadataCacheLock, INFINITE);
266 s_metadataCache.set(varName, value);
267 RWLockUnlock(s_metadataCacheLock);
268
e9902466
VK
269 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
270
271 // Check for variable existence
272 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM metadata WHERE var_name=?"));
273 if (hStmt == NULL)
274 {
275 DBConnectionPoolReleaseConnection(hdb);
276 return false;
277 }
278 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
279 DB_RESULT hResult = DBSelectPrepared(hStmt);
280 bool bVarExist = false;
281 if (hResult != NULL)
282 {
283 if (DBGetNumRows(hResult) > 0)
284 bVarExist = true;
285 DBFreeResult(hResult);
286 }
287 DBFreeStatement(hStmt);
288
289 // Create or update variable value
290 if (bVarExist)
291 {
292 hStmt = DBPrepare(hdb, _T("UPDATE metadata SET var_value=? WHERE var_name=?"));
293 if (hStmt == NULL)
294 {
295 DBConnectionPoolReleaseConnection(hdb);
296 return false;
297 }
298 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
299 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
300 }
301 else
302 {
303 hStmt = DBPrepare(hdb, _T("INSERT INTO metadata (var_name,var_value) VALUES (?,?)"));
304 if (hStmt == NULL)
305 {
306 DBConnectionPoolReleaseConnection(hdb);
307 return false;
308 }
309 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
310 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
311 }
312 bool success = DBExecute(hStmt);
313 DBFreeStatement(hStmt);
314 DBConnectionPoolReleaseConnection(hdb);
315 return success;
316}
317
35959841
VK
318/**
319 * Config cache
320 */
321static StringMap s_configCache;
322static RWLOCK s_configCacheLock = RWLockCreate();
323
69bb7f47
VK
324/**
325 * Callback for configuration variables change
326 */
35959841 327static void OnConfigVariableChange(bool isCLOB, const TCHAR *name, const TCHAR *value)
4d0c32f3 328{
35959841
VK
329 RWLockWriteLock(s_configCacheLock, INFINITE);
330 s_configCache.set(name, value);
331 RWLockUnlock(s_configCacheLock);
332
4d0c32f3
VK
333 // Restart syslog parser if configuration was changed
334 if (isCLOB && !_tcscmp(name, _T("SyslogParser")))
335 {
336 ReinitializeSyslogParser();
337 }
958a9397
VK
338 else if (!_tcsncmp(name, _T("CAS"), 3))
339 {
340 CASReadSettings();
341 }
90e3031f
VK
342 else if (!_tcscmp(name, _T("DefaultDCIPollingInterval")))
343 {
344 DCObject::m_defaultPollingInterval = _tcstol(value, NULL, 0);
345 }
346 else if (!_tcscmp(name, _T("DefaultDCIRetentionTime")))
347 {
348 DCObject::m_defaultRetentionTime = _tcstol(value, NULL, 0);
349 }
d184506f 350 else if (!_tcscmp(name, _T("StrictAlarmStatusFlow")))
b81d7b7d 351 {
d184506f 352 NotifyClientSessions(NX_NOTIFY_ALARM_STATUS_FLOW_CHANGED, _tcstol(value, NULL, 0));
b81d7b7d 353 }
b8c8a8a7
VK
354 else if (!_tcsncmp(name, _T("Syslog"), 6))
355 {
356 OnSyslogConfigurationChange(name, value);
357 }
4d0c32f3
VK
358}
359
f5797a09
VK
360/**
361 * Read string value from configuration table
362 */
9bd1bace 363bool NXCORE_EXPORTABLE ConfigReadStrEx(DB_HANDLE dbHandle, const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
5039dede 364{
5039dede
AK
365 nx_strncpy(szBuffer, szDefault, iBufSize);
366 if (_tcslen(szVar) > 127)
35959841
VK
367 return false;
368
369 RWLockReadLock(s_configCacheLock, INFINITE);
370 const TCHAR *value = s_configCache.get(szVar);
371 RWLockUnlock(s_configCacheLock);
372 if (value != NULL)
373 {
374 nx_strncpy(szBuffer, value, iBufSize);
375 DbgPrintf(8, _T("ConfigReadStr: (cached) name=%s value=\"%s\""), szVar, szBuffer);
376 return true;
377 }
5039dede 378
9bd1bace
VK
379 bool bSuccess = false;
380 DB_HANDLE hdb = (dbHandle == NULL) ? DBConnectionPoolAcquireConnection() : dbHandle;
d58757ae 381 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
9af35d07
VK
382 if (hStmt != NULL)
383 {
384 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
9bd1bace 385 DB_RESULT hResult = DBSelectPrepared(hStmt);
9af35d07
VK
386 if (hResult != NULL)
387 {
388 if (DBGetNumRows(hResult) > 0)
389 {
390 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
1fa5706e 391 DbgPrintf(8, _T("ConfigReadStr: name=%s value=\"%s\""), szVar, szBuffer);
35959841 392 bSuccess = true;
9af35d07
VK
393 }
394 DBFreeResult(hResult);
395 }
396 DBFreeStatement(hStmt);
397 }
9bd1bace 398 if (dbHandle == NULL)
e94b29f6 399 DBConnectionPoolReleaseConnection(hdb);
35959841
VK
400
401 if (bSuccess)
402 {
403 RWLockWriteLock(s_configCacheLock, INFINITE);
404 s_configCache.set(szVar, szBuffer);
405 RWLockUnlock(s_configCacheLock);
406 }
407
5039dede
AK
408 return bSuccess;
409}
410
9bd1bace
VK
411/**
412 * Read string value from configuration table
413 */
414bool NXCORE_EXPORTABLE ConfigReadStr(const TCHAR *var, TCHAR *buffer, int bufferSize, const TCHAR *defaultValue)
415{
416 return ConfigReadStrEx(NULL, var, buffer, bufferSize, defaultValue);
417}
418
f5797a09
VK
419/**
420 * Read multibyte string from configuration table
421 */
35f836fe
VK
422#ifdef UNICODE
423
35959841 424bool NXCORE_EXPORTABLE ConfigReadStrA(const WCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
35f836fe
VK
425{
426 WCHAR *wcBuffer = (WCHAR *)malloc(iBufSize * sizeof(WCHAR));
35959841 427 bool rc = ConfigReadStr(szVar, wcBuffer, iBufSize, _T(""));
35f836fe
VK
428 if (rc)
429 {
430 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, wcBuffer, -1, szBuffer, iBufSize, NULL, NULL);
431 }
432 else
433 {
434 strncpy(szBuffer, szDefault, iBufSize);
435 }
436 szBuffer[iBufSize - 1] = 0;
437 free(wcBuffer);
438 return rc;
439}
440
441#endif
442
43526096
VK
443/**
444 * Read string value from configuration table as UTF8 string
445 */
446bool NXCORE_EXPORTABLE ConfigReadStrUTF8(const TCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
447{
448 DB_RESULT hResult;
449 bool bSuccess = false;
450
451 strncpy(szBuffer, szDefault, iBufSize);
452 if (_tcslen(szVar) > 127)
453 return false;
454
9bd1bace 455 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
43526096
VK
456 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
457 if (hStmt != NULL)
458 {
459 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
460 hResult = DBSelectPrepared(hStmt);
461 if (hResult != NULL)
462 {
463 if (DBGetNumRows(hResult) > 0)
464 {
465 DBGetFieldUTF8(hResult, 0, 0, szBuffer, iBufSize);
466 bSuccess = true;
467 }
468 DBFreeResult(hResult);
469 }
470 DBFreeStatement(hStmt);
471 }
9bd1bace 472 DBConnectionPoolReleaseConnection(hdb);
43526096
VK
473
474 return bSuccess;
475}
476
69bb7f47
VK
477/**
478 * Read integer value from configuration table
479 */
5039dede 480int NXCORE_EXPORTABLE ConfigReadInt(const TCHAR *szVar, int iDefault)
9bd1bace
VK
481{
482 return ConfigReadIntEx(NULL, szVar, iDefault);
483}
484
485/**
486 * Read integer value from configuration table
487 */
488int NXCORE_EXPORTABLE ConfigReadIntEx(DB_HANDLE hdb, const TCHAR *szVar, int iDefault)
5039dede
AK
489{
490 TCHAR szBuffer[64];
491
9bd1bace 492 if (ConfigReadStrEx(hdb, szVar, szBuffer, 64, _T("")))
5039dede
AK
493 return _tcstol(szBuffer, NULL, 0);
494 else
495 return iDefault;
496}
497
69bb7f47 498/**
b81d7b7d 499 * Read unsigned long value from configuration table
69bb7f47 500 */
967893bb 501UINT32 NXCORE_EXPORTABLE ConfigReadULong(const TCHAR *szVar, UINT32 dwDefault)
5039dede
AK
502{
503 TCHAR szBuffer[64];
504
505 if (ConfigReadStr(szVar, szBuffer, 64, _T("")))
506 return _tcstoul(szBuffer, NULL, 0);
507 else
508 return dwDefault;
509}
510
69bb7f47
VK
511/**
512 * Read byte array (in hex form) from configuration table into integer array
513 */
35959841 514bool NXCORE_EXPORTABLE ConfigReadByteArray(const TCHAR *pszVar, int *pnArray, int nSize, int nDefault)
5039dede
AK
515{
516 TCHAR szBuffer[256];
517 char pbBytes[128];
35959841 518 bool bResult;
5039dede
AK
519 int i, nLen;
520
521 if (ConfigReadStr(pszVar, szBuffer, 256, _T("")))
522 {
523 StrToBin(szBuffer, (BYTE *)pbBytes, 128);
35f836fe 524 nLen = (int)_tcslen(szBuffer) / 2;
5039dede
AK
525 for(i = 0; (i < nSize) && (i < nLen); i++)
526 pnArray[i] = pbBytes[i];
527 for(; i < nSize; i++)
528 pnArray[i] = nDefault;
35959841 529 bResult = true;
5039dede
AK
530 }
531 else
532 {
533 for(i = 0; i < nSize; i++)
534 pnArray[i] = nDefault;
35959841 535 bResult = false;
5039dede
AK
536 }
537 return bResult;
538}
539
69bb7f47
VK
540/**
541 * Write string value to configuration table
542 */
35959841 543bool NXCORE_EXPORTABLE ConfigWriteStr(const TCHAR *varName, const TCHAR *value, bool bCreate, bool isVisible, bool needRestart)
5039dede 544{
d6bf58f9 545 if (_tcslen(varName) > 63)
35959841 546 return false;
5039dede 547
d58757ae
VK
548 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
549
5039dede 550 // Check for variable existence
d58757ae 551 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
d6bf58f9 552 if (hStmt == NULL)
d58757ae
VK
553 {
554 DBConnectionPoolReleaseConnection(hdb);
35959841 555 return false;
d58757ae 556 }
d6bf58f9
VK
557 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
558 DB_RESULT hResult = DBSelectPrepared(hStmt);
35959841 559 bool bVarExist = false;
5039dede
AK
560 if (hResult != NULL)
561 {
562 if (DBGetNumRows(hResult) > 0)
35959841 563 bVarExist = true;
5039dede
AK
564 DBFreeResult(hResult);
565 }
d6bf58f9 566 DBFreeStatement(hStmt);
5039dede
AK
567
568 // Don't create non-existing variable if creation flag not set
569 if (!bCreate && !bVarExist)
d58757ae
VK
570 {
571 DBConnectionPoolReleaseConnection(hdb);
35959841 572 return false;
d58757ae 573 }
5039dede
AK
574
575 // Create or update variable value
5039dede 576 if (bVarExist)
d6bf58f9 577 {
d58757ae 578 hStmt = DBPrepare(hdb, _T("UPDATE config SET var_value=? WHERE var_name=?"));
d6bf58f9 579 if (hStmt == NULL)
b3eb058b
VK
580 {
581 DBConnectionPoolReleaseConnection(hdb);
35959841 582 return false;
b3eb058b
VK
583 }
584 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
d6bf58f9
VK
585 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
586 }
5039dede 587 else
d6bf58f9 588 {
d58757ae 589 hStmt = DBPrepare(hdb, _T("INSERT INTO config (var_name,var_value,is_visible,need_server_restart) VALUES (?,?,?,?)"));
d6bf58f9 590 if (hStmt == NULL)
b3eb058b
VK
591 {
592 DBConnectionPoolReleaseConnection(hdb);
35959841 593 return false;
b3eb058b 594 }
d6bf58f9
VK
595 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
596 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
597 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)(isVisible ? 1 : 0));
598 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)(needRestart ? 1 : 0));
599 }
e9902466 600 bool success = DBExecute(hStmt);
d6bf58f9 601 DBFreeStatement(hStmt);
d58757ae 602 DBConnectionPoolReleaseConnection(hdb);
4d0c32f3 603 if (success)
35959841 604 OnConfigVariableChange(false, varName, value);
4d0c32f3 605 return success;
5039dede
AK
606}
607
69bb7f47
VK
608/**
609 * Write integer value to configuration table
610 */
35959841 611bool NXCORE_EXPORTABLE ConfigWriteInt(const TCHAR *szVar, int iValue, bool bCreate, bool isVisible, bool needRestart)
5039dede
AK
612{
613 TCHAR szBuffer[64];
614
35f836fe 615 _sntprintf(szBuffer, 64, _T("%d"), iValue);
5039dede
AK
616 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
617}
618
69bb7f47
VK
619/**
620 * Write unsigned long value to configuration table
621 */
35959841 622bool NXCORE_EXPORTABLE ConfigWriteULong(const TCHAR *szVar, UINT32 dwValue, bool bCreate, bool isVisible, bool needRestart)
5039dede
AK
623{
624 TCHAR szBuffer[64];
625
35f836fe 626 _sntprintf(szBuffer, 64, _T("%u"), dwValue);
5039dede
AK
627 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
628}
629
69bb7f47
VK
630/**
631 * Write integer array to configuration table
632 */
35959841 633bool NXCORE_EXPORTABLE ConfigWriteByteArray(const TCHAR *pszVar, int *pnArray, int nSize, bool bCreate, bool isVisible, bool needRestart)
5039dede
AK
634{
635 TCHAR szBuffer[256];
636 int i, j;
637
638 for(i = 0, j = 0; (i < nSize) && (i < 127); i++, j += 2)
35f836fe 639 _sntprintf(&szBuffer[j], 256 - j, _T("%02X"), (char)((pnArray[i] > 127) ? 127 : ((pnArray[i] < -127) ? -127 : pnArray[i])));
5039dede
AK
640 return ConfigWriteStr(pszVar, szBuffer, bCreate, isVisible, needRestart);
641}
642
35959841
VK
643/**
644 * Delete configuratrion variable
645 */
646bool NXCORE_EXPORTABLE ConfigDelete(const TCHAR *name)
647{
648 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
649
650 TCHAR query[1024];
651 _sntprintf(query, 1024, _T("DELETE FROM config WHERE var_name=%s"), (const TCHAR *)DBPrepareString(hdb, name));
652 bool success = DBQuery(hdb, query) ? true : false;
653
654 DBConnectionPoolReleaseConnection(hdb);
655
656 if (success)
657 {
658 RWLockWriteLock(s_configCacheLock, INFINITE);
659 s_configCache.remove(name);
660 RWLockUnlock(s_configCacheLock);
661 }
662
663 return success;
664}
665
69bb7f47
VK
666/**
667 * Read large string (clob) value from configuration table
668 */
5039dede
AK
669TCHAR NXCORE_EXPORTABLE *ConfigReadCLOB(const TCHAR *var, const TCHAR *defValue)
670{
b3eb058b 671 TCHAR *result = NULL;
5039dede 672
b3eb058b 673 if (_tcslen(var) <= 63)
5039dede 674 {
b3eb058b
VK
675 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
676 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
677 if (hStmt != NULL)
678 {
679 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
680 DB_RESULT hResult = DBSelectPrepared(hStmt);
681 if (hResult != NULL)
682 {
683 if (DBGetNumRows(hResult) > 0)
684 {
685 result = DBGetField(hResult, 0, 0, NULL, 0);
686 }
687 DBFreeResult(hResult);
688 }
689 DBFreeStatement(hStmt);
690 }
691 DBConnectionPoolReleaseConnection(hdb);
5039dede
AK
692 }
693
694 // Return default value in case of error
695 if ((result == NULL) && (defValue != NULL))
696 result = _tcsdup(defValue);
697
698 return result;
699}
700
69bb7f47
VK
701/**
702 * Write large string (clob) value to configuration table
703 */
35959841 704bool NXCORE_EXPORTABLE ConfigWriteCLOB(const TCHAR *var, const TCHAR *value, bool bCreate)
5039dede 705{
b3eb058b 706 if (_tcslen(var) > 63)
35959841 707 return false;
5039dede 708
b3eb058b 709 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
5039dede
AK
710
711 // Check for variable existence
b3eb058b
VK
712 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
713 if (hStmt == NULL)
714 {
715 DBConnectionPoolReleaseConnection(hdb);
716 return false;
717 }
718 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
719 DB_RESULT hResult = DBSelectPrepared(hStmt);
720 bool bVarExist = false;
5039dede
AK
721 if (hResult != NULL)
722 {
723 if (DBGetNumRows(hResult) > 0)
35959841 724 bVarExist = true;
5039dede
AK
725 DBFreeResult(hResult);
726 }
b3eb058b 727 DBFreeStatement(hStmt);
5039dede
AK
728
729 // Don't create non-existing variable if creation flag not set
b3eb058b
VK
730 if (!bCreate && !bVarExist)
731 {
732 DBConnectionPoolReleaseConnection(hdb);
733 return false;
734 }
735
736 // Create or update variable value
737 if (bVarExist)
5039dede 738 {
b3eb058b
VK
739 hStmt = DBPrepare(hdb, _T("UPDATE config_clob SET var_value=? WHERE var_name=?"));
740 if (hStmt == NULL)
741 {
742 DBConnectionPoolReleaseConnection(hdb);
743 return false;
744 }
745 DBBind(hStmt, 1, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
746 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
5039dede 747 }
b3eb058b
VK
748 else
749 {
750 hStmt = DBPrepare(hdb, _T("INSERT INTO config_clob (var_name,var_value) VALUES (?,?)"));
751 if (hStmt == NULL)
752 {
753 DBConnectionPoolReleaseConnection(hdb);
754 return false;
755 }
756 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
757 DBBind(hStmt, 2, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
758 }
759 bool success = DBExecute(hStmt) ? true : false;
760 DBFreeStatement(hStmt);
761 DBConnectionPoolReleaseConnection(hdb);
4d0c32f3 762 if (success)
35959841 763 OnConfigVariableChange(true, var, value);
5039dede
AK
764 return success;
765}