2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Raden Solutions
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.
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.
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.
25 #include <netxms_mt.h>
28 #if !defined(_WIN32) && HAVE_READLINE_READLINE_H && HAVE_READLINE && !defined(UNICODE)
29 #include <readline/readline.h>
30 #include <readline/history.h>
31 #define USE_READLINE 1
51 * Format string to show value of global flag
53 #define SHOW_FLAG_VALUE(x) _T(" %-38s = %d\n"), _T(#x), (g_flags & x) ? 1 : 0
56 * Messages generated by mc.pl (for UNIX version only)
59 extern unsigned int g_dwNumMessages
;
60 extern const TCHAR
*g_szMessages
[];
66 #define SHUTDOWN_DEFAULT 0
67 #define SHUTDOWN_FROM_CONSOLE 1
68 #define SHUTDOWN_BY_SIGNAL 2
73 extern Queue g_nodePollerQueue
;
74 extern Queue g_dataCollectionQueue
;
75 extern Queue g_dciCacheLoaderQueue
;
76 extern Queue g_syslogProcessingQueue
;
77 extern Queue g_syslogWriteQueue
;
78 extern ThreadPool
*g_pollerThreadPool
;
79 extern ThreadPool
*g_schedulerThreadPool
;
81 void InitClientListeners();
82 void InitMobileDeviceListeners();
83 void InitCertificates();
86 void LoadPerfDataStorageDrivers();
87 void ImportLocalConfiguration();
89 void ExecuteScheduledScript(const ScheduledTaskParameters
*param
);
90 void MaintenanceModeEnter(const ScheduledTaskParameters
*params
);
91 void MaintenanceModeLeave(const ScheduledTaskParameters
*params
);
94 void StartXMPPConnector();
95 void StopXMPPConnector();
99 * Syslog server control
101 void StartSyslogServer();
102 void StopSyslogServer();
105 * Housekeeper control
107 void StartHouseKeeper();
108 void StopHouseKeeper();
109 void RunHouseKeeper();
114 THREAD_RESULT THREAD_CALL
Syncer(void *);
115 THREAD_RESULT THREAD_CALL
NodePoller(void *);
116 THREAD_RESULT THREAD_CALL
PollManager(void *);
117 THREAD_RESULT THREAD_CALL
EventProcessor(void *);
118 THREAD_RESULT THREAD_CALL
WatchdogThread(void *);
119 THREAD_RESULT THREAD_CALL
ClientListener(void *);
120 THREAD_RESULT THREAD_CALL
ClientListenerIPv6(void *);
121 THREAD_RESULT THREAD_CALL
MobileDeviceListener(void *);
122 THREAD_RESULT THREAD_CALL
MobileDeviceListenerIPv6(void *);
123 THREAD_RESULT THREAD_CALL
ISCListener(void *);
124 THREAD_RESULT THREAD_CALL
LocalAdminListener(void *);
125 THREAD_RESULT THREAD_CALL
SNMPTrapReceiver(void *);
126 THREAD_RESULT THREAD_CALL
BeaconPoller(void *);
127 THREAD_RESULT THREAD_CALL
JobManagerThread(void *);
128 THREAD_RESULT THREAD_CALL
UptimeCalculator(void *);
129 THREAD_RESULT THREAD_CALL
ReportingServerConnector(void *);
134 TCHAR NXCORE_EXPORTABLE g_szConfigFile
[MAX_PATH
] = _T("{search}");
135 TCHAR NXCORE_EXPORTABLE g_szLogFile
[MAX_PATH
] = DEFAULT_LOG_FILE
;
136 UINT32 g_dwLogRotationMode
= NXLOG_ROTATION_BY_SIZE
;
137 UINT32 g_dwMaxLogSize
= 16384 * 1024;
138 UINT32 g_dwLogHistorySize
= 4;
139 TCHAR g_szDailyLogFileSuffix
[64] = _T("");
140 TCHAR NXCORE_EXPORTABLE g_szDumpDir
[MAX_PATH
] = DEFAULT_DUMP_DIR
;
141 char g_szCodePage
[256] = ICONV_DEFAULT_CODEPAGE
;
142 TCHAR NXCORE_EXPORTABLE g_szListenAddress
[MAX_PATH
] = _T("*");
144 TCHAR NXCORE_EXPORTABLE g_szPIDFile
[MAX_PATH
] = _T("/var/run/netxmsd.pid");
146 UINT32 g_dwDiscoveryPollingInterval
;
147 UINT32 g_dwStatusPollingInterval
;
148 UINT32 g_dwConfigurationPollingInterval
;
149 UINT32 g_dwRoutingTableUpdateInterval
;
150 UINT32 g_dwTopologyPollingInterval
;
151 UINT32 g_dwConditionPollingInterval
;
152 UINT32 g_instancePollingInterval
;
153 UINT32 g_icmpPingSize
;
154 UINT32 g_icmpPingTimeout
= 1500; // ICMP ping timeout (milliseconds)
156 UINT32 g_slmPollingInterval
;
157 TCHAR NXCORE_EXPORTABLE g_netxmsdDataDir
[MAX_PATH
] = _T("");
158 TCHAR NXCORE_EXPORTABLE g_netxmsdLibDir
[MAX_PATH
] = _T("");
159 int g_dbSyntax
= DB_SYNTAX_UNKNOWN
;
160 UINT32 NXCORE_EXPORTABLE g_processAffinityMask
= DEFAULT_AFFINITY_MASK
;
161 UINT64 g_serverId
= 0;
162 RSA
*g_pServerKey
= NULL
;
163 time_t g_serverStartTime
= 0;
164 UINT32 g_lockTimeout
= 60000; // Default timeout for acquiring mutex
165 UINT32 g_agentCommandTimeout
= 4000; // Default timeout for requests to agent
166 UINT32 g_thresholdRepeatInterval
= 0; // Disabled by default
167 int g_requiredPolls
= 1;
168 DB_DRIVER g_dbDriver
= NULL
;
169 ThreadPool
*g_mainThreadPool
= NULL
;
170 INT16 g_defaultAgentCacheMode
= AGENT_CACHE_OFF
;
175 static CONDITION m_condShutdown
= INVALID_CONDITION_HANDLE
;
176 static THREAD m_thPollManager
= INVALID_THREAD_HANDLE
;
177 static THREAD m_thSyncer
= INVALID_THREAD_HANDLE
;
178 static int m_nShutdownReason
= SHUTDOWN_DEFAULT
;
181 static pthread_t m_signalHandlerThread
;
185 * Sleep for specified number of seconds or until system shutdown arrives
186 * Function will return TRUE if shutdown event occurs
188 * @param seconds seconds to sleep
189 * @return true if server is shutting down
191 bool NXCORE_EXPORTABLE
SleepAndCheckForShutdown(int seconds
)
193 return ConditionWait(m_condShutdown
, seconds
* 1000);
197 * Disconnect from database (exportable function for startup module)
199 void NXCORE_EXPORTABLE
ShutdownDB()
201 DBConnectionPoolShutdown();
202 DBUnloadDriver(g_dbDriver
);
206 * Check data directory for existence
208 static BOOL
CheckDataDir()
210 TCHAR szBuffer
[MAX_PATH
];
212 if (_tchdir(g_netxmsdDataDir
) == -1)
214 nxlog_write(MSG_INVALID_DATA_DIR
, EVENTLOG_ERROR_TYPE
, "s", g_netxmsdDataDir
);
219 #define MKDIR(name) _tmkdir(name)
221 #define MKDIR(name) _tmkdir(name, 0700)
224 // Create directory for package files if it doesn't exist
225 _tcscpy(szBuffer
, g_netxmsdDataDir
);
226 _tcscat(szBuffer
, DDIR_PACKAGES
);
227 if (MKDIR(szBuffer
) == -1)
230 nxlog_write(MSG_ERROR_CREATING_DATA_DIR
, EVENTLOG_ERROR_TYPE
, "s", szBuffer
);
234 // Create directory for map background images if it doesn't exist
235 _tcscpy(szBuffer
, g_netxmsdDataDir
);
236 _tcscat(szBuffer
, DDIR_BACKGROUNDS
);
237 if (MKDIR(szBuffer
) == -1)
240 nxlog_write(MSG_ERROR_CREATING_DATA_DIR
, EVENTLOG_ERROR_TYPE
, "s", szBuffer
);
244 // Create directory for image library is if does't exists
245 _tcscpy(szBuffer
, g_netxmsdDataDir
);
246 _tcscat(szBuffer
, DDIR_IMAGES
);
247 if (MKDIR(szBuffer
) == -1)
251 nxlog_write(MSG_ERROR_CREATING_DATA_DIR
, EVENTLOG_ERROR_TYPE
, "s", szBuffer
);
256 // Create directory for file store if does't exists
257 _tcscpy(szBuffer
, g_netxmsdDataDir
);
258 _tcscat(szBuffer
, DDIR_FILES
);
259 if (MKDIR(szBuffer
) == -1)
263 nxlog_write(MSG_ERROR_CREATING_DATA_DIR
, EVENTLOG_ERROR_TYPE
, "s", szBuffer
);
274 * Load global configuration parameters
276 static void LoadGlobalConfig()
278 g_dwDiscoveryPollingInterval
= ConfigReadInt(_T("DiscoveryPollingInterval"), 900);
279 g_dwStatusPollingInterval
= ConfigReadInt(_T("StatusPollingInterval"), 60);
280 g_dwConfigurationPollingInterval
= ConfigReadInt(_T("ConfigurationPollingInterval"), 3600);
281 g_instancePollingInterval
= ConfigReadInt(_T("InstancePollingInterval"), 600);
282 g_dwRoutingTableUpdateInterval
= ConfigReadInt(_T("RoutingTableUpdateInterval"), 300);
283 g_dwTopologyPollingInterval
= ConfigReadInt(_T("TopologyPollingInterval"), 1800);
284 g_dwConditionPollingInterval
= ConfigReadInt(_T("ConditionPollingInterval"), 60);
285 g_slmPollingInterval
= ConfigReadInt(_T("SlmPollingInterval"), 60);
286 DCObject::m_defaultPollingInterval
= ConfigReadInt(_T("DefaultDCIPollingInterval"), 60);
287 DCObject::m_defaultRetentionTime
= ConfigReadInt(_T("DefaultDCIRetentionTime"), 30);
288 g_defaultAgentCacheMode
= (INT16
)ConfigReadInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF
);
289 if ((g_defaultAgentCacheMode
!= AGENT_CACHE_ON
) && (g_defaultAgentCacheMode
!= AGENT_CACHE_OFF
))
291 DbgPrintf(1, _T("Invalid value %d of DefaultAgentCacheMode: reset to %d (OFF)"), g_defaultAgentCacheMode
, AGENT_CACHE_OFF
);
292 ConfigWriteInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF
, true, true, true);
293 g_defaultAgentCacheMode
= AGENT_CACHE_OFF
;
295 if (ConfigReadInt(_T("DeleteEmptySubnets"), 1))
296 g_flags
|= AF_DELETE_EMPTY_SUBNETS
;
297 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
298 g_flags
|= AF_ENABLE_SNMP_TRAPD
;
299 if (ConfigReadInt(_T("ProcessTrapsFromUnmanagedNodes"), 0))
300 g_flags
|= AF_TRAPS_FROM_UNMANAGED_NODES
;
301 if (ConfigReadInt(_T("EnableZoning"), 0))
302 g_flags
|= AF_ENABLE_ZONING
;
303 if (ConfigReadInt(_T("EnableObjectTransactions"), 0))
304 g_flags
|= AF_ENABLE_OBJECT_TRANSACTIONS
;
305 if (ConfigReadInt(_T("RunNetworkDiscovery"), 0))
306 g_flags
|= AF_ENABLE_NETWORK_DISCOVERY
;
307 if (ConfigReadInt(_T("ActiveNetworkDiscovery"), 0))
308 g_flags
|= AF_ACTIVE_NETWORK_DISCOVERY
;
309 if (ConfigReadInt(_T("UseSNMPTrapsForDiscovery"), 0))
310 g_flags
|= AF_SNMP_TRAP_DISCOVERY
;
311 if (ConfigReadInt(_T("ResolveNodeNames"), 1))
312 g_flags
|= AF_RESOLVE_NODE_NAMES
;
313 if (ConfigReadInt(_T("SyncNodeNamesWithDNS"), 0))
314 g_flags
|= AF_SYNC_NODE_NAMES_WITH_DNS
;
315 if (ConfigReadInt(_T("CheckTrustedNodes"), 1))
316 g_flags
|= AF_CHECK_TRUSTED_NODES
;
317 if (ConfigReadInt(_T("EnableNXSLContainerFunctions"), 1))
318 g_flags
|= AF_ENABLE_NXSL_CONTAINER_FUNCS
;
319 if (ConfigReadInt(_T("UseFQDNForNodeNames"), 1))
320 g_flags
|= AF_USE_FQDN_FOR_NODE_NAMES
;
321 if (ConfigReadInt(_T("ApplyDCIFromTemplateToDisabledDCI"), 1))
322 g_flags
|= AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE
;
323 if (ConfigReadInt(_T("ResolveDNSToIPOnStatusPoll"), 0))
324 g_flags
|= AF_RESOLVE_IP_FOR_EACH_STATUS_POLL
;
325 if (ConfigReadInt(_T("CaseInsensitiveLoginNames"), 0))
326 g_flags
|= AF_CASE_INSENSITIVE_LOGINS
;
327 if (ConfigReadInt(_T("TrapSourcesInAllZones"), 0))
328 g_flags
|= AF_TRAP_SOURCES_IN_ALL_ZONES
;
330 if (g_netxmsdDataDir
[0] == 0)
332 GetNetXMSDirectory(nxDirData
, g_netxmsdDataDir
);
333 DbgPrintf(1, _T("Data directory set to %s"), g_netxmsdDataDir
);
337 DbgPrintf(1, _T("Using data directory %s"), g_netxmsdDataDir
);
340 g_icmpPingTimeout
= ConfigReadInt(_T("IcmpPingTimeout"), 1500);
341 g_icmpPingSize
= ConfigReadInt(_T("IcmpPingSize"), 46);
342 g_lockTimeout
= ConfigReadInt(_T("LockTimeout"), 60000);
343 g_agentCommandTimeout
= ConfigReadInt(_T("AgentCommandTimeout"), 4000);
344 g_thresholdRepeatInterval
= ConfigReadInt(_T("ThresholdRepeatInterval"), 0);
345 g_requiredPolls
= ConfigReadInt(_T("PollCountForStatusChange"), 1);
347 UINT32 snmpTimeout
= ConfigReadInt(_T("SNMPRequestTimeout"), 1500);
348 SnmpSetDefaultTimeout(snmpTimeout
);
352 * Initialize cryptografic functions
354 static BOOL
InitCryptografy()
356 #ifdef _WITH_ENCRYPTION
357 TCHAR szKeyFile
[MAX_PATH
];
358 BOOL bResult
= FALSE
;
361 BYTE
*pBufPos
, *pKeyBuffer
, hash
[SHA1_DIGEST_SIZE
];
363 if (!InitCryptoLib(ConfigReadULong(_T("AllowedCiphers"), 0x7F), DbgPrintf2
))
365 DbgPrintf(4, _T("Supported ciphers: %s"), (const TCHAR
*)NXCPGetSupportedCiphersAsText());
368 SSL_load_error_strings();
370 _tcscpy(szKeyFile
, g_netxmsdDataDir
);
371 _tcscat(szKeyFile
, DFILE_KEYS
);
372 fd
= _topen(szKeyFile
, O_RDONLY
| O_BINARY
);
373 g_pServerKey
= LoadRSAKeys(szKeyFile
);
374 if (g_pServerKey
== NULL
)
376 DbgPrintf(1, _T("Generating RSA key pair..."));
377 g_pServerKey
= RSA_generate_key(NETXMS_RSA_KEYLEN
, 17, NULL
, 0);
378 if (g_pServerKey
!= NULL
)
380 fd
= _topen(szKeyFile
, O_WRONLY
| O_BINARY
| O_CREAT
| O_TRUNC
, 0600);
383 dwLen
= i2d_RSAPublicKey(g_pServerKey
, NULL
);
384 dwLen
+= i2d_RSAPrivateKey(g_pServerKey
, NULL
);
385 pKeyBuffer
= (BYTE
*)malloc(dwLen
);
387 pBufPos
= pKeyBuffer
;
388 i2d_RSAPublicKey(g_pServerKey
, &pBufPos
);
389 i2d_RSAPrivateKey(g_pServerKey
, &pBufPos
);
390 write(fd
, &dwLen
, sizeof(UINT32
));
391 write(fd
, pKeyBuffer
, dwLen
);
393 CalculateSHA1Hash(pKeyBuffer
, dwLen
, hash
);
394 write(fd
, hash
, SHA1_DIGEST_SIZE
);
402 DbgPrintf(0, _T("Failed to open %s for writing"), szKeyFile
);
407 DbgPrintf(0, _T("Failed to generate RSA key"));
415 iPolicy
= ConfigReadInt(_T("DefaultEncryptionPolicy"), 1);
416 if ((iPolicy
< 0) || (iPolicy
> 3))
418 SetAgentDEP(iPolicy
);
427 * Check if process with given PID exists and is a NetXMS server process
429 static BOOL
IsNetxmsdProcess(UINT32 dwPID
)
433 TCHAR szExtModule
[MAX_PATH
], szIntModule
[MAX_PATH
];
436 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, dwPID
);
437 if (hProcess
!= NULL
)
439 if ((GetModuleBaseName(hProcess
, NULL
, szExtModule
, MAX_PATH
) > 0) &&
440 (GetModuleBaseName(GetCurrentProcess(), NULL
, szIntModule
, MAX_PATH
) > 0))
442 bRet
= !_tcsicmp(szExtModule
, szIntModule
);
446 // Cannot read process name, for safety assume that it's a server process
449 CloseHandle(hProcess
);
453 return (kill((pid_t
)dwPID
, 0) != -1);
458 * Database event handler
460 static void DBEventHandler(DWORD dwEvent
, const WCHAR
*pszArg1
, const WCHAR
*pszArg2
, bool connLost
, void *userArg
)
462 if (!(g_flags
& AF_SERVER_INITIALIZED
))
463 return; // Don't try to do anything if server is not ready yet
467 case DBEVENT_CONNECTION_LOST
:
468 PostEvent(EVENT_DB_CONNECTION_LOST
, g_dwMgmtNode
, NULL
);
469 g_flags
|= AF_DB_CONNECTION_LOST
;
470 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS
, FALSE
);
472 case DBEVENT_CONNECTION_RESTORED
:
473 PostEvent(EVENT_DB_CONNECTION_RESTORED
, g_dwMgmtNode
, NULL
);
474 g_flags
&= ~AF_DB_CONNECTION_LOST
;
475 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS
, TRUE
);
477 case DBEVENT_QUERY_FAILED
:
478 PostEvent(EVENT_DB_QUERY_FAILED
, g_dwMgmtNode
, "uud", pszArg1
, pszArg2
, connLost
? 1 : 0);
486 * Send console message to session with open console
488 static void SendConsoleMessage(ClientSession
*session
, void *arg
)
490 if (session
->isConsoleOpen())
494 msg
.setCode(CMD_ADM_MESSAGE
);
495 msg
.setField(VID_MESSAGE
, (TCHAR
*)arg
);
496 session
->postMessage(&msg
);
503 static void LogConsoleWriter(const TCHAR
*format
, ...)
508 va_start(args
, format
);
509 _vsntprintf(buffer
, 8192, format
, args
);
513 WriteToTerminal(buffer
);
515 EnumerateClientSessions(SendConsoleMessage
, buffer
);
519 * Oracle session init callback
521 static void OracleSessionInitCallback(DB_HANDLE hdb
)
523 DBQuery(hdb
, _T("ALTER SESSION SET DDL_LOCK_TIMEOUT = 60"));
527 * Server initialization
529 BOOL NXCORE_EXPORTABLE
Initialize()
534 g_serverStartTime
= time(NULL
);
535 srand((unsigned int)g_serverStartTime
);
537 if (g_netxmsdLibDir
[0] == 0)
539 GetNetXMSDirectory(nxDirLib
, g_netxmsdLibDir
);
540 DbgPrintf(1, _T("Lib directory set to %s"), g_netxmsdLibDir
);
543 if (!(g_flags
& AF_USE_SYSLOG
))
545 if (!nxlog_set_rotation_policy((int)g_dwLogRotationMode
, (int)g_dwMaxLogSize
, (int)g_dwLogHistorySize
, g_szDailyLogFileSuffix
))
546 if (!(g_flags
& AF_DAEMON
))
547 _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n"));
549 if (!nxlog_open((g_flags
& AF_USE_SYSLOG
) ? NETXMSD_SYSLOG_NAME
: g_szLogFile
,
550 ((g_flags
& AF_USE_SYSLOG
) ? NXLOG_USE_SYSLOG
: 0) |
551 ((g_flags
& AF_BACKGROUND_LOG_WRITER
) ? NXLOG_BACKGROUND_WRITER
: 0) |
552 ((g_flags
& AF_DAEMON
) ? 0 : NXLOG_PRINT_TO_STDOUT
),
557 g_dwNumMessages
, g_szMessages
))
560 _ftprintf(stderr
, _T("FATAL ERROR: Cannot open log file\n"));
563 nxlog_set_console_writer(LogConsoleWriter
);
567 if (SetDefaultCodepage(g_szCodePage
))
569 DbgPrintf(1, _T("Code page set to %hs"), g_szCodePage
);
573 nxlog_write(MSG_CODEPAGE_ERROR
, EVENTLOG_WARNING_TYPE
, "m", g_szCodePage
);
577 // Set process affinity mask
578 if (g_processAffinityMask
!= DEFAULT_AFFINITY_MASK
)
581 if (SetProcessAffinityMask(GetCurrentProcess(), g_processAffinityMask
))
582 DbgPrintf(1, _T("Process affinity mask set to 0x%08X"), g_processAffinityMask
);
584 nxlog_write(MSG_SET_PROCESS_AFFINITY_NOT_SUPPORTED
, EVENTLOG_WARNING_TYPE
, NULL
);
590 int wrc
= WSAStartup(MAKEWORD(2, 2), &wsaData
);
593 nxlog_write(MSG_WSASTARTUP_FAILED
, EVENTLOG_ERROR_TYPE
, "e", wrc
);
599 SnmpSetMessageIds(MSG_OID_PARSE_ERROR
, MSG_SNMP_UNKNOWN_TYPE
, MSG_SNMP_GET_ERROR
);
601 // Create queue for delayed SQL queries
602 g_dbWriterQueue
= new Queue(256, 64);
603 g_dciDataWriterQueue
= new Queue(1024, 1024);
604 g_dciRawDataWriterQueue
= new Queue(1024, 1024);
606 // Initialize database driver and connect to database
607 DBSetDebugPrintCallback(DbgPrintf2
);
608 if (!DBInit(MSG_OTHER
, (g_flags
& AF_LOG_SQL_ERRORS
) ? MSG_SQL_ERROR
: 0))
610 g_dbDriver
= DBLoadDriver(g_szDbDriver
, g_szDbDrvParams
, (g_debugLevel
>= 9), DBEventHandler
, NULL
);
611 if (g_dbDriver
== NULL
)
614 // Connect to database
615 DB_HANDLE hdbBootstrap
= NULL
;
616 TCHAR errorText
[DBDRV_MAX_ERROR_TEXT
];
619 hdbBootstrap
= DBConnect(g_dbDriver
, g_szDbServer
, g_szDbName
, g_szDbLogin
, g_szDbPassword
, g_szDbSchema
, errorText
);
620 if ((hdbBootstrap
!= NULL
) || (i
== 5))
624 if (hdbBootstrap
== NULL
)
626 nxlog_write(MSG_DB_CONNFAIL
, EVENTLOG_ERROR_TYPE
, "s", errorText
);
629 DbgPrintf(1, _T("Successfully connected to database %s@%s"), g_szDbName
, g_szDbServer
);
631 // Check database version
632 iDBVersion
= DBGetSchemaVersion(hdbBootstrap
);
633 if (iDBVersion
!= DB_FORMAT_VERSION
)
635 nxlog_write(MSG_WRONG_DB_VERSION
, EVENTLOG_ERROR_TYPE
, "dd", iDBVersion
, DB_FORMAT_VERSION
);
636 DBDisconnect(hdbBootstrap
);
640 // Read database syntax
641 g_dbSyntax
= DBGetSyntax(hdbBootstrap
);
642 if (g_dbSyntax
== DB_SYNTAX_ORACLE
)
644 DBSetSessionInitCallback(OracleSessionInitCallback
);
647 int baseSize
= ConfigReadIntEx(hdbBootstrap
, _T("DBConnectionPoolBaseSize"), 10);
648 int maxSize
= ConfigReadIntEx(hdbBootstrap
, _T("DBConnectionPoolMaxSize"), 30);
649 int cooldownTime
= ConfigReadIntEx(hdbBootstrap
, _T("DBConnectionPoolCooldownTime"), 300);
650 int ttl
= ConfigReadIntEx(hdbBootstrap
, _T("DBConnectionPoolMaxLifetime"), 14400);
652 DBDisconnect(hdbBootstrap
);
654 if (!DBConnectionPoolStartup(g_dbDriver
, g_szDbServer
, g_szDbName
, g_szDbLogin
, g_szDbPassword
, g_szDbSchema
, baseSize
, maxSize
, cooldownTime
, ttl
))
656 nxlog_write(MSG_DBCONNPOOL_INIT_FAILED
, EVENTLOG_ERROR_TYPE
, NULL
);
660 UINT32 lrt
= ConfigReadULong(_T("LongRunningQueryThreshold"), 0);
662 DBSetLongRunningThreshold(lrt
);
665 MetaDataReadStr(_T("ServerID"), szInfo
, 256, _T(""));
669 g_serverId
= _tcstoull(szInfo
, NULL
, 16);
674 g_serverId
= ((UINT64
)time(NULL
) << 31) | (UINT64
)((UINT32
)rand() & 0x7FFFFFFF);
675 _sntprintf(szInfo
, 256, UINT64X_FMT(_T("016")), g_serverId
);
676 MetaDataWriteStr(_T("ServerID"), szInfo
);
678 DbgPrintf(1, _T("Server ID ") UINT64X_FMT(_T("016")), g_serverId
);
683 if (!InitLocks(&addr
, szInfo
))
685 if (!addr
.isValid()) // Some SQL problems
687 nxlog_write(MSG_INIT_LOCKS_FAILED
, EVENTLOG_ERROR_TYPE
, NULL
);
689 else // Database already locked by another server instance
691 // Check for lock from crashed/terminated local process
692 if (GetLocalIpAddr().equals(addr
))
696 dwPID
= ConfigReadULong(_T("DBLockPID"), 0);
697 if (!IsNetxmsdProcess(dwPID
) || (dwPID
== GetCurrentProcessId()))
700 nxlog_write(MSG_DB_LOCK_REMOVED
, EVENTLOG_INFORMATION_TYPE
, NULL
);
704 nxlog_write(MSG_DB_LOCKED
, EVENTLOG_ERROR_TYPE
, "As", &addr
, szInfo
);
708 g_flags
|= AF_DB_LOCKED
;
710 // Load global configuration parameters
713 DbgPrintf(1, _T("Global configuration loaded"));
715 // Check data directory
719 // Initialize cryptografy
720 if (!InitCryptografy())
722 nxlog_write(MSG_INIT_CRYPTO_FAILED
, EVENTLOG_ERROR_TYPE
, NULL
);
726 // Initialize certificate store and CA
729 // Create synchronization stuff
730 m_condShutdown
= ConditionCreate(TRUE
);
732 // Create thread pools
733 DbgPrintf(2, _T("Creating thread pools"));
734 ThreadPoolSetDebugCallback(DbgPrintf2
);
735 g_mainThreadPool
= ThreadPoolCreate(8, 256, _T("MAIN"));
736 g_agentConnectionThreadPool
= ThreadPoolCreate(4, 256, _T("AGENT"));
738 // Setup unique identifiers table
741 DbgPrintf(2, _T("ID table created"));
743 // Update status for unfinished jobs in job history
744 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
745 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)"));
746 DBConnectionPoolReleaseConnection(hdb
);
748 // Load and compile scripts
751 // Initialize watchdog
755 if (!LoadNetXMSModules())
756 return FALSE
; // Mandatory module not loaded
758 // Initialize mailer and SMS sender
762 // Load users from database
766 nxlog_write(MSG_ERROR_LOADING_USERS
, EVENTLOG_ERROR_TYPE
, NULL
);
769 DbgPrintf(2, _T("User accounts loaded"));
774 // Initialize event handling subsystem
775 if (!InitEventSubsystem())
779 if (!InitAlarmManager())
782 // Initialize objects infrastructure and load objects from database
783 LoadNetworkDeviceDrivers();
787 DbgPrintf(1, _T("Objects loaded and initialized"));
789 // Initialize situations
790 if (!SituationsInit())
792 DbgPrintf(1, _T("Situations loaded and initialized"));
794 // Initialize and load event actions
797 nxlog_write(MSG_ACTION_INIT_ERROR
, EVENTLOG_ERROR_TYPE
, NULL
);
801 // Initialize helpdesk link
802 SetHDLinkEntryPoints(ResolveAlarmByHDRef
, TerminateAlarmByHDRef
);
805 // Initialize data collection subsystem
806 LoadPerfDataStorageDrivers();
807 if (!InitDataCollector())
811 FileUploadJob::init();
814 InitClientListeners();
815 if (ConfigReadInt(_T("ImportConfigurationOnStartup"), 1))
816 ImportLocalConfiguration();
818 // Check if management node object presented in database
820 if (g_dwMgmtNode
== 0)
822 nxlog_write(MSG_CANNOT_FIND_SELF
, EVENTLOG_ERROR_TYPE
, NULL
);
827 ThreadCreate(WatchdogThread
, 0, NULL
);
828 ThreadCreate(NodePoller
, 0, NULL
);
829 ThreadCreate(JobManagerThread
, 0, NULL
);
830 m_thSyncer
= ThreadCreateEx(Syncer
, 0, NULL
);
831 m_thPollManager
= ThreadCreateEx(PollManager
, 0, NULL
);
835 // Start event processor
836 ThreadCreate(EventProcessor
, 0, NULL
);
838 // Start SNMP trapper
840 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
841 ThreadCreate(SNMPTrapReceiver
, 0, NULL
);
843 // Start built-in syslog daemon
844 if (ConfigReadInt(_T("EnableSyslogDaemon"), 0))
847 // Start database _T("lazy") write thread
850 // Start local administartive interface listener if required
851 if (ConfigReadInt(_T("EnableAdminInterface"), 1))
852 ThreadCreate(LocalAdminListener
, 0, NULL
);
854 // Start beacon host poller
855 ThreadCreate(BeaconPoller
, 0, NULL
);
857 // Start inter-server communication listener
858 if (ConfigReadInt(_T("EnableISCListener"), 0))
859 ThreadCreate(ISCListener
, 0, NULL
);
861 // Start reporting server connector
862 if (ConfigReadInt(_T("EnableReportingServer"), 0))
863 ThreadCreate(ReportingServerConnector
, 0, NULL
);
865 //Start ldap synchronization
866 if (ConfigReadInt(_T("LdapSyncInterval"), 0))
867 ThreadCreate(SyncLDAPUsers
, 0, NULL
);
869 RegisterSchedulerTaskHandler(_T("Execute.Script"), ExecuteScheduledScript
, SYSTEM_ACCESS_SCHEDULE_SCRIPT
);
870 RegisterSchedulerTaskHandler(_T("Maintenance.Enter"), MaintenanceModeEnter
, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE
);
871 RegisterSchedulerTaskHandler(_T("Maintenance.Leave"), MaintenanceModeLeave
, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE
);
872 InitializeTaskScheduler();
874 // Allow clients to connect
875 ThreadCreate(ClientListener
, 0, NULL
);
877 ThreadCreate(ClientListenerIPv6
, 0, NULL
);
880 // Allow mobile devices to connect
881 InitMobileDeviceListeners();
882 ThreadCreate(MobileDeviceListener
, 0, NULL
);
884 ThreadCreate(MobileDeviceListenerIPv6
, 0, NULL
);
887 // Start uptime calculator for SLM
888 ThreadCreate(UptimeCalculator
, 0, NULL
);
890 DbgPrintf(2, _T("LIBDIR: %s"), g_netxmsdLibDir
);
892 // Call startup functions for the modules
893 CALL_ALL_MODULES(pfServerStarted
, ());
896 if (ConfigReadInt(_T("EnableXMPPConnector"), 1))
898 StartXMPPConnector();
906 g_flags
|= AF_SERVER_INITIALIZED
;
907 DbgPrintf(1, _T("Server initialization completed"));
914 void NXCORE_EXPORTABLE
Shutdown()
917 NotifyClientSessions(NX_NOTIFY_SHUTDOWN
, 0);
919 nxlog_write(MSG_SERVER_STOPPED
, EVENTLOG_INFORMATION_TYPE
, NULL
);
920 g_flags
|= AF_SHUTDOWN
; // Set shutdown flag
921 ConditionSet(m_condShutdown
);
923 CloseTaskScheduler();
925 // Stop DCI cache loading thread
926 g_dciCacheLoaderQueue
.setShutdownMode();
936 g_pEventQueue
->clear();
937 g_pEventQueue
->put(INVALID_POINTER_VALUE
);
942 ThreadSleep(1); // Give other threads a chance to terminate in a safe way
943 DbgPrintf(2, _T("All threads was notified, continue with shutdown"));
948 // Wait for critical threads
949 ThreadJoin(m_thPollManager
);
950 ThreadJoin(m_thSyncer
);
952 // Call shutdown functions for the modules
953 // CALL_ALL_MODULES cannot be used here because it checks for shutdown flag
954 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
956 if (g_pModuleList
[i
].pfShutdown
!= NULL
)
957 g_pModuleList
[i
].pfShutdown();
960 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
962 DbgPrintf(2, _T("All objects saved to database"));
964 DbgPrintf(2, _T("All users saved to database"));
965 DBConnectionPoolReleaseConnection(hdb
);
968 DbgPrintf(1, _T("Database writer stopped"));
972 // Remove database lock
975 DBConnectionPoolShutdown();
976 DBUnloadDriver(g_dbDriver
);
977 DbgPrintf(1, _T("Database driver unloaded"));
980 ShutdownEventSubsystem();
981 ShutdownAlarmManager();
982 DbgPrintf(1, _T("Event processing stopped"));
984 ThreadPoolDestroy(g_agentConnectionThreadPool
);
985 ThreadPoolDestroy(g_mainThreadPool
);
986 MsgWaitQueue::shutdown();
988 delete g_pScriptLibrary
;
990 DbgPrintf(1, _T("Server shutdown complete"));
995 _tremove(g_szPIDFile
);
1000 if (!(g_flags
& AF_DAEMON
))
1008 * Fast server shutdown - normally called only by Windows service on system shutdown
1010 void NXCORE_EXPORTABLE
FastShutdown()
1012 DbgPrintf(1, _T("Using fast shutdown procedure"));
1014 g_flags
|= AF_SHUTDOWN
; // Set shutdown flag
1015 ConditionSet(m_condShutdown
);
1017 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
1019 DbgPrintf(2, _T("All objects saved to database"));
1021 DbgPrintf(2, _T("All users saved to database"));
1022 DBConnectionPoolReleaseConnection(hdb
);
1024 // Remove database lock first, because we have a chance to lose DB connection
1027 // Stop database writers
1029 DbgPrintf(1, _T("Database writer stopped"));
1031 DbgPrintf(1, _T("Server shutdown complete"));
1036 * Compare given string to command template with abbreviation possibility
1038 static bool IsCommand(const TCHAR
*cmdTemplate
, TCHAR
*pszString
, int iMinChars
)
1042 // Convert given string to uppercase
1045 for(i
= 0; pszString
[i
] != 0; i
++)
1046 if (pszString
[i
] != cmdTemplate
[i
])
1054 * Dump index callback (by IP address)
1056 static void DumpIndexCallbackByInetAddr(const InetAddress
& addr
, NetObj
*object
, void *data
)
1059 ConsolePrintf((CONSOLE_CTX
)data
, _T("%-40s %p %s [%d]\n"), addr
.toString(buffer
), object
, object
->getName(), (int)object
->getId());
1063 * Dump index (by IP address)
1065 static void DumpIndex(CONSOLE_CTX pCtx
, InetAddressIndex
*index
)
1067 index
->forEach(DumpIndexCallbackByInetAddr
, pCtx
);
1071 * Dump index callback (by ID)
1073 static void DumpIndexCallbackById(NetObj
*object
, void *data
)
1075 ConsolePrintf((CONSOLE_CTX
)data
, _T("%08X %p %s\n"), object
->getId(), object
, object
->getName());
1079 * Dump index (by ID)
1081 static void DumpIndex(CONSOLE_CTX pCtx
, ObjectIndex
*index
)
1083 index
->forEach(DumpIndexCallbackById
, pCtx
);
1087 * Process command entered from command line in standalone mode
1088 * Return TRUE if command was _T("down")
1090 int ProcessConsoleCommand(const TCHAR
*pszCmdLine
, CONSOLE_CTX pCtx
)
1093 TCHAR szBuffer
[256], *eptr
;
1094 int nExitCode
= CMD_EXIT_CONTINUE
;
1097 pArg
= ExtractWord(pszCmdLine
, szBuffer
);
1099 if (IsCommand(_T("AT"), szBuffer
, 2))
1101 pArg
= ExtractWord(pArg
, szBuffer
);
1102 if (szBuffer
[0] == _T('+'))
1104 int offset
= _tcstoul(&szBuffer
[1], NULL
, 0);
1105 AddOneTimeScheduledTask(_T("Execute.Script"), time(NULL
) + offset
, pArg
, 0, 0, SYSTEM_ACCESS_FULL
);//TODO: change to correct user
1109 AddScheduledTask(_T("Execute.Script"), szBuffer
, pArg
, 0, 0, SYSTEM_ACCESS_FULL
); //TODO: change to correct user
1112 if (IsCommand(_T("DEBUG"), szBuffer
, 2))
1115 pArg
= ExtractWord(pArg
, szBuffer
);
1116 int level
= (int)_tcstol(szBuffer
, &eptr
, 0);
1117 if ((*eptr
== 0) && (level
>= 0) && (level
<= 9))
1119 g_debugLevel
= (UINT32
)level
;
1120 ConsolePrintf(pCtx
, (level
== 0) ? _T("Debug mode turned off\n") : _T("Debug level set to %d\n"), level
);
1122 else if (IsCommand(_T("OFF"), szBuffer
, 2))
1125 ConsoleWrite(pCtx
, _T("Debug mode turned off\n"));
1129 if (szBuffer
[0] == 0)
1130 ConsoleWrite(pCtx
, _T("ERROR: Missing argument\n\n"));
1132 ConsoleWrite(pCtx
, _T("ERROR: Invalid debug level\n\n"));
1135 else if (IsCommand(_T("DOWN"), szBuffer
, 4))
1137 ConsoleWrite(pCtx
, _T("Proceeding with server shutdown...\n"));
1138 nExitCode
= CMD_EXIT_SHUTDOWN
;
1140 else if (IsCommand(_T("DUMP"), szBuffer
, 4))
1144 else if (IsCommand(_T("GET"), szBuffer
, 3))
1146 pArg
= ExtractWord(pArg
, szBuffer
);
1147 if (szBuffer
[0] != 0)
1149 TCHAR value
[MAX_CONFIG_VALUE
];
1150 ConfigReadStr(szBuffer
, value
, MAX_CONFIG_VALUE
, _T(""));
1151 ConsolePrintf(pCtx
, _T("%s = %s\n"), szBuffer
, value
);
1155 ConsoleWrite(pCtx
, _T("Variable name missing\n"));
1158 else if (IsCommand(_T("HKRUN"), szBuffer
, 2))
1160 ConsoleWrite(pCtx
, _T("Starting housekeeper\n"));
1163 else if (IsCommand(_T("LDAPSYNC"), szBuffer
, 4))
1165 LDAPConnection conn
;
1168 else if (IsCommand(_T("LOG"), szBuffer
, 3))
1170 while(_istspace(*pArg
))
1173 DbgPrintf(0, _T("%s"), pArg
);
1175 else if (IsCommand(_T("LOGMARK"), szBuffer
, 4))
1177 DbgPrintf(0, _T("******* MARK *******"));
1179 else if (IsCommand(_T("RAISE"), szBuffer
, 5))
1182 pArg
= ExtractWord(pArg
, szBuffer
);
1184 if (IsCommand(_T("ACCESS"), szBuffer
, 6))
1186 ConsoleWrite(pCtx
, _T("Raising exception...\n"));
1190 else if (IsCommand(_T("BREAKPOINT"), szBuffer
, 5))
1193 ConsoleWrite(pCtx
, _T("Raising exception...\n"));
1194 RaiseException(EXCEPTION_BREAKPOINT
, 0, 0, NULL
);
1196 ConsoleWrite(pCtx
, _T("ERROR: Not supported on current platform\n"));
1201 ConsoleWrite(pCtx
, _T("Invalid exception name; possible names are:\nACCESS BREAKPOINT\n"));
1204 else if (IsCommand(_T("EXIT"), szBuffer
, 4))
1206 if ((pCtx
->hSocket
!= -1) || (pCtx
->session
!= NULL
))
1208 ConsoleWrite(pCtx
, _T("Closing session...\n"));
1209 nExitCode
= CMD_EXIT_CLOSE_SESSION
;
1213 ConsoleWrite(pCtx
, _T("Cannot exit from local server console\n"));
1216 else if (IsCommand(_T("KILL"), szBuffer
, 4))
1218 pArg
= ExtractWord(pArg
, szBuffer
);
1219 if (szBuffer
[0] != 0)
1221 int id
= _tcstol(szBuffer
, &eptr
, 10);
1224 if (KillClientSession(id
))
1226 ConsoleWrite(pCtx
, _T("Session killed\n"));
1230 ConsoleWrite(pCtx
, _T("Invalid session ID\n"));
1235 ConsoleWrite(pCtx
, _T("Invalid session ID\n"));
1240 ConsoleWrite(pCtx
, _T("Session ID missing\n"));
1243 else if (IsCommand(_T("PING"), szBuffer
, 4))
1245 pArg
= ExtractWord(pArg
, szBuffer
);
1246 if (szBuffer
[0] != 0)
1248 InetAddress addr
= InetAddress::parse(szBuffer
);
1252 UINT32 rc
= IcmpPing(addr
, 1, 2000, &rtt
, 128);
1256 ConsolePrintf(pCtx
, _T("Success, RTT = %d ms\n"), (int)rtt
);
1258 case ICMP_UNREACHEABLE
:
1259 ConsolePrintf(pCtx
, _T("Destination unreachable\n"));
1262 ConsolePrintf(pCtx
, _T("Request timeout\n"));
1264 case ICMP_RAW_SOCK_FAILED
:
1265 ConsolePrintf(pCtx
, _T("Cannot create raw socket\n"));
1267 case ICMP_API_ERROR
:
1268 ConsolePrintf(pCtx
, _T("API error\n"));
1271 ConsolePrintf(pCtx
, _T("ERROR %d\n"), (int)rc
);
1277 ConsoleWrite(pCtx
, _T("Invalid IP address\n"));
1282 ConsoleWrite(pCtx
, _T("Usage: PING <address>\n"));
1285 else if (IsCommand(_T("POLL"), szBuffer
, 2))
1287 pArg
= ExtractWord(pArg
, szBuffer
);
1288 if (szBuffer
[0] != 0)
1291 if (IsCommand(_T("CONFIGURATION"), szBuffer
, 1))
1295 else if (IsCommand(_T("STATUS"), szBuffer
, 1))
1299 else if (IsCommand(_T("TOPOLOGY"), szBuffer
, 1))
1310 pArg
= ExtractWord(pArg
, szBuffer
);
1311 UINT32 id
= _tcstoul(szBuffer
, NULL
, 0);
1314 Node
*node
= (Node
*)FindObjectById(id
, OBJECT_NODE
);
1320 node
->lockForConfigurationPoll();
1321 ThreadPoolExecute(g_pollerThreadPool
, node
, &Node::configurationPoll
, RegisterPoller(POLLER_TYPE_CONFIGURATION
, node
));
1324 node
->lockForStatusPoll();
1325 ThreadPoolExecute(g_pollerThreadPool
, node
, &Node::statusPoll
, RegisterPoller(POLLER_TYPE_STATUS
, node
));
1328 node
->lockForTopologyPoll();
1329 ThreadPoolExecute(g_pollerThreadPool
, node
, &Node::topologyPoll
, RegisterPoller(POLLER_TYPE_TOPOLOGY
, node
));
1335 ConsolePrintf(pCtx
, _T("ERROR: Node with ID %d does not exist\n\n"), id
);
1340 ConsoleWrite(pCtx
, _T("ERROR: Invalid or missing node ID\n\n"));
1345 ConsoleWrite(pCtx
, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
1350 ConsoleWrite(pCtx
, _T("Usage POLL [CONFIGURATION|STATUS|TOPOLOGY] <node>\n"));
1353 else if (IsCommand(_T("SET"), szBuffer
, 3))
1355 pArg
= ExtractWord(pArg
, szBuffer
);
1356 if (szBuffer
[0] != 0)
1359 pArg
= ExtractWord(pArg
, value
);
1360 if (ConfigWriteStr(szBuffer
, value
, TRUE
, TRUE
, TRUE
))
1362 ConsolePrintf(pCtx
, _T("Configuration variable %s updated\n"), szBuffer
);
1366 ConsolePrintf(pCtx
, _T("ERROR: cannot update configuration variable %s\n"), szBuffer
);
1371 ConsolePrintf(pCtx
, _T("Variable name missing\n"));
1374 else if (IsCommand(_T("SHOW"), szBuffer
, 2))
1377 pArg
= ExtractWord(pArg
, szBuffer
);
1379 if (IsCommand(_T("COMPONENTS"), szBuffer
, 1))
1382 pArg
= ExtractWord(pArg
, szBuffer
);
1383 UINT32 dwNode
= _tcstoul(szBuffer
, NULL
, 0);
1386 NetObj
*pObject
= FindObjectById(dwNode
);
1387 if (pObject
!= NULL
)
1389 if (pObject
->getObjectClass() == OBJECT_NODE
)
1391 ComponentTree
*components
= ((Node
*)pObject
)->getComponents();
1392 if (components
!= NULL
)
1394 components
->print(pCtx
);
1395 components
->decRefCount();
1399 ConsoleWrite(pCtx
, _T("ERROR: Node does not have physical component information\n\n"));
1404 ConsoleWrite(pCtx
, _T("ERROR: Object is not a node\n\n"));
1409 ConsolePrintf(pCtx
, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode
);
1414 ConsoleWrite(pCtx
, _T("ERROR: Invalid or missing node ID\n\n"));
1417 else if (IsCommand(_T("DBCP"), szBuffer
, 4))
1419 ObjectArray
<PoolConnectionInfo
> *list
= DBConnectionPoolGetConnectionList();
1420 for(int i
= 0; i
< list
->size(); i
++)
1422 PoolConnectionInfo
*c
= list
->get(i
);
1423 TCHAR accessTime
[64];
1424 struct tm
*ltm
= localtime(&c
->lastAccessTime
);
1425 _tcsftime(accessTime
, 64, _T("%d.%b.%Y %H:%M:%S"), ltm
);
1426 ConsolePrintf(pCtx
, _T("%p %s %hs:%d\n"), c
->handle
, accessTime
, c
->srcFile
, c
->srcLine
);
1428 ConsolePrintf(pCtx
, _T("%d database connections in use\n\n"), list
->size());
1431 else if (IsCommand(_T("DBSTATS"), szBuffer
, 3))
1433 LIBNXDB_PERF_COUNTERS counters
;
1434 DBGetPerfCounters(&counters
);
1435 ConsolePrintf(pCtx
, _T("SQL query counters:\n"));
1436 ConsolePrintf(pCtx
, _T(" Total .......... ") INT64_FMT
_T("\n"), counters
.totalQueries
);
1437 ConsolePrintf(pCtx
, _T(" SELECT ......... ") INT64_FMT
_T("\n"), counters
.selectQueries
);
1438 ConsolePrintf(pCtx
, _T(" Non-SELECT ..... ") INT64_FMT
_T("\n"), counters
.nonSelectQueries
);
1439 ConsolePrintf(pCtx
, _T(" Long running ... ") INT64_FMT
_T("\n"), counters
.longRunningQueries
);
1440 ConsolePrintf(pCtx
, _T(" Failed ......... ") INT64_FMT
_T("\n"), counters
.failedQueries
);
1442 ConsolePrintf(pCtx
, _T("Background writer requests:\n"));
1443 ConsolePrintf(pCtx
, _T(" DCI data ....... ") INT64_FMT
_T("\n"), g_idataWriteRequests
);
1444 ConsolePrintf(pCtx
, _T(" DCI raw data ... ") INT64_FMT
_T("\n"), g_rawDataWriteRequests
);
1445 ConsolePrintf(pCtx
, _T(" Others ......... ") INT64_FMT
_T("\n"), g_otherWriteRequests
);
1447 else if (IsCommand(_T("FDB"), szBuffer
, 3))
1450 pArg
= ExtractWord(pArg
, szBuffer
);
1451 UINT32 dwNode
= _tcstoul(szBuffer
, NULL
, 0);
1454 NetObj
*pObject
= FindObjectById(dwNode
);
1455 if (pObject
!= NULL
)
1457 if (pObject
->getObjectClass() == OBJECT_NODE
)
1459 ForwardingDatabase
*fdb
= ((Node
*)pObject
)->getSwitchForwardingDatabase();
1462 fdb
->print(pCtx
, (Node
*)pObject
);
1467 ConsoleWrite(pCtx
, _T("ERROR: Node does not have forwarding database information\n\n"));
1472 ConsoleWrite(pCtx
, _T("ERROR: Object is not a node\n\n"));
1477 ConsolePrintf(pCtx
, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode
);
1482 ConsoleWrite(pCtx
, _T("ERROR: Invalid or missing node ID\n\n"));
1485 else if (IsCommand(_T("FLAGS"), szBuffer
, 1))
1487 ConsolePrintf(pCtx
, _T("Flags: 0x") UINT64X_FMT(_T("016")) _T("\n"), g_flags
);
1488 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_DAEMON
));
1489 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_USE_SYSLOG
));
1490 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_ENABLE_NETWORK_DISCOVERY
));
1491 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_ACTIVE_NETWORK_DISCOVERY
));
1492 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_LOG_SQL_ERRORS
));
1493 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_DELETE_EMPTY_SUBNETS
));
1494 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_ENABLE_SNMP_TRAPD
));
1495 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_ENABLE_ZONING
));
1496 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_SYNC_NODE_NAMES_WITH_DNS
));
1497 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_CHECK_TRUSTED_NODES
));
1498 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_ENABLE_NXSL_CONTAINER_FUNCS
));
1499 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_USE_FQDN_FOR_NODE_NAMES
));
1500 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE
));
1501 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_DEBUG_CONSOLE_DISABLED
));
1502 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_ENABLE_OBJECT_TRANSACTIONS
));
1503 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_WRITE_FULL_DUMP
));
1504 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_RESOLVE_NODE_NAMES
));
1505 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_CATCH_EXCEPTIONS
));
1506 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_HELPDESK_LINK_ACTIVE
));
1507 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_DB_LOCKED
));
1508 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_DB_CONNECTION_LOST
));
1509 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_NO_NETWORK_CONNECTIVITY
));
1510 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_EVENT_STORM_DETECTED
));
1511 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_SNMP_TRAP_DISCOVERY
));
1512 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_TRAPS_FROM_UNMANAGED_NODES
));
1513 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_RESOLVE_IP_FOR_EACH_STATUS_POLL
));
1514 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_PERFDATA_STORAGE_DRIVER_LOADED
));
1515 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_BACKGROUND_LOG_WRITER
));
1516 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_CASE_INSENSITIVE_LOGINS
));
1517 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_TRAP_SOURCES_IN_ALL_ZONES
));
1518 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_SERVER_INITIALIZED
));
1519 ConsolePrintf(pCtx
, SHOW_FLAG_VALUE(AF_SHUTDOWN
));
1520 ConsolePrintf(pCtx
, _T("\n"));
1522 else if (IsCommand(_T("HEAP"), szBuffer
, 1))
1524 TCHAR
*text
= GetHeapInfo();
1527 ConsoleWrite(pCtx
, text
);
1528 ConsoleWrite(pCtx
, _T("\n"));
1533 ConsoleWrite(pCtx
, _T("Error reading heap information\n"));
1536 else if (IsCommand(_T("INDEX"), szBuffer
, 1))
1539 pArg
= ExtractWord(pArg
, szBuffer
);
1541 if (IsCommand(_T("CONDITION"), szBuffer
, 1))
1543 DumpIndex(pCtx
, &g_idxConditionById
);
1545 else if (IsCommand(_T("ID"), szBuffer
, 2))
1547 DumpIndex(pCtx
, &g_idxObjectById
);
1549 else if (IsCommand(_T("INTERFACE"), szBuffer
, 2))
1551 DumpIndex(pCtx
, &g_idxInterfaceByAddr
);
1553 else if (IsCommand(_T("NODEADDR"), szBuffer
, 5))
1555 DumpIndex(pCtx
, &g_idxNodeByAddr
);
1557 else if (IsCommand(_T("NODEID"), szBuffer
, 5))
1559 DumpIndex(pCtx
, &g_idxNodeById
);
1561 else if (IsCommand(_T("SUBNET"), szBuffer
, 1))
1563 DumpIndex(pCtx
, &g_idxSubnetByAddr
);
1565 else if (IsCommand(_T("ZONE"), szBuffer
, 1))
1567 DumpIndex(pCtx
, &g_idxZoneByGUID
);
1571 if (szBuffer
[0] == 0)
1572 ConsoleWrite(pCtx
, _T("ERROR: Missing index name\n")
1573 _T("Valid names are: CONDITION, ID, INTERFACE, NODEADDR, NODEID, SUBNET, ZONE\n\n"));
1575 ConsoleWrite(pCtx
, _T("ERROR: Invalid index name\n\n"));
1578 else if (IsCommand(_T("MODULES"), szBuffer
, 3))
1580 ConsoleWrite(pCtx
, _T("Loaded server modules:\n"));
1581 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
1583 ConsolePrintf(pCtx
, _T(" %s\n"), g_pModuleList
[i
].szName
);
1585 ConsolePrintf(pCtx
, _T("%d modules loaded\n"), g_dwNumModules
);
1587 else if (IsCommand(_T("MSGWQ"), szBuffer
, 2))
1589 String text
= MsgWaitQueue::getDiagInfo();
1590 ConsoleWrite(pCtx
, text
);
1591 ConsoleWrite(pCtx
, _T("\n"));
1593 else if (IsCommand(_T("OBJECTS"), szBuffer
, 1))
1596 pArg
= ExtractWord(pArg
, szBuffer
);
1598 DumpObjects(pCtx
, (szBuffer
[0] != 0) ? szBuffer
: NULL
);
1600 else if (IsCommand(_T("POLLERS"), szBuffer
, 1))
1604 else if (IsCommand(_T("QUEUES"), szBuffer
, 1))
1606 ShowQueueStats(pCtx
, &g_dataCollectionQueue
, _T("Data collector"));
1607 ShowQueueStats(pCtx
, &g_dciCacheLoaderQueue
, _T("DCI cache loader"));
1608 ShowQueueStats(pCtx
, g_dbWriterQueue
, _T("Database writer"));
1609 ShowQueueStats(pCtx
, g_dciDataWriterQueue
, _T("Database writer (IData)"));
1610 ShowQueueStats(pCtx
, g_dciRawDataWriterQueue
, _T("Database writer (raw DCI values)"));
1611 ShowQueueStats(pCtx
, g_pEventQueue
, _T("Event processor"));
1612 ShowQueueStats(pCtx
, &g_nodePollerQueue
, _T("Node poller"));
1613 ShowQueueStats(pCtx
, &g_syslogProcessingQueue
, _T("Syslog processing"));
1614 ShowQueueStats(pCtx
, &g_syslogWriteQueue
, _T("Syslog writer"));
1615 ConsolePrintf(pCtx
, _T("\n"));
1617 else if (IsCommand(_T("ROUTING-TABLE"), szBuffer
, 1))
1622 pArg
= ExtractWord(pArg
, szBuffer
);
1623 dwNode
= _tcstoul(szBuffer
, NULL
, 0);
1626 pObject
= FindObjectById(dwNode
);
1627 if (pObject
!= NULL
)
1629 if (pObject
->getObjectClass() == OBJECT_NODE
)
1635 ConsolePrintf(pCtx
, _T("Routing table for node %s:\n\n"), pObject
->getName());
1636 pRT
= ((Node
*)pObject
)->getCachedRoutingTable();
1639 for(i
= 0; i
< pRT
->iNumEntries
; i
++)
1641 _sntprintf(szBuffer
, 256, _T("%s/%d"), IpToStr(pRT
->pRoutes
[i
].dwDestAddr
, szIpAddr
),
1642 BitsInMask(pRT
->pRoutes
[i
].dwDestMask
));
1643 ConsolePrintf(pCtx
, _T("%-18s %-15s %-6d %d\n"), szBuffer
,
1644 IpToStr(pRT
->pRoutes
[i
].dwNextHop
, szIpAddr
),
1645 pRT
->pRoutes
[i
].dwIfIndex
, pRT
->pRoutes
[i
].dwRouteType
);
1647 ConsoleWrite(pCtx
, _T("\n"));
1651 ConsoleWrite(pCtx
, _T("Node doesn't have cached routing table\n\n"));
1656 ConsoleWrite(pCtx
, _T("ERROR: Object is not a node\n\n"));
1661 ConsolePrintf(pCtx
, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode
);
1666 ConsoleWrite(pCtx
, _T("ERROR: Invalid or missing node ID\n\n"));
1669 else if (IsCommand(_T("SESSIONS"), szBuffer
, 2))
1671 ConsoleWrite(pCtx
, _T("\x1b[1mCLIENT SESSIONS\x1b[0m\n============================================================\n"));
1672 DumpClientSessions(pCtx
);
1673 ConsoleWrite(pCtx
, _T("\n\x1b[1mMOBILE DEVICE SESSIONS\x1b[0m\n============================================================\n"));
1674 DumpMobileDeviceSessions(pCtx
);
1676 else if (IsCommand(_T("STATS"), szBuffer
, 2))
1678 ShowServerStats(pCtx
);
1680 else if (IsCommand(_T("THREADS"), szBuffer
, 2))
1682 ShowThreadPool(pCtx
, g_mainThreadPool
);
1683 ShowThreadPool(pCtx
, g_pollerThreadPool
);
1684 ShowThreadPool(pCtx
, g_schedulerThreadPool
);
1685 ShowThreadPool(pCtx
, g_agentConnectionThreadPool
);
1687 else if (IsCommand(_T("TOPOLOGY"), szBuffer
, 1))
1689 pArg
= ExtractWord(pArg
, szBuffer
);
1690 UINT32 nodeId
= _tcstoul(szBuffer
, NULL
, 0);
1693 Node
*node
= (Node
*)FindObjectById(nodeId
, OBJECT_NODE
);
1696 LinkLayerNeighbors
*nbs
= BuildLinkLayerNeighborList(node
);
1699 ConsolePrintf(pCtx
, _T("Proto | PtP | ifLocal | ifRemote | Peer\n")
1700 _T("--------+-----+---------+----------+------------------------------------\n"));
1701 for(int i
= 0; i
< nbs
->size(); i
++)
1703 LL_NEIGHBOR_INFO
*ni
= nbs
->getConnection(i
);
1705 if (ni
->objectId
!= 0)
1707 NetObj
*object
= FindObjectById(ni
->objectId
);
1709 _sntprintf(peer
, 256, _T("%s [%d]"), object
->getName(), ni
->objectId
);
1711 _sntprintf(peer
, 256, _T("[%d]"), ni
->objectId
);
1717 ConsolePrintf(pCtx
, _T("%-7s | %c | %7d | %7d | %s\n"),
1718 GetLinkLayerProtocolName(ni
->protocol
), ni
->isPtToPt
? _T('Y') : _T('N'), ni
->ifLocal
, ni
->ifRemote
, peer
);
1724 ConsoleWrite(pCtx
, _T("ERROR: call to BuildLinkLayerNeighborList failed\n\n"));
1729 ConsolePrintf(pCtx
, _T("ERROR: Node with ID %d does not exist\n\n"), nodeId
);
1734 ConsoleWrite(pCtx
, _T("ERROR: Invalid or missing node ID\n\n"));
1737 else if (IsCommand(_T("USERS"), szBuffer
, 1))
1741 else if (IsCommand(_T("VLANS"), szBuffer
, 1))
1746 pArg
= ExtractWord(pArg
, szBuffer
);
1747 dwNode
= _tcstoul(szBuffer
, NULL
, 0);
1750 pObject
= FindObjectById(dwNode
);
1751 if (pObject
!= NULL
)
1753 if (pObject
->getObjectClass() == OBJECT_NODE
)
1755 VlanList
*vlans
= ((Node
*)pObject
)->getVlans();
1758 ConsoleWrite(pCtx
, _T("\x1b[1mVLAN\x1b[0m | \x1b[1mName\x1b[0m | \x1b[1mPorts\x1b[0m\n")
1759 _T("-----+------------------+-----------------------------------------------------------------\n"));
1760 for(int i
= 0; i
< vlans
->size(); i
++)
1762 VlanInfo
*vlan
= vlans
->get(i
);
1763 ConsolePrintf(pCtx
, _T("%4d | %-16s |"), vlan
->getVlanId(), vlan
->getName());
1764 for(int j
= 0; j
< vlan
->getNumPorts(); j
++)
1765 ConsolePrintf(pCtx
, _T(" %d.%d"), (int)(vlan
->getPorts()[j
] >> 16), (int)(vlan
->getPorts()[j
] & 0xFFFF));
1766 ConsolePrintf(pCtx
, _T("\n"));
1768 ConsolePrintf(pCtx
, _T("\n"));
1769 vlans
->decRefCount();
1773 ConsoleWrite(pCtx
, _T("\x1b[31mNode doesn't have VLAN information\x1b[0m\n\n"));
1778 ConsoleWrite(pCtx
, _T("\x1b[31mERROR: Object is not a node\x1b[0m\n\n"));
1783 ConsolePrintf(pCtx
, _T("\x1b[31mERROR: Object with ID %d does not exist\x1b[0m\n\n"), dwNode
);
1788 ConsoleWrite(pCtx
, _T("\x1b[31mERROR: Invalid or missing node ID\x1b[0m\n\n"));
1791 else if (IsCommand(_T("WATCHDOG"), szBuffer
, 1))
1793 WatchdogPrintStatus(pCtx
);
1794 ConsoleWrite(pCtx
, _T("\n"));
1798 if (szBuffer
[0] == 0)
1799 ConsoleWrite(pCtx
, _T("ERROR: Missing subcommand\n\n"));
1801 ConsoleWrite(pCtx
, _T("ERROR: Invalid SHOW subcommand\n\n"));
1804 else if (IsCommand(_T("EXEC"), szBuffer
, 3))
1806 pArg
= ExtractWord(pArg
, szBuffer
);
1808 bool libraryLocked
= true;
1809 bool destroyCompiledScript
= false;
1810 g_pScriptLibrary
->lock();
1812 NXSL_Program
*compiledScript
= g_pScriptLibrary
->findScript(szBuffer
);
1813 if (compiledScript
== NULL
)
1815 g_pScriptLibrary
->unlock();
1816 libraryLocked
= false;
1817 destroyCompiledScript
= true;
1820 if ((script
= (char *)LoadFile(szBuffer
, &fileSize
)) != NULL
)
1822 const int errorMsgLen
= 512;
1823 TCHAR errorMsg
[errorMsgLen
];
1825 WCHAR
*wscript
= WideStringFromMBString(script
);
1826 compiledScript
= NXSLCompile(wscript
, errorMsg
, errorMsgLen
, NULL
);
1829 compiledScript
= NXSLCompile(script
, errorMsg
, errorMsgLen
, NULL
);
1832 if (compiledScript
== NULL
)
1834 ConsolePrintf(pCtx
, _T("ERROR: Script compilation error: %s\n\n"), errorMsg
);
1839 ConsolePrintf(pCtx
, _T("ERROR: Script \"%s\" not found\n\n"), szBuffer
);
1843 if (compiledScript
!= NULL
)
1845 NXSL_ServerEnv
*pEnv
= new NXSL_ServerEnv
;
1846 pEnv
->setConsole(pCtx
);
1848 NXSL_VM
*vm
= new NXSL_VM(pEnv
);
1849 if (vm
->load(compiledScript
))
1853 g_pScriptLibrary
->unlock();
1854 libraryLocked
= false;
1857 NXSL_Value
*argv
[32];
1861 pArg
= ExtractWord(pArg
, szBuffer
);
1862 if (szBuffer
[0] == 0)
1864 argv
[argc
++] = new NXSL_Value(szBuffer
);
1867 if (vm
->run(argc
, argv
))
1869 NXSL_Value
*pValue
= vm
->getResult();
1870 int retCode
= pValue
->getValueAsInt32();
1871 ConsolePrintf(pCtx
, _T("INFO: Script finished with rc=%d\n\n"), retCode
);
1875 ConsolePrintf(pCtx
, _T("ERROR: Script finished with error: %s\n\n"), vm
->getErrorText());
1880 ConsolePrintf(pCtx
, _T("ERROR: VM creation failed: %s\n\n"), vm
->getErrorText());
1883 if (destroyCompiledScript
)
1884 delete compiledScript
;
1887 g_pScriptLibrary
->unlock();
1889 else if (IsCommand(_T("TRACE"), szBuffer
, 1))
1891 UINT32 dwNode1
, dwNode2
;
1892 NetObj
*pObject1
, *pObject2
;
1893 NetworkPath
*pTrace
;
1894 TCHAR szNextHop
[16];
1898 pArg
= ExtractWord(pArg
, szBuffer
);
1899 dwNode1
= _tcstoul(szBuffer
, NULL
, 0);
1901 pArg
= ExtractWord(pArg
, szBuffer
);
1902 dwNode2
= _tcstoul(szBuffer
, NULL
, 0);
1904 if ((dwNode1
!= 0) && (dwNode2
!= 0))
1906 pObject1
= FindObjectById(dwNode1
);
1907 if (pObject1
== NULL
)
1909 ConsolePrintf(pCtx
, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode1
);
1913 pObject2
= FindObjectById(dwNode2
);
1914 if (pObject2
== NULL
)
1916 ConsolePrintf(pCtx
, _T("ERROR: Object with ID %d does not exist\n\n"), dwNode2
);
1920 if ((pObject1
->getObjectClass() == OBJECT_NODE
) && (pObject2
->getObjectClass() == OBJECT_NODE
))
1922 pTrace
= TraceRoute((Node
*)pObject1
, (Node
*)pObject2
);
1926 ConsolePrintf(pCtx
, _T("Trace from %s to %s (%d hops, %s, source IP %s):\n"),
1927 pObject1
->getName(), pObject2
->getName(), pTrace
->getHopCount(),
1928 pTrace
->isComplete() ? _T("complete") : _T("incomplete"),
1929 pTrace
->getSourceAddress().toString(sourceIp
));
1930 for(i
= 0; i
< pTrace
->getHopCount(); i
++)
1932 HOP_INFO
*hop
= pTrace
->getHopInfo(i
);
1933 ConsolePrintf(pCtx
, _T("[%d] %s %s %s %d\n"),
1934 hop
->object
->getId(),
1935 hop
->object
->getName(),
1936 hop
->nextHop
.toString(szNextHop
),
1937 hop
->isVpn
? _T("VPN Connector ID:") : _T("Interface Index: "),
1941 ConsolePrintf(pCtx
, _T("\n"));
1945 ConsoleWrite(pCtx
, _T("ERROR: Call to TraceRoute() failed\n\n"));
1950 ConsoleWrite(pCtx
, _T("ERROR: Object is not a node\n\n"));
1957 ConsoleWrite(pCtx
, _T("ERROR: Invalid or missing node id(s)\n\n"));
1960 else if (IsCommand(_T("HELP"), szBuffer
, 2) || IsCommand(_T("?"), szBuffer
, 1))
1963 _T("Valid commands are:\n")
1964 _T(" at +<seconds>|<schedule> <script> [<parameters>]\n")
1965 _T(" - Schedule script execution task\n")
1966 _T(" debug [<level>|off] - Set debug level (valid range is 0..9)\n")
1967 _T(" down - Shutdown NetXMS server\n")
1968 _T(" exec <script> [<params>] - Executes NXSL script from script library\n")
1969 _T(" exit - Exit from remote session\n")
1970 _T(" kill <session> - Kill client session\n")
1971 _T(" get <variable> - Get value of server configuration variable\n")
1972 _T(" help - Display this help\n")
1973 _T(" hkrun - Run housekeeper immediately\n")
1974 _T(" ldapsync - Synchronize ldap users with local user database\n")
1975 _T(" log <text> - Write given text to server log file\n")
1976 _T(" logmark - Write marker ******* MARK ******* to server log file\n")
1977 _T(" ping <address> - Send ICMP echo request to given IP address\n")
1978 _T(" poll <type> <node> - Initiate node poll\n")
1979 _T(" raise <exception> - Raise exception\n")
1980 _T(" set <variable> <value> - Set value of server configuration variable\n")
1981 _T(" show components <node> - Show physical components of given node\n")
1982 _T(" show dbcp - Show active sessions in database connection pool\n")
1983 _T(" show dbstats - Show DB library statistics\n")
1984 _T(" show fdb <node> - Show forwarding database for node\n")
1985 _T(" show flags - Show internal server flags\n")
1986 _T(" show heap - Show heap information\n")
1987 _T(" show index <index> - Show internal index\n")
1988 _T(" show modules - Show loaded server modules\n")
1989 _T(" show msgwq - Show message wait queues information\n")
1990 _T(" show objects [<filter>] - Dump network objects to screen\n")
1991 _T(" show pollers - Show poller threads state information\n")
1992 _T(" show queues - Show internal queues statistics\n")
1993 _T(" show routing-table <node> - Show cached routing table for node\n")
1994 _T(" show sessions - Show active client sessions\n")
1995 _T(" show stats - Show server statistics\n")
1996 _T(" show topology <node> - Collect and show link layer topology for node\n")
1997 _T(" show users - Show users\n")
1998 _T(" show vlans <node> - Show cached VLAN information for node\n")
1999 _T(" show watchdog - Display watchdog information\n")
2000 _T(" trace <node1> <node2> - Show network path trace between two nodes\n")
2001 _T("\nAlmost all commands can be abbreviated to 2 or 3 characters\n")
2006 ConsoleWrite(pCtx
, _T("UNKNOWN COMMAND\n\n"));
2013 * Signal handler for UNIX platforms
2017 void SignalHandlerStub(int nSignal
)
2019 // should be unused, but JIC...
2020 if (nSignal
== SIGCHLD
)
2022 while (waitpid(-1, NULL
, WNOHANG
) > 0)
2027 THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL
SignalHandler(void *pArg
)
2032 m_signalHandlerThread
= pthread_self();
2034 // default for SIGCHLD: ignore
2035 signal(SIGCHLD
, &SignalHandlerStub
);
2037 sigemptyset(&signals
);
2038 sigaddset(&signals
, SIGTERM
);
2039 sigaddset(&signals
, SIGINT
);
2040 sigaddset(&signals
, SIGSEGV
);
2041 sigaddset(&signals
, SIGCHLD
);
2042 sigaddset(&signals
, SIGHUP
);
2043 sigaddset(&signals
, SIGUSR1
);
2044 sigaddset(&signals
, SIGUSR2
);
2045 #if !defined(__sun) && !defined(_AIX) && !defined(__hpux)
2046 sigaddset(&signals
, SIGPIPE
);
2049 sigprocmask(SIG_BLOCK
, &signals
, NULL
);
2053 if (sigwait(&signals
, &nSignal
) == 0)
2059 // avoid repeat Shutdown() call
2060 if (!(g_flags
& AF_SHUTDOWN
))
2062 m_nShutdownReason
= SHUTDOWN_BY_SIGNAL
;
2064 Shutdown(); // will never return
2066 ConditionSet(m_condShutdown
);
2073 while (waitpid(-1, NULL
, WNOHANG
) > 0)
2077 if (g_flags
& AF_SHUTDOWN
)
2091 sigprocmask(SIG_UNBLOCK
, &signals
, NULL
);
2100 THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL
Main(void *pArg
)
2102 nxlog_write(MSG_SERVER_STARTED
, EVENTLOG_INFORMATION_TYPE
, NULL
);
2106 if (!(g_flags
& AF_DEBUG_CONSOLE_DISABLED
))
2108 char *ptr
, szCommand
[256];
2109 struct __console_ctx ctx
;
2111 WCHAR wcCommand
[256];
2115 ctx
.socketMutex
= INVALID_MUTEX_HANDLE
;
2119 WriteToTerminal(_T("\nNetXMS Server V") NETXMS_VERSION_STRING
_T(" Build ") NETXMS_VERSION_BUILD_STRING IS_UNICODE_BUILD_STRING
_T(" Ready\n")
2120 _T("Enter \"\x1b[1mhelp\x1b[0m\" for command list or \"\x1b[1mdown\x1b[0m\" for server shutdown\n")
2121 _T("System Console\n\n"));
2124 // Initialize readline library if we use it
2125 rl_bind_key('\t', RL_INSERT_CAST rl_insert
);
2131 ptr
= readline("\x1b[33mnetxmsd:\x1b[0m ");
2133 WriteToTerminal(_T("\x1b[33mnetxmsd:\x1b[0m "));
2135 if (fgets(szCommand
, 255, stdin
) == NULL
)
2136 break; // Error reading stdin
2137 ptr
= strchr(szCommand
, '\n');
2147 mbstowcs(wcCommand
, ptr
, 255);
2149 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, ptr
, -1, wcCommand
, 256);
2152 StrStrip(wcCommand
);
2153 if (wcCommand
[0] != 0)
2155 if (ProcessConsoleCommand(wcCommand
, &ctx
) == CMD_EXIT_SHUTDOWN
)
2160 if (ProcessConsoleCommand(ptr
, &ctx
) == CMD_EXIT_SHUTDOWN
)
2180 if (!(g_flags
& AF_SHUTDOWN
))
2182 m_nShutdownReason
= SHUTDOWN_FROM_CONSOLE
;
2188 // standalone with debug console disabled
2190 _tprintf(_T("Server running. Press ESC to shutdown.\n"));
2196 _tprintf(_T("Server shutting down...\n"));
2199 _tprintf(_T("Server running. Press Ctrl+C to shutdown.\n"));
2200 // Shutdown will be called from signal handler
2201 ConditionWait(m_condShutdown
, INFINITE
);
2207 ConditionWait(m_condShutdown
, INFINITE
);
2208 // On Win32, Shutdown() will be called by service control handler
2217 * Initiate server shutdown
2219 void InitiateShutdown()
2230 pthread_kill(m_signalHandlerThread
, SIGTERM
);
2240 BOOL WINAPI
DllMain(HINSTANCE hInstance
, DWORD dwReason
, LPVOID lpReserved
)
2242 if (dwReason
== DLL_PROCESS_ATTACH
)
2243 DisableThreadLibraryCalls(hInstance
);