Skip to content

Commit

Permalink
Implement command line and environment handling for pcp htop.
Browse files Browse the repository at this point in the history
  • Loading branch information
natoscott committed Jun 9, 2021
1 parent b424a5b commit 5dfb524
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# the binary:
# the binaries:
htop
pcp-htop

# all object files
*.o
Expand Down
7 changes: 5 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,7 @@ pcp_platform_headers = \
zfs/ZfsArcStats.h \
zfs/ZfsCompressedArcMeter.h

if HTOP_PCP
myhtopplatsources = \
pcp_platform_sources = \
pcp/PCPProcess.c \
pcp/PCPProcessList.c \
pcp/Platform.c \
Expand All @@ -353,7 +352,11 @@ myhtopplatsources = \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c

if HTOP_PCP
myhtopplatprogram = pcp-htop
myhtopplatheaders = $(pcp_platform_headers)
myhtopplatsources = $(pcp_platform_sources)
pcp_htop_SOURCES = $(htop_SOURCES)
endif

# Unsupported
Expand Down
26 changes: 26 additions & 0 deletions pcp-htop.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
htop - pcp-htop.c
(C) 2004-2011 Hisham H. Muhammad
(C) 2020-2021 htop dev team
Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/

#include "config.h" // IWYU pragma: keep

#include <pcp/pmapi.h>

#include "CommandLine.h"
#include "Platform.h"


