blob: 19212298bf20e7e05b76a36781cc3a01e38daf9f [file] [log] [blame]
/*
* Copyright (C) Tildeslash Ltd. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
*
* You must obey the GNU Affero General Public License in all respects
* for all of the code used other than OpenSSL.
*/
#include "config.h"
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef TIME_WITH_SYS_TIME
#include <time.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#else
#include <time.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#define _RUSAGE_EXTENDED
#ifdef HAVE_SYS_PSTAT_H
#include <sys/pstat.h>
#endif
#ifdef HAVE_NLIST_H
#include <nlist.h>
#endif
#ifdef HAVE_SYS_DK_H
#include <sys/dk.h>
#endif
#ifdef HAVE_SYS_SWAP_H
#include <sys/swap.h>
#endif
#include "monit.h"
#include "process.h"
#include "process_sysdep.h"
static int page_size;
static int nproc;
static long cpu_total_old = 0;
static long cpu_user_old = 0;
static long cpu_syst_old = 0;
static long cpu_wait_old = 0;
struct pst_dynamic pst_dyn;
struct pst_status *psall;
#define MAXSTRSIZE 80
/**
* System dependent resource gathering code for HP/UX.
*
* @file
*/
/*
* Helpful guide for implematation:
* "SunOS to HP-UX 9.05 Porting Guide" at http://www.interex.org/tech/9000/Tech/sun_hpux_port/portguide.html
*/
int init_process_info_sysdep(void) {
struct pst_dynamic psd;
struct pst_static pst;
if (pstat_getdynamic(&psd,sizeof(psd),(size_t)1,0) != -1)
systeminfo.cpus=psd.psd_proc_cnt;
else
return FALSE;
if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) != -1) {
systeminfo.mem_kbyte_max=(unsigned long)(pst.physical_memory * (pst.page_size / 1024));
page_size=pst.page_size;
} else {
return FALSE;
}
return TRUE;
}
/**
* This routine returns 'na' double precision floats containing
* the load averages in 'a'; at most 3 values will be returned.
* @param loadv destination of the load averages
* @param nelem number of averages
* @return: 0 if successful, -1 if failed (and all load averages are 0).
*/
int getloadavg_sysdep (double *a, int na) {
struct pst_dynamic psd;
if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) {
switch (na) {
case 3:
a[2] = psd.psd_avg_15_min;
case 2:
a[1] = psd.psd_avg_5_min;
case 1:
a[0] = psd.psd_avg_1_min;
}
} else {
return FALSE;
}
return TRUE;
}
/**
* Read all processes to initialize the process tree
* @param reference reference of ProcessTree
* @return treesize>0 if succeeded otherwise 0.
*/
int initprocesstree_sysdep(ProcessTree_T ** reference) {
int i;
int treesize;
ProcessTree_T *pt;
ASSERT(reference);
pstat_getdynamic(&pst_dyn, sizeof(struct pst_dynamic), 1, 0);
nproc = pst_dyn.psd_activeprocs;
if (nproc)
RESIZE(psall, nproc * sizeof(struct pst_status));
else
return 0;
if ((treesize = pstat_getproc(psall, sizeof(struct pst_status), nproc , 0)) == -1) {
LogError("system statistic error 1 -- pstat_getproc failed: %s\n", strerror(errno));
return 0;
}
pt = CALLOC(sizeof(ProcessTree_T), treesize);
for (i = 0; i < treesize; i++) {
pt[i].pid = psall[i].pst_pid;
pt[i].ppid = psall[i].pst_ppid;
pt[i].starttime = psall[i].pst_start;
pt[i].time = get_float_time();
pt[i].cputime = psall[i].pst_utime + psall[i].pst_stime * 10;
pt[i].cpu_percent = (int)(1000. * psall[i].pst_pctcpu / (float)systeminfo.cpus);
pt[i].mem_kbyte = (unsigned long)(psall[i].pst_rssize * (page_size / 1024.0));
pt[i].cmdline = (psall[i].pst_cmd && *psall[i].pst_cmd) ? Str_dup(psall[i].pst_cmd) : Str_dup(psall[i].pst_ucomm);
if ( psall[i].pst_stat == PS_ZOMBIE )
pt[i].status_flag |= PROCESS_ZOMBIE;
}
*reference = pt;
return treesize;
}
/**
* This routine returns kbyte of real memory in use.
* @return: TRUE if successful, FALSE if failed (or not available)
*/
int used_system_memory_sysdep(SystemInfo_T *si) {
int i, n, num;
struct pst_static pst;
struct pst_dynamic psd;
struct swaptable *s;
char *strtab;
unsigned long long total = 0ULL;
unsigned long long used = 0ULL;
/* Memory */
if(pstat_getstatic(&pst, sizeof(pst), (size_t)1, 0) == -1) {
LogError("system statistic error -- pstat_getstatic failed: %s\n", STRERROR);
return FALSE;
}
if(pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) == -1) {
LogError("system statistic error -- pstat_getdynamic failed: %s\n", STRERROR);
return FALSE;
}
si->total_mem_kbyte = (unsigned long)((pst.physical_memory - psd.psd_free) * (pst.page_size/1024));
/* Swap */
again:
if ((num = swapctl(SC_GETNSWP, 0)) == -1) {
LogError("system statistic error -- swap usage gathering failed: %s\n", STRERROR);
return FALSE;
}
if (num == 0) {
DEBUG("system statistic -- no swap configured\n");
si->swap_kbyte_max = 0;
return TRUE;
}
s = (struct swaptable *)ALLOC(num * sizeof(struct swapent) + sizeof(struct swaptable));
strtab = (char *)ALLOC((num + 1) * MAXSTRSIZE);
for (i = 0; i < (num + 1); i++)
s->swt_ent[i].ste_path = strtab + (i * MAXSTRSIZE);
s->swt_n = num + 1;
if ((n = swapctl(SC_LIST, s)) < 0) {
LogError("system statistic error -- swap usage gathering failed: %s\n", STRERROR);
si->swap_kbyte_max = 0;
FREE(s);
FREE(strtab);
return FALSE;
}
if (n > num) {
DEBUG("system statistic -- new swap added: deferring swap usage statistics to next cycle\n");
FREE(s);
FREE(strtab);
goto again;
}
for (i = 0; i < n; i++) {
if (!(s->swt_ent[i].ste_flags & ST_INDEL) && !(s->swt_ent[i].ste_flags & ST_DOINGDEL)) {
total += s->swt_ent[i].ste_pages;
used += s->swt_ent[i].ste_pages - s->swt_ent[i].ste_free;
}
}
FREE(s);
FREE(strtab);
si->swap_kbyte_max = (unsigned long)(double)(total * page_size) / 1024.;
si->total_swap_kbyte = (unsigned long)(double)(used * page_size) / 1024.;
return TRUE;
}
/**
* This routine returns system/user CPU time in use.
* @return: TRUE if successful, FALSE if failed (or not available)
*/
int used_system_cpu_sysdep(SystemInfo_T *si) {
int i;
long cpu_total;
long cpu_total_new = 0;
long cpu_user = 0;
long cpu_syst = 0;
long cpu_wait = 0;
struct pst_dynamic psd;
pstat_getdynamic(&psd, sizeof(psd), 1, 0);
for(i = 0; i < CPUSTATES; i++)
cpu_total_new += psd.psd_cpu_time[i];
cpu_total = cpu_total_new - cpu_total_old;
cpu_total_old = cpu_total_new;
cpu_user = psd.psd_cpu_time[CP_USER] + psd.psd_cpu_time[CP_NICE];
cpu_syst = psd.psd_cpu_time[CP_SYS];
cpu_wait = psd.psd_cpu_time[CP_WAIT];
si->total_cpu_user_percent = (cpu_total > 0)?(int)(1000 * (double)(cpu_user - cpu_user_old) / cpu_total):-10;
si->total_cpu_syst_percent = (cpu_total > 0)?(int)(1000 * (double)(cpu_syst - cpu_syst_old) / cpu_total):-10;
si->total_cpu_wait_percent = (cpu_total > 0)?(int)(1000 * (double)(cpu_wait - cpu_wait_old) / cpu_total):-10;
cpu_user_old = cpu_user;
cpu_syst_old = cpu_syst;
cpu_wait_old = cpu_wait;
return TRUE;
}