diff options
author | Nathan Scott <nathans@redhat.com> | 2021-06-23 17:44:56 +1000 |
---|---|---|
committer | Nathan Scott <nathans@redhat.com> | 2021-07-07 10:59:36 +1000 |
commit | f0ed0fdafb9ecefc9d103ffb8f5d91bf723518f6 (patch) | |
tree | 8f82bf54c96a07d8efa5c9a8bd2c50865bd6757a | |
parent | 865b85eb2d31321e9c37334838fa514ac348d61a (diff) |
Add a new DynamicMeter class for runtime Meter extension
This commit is based on exploratory work by Sohaib Mohamed.
The end goal is two-fold - to support addition of Meters we
build via configuration files for both the PCP platform and
for scripts ( https://github.com/htop-dev/htop/issues/526 )
Here, we focus on generic code and the PCP support. A new
class DynamicMeter is introduced - it uses the special case
'param' field handling that previously was used only by the
CPUMeter, such that every runtime-configured Meter is given
a unique identifier. Unlike with the CPUMeter this is used
internally only. When reading/writing to htoprc instead of
CPU(N) - where N is an integer param (CPU number) - we use
the string name for each meter. For example, if we have a
configuration for a DynamicMeter for some Redis metrics, we
might read and write "Dynamic(redis)". This identifier is
subsequently matched (back) up to the configuration file so
we're able to re-create arbitrary user configurations.
The PCP platform configuration file format is fairly simple.
We expand configs from several directories, including the
users homedir alongside htoprc (below htop/meters/) and also
/etc/pcp/htop/meters. The format will be described via a
new pcp-htop(5) man page, but its basically ini-style and
each Meter has one or more metric expressions associated, as
well as specifications for labels, color and so on via a dot
separated notation for individual metrics within the Meter.
A few initial sample configuration files are provided below
./pcp/meters that give the general idea. The PCP "derived"
metric specification - see pmRegisterDerived(3) - is used
as the syntax for specifying metrics in PCP DynamicMeters.
48 files changed, 1044 insertions, 68 deletions
diff --git a/AvailableMetersPanel.c b/AvailableMetersPanel.c index 22f2c5ef..048c7175 100644 --- a/AvailableMetersPanel.c +++ b/AvailableMetersPanel.c @@ -12,6 +12,7 @@ in the source distribution for its full text. #include <stdlib.h> #include "CPUMeter.h" +#include "DynamicMeter.h" #include "FunctionBar.h" #include "Header.h" #include "ListItem.h" @@ -91,6 +92,49 @@ const PanelClass AvailableMetersPanel_class = { .eventHandler = AvailableMetersPanel_eventHandler }; +// Handle (&CPUMeter_class) entries in the AvailableMetersPanel +static void AvailableMetersPanel_addCPUMeters(Panel* super, const MeterClass* type, const ProcessList* pl) { + if (pl->cpuCount > 1) { + Panel_add(super, (Object*) ListItem_new("CPU average", 0)); + for (unsigned int i = 1; i <= pl->cpuCount; i++) { + char buffer[50]; + xSnprintf(buffer, sizeof(buffer), "%s %d", type->uiName, Settings_cpuId(pl->settings, i - 1)); + Panel_add(super, (Object*) ListItem_new(buffer, i)); + } + } else { + Panel_add(super, (Object*) ListItem_new(type->uiName, 1)); + } +} + +typedef struct { + Panel* super; + unsigned int id; + unsigned int offset; +} DynamicIterator; + +static void AvailableMetersPanel_addDynamicMeter(ATTR_UNUSED ht_key_t key, void* value, void* data) { + const DynamicMeter* meter = (const DynamicMeter*)value; + DynamicIterator* iter = (DynamicIterator*)data; + unsigned int identifier = (iter->offset << 16) | iter->id; + const char* label = meter->description ? meter->description : meter->caption; + if (!label) label = meter->name; /* last fallback to name, guaranteed set */ + Panel_add(iter->super, (Object*) ListItem_new(label, identifier)); + iter->id++; +} + +// Handle (&DynamicMeter_class) entries in the AvailableMetersPanel +static void AvailableMetersPanel_addDynamicMeters(Panel* super, const ProcessList *pl, unsigned int offset) { + DynamicIterator iter = { .super = super, .id = 1, .offset = offset }; + assert(pl->dynamicMeters != NULL); + Hashtable_foreach(pl->dynamicMeters, AvailableMetersPanel_addDynamicMeter, &iter); +} + +// Handle remaining Platform Meter entries in the AvailableMetersPanel +static void AvailableMetersPanel_addPlatformMeter(Panel* super, const MeterClass* type, unsigned int offset) { + const char* label = type->description ? type->description : type->uiName; + Panel_add(super, (Object*) ListItem_new(label, offset << 16)); +} + AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl) { AvailableMetersPanel* this = AllocThis(AvailableMetersPanel); Panel* super = (Panel*) this; @@ -104,26 +148,19 @@ AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* heade this->scr = scr; Panel_setHeader(super, "Available meters"); - // Platform_meterTypes[0] should be always (&CPUMeter_class), which we will - // handle separately in the code below. - for (int i = 1; Platform_meterTypes[i]; i++) { + // Platform_meterTypes[0] should be always (&CPUMeter_class) which we will + // handle separately in the code below. Likewise, identifiers for Dynamic + // Meters are handled separately - similar to CPUs, this allows generation + // of multiple different Meters (also using 'param' to distinguish them). + for (unsigned int i = 1; Platform_meterTypes[i]; i++) { const MeterClass* type = Platform_meterTypes[i]; assert(type != &CPUMeter_class); - const char* label = type->description ? type->description : type->uiName; - Panel_add(super, (Object*) ListItem_new(label, i << 16)); - } - // Handle (&CPUMeter_class) - const MeterClass* type = &CPUMeter_class; - unsigned int cpus = pl->cpuCount; - if (cpus > 1) { - Panel_add(super, (Object*) ListItem_new("CPU average", 0)); - for (unsigned int i = 1; i <= cpus; i++) { - char buffer[50]; - xSnprintf(buffer, sizeof(buffer), "%s %d", type->uiName, Settings_cpuId(this->settings, i - 1)); - Panel_add(super, (Object*) ListItem_new(buffer, i)); - } - } else { - Panel_add(super, (Object*) ListItem_new("CPU", 1)); + if (type == &DynamicMeter_class) + AvailableMetersPanel_addDynamicMeters(super, pl, i); + else + AvailableMetersPanel_addPlatformMeter(super, type, i); } + AvailableMetersPanel_addCPUMeters(super, &CPUMeter_class, pl); + return this; } @@ -50,6 +50,14 @@ static void CPUMeter_init(Meter* this) { } } +// Custom uiName runtime logic to include the param (processor) +static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) { + if (this->param > 0) + xSnprintf(buffer, sizeof(length), "%s %u", Meter_uiName(this), this->param); + else + xSnprintf(buffer, sizeof(length), "%s", Meter_uiName(this)); +} + static void CPUMeter_updateValues(Meter* this) { unsigned int cpu = this->param; if (cpu > this->pl->cpuCount) { @@ -326,6 +334,7 @@ const MeterClass CPUMeter_class = { .display = CPUMeter_display }, .updateValues = CPUMeter_updateValues, + .getUiName = CPUMeter_getUiName, .defaultMode = BAR_METERMODE, .maxItems = CPU_METER_ITEMCOUNT, .total = 100.0, @@ -195,6 +195,15 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [ZFS_COMPRESSED] = ColorPair(Blue, Black), [ZFS_RATIO] = ColorPair(Magenta, Black), [ZRAM] = ColorPair(Yellow, Black), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Black), + [DYNAMIC_GREEN] = ColorPair(Green, Black), + [DYNAMIC_BLUE] = ColorPair(Blue, Black), + [DYNAMIC_CYAN] = ColorPair(Cyan, Black), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Black), + [DYNAMIC_WHITE] = ColorPair(White, Black), }, [COLORSCHEME_MONOCHROME] = { [RESET_COLOR] = A_NORMAL, @@ -288,6 +297,15 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [ZFS_COMPRESSED] = A_BOLD, [ZFS_RATIO] = A_BOLD, [ZRAM] = A_NORMAL, + [DYNAMIC_GRAY] = A_DIM, + [DYNAMIC_DARKGRAY] = A_DIM, + [DYNAMIC_RED] = A_BOLD, + [DYNAMIC_GREEN] = A_NORMAL, + [DYNAMIC_BLUE] = A_NORMAL, + [DYNAMIC_CYAN] = A_BOLD, + [DYNAMIC_MAGENTA] = A_NORMAL, + [DYNAMIC_YELLOW] = A_NORMAL, + [DYNAMIC_WHITE] = A_BOLD, }, [COLORSCHEME_BLACKONWHITE] = { [RESET_COLOR] = ColorPair(Black, White), @@ -380,7 +398,16 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [ZFS_OTHER] = ColorPair(Magenta, White), [ZFS_COMPRESSED] = ColorPair(Cyan, White), [ZFS_RATIO] = ColorPair(Magenta, White), - [ZRAM] = ColorPair(Yellow, White) + [ZRAM] = ColorPair(Yellow, White), + [DYNAMIC_GRAY] = ColorPair(Black, White), + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPair(Black, White), + [DYNAMIC_RED] = ColorPair(Red, White), + [DYNAMIC_GREEN] = ColorPair(Green, White), + [DYNAMIC_BLUE] = ColorPair(Blue, White), + [DYNAMIC_CYAN] = ColorPair(Yellow, White), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, White), + [DYNAMIC_YELLOW] = ColorPair(Yellow, White), + [DYNAMIC_WHITE] = A_BOLD | ColorPair(Black, White), }, [COLORSCHEME_LIGHTTERMINAL] = { [RESET_COLOR] = ColorPair(Black, Black), @@ -474,6 +501,15 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [ZFS_COMPRESSED] = ColorPair(Cyan, Black), [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black), [ZRAM] = ColorPair(Yellow, Black), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Black), + [DYNAMIC_GREEN] = ColorPair(Green, Black), + [DYNAMIC_BLUE] = ColorPair(Blue, Black), + [DYNAMIC_CYAN] = ColorPair(Cyan, Black), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Black), + [DYNAMIC_WHITE] = ColorPairWhiteDefault, }, [COLORSCHEME_MIDNIGHT] = { [RESET_COLOR] = ColorPair(White, Blue), @@ -567,6 +603,15 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [ZFS_COMPRESSED] = A_BOLD | ColorPair(White, Blue), [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Blue), [ZRAM] = A_BOLD | ColorPair(Yellow, Blue), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Blue), + [DYNAMIC_GREEN] = ColorPair(Green, Blue), + [DYNAMIC_BLUE] = ColorPair(Black, Blue), + [DYNAMIC_CYAN] = ColorPair(Cyan, Blue), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Blue), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Blue), + [DYNAMIC_WHITE] = ColorPair(White, Blue), }, [COLORSCHEME_BLACKNIGHT] = { [RESET_COLOR] = ColorPair(Cyan, Black), @@ -658,6 +703,15 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [ZFS_COMPRESSED] = ColorPair(Blue, Black), [ZFS_RATIO] = ColorPair(Magenta, Black), [ZRAM] = ColorPair(Yellow, Black), + [DYNAMIC_GRAY] = ColorPairGrayBlack, + [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack, + [DYNAMIC_RED] = ColorPair(Red, Black), + [DYNAMIC_GREEN] = ColorPair(Green, Black), + [DYNAMIC_BLUE] = ColorPair(Blue, Black), + [DYNAMIC_CYAN] = ColorPair(Cyan, Black), + [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black), + [DYNAMIC_YELLOW] = ColorPair(Yellow, Black), + [DYNAMIC_WHITE] = ColorPair(White, Black), }, [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. }; @@ -131,6 +131,15 @@ typedef enum ColorElements_ { ZFS_COMPRESSED, ZFS_RATIO, ZRAM, + DYNAMIC_GRAY, + DYNAMIC_DARKGRAY, + DYNAMIC_RED, + DYNAMIC_GREEN, + DYNAMIC_BLUE, + DYNAMIC_CYAN, + DYNAMIC_MAGENTA, + DYNAMIC_YELLOW, + DYNAMIC_WHITE, LAST_COLORELEMENT } ColorElements; diff --git a/CommandLine.c b/CommandLine.c index 60582dcf..4a721a3d 100644 --- a/CommandLine.c +++ b/CommandLine.c @@ -22,6 +22,7 @@ in the source distribution for its full text. #include "Action.h" #include "CRT.h" +#include "DynamicMeter.h" #include "Hashtable.h" #include "Header.h" #include "IncSet.h" @@ -288,7 +289,8 @@ int CommandLine_run(const char* name, int argc, char** argv) { Process_setupColumnWidths(); UsersTable* ut = UsersTable_new(); - ProcessList* pl = ProcessList_new(ut, flags.pidMatchList, flags.userId); + Hashtable* dm = DynamicMeters_new(); + ProcessList* pl = ProcessList_new(ut, dm, flags.pidMatchList, flags.userId); Settings* settings = Settings_new(pl->cpuCount); pl->settings = settings; diff --git a/DynamicMeter.c b/DynamicMeter.c new file mode 100644 index 00000000..7b39fdaa --- /dev/null +++ b/DynamicMeter.c @@ -0,0 +1,98 @@ +/* +htop - DynamicMeter.c +(C) 2021 htop dev team +(C) 2021 Red Hat, Inc. All Rights Reserved. +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ +#include "config.h" // IWYU pragma: keep + +#include "DynamicMeter.h" + +#include "CRT.h" +#include "Object.h" +#include "Platform.h" +#include "ProcessList.h" +#include "RichString.h" +#include "XUtils.h" + + +static const int DynamicMeter_attributes[] = { + DYNAMIC_GRAY, + DYNAMIC_DARKGRAY, + DYNAMIC_RED, + DYNAMIC_GREEN, + DYNAMIC_BLUE, + DYNAMIC_CYAN, + DYNAMIC_MAGENTA, + DYNAMIC_YELLOW, + DYNAMIC_WHITE +}; + +Hashtable* DynamicMeters_new(void) { + return Platform_dynamicMeters(); +} + +typedef struct { + unsigned int key; + const char* name; +} DynamicIterator; + +static void DynamicMeter_compare(ht_key_t key, void* value, void* data) { + const DynamicMeter* meter = (const DynamicMeter*)value; + DynamicIterator* iter = (DynamicIterator*)data; + if (String_eq(iter->name, meter->name)) + iter->key = key; +} + +unsigned int DynamicMeter_search(const ProcessList* pl, const char* name) { + DynamicIterator iter = { .key = 0, .name = name }; + if (pl->dynamicMeters) + Hashtable_foreach(pl->dynamicMeters, DynamicMeter_compare, &iter); + return iter.key; +} + +const char* DynamicMeter_lookup(const ProcessList* pl, unsigned int key) { + const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, key); + return meter ? meter->name : NULL; +} + +static void DynamicMeter_init(Meter* meter) { + Platform_dynamicMeterInit(meter); +} + +static void DynamicMeter_updateValues(Meter* meter) { + Platform_dynamicMeterUpdateValues(meter); +} + +static void DynamicMeter_display(const Object* cast, RichString* out) { + const Meter* meter = (const Meter*)cast; + Platform_dynamicMeterDisplay(meter, out); +} + +static void DynamicMeter_getUiName(const Meter* this, char* name, size_t length) { + const ProcessList* pl = this->pl; + const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, this->param); + if (meter) { + const char* uiName = meter->caption ? meter->caption : meter->name; + xSnprintf(name, length, "%s", uiName); + } +} + +const MeterClass DynamicMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = DynamicMeter_display + }, + .init = DynamicMeter_init, + .updateValues = DynamicMeter_updateValues, + .getUiName = DynamicMeter_getUiName, + .defaultMode = TEXT_METERMODE, + .maxItems = 0, + .total = 100.0, + .attributes = DynamicMeter_attributes, + .name = "Dynamic", + .uiName = "Dynamic", + .caption = "", +}; diff --git a/DynamicMeter.h b/DynamicMeter.h new file mode 100644 index 00000000..3d1bc9f2 --- /dev/null +++ b/DynamicMeter.h @@ -0,0 +1,25 @@ +#ifndef HEADER_DynamicMeter +#define HEADER_DynamicMeter + +#include "Meter.h" + + +typedef struct DynamicMeter_ { + char name[32]; /* unique name, cannot contain spaces */ + char* caption; + char* description; + unsigned int type; + double maximum; + + void* dynamicData; /* platform-specific meter data */ +} DynamicMeter; + +Hashtable* DynamicMeters_new(void); + +const char* DynamicMeter_lookup(const ProcessList* pl, unsigned int param); + +unsigned int DynamicMeter_search(const ProcessList* pl, const char* name); + +extern const MeterClass DynamicMeter_class; + +#endif @@ -13,6 +13,8 @@ in the source distribution for its full text. #include <string.h> #include "CRT.h" +#include "CPUMeter.h" +#include "DynamicMeter.h" #include "Macros.h" #include "Object.h" #include "Platform.h" @@ -70,7 +72,10 @@ void Header_writeBackToSettings(const Header* this) { for (int i = 0; i < len; i++) { const Meter* meter = (Meter*) Vector_get(vec, i); char* name; - if (meter->param) { + if (meter->param && As_Meter(meter) == &DynamicMeter_class) { + const char* dynamic = DynamicMeter_lookup(this->pl, meter->param); + xAsprintf(&name, "%s(%s)", As_Meter(meter)->name, dynamic); + } else if (meter->param && As_Meter(meter) == &CPUMeter_class) { xAsprintf(&name, "%s(%u)", As_Meter(meter)->name, meter->param); } else { xAsprintf(&name, "%s", As_Meter(meter)->name); @@ -87,9 +92,13 @@ MeterModeId Header_addMeterByName(Header* this, const char* name, int column) { char* paren = strchr(name, '('); unsigned int param = 0; if (paren) { - int ok = sscanf(paren, "(%10u)", ¶m); - if (!ok) - param = 0; + char* end, dynamic[32] = {0}; + int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter + if (!ok) { + ok = sscanf(paren, "(%30s)", dynamic); // DynamicMeter + if (ok && (end = strrchr(dynamic, ')'))) *end = '\0'; + param = ok ? DynamicMeter_search(this->pl, dynamic) : 0; + } *paren = '\0'; } MeterModeId mode = TEXT_METERMODE; diff --git a/Makefile.am b/Makefile.am index 079bcd86..ce50d0f7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,7 @@ myhtopsources = \ DateTimeMeter.c \ DiskIOMeter.c \ DisplayOptionsPanel.c \ + DynamicMeter.c \ EnvScreen.c \ FunctionBar.c \ Hashtable.c \ @@ -93,6 +94,7 @@ myhtopheaders = \ DateTimeMeter.h \ DiskIOMeter.h \ DisplayOptionsPanel.h \ + DynamicMeter.h \ EnvScreen.h \ FunctionBar.h \ Hashtable.h \ @@ -357,6 +359,7 @@ endif # -------------------------- pcp_platform_headers = \ + pcp/PCPDynamicMeter.h \ pcp/PCPProcess.h \ pcp/PCPProcessList.h \ pcp/Platform.h \ @@ -369,6 +372,7 @@ pcp_platform_headers = \ zfs/ZfsCompressedArcMeter.h pcp_platform_sources = \ + pcp/PCPDynamicMeter.c \ pcp/PCPProcess.c \ pcp/PCPProcessList.c \ pcp/Platform.c \ @@ -138,14 +138,13 @@ ListItem* Meter_toListItem(const Meter* this, bool moving) { } else { mode[0] = '\0'; } - char number[10]; - if (this->param > 0) { - xSnprintf(number, sizeof(number), " %u", this->param); - } else { - number[0] = '\0'; - } + char name[32]; + if (Meter_getUiNameFn(this)) + Meter_getUiName(this, name, sizeof(name)); + else + xSnprintf(name, sizeof(name), "%s", Meter_uiName(this)); char buffer[50]; - xSnprintf(buffer, sizeof(buffer), "%s%s%s", Meter_uiName(this), number, mode); + xSnprintf(buffer, sizeof(buffer), "%s%s", name, mode); ListItem* li = ListItem_new(buffer, 0); li->moving = moving; return li; @@ -53,14 +53,16 @@ typedef void(*Meter_Done)(Meter*); typedef void(*Meter_UpdateMode)(Meter*, int); typedef void(*Meter_UpdateValues)(Meter*); typedef void(*Meter_Draw)(Meter*, int, int, int); +typedef void(*Meter_GetUiName)(const Meter*, char*, size_t); typedef struct MeterClass_ { const ObjectClass super; const Meter_Init init; const Meter_Done done; const Meter_UpdateMode updateMode; - const Meter_Draw draw; const Meter_UpdateValues updateValues; + const Meter_Draw draw; + const Meter_GetUiName getUiName; const int defaultMode; const double total; const int* const attributes; @@ -80,6 +82,8 @@ typedef struct MeterClass_ { #define Meter_drawFn(this_) As_Meter(this_)->draw #define Meter_doneFn(this_) As_Meter(this_)->done #define Meter_updateValues(this_) As_Meter(this_)->updateValues((Meter*)(this_)) +#define Meter_getUiNameFn(this_) As_Meter(this_)->getUiName +#define Meter_getUiName(this_,n_,l_) As_Meter(this_)->getUiName((const Meter*)(this_),n_,l_) #define Meter_defaultMode(this_) As_Meter(this_)->defaultMode #define Meter_attributes(this_) As_Meter(this_)->attributes #define Meter_name(this_) As_Meter(this_)->name diff --git a/ProcessList.c b/ProcessList.c index da5d7a91..82f719f8 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -19,7 +19,7 @@ in the source distribution for its full text. #include "XUtils.h" -ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) { +ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { this->processes = Vector_new(klass, true, DEFAULT_SIZE); this->processes2 = Vector_new(klass, true, DEFAULT_SIZE); // tree-view auxiliary buffer @@ -29,6 +29,7 @@ ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, Users this->usersTable = usersTable; this->pidMatchList = pidMatchList; + this->dynamicMeters = dynamicMeters; this->userId = userId; diff --git a/ProcessList.h b/ProcessList.h index 32bdfa18..da4a50da 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -50,6 +50,8 @@ typedef struct ProcessList_ { Hashtable* displayTreeSet; Hashtable* draftingTreeSet; + Hashtable* dynamicMeters; /* runtime-discovered meters */ + struct timeval realtime; /* time of the current sample */ uint64_t realtimeMs; /* current time in milliseconds */ uint64_t monotonicMs; /* same, but from monotonic clock */ @@ -84,12 +86,12 @@ typedef struct ProcessList_ { unsigned int cpuCount; } ProcessList; -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); void ProcessList_delete(ProcessList* pl); void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); -ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); +ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); void ProcessList_done(ProcessList* this); diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c index 900677ae..91d62c4a 100644 --- a/darwin/DarwinProcessList.c +++ b/darwin/DarwinProcessList.c @@ -128,10 +128,10 @@ static struct kinfo_proc* ProcessList_getKInfoProcs(size_t* count) { CRT_fatalError("Unable to get kinfo_procs"); } -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) { +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { DarwinProcessList* this = xCalloc(1, sizeof(DarwinProcessList)); - ProcessList_init(&this->super, Class(DarwinProcess), usersTable, pidMatchList, userId); + ProcessList_init(&this->super, Class(DarwinProcess), usersTable, dynamicMeters, pidMatchList, userId); /* Initialize the CPU information */ this->super.cpuCount = ProcessList_allocateCPULoadInfo(&this->prev_load); diff --git a/darwin/DarwinProcessList.h b/darwin/DarwinProcessList.h index 1ae2f2b9..bd39ab0e 100644 --- a/darwin/DarwinProcessList.h +++ b/darwin/DarwinProcessList.h @@ -28,7 +28,7 @@ typedef struct DarwinProcessList_ { ZfsArcStats zfs; } DarwinProcessList; -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId); +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId); void ProcessList_delete(ProcessList* this); diff --git a/darwin/Platf |