Queue class can shrink buffer; cosmetic code refactoring
[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 */
5d3459af 32void DbgTestRWLock(RWLOCK hLock, const TCHAR *szName, CONSOLE_CTX console)
5039dede 33{
5d3459af 34 ConsolePrintf(console, _T(" %s: "), szName);
5039dede
AK
35 if (RWLockWriteLock(hLock, 100))
36 {
5d3459af 37 ConsolePrintf(console, _T("unlocked\n"));
5039dede
AK
38 RWLockUnlock(hLock);
39 }
40 else
41 {
42 if (RWLockReadLock(hLock, 100))
43 {
5d3459af 44 ConsolePrintf(console, _T("locked for reading\n"));
5039dede
AK
45 RWLockUnlock(hLock);
46 }
47 else
48 {
5d3459af 49 ConsolePrintf(console, _T("locked for writing\n"));
5039dede
AK
50 }
51 }
52}
53
534e1b83
VK
54/**
55 * Print message to console, either local or remote
56 */
5d3459af 57void ConsolePrintf(CONSOLE_CTX console, 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
5d3459af 67 if ((console->hSocket == -1) && (console->session == NULL) && (console->output == NULL))
5039dede 68 {
f669df41 69 WriteToTerminal(szBuffer);
5039dede 70 }
5d3459af 71 else if (console->output != NULL)
244c65ef
VK
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
5d3459af
VK
90 MutexLock(console->socketMutex);
91 *console->output += szBuffer;
92 MutexUnlock(console->socketMutex);
244c65ef 93 }
5039dede
AK
94 else
95 {
5d3459af
VK
96 console->pMsg->setField(VID_MESSAGE, szBuffer);
97 if (console->session != NULL)
200d662d 98 {
5d3459af 99 console->session->postMessage(console->pMsg);
200d662d
VK
100 }
101 else
102 {
5d3459af
VK
103 NXCP_MESSAGE *pRawMsg = console->pMsg->createMessage();
104 SendEx(console->hSocket, pRawMsg, ntohl(pRawMsg->size), 0, console->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
5d3459af 118void ShowServerStats(CONSOLE_CTX console)
9d605305
VK
119{
120 int dciCount = 0;
121 g_idxNodeById.forEach(DciCountCallback, &dciCount);
5d3459af
VK
122 ConsolePrintf(console, _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 */
5d3459af 131void ShowQueueStats(CONSOLE_CTX console, Queue *pQueue, const TCHAR *pszName)
5039dede
AK
132{
133 if (pQueue != NULL)
19dbc8ef 134 ConsolePrintf(console, _T("%-32s : %d\n"), pszName, pQueue->size());
5d3459af
VK
135}
136
137/**
138 * Show thread pool stats
139 */
140void ShowThreadPool(CONSOLE_CTX console, ThreadPool *p)
141{
142 ThreadPoolInfo info;
143 ThreadPoolGetInfo(p, &info);
144 ConsolePrintf(console, _T("\x1b[1m%s\x1b[0m\n")
145 _T(" Threads: %d (%d/%d)\n")
146 _T(" Load: %d%%\n")
147 _T(" Usage: %d%%\n")
148 _T(" Requests: %d\n\n"),
149 info.name, info.curThreads, info.minThreads, info.maxThreads, info.load, info.usage, info.activeRequests);
5039dede
AK
150}
151
534e1b83
VK
152/**
153 * Write process coredump
154 */
5039dede
AK
155#ifdef _WIN32
156
5d3459af 157void DumpProcess(CONSOLE_CTX console)
5039dede 158{
35f836fe 159 STARTUPINFOA si;
5039dede 160 PROCESS_INFORMATION pi;
35f836fe 161 char cmdLine[64];
5039dede 162
5d3459af 163 ConsolePrintf(console, _T("Dumping process to disk...\n"));
5039dede
AK
164
165 sprintf(cmdLine, "netxmsd.exe --dump %d", GetCurrentProcessId());
166 memset(&si, 0, sizeof(STARTUPINFO));
167 si.cb = sizeof(STARTUPINFO);
35f836fe 168 if (CreateProcessA(NULL, cmdLine, NULL, NULL, FALSE,
c8076b19 169 (g_flags & AF_DAEMON) ? CREATE_NO_WINDOW : 0, NULL, NULL, &si, &pi))
5039dede
AK
170 {
171 WaitForSingleObject(pi.hProcess, INFINITE);
172 CloseHandle(pi.hThread);
173 CloseHandle(pi.hProcess);
174
5d3459af 175 ConsolePrintf(console, _T("Done.\n"));
5039dede
AK
176 }
177 else
178 {
35f836fe 179 TCHAR buffer[256];
5d3459af 180 ConsolePrintf(console, _T("Dump error: CreateProcess() failed (%s)\n"), GetSystemErrorText(GetLastError(), buffer, 256));
5039dede
AK
181 }
182}
183
184#else
185
5d3459af 186void DumpProcess(CONSOLE_CTX console)
5039dede 187{
5d3459af 188 ConsolePrintf(console, _T("DUMP command is not supported for current operating system\n"));
5039dede
AK
189}
190
191#endif