3cd54e492e45078aaa793e49c79f9997ce18b8a7
[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 <time.h>
26 #include "system.h"
27 #include "hpux.h"
28
29
30 //
31 // Possible consolidation types of per-process information
32 //
33
34 #define INFOTYPE_MIN 0
35 #define INFOTYPE_MAX 1
36 #define INFOTYPE_AVG 2
37 #define INFOTYPE_SUM 3
38
39
40 //
41 // Process cache
42 //
43
44 #define EXPIRATION 3
45
46 static struct pst_status *m_processList = NULL;
47 static time_t m_processListUpdated = 0;
48
49 //
50 // Handler for System.ProcessCount parameter
51 //
52
53 LONG H_SysProcessCount(const char *pszParam, const char *pArg, char *pValue)
54 {
55 struct pst_dynamic pd;
56 LONG nRet = SYSINFO_RC_ERROR;
57
58 if (pstat_getdynamic(&pd, sizeof(struct pst_dynamic), 1, 0) == 1)
59 {
60 nRet = SYSINFO_RC_SUCCESS;
61 ret_int(pValue, (LONG)pd.psd_activeprocs);
62 }
63 return nRet;
64 }
65
66
67 //
68 // Get process list
69 //
70
71 static struct pst_status *GetProcessList(int *pnNumProcs)
72 {
73 int nSize = 0, nCount;
74 struct pst_status *pBuffer = NULL;
75 time_t now;
76
77 if (m_processList != NULL)
78 {
79 now = time(NULL);
80 if (now < m_processListUpdated + EXPIRATION)
81 {
82 return m_processList;
83 }
84 }
85
86 do
87 {
88 nSize += 1000;
89 pBuffer = (pst_status *)realloc(pBuffer, sizeof(struct pst_status) * nSize);
90 nCount = pstat_getproc(pBuffer, sizeof(struct pst_status), nSize, 0);
91 } while(nCount == nSize);
92
93 if (nCount <= 0)
94 {
95 free(pBuffer);
96 pBuffer = NULL;
97 }
98 else
99 {
100 *pnNumProcs = nCount;
101 }
102
103 m_processList = pBuffer;
104 m_processListUpdated = now;
105
106 return pBuffer;
107 }
108
109
110 //
111 // Handler for System.ThreadCount parameter
112 //
113
114 LONG H_SysThreadCount(const char *pszParam, const char *pArg, char *pValue)
115 {
116 LONG nRet;
117 struct pst_status *pList;
118 int i, nProcCount, nThreadCount;
119
120 pList = GetProcessList(&nProcCount);
121 if (pList != NULL)
122 {
123 for(i = 0, nThreadCount = 0; i < nProcCount; i++)
124 {
125 nThreadCount += pList[i].pst_nlwps;
126 }
127 free(pList);
128 ret_uint(pValue, nThreadCount);
129 nRet = SYSINFO_RC_SUCCESS;
130 }
131 else
132 {
133 nRet = SYSINFO_RC_ERROR;
134 }
135
136 return nRet;
137 }
138
139
140 //
141 // Handler for Process.Count(*) parameter
142 //
143
144 LONG H_ProcessCount(const char *pszParam, const char *pArg, char *pValue)
145 {
146 struct pst_status *pst;
147 int i, nCount, nTotal;
148 char szArg[256];
149 LONG nRet = SYSINFO_RC_ERROR;
150
151 if (!AgentGetParameterArg(pszParam, 1, szArg, sizeof(szArg)))
152 return SYSINFO_RC_UNSUPPORTED;
153
154 pst = GetProcessList(&nCount);
155 if (pst != NULL)
156 {
157 for (i = 0, nTotal = 0; i < nCount; i++)
158 {
159 if (!strcasecmp(pst[i].pst_ucomm, szArg))
160 nTotal++;
161 }
162 free(pst);
163 ret_int(pValue, nTotal);
164 nRet = SYSINFO_RC_SUCCESS;
165 }
166
167 return nRet;
168 }
169
170
171 //
172 // Handler for Process.xxx() parameters
173 // Parameter has the following syntax:
174 // Process.XXX(<process>,<type>,<cmdline>)
175 // where
176 // XXX - requested process attribute (see documentation for list of valid attributes)
177 // <process> - process name (same as in Process.Count() parameter)
178 // <type> - representation type (meaningful when more than one process with the same
179 // name exists). Valid values are:
180 // min - minimal value among all processes named <process>
181 // max - maximal value among all processes named <process>
182 // avg - average value for all processes named <process>
183 // sum - sum of values for all processes named <process>
184 // <cmdline> - command line
185 //
186
187 LONG H_ProcessInfo(const char *pszParam, const char *pArg, char *pValue)
188 {
189 int nRet = SYSINFO_RC_SUCCESS;
190 char szBuffer[256] = "";
191 int i, nProcCount, nType, nCount;
192 struct pst_status *pList;
193 QWORD qwValue, qwCurrVal;
194 static const char *pszTypeList[]={ "min", "max", "avg", "sum", NULL };
195
196 // Get parameter type arguments
197 AgentGetParameterArg(pszParam, 2, szBuffer, sizeof(szBuffer));
198 if (szBuffer[0] == 0) // Omited type
199 {
200 nType = INFOTYPE_SUM;
201 }
202 else
203 {
204 for(nType = 0; pszTypeList[nType] != NULL; nType++)
205 if (!stricmp(pszTypeList[nType], szBuffer))
206 break;
207 if (pszTypeList[nType] == NULL)
208 return SYSINFO_RC_UNSUPPORTED; // Unsupported type
209 }
210
211 AgentGetParameterArg(pszParam, 1, szBuffer, sizeof(szBuffer));
212
213 pList = GetProcessList(&nProcCount);
214 if (pList != NULL)
215 {
216 for(i = 0, qwValue = 0, nCount = 0; i < nProcCount; i++)
217 {
218 if (!strcmp(pList[i].pst_ucomm, szBuffer))
219 {
220 switch(CAST_FROM_POINTER(pArg, int))
221 {
222 case PROCINFO_CPUTIME:
223 qwCurrVal = (pList[i].pst_stime + pList[i].pst_utime) * 1000;
224 break;
225 // case PROCINFO_IO_READ_B:
226 case PROCINFO_IO_READ_OP:
227 qwCurrVal = pList[i].pst_inblock;
228 break;
229 // case PROCINFO_IO_WRITE_B:
230 case PROCINFO_IO_WRITE_OP:
231 qwCurrVal = pList[i].pst_oublock;
232 break;
233 case PROCINFO_KTIME:
234 qwCurrVal = pList[i].pst_stime * 1000;
235 break;
236 case PROCINFO_PF:
237 qwCurrVal = pList[i].pst_minorfaults + pList[i].pst_majorfaults;
238 break;
239 case PROCINFO_THREADS:
240 qwCurrVal = pList[i].pst_nlwps;
241 break;
242 case PROCINFO_UTIME:
243 qwCurrVal = pList[i].pst_utime * 1000;
244 break;
245 case PROCINFO_VMSIZE:
246 qwCurrVal = (pList[i].pst_vtsize /* text */
247 + pList[i].pst_vdsize /* data */
248 + pList[i].pst_vssize /* stack */
249 + pList[i].pst_vshmsize /* shared memory */
250 + pList[i].pst_vmmsize /* mem-mapped files */
251 + pList[i].pst_vusize /* U-Area & K-Stack */
252 + pList[i].pst_viosize) /* I/O dev mapping */
253 * getpagesize();
254 break;
255 case PROCINFO_WKSET:
256 qwCurrVal = pList[i].pst_rssize * getpagesize();
257 break;
258 default:
259 nRet = SYSINFO_RC_UNSUPPORTED;
260 break;
261 }
262
263 if (nCount == 0)
264 {
265 qwValue = qwCurrVal;
266 }
267 else
268 {
269 switch(nType)
270 {
271 case INFOTYPE_MIN:
272 qwValue = min(qwValue, qwCurrVal);
273 break;
274 case INFOTYPE_MAX:
275 qwValue = max(qwValue, qwCurrVal);
276 break;
277 case INFOTYPE_AVG:
278 qwValue = (qwValue * nCount + qwCurrVal) / (nCount + 1);
279 break;
280 case INFOTYPE_SUM:
281 qwValue += qwCurrVal;
282 break;
283 }
284 }
285 nCount++;
286 }
287 }
288 free(pList);
289 ret_uint64(pValue, qwValue);
290 }
291 else
292 {
293 nRet = SYSINFO_RC_ERROR;
294 }
295
296 return nRet;
297 }
298
299
300 //
301 // Handler for System.ProcessList enum
302 //
303
304 LONG H_ProcessList(const char *pszParam, const char *pArg, StringList *pValue)
305 {
306 LONG nRet = SYSINFO_RC_ERROR;
307 int i, nCount;
308 struct pst_status *pst;
309 char szBuff[256];
310
311 pst = GetProcessList(&nCount);
312 if (pst != NULL)
313 {
314 for (i = 0; i < nCount; i++)
315 {
316 snprintf(szBuff, sizeof(szBuff), "%d %s", (DWORD)pst[i].pst_pid, pst[i].pst_ucomm);
317 pValue->add(szBuff);
318 }
319 free(pst);
320 nRet = SYSINFO_RC_SUCCESS;
321 }
322
323 return nRet;
324 }