From 5dfb5242370610dfad09c855925224c587edbfbf Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 25 Mar 2021 17:24:14 +1100 Subject: [PATCH] Implement command line and environment handling for pcp htop. --- .gitignore | 3 ++- Makefile.am | 7 +++-- pcp-htop.c | 26 ++++++++++++++++++ pcp/PCPProcessList.c | 10 +++---- pcp/Platform.c | 64 +++++++++++++++++++++++++++++++++++++++++--- pcp/Platform.h | 17 ++++++++++++ 6 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 pcp-htop.c diff --git a/.gitignore b/.gitignore index 4aebe4c9..fe0279fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -# the binary: +# the binaries: htop +pcp-htop # all object files *.o diff --git a/Makefile.am b/Makefile.am index 8ae0e1f9..52c42157 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ @@ -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 diff --git a/pcp-htop.c b/pcp-htop.c new file mode 100644 index 00000000..eb81cfaa --- /dev/null +++ b/pcp-htop.c @@ -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 + +#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); +} diff --git a/pcp/PCPProcessList.c b/pcp/PCPProcessList.c index 780862b3..847765a2 100644 --- a/pcp/PCPProcessList.c +++ b/pcp/PCPProcessList.c @@ -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; @@ -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)); } @@ -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); @@ -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); @@ -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) diff --git a/pcp/Platform.c b/pcp/Platform.c index 70af0a85..2a591dee 100644 --- a/pcp/Platform.c +++ b/pcp/Platform.c @@ -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; @@ -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)); @@ -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; +} diff --git a/pcp/Platform.h b/pcp/Platform.h index 1661be77..33ea0db7 100644 --- a/pcp/Platform.h +++ b/pcp/Platform.h @@ -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 */