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