93f0e1db756be40482b4704407c7ffd3876ace5e
[public/netxms.git] / src / server / core / config.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2014 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 * Config file template
46 */
47 static NX_CFG_TEMPLATE m_cfgTemplate[] =
48 {
49 { _T("BackgroundLogWriter"), CT_BOOLEAN64, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_flags, NULL },
50 { _T("CodePage"), CT_MB_STRING, 0, 0, 256, 0, g_szCodePage, NULL },
51 { _T("CreateCrashDumps"), CT_BOOLEAN64, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_flags, NULL },
52 { _T("DailyLogFileSuffix"), CT_STRING, 0, 0, 64, 0, g_szDailyLogFileSuffix, NULL },
53 { _T("DataDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdDataDir, NULL },
54 { _T("DBDriver"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDriver, NULL },
55 { _T("DBDrvParams"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDrvParams, NULL },
56 { _T("DBLogin"), CT_STRING, 0, 0, MAX_DB_LOGIN, 0, g_szDbLogin, NULL },
57 { _T("DBName"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbName, NULL },
58 { _T("DBPassword"), CT_STRING, 0, 0, MAX_PASSWORD, 0, g_szDbPassword, NULL },
59 { _T("DBEncryptedPassword"), CT_STRING, 0, 0, MAX_PASSWORD, 0, g_szDbPassword, NULL },
60 { _T("DBSchema"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbSchema, NULL },
61 { _T("DBServer"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbServer, NULL },
62 { _T("DebugLevel"), CT_LONG, 0, 0, 0, 0, &g_debugLevel, &g_debugLevel },
63 { _T("DumpDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDumpDir, NULL },
64 { _T("FullCrashDumps"), CT_BOOLEAN64, 0, 0, AF_WRITE_FULL_DUMP, 0, &g_flags, NULL },
65 { _T("LibraryDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdLibDir, NULL },
66 { _T("ListenAddress"), CT_STRING, 0, 0, MAX_PATH, 0, g_szListenAddress, NULL },
67 { _T("LogFailedSQLQueries"), CT_BOOLEAN64, 0, 0, AF_LOG_SQL_ERRORS, 0, &g_flags, NULL },
68 { _T("LogFile"), CT_STRING, 0, 0, MAX_PATH, 0, g_szLogFile, NULL },
69 { _T("LogHistorySize"), CT_LONG, 0, 0, 0, 0, &g_dwLogHistorySize, NULL },
70 { _T("LogRotationMode"), CT_LONG, 0, 0, 0, 0, &g_dwLogRotationMode, NULL },
71 { _T("MaxLogSize"), CT_LONG, 0, 0, 0, 0, &g_dwMaxLogSize, NULL },
72 { _T("Module"), CT_STRING_LIST, '\n', 0, 0, 0, &g_moduleLoadList, NULL },
73 { _T("PerfDataStorageDriver"), CT_STRING_LIST, '\n', 0, 0, 0, &g_pdsLoadList, NULL },
74 { _T("ProcessAffinityMask"), CT_LONG, 0, 0, 0, 0, &g_processAffinityMask, NULL },
75 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL, NULL }
76 };
77
78 /**
79 * Load and parse configuration file
80 * Returns TRUE on success and FALSE on failure
81 */
82 bool NXCORE_EXPORTABLE LoadConfig()
83 {
84 bool bSuccess = false;
85 Config *config;
86
87 if (!_tcscmp(g_szConfigFile, _T("{search}")))
88 {
89 #ifdef _WIN32
90 TCHAR path[MAX_PATH];
91 GetNetXMSDirectory(nxDirEtc, path);
92 _tcscat(path, _T("\\netxmsd.conf"));
93 if (_taccess(path, 4) == 0)
94 {
95 _tcscpy(g_szConfigFile, path);
96 }
97 else
98 {
99 _tcscpy(g_szConfigFile, _T("C:\\netxmsd.conf"));
100 }
101 #else
102 const TCHAR *homeDir = _tgetenv(_T("NETXMS_HOME"));
103 if ((homeDir != NULL) && (*homeDir != 0))
104 {
105 TCHAR config[MAX_PATH];
106 _sntprintf(config, MAX_PATH, _T("%s/etc/netxmsd.conf"), homeDir);
107 if (_taccess(config, 4) == 0)
108 {
109 _tcscpy(g_szConfigFile, config);
110 goto stop_search;
111 }
112 }
113 if (_taccess(PREFIX _T("/etc/netxmsd.conf"), 4) == 0)
114 {
115 _tcscpy(g_szConfigFile, PREFIX _T("/etc/netxmsd.conf"));
116 }
117 else if (_taccess(_T("/usr/etc/netxmsd.conf"), 4) == 0)
118 {
119 _tcscpy(g_szConfigFile, _T("/usr/etc/netxmsd.conf"));
120 }
121 else
122 {
123 _tcscpy(g_szConfigFile, _T("/etc/netxmsd.conf"));
124 }
125 stop_search:
126 ;
127 #endif
128 }
129
130 if (IsStandalone())
131 _tprintf(_T("Using configuration file \"%s\"\n"), g_szConfigFile);
132
133 config = new Config();
134 if (config->loadConfig(g_szConfigFile, _T("server")) && config->parseTemplate(_T("server"), m_cfgTemplate))
135 {
136 if ((!_tcsicmp(g_szLogFile, _T("{EventLog}"))) ||
137 (!_tcsicmp(g_szLogFile, _T("{syslog}"))))
138 {
139 g_flags |= AF_USE_SYSLOG;
140 }
141 else
142 {
143 g_flags &= ~AF_USE_SYSLOG;
144 }
145 bSuccess = true;
146 }
147 delete config;
148
149 // Decrypt password
150 DecryptPassword(g_szDbLogin, g_szDbPassword, g_szDbPassword, MAX_PASSWORD);
151
152 return bSuccess;
153 }
154
155 /**
156 * Read string value from metadata table
157 */
158 bool NXCORE_EXPORTABLE MetaDataReadStr(const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
159 {
160 DB_RESULT hResult;
161 bool bSuccess = false;
162
163 nx_strncpy(szBuffer, szDefault, iBufSize);
164 if (_tcslen(szVar) > 127)
165 return false;
166
167 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
168 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM metadata WHERE var_name=?"));
169 if (hStmt != NULL)
170 {
171 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
172 hResult = DBSelectPrepared(hStmt);
173 if (hResult != NULL)
174 {
175 if (DBGetNumRows(hResult) > 0)
176 {
177 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
178 bSuccess = true;
179 }
180 DBFreeResult(hResult);
181 }
182 DBFreeStatement(hStmt);
183 }
184 DBConnectionPoolReleaseConnection(hdb);
185 return bSuccess;
186 }
187
188 /**
189 * Read integer value from metadata table
190 */
191 INT32 NXCORE_EXPORTABLE MetaDataReadInt(const TCHAR *var, UINT32 defaultValue)
192 {
193 TCHAR buffer[256];
194 if (MetaDataReadStr(var, buffer, 256, _T("")))
195 {
196 TCHAR *eptr;
197 INT32 value = _tcstol(buffer, &eptr, 0);
198 return (*eptr == 0) ? value : defaultValue;
199 }
200 else
201 {
202 return defaultValue;
203 }
204 }
205
206 /**
207 * Write string value to metadata table
208 */
209 bool NXCORE_EXPORTABLE MetaDataWriteStr(const TCHAR *varName, const TCHAR *value)
210 {
211 if (_tcslen(varName) > 63)
212 return false;
213
214 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
215
216 // Check for variable existence
217 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM metadata WHERE var_name=?"));
218 if (hStmt == NULL)
219 {
220 DBConnectionPoolReleaseConnection(hdb);
221 return false;
222 }
223 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
224 DB_RESULT hResult = DBSelectPrepared(hStmt);
225 bool bVarExist = false;
226 if (hResult != NULL)
227 {
228 if (DBGetNumRows(hResult) > 0)
229 bVarExist = true;
230 DBFreeResult(hResult);
231 }
232 DBFreeStatement(hStmt);
233
234 // Create or update variable value
235 if (bVarExist)
236 {
237 hStmt = DBPrepare(hdb, _T("UPDATE metadata SET var_value=? WHERE var_name=?"));
238 if (hStmt == NULL)
239 {
240 DBConnectionPoolReleaseConnection(hdb);
241 return false;
242 }
243 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
244 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
245 }
246 else
247 {
248 hStmt = DBPrepare(hdb, _T("INSERT INTO metadata (var_name,var_value) VALUES (?,?)"));
249 if (hStmt == NULL)
250 {
251 DBConnectionPoolReleaseConnection(hdb);
252 return false;
253 }
254 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
255 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
256 }
257 bool success = DBExecute(hStmt);
258 DBFreeStatement(hStmt);
259 DBConnectionPoolReleaseConnection(hdb);
260 return success;
261 }
262
263 /**
264 * Config cache
265 */
266 static StringMap s_configCache;
267 static RWLOCK s_configCacheLock = RWLockCreate();
268
269 /**
270 * Callback for configuration variables change
271 */
272 static void OnConfigVariableChange(bool isCLOB, const TCHAR *name, const TCHAR *value)
273 {
274 RWLockWriteLock(s_configCacheLock, INFINITE);
275 s_configCache.set(name, value);
276 RWLockUnlock(s_configCacheLock);
277
278 // Restart syslog parser if configuration was changed
279 if (isCLOB && !_tcscmp(name, _T("SyslogParser")))
280 {
281 ReinitializeSyslogParser();
282 }
283 else if (!_tcsncmp(name, _T("CAS"), 3))
284 {
285 CASReadSettings();
286 }
287 else if (!_tcscmp(name, _T("DefaultDCIPollingInterval")))
288 {
289 DCObject::m_defaultPollingInterval = _tcstol(value, NULL, 0);
290 }
291 else if (!_tcscmp(name, _T("DefaultDCIRetentionTime")))
292 {
293 DCObject::m_defaultRetentionTime = _tcstol(value, NULL, 0);
294 }
295 else if (!_tcscmp(name, _T("StrictAlarmStatusFlow")))
296 {
297 NotifyClientSessions(NX_NOTIFY_ALARM_STATUS_FLOW_CHANGED, _tcstol(value, NULL, 0));
298 }
299 }
300
301 /**
302 * Read string value from configuration table
303 */
304 bool NXCORE_EXPORTABLE ConfigReadStrEx(DB_HANDLE dbHandle, const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
305 {
306 nx_strncpy(szBuffer, szDefault, iBufSize);
307 if (_tcslen(szVar) > 127)
308 return false;
309
310 RWLockReadLock(s_configCacheLock, INFINITE);
311 const TCHAR *value = s_configCache.get(szVar);
312 RWLockUnlock(s_configCacheLock);
313 if (value != NULL)
314 {
315 nx_strncpy(szBuffer, value, iBufSize);
316 DbgPrintf(8, _T("ConfigReadStr: (cached) name=%s value=\"%s\""), szVar, szBuffer);
317 return true;
318 }
319
320 bool bSuccess = false;
321 DB_HANDLE hdb = (dbHandle == NULL) ? DBConnectionPoolAcquireConnection() : dbHandle;
322 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
323 if (hStmt != NULL)
324 {
325 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
326 DB_RESULT hResult = DBSelectPrepared(hStmt);
327 if (hResult != NULL)
328 {
329 if (DBGetNumRows(hResult) > 0)
330 {
331 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
332 DbgPrintf(8, _T("ConfigReadStr: name=%s value=\"%s\""), szVar, szBuffer);
333 bSuccess = true;
334 }
335 DBFreeResult(hResult);
336 }
337 DBFreeStatement(hStmt);
338 }
339 if (dbHandle == NULL)
340 DBConnectionPoolReleaseConnection(hdb);
341
342 if (bSuccess)
343 {
344 RWLockWriteLock(s_configCacheLock, INFINITE);
345 s_configCache.set(szVar, szBuffer);
346 RWLockUnlock(s_configCacheLock);
347 }
348
349 return bSuccess;
350 }
351
352 /**
353 * Read string value from configuration table
354 */
355 bool NXCORE_EXPORTABLE ConfigReadStr(const TCHAR *var, TCHAR *buffer, int bufferSize, const TCHAR *defaultValue)
356 {
357 return ConfigReadStrEx(NULL, var, buffer, bufferSize, defaultValue);
358 }
359
360 /**
361 * Read multibyte string from configuration table
362 */
363 #ifdef UNICODE
364
365 bool NXCORE_EXPORTABLE ConfigReadStrA(const WCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
366 {
367 WCHAR *wcBuffer = (WCHAR *)malloc(iBufSize * sizeof(WCHAR));
368 bool rc = ConfigReadStr(szVar, wcBuffer, iBufSize, _T(""));
369 if (rc)
370 {
371 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, wcBuffer, -1, szBuffer, iBufSize, NULL, NULL);
372 }
373 else
374 {
375 strncpy(szBuffer, szDefault, iBufSize);
376 }
377 szBuffer[iBufSize - 1] = 0;
378 free(wcBuffer);
379 return rc;
380 }
381
382 #endif
383
384 /**
385 * Read string value from configuration table as UTF8 string
386 */
387 bool NXCORE_EXPORTABLE ConfigReadStrUTF8(const TCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
388 {
389 DB_RESULT hResult;
390 bool bSuccess = false;
391
392 strncpy(szBuffer, szDefault, iBufSize);
393 if (_tcslen(szVar) > 127)
394 return false;
395
396 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
397 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
398 if (hStmt != NULL)
399 {
400 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
401 hResult = DBSelectPrepared(hStmt);
402 if (hResult != NULL)
403 {
404 if (DBGetNumRows(hResult) > 0)
405 {
406 DBGetFieldUTF8(hResult, 0, 0, szBuffer, iBufSize);
407 bSuccess = true;
408 }
409 DBFreeResult(hResult);
410 }
411 DBFreeStatement(hStmt);
412 }
413 DBConnectionPoolReleaseConnection(hdb);
414
415 return bSuccess;
416 }
417
418 /**
419 * Read integer value from configuration table
420 */
421 int NXCORE_EXPORTABLE ConfigReadInt(const TCHAR *szVar, int iDefault)
422 {
423 return ConfigReadIntEx(NULL, szVar, iDefault);
424 }
425
426 /**
427 * Read integer value from configuration table
428 */
429 int NXCORE_EXPORTABLE ConfigReadIntEx(DB_HANDLE hdb, const TCHAR *szVar, int iDefault)
430 {
431 TCHAR szBuffer[64];
432
433 if (ConfigReadStrEx(hdb, szVar, szBuffer, 64, _T("")))
434 return _tcstol(szBuffer, NULL, 0);
435 else
436 return iDefault;
437 }
438
439 /**
440 * Read unsigned long value from configuration table
441 */
442 UINT32 NXCORE_EXPORTABLE ConfigReadULong(const TCHAR *szVar, UINT32 dwDefault)
443 {
444 TCHAR szBuffer[64];
445
446 if (ConfigReadStr(szVar, szBuffer, 64, _T("")))
447 return _tcstoul(szBuffer, NULL, 0);
448 else
449 return dwDefault;
450 }
451
452 /**
453 * Read byte array (in hex form) from configuration table into integer array
454 */
455 bool NXCORE_EXPORTABLE ConfigReadByteArray(const TCHAR *pszVar, int *pnArray, int nSize, int nDefault)
456 {
457 TCHAR szBuffer[256];
458 char pbBytes[128];
459 bool bResult;
460 int i, nLen;
461
462 if (ConfigReadStr(pszVar, szBuffer, 256, _T("")))
463 {
464 StrToBin(szBuffer, (BYTE *)pbBytes, 128);
465 nLen = (int)_tcslen(szBuffer) / 2;
466 for(i = 0; (i < nSize) && (i < nLen); i++)
467 pnArray[i] = pbBytes[i];
468 for(; i < nSize; i++)
469 pnArray[i] = nDefault;
470 bResult = true;
471 }
472 else
473 {
474 for(i = 0; i < nSize; i++)
475 pnArray[i] = nDefault;
476 bResult = false;
477 }
478 return bResult;
479 }
480
481 /**
482 * Write string value to configuration table
483 */
484 bool NXCORE_EXPORTABLE ConfigWriteStr(const TCHAR *varName, const TCHAR *value, bool bCreate, bool isVisible, bool needRestart)
485 {
486 if (_tcslen(varName) > 63)
487 return false;
488
489 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
490
491 // Check for variable existence
492 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
493 if (hStmt == NULL)
494 {
495 DBConnectionPoolReleaseConnection(hdb);
496 return false;
497 }
498 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
499 DB_RESULT hResult = DBSelectPrepared(hStmt);
500 bool bVarExist = false;
501 if (hResult != NULL)
502 {
503 if (DBGetNumRows(hResult) > 0)
504 bVarExist = true;
505 DBFreeResult(hResult);
506 }
507 DBFreeStatement(hStmt);
508
509 // Don't create non-existing variable if creation flag not set
510 if (!bCreate && !bVarExist)
511 {
512 DBConnectionPoolReleaseConnection(hdb);
513 return false;
514 }
515
516 // Create or update variable value
517 if (bVarExist)
518 {
519 hStmt = DBPrepare(hdb, _T("UPDATE config SET var_value=? WHERE var_name=?"));
520 if (hStmt == NULL)
521 {
522 DBConnectionPoolReleaseConnection(hdb);
523 return false;
524 }
525 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
526 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
527 }
528 else
529 {
530 hStmt = DBPrepare(hdb, _T("INSERT INTO config (var_name,var_value,is_visible,need_server_restart) VALUES (?,?,?,?)"));
531 if (hStmt == NULL)
532 {
533 DBConnectionPoolReleaseConnection(hdb);
534 return false;
535 }
536 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
537 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
538 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)(isVisible ? 1 : 0));
539 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)(needRestart ? 1 : 0));
540 }
541 bool success = DBExecute(hStmt);
542 DBFreeStatement(hStmt);
543 DBConnectionPoolReleaseConnection(hdb);
544 if (success)
545 OnConfigVariableChange(false, varName, value);
546 return success;
547 }
548
549 /**
550 * Write integer value to configuration table
551 */
552 bool NXCORE_EXPORTABLE ConfigWriteInt(const TCHAR *szVar, int iValue, bool bCreate, bool isVisible, bool needRestart)
553 {
554 TCHAR szBuffer[64];
555
556 _sntprintf(szBuffer, 64, _T("%d"), iValue);
557 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
558 }
559
560 /**
561 * Write unsigned long value to configuration table
562 */
563 bool NXCORE_EXPORTABLE ConfigWriteULong(const TCHAR *szVar, UINT32 dwValue, bool bCreate, bool isVisible, bool needRestart)
564 {
565 TCHAR szBuffer[64];
566
567 _sntprintf(szBuffer, 64, _T("%u"), dwValue);
568 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
569 }
570
571 /**
572 * Write integer array to configuration table
573 */
574 bool NXCORE_EXPORTABLE ConfigWriteByteArray(const TCHAR *pszVar, int *pnArray, int nSize, bool bCreate, bool isVisible, bool needRestart)
575 {
576 TCHAR szBuffer[256];
577 int i, j;
578
579 for(i = 0, j = 0; (i < nSize) && (i < 127); i++, j += 2)
580 _sntprintf(&szBuffer[j], 256 - j, _T("%02X"), (char)((pnArray[i] > 127) ? 127 : ((pnArray[i] < -127) ? -127 : pnArray[i])));
581 return ConfigWriteStr(pszVar, szBuffer, bCreate, isVisible, needRestart);
582 }
583
584 /**
585 * Delete configuratrion variable
586 */
587 bool NXCORE_EXPORTABLE ConfigDelete(const TCHAR *name)
588 {
589 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
590
591 TCHAR query[1024];
592 _sntprintf(query, 1024, _T("DELETE FROM config WHERE var_name=%s"), (const TCHAR *)DBPrepareString(hdb, name));
593 bool success = DBQuery(hdb, query) ? true : false;
594
595 DBConnectionPoolReleaseConnection(hdb);
596
597 if (success)
598 {
599 RWLockWriteLock(s_configCacheLock, INFINITE);
600 s_configCache.remove(name);
601 RWLockUnlock(s_configCacheLock);
602 }
603
604 return success;
605 }
606
607 /**
608 * Read large string (clob) value from configuration table
609 */
610 TCHAR NXCORE_EXPORTABLE *ConfigReadCLOB(const TCHAR *var, const TCHAR *defValue)
611 {
612 TCHAR *result = NULL;
613
614 if (_tcslen(var) <= 63)
615 {
616 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
617 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
618 if (hStmt != NULL)
619 {
620 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
621 DB_RESULT hResult = DBSelectPrepared(hStmt);
622 if (hResult != NULL)
623 {
624 if (DBGetNumRows(hResult) > 0)
625 {
626 result = DBGetField(hResult, 0, 0, NULL, 0);
627 }
628 DBFreeResult(hResult);
629 }
630 DBFreeStatement(hStmt);
631 }
632 DBConnectionPoolReleaseConnection(hdb);
633 }
634
635 // Return default value in case of error
636 if ((result == NULL) && (defValue != NULL))
637 result = _tcsdup(defValue);
638
639 return result;
640 }
641
642 /**
643 * Write large string (clob) value to configuration table
644 */
645 bool NXCORE_EXPORTABLE ConfigWriteCLOB(const TCHAR *var, const TCHAR *value, bool bCreate)
646 {
647 if (_tcslen(var) > 63)
648 return false;
649
650 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
651
652 // Check for variable existence
653 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
654 if (hStmt == NULL)
655 {
656 DBConnectionPoolReleaseConnection(hdb);
657 return false;
658 }
659 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
660 DB_RESULT hResult = DBSelectPrepared(hStmt);
661 bool bVarExist = false;
662 if (hResult != NULL)
663 {
664 if (DBGetNumRows(hResult) > 0)
665 bVarExist = true;
666 DBFreeResult(hResult);
667 }
668 DBFreeStatement(hStmt);
669
670 // Don't create non-existing variable if creation flag not set
671 if (!bCreate && !bVarExist)
672 {
673 DBConnectionPoolReleaseConnection(hdb);
674 return false;
675 }
676
677 // Create or update variable value
678 if (bVarExist)
679 {
680 hStmt = DBPrepare(hdb, _T("UPDATE config_clob SET var_value=? WHERE var_name=?"));
681 if (hStmt == NULL)
682 {
683 DBConnectionPoolReleaseConnection(hdb);
684 return false;
685 }
686 DBBind(hStmt, 1, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
687 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
688 }
689 else
690 {
691 hStmt = DBPrepare(hdb, _T("INSERT INTO config_clob (var_name,var_value) VALUES (?,?)"));
692 if (hStmt == NULL)
693 {
694 DBConnectionPoolReleaseConnection(hdb);
695 return false;
696 }
697 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
698 DBBind(hStmt, 2, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
699 }
700 bool success = DBExecute(hStmt) ? true : false;
701 DBFreeStatement(hStmt);
702 DBConnectionPoolReleaseConnection(hdb);
703 if (success)
704 OnConfigVariableChange(true, var, value);
705 return success;
706 }