int main(int argc, char** argv) {
const char* name = "pcp-htop";
pmSetProgname(name);

/* extract environment variables */
opts.flags |= PM_OPTFLAG_ENV_ONLY;
pmGetOptions(argc, argv, &opts);

return CommandLine_run(name, argc, argv);
}
10 changes: 5 additions & 5 deletions pcp/PCPProcessList.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static int PCPProcessList_computeCPUcount(void) {

static void PCPProcessList_updateCPUcount(PCPProcessList* this) {
ProcessList* pl = &(this->super);
int cpus = PCPProcessList_computeCPUcount();
unsigned int cpus = PCPProcessList_computeCPUcount();
if (cpus == pl->cpuCount)
return;

Expand All @@ -40,7 +40,7 @@ static void PCPProcessList_updateCPUcount(PCPProcessList* this) {
free(this->values);

this->percpu = xCalloc(cpus, sizeof(pmAtomValue *));
for (int i = 0; i < cpus; i++)
for (unsigned int i = 0; i < cpus; i++)
this->percpu[i] = xCalloc(CPU_METRIC_COUNT, sizeof(pmAtomValue));
this->values = xCalloc(cpus, sizeof(pmAtomValue));
}
Expand Down Expand Up @@ -78,7 +78,7 @@ void ProcessList_delete(ProcessList* pl) {
PCPProcessList* this = (PCPProcessList*) pl;
ProcessList_done(pl);
free(this->values);
for (int i = 0; i < pl->cpuCount; i++)
for (unsigned int i = 0; i < pl->cpuCount; i++)
free(this->percpu[i]);
free(this->percpu);
free(this->cpu);
Expand Down Expand Up @@ -716,7 +716,7 @@ static void PCPProcessList_updateHeader(ProcessList* super, const Settings* sett
PCPProcessList_updateAllCPUTime(this, PCP_CPU_GUEST, CPU_GUEST_TIME);
PCPProcessList_deriveCPUTime(this->cpu);

for (int i = 0; i < super->cpuCount; i++)
for (unsigned int i = 0; i < super->cpuCount; i++)
PCPProcessList_backupCPUTime(this->percpu[i]);
PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_USER, CPU_USER_TIME);
PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_NICE, CPU_NICE_TIME);
Expand All @@ -727,7 +727,7 @@ static void PCPProcessList_updateHeader(ProcessList* super, const Settings* sett
PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_SOFTIRQ, CPU_SOFTIRQ_TIME);
PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_STEAL, CPU_STEAL_TIME);
PCPProcessList_updatePerCPUTime(this, PCP_PERCPU_GUEST, CPU_GUEST_TIME);
for (int i = 0; i < super->cpuCount; i++)
for (unsigned int i = 0; i < super->cpuCount; i++)
PCPProcessList_deriveCPUTime(this->percpu[i]);

if (settings->showCPUFrequency)
Expand Down
64 changes: 61 additions & 3 deletions pcp/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ typedef struct Platform_ {
pmResult* result; /* sample values result indexed by Metric */

long long btime; /* boottime in seconds since the epoch */
char *release; /* uname and distro from this context */
char* release; /* uname and distro from this context */
int pidmax; /* maximum platform process identifier */
int ncpu; /* maximum processor count configured */
} Platform;
Expand Down Expand Up @@ -403,14 +403,28 @@ static int Platform_addMetric(Metric id, const char *name) {
return ++pcp->total;
}

/* global state from the environment and command line arguments */
pmOptions opts;

void Platform_init(void) {
int sts = pmNewContext(PM_CONTEXT_HOST, "local:");
if (sts < 0)
const char* host = opts.nhosts > 0 ? opts.hosts[0] : "local:";

int sts;
sts = pmNewContext(PM_CONTEXT_HOST, host);
/* with no host requested, fallback to PM_CONTEXT_LOCAL shared libraries */
if (sts < 0 && opts.nhosts == 0)
sts = pmNewContext(PM_CONTEXT_LOCAL, NULL);
if (sts < 0) {
fprintf(stderr, "Cannot setup PCP metric source: %s\n", pmErrStr(sts));
exit(1);
}
/* setup timezones and other general startup preparation completion */
pmGetContextOptions(sts, &opts);
if (opts.errors) {
pmflush();
exit(1);
}

pcp = xCalloc(1, sizeof(Platform));
pcp->context = sts;
pcp->fetch = xCalloc(PCP_METRIC_COUNT, sizeof(pmID));
Expand Down Expand Up @@ -795,3 +809,47 @@ void Platform_getBattery(double* level, ACPresence* isOnAC) {
*level = NAN;
*isOnAC = AC_ERROR;
}

void Platform_longOptionsUsage(ATTR_UNUSED const char* name) {
printf(
" --host=HOSTSPEC metrics source is PMCD at HOSTSPEC [see PCPIntro(1)]\n"
" --hostzone set reporting timezone to local time of metrics source\n"
" --timezone=TZ set reporting timezone\n");
}

bool Platform_getLongOption(int opt, ATTR_UNUSED int argc, char** argv) {
/* libpcp export without a header definition */
extern void __pmAddOptHost(pmOptions *, char *);

switch (opt) {
case PLATFORM_LONGOPT_HOST: /* --host=HOSTSPEC */
if (argv[optind][0] == '\0')
return false;
__pmAddOptHost(&opts, optarg);
return true;

case PLATFORM_LONGOPT_HOSTZONE: /* --hostzone */
if (opts.timezone) {
pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname());
opts.errors++;
} else {
opts.tzflag = 1;
}
return true;

case PLATFORM_LONGOPT_TIMEZONE: /* --timezone=TZ */
if (argv[optind][0] == '\0')
return false;
if (opts.tzflag) {
pmprintf("%s: at most one of -Z and -z allowed\n", pmGetProgname());
opts.errors++;
} else {
opts.timezone = optarg;
}
return true;

default:
break;
}
return false;
}
17 changes: 17 additions & 0 deletions pcp/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,23 @@ void Platform_getHostname(char* buffer, size_t size);

void Platform_getRelease(char** string);

enum {
PLATFORM_LONGOPT_HOST = 128,
PLATFORM_LONGOPT_TIMEZONE,
PLATFORM_LONGOPT_HOSTZONE,
};

#define PLATFORM_LONG_OPTIONS \
{PMLONGOPT_HOST, optional_argument, 0, PLATFORM_LONGOPT_HOST}, \
{PMLONGOPT_TIMEZONE, optional_argument, 0, PLATFORM_LONGOPT_TIMEZONE}, \
{PMLONGOPT_HOSTZONE, optional_argument, 0, PLATFORM_LONGOPT_HOSTZONE}, \

void Platform_longOptionsUsage(const char* name);

bool Platform_getLongOption(int opt, int argc, char** argv);

extern pmOptions opts;


typedef enum Metric_ {
PCP_CONTROL_THREADS, /* proc.control.perclient.threads */
Expand Down

0 comments on commit 5dfb524

Please sign in to comment.