9016ce420901766195eeb1b31372d9f6fd7155f8
[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_logHistorySize, NULL },
75 { _T("LogRotationMode"), CT_LONG, 0, 0, 0, 0, &g_logRotationMode, NULL },
76 { _T("MaxLogSize"), CT_SIZE_BYTES, 0, 0, 0, 0, &g_maxLogSize, 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 MetaDataReadInt32(const TCHAR *var, INT32 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 * Write integer value to metadata table
320 */
321 bool NXCORE_EXPORTABLE MetaDataWriteInt32(const TCHAR *name, INT32 value)
322 {
323 TCHAR buffer[32];
324 _sntprintf(buffer, 32, _T("%d"), value);
325 return MetaDataWriteStr(name, buffer);
326 }
327
328 /**
329 * Config cache
330 */
331 static StringMap s_configCache;
332 static RWLOCK s_configCacheLock = RWLockCreate();
333
334 /**
335 * Callback for configuration variables change
336 */
337 static void OnConfigVariableChange(bool isCLOB, const TCHAR *name, const TCHAR *value)
338 {
339 RWLockWriteLock(s_configCacheLock, INFINITE);
340 s_configCache.set(name, value);
341 RWLockUnlock(s_configCacheLock);
342
343 // Restart syslog parser if configuration was changed
344 if (isCLOB && !_tcscmp(name, _T("SyslogParser")))
345 {
346 ReinitializeSyslogParser();
347 }
348 else if (!_tcsncmp(name, _T("CAS"), 3))
349 {
350 CASReadSettings();
351 }
352 else if (!_tcscmp(name, _T("DefaultDCIPollingInterval")))
353 {
354 DCObject::m_defaultPollingInterval = _tcstol(value, NULL, 0);
355 }
356 else if (!_tcscmp(name, _T("DefaultDCIRetentionTime")))
357 {
358 DCObject::m_defaultRetentionTime = _tcstol(value, NULL, 0);
359 }
360 else if (!_tcscmp(name, _T("StrictAlarmStatusFlow")))
361 {
362 NotifyClientSessions(NX_NOTIFY_ALARM_STATUS_FLOW_CHANGED, _tcstol(value, NULL, 0));
363 }
364 else if (!_tcsncmp(name, _T("Syslog"), 6))
365 {
366 OnSyslogConfigurationChange(name, value);
367 }
368 }
369
370 /**
371 * Read string value from configuration table
372 */
373 bool NXCORE_EXPORTABLE ConfigReadStrEx(DB_HANDLE dbHandle, const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
374 {
375 nx_strncpy(szBuffer, szDefault, iBufSize);
376 if (_tcslen(szVar) > 127)
377 return false;
378
379 RWLockReadLock(s_configCacheLock, INFINITE);
380 const TCHAR *value = s_configCache.get(szVar);
381 RWLockUnlock(s_configCacheLock);
382 if (value != NULL)
383 {
384 nx_strncpy(szBuffer, value, iBufSize);
385 DbgPrintf(8, _T("ConfigReadStr: (cached) name=%s value=\"%s\""), szVar, szBuffer);
386 return true;
387 }
388
389 bool bSuccess = false;
390 DB_HANDLE hdb = (dbHandle == NULL) ? DBConnectionPoolAcquireConnection() : dbHandle;
391 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
392 if (hStmt != NULL)
393 {
394 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
395 DB_RESULT hResult = DBSelectPrepared(hStmt);
396 if (hResult != NULL)
397 {
398 if (DBGetNumRows(hResult) > 0)
399 {
400 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
401 DbgPrintf(8, _T("ConfigReadStr: name=%s value=\"%s\""), szVar, szBuffer);
402 bSuccess = true;
403 }
404 DBFreeResult(hResult);
405 }
406 DBFreeStatement(hStmt);
407 }
408 if (dbHandle == NULL)
409 DBConnectionPoolReleaseConnection(hdb);
410
411 if (bSuccess)
412 {
413 RWLockWriteLock(s_configCacheLock, INFINITE);
414 s_configCache.set(szVar, szBuffer);
415 RWLockUnlock(s_configCacheLock);
416 }
417
418 return bSuccess;
419 }
420
421 /**
422 * Read string value from configuration table
423 */
424 bool NXCORE_EXPORTABLE ConfigReadStr(const TCHAR *var, TCHAR *buffer, int bufferSize, const TCHAR *defaultValue)
425 {
426 return ConfigReadStrEx(NULL, var, buffer, bufferSize, defaultValue);
427 }
428
429 /**
430 * Read multibyte string from configuration table
431 */
432 #ifdef UNICODE
433
434 bool NXCORE_EXPORTABLE ConfigReadStrA(const WCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
435 {
436 WCHAR *wcBuffer = (WCHAR *)malloc(iBufSize * sizeof(WCHAR));
437 bool rc = ConfigReadStr(szVar, wcBuffer, iBufSize, _T(""));
438 if (rc)
439 {
440 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, wcBuffer, -1, szBuffer, iBufSize, NULL, NULL);
441 }
442 else
443 {
444 strncpy(szBuffer, szDefault, iBufSize);
445 }
446 szBuffer[iBufSize - 1] = 0;
447 free(wcBuffer);
448 return rc;
449 }
450
451 #endif
452
453 /**
454 * Read string value from configuration table as UTF8 string
455 */
456 bool NXCORE_EXPORTABLE ConfigReadStrUTF8(const TCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
457 {
458 DB_RESULT hResult;
459 bool bSuccess = false;
460
461 strncpy(szBuffer, szDefault, iBufSize);
462 if (_tcslen(szVar) > 127)
463 return false;
464
465 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
466 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
467 if (hStmt != NULL)
468 {
469 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
470 hResult = DBSelectPrepared(hStmt);
471 if (hResult != NULL)
472 {
473 if (DBGetNumRows(hResult) > 0)
474 {
475 DBGetFieldUTF8(hResult, 0, 0, szBuffer, iBufSize);
476 bSuccess = true;
477 }
478 DBFreeResult(hResult);
479 }
480 DBFreeStatement(hStmt);
481 }
482 DBConnectionPoolReleaseConnection(hdb);
483
484 return bSuccess;
485 }
486
487 /**
488 * Read integer value from configuration table
489 */
490 int NXCORE_EXPORTABLE ConfigReadInt(const TCHAR *szVar, int iDefault)
491 {
492 return ConfigReadIntEx(NULL, szVar, iDefault);
493 }
494
495 /**
496 * Read integer value from configuration table
497 */
498 int NXCORE_EXPORTABLE ConfigReadIntEx(DB_HANDLE hdb, const TCHAR *szVar, int iDefault)
499 {
500 TCHAR szBuffer[64];
501
502 if (ConfigReadStrEx(hdb, szVar, szBuffer, 64, _T("")))
503 return _tcstol(szBuffer, NULL, 0);
504 else
505 return iDefault;
506 }
507
508 /**
509 * Read unsigned long value from configuration table
510 */
511 UINT32 NXCORE_EXPORTABLE ConfigReadULong(const TCHAR *szVar, UINT32 dwDefault)
512 {
513 TCHAR szBuffer[64];
514
515 if (ConfigReadStr(szVar, szBuffer, 64, _T("")))
516 return _tcstoul(szBuffer, NULL, 0);
517 else
518 return dwDefault;
519 }
520
521 /**
522 * Read byte array (in hex form) from configuration table into integer array
523 */
524 bool NXCORE_EXPORTABLE ConfigReadByteArray(const TCHAR *pszVar, int *pnArray, int nSize, int nDefault)
525 {
526 TCHAR szBuffer[256];
527 char pbBytes[128];
528 bool bResult;
529 int i, nLen;
530
531 if (ConfigReadStr(pszVar, szBuffer, 256, _T("")))
532 {
533 StrToBin(szBuffer, (BYTE *)pbBytes, 128);
534 nLen = (int)_tcslen(szBuffer) / 2;
535 for(i = 0; (i < nSize) && (i < nLen); i++)
536 pnArray[i] = pbBytes[i];
537 for(; i < nSize; i++)
538 pnArray[i] = nDefault;
539 bResult = true;
540 }
541 else
542 {
543 for(i = 0; i < nSize; i++)
544 pnArray[i] = nDefault;
545 bResult = false;
546 }
547 return bResult;
548 }
549
550 /**
551 * Write string value to configuration table
552 */
553 bool NXCORE_EXPORTABLE ConfigWriteStr(const TCHAR *varName, const TCHAR *value, bool bCreate, bool isVisible, bool needRestart)
554 {
555 if (_tcslen(varName) > 63)
556 return false;
557
558 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
559
560 // Check for variable existence
561 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
562 if (hStmt == NULL)
563 {
564 DBConnectionPoolReleaseConnection(hdb);
565 return false;
566 }
567 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
568 DB_RESULT hResult = DBSelectPrepared(hStmt);
569 bool bVarExist = false;
570 if (hResult != NULL)
571 {
572 if (DBGetNumRows(hResult) > 0)
573 bVarExist = true;
574 DBFreeResult(hResult);
575 }
576 DBFreeStatement(hStmt);
577
578 // Don't create non-existing variable if creation flag not set
579 if (!bCreate && !bVarExist)
580 {
581 DBConnectionPoolReleaseConnection(hdb);
582 return false;
583 }
584
585 // Create or update variable value
586 if (bVarExist)
587 {
588 hStmt = DBPrepare(hdb, _T("UPDATE config SET var_value=? WHERE var_name=?"));
589 if (hStmt == NULL)
590 {
591 DBConnectionPoolReleaseConnection(hdb);
592 return false;
593 }
594 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
595 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
596 }
597 else
598 {
599 hStmt = DBPrepare(hdb, _T("INSERT INTO config (var_name,var_value,is_visible,need_server_restart) VALUES (?,?,?,?)"));
600 if (hStmt == NULL)
601 {
602 DBConnectionPoolReleaseConnection(hdb);
603 return false;
604 }
605 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
606 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
607 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)(isVisible ? 1 : 0));
608 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)(needRestart ? 1 : 0));
609 }
610 bool success = DBExecute(hStmt);
611 DBFreeStatement(hStmt);
612 DBConnectionPoolReleaseConnection(hdb);
613 if (success)
614 OnConfigVariableChange(false, varName, value);
615 return success;
616 }
617
618 /**
619 * Write integer value to configuration table
620 */
621 bool NXCORE_EXPORTABLE ConfigWriteInt(const TCHAR *szVar, int iValue, bool bCreate, bool isVisible, bool needRestart)
622 {
623 TCHAR szBuffer[64];
624
625 _sntprintf(szBuffer, 64, _T("%d"), iValue);
626 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
627 }
628
629 /**
630 * Write unsigned long value to configuration table
631 */
632 bool NXCORE_EXPORTABLE ConfigWriteULong(const TCHAR *szVar, UINT32 dwValue, bool bCreate, bool isVisible, bool needRestart)
633 {
634 TCHAR szBuffer[64];
635
636 _sntprintf(szBuffer, 64, _T("%u"), dwValue);
637 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
638 }
639
640 /**
641 * Write integer array to configuration table
642 */
643 bool NXCORE_EXPORTABLE ConfigWriteByteArray(const TCHAR *pszVar, int *pnArray, int nSize, bool bCreate, bool isVisible, bool needRestart)
644 {
645 TCHAR szBuffer[256];
646 int i, j;
647
648 for(i = 0, j = 0; (i < nSize) && (i < 127); i++, j += 2)
649 _sntprintf(&szBuffer[j], 256 - j, _T("%02X"), (char)((pnArray[i] > 127) ? 127 : ((pnArray[i] < -127) ? -127 : pnArray[i])));
650 return ConfigWriteStr(pszVar, szBuffer, bCreate, isVisible, needRestart);
651 }
652
653 /**
654 * Delete configuratrion variable
655 */
656 bool NXCORE_EXPORTABLE ConfigDelete(const TCHAR *name)
657 {
658 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
659
660 TCHAR query[1024];
661 _sntprintf(query, 1024, _T("DELETE FROM config WHERE var_name=%s"), (const TCHAR *)DBPrepareString(hdb, name));
662 bool success = DBQuery(hdb, query) ? true : false;
663
664 DBConnectionPoolReleaseConnection(hdb);
665
666 if (success)
667 {
668 RWLockWriteLock(s_configCacheLock, INFINITE);
669 s_configCache.remove(name);
670 RWLockUnlock(s_configCacheLock);
671 }
672
673 return success;
674 }
675
676 /**
677 * Read large string (clob) value from configuration table
678 */
679 TCHAR NXCORE_EXPORTABLE *ConfigReadCLOB(const TCHAR *var, const TCHAR *defValue)
680 {
681 TCHAR *result = NULL;
682
683 if (_tcslen(var) <= 63)
684 {
685 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
686 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
687 if (hStmt != NULL)
688 {
689 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
690 DB_RESULT hResult = DBSelectPrepared(hStmt);
691 if (hResult != NULL)
692 {
693 if (DBGetNumRows(hResult) > 0)
694 {
695 result = DBGetField(hResult, 0, 0, NULL, 0);
696 }
697 DBFreeResult(hResult);
698 }
699 DBFreeStatement(hStmt);
700 }
701 DBConnectionPoolReleaseConnection(hdb);
702 }
703
704 // Return default value in case of error
705 if ((result == NULL) && (defValue != NULL))
706 result = _tcsdup(defValue);
707
708 return result;
709 }
710
711 /**
712 * Write large string (clob) value to configuration table
713 */
714 bool NXCORE_EXPORTABLE ConfigWriteCLOB(const TCHAR *var, const TCHAR *value, bool bCreate)
715 {
716 if (_tcslen(var) > 63)
717 return false;
718
719 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
720
721 // Check for variable existence
722 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
723 if (hStmt == NULL)
724 {
725 DBConnectionPoolReleaseConnection(hdb);
726 return false;
727 }
728 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
729 DB_RESULT hResult = DBSelectPrepared(hStmt);
730 bool bVarExist = false;
731 if (hResult != NULL)
732 {
733 if (DBGetNumRows(hResult) > 0)
734 bVarExist = true;
735 DBFreeResult(hResult);
736 }
737 DBFreeStatement(hStmt);
738
739 // Don't create non-existing variable if creation flag not set
740 if (!bCreate && !bVarExist)
741 {
742 DBConnectionPoolReleaseConnection(hdb);
743 return false;
744 }
745
746 // Create or update variable value
747 if (bVarExist)
748 {
749 hStmt = DBPrepare(hdb, _T("UPDATE config_clob SET var_value=? WHERE var_name=?"));
750 if (hStmt == NULL)
751 {
752 DBConnectionPoolReleaseConnection(hdb);
753 return false;
754 }
755 DBBind(hStmt, 1, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
756 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
757 }
758 else
759 {
760 hStmt = DBPrepare(hdb, _T("INSERT INTO config_clob (var_name,var_value) VALUES (?,?)"));
761 if (hStmt == NULL)
762 {
763 DBConnectionPoolReleaseConnection(hdb);
764 return false;
765 }
766 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
767 DBBind(hStmt, 2, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
768 }
769 bool success = DBExecute(hStmt) ? true : false;
770 DBFreeStatement(hStmt);
771 DBConnectionPoolReleaseConnection(hdb);
772 if (success)
773 OnConfigVariableChange(true, var, value);
774 return success;
775 }