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