Skip to content

Commit

Permalink
Introduce Row and Table classes for screens beyond top-processes
Browse files Browse the repository at this point in the history
This commit refactors the Process and ProcessList structures such
they each have a new parent - Row and Table, respectively.  These
new classes handle screen updates relating to anything that could
be represented in tabular format, e.g. cgroups, filesystems, etc,
without us having to reimplement the display logic repeatedly for
each new entity.
  • Loading branch information
natoscott committed May 16, 2023
1 parent 1de7a2b commit fe92ef2
Show file tree
Hide file tree
Showing 53 changed files with 1,954 additions and 1,460 deletions.
102 changes: 56 additions & 46 deletions Action.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,22 @@ Object* Action_pickFromVector(State* st, Panel* list, int x, bool follow) {
Panel* panelFocus;
int ch;
bool unfollow = false;
int pid = follow ? MainPanel_selectedPid(mainPanel) : -1;
if (follow && host->pl->following == -1) {
host->pl->following = pid;
int row = follow ? MainPanel_selectedRow(mainPanel) : -1;
if (follow && host->activeTable->following == -1) {
host->activeTable->following = row;
unfollow = true;
}
ScreenManager_run(scr, &panelFocus, &ch, NULL);
if (unfollow) {
host->pl->following = -1;
host->activeTable->following = -1;
}
ScreenManager_delete(scr);
Panel_move((Panel*)mainPanel, 0, y);
Panel_resize((Panel*)mainPanel, COLS, LINES - y - 1);
if (panelFocus == list && ch == 13) {
if (follow) {
const Process* selected = (const Process*)Panel_getSelected((Panel*)mainPanel);
if (selected && selected->pid == pid)
const Row* selected = (const Row*)Panel_getSelected((Panel*)mainPanel);
if (selected && selected->id == row)
return Panel_getSelected(list);

beep();
Expand Down Expand Up @@ -99,7 +99,7 @@ static void Action_runSetup(State* st) {

static bool changePriority(MainPanel* panel, int delta) {
bool anyTagged;
bool ok = MainPanel_foreachProcess(panel, Process_changePriorityBy, (Arg) { .i = delta }, &anyTagged);
bool ok = MainPanel_foreachRow(panel, Process_changePriorityBy, (Arg) { .i = delta }, &anyTagged);
if (!ok)
beep();
return anyTagged;
Expand All @@ -121,36 +121,36 @@ bool Action_setUserOnly(const char* userName, uid_t* userId) {
return false;
}

static void tagAllChildren(Panel* panel, Process* parent) {
static void tagAllChildren(Panel* panel, Row* parent) {
parent->tag = true;
pid_t ppid = parent->pid;
int parent_id = parent->id;
for (int i = 0; i < Panel_size(panel); i++) {
Process* p = (Process*) Panel_get(panel, i);
if (!p->tag && Process_isChildOf(p, ppid)) {
tagAllChildren(panel, p);
Row* row = (Row*) Panel_get(panel, i);
if (!row->tag && Row_isChildOf(row, parent_id)) {
tagAllChildren(panel, row);
}
}
}

static bool expandCollapse(Panel* panel) {
Process* p = (Process*) Panel_getSelected(panel);
if (!p)
Row* row = (Row*) Panel_getSelected(panel);
if (!row)
return false;

p->showChildren = !p->showChildren;
row->showChildren = !row->showChildren;
return true;
}

static bool collapseIntoParent(Panel* panel) {
const Process* p = (Process*) Panel_getSelected(panel);
if (!p)
const Row* r = (Row*) Panel_getSelected(panel);
if (!r)
return false;

pid_t ppid = Process_getParentPid(p);
int parent_id = Row_getGroupOrParent(r);
for (int i = 0; i < Panel_size(panel); i++) {
Process* q = (Process*) Panel_get(panel, i);
if (q->pid == ppid) {
q->showChildren = false;
Row* row = (Row*) Panel_get(panel, i);
if (row->id == parent_id) {
row->showChildren = false;
Panel_setSelected(panel, i);
return true;
}
Expand All @@ -159,7 +159,7 @@ static bool collapseIntoParent(Panel* panel) {
}

Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) {
ScreenSettings_setSortKey(settings->ss, sortKey);
ScreenSettings_setSortKey(settings->ss, (RowField) sortKey);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
}

Expand All @@ -171,11 +171,11 @@ static Htop_Reaction actionSetSortColumn(State* st) {
Panel_setHeader(sortPanel, "Sort by");
Machine* host = st->host;
Settings* settings = host->settings;
const ProcessField* fields = settings->ss->fields;
const RowField* fields = settings->ss->fields;
Hashtable* dynamicColumns = settings->dynamicColumns;
for (int i = 0; fields[i]; i++) {
char* name = NULL;
if (fields[i] >= LAST_PROCESSFIELD) {
if (fields[i] >= ROW_DYNAMIC_FIELDS) {
DynamicColumn* column = Hashtable_get(dynamicColumns, fields[i]);
if (!column)
continue;
Expand All @@ -195,7 +195,7 @@ static Htop_Reaction actionSetSortColumn(State* st) {
}
Object_delete(sortPanel);

host->pl->needsSort = true;
host->activeTable->needsSort = true;

return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
Expand Down Expand Up @@ -262,9 +262,9 @@ static Htop_Reaction actionToggleTreeView(State* st) {
ss->treeView = !ss->treeView;

if (!ss->allBranchesCollapsed)
ProcessList_expandTree(host->pl);
Table_expandTree(host->activeTable);

host->pl->needsSort = true;
host->activeTable->needsSort = true;

return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
}
Expand All @@ -282,17 +282,17 @@ static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) {
}
ss->allBranchesCollapsed = !ss->allBranchesCollapsed;
if (ss->allBranchesCollapsed)
ProcessList_collapseAllBranches(host->pl);
Table_collapseAllBranches(host->activeTable);
else
ProcessList_expandTree(host->pl);
Table_expandTree(host->activeTable);
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
}

static Htop_Reaction actionIncFilter(State* st) {
Machine* host = st->host;
IncSet* inc = (st->mainPanel)->inc;
IncSet_activate(inc, INC_FILTER, (Panel*)st->mainPanel);
host->pl->incFilter = IncSet_filter(inc);
host->activeTable->incFilter = IncSet_filter(inc);
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
}

Expand Down Expand Up @@ -321,7 +321,7 @@ static Htop_Reaction actionLowerPriority(State* st) {
static Htop_Reaction actionInvertSortOrder(State* st) {
Machine* host = st->host;
ScreenSettings_invertSortOrder(host->settings->ss);
host->pl->needsSort = true;
host->activeTable->needsSort = true;
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_UPDATE_PANELHDR;
}

Expand Down Expand Up @@ -397,11 +397,11 @@ static Htop_Reaction actionSetAffinity(State* st) {
return HTOP_OK;

#if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
const Process* p = (const Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
const Row* row = (const Row*) Panel_getSelected((Panel*)st->mainPanel);
if (!row)
return HTOP_OK;

Affinity* affinity1 = Affinity_get(p, host);
Affinity* affinity1 = Affinity_get(row, host);
if (!affinity1)
return HTOP_OK;

Expand All @@ -412,7 +412,7 @@ static Htop_Reaction actionSetAffinity(State* st) {
const void* set = Action_pickFromVector(st, affinityPanel, width, true);
if (set) {
Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, host);
bool ok = MainPanel_foreachProcess(st->mainPanel, Affinity_set, (Arg) { .v = affinity2 }, NULL);
bool ok = MainPanel_foreachRow(st->mainPanel, Affinity_set, (Arg) { .v = affinity2 }, NULL);
if (!ok)
beep();
Affinity_delete(affinity2);
Expand Down Expand Up @@ -459,7 +459,7 @@ static Htop_Reaction actionSetSchedPolicy(State* st) {

SchedulingArg v = { .policy = preSelectedPolicy, .priority = preSelectedPriority };

bool ok = MainPanel_foreachProcess(st->mainPanel, Scheduling_setPolicy, (Arg) { .v = &v }, NULL);
bool ok = MainPanel_foreachRow(st->mainPanel, Scheduling_setPolicy, (Arg) { .v = &v }, NULL);
if (!ok)
beep();
}
Expand All @@ -483,7 +483,7 @@ static Htop_Reaction actionKill(State* st) {
Panel_setHeader((Panel*)st->mainPanel, "Sending...");
Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st));
refresh();
MainPanel_foreachProcess(st->mainPanel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
MainPanel_foreachRow(st->mainPanel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
napms(500);
}
Panel_delete((Object*)signalsPanel);
Expand Down Expand Up @@ -511,7 +511,7 @@ static Htop_Reaction actionFilterByUser(State* st) {
}

Htop_Reaction Action_follow(State* st) {
st->host->pl->following = MainPanel_selectedPid(st->mainPanel);
st->host->activeTable->following = MainPanel_selectedRow(st->mainPanel);
Panel_setSelectionColor((Panel*)st->mainPanel, PANEL_SELECTION_FOLLOW);
return HTOP_KEEP_FOLLOWING;
}
Expand All @@ -529,6 +529,8 @@ static Htop_Reaction actionLsof(State* st) {
if (!p)
return HTOP_OK;

assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));

OpenFilesScreen* ofs = OpenFilesScreen_new(p);
InfoScreen_run((InfoScreen*)ofs);
OpenFilesScreen_delete((Object*)ofs);
Expand All @@ -541,6 +543,9 @@ static Htop_Reaction actionShowLocks(State* st) {
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;

assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));

ProcessLocksScreen* pls = ProcessLocksScreen_new(p);
InfoScreen_run((InfoScreen*)pls);
ProcessLocksScreen_delete((Object*)pls);
Expand All @@ -556,6 +561,7 @@ static Htop_Reaction actionStrace(State* st) {
const Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
return HTOP_OK;
assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));

TraceScreen* ts = TraceScreen_new(p);
bool ok = TraceScreen_forkTracer(ts);
Expand All @@ -569,11 +575,11 @@ static Htop_Reaction actionStrace(State* st) {
}

static Htop_Reaction actionTag(State* st) {
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
Row* r = (Row*) Panel_getSelected((Panel*)st->mainPanel);
if (!r)
return HTOP_OK;

Process_toggleTag(p);
Row_toggleTag(r);
Panel_onKey((Panel*)st->mainPanel, KEY_DOWN);
return HTOP_OK;
}
Expand Down Expand Up @@ -782,18 +788,18 @@ static Htop_Reaction actionHelp(State* st) {

static Htop_Reaction actionUntagAll(State* st) {
for (int i = 0; i < Panel_size((Panel*)st->mainPanel); i++) {
Process* p = (Process*) Panel_get((Panel*)st->mainPanel, i);
p->tag = false;
Row* row = (Row*) Panel_get((Panel*)st->mainPanel, i);
row->tag = false;
}
return HTOP_REFRESH;
}

static Htop_Reaction actionTagAllChildren(State* st) {
Process* p = (Process*) Panel_getSelected((Panel*)st->mainPanel);
if (!p)
Row* row = (Row*) Panel_getSelected((Panel*)st->mainPanel);
if (!row)
return HTOP_OK;

tagAllChildren((Panel*)st->mainPanel, p);
tagAllChildren((Panel*)st->mainPanel, row);
return HTOP_OK;
}

Expand All @@ -802,6 +808,8 @@ static Htop_Reaction actionShowEnvScreen(State* st) {
if (!p)
return HTOP_OK;

assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));

EnvScreen* es = EnvScreen_new(p);
InfoScreen_run((InfoScreen*)es);
EnvScreen_delete((Object*)es);
Expand All @@ -815,6 +823,8 @@ static Htop_Reaction actionShowCommandScreen(State* st) {
if (!p)
return HTOP_OK;

assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));

CommandScreen* cmdScr = CommandScreen_new(p);
InfoScreen_run((InfoScreen*)cmdScr);
CommandScreen_delete((Object*)cmdScr);
Expand Down
16 changes: 8 additions & 8 deletions Affinity.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ void Affinity_add(Affinity* this, unsigned int id) {

#if defined(HAVE_LIBHWLOC)

Affinity* Affinity_get(const Process* proc, Machine* host) {
Affinity* Affinity_get(const Row* row, Machine* host) {
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
bool ok = (hwloc_get_proc_cpubind(host->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
bool ok = (hwloc_get_proc_cpubind(host->topology, row->id, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
Affinity* affinity = NULL;
if (ok) {
affinity = Affinity_new(host);
Expand All @@ -73,22 +73,22 @@ Affinity* Affinity_get(const Process* proc, Machine* host) {
return affinity;
}

bool Affinity_set(Process* proc, Arg arg) {
bool Affinity_set(Row* row, Arg arg) {
Affinity* this = arg.v;
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
for (unsigned int i = 0; i < this->used; i++) {
hwloc_bitmap_set(cpuset, this->cpus[i]);
}
bool ok = (hwloc_set_proc_cpubind(this->host->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
bool ok = (hwloc_set_proc_cpubind(this->host->topology, row->id, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
hwloc_bitmap_free(cpuset);
return ok;
}

#elif defined(HAVE_AFFINITY)

Affinity* Affinity_get(const Process* proc, Machine* host) {
Affinity* Affinity_get(const Row* row, Machine* host) {
cpu_set_t cpuset;
bool ok = (sched_getaffinity(proc->pid, sizeof(cpu_set_t), &cpuset) == 0);
bool ok = (sched_getaffinity(row->id, sizeof(cpu_set_t), &cpuset) == 0);
if (!ok)
return NULL;

Expand All @@ -101,14 +101,14 @@ Affinity* Affinity_get(const Process* proc, Machine* host) {
return affinity;
}

bool Affinity_set(Process* proc, Arg arg) {
bool Affinity_set(Row* row, Arg arg) {
Affinity* this = arg.v;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
for (unsigned int i = 0; i < this->used; i++) {
CPU_SET(this->cpus[i], &cpuset);
}
bool ok = (sched_setaffinity(proc->pid, sizeof(unsigned long), &cpuset) == 0);
bool ok = (sched_setaffinity(row->id, sizeof(unsigned long), &cpuset) == 0);
return ok;
}

Expand Down
6 changes: 3 additions & 3 deletions Affinity.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ in the source distribution for its full text.
#include <stdbool.h>

#include "Object.h"
#include "Process.h"
#include "Row.h"
#endif


Expand All @@ -40,9 +40,9 @@ void Affinity_add(Affinity* this, unsigned int id);

#if defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY)

Affinity* Affinity_get(const Process* proc, Machine* host);
Affinity* Affinity_get(const Row* row, Machine* host);

bool Affinity_set(Process* proc, Arg arg);
bool Affinity_set(Row* row, Arg arg);

#endif /* HAVE_LIBHWLOC || HAVE_AFFINITY */

Expand Down
2 changes: 1 addition & 1 deletion AvailableColumnsPanel.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static void AvailableColumnsPanel_delete(Object* object) {

static void AvailableColumnsPanel_insert(AvailableColumnsPanel* this, int at, int key) {
const char* name;
if (key >= LAST_PROCESSFIELD)
if (key >= ROW_DYNAMIC_FIELDS)
name = DynamicColumn_init(key);
else
name = Process_fields[key].name;
Expand Down
2 changes: 1 addition & 1 deletion ColumnsPanel.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ static void ColumnsPanel_add(Panel* super, unsigned int key, Hashtable* columns)
void ColumnsPanel_fill(ColumnsPanel* this, ScreenSettings* ss, Hashtable* columns) {
Panel* super = (Panel*) this;
Panel_prune(super);
for (const ProcessField* fields = ss->fields; *fields; fields++)
for (const RowField* fields = ss->fields; *fields; fields++)
ColumnsPanel_add(super, *fields, columns);
this->ss = ss;
}
Expand Down
Loading

0 comments on commit fe92ef2

Please sign in to comment.