metadata table cached in memory
[public/netxms.git] / src / server / core / config.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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"
24 #include <nxconfig.h>
25
26 /**
27 * Externals
28 */
29 extern char g_szCodePage[];
30 extern TCHAR *g_moduleLoadList;
31 extern TCHAR *g_pdsLoadList;
32
33 /**
34 * database connection parameters
35 */
36 TCHAR g_szDbDriver[MAX_PATH] = _T("");
37 TCHAR g_szDbDrvParams[MAX_PATH] = _T("");
38 TCHAR g_szDbServer[MAX_PATH] = _T("127.0.0.1");
39 TCHAR g_szDbLogin[MAX_DB_LOGIN] = _T("netxms");
40 TCHAR g_szDbPassword[MAX_PASSWORD] = _T("");
41 TCHAR g_szDbName[MAX_DB_NAME] = _T("netxms_db");
42 TCHAR g_szDbSchema[MAX_DB_NAME] = _T("");
43
44 /**
45 * Debug level from config
46 */
47 static UINT32 s_debugLevel = (UINT32)NXCONFIG_UNINITIALIZED_VALUE;
48
49 /**
50 * Config file template
51 */
52 static NX_CFG_TEMPLATE m_cfgTemplate[] =
53 {
54 { _T("BackgroundLogWriter"), CT_BOOLEAN64, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_flags, NULL },
55 { _T("CodePage"), CT_MB_STRING, 0, 0, 256, 0, g_szCodePage, NULL },
56 { _T("CreateCrashDumps"), CT_BOOLEAN64, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_flags, NULL },
57 { _T("DailyLogFileSuffix"), CT_STRING, 0, 0, 64, 0, g_szDailyLogFileSuffix, NULL },
58 { _T("DataDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdDataDir, NULL },
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 },
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 },
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 },
65 { _T("DBSchema"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbSchema, NULL },
66 { _T("DBServer"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbServer, NULL },
67 { _T("DebugLevel"), CT_LONG, 0, 0, 0, 0, &s_debugLevel, &s_debugLevel },
68 { _T("DumpDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDumpDir, NULL },
69 { _T("FullCrashDumps"), CT_BOOLEAN64, 0, 0, AF_WRITE_FULL_DUMP, 0, &g_flags, NULL },
70 { _T("LibraryDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdLibDir, NULL },
71 { _T("ListenAddress"), CT_STRING, 0, 0, MAX_PATH, 0, g_szListenAddress, NULL },
72 { _T("LogFailedSQLQueries"), CT_BOOLEAN64, 0, 0, AF_LOG_SQL_ERRORS, 0, &g_flags, NULL },
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 },
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 },
79 { _T("ProcessAffinityMask"), CT_LONG, 0, 0, 0, 0, &g_processAffinityMask, NULL },
80 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL, NULL }
81 };
82
83 /**
84 * Loaded server config
85 */
86 Config g_serverConfig;
87
88 /**
89 * Load and parse configuration file
90 * Returns TRUE on success and FALSE on failure
91 */
92 bool NXCORE_EXPORTABLE LoadConfig(int *debugLevel)
93 {
94 bool bSuccess = false;
95
96 if (!_tcscmp(g_szConfigFile, _T("{search}")))
97 {
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
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 }
122 if (_taccess(PREFIX _T("/etc/netxmsd.conf"), 4) == 0)
123 {
124 _tcscpy(g_szConfigFile, PREFIX _T("/etc/netxmsd.conf"));
125 }
126 else if (_taccess(_T("/usr/etc/netxmsd.conf"), 4) == 0)
127 {
128 _tcscpy(g_szConfigFile, _T("/usr/etc/netxmsd.conf"));
129 }
130 else
131 {
132 _tcscpy(g_szConfigFile, _T("/etc/netxmsd.conf"));
133 }
134 stop_search:
135 ;
136 #endif
137 }
138
139 if (IsStandalone())
140 _tprintf(_T("Using configuration file \"%s\"\n"), g_szConfigFile);
141
142 if (g_serverConfig.loadConfig(g_szConfigFile, _T("server")) && g_serverConfig.parseTemplate(_T("server"), m_cfgTemplate))
143 {
144 if ((!_tcsicmp(g_szLogFile, _T("{EventLog}"))) ||
145 (!_tcsicmp(g_szLogFile, _T("{syslog}"))))
146 {
147 g_flags |= AF_USE_SYSLOG;
148 }
149 else
150 {
151 g_flags &= ~AF_USE_SYSLOG;
152 }
153 bSuccess = true;
154 }
155
156 if (*debugLevel == NXCONFIG_UNINITIALIZED_VALUE)
157 *debugLevel = (int)s_debugLevel;
158
159 // Decrypt password
160 DecryptPassword(g_szDbLogin, g_szDbPassword, g_szDbPassword, MAX_PASSWORD);
161 return bSuccess;
162 }
163
164 /**
165 * Metadata cache
166 */
167 static StringMap s_metadataCache;
168 static RWLOCK s_metadataCacheLock = RWLockCreate();
169
170 /**
171 * Pre-load metadata
172 */
173 void 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
192 /**
193 * Read string value from metadata table
194 */
195 bool NXCORE_EXPORTABLE MetaDataReadStr(const TCHAR *name, TCHAR *buffer, int bufSize, const TCHAR *defaultValue)
196 {
197 bool bSuccess = false;
198
199 nx_strncpy(buffer, defaultValue, bufSize);
200 if (_tcslen(name) > 127)
201 return false;
202
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 }
236 return bSuccess;
237 }
238
239 /**
240 * Read integer value from metadata table
241 */
242 INT32 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
257 /**
258 * Write string value to metadata table
259 */
260 bool NXCORE_EXPORTABLE MetaDataWriteStr(const TCHAR *varName, const TCHAR *value)
261 {
262 if (_tcslen(varName) > 63)
263 return false;
264
265 RWLockWriteLock(s_metadataCacheLock, INFINITE);
266 s_metadataCache.set(varName, value);
267 RWLockUnlock(s_metadataCacheLock);
268
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
318 /**
319 * Config cache
320 */
321 static StringMap s_configCache;
322 static RWLOCK s_configCacheLock = RWLockCreate();
323
324 /**
325 * Callback for configuration variables change
326 */
327 static void OnConfigVariableChange(bool isCLOB, const TCHAR *name, const TCHAR *value)
328 {
329 RWLockWriteLock(s_configCacheLock, INFINITE);
330 s_configCache.set(name, value);
331 RWLockUnlock(s_configCacheLock);
332
333 // Restart syslog parser if configuration was changed
334 if (isCLOB && !_tcscmp(name, _T("SyslogParser")))
335 {
336 ReinitializeSyslogParser();
337 }
338 else if (!_tcsncmp(name, _T("CAS"), 3))
339 {
340 CASReadSettings();
341 }
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 }
350 else if (!_tcscmp(name, _T("StrictAlarmStatusFlow")))
351 {
352 NotifyClientSessions(NX_NOTIFY_ALARM_STATUS_FLOW_CHANGED, _tcstol(value, NULL, 0));
353 }
354 else if (!_tcsncmp(name, _T("Syslog"), 6))
355 {
356 OnSyslogConfigurationChange(name, value);
357 }
358 }
359
360 /**
361 * Read string value from configuration table
362 */
363 bool NXCORE_EXPORTABLE ConfigReadStrEx(DB_HANDLE dbHandle, const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
364 {
365 nx_strncpy(szBuffer, szDefault, iBufSize);
366 if (_tcslen(szVar) > 127)
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 }
378
379 bool bSuccess = false;
380 DB_HANDLE hdb = (dbHandle == NULL) ? DBConnectionPoolAcquireConnection() : dbHandle;
381 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
382 if (hStmt != NULL)
383 {
384 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
385 DB_RESULT hResult = DBSelectPrepared(hStmt);
386 if (hResult != NULL)
387 {
388 if (DBGetNumRows(hResult) > 0)
389 {
390 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
391 DbgPrintf(8, _T("ConfigReadStr: name=%s value=\"%s\""), szVar, szBuffer);
392 bSuccess = true;
393 }
394 DBFreeResult(hResult);
395 }
396 DBFreeStatement(hStmt);
397 }
398 if (dbHandle == NULL)
399 DBConnectionPoolReleaseConnection(hdb);
400
401 if (bSuccess)
402 {
403 RWLockWriteLock(s_configCacheLock, INFINITE);
404 s_configCache.set(szVar, szBuffer);
405 RWLockUnlock(s_configCacheLock);
406 }
407
408 return bSuccess;
409 }
410
411 /**
412 * Read string value from configuration table
413 */
414 bool NXCORE_EXPORTABLE ConfigReadStr(const TCHAR *var, TCHAR *buffer, int bufferSize, const TCHAR *defaultValue)
415 {
416 return ConfigReadStrEx(NULL, var, buffer, bufferSize, defaultValue);
417 }
418
419 /**
420 * Read multibyte string from configuration table
421 */
422 #ifdef UNICODE
423
424 bool NXCORE_EXPORTABLE ConfigReadStrA(const WCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
425 {
426 WCHAR *wcBuffer = (WCHAR *)malloc(iBufSize * sizeof(WCHAR));
427 bool rc = ConfigReadStr(szVar, wcBuffer, iBufSize, _T(""));
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
443 /**
444 * Read string value from configuration table as UTF8 string
445 */
446 bool 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
455 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
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 }
472 DBConnectionPoolReleaseConnection(hdb);
473
474 return bSuccess;
475 }
476
477 /**
478 * Read integer value from configuration table
479 */
480 int NXCORE_EXPORTABLE ConfigReadInt(const TCHAR *szVar, int iDefault)
481 {
482 return ConfigReadIntEx(NULL, szVar, iDefault);
483 }
484
485 /**
486 * Read integer value from configuration table
487 */
488 int NXCORE_EXPORTABLE ConfigReadIntEx(DB_HANDLE hdb, const TCHAR *szVar, int iDefault)
489 {
490 TCHAR szBuffer[64];
491
492 if (ConfigReadStrEx(hdb, szVar, szBuffer, 64, _T("")))
493 return _tcstol(szBuffer, NULL, 0);
494 else
495 return iDefault;
496 }
497
498 /**
499 * Read unsigned long value from configuration table
500 */
501 UINT32 NXCORE_EXPORTABLE ConfigReadULong(const TCHAR *szVar, UINT32 dwDefault)
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
511 /**
512 * Read byte array (in hex form) from configuration table into integer array
513 */
514 bool NXCORE_EXPORTABLE ConfigReadByteArray(const TCHAR *pszVar, int *pnArray, int nSize, int nDefault)
515 {
516 TCHAR szBuffer[256];
517 char pbBytes[128];
518 bool bResult;
519 int i, nLen;
520
521 if (ConfigReadStr(pszVar, szBuffer, 256, _T("")))
522 {
523 StrToBin(szBuffer, (BYTE *)pbBytes, 128);
524 nLen = (int)_tcslen(szBuffer) / 2;
525 for(i = 0; (i < nSize) && (i < nLen); i++)
526 pnArray[i] = pbBytes[i];
527 for(; i < nSize; i++)
528 pnArray[i] = nDefault;
529 bResult = true;
530 }
531 else
532 {
533 for(i = 0; i < nSize; i++)
534 pnArray[i] = nDefault;
535 bResult = false;
536 }
537 return bResult;
538 }
539
540 /**
541 * Write string value to configuration table
542 */
543 bool NXCORE_EXPORTABLE ConfigWriteStr(const TCHAR *varName, const TCHAR *value, bool bCreate, bool isVisible, bool needRestart)
544 {
545 if (_tcslen(varName) > 63)
546 return false;
547
548 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
549
550 // Check for variable existence
551 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
552 if (hStmt == NULL)
553 {
554 DBConnectionPoolReleaseConnection(hdb);
555 return false;
556 }
557 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
558 DB_RESULT hResult = DBSelectPrepared(hStmt);
559 bool bVarExist = false;
560 if (hResult != NULL)
561 {
562 if (DBGetNumRows(hResult) > 0)
563 bVarExist = true;
564 DBFreeResult(hResult);
565 }
566 DBFreeStatement(hStmt);
567
568 // Don't create non-existing variable if creation flag not set
569 if (!bCreate && !bVarExist)
570 {
571 DBConnectionPoolReleaseConnection(hdb);
572 return false;
573 }
574
575 // Create or update variable value
576 if (bVarExist)
577 {
578 hStmt = DBPrepare(hdb, _T("UPDATE config SET var_value=? WHERE var_name=?"));
579 if (hStmt == NULL)
580 {
581 DBConnectionPoolReleaseConnection(hdb);
582 return false;
583 }
584 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
585 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
586 }
587 else
588 {
589 hStmt = DBPrepare(hdb, _T("INSERT INTO config (var_name,var_value,is_visible,need_server_restart) VALUES (?,?,?,?)"));
590 if (hStmt == NULL)
591 {
592 DBConnectionPoolReleaseConnection(hdb);
593 return false;
594 }
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 }
600 bool success = DBExecute(hStmt);
601 DBFreeStatement(hStmt);
602 DBConnectionPoolReleaseConnection(hdb);
603 if (success)
604 OnConfigVariableChange(false, varName, value);
605 return success;
606 }
607
608 /**
609 * Write integer value to configuration table
610 */
611 bool NXCORE_EXPORTABLE ConfigWriteInt(const TCHAR *szVar, int iValue, bool bCreate, bool isVisible, bool needRestart)
612 {
613 TCHAR szBuffer[64];
614
615 _sntprintf(szBuffer, 64, _T("%d"), iValue);
616 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
617 }
618
619 /**
620 * Write unsigned long value to configuration table
621 */
622 bool NXCORE_EXPORTABLE ConfigWriteULong(const TCHAR *szVar, UINT32 dwValue, bool bCreate, bool isVisible, bool needRestart)
623 {
624 TCHAR szBuffer[64];
625
626 _sntprintf(szBuffer, 64, _T("%u"), dwValue);
627 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
628 }
629
630 /**
631 * Write integer array to configuration table
632 */
633 bool NXCORE_EXPORTABLE ConfigWriteByteArray(const TCHAR *pszVar, int *pnArray, int nSize, bool bCreate, bool isVisible, bool needRestart)
634 {
635 TCHAR szBuffer[256];
636 int i, j;
637
638 for(i = 0, j = 0; (i < nSize) && (i < 127); i++, j += 2)
639 _sntprintf(&szBuffer[j], 256 - j, _T("%02X"), (char)((pnArray[i] > 127) ? 127 : ((pnArray[i] < -127) ? -127 : pnArray[i])));
640 return ConfigWriteStr(pszVar, szBuffer, bCreate, isVisible, needRestart);
641 }
642
643 /**
644 * Delete configuratrion variable
645 */
646 bool 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
666 /**
667 * Read large string (clob) value from configuration table
668 */
669 TCHAR NXCORE_EXPORTABLE *ConfigReadCLOB(const TCHAR *var, const TCHAR *defValue)
670 {
671 TCHAR *result = NULL;
672
673 if (_tcslen(var) <= 63)
674 {
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);
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
701 /**
702 * Write large string (clob) value to configuration table
703 */
704 bool NXCORE_EXPORTABLE ConfigWriteCLOB(const TCHAR *var, const TCHAR *value, bool bCreate)
705 {
706 if (_tcslen(var) > 63)
707 return false;
708
709 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
710
711 // Check for variable existence
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;
721 if (hResult != NULL)
722 {
723 if (DBGetNumRows(hResult) > 0)
724 bVarExist = true;
725 DBFreeResult(hResult);
726 }
727 DBFreeStatement(hStmt);
728
729 // Don't create non-existing variable if creation flag not set
730 if (!bCreate && !bVarExist)
731 {
732 DBConnectionPoolReleaseConnection(hdb);
733 return false;
734 }
735
736 // Create or update variable value
737 if (bVarExist)
738 {
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);
747 }
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);
762 if (success)
763 OnConfigVariableChange(true, var, value);
764 return success;
765 }