c95e382aa77849b16231d965fe8db6e0894b99e4
[public/netxms.git] / src / agent / subagents / hpux / proc.cpp
1 /*
2 ** NetXMS subagent for HP-UX
3 ** Copyright (C) 2006 Alex Kirhenshtein
4 ** Copyright (C) 2010 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 */
21
22 #include <nms_common.h>
23 #include <nms_agent.h>
24 #include <sys/pstat.h>
25 #include "system.h"
26 #include "hpux.h"
27
28
29 //
30 // Possible consolidation types of per-process information
31 //
32
33 #define INFOTYPE_MIN 0
34 #define INFOTYPE_MAX 1
35 #define INFOTYPE_AVG 2
36 #define INFOTYPE_SUM 3
37
38
39 //
40 // Handler for System.ProcessCount parameter
41 //
42
43 LONG H_SysProcessCount(const char *pszParam, const char *pArg, char *pValue)
44 {
45 struct pst_dynamic pd;
46 LONG nRet = SYSINFO_RC_ERROR;
47
48 if (pstat_getdynamic(&pd, sizeof(struct pst_dynamic), 1, 0) == 1)
49 {
50 nRet = SYSINFO_RC_SUCCESS;
51 ret_int(pValue, (LONG)pd.psd_activeprocs);
52 }
53 return nRet;
54 }
55
56
57 //
58 // Get process list
59 //
60
61 static struct pst_status *GetProcessList(int *pnNumProcs)
62 {
63 int nSize = 0, nCount;
64 struct pst_status *pBuffer = NULL;
65
66 do
67 {
68 nSize += 1000;
69 pBuffer = (pst_status *)realloc(pBuffer, sizeof(struct pst_status) * nSize);
70 nCount = pstat_getproc(pBuffer, sizeof(struct pst_status), nSize, 0);
71 } while(nCount == nSize);
72
73 if (nCount <= 0)
74 {
75 free(pBuffer);
76 pBuffer = NULL;
77 }
78 else
79 {
80 *pnNumProcs = nCount;
81 }
82
83 return pBuffer;
84 }
85
86
87 //
88 // Handler for System.ThreadCount parameter
89 //
90
91 LONG H_SysThreadCount(const char *pszParam, const char *pArg, char *pValue)
92 {
93 LONG nRet;
94 struct pst_status *pList;
95 int i, nProcCount, nThreadCount;
96
97 pList = GetProcessList(&nProcCount);
98 if (pList != NULL)
99 {
100 for(i = 0, nThreadCount = 0; i < nProcCount; i++)
101 {
102 nThreadCount += pList[i].pst_nlwps;
103 }
104 free(pList);
105 ret_uint(pValue, nThreadCount);
106 nRet = SYSINFO_RC_SUCCESS;
107 }
108 else
109 {
110 nRet = SYSINFO_RC_ERROR;
111 }
112
113 return nRet;
114 }
115
116
117 //
118 // Handler for Process.Count(*) parameter
119 //
120
121 LONG H_ProcessCount(const char *pszParam, const char *pArg, char *pValue)
122 {
123 struct pst_status *pst;
124 int i, nCount, nTotal;
125 char szArg[256];
126 LONG nRet = SYSINFO_RC_ERROR;
127
128 if (!AgentGetParameterArg(pszParam, 1, szArg, sizeof(szArg)))
129 return SYSINFO_RC_UNSUPPORTED;
130
131 pst = GetProcessList(&nCount);
132 if (pst != NULL)
133 {
134 for (i = 0, nTotal = 0; i < nCount; i++)
135 {
136 if (!strcasecmp(pst[i].pst_ucomm, szArg))
137 nTotal++;
138 }
139 free(pst);
140 ret_int(pValue, nTotal);
141 nRet = SYSINFO_RC_SUCCESS;
142 }
143
144 return nRet;
145 }
146
147
148 //
149 // Handler for Process.xxx() parameters
150 // Parameter has the following syntax:
151 // Process.XXX(<process>,<type>,<cmdline>)
152 // where
153 // XXX - requested process attribute (see documentation for list of valid attributes)
154 // <process> - process name (same as in Process.Count() parameter)
155 // <type> - representation type (meaningful when more than one process with the same
156 // name exists). Valid values are:
157 // min - minimal value among all processes named <process>
158 // max - maximal value among all processes named <process>
159 // avg - average value for all processes named <process>
160 // sum - sum of values for all processes named <process>
161 // <cmdline> - command line
162 //
163
164 LONG H_ProcessInfo(const char *pszParam, const char *pArg, char *pValue)
165 {
166 int nRet = SYSINFO_RC_SUCCESS;
167 char szBuffer[256] = "";
168 int i, nProcCount, nType, nCount;
169 struct pst_status *pList;
170 QWORD qwValue, qwCurrVal;
171 static const char *pszTypeList[]={ "min", "max", "avg", "sum", NULL };
172
173 // Get parameter type arguments
174 AgentGetParameterArg(pszParam, 2, szBuffer, sizeof(szBuffer));
175 if (szBuffer[0] == 0) // Omited type
176 {
177 nType = INFOTYPE_SUM;
178 }
179 else
180 {
181 for(nType = 0; pszTypeList[nType] != NULL; nType++)
182 if (!stricmp(pszTypeList[nType], szBuffer))
183 break;
184 if (pszTypeList[nType] == NULL)
185 return SYSINFO_RC_UNSUPPORTED; // Unsupported type
186 }
187
188 AgentGetParameterArg(pszParam, 1, szBuffer, sizeof(szBuffer));
189
190 pList = GetProcessList(&nProcCount);
191 if (pList != NULL)
192 {
193 for(i = 0, qwValue = 0, nCount = 0; i < nProcCount; i++)
194 {
195 if (!strcmp(pList[i].pst_ucomm, szBuffer))
196 {
197 switch(CAST_FROM_POINTER(pArg, int))
198 {
199 case PROCINFO_CPUTIME:
200 qwCurrVal = (pList[i].pst_stime + pList[i].pst_utime) * 1000;
201 break;
202 // case PROCINFO_IO_READ_B:
203 case PROCINFO_IO_READ_OP:
204 qwCurrVal = pList[i].pst_inblock;
205 break;
206 // case PROCINFO_IO_WRITE_B:
207 case PROCINFO_IO_WRITE_OP:
208 qwCurrVal = pList[i].pst_oublock;
209 break;
210 case PROCINFO_KTIME:
211 qwCurrVal = pList[i].pst_stime * 1000;
212 break;
213 case PROCINFO_PF:
214 qwCurrVal = pList[i].pst_minorfaults + pList[i].pst_majorfaults;
215 break;
216 case PROCINFO_THREADS:
217 qwCurrVal = pList[i].pst_nlwps;
218 break;
219 case PROCINFO_UTIME:
220 qwCurrVal = pList[i].pst_utime * 1000;
221 break;
222 case PROCINFO_VMSIZE:
223 qwCurrVal = (pList[i].pst_vtsize /* text */
224 + pList[i].pst_vdsize /* data */
225 + pList[i].pst_vssize /* stack */
226 + pList[i].pst_vshmsize /* shared memory */
227 + pList[i].pst_vmmsize /* mem-mapped files */
228 + pList[i].pst_vusize /* U-Area & K-Stack */
229 + pList[i].pst_viosize) /* I/O dev mapping */
230 * getpagesize();
231 break;
232 case PROCINFO_WKSET:
233 qwCurrVal = pList[i].pst_rssize * getpagesize();
234 break;
235 default:
236 nRet = SYSINFO_RC_UNSUPPORTED;
237 break;
238 }
239
240 if (nCount == 0)
241 {
242 qwValue = qwCurrVal;
243 }
244 else
245 {
246 switch(nType)
247 {
248 case INFOTYPE_MIN:
249 qwValue = min(qwValue, qwCurrVal);
250 break;
251 case INFOTYPE_MAX:
252 qwValue = max(qwValue, qwCurrVal);
253 break;
254 case INFOTYPE_AVG:
255 qwValue = (qwValue * nCount + qwCurrVal) / (nCount + 1);
256 break;
257 case INFOTYPE_SUM:
258 qwValue += qwCurrVal;
259 break;
260 }
261 }
262 nCount++;
263 }
264 }
265 free(pList);
266 ret_uint64(pValue, qwValue);
267 }
268 else
269 {
270 nRet = SYSINFO_RC_ERROR;
271 }
272
273 return nRet;
274 }
275
276
277 //
278 // Handler for System.ProcessList enum
279 //
280
281 LONG H_ProcessList(const char *pszParam, const char *pArg, StringList *pValue)
282 {
283 LONG nRet = SYSINFO_RC_ERROR;
284 int i, nCount;
285 struct pst_status *pst;
286 char szBuff[256];
287
288 pst = GetProcessList(&nCount);
289 if (pst != NULL)
290 {
291 for (i = 0; i < nCount; i++)
292 {
293 snprintf(szBuff, sizeof(szBuff), "%d %s", (DWORD)pst[i].pst_pid, pst[i].pst_ucomm);
294 pValue->add(szBuff);
295 }
296 free(pst);
297 nRet = SYSINFO_RC_SUCCESS;
298 }
299
300 return nRet;
301 }