devemu subagent added to installer
[public/netxms.git] / src / server / core / debug.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
534e1b83 3** Copyright (C) 2003-2012 Victor Kirhenshtein
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: debug.cpp
20**
21**/
22
23#include "nxcore.h"
24
25#ifdef _WIN32
26#include <dbghelp.h>
27#endif
28
534e1b83
VK
29/**
30 * Test read/write lock state and print to stdout
31 */
5039dede
AK
32void DbgTestRWLock(RWLOCK hLock, const TCHAR *szName, CONSOLE_CTX pCtx)
33{
34 ConsolePrintf(pCtx, _T(" %s: "), szName);
35 if (RWLockWriteLock(hLock, 100))
36 {
37 ConsolePrintf(pCtx, _T("unlocked\n"));
38 RWLockUnlock(hLock);
39 }
40 else
41 {
42 if (RWLockReadLock(hLock, 100))
43 {
44 ConsolePrintf(pCtx, _T("locked for reading\n"));
45 RWLockUnlock(hLock);
46 }
47 else
48 {
49 ConsolePrintf(pCtx, _T("locked for writing\n"));
50 }
51 }
52}
53
534e1b83
VK
54/**
55 * Print message to console, either local or remote
56 */
35f836fe 57void ConsolePrintf(CONSOLE_CTX pCtx, const TCHAR *pszFormat, ...)
5039dede
AK
58{
59 va_list args;
f669df41 60 TCHAR szBuffer[8192];
5039dede
AK
61
62 va_start(args, pszFormat);
f669df41
VK
63 _vsntprintf(szBuffer, 8191, pszFormat, args);
64 szBuffer[8191] = 0;
65 va_end(args);
66
244c65ef 67 if ((pCtx->hSocket == -1) && (pCtx->session == NULL) && (pCtx->output == NULL))
5039dede 68 {
f669df41 69 WriteToTerminal(szBuffer);
5039dede 70 }
244c65ef
VK
71 else if (pCtx->output != NULL)
72 {
73 // remove possible escape sequences
74 for(int i = 0; szBuffer[i] != 0; i++)
75 {
76 if (szBuffer[i] == 27)
77 {
78 int start = i++;
79 if (szBuffer[i] == '[')
80 {
81 for(i++; (szBuffer[i] != 0) && (szBuffer[i] != 'm'); i++);
82 if (szBuffer[i] == 'm')
83 i++;
84 }
85 memmove(&szBuffer[start], &szBuffer[i], (_tcslen(&szBuffer[i]) + 1) * sizeof(TCHAR));
86 i = start - 1;
87 }
88 }
89
90 MutexLock(pCtx->socketMutex);
91 *pCtx->output += szBuffer;
92 MutexUnlock(pCtx->socketMutex);
93 }
5039dede
AK
94 else
95 {
b368969c 96 pCtx->pMsg->setField(VID_MESSAGE, szBuffer);
200d662d
VK
97 if (pCtx->session != NULL)
98 {
d3a7cf4c 99 pCtx->session->postMessage(pCtx->pMsg);
200d662d
VK
100 }
101 else
102 {
b368969c
VK
103 NXCP_MESSAGE *pRawMsg = pCtx->pMsg->createMessage();
104 SendEx(pCtx->hSocket, pRawMsg, ntohl(pRawMsg->size), 0, pCtx->socketMutex);
200d662d
VK
105 free(pRawMsg);
106 }
5039dede 107 }
5039dede
AK
108}
109
534e1b83
VK
110/**
111 * Show server statistics
112 */
9d605305 113static void DciCountCallback(NetObj *object, void *data)
5039dede 114{
9d605305
VK
115 *((int *)data) += (int)((Node *)object)->getItemCount();
116}
5039dede 117
9d605305
VK
118void ShowServerStats(CONSOLE_CTX pCtx)
119{
120 int dciCount = 0;
121 g_idxNodeById.forEach(DciCountCallback, &dciCount);
35f836fe
VK
122 ConsolePrintf(pCtx, _T("Total number of objects: %d\n")
123 _T("Number of monitored nodes: %d\n")
124 _T("Number of collectable DCIs: %d\n\n"),
a6312bd6 125 g_idxObjectById.size(), g_idxNodeById.size(), dciCount);
5039dede
AK
126}
127
534e1b83
VK
128/**
129 * Show queue stats
130 */
35f836fe 131void ShowQueueStats(CONSOLE_CTX pCtx, Queue *pQueue, const TCHAR *pszName)
5039dede
AK
132{
133 if (pQueue != NULL)
35f836fe 134 ConsolePrintf(pCtx, _T("%-32s : %d\n"), pszName, pQueue->Size());
5039dede
AK
135}
136
534e1b83
VK
137/**
138 * Write process coredump
139 */
5039dede
AK
140#ifdef _WIN32
141
142void DumpProcess(CONSOLE_CTX pCtx)
143{
35f836fe 144 STARTUPINFOA si;
5039dede 145 PROCESS_INFORMATION pi;
35f836fe 146 char cmdLine[64];
5039dede 147
35f836fe 148 ConsolePrintf(pCtx, _T("Dumping process to disk...\n"));
5039dede
AK
149
150 sprintf(cmdLine, "netxmsd.exe --dump %d", GetCurrentProcessId());
151 memset(&si, 0, sizeof(STARTUPINFO));
152 si.cb = sizeof(STARTUPINFO);
35f836fe 153 if (CreateProcessA(NULL, cmdLine, NULL, NULL, FALSE,
c8076b19 154 (g_flags & AF_DAEMON) ? CREATE_NO_WINDOW : 0, NULL, NULL, &si, &pi))
5039dede
AK
155 {
156 WaitForSingleObject(pi.hProcess, INFINITE);
157 CloseHandle(pi.hThread);
158 CloseHandle(pi.hProcess);
159
35f836fe 160 ConsolePrintf(pCtx, _T("Done.\n"));
5039dede
AK
161 }
162 else
163 {
35f836fe
VK
164 TCHAR buffer[256];
165 ConsolePrintf(pCtx, _T("Dump error: CreateProcess() failed (%s)\n"), GetSystemErrorText(GetLastError(), buffer, 256));
5039dede
AK
166 }
167}
168
169#else
170
171void DumpProcess(CONSOLE_CTX pCtx)
172{
b07c50cc 173 ConsolePrintf(pCtx, _T("DUMP command is not supported for current operating system\n"));
5039dede
AK
174}
175
176#endif