XEN subagent: added domain state parameters
[public/netxms.git] / src / server / core / main.cpp
CommitLineData
d9177dd1 1/*
5039dede 2** NetXMS - Network Management System
302bb0af 3** Copyright (C) 2003-2017 Raden Solutions
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: main.cpp
20**
21**/
22
23#include "nxcore.h"
24#include <netxmsdb.h>
fdbee7f8 25#include <netxms_mt.h>
6fad8870 26#include <hdlink.h>
5039dede 27
b847803c 28#if !defined(_WIN32) && HAVE_READLINE_READLINE_H && HAVE_READLINE && !defined(UNICODE)
0322eed7
VK
29#include <readline/readline.h>
30#include <readline/history.h>
31#define USE_READLINE 1
5039dede
AK
32#endif
33
34#ifdef _WIN32
a23d8e0d
VK
35#include <errno.h>
36#include <psapi.h>
7bdb43c3 37#include <conio.h>
5039dede 38#else
a23d8e0d
VK
39#include <signal.h>
40#include <sys/wait.h>
5039dede
AK
41#endif
42
4ef60905
AK
43#ifdef WITH_ZMQ
44#include "zeromq.h"
45#endif
46
3a82d5ae
VK
47/**
48 * Messages generated by mc.pl (for UNIX version only)
49 */
5039dede
AK
50#ifndef _WIN32
51extern unsigned int g_dwNumMessages;
52extern const TCHAR *g_szMessages[];
53#endif
54
8f99849c
VK
55/**
56 * Shutdown reasons
57 */
030a0779
VK
58#define SHUTDOWN_DEFAULT 0
59#define SHUTDOWN_FROM_CONSOLE 1
60#define SHUTDOWN_BY_SIGNAL 2
5039dede 61
8f99849c
VK
62/**
63 * Externals
64 */
d140955e 65extern Queue g_dciCacheLoaderQueue;
5039dede 66
36e44abe 67void InitClientListeners();
534e1b83 68void InitMobileDeviceListeners();
36e44abe 69void InitCertificates();
cce82c3a 70bool LoadServerCertificate(RSA **serverKey);
ab185583
VK
71void InitUsers();
72void CleanupUsers();
8fd95c92 73void LoadPerfDataStorageDrivers();
03b96461 74void ImportLocalConfiguration();
288a0046 75void RegisterPredictionEngines();
cf4260a7 76void ExecuteStartupScripts();
bf306af3 77void CloseAgentTunnels();
ec13a467
VK
78
79void ExecuteScheduledScript(const ScheduledTaskParameters *param);
80void MaintenanceModeEnter(const ScheduledTaskParameters *params);
81void MaintenanceModeLeave(const ScheduledTaskParameters *params);
82deb2d7
TD
82void ScheduleDeployPolicy(const ScheduledTaskParameters *params);
83void ScheduleUninstallPolicy(const ScheduledTaskParameters * params);
058bf6fc 84
0de31ec3
VK
85void InitCountryList();
86void InitCurrencyList();
87
058bf6fc 88#if XMPP_SUPPORTED
098ef635 89void StartXMPPConnector();
244c65ef 90void StopXMPPConnector();
058bf6fc 91#endif
5039dede 92
af4a09df
VK
93/**
94 * Syslog server control
95 */
96void StartSyslogServer();
97void StopSyslogServer();
98
534e1b83
VK
99/**
100 * Thread functions
101 */
534e1b83
VK
102THREAD_RESULT THREAD_CALL Syncer(void *);
103THREAD_RESULT THREAD_CALL NodePoller(void *);
104THREAD_RESULT THREAD_CALL PollManager(void *);
105THREAD_RESULT THREAD_CALL EventProcessor(void *);
106THREAD_RESULT THREAD_CALL WatchdogThread(void *);
107THREAD_RESULT THREAD_CALL ClientListener(void *);
108THREAD_RESULT THREAD_CALL ClientListenerIPv6(void *);
109THREAD_RESULT THREAD_CALL MobileDeviceListener(void *);
110THREAD_RESULT THREAD_CALL MobileDeviceListenerIPv6(void *);
111THREAD_RESULT THREAD_CALL ISCListener(void *);
112THREAD_RESULT THREAD_CALL LocalAdminListener(void *);
113THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *);
534e1b83
VK
114THREAD_RESULT THREAD_CALL BeaconPoller(void *);
115THREAD_RESULT THREAD_CALL JobManagerThread(void *);
116THREAD_RESULT THREAD_CALL UptimeCalculator(void *);
d75003e1 117THREAD_RESULT THREAD_CALL ReportingServerConnector(void *);
bf306af3 118THREAD_RESULT THREAD_CALL TunnelListener(void *arg);
058bf6fc 119
534e1b83
VK
120/**
121 * Global variables
122 */
1039d7ee 123TCHAR NXCORE_EXPORTABLE g_szConfigFile[MAX_PATH] = _T("{search}");
5039dede 124TCHAR NXCORE_EXPORTABLE g_szLogFile[MAX_PATH] = DEFAULT_LOG_FILE;
458b5d2b
VK
125UINT32 g_logRotationMode = NXLOG_ROTATION_BY_SIZE;
126UINT64 g_maxLogSize = 16384 * 1024;
127UINT32 g_logHistorySize = 4;
4f8998ca 128TCHAR g_szDailyLogFileSuffix[64] = _T("");
5039dede 129TCHAR NXCORE_EXPORTABLE g_szDumpDir[MAX_PATH] = DEFAULT_DUMP_DIR;
29dc8792 130char g_szCodePage[256] = ICONV_DEFAULT_CODEPAGE;
5f6e8d09 131TCHAR NXCORE_EXPORTABLE g_szListenAddress[MAX_PATH] = _T("*");
5039dede 132#ifndef _WIN32
b07c50cc 133TCHAR NXCORE_EXPORTABLE g_szPIDFile[MAX_PATH] = _T("/var/run/netxmsd.pid");
5039dede 134#endif
967893bb
VK
135UINT32 g_dwDiscoveryPollingInterval;
136UINT32 g_dwStatusPollingInterval;
137UINT32 g_dwConfigurationPollingInterval;
138UINT32 g_dwRoutingTableUpdateInterval;
139UINT32 g_dwTopologyPollingInterval;
140UINT32 g_dwConditionPollingInterval;
805171de 141UINT32 g_instancePollingInterval;
c59466d2
VK
142UINT32 g_icmpPingSize;
143UINT32 g_icmpPingTimeout = 1500; // ICMP ping timeout (milliseconds)
144UINT32 g_auditFlags;
145UINT32 g_slmPollingInterval;
f6456d80 146UINT32 g_offlineDataRelevanceTime = 86400;
db6a6b45
VK
147TCHAR NXCORE_EXPORTABLE g_netxmsdDataDir[MAX_PATH] = _T("");
148TCHAR NXCORE_EXPORTABLE g_netxmsdLibDir[MAX_PATH] = _T("");
2a964810 149int g_dbSyntax = DB_SYNTAX_UNKNOWN;
967893bb 150UINT32 NXCORE_EXPORTABLE g_processAffinityMask = DEFAULT_AFFINITY_MASK;
e9902466 151UINT64 g_serverId = 0;
5039dede 152RSA *g_pServerKey = NULL;
c59466d2
VK
153time_t g_serverStartTime = 0;
154UINT32 g_lockTimeout = 60000; // Default timeout for acquiring mutex
155UINT32 g_agentCommandTimeout = 4000; // Default timeout for requests to agent
156UINT32 g_thresholdRepeatInterval = 0; // Disabled by default
157int g_requiredPolls = 1;
b8c1ec69 158DB_DRIVER g_dbDriver = NULL;
1ef6170e 159ThreadPool NXCORE_EXPORTABLE *g_mainThreadPool = NULL;
9708eff4 160INT16 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
fbd0079b 161InetAddressList g_peerNodeAddrList;
5039dede 162
f375019e
VK
163/**
164 * Static data
165 */
5039dede
AK
166static CONDITION m_condShutdown = INVALID_CONDITION_HANDLE;
167static THREAD m_thPollManager = INVALID_THREAD_HANDLE;
5039dede 168static THREAD m_thSyncer = INVALID_THREAD_HANDLE;
bf306af3 169static THREAD s_tunnelListenerThread = INVALID_THREAD_HANDLE;
5039dede 170static int m_nShutdownReason = SHUTDOWN_DEFAULT;
4fd0b7ca 171static StringSet s_components;
5039dede
AK
172
173#ifndef _WIN32
174static pthread_t m_signalHandlerThread;
175#endif
176
4fd0b7ca
VK
177/**
178 * Register component
179 */
180void NXCORE_EXPORTABLE RegisterComponent(const TCHAR *id)
181{
182 s_components.add(id);
183}
184
185/**
186 * Check if component with given ID is registered
187 */
188bool NXCORE_EXPORTABLE IsComponentRegistered(const TCHAR *id)
189{
190 return s_components.contains(id);
191}
192
193/**
194 * Fill NXCP message with components data
195 */
196void FillComponentsMessage(NXCPMessage *msg)
197{
198 msg->setField(VID_NUM_COMPONENTS, (INT32)s_components.size());
199 UINT32 fieldId = VID_COMPONENT_LIST_BASE;
200 Iterator<const TCHAR> *it = s_components.iterator();
201 while(it->hasNext())
202 {
203 msg->setField(fieldId++, it->next());
204 }
205 delete it;
206}
207
496390c2
VK
208/**
209 * Sleep for specified number of seconds or until system shutdown arrives
210 * Function will return TRUE if shutdown event occurs
211 *
212 * @param seconds seconds to sleep
213 * @return true if server is shutting down
214 */
400e55c4 215bool NXCORE_EXPORTABLE SleepAndCheckForShutdown(int seconds)
5039dede 216{
496390c2 217 return ConditionWait(m_condShutdown, seconds * 1000);
5039dede
AK
218}
219
496390c2
VK
220/**
221 * Disconnect from database (exportable function for startup module)
222 */
73869331 223void NXCORE_EXPORTABLE ShutdownDB()
5039dede 224{
9bd1bace 225 DBConnectionPoolShutdown();
b8c1ec69 226 DBUnloadDriver(g_dbDriver);
5039dede
AK
227}
228
496390c2
VK
229/**
230 * Check data directory for existence
231 */
35f836fe 232static BOOL CheckDataDir()
5039dede 233{
35f836fe 234 TCHAR szBuffer[MAX_PATH];
5039dede 235
db6a6b45 236 if (_tchdir(g_netxmsdDataDir) == -1)
5039dede 237 {
db6a6b45 238 nxlog_write(MSG_INVALID_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", g_netxmsdDataDir);
5039dede
AK
239 return FALSE;
240 }
241
242#ifdef _WIN32
35f836fe 243#define MKDIR(name) _tmkdir(name)
5039dede 244#else
35f836fe 245#define MKDIR(name) _tmkdir(name, 0700)
5039dede
AK
246#endif
247
5039dede 248 // Create directory for package files if it doesn't exist
db6a6b45 249 _tcscpy(szBuffer, g_netxmsdDataDir);
35f836fe 250 _tcscat(szBuffer, DDIR_PACKAGES);
5039dede
AK
251 if (MKDIR(szBuffer) == -1)
252 if (errno != EEXIST)
253 {
254 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
255 return FALSE;
256 }
257
4d0c32f3 258 // Create directory for map background images if it doesn't exist
db6a6b45 259 _tcscpy(szBuffer, g_netxmsdDataDir);
35f836fe 260 _tcscat(szBuffer, DDIR_BACKGROUNDS);
4d0c32f3
VK
261 if (MKDIR(szBuffer) == -1)
262 if (errno != EEXIST)
263 {
264 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
265 return FALSE;
266 }
267
e6b9439a 268 // Create directory for image library is if does't exists
db6a6b45 269 _tcscpy(szBuffer, g_netxmsdDataDir);
e6b9439a
AK
270 _tcscat(szBuffer, DDIR_IMAGES);
271 if (MKDIR(szBuffer) == -1)
272 {
273 if (errno != EEXIST)
274 {
275 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
276 return FALSE;
277 }
278 }
279
619e5c9b 280 // Create directory for file store if does't exists
db6a6b45 281 _tcscpy(szBuffer, g_netxmsdDataDir);
619e5c9b
VK
282 _tcscat(szBuffer, DDIR_FILES);
283 if (MKDIR(szBuffer) == -1)
57fef75c
VK
284 {
285 if (errno != EEXIST)
286 {
287 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
288 return FALSE;
289 }
290 }
291
5039dede
AK
292#undef MKDIR
293
294 return TRUE;
295}
296
496390c2
VK
297/**
298 * Load global configuration parameters
299 */
5039dede
AK
300static void LoadGlobalConfig()
301{
35f836fe
VK
302 g_dwDiscoveryPollingInterval = ConfigReadInt(_T("DiscoveryPollingInterval"), 900);
303 g_dwStatusPollingInterval = ConfigReadInt(_T("StatusPollingInterval"), 60);
304 g_dwConfigurationPollingInterval = ConfigReadInt(_T("ConfigurationPollingInterval"), 3600);
805171de 305 g_instancePollingInterval = ConfigReadInt(_T("InstancePollingInterval"), 600);
35f836fe 306 g_dwRoutingTableUpdateInterval = ConfigReadInt(_T("RoutingTableUpdateInterval"), 300);
040c45fa 307 g_dwTopologyPollingInterval = ConfigReadInt(_T("TopologyPollingInterval"), 1800);
35f836fe 308 g_dwConditionPollingInterval = ConfigReadInt(_T("ConditionPollingInterval"), 60);
c59466d2 309 g_slmPollingInterval = ConfigReadInt(_T("SlmPollingInterval"), 60);
90e3031f
VK
310 DCObject::m_defaultPollingInterval = ConfigReadInt(_T("DefaultDCIPollingInterval"), 60);
311 DCObject::m_defaultRetentionTime = ConfigReadInt(_T("DefaultDCIRetentionTime"), 30);
9708eff4 312 g_defaultAgentCacheMode = (INT16)ConfigReadInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF);
e9902466
VK
313 if ((g_defaultAgentCacheMode != AGENT_CACHE_ON) && (g_defaultAgentCacheMode != AGENT_CACHE_OFF))
314 {
315 DbgPrintf(1, _T("Invalid value %d of DefaultAgentCacheMode: reset to %d (OFF)"), g_defaultAgentCacheMode, AGENT_CACHE_OFF);
316 ConfigWriteInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF, true, true, true);
c1f07289 317 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
e9902466 318 }
35f836fe 319 if (ConfigReadInt(_T("DeleteEmptySubnets"), 1))
c8076b19 320 g_flags |= AF_DELETE_EMPTY_SUBNETS;
35f836fe 321 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
c8076b19
VK
322 g_flags |= AF_ENABLE_SNMP_TRAPD;
323 if (ConfigReadInt(_T("ProcessTrapsFromUnmanagedNodes"), 0))
324 g_flags |= AF_TRAPS_FROM_UNMANAGED_NODES;
35f836fe 325 if (ConfigReadInt(_T("EnableZoning"), 0))
c8076b19 326 g_flags |= AF_ENABLE_ZONING;
549f48b3 327 if (ConfigReadInt(_T("EnableObjectTransactions"), 0))
c8076b19 328 g_flags |= AF_ENABLE_OBJECT_TRANSACTIONS;
35f836fe 329 if (ConfigReadInt(_T("RunNetworkDiscovery"), 0))
c8076b19 330 g_flags |= AF_ENABLE_NETWORK_DISCOVERY;
35f836fe 331 if (ConfigReadInt(_T("ActiveNetworkDiscovery"), 0))
c8076b19 332 g_flags |= AF_ACTIVE_NETWORK_DISCOVERY;
e02953a4 333 if (ConfigReadInt(_T("UseSNMPTrapsForDiscovery"), 0))
c8076b19 334 g_flags |= AF_SNMP_TRAP_DISCOVERY;
727b90ff
VK
335 if (ConfigReadInt(_T("UseSyslogForDiscovery"), 0))
336 g_flags |= AF_SYSLOG_DISCOVERY;
35f836fe 337 if (ConfigReadInt(_T("ResolveNodeNames"), 1))
c8076b19 338 g_flags |= AF_RESOLVE_NODE_NAMES;
35f836fe 339 if (ConfigReadInt(_T("SyncNodeNamesWithDNS"), 0))
c8076b19 340 g_flags |= AF_SYNC_NODE_NAMES_WITH_DNS;
35f836fe 341 if (ConfigReadInt(_T("CheckTrustedNodes"), 1))
c8076b19 342 g_flags |= AF_CHECK_TRUSTED_NODES;
3bbc7435 343 if (ConfigReadInt(_T("EnableNXSLContainerFunctions"), 1))
c8076b19 344 g_flags |= AF_ENABLE_NXSL_CONTAINER_FUNCS;
f31c22b3 345 if (ConfigReadInt(_T("UseFQDNForNodeNames"), 1))
c8076b19 346 g_flags |= AF_USE_FQDN_FOR_NODE_NAMES;
098ef635 347 if (ConfigReadInt(_T("ApplyDCIFromTemplateToDisabledDCI"), 1))
c8076b19 348 g_flags |= AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE;
4553d424 349 if (ConfigReadInt(_T("ResolveDNSToIPOnStatusPoll"), 0))
385b1f20 350 g_flags |= AF_RESOLVE_IP_FOR_EACH_STATUS_POLL;
8a1519ce
VK
351 if (ConfigReadInt(_T("CaseInsensitiveLoginNames"), 0))
352 g_flags |= AF_CASE_INSENSITIVE_LOGINS;
0eff2ce4
VK
353 if (ConfigReadInt(_T("TrapSourcesInAllZones"), 0))
354 g_flags |= AF_TRAP_SOURCES_IN_ALL_ZONES;
fc958888 355
db6a6b45 356 if (g_netxmsdDataDir[0] == 0)
f31c22b3 357 {
1039d7ee
VK
358 GetNetXMSDirectory(nxDirData, g_netxmsdDataDir);
359 DbgPrintf(1, _T("Data directory set to %s"), g_netxmsdDataDir);
f31c22b3
VK
360 }
361 else
362 {
db6a6b45 363 DbgPrintf(1, _T("Using data directory %s"), g_netxmsdDataDir);
f31c22b3 364 }
d96bd4c7 365
c59466d2
VK
366 g_icmpPingTimeout = ConfigReadInt(_T("IcmpPingTimeout"), 1500);
367 g_icmpPingSize = ConfigReadInt(_T("IcmpPingSize"), 46);
368 g_lockTimeout = ConfigReadInt(_T("LockTimeout"), 60000);
c59466d2
VK
369 g_agentCommandTimeout = ConfigReadInt(_T("AgentCommandTimeout"), 4000);
370 g_thresholdRepeatInterval = ConfigReadInt(_T("ThresholdRepeatInterval"), 0);
371 g_requiredPolls = ConfigReadInt(_T("PollCountForStatusChange"), 1);
f6456d80 372 g_offlineDataRelevanceTime = ConfigReadInt(_T("OfflineDataRelevanceTime"), 86400);
296ae03d 373
014fbefc 374 UINT32 snmpTimeout = ConfigReadInt(_T("SNMPRequestTimeout"), 1500);
296ae03d 375 SnmpSetDefaultTimeout(snmpTimeout);
5039dede
AK
376}
377
fdbee7f8
VK
378/**
379 * Initialize cryptografic functions
380 */
cce82c3a 381static bool InitCryptografy()
5039dede
AK
382{
383#ifdef _WITH_ENCRYPTION
cce82c3a 384 bool success = false;
5039dede 385
2df047f4 386 if (!InitCryptoLib(ConfigReadULong(_T("AllowedCiphers"), 0x7F)))
5039dede 387 return FALSE;
2df047f4 388 nxlog_debug(4, _T("Supported ciphers: %s"), (const TCHAR *)NXCPGetSupportedCiphersAsText());
5039dede 389
958a9397 390 SSL_library_init();
0fd5c0a1 391 SSL_load_error_strings();
958a9397 392
cce82c3a
VK
393 if (LoadServerCertificate(&g_pServerKey))
394 {
395 nxlog_debug(1, _T("Server certificate loaded"));
396 }
397 if (g_pServerKey != NULL)
398 {
399 nxlog_debug(1, _T("Using server certificate key"));
400 success = true;
401 }
402 else
403 {
404 TCHAR szKeyFile[MAX_PATH];
405 _tcscpy(szKeyFile, g_netxmsdDataDir);
406 _tcscat(szKeyFile, DFILE_KEYS);
407 g_pServerKey = LoadRSAKeys(szKeyFile);
408 if (g_pServerKey == NULL)
409 {
410 nxlog_debug(1, _T("Generating RSA key pair..."));
3b89a4c1 411 g_pServerKey = RSA_generate_key(NETXMS_RSA_KEYLEN, 17, NULL, NULL);
cce82c3a
VK
412 if (g_pServerKey != NULL)
413 {
414 int fd = _topen(szKeyFile, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0600);
415 if (fd != -1)
416 {
417 UINT32 dwLen = i2d_RSAPublicKey(g_pServerKey, NULL);
418 dwLen += i2d_RSAPrivateKey(g_pServerKey, NULL);
419 BYTE *pKeyBuffer = (BYTE *)malloc(dwLen);
420
421 BYTE *pBufPos = pKeyBuffer;
422 i2d_RSAPublicKey(g_pServerKey, &pBufPos);
423 i2d_RSAPrivateKey(g_pServerKey, &pBufPos);
424 _write(fd, &dwLen, sizeof(UINT32));
425 _write(fd, pKeyBuffer, dwLen);
426
427 BYTE hash[SHA1_DIGEST_SIZE];
428 CalculateSHA1Hash(pKeyBuffer, dwLen, hash);
429 _write(fd, hash, SHA1_DIGEST_SIZE);
430
431 _close(fd);
432 free(pKeyBuffer);
433 success = true;
434 }
435 else
436 {
437 nxlog_debug(0, _T("Failed to open %s for writing"), szKeyFile);
438 }
439 }
2df047f4
VK
440 else
441 {
cce82c3a 442 nxlog_debug(0, _T("Failed to generate RSA key"));
2df047f4 443 }
cce82c3a 444 }
c578be51
AK
445 else
446 {
cce82c3a 447 success = true;
c578be51 448 }
cce82c3a 449 }
5039dede 450
a3ef278b 451 int iPolicy = ConfigReadInt(_T("DefaultEncryptionPolicy"), 1);
5039dede
AK
452 if ((iPolicy < 0) || (iPolicy > 3))
453 iPolicy = 1;
454 SetAgentDEP(iPolicy);
455
cce82c3a 456 return success;
5039dede
AK
457#else
458 return TRUE;
459#endif
460}
461
496390c2
VK
462/**
463 * Check if process with given PID exists and is a NetXMS server process
464 */
fbd0079b 465static bool IsNetxmsdProcess(UINT32 pid)
5039dede
AK
466{
467#ifdef _WIN32
fbd0079b
VK
468 bool result = false;
469 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
5039dede
AK
470 if (hProcess != NULL)
471 {
fbd0079b 472 TCHAR szExtModule[MAX_PATH], szIntModule[MAX_PATH];
5039dede 473 if ((GetModuleBaseName(hProcess, NULL, szExtModule, MAX_PATH) > 0) &&
fbd0079b 474 (GetModuleBaseName(GetCurrentProcess(), NULL, szIntModule, MAX_PATH) > 0))
5039dede 475 {
fbd0079b 476 result = (_tcsicmp(szExtModule, szIntModule) == 0);
5039dede
AK
477 }
478 else
479 {
480 // Cannot read process name, for safety assume that it's a server process
fbd0079b 481 result = true;
5039dede
AK
482 }
483 CloseHandle(hProcess);
484 }
fbd0079b 485 return result;
5039dede 486#else
fbd0079b 487 return kill((pid_t)pid, 0) != -1;
5039dede
AK
488#endif
489}
490
fbd0079b
VK
491/**
492 * Check if remote netxmsd is running
493 */
494static bool PeerNodeIsRunning(const InetAddress& addr)
495{
496 bool result = false;
497
498 TCHAR keyFile[MAX_PATH];
499 _tcscpy(keyFile, g_netxmsdDataDir);
500 _tcscat(keyFile, DFILE_KEYS);
501 RSA *key = LoadRSAKeys(keyFile);
502
503 AgentConnection *ac = new AgentConnection(addr);
504 if (ac->connect(key))
505 {
506 TCHAR result[MAX_RESULT_LENGTH];
507#ifdef _WIN32
508 UINT32 rcc = ac->getParameter(_T("Process.Count(netxmsd.exe)"), MAX_RESULT_LENGTH, result);
509#else
510 UINT32 rcc = ac->getParameter(_T("Process.Count(netxmsd)"), MAX_RESULT_LENGTH, result);
511#endif
512 ac->decRefCount();
513 if (key != NULL)
514 RSA_free(key);
515 if (rcc == ERR_SUCCESS)
516 {
517 return _tcstol(result, NULL, 10) > 0;
518 }
519 }
520 else
521 {
522 ac->decRefCount();
523 if (key != NULL)
524 RSA_free(key);
525 }
526
527 UINT16 port = (UINT16)ConfigReadInt(_T("ClientListenerPort"), SERVER_LISTEN_PORT_FOR_CLIENTS);
528 SOCKET s = ConnectToHost(addr, port, 5000);
529 if (s != INVALID_SOCKET)
530 {
531 shutdown(s, SHUT_RDWR);
532 closesocket(s);
533 result = true;
534 }
535 return result;
536}
537
496390c2
VK
538/**
539 * Database event handler
540 */
526ae8b8 541static void DBEventHandler(DWORD dwEvent, const WCHAR *pszArg1, const WCHAR *pszArg2, bool connLost, void *userArg)
5039dede 542{
c8076b19 543 if (!(g_flags & AF_SERVER_INITIALIZED))
5039dede
AK
544 return; // Don't try to do anything if server is not ready yet
545
546 switch(dwEvent)
547 {
548 case DBEVENT_CONNECTION_LOST:
549 PostEvent(EVENT_DB_CONNECTION_LOST, g_dwMgmtNode, NULL);
c8076b19 550 g_flags |= AF_DB_CONNECTION_LOST;
5039dede
AK
551 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS, FALSE);
552 break;
553 case DBEVENT_CONNECTION_RESTORED:
554 PostEvent(EVENT_DB_CONNECTION_RESTORED, g_dwMgmtNode, NULL);
c8076b19 555 g_flags &= ~AF_DB_CONNECTION_LOST;
5039dede
AK
556 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS, TRUE);
557 break;
4d0c32f3 558 case DBEVENT_QUERY_FAILED:
526ae8b8 559 PostEvent(EVENT_DB_QUERY_FAILED, g_dwMgmtNode, "uud", pszArg1, pszArg2, connLost ? 1 : 0);
4d0c32f3 560 break;
5039dede
AK
561 default:
562 break;
563 }
564}
565
496390c2
VK
566/**
567 * Send console message to session with open console
568 */
f669df41
VK
569static void SendConsoleMessage(ClientSession *session, void *arg)
570{
571 if (session->isConsoleOpen())
572 {
b368969c 573 NXCPMessage msg;
f669df41 574
b368969c
VK
575 msg.setCode(CMD_ADM_MESSAGE);
576 msg.setField(VID_MESSAGE, (TCHAR *)arg);
d3a7cf4c 577 session->postMessage(&msg);
f669df41
VK
578 }
579}
580
d6217efa
VK
581/**
582 * Console writer
583 */
f669df41
VK
584static void LogConsoleWriter(const TCHAR *format, ...)
585{
586 TCHAR buffer[8192];
587 va_list args;
588
589 va_start(args, format);
590 _vsntprintf(buffer, 8192, format, args);
591 buffer[8191] = 0;
592 va_end(args);
593
594 WriteToTerminal(buffer);
595
596 EnumerateClientSessions(SendConsoleMessage, buffer);
597}
598
b6aff59d
VK
599/**
600 * Oracle session init callback
601 */
602static void OracleSessionInitCallback(DB_HANDLE hdb)
603{
604 DBQuery(hdb, _T("ALTER SESSION SET DDL_LOCK_TIMEOUT = 60"));
605}
606
fdbee7f8
VK
607/**
608 * Server initialization
609 */
bc980b27 610BOOL NXCORE_EXPORTABLE Initialize()
5039dede 611{
4fd0b7ca 612 s_components.add(_T("CORE"));
5039dede 613
c59466d2
VK
614 g_serverStartTime = time(NULL);
615 srand((unsigned int)g_serverStartTime);
4f8998ca 616
c8076b19 617 if (!(g_flags & AF_USE_SYSLOG))
4f8998ca 618 {
458b5d2b 619 if (!nxlog_set_rotation_policy((int)g_logRotationMode, g_maxLogSize, (int)g_logHistorySize, g_szDailyLogFileSuffix))
c8076b19 620 if (!(g_flags & AF_DAEMON))
4f8998ca
VK
621 _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n"));
622 }
c8076b19 623 if (!nxlog_open((g_flags & AF_USE_SYSLOG) ? NETXMSD_SYSLOG_NAME : g_szLogFile,
2589cc10 624 ((g_flags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) |
625 ((g_flags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) |
4e0e77e6 626 ((g_flags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
9d381279 627 _T("LIBNXSRV.DLL"),
5039dede 628#ifdef _WIN32
2df047f4 629 0, NULL, MSG_DEBUG))
5039dede 630#else
2df047f4 631 g_dwNumMessages, g_szMessages, MSG_DEBUG))
5039dede 632#endif
9d381279
VK
633 {
634 _ftprintf(stderr, _T("FATAL ERROR: Cannot open log file\n"));
635 return FALSE;
636 }
f669df41 637 nxlog_set_console_writer(LogConsoleWriter);
5039dede 638
2df047f4
VK
639 if (g_netxmsdLibDir[0] == 0)
640 {
641 GetNetXMSDirectory(nxDirLib, g_netxmsdLibDir);
642 nxlog_debug(1, _T("LIB directory set to %s"), g_netxmsdLibDir);
643 }
644
5039dede
AK
645 // Set code page
646#ifndef _WIN32
647 if (SetDefaultCodepage(g_szCodePage))
648 {
f5797a09 649 DbgPrintf(1, _T("Code page set to %hs"), g_szCodePage);
5039dede
AK
650 }
651 else
652 {
f375019e 653 nxlog_write(MSG_CODEPAGE_ERROR, EVENTLOG_WARNING_TYPE, "m", g_szCodePage);
5039dede
AK
654 }
655#endif
656
73869331
VK
657 // Set process affinity mask
658 if (g_processAffinityMask != DEFAULT_AFFINITY_MASK)
659 {
660#ifdef _WIN32
661 if (SetProcessAffinityMask(GetCurrentProcess(), g_processAffinityMask))
2df047f4 662 nxlog_debug(1, _T("Process affinity mask set to 0x%08X"), g_processAffinityMask);
73869331
VK
663#else
664 nxlog_write(MSG_SET_PROCESS_AFFINITY_NOT_SUPPORTED, EVENTLOG_WARNING_TYPE, NULL);
665#endif
666 }
667
5039dede
AK
668#ifdef _WIN32
669 WSADATA wsaData;
1ddf3f0c
VK
670 int wrc = WSAStartup(MAKEWORD(2, 2), &wsaData);
671 if (wrc != 0)
672 {
673 nxlog_write(MSG_WSASTARTUP_FAILED, EVENTLOG_ERROR_TYPE, "e", wrc);
674 return FALSE;
675 }
5039dede
AK
676#endif
677
678 InitLocalNetInfo();
296ae03d 679 SnmpSetMessageIds(MSG_OID_PARSE_ERROR, MSG_SNMP_UNKNOWN_TYPE, MSG_SNMP_GET_ERROR);
5039dede
AK
680
681 // Create queue for delayed SQL queries
76fcb995
VK
682 g_dbWriterQueue = new Queue(256, 64);
683 g_dciDataWriterQueue = new Queue(1024, 1024);
684 g_dciRawDataWriterQueue = new Queue(1024, 1024);
5039dede
AK
685
686 // Initialize database driver and connect to database
c8076b19 687 if (!DBInit(MSG_OTHER, (g_flags & AF_LOG_SQL_ERRORS) ? MSG_SQL_ERROR : 0))
b8c1ec69 688 return FALSE;
2df047f4 689 g_dbDriver = DBLoadDriver(g_szDbDriver, g_szDbDrvParams, (nxlog_get_debug_level() >= 9), DBEventHandler, NULL);
b8c1ec69 690 if (g_dbDriver == NULL)
5039dede
AK
691 return FALSE;
692
693 // Connect to database
9bd1bace 694 DB_HANDLE hdbBootstrap = NULL;
465b3f2d 695 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
4fd0b7ca 696 for(int i = 0; ; i++)
5039dede 697 {
9bd1bace
VK
698 hdbBootstrap = DBConnect(g_dbDriver, g_szDbServer, g_szDbName, g_szDbLogin, g_szDbPassword, g_szDbSchema, errorText);
699 if ((hdbBootstrap != NULL) || (i == 5))
5039dede
AK
700 break;
701 ThreadSleep(5);
702 }
9bd1bace 703 if (hdbBootstrap == NULL)
5039dede 704 {
465b3f2d 705 nxlog_write(MSG_DB_CONNFAIL, EVENTLOG_ERROR_TYPE, "s", errorText);
5039dede
AK
706 return FALSE;
707 }
2df047f4 708 nxlog_debug(1, _T("Successfully connected to database %s@%s"), g_szDbName, g_szDbServer);
5039dede 709
4fd0b7ca
VK
710 // Check database schema version
711 int schemaVersion = DBGetSchemaVersion(hdbBootstrap);
712 if (schemaVersion != DB_FORMAT_VERSION)
5039dede 713 {
4fd0b7ca 714 nxlog_write(MSG_WRONG_DB_VERSION, EVENTLOG_ERROR_TYPE, "dd", schemaVersion, DB_FORMAT_VERSION);
9bd1bace 715 DBDisconnect(hdbBootstrap);
5039dede
AK
716 return FALSE;
717 }
718
b6aff59d 719 // Read database syntax
9bd1bace 720 g_dbSyntax = DBGetSyntax(hdbBootstrap);
b6aff59d
VK
721 if (g_dbSyntax == DB_SYNTAX_ORACLE)
722 {
723 DBSetSessionInitCallback(OracleSessionInitCallback);
724 }
725
9bd1bace
VK
726 int baseSize = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolBaseSize"), 10);
727 int maxSize = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolMaxSize"), 30);
728 int cooldownTime = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolCooldownTime"), 300);
729 int ttl = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolMaxLifetime"), 14400);
730
731 DBDisconnect(hdbBootstrap);
732
733 if (!DBConnectionPoolStartup(g_dbDriver, g_szDbServer, g_szDbName, g_szDbLogin, g_szDbPassword, g_szDbSchema, baseSize, maxSize, cooldownTime, ttl))
734 {
735 nxlog_write(MSG_DBCONNPOOL_INIT_FAILED, EVENTLOG_ERROR_TYPE, NULL);
736 return FALSE;
737 }
f727d089 738
58f1f627
VK
739 UINT32 lrt = ConfigReadULong(_T("LongRunningQueryThreshold"), 0);
740 if (lrt != 0)
741 DBSetLongRunningThreshold(lrt);
742
0fdb37c6
VK
743 MetaDataPreLoad();
744
5039dede 745 // Read server ID
4fd0b7ca
VK
746 TCHAR buffer[256];
747 MetaDataReadStr(_T("ServerID"), buffer, 256, _T(""));
748 StrStrip(buffer);
749 if (buffer[0] != 0)
5039dede 750 {
4fd0b7ca 751 g_serverId = _tcstoull(buffer, NULL, 16);
5039dede
AK
752 }
753 else
754 {
755 // Generate new ID
e9902466 756 g_serverId = ((UINT64)time(NULL) << 31) | (UINT64)((UINT32)rand() & 0x7FFFFFFF);
4fd0b7ca
VK
757 _sntprintf(buffer, 256, UINT64X_FMT(_T("016")), g_serverId);
758 MetaDataWriteStr(_T("ServerID"), buffer);
5039dede 759 }
2df047f4 760 nxlog_debug(1, _T("Server ID ") UINT64X_FMT(_T("016")), g_serverId);
5039dede
AK
761
762 // Initialize locks
763retry_db_lock:
c30c0c0f 764 InetAddress addr;
4fd0b7ca 765 if (!InitLocks(&addr, buffer))
5039dede 766 {
fbd0079b 767 if (addr.isValidUnicast()) // Database already locked by another server instance
5039dede
AK
768 {
769 // Check for lock from crashed/terminated local process
c30c0c0f 770 if (GetLocalIpAddr().equals(addr))
5039dede 771 {
fbd0079b
VK
772 UINT32 pid = ConfigReadULong(_T("DBLockPID"), 0);
773 if (!IsNetxmsdProcess(pid) || (pid == GetCurrentProcessId()))
5039dede
AK
774 {
775 UnlockDB();
776 nxlog_write(MSG_DB_LOCK_REMOVED, EVENTLOG_INFORMATION_TYPE, NULL);
777 goto retry_db_lock;
778 }
779 }
fbd0079b
VK
780 else if (g_peerNodeAddrList.hasAddress(addr))
781 {
782 if (!PeerNodeIsRunning(addr))
783 {
784 UnlockDB();
785 nxlog_write(MSG_DB_LOCK_REMOVED, EVENTLOG_INFORMATION_TYPE, NULL);
786 goto retry_db_lock;
787 }
788 }
d94ada36 789 nxlog_write(MSG_DB_LOCKED, EVENTLOG_ERROR_TYPE, "Is", &addr, buffer);
5039dede 790 }
fbd0079b
VK
791 else
792 {
793 nxlog_write(MSG_INIT_LOCKS_FAILED, EVENTLOG_ERROR_TYPE, NULL);
794 }
5039dede
AK
795 return FALSE;
796 }
c8076b19 797 g_flags |= AF_DB_LOCKED;
5039dede
AK
798
799 // Load global configuration parameters
800 LoadGlobalConfig();
958a9397 801 CASReadSettings();
2df047f4 802 nxlog_debug(1, _T("Global configuration loaded"));
5039dede
AK
803
804 // Check data directory
805 if (!CheckDataDir())
806 return FALSE;
807
808 // Initialize cryptografy
809 if (!InitCryptografy())
810 {
811 nxlog_write(MSG_INIT_CRYPTO_FAILED, EVENTLOG_ERROR_TYPE, NULL);
812 return FALSE;
813 }
814
815 // Initialize certificate store and CA
816 InitCertificates();
817
5039dede
AK
818 // Create synchronization stuff
819 m_condShutdown = ConditionCreate(TRUE);
820
5d3459af 821 // Create thread pools
2df047f4 822 nxlog_debug(2, _T("Creating thread pools"));
5d3459af 823 g_mainThreadPool = ThreadPoolCreate(8, 256, _T("MAIN"));
1693f955 824 g_agentConnectionThreadPool = ThreadPoolCreate(4, 256, _T("AGENT"));
5d3459af 825
5039dede
AK
826 // Setup unique identifiers table
827 if (!InitIdTable())
828 return FALSE;
2df047f4 829 nxlog_debug(2, _T("ID table created"));
5039dede 830
0de31ec3
VK
831 InitCountryList();
832 InitCurrencyList();
833
24dc5346 834 // Update status for unfinished jobs in job history
9bd1bace
VK
835 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
836 DBQuery(hdb, _T("UPDATE job_history SET status=4,failure_message='Aborted due to server shutdown or crash' WHERE status NOT IN (3,4,5)"));
837 DBConnectionPoolReleaseConnection(hdb);
24dc5346 838
5039dede
AK
839 // Load and compile scripts
840 LoadScripts();
841
00420032 842 // Initialize persistent storage
843 PersistentStorageInit();
844
f7e4c50e
VK
845 // Initialize watchdog
846 WatchdogInit();
847
53d2de79 848 // Load modules
890478d8
VK
849 if (!LoadNetXMSModules())
850 return FALSE; // Mandatory module not loaded
288a0046 851 RegisterPredictionEngines();
53d2de79 852
5039dede
AK
853 // Initialize mailer and SMS sender
854 InitMailer();
855 InitSMSSender();
856
857 // Load users from database
ab185583 858 InitUsers();
5039dede
AK
859 if (!LoadUsers())
860 {
861 nxlog_write(MSG_ERROR_LOADING_USERS, EVENTLOG_ERROR_TYPE, NULL);
862 return FALSE;
863 }
2df047f4 864 nxlog_debug(2, _T("User accounts loaded"));
5039dede
AK
865
866 // Initialize audit
867 InitAuditLog();
868
da84c57a
VK
869 // Initialize event handling subsystem
870 if (!InitEventSubsystem())
871 return FALSE;
872
873 // Initialize alarms
e30c2442 874 LoadAlarmCategories();
da84c57a
VK
875 if (!InitAlarmManager())
876 return FALSE;
877
5039dede 878 // Initialize objects infrastructure and load objects from database
9796ce45 879 LoadNetworkDeviceDrivers();
5039dede
AK
880 ObjectsInit();
881 if (!LoadObjects())
882 return FALSE;
2df047f4 883 nxlog_debug(1, _T("Objects loaded and initialized"));
d9177dd1 884
5039dede
AK
885 // Initialize and load event actions
886 if (!InitActions())
887 {
888 nxlog_write(MSG_ACTION_INIT_ERROR, EVENTLOG_ERROR_TYPE, NULL);
889 return FALSE;
890 }
891
6fad8870
VK
892 // Initialize helpdesk link
893 SetHDLinkEntryPoints(ResolveAlarmByHDRef, TerminateAlarmByHDRef);
894 LoadHelpDeskLink();
895
5039dede 896 // Initialize data collection subsystem
8fd95c92 897 LoadPerfDataStorageDrivers();
5039dede
AK
898 if (!InitDataCollector())
899 return FALSE;
900
e05b1945 901 InitLogAccess();
d77baddd 902 FileUploadJob::init();
fdbee7f8 903 InitMappingTables();
e05b1945 904
03b96461
VK
905 InitClientListeners();
906 if (ConfigReadInt(_T("ImportConfigurationOnStartup"), 1))
907 ImportLocalConfiguration();
908
5039dede
AK
909 // Check if management node object presented in database
910 CheckForMgmtNode();
911 if (g_dwMgmtNode == 0)
912 {
913 nxlog_write(MSG_CANNOT_FIND_SELF, EVENTLOG_ERROR_TYPE, NULL);
914 return FALSE;
915 }
916
917 // Start threads
918 ThreadCreate(WatchdogThread, 0, NULL);
919 ThreadCreate(NodePoller, 0, NULL);
3929b1ca 920 ThreadCreate(JobManagerThread, 0, NULL);
5039dede 921 m_thSyncer = ThreadCreateEx(Syncer, 0, NULL);
5039dede
AK
922 m_thPollManager = ThreadCreateEx(PollManager, 0, NULL);
923
a64c346b
VK
924 StartHouseKeeper();
925
5039dede
AK
926 // Start event processor
927 ThreadCreate(EventProcessor, 0, NULL);
928
929 // Start SNMP trapper
930 InitTraps();
35f836fe 931 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
5039dede
AK
932 ThreadCreate(SNMPTrapReceiver, 0, NULL);
933
934 // Start built-in syslog daemon
685508a7 935 StartSyslogServer();
5039dede 936
35f836fe 937 // Start database _T("lazy") write thread
5039dede
AK
938 StartDBWriter();
939
940 // Start local administartive interface listener if required
35f836fe 941 if (ConfigReadInt(_T("EnableAdminInterface"), 1))
5039dede
AK
942 ThreadCreate(LocalAdminListener, 0, NULL);
943
5039dede
AK
944 // Start beacon host poller
945 ThreadCreate(BeaconPoller, 0, NULL);
946
947 // Start inter-server communication listener
35f836fe 948 if (ConfigReadInt(_T("EnableISCListener"), 0))
5039dede
AK
949 ThreadCreate(ISCListener, 0, NULL);
950
d75003e1
AK
951 // Start reporting server connector
952 if (ConfigReadInt(_T("EnableReportingServer"), 0))
953 ThreadCreate(ReportingServerConnector, 0, NULL);
954
d9177dd1 955 //Start ldap synchronization
956 if (ConfigReadInt(_T("LdapSyncInterval"), 0))
957 ThreadCreate(SyncLDAPUsers, 0, NULL);
958
ec13a467
VK
959 RegisterSchedulerTaskHandler(_T("Execute.Script"), ExecuteScheduledScript, SYSTEM_ACCESS_SCHEDULE_SCRIPT);
960 RegisterSchedulerTaskHandler(_T("Maintenance.Enter"), MaintenanceModeEnter, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE);
961 RegisterSchedulerTaskHandler(_T("Maintenance.Leave"), MaintenanceModeLeave, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE);
82deb2d7
TD
962 RegisterSchedulerTaskHandler(_T("Policy.Deploy"), ScheduleDeployPolicy, 0); //No access right beacause it will be used only by server
963 RegisterSchedulerTaskHandler(_T("Policy.Uninstall"), ScheduleUninstallPolicy, 0); //No access right beacause it will be used only by server
ed0a30ba 964 RegisterSchedulerTaskHandler(ALARM_SUMMARY_EMAIL_TASK_ID, SendAlarmSummaryEmail, 0); //No access right beacause it will be used only by server
0a145c10 965 InitializeTaskScheduler();
966
f14e669f
EJ
967 // Send summary emails
968 if (ConfigReadInt(_T("EnableAlarmSummaryEmails"), 0))
969 EnableAlarmSummaryEmails();
970 else
ed0a30ba 971 RemoveScheduledTaskByHandlerId(ALARM_SUMMARY_EMAIL_TASK_ID);
f14e669f 972
5039dede
AK
973 // Allow clients to connect
974 ThreadCreate(ClientListener, 0, NULL);
36e44abe
VK
975#ifdef WITH_IPV6
976 ThreadCreate(ClientListenerIPv6, 0, NULL);
977#endif
5039dede 978
534e1b83
VK
979 // Allow mobile devices to connect
980 InitMobileDeviceListeners();
981 ThreadCreate(MobileDeviceListener, 0, NULL);
982#ifdef WITH_IPV6
983 ThreadCreate(MobileDeviceListenerIPv6, 0, NULL);
984#endif
985
bf306af3
VK
986 // Agent tunnels
987 s_tunnelListenerThread = ThreadCreateEx(TunnelListener, 0, NULL);
988
86457857
AK
989 // Start uptime calculator for SLM
990 ThreadCreate(UptimeCalculator, 0, NULL);
991
2df047f4 992 nxlog_debug(2, _T("LIBDIR: %s"), g_netxmsdLibDir);
712dd47d 993
1b42a673 994 // Call startup functions for the modules
a0efa7b5 995 CALL_ALL_MODULES(pfServerStarted, ());
53d2de79 996
058bf6fc 997#if XMPP_SUPPORTED
244c65ef
VK
998 if (ConfigReadInt(_T("EnableXMPPConnector"), 1))
999 {
098ef635 1000 StartXMPPConnector();
244c65ef 1001 }
058bf6fc 1002#endif
244c65ef 1003
9df36f62
AK
1004#if WITH_ZMQ
1005 StartZMQConnector();
1006#endif
1007
cf4260a7
VK
1008 ExecuteStartupScripts();
1009
c8076b19 1010 g_flags |= AF_SERVER_INITIALIZED;
2df047f4 1011 nxlog_debug(1, _T("Server initialization completed"));
5039dede
AK
1012 return TRUE;
1013}
1014
371d9c60
VK
1015/**
1016 * Server shutdown
1017 */
035a4d73 1018void NXCORE_EXPORTABLE Shutdown()
5039dede 1019{
5039dede
AK
1020 // Notify clients
1021 NotifyClientSessions(NX_NOTIFY_SHUTDOWN, 0);
1022
1023 nxlog_write(MSG_SERVER_STOPPED, EVENTLOG_INFORMATION_TYPE, NULL);
c8076b19 1024 g_flags |= AF_SHUTDOWN; // Set shutdown flag
5039dede
AK
1025 ConditionSet(m_condShutdown);
1026
0a145c10 1027 CloseTaskScheduler();
1028
d140955e 1029 // Stop DCI cache loading thread
19dbc8ef 1030 g_dciCacheLoaderQueue.setShutdownMode();
d140955e 1031
058bf6fc 1032#if XMPP_SUPPORTED
244c65ef 1033 StopXMPPConnector();
058bf6fc 1034#endif
244c65ef 1035
9df36f62
AK
1036#if WITH_ZMQ
1037 StopZMQConnector();
1038#endif
1039
19dbc8ef
VK
1040 g_pEventQueue->clear();
1041 g_pEventQueue->put(INVALID_POINTER_VALUE);
5039dede
AK
1042
1043 ShutdownMailer();
1044 ShutdownSMSSender();
1045
1046 ThreadSleep(1); // Give other threads a chance to terminate in a safe way
2df047f4 1047 nxlog_debug(2, _T("All threads was notified, continue with shutdown"));
5039dede 1048
af4a09df 1049 StopSyslogServer();
a64c346b 1050 StopHouseKeeper();
af4a09df 1051
5039dede 1052 // Wait for critical threads
5039dede
AK
1053 ThreadJoin(m_thPollManager);
1054 ThreadJoin(m_thSyncer);
bf306af3
VK
1055 ThreadJoin(s_tunnelListenerThread);
1056
1057 CloseAgentTunnels();
5039dede 1058
a0efa7b5
VK
1059 // Call shutdown functions for the modules
1060 // CALL_ALL_MODULES cannot be used here because it checks for shutdown flag
1061 for(UINT32 i = 0; i < g_dwNumModules; i++)
1062 {
1063 if (g_pModuleList[i].pfShutdown != NULL)
1064 g_pModuleList[i].pfShutdown();
1065 }
1066
9bd1bace 1067 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
83b1c107 1068 SaveObjects(hdb, INVALID_INDEX);
2df047f4 1069 nxlog_debug(2, _T("All objects saved to database"));
83b1c107 1070 SaveUsers(hdb, INVALID_INDEX);
2df047f4 1071 nxlog_debug(2, _T("All users saved to database"));
76d77587 1072 UpdatePStorageDatabase(hdb, INVALID_INDEX);
1073 nxlog_debug(2, _T("All persistent storage values saved"));
9bd1bace
VK
1074 DBConnectionPoolReleaseConnection(hdb);
1075
5039dede 1076 StopDBWriter();
2df047f4 1077 nxlog_debug(1, _T("Database writer stopped"));
5039dede 1078
ab185583 1079 CleanupUsers();
7b45b90d 1080 PersistentStorageDestroy();
ab185583 1081
5039dede
AK
1082 // Remove database lock
1083 UnlockDB();
1084
7a7dfb3e 1085 DBConnectionPoolShutdown();
b8c1ec69 1086 DBUnloadDriver(g_dbDriver);
2df047f4 1087 nxlog_debug(1, _T("Database driver unloaded"));
5039dede
AK
1088
1089 CleanupActions();
1090 ShutdownEventSubsystem();
da84c57a 1091 ShutdownAlarmManager();
2df047f4 1092 nxlog_debug(1, _T("Event processing stopped"));
5039dede 1093
1693f955 1094 ThreadPoolDestroy(g_agentConnectionThreadPool);
5d3459af 1095 ThreadPoolDestroy(g_mainThreadPool);
d87ddcc2 1096 MsgWaitQueue::shutdown();
83b1c107 1097 WatchdogShutdown();
5d3459af 1098
2df047f4 1099 nxlog_debug(1, _T("Server shutdown complete"));
5039dede
AK
1100 nxlog_close();
1101
1102 // Remove PID file
1103#ifndef _WIN32
dda7c270 1104 _tremove(g_szPIDFile);
5039dede
AK
1105#endif
1106
1107 // Terminate process
1108#ifdef _WIN32
c8076b19 1109 if (!(g_flags & AF_DAEMON))
5039dede
AK
1110 ExitProcess(0);
1111#else
1112 exit(0);
1113#endif
1114}
1115
371d9c60
VK
1116/**
1117 * Fast server shutdown - normally called only by Windows service on system shutdown
1118 */
f669df41 1119void NXCORE_EXPORTABLE FastShutdown()
5039dede 1120{
bc9263d1
VK
1121 DbgPrintf(1, _T("Using fast shutdown procedure"));
1122
c8076b19 1123 g_flags |= AF_SHUTDOWN; // Set shutdown flag
5039dede
AK
1124 ConditionSet(m_condShutdown);
1125
9bd1bace 1126 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
83b1c107 1127 SaveObjects(hdb, INVALID_INDEX);
35f836fe 1128 DbgPrintf(2, _T("All objects saved to database"));
83b1c107 1129 SaveUsers(hdb, INVALID_INDEX);
35f836fe 1130 DbgPrintf(2, _T("All users saved to database"));
76d77587 1131 UpdatePStorageDatabase(hdb, INVALID_INDEX);
1132 DbgPrintf(2, _T("All persistent storage values saved"));
9bd1bace 1133 DBConnectionPoolReleaseConnection(hdb);
5039dede 1134
9bd1bace 1135 // Remove database lock first, because we have a chance to lose DB connection
5039dede
AK
1136 UnlockDB();
1137
1138 // Stop database writers
1139 StopDBWriter();
35f836fe 1140 DbgPrintf(1, _T("Database writer stopped"));
5039dede 1141
bc9263d1 1142 DbgPrintf(1, _T("Server shutdown complete"));
5039dede
AK
1143 nxlog_close();
1144}
1145
fdbee7f8
VK
1146/**
1147 * Signal handler for UNIX platforms
1148 */
5039dede
AK
1149#ifndef _WIN32
1150
1151void SignalHandlerStub(int nSignal)
1152{
1153 // should be unused, but JIC...
1154 if (nSignal == SIGCHLD)
1155 {
1156 while (waitpid(-1, NULL, WNOHANG) > 0)
1157 ;
1158 }
1159}
1160
1161THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL SignalHandler(void *pArg)
1162{
1163 sigset_t signals;
1164 int nSignal;
5039dede
AK
1165
1166 m_signalHandlerThread = pthread_self();
1167
1168 // default for SIGCHLD: ignore
1169 signal(SIGCHLD, &SignalHandlerStub);
1170
1171 sigemptyset(&signals);
1172 sigaddset(&signals, SIGTERM);
1173 sigaddset(&signals, SIGINT);
5039dede
AK
1174 sigaddset(&signals, SIGSEGV);
1175 sigaddset(&signals, SIGCHLD);
1176 sigaddset(&signals, SIGHUP);
1177 sigaddset(&signals, SIGUSR1);
1178 sigaddset(&signals, SIGUSR2);
95e2329a
VK
1179#if !defined(__sun) && !defined(_AIX) && !defined(__hpux)
1180 sigaddset(&signals, SIGPIPE);
1181#endif
5039dede
AK
1182
1183 sigprocmask(SIG_BLOCK, &signals, NULL);
1184
1185 while(1)
1186 {
1187 if (sigwait(&signals, &nSignal) == 0)
1188 {
1189 switch(nSignal)
1190 {
1191 case SIGTERM:
1192 case SIGINT:
bc9263d1
VK
1193 // avoid repeat Shutdown() call
1194 if (!(g_flags & AF_SHUTDOWN))
1195 {
1196 m_nShutdownReason = SHUTDOWN_BY_SIGNAL;
1197 if (IsStandalone())
1198 Shutdown(); // will never return
1199 else
1200 ConditionSet(m_condShutdown);
1201 }
1202 break;
5039dede
AK
1203 case SIGSEGV:
1204 abort();
1205 break;
1206 case SIGCHLD:
1207 while (waitpid(-1, NULL, WNOHANG) > 0)
1208 ;
1209 break;
1210 case SIGUSR1:
c8076b19 1211 if (g_flags & AF_SHUTDOWN)
5039dede
AK
1212 goto stop_handler;
1213 break;
1214 default:
1215 break;
1216 }
1217 }
1218 else
1219 {
1220 ThreadSleepMs(100);
1221 }
1222 }
1223
1224stop_handler:
1225 sigprocmask(SIG_UNBLOCK, &signals, NULL);
5039dede
AK
1226 return THREAD_OK;
1227}
1228
1229#endif
1230
fdbee7f8
VK
1231/**
1232 * Common main()
1233 */
5039dede
AK
1234THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL Main(void *pArg)
1235{
1236 nxlog_write(MSG_SERVER_STARTED, EVENTLOG_INFORMATION_TYPE, NULL);
1237
7bdb43c3
VK
1238 if (IsStandalone())
1239 {
c8076b19 1240 if (!(g_flags & AF_DEBUG_CONSOLE_DISABLED))
7bdb43c3
VK
1241 {
1242 char *ptr, szCommand[256];
1243 struct __console_ctx ctx;
35f836fe 1244#ifdef UNICODE
7bdb43c3 1245 WCHAR wcCommand[256];
35f836fe 1246#endif
5039dede 1247
7bdb43c3
VK
1248 ctx.hSocket = -1;
1249 ctx.socketMutex = INVALID_MUTEX_HANDLE;
1250 ctx.pMsg = NULL;
1251 ctx.session = NULL;
1252 ctx.output = NULL;
8e17001f 1253 WriteToTerminal(_T("\nNetXMS Server V") NETXMS_VERSION_STRING _T(" Build ") NETXMS_VERSION_BUILD_STRING IS_UNICODE_BUILD_STRING _T(" Ready\n")
7bdb43c3
VK
1254 _T("Enter \"\x1b[1mhelp\x1b[0m\" for command list or \"\x1b[1mdown\x1b[0m\" for server shutdown\n")
1255 _T("System Console\n\n"));
5039dede
AK
1256
1257#if USE_READLINE
7bdb43c3
VK
1258 // Initialize readline library if we use it
1259 rl_bind_key('\t', RL_INSERT_CAST rl_insert);
5039dede
AK
1260#endif
1261
7bdb43c3
VK
1262 while(1)
1263 {
5039dede 1264#if USE_READLINE
7bdb43c3 1265 ptr = readline("\x1b[33mnetxmsd:\x1b[0m ");
5039dede 1266#else
7bdb43c3
VK
1267 WriteToTerminal(_T("\x1b[33mnetxmsd:\x1b[0m "));
1268 fflush(stdout);
1269 if (fgets(szCommand, 255, stdin) == NULL)
1270 break; // Error reading stdin
1271 ptr = strchr(szCommand, '\n');
1272 if (ptr != NULL)
1273 *ptr = 0;
1274 ptr = szCommand;
5039dede
AK
1275#endif
1276
7bdb43c3
VK
1277 if (ptr != NULL)
1278 {
35f836fe 1279#ifdef UNICODE
fe8ea784
VK
1280#if HAVE_MBSTOWCS
1281 mbstowcs(wcCommand, ptr, 255);
1282#else
7bdb43c3 1283 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ptr, -1, wcCommand, 256);
fe8ea784 1284#endif
7bdb43c3
VK
1285 wcCommand[255] = 0;
1286 StrStrip(wcCommand);
1287 if (wcCommand[0] != 0)
1288 {
1289 if (ProcessConsoleCommand(wcCommand, &ctx) == CMD_EXIT_SHUTDOWN)
35f836fe 1290#else
7bdb43c3
VK
1291 StrStrip(ptr);
1292 if (*ptr != 0)
1293 {
1294 if (ProcessConsoleCommand(ptr, &ctx) == CMD_EXIT_SHUTDOWN)
35f836fe 1295#endif
7bdb43c3 1296 break;
5039dede 1297#if USE_READLINE
7bdb43c3 1298 add_history(ptr);
5039dede 1299#endif
7bdb43c3 1300 }
5039dede 1301#if USE_READLINE
7bdb43c3 1302 free(ptr);
5039dede 1303#endif
7bdb43c3
VK
1304 }
1305 else
1306 {
1307 _tprintf(_T("\n"));
1308 }
1309 }
5039dede
AK
1310
1311#if USE_READLINE
7bdb43c3 1312 free(ptr);
5039dede 1313#endif
bc9263d1
VK
1314 if (!(g_flags & AF_SHUTDOWN))
1315 {
1316 m_nShutdownReason = SHUTDOWN_FROM_CONSOLE;
1317 Shutdown();
1318 }
7bdb43c3
VK
1319 }
1320 else
1321 {
1322 // standalone with debug console disabled
1323#ifdef _WIN32
1324 _tprintf(_T("Server running. Press ESC to shutdown.\n"));
1325 while(1)
1326 {
1327 if (_getch() == 27)
1328 break;
1329 }
1330 _tprintf(_T("Server shutting down...\n"));
1331 Shutdown();
1332#else
1333 _tprintf(_T("Server running. Press Ctrl+C to shutdown.\n"));
1334 // Shutdown will be called from signal handler
1335 ConditionWait(m_condShutdown, INFINITE);
1336#endif
1337 }
5039dede
AK
1338 }
1339 else
1340 {
1341 ConditionWait(m_condShutdown, INFINITE);
1342 // On Win32, Shutdown() will be called by service control handler
1343#ifndef _WIN32
1344 Shutdown();
1345#endif
1346 }
1347 return THREAD_OK;
1348}
1349
fdbee7f8
VK
1350/**
1351 * Initiate server shutdown
1352 */
035a4d73 1353void InitiateShutdown()
5039dede
AK
1354{
1355#ifdef _WIN32
1356 Shutdown();
1357#else
1358 if (IsStandalone())
1359 {
1360 Shutdown();
1361 }
1362 else
1363 {
1364 pthread_kill(m_signalHandlerThread, SIGTERM);
1365 }
1366#endif
1367}
1368
fdbee7f8
VK
1369/**
1370 *DLL Entry point
1371 */
5039dede
AK
1372#ifdef _WIN32
1373
1374BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
1375{
1376 if (dwReason == DLL_PROCESS_ATTACH)
1377 DisableThreadLibraryCalls(hInstance);
1378 return TRUE;
1379}
1380
1381#endif