**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
/* Include header files for the mach system, if they exist.. */
#if HAVE_THREAD_INFO
unsigned long vmem_code;
unsigned long stack_size;
- unsigned long vmem_minflt;
- unsigned long vmem_majflt;
derive_t vmem_minflt_counter;
derive_t vmem_majflt_counter;
- unsigned long cpu_user;
- unsigned long cpu_system;
derive_t cpu_user_counter;
derive_t cpu_system_counter;
derive_t io_wchar;
derive_t io_syscr;
derive_t io_syscw;
+ _Bool has_io;
derive_t cswitch_vol;
derive_t cswitch_invol;
+ _Bool has_cswitch;
struct procstat_entry_s *next;
} procstat_entry_t;
static procstat_t *list_head_g = NULL;
+static _Bool want_init = 1;
static _Bool report_ctx_switch = 0;
#if HAVE_THREAD_INFO
#elif KERNEL_LINUX
static long pagesize_g;
+static void ps_fill_details (const procstat_t *ps, procstat_entry_t *entry);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
return (0);
} /* int ps_list_match */
-static void ps_update_counter (_Bool init, derive_t *group_counter,
- derive_t *curr_counter, unsigned long *curr_value,
- derive_t new_counter, unsigned long new_value)
+static void ps_update_counter (derive_t *group_counter,
+ derive_t *curr_counter, derive_t new_counter)
{
- if (init)
+ unsigned long curr_value;
+
+ if (want_init)
{
- *curr_value = new_value;
- *curr_counter += new_value;
- *group_counter += new_value;
+ *curr_counter = new_counter;
return;
}
if (new_counter < *curr_counter)
- *curr_value = new_counter + (ULONG_MAX - *curr_counter);
+ curr_value = new_counter + (ULONG_MAX - *curr_counter);
else
- *curr_value = new_counter - *curr_counter;
+ curr_value = new_counter - *curr_counter;
*curr_counter = new_counter;
- *group_counter += *curr_value;
+ *group_counter += curr_value;
}
/* add process entry to 'instances' of process 'name' (or refresh it) */
static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
{
- procstat_t *ps;
procstat_entry_t *pse;
if (entry->id == 0)
return;
- for (ps = list_head_g; ps != NULL; ps = ps->next)
+ for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
{
- _Bool want_init;
-
if ((ps_list_match (name, cmdline, ps)) == 0)
continue;
+#if KERNEL_LINUX
+ ps_fill_details(ps, entry);
+#endif
+
for (pse = ps->instances; pse != NULL; pse = pse->next)
if ((pse->id == entry->id) || (pse->next == NULL))
break;
ps->cswitch_vol += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
- want_init = (entry->vmem_minflt_counter == 0)
- && (entry->vmem_majflt_counter == 0);
- ps_update_counter (want_init,
+ ps_update_counter (
&ps->vmem_minflt_counter,
- &pse->vmem_minflt_counter, &pse->vmem_minflt,
- entry->vmem_minflt_counter, entry->vmem_minflt);
- ps_update_counter (want_init,
+ &pse->vmem_minflt_counter,
+ entry->vmem_minflt_counter);
+ ps_update_counter (
&ps->vmem_majflt_counter,
- &pse->vmem_majflt_counter, &pse->vmem_majflt,
- entry->vmem_majflt_counter, entry->vmem_majflt);
+ &pse->vmem_majflt_counter,
+ entry->vmem_majflt_counter);
- want_init = (entry->cpu_user_counter == 0)
- && (entry->cpu_system_counter == 0);
- ps_update_counter (want_init,
+ ps_update_counter (
&ps->cpu_user_counter,
- &pse->cpu_user_counter, &pse->cpu_user,
- entry->cpu_user_counter, entry->cpu_user);
- ps_update_counter (want_init,
+ &pse->cpu_user_counter,
+ entry->cpu_user_counter);
+ ps_update_counter (
&ps->cpu_system_counter,
- &pse->cpu_system_counter, &pse->cpu_system,
- entry->cpu_system_counter, entry->cpu_system);
+ &pse->cpu_system_counter,
+ entry->cpu_system_counter);
}
}
/* remove old entries from instances of processes in list_head_g */
static void ps_list_reset (void)
{
- procstat_t *ps;
procstat_entry_t *pse;
procstat_entry_t *pse_prev;
- for (ps = list_head_g; ps != NULL; ps = ps->next)
+ for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
{
ps->num_proc = 0;
ps->num_lwp = 0;
/* put all pre-defined 'Process' names from config to list_head_g tree */
static int ps_config (oconfig_item_t *ci)
{
- int i;
-
#if KERNEL_LINUX
const size_t max_procname_len = 15;
#elif KERNEL_SOLARIS || KERNEL_FREEBSD
const size_t max_procname_len = MAXCOMLEN -1;
#endif
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (strcasecmp (c->key, "Process") == 0)
/* submit global state (e.g.: qty of zombies, running, etc..) */
static void ps_submit_state (const char *state, double value)
{
- value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- values[0].gauge = value;
-
- vl.values = values;
+ vl.values = &(value_t) { .gauge = value };
vl.values_len = 1;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
sstrncpy (vl.type, "ps_state", sizeof (vl.type));
/* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */
static void ps_submit_proc_list (procstat_t *ps)
{
- value_t values[2];
value_list_t vl = VALUE_LIST_INIT;
+ value_t values[2];
vl.values = values;
- vl.values_len = 2;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
#if KERNEL_LINUX || KERNEL_SOLARIS
static void ps_submit_fork_rate (derive_t value)
{
- value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- values[0].derive = value;
-
- vl.values = values;
+ vl.values = &(value_t) { .derive = value };
vl.values_len = 1;
- sstrncpy(vl.host, hostname_g, sizeof (vl.host));
sstrncpy(vl.plugin, "processes", sizeof (vl.plugin));
sstrncpy(vl.plugin_instance, "", sizeof (vl.plugin_instance));
sstrncpy(vl.type, "fork_rate", sizeof (vl.type));
/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
-static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
+static int ps_read_tasks_status (procstat_entry_t *ps)
{
char dirname[64];
DIR *dh;
char *fields[8];
int numfields;
- ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", pid);
+ ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", ps->id);
if ((dh = opendir (dirname)) == NULL)
{
DEBUG ("Failed to open directory `%s'", dirname);
- return (NULL);
+ return (-1);
}
while ((ent = readdir (dh)) != NULL)
tpid = ent->d_name;
- ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", pid, tpid);
+ ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", ps->id, tpid);
if ((fh = fopen (filename, "r")) == NULL)
{
DEBUG ("Failed to open file `%s'", filename);
ps->cswitch_vol = cswitch_vol;
ps->cswitch_invol = cswitch_invol;
- return (ps);
+ return (0);
} /* int *ps_read_tasks_status */
/* Read data from /proc/pid/status */
return (ps);
} /* procstat_t *ps_read_vmem */
-static procstat_t *ps_read_io (long pid, procstat_t *ps)
+static int ps_read_io (procstat_entry_t *ps)
{
FILE *fh;
char buffer[1024];
char *fields[8];
int numfields;
- ssnprintf (filename, sizeof (filename), "/proc/%li/io", pid);
+ ssnprintf (filename, sizeof (filename), "/proc/%li/io", ps->id);
if ((fh = fopen (filename, "r")) == NULL)
- return (NULL);
+ return (-1);
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
WARNING ("processes: fclose: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
}
+ return (0);
+} /* int ps_read_io (...) */
- return (ps);
-} /* procstat_t *ps_read_io */
+static void ps_fill_details (const procstat_t *ps, procstat_entry_t *entry)
+{
+ if ( entry->has_io == 0 && ps_read_io (entry) != 0 )
+ {
+ /* no io data */
+ entry->io_rchar = -1;
+ entry->io_wchar = -1;
+ entry->io_syscr = -1;
+ entry->io_syscw = -1;
+
+ DEBUG("ps_read_process: not get io data for pid %li", entry->id);
+ }
+ entry->has_io = 1;
+
+ if ( report_ctx_switch )
+ {
+ if ( entry->has_cswitch == 0 && ps_read_tasks_status(entry) != 0 )
+ {
+ entry->cswitch_vol = -1;
+ entry->cswitch_invol = -1;
+
+ DEBUG("ps_read_tasks_status: not get context "
+ "switch data for pid %li", entry->id);
+ }
+ entry->has_cswitch = 1;
+ }
+} /* void ps_fill_details (...) */
static int ps_read_process (long pid, procstat_t *ps, char *state)
{
ps->vmem_rss = (unsigned long) vmem_rss;
ps->stack_size = (unsigned long) stack_size;
- if ( (ps_read_io (pid, ps)) == NULL)
- {
- /* no io data */
- ps->io_rchar = -1;
- ps->io_wchar = -1;
- ps->io_syscr = -1;
- ps->io_syscw = -1;
-
- DEBUG("ps_read_process: not get io data for pid %li", pid);
- }
-
- if ( report_ctx_switch )
- {
- if ( (ps_read_tasks_status(pid, ps)) == NULL)
- {
- ps->cswitch_vol = -1;
- ps->cswitch_invol = -1;
-
- DEBUG("ps_read_tasks_status: not get context "
- "switch data for pid %li", pid);
- }
- }
-
/* success */
return (0);
} /* int ps_read_process (...) */
static int read_fork_rate (void)
{
extern kstat_ctl_t *kc;
- kstat_t *ksp_chain = NULL;
derive_t result = 0;
if (kc == NULL)
return (-1);
- for (ksp_chain = kc->kc_chain;
+ for (kstat_t *ksp_chain = kc->kc_chain;
ksp_chain != NULL;
ksp_chain = ksp_chain->ks_next)
{
#if HAVE_THREAD_INFO
kern_return_t status;
- int pset;
processor_set_t port_pset_priv;
- int task;
task_array_t task_list;
mach_msg_type_number_t task_list_len;
int task_pid;
char task_name[MAXCOMLEN + 1];
- int thread;
thread_act_array_t thread_list;
mach_msg_type_number_t thread_list_len;
thread_basic_info_data_t thread_data;
* Tasks are assigned to sets of processors, so that's where you go to
* get a list.
*/
- for (pset = 0; pset < pset_list_len; pset++)
+ for (mach_msg_type_number_t pset = 0; pset < pset_list_len; pset++)
{
if ((status = host_processor_set_priv (port_host_self,
pset_list[pset],
continue;
}
- for (task = 0; task < task_list_len; task++)
+ for (mach_msg_type_number_t task = 0; task < task_list_len; task++)
{
ps = NULL;
if (mach_get_task_name (task_list[task],
continue; /* with next task_list */
}
- for (thread = 0; thread < thread_list_len; thread++)
+ for (mach_msg_type_number_t thread = 0; thread < thread_list_len; thread++)
{
thread_data_len = THREAD_BASIC_INFO_COUNT;
status = thread_info (thread_list[thread],
procstat_entry_t pse;
char state;
- procstat_t *ps_ptr;
-
running = sleeping = zombies = stopped = paging = blocked = 0;
ps_list_reset ();
pse.vmem_code = ps.vmem_code;
pse.stack_size = ps.stack_size;
- pse.vmem_minflt = 0;
pse.vmem_minflt_counter = ps.vmem_minflt_counter;
- pse.vmem_majflt = 0;
pse.vmem_majflt_counter = ps.vmem_majflt_counter;
- pse.cpu_user = 0;
pse.cpu_user_counter = ps.cpu_user_counter;
- pse.cpu_system = 0;
pse.cpu_system_counter = ps.cpu_system_counter;
pse.io_rchar = ps.io_rchar;
ps_submit_state ("paging", paging);
ps_submit_state ("blocked", blocked);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
read_fork_rate();
struct kinfo_proc *procs; /* array of processes */
struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
- int i;
- procstat_t *ps_ptr;
procstat_entry_t pse;
ps_list_reset ();
}
/* Iterate through the processes in kinfo_proc */
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
{
/* Create only one process list entry per _process_, i.e.
* filter out threads (duplicate PID entries). */
pse.vmem_data = procs[i].ki_dsize * pagesize;
pse.vmem_code = procs[i].ki_tsize * pagesize;
pse.stack_size = procs[i].ki_ssize * pagesize;
- pse.vmem_minflt = 0;
pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt;
- pse.vmem_majflt = 0;
pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt;
- pse.cpu_user = 0;
- pse.cpu_system = 0;
pse.cpu_user_counter = 0;
pse.cpu_system_counter = 0;
/*
ps_submit_state ("idle", idle);
ps_submit_state ("wait", wait);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
struct kinfo_proc *procs; /* array of processes */
struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
- int i;
- procstat_t *ps_ptr;
procstat_entry_t pse;
ps_list_reset ();
}
/* Iterate through the processes in kinfo_proc */
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
{
/* Create only one process list entry per _process_, i.e.
* filter out threads (duplicate PID entries). */
pse.vmem_code = procs[i].p_vm_tsize * pagesize;
pse.stack_size = procs[i].p_vm_ssize * pagesize;
pse.vmem_size = pse.stack_size + pse.vmem_code + pse.vmem_data;
- pse.vmem_minflt = 0;
pse.vmem_minflt_counter = procs[i].p_uru_minflt;
- pse.vmem_majflt = 0;
pse.vmem_majflt_counter = procs[i].p_uru_majflt;
- pse.cpu_user = 0;
- pse.cpu_system = 0;
pse.cpu_user_counter = procs[i].p_uutime_usec +
(1000000lu * procs[i].p_uutime_sec);
pse.cpu_system_counter = procs[i].p_ustime_usec +
ps_submit_state ("idle", idle);
ps_submit_state ("dead", dead);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
pid_t pindex = 0;
int nprocs;
- procstat_t *ps;
procstat_entry_t pse;
ps_list_reset ();
/* fdsinfo = */ NULL, sizeof(struct fdsinfo64),
&pindex, MAXPROCENTRY)) > 0)
{
- int i;
-
- for (i = 0; i < nprocs; i++)
+ for (int i = 0; i < nprocs; i++)
{
tid64_t thindex;
int nthreads;
break;
}
- pse.cpu_user = 0;
/* tv_usec is nanosec ??? */
pse.cpu_user_counter = procentry[i].pi_ru.ru_utime.tv_sec * 1000000 +
procentry[i].pi_ru.ru_utime.tv_usec / 1000;
pse.cpu_system_counter = procentry[i].pi_ru.ru_stime.tv_sec * 1000000 +
procentry[i].pi_ru.ru_stime.tv_usec / 1000;
- pse.vmem_minflt = 0;
pse.vmem_minflt_counter = procentry[i].pi_minflt;
- pse.vmem_majflt = 0;
pse.vmem_majflt_counter = procentry[i].pi_majflt;
pse.vmem_size = procentry[i].pi_tsize + procentry[i].pi_dvm * pagesize;
ps_submit_state ("paging", paging);
ps_submit_state ("blocked", blocked);
- for (ps = list_head_g; ps != NULL; ps = ps->next)
+ for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
ps_submit_proc_list (ps);
/* #endif HAVE_PROCINFO_H */
DIR *proc;
int status;
- procstat_t *ps_ptr;
char state;
char cmdline[PRARGSZ];
pse.vmem_code = ps.vmem_code;
pse.stack_size = ps.stack_size;
- pse.vmem_minflt = 0;
pse.vmem_minflt_counter = ps.vmem_minflt_counter;
- pse.vmem_majflt = 0;
pse.vmem_majflt_counter = ps.vmem_majflt_counter;
- pse.cpu_user = 0;
pse.cpu_user_counter = ps.cpu_user_counter;
- pse.cpu_system = 0;
pse.cpu_system_counter = ps.cpu_system_counter;
pse.io_rchar = ps.io_rchar;
ps_submit_state ("system", system);
ps_submit_state ("orphan", orphan);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
read_fork_rate();
#endif /* KERNEL_SOLARIS */
+ want_init = 0;
+
return (0);
} /* int ps_read */