htop/pcp/Instance.c

164 lines
4.3 KiB
C

/*
htop - Instance.c
(C) 2022-2023 Sohaib Mohammed
(C) 2022-2023 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/Instance.h"
#include <stdbool.h>
#include <stdlib.h>
#include "CRT.h"
#include "DynamicColumn.h"
#include "DynamicScreen.h"
#include "Hashtable.h"
#include "Machine.h"
#include "Macros.h"
#include "Metric.h"
#include "Platform.h"
#include "PCPDynamicColumn.h"
#include "PCPDynamicScreen.h"
#include "Row.h"
#include "RichString.h"
#include "XUtils.h"
#include "pcp/InDomTable.h"
#include "pcp/Metric.h"
Instance* Instance_new(const Machine* host, const InDomTable* indom) {
Instance* this = xCalloc(1, sizeof(Instance));
Object_setClass(this, Class(Instance));
Row* super = &this->super;
Row_init(super, host);
this->indom = indom;
return this;
}
void Instance_done(Instance* this) {
if (this->name)
free(this->name);
Row_done(&this->super);
}
static void Instance_delete(Object* cast) {
Instance* this = (Instance*) cast;
Instance_done(this);
free(this);
}
static void Instance_writeField(const Row* super, RichString* str, RowField field) {
const Instance* this = (const Instance*) super;
int instid = Instance_getId(this);
const Settings* settings = super->host->settings;
DynamicColumn* column = Hashtable_get(settings->dynamicColumns, field);
PCPDynamicColumn* cp = (PCPDynamicColumn*) column;
if (!cp)
return;
pmAtomValue atom;
pmAtomValue* ap = &atom;
const pmDesc* descp = Metric_desc(cp->id);
if (!Metric_instance(cp->id, instid, this->offset, ap, descp->type))
ap = NULL;
PCPDynamicColumn_writeAtomValue(cp, str, settings, cp->id, instid, descp, ap);
if (ap && descp->type == PM_TYPE_STRING)
free(ap->cp);
}
static const char* Instance_externalName(Row* super) {
Instance* this = (Instance*) super;
if (!this->name)
/* ignore any failure here - its safe and we try again next time */
(void)pmNameInDom(InDom_getId(this), Instance_getId(this), &this->name);
return this->name;
}
static int Instance_compareByKey(const Row* v1, const Row* v2, int key) {
const Instance* i1 = (const Instance*)v1;
const Instance* i2 = (const Instance*)v2;
if (key < 0)
return 0;
Hashtable* dc = Platform_dynamicColumns();
const PCPDynamicColumn* column = Hashtable_get(dc, key);
if (!column)
return -1;
size_t metric = column->id;
unsigned int type = Metric_type(metric);
pmAtomValue atom1 = {0}, atom2 = {0};
if (!Metric_instance(metric, i1->offset, i1->offset, &atom1, type) ||
!Metric_instance(metric, i2->offset, i2->offset, &atom2, type)) {
if (type == PM_TYPE_STRING) {
free(atom1.cp);
free(atom2.cp);
}
return -1;
}
switch (type) {
case PM_TYPE_STRING: {
int cmp = SPACESHIP_NULLSTR(atom2.cp, atom1.cp);
free(atom2.cp);
free(atom1.cp);
return cmp;
}
case PM_TYPE_32:
return SPACESHIP_NUMBER(atom2.l, atom1.l);
case PM_TYPE_U32:
return SPACESHIP_NUMBER(atom2.ul, atom1.ul);
case PM_TYPE_64:
return SPACESHIP_NUMBER(atom2.ll, atom1.ll);
case PM_TYPE_U64:
return SPACESHIP_NUMBER(atom2.ull, atom1.ull);
case PM_TYPE_FLOAT:
return SPACESHIP_NUMBER(atom2.f, atom1.f);
case PM_TYPE_DOUBLE:
return SPACESHIP_NUMBER(atom2.d, atom1.d);
default:
break;
}
return 0;
}
static int Instance_compare(const void* v1, const void* v2) {
const Instance* i1 = (const Instance*)v1;
const Instance* i2 = (const Instance*)v2;
const ScreenSettings* ss = i1->super.host->settings->ss;
RowField key = ScreenSettings_getActiveSortKey(ss);
int result = Instance_compareByKey(v1, v2, key);
// Implement tie-breaker (needed to make tree mode more stable)
if (!result)
return SPACESHIP_NUMBER(Instance_getId(i1), Instance_getId(i2));
return (ScreenSettings_getActiveDirection(ss) == 1) ? result : -result;
}
const RowClass Instance_class = {
.super = {
.extends = Class(Row),
.display = Row_display,
.delete = Instance_delete,
.compare = Instance_compare,
},
.sortKeyString = Instance_externalName,
.writeField = Instance_writeField,
};