Instance.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. htop - Instance.c
  3. (C) 2022-2023 Sohaib Mohammed
  4. (C) 2022-2023 htop dev team
  5. Released under the GNU GPLv2+, see the COPYING file
  6. in the source distribution for its full text.
  7. */
  8. #include "config.h" // IWYU pragma: keep
  9. #include "pcp/Instance.h"
  10. #include <stdbool.h>
  11. #include <stdlib.h>
  12. #include "CRT.h"
  13. #include "DynamicColumn.h"
  14. #include "DynamicScreen.h"
  15. #include "Hashtable.h"
  16. #include "Machine.h"
  17. #include "Macros.h"
  18. #include "Metric.h"
  19. #include "Platform.h"
  20. #include "PCPDynamicColumn.h"
  21. #include "PCPDynamicScreen.h"
  22. #include "Row.h"
  23. #include "RichString.h"
  24. #include "XUtils.h"
  25. #include "pcp/InDomTable.h"
  26. #include "pcp/Metric.h"
  27. Instance* Instance_new(const Machine* host, const InDomTable* indom) {
  28. Instance* this = xCalloc(1, sizeof(Instance));
  29. Object_setClass(this, Class(Instance));
  30. Row* super = &this->super;
  31. Row_init(super, host);
  32. this->indom = indom;
  33. return this;
  34. }
  35. void Instance_done(Instance* this) {
  36. if (this->name)
  37. free(this->name);
  38. Row_done(&this->super);
  39. }
  40. static void Instance_delete(Object* cast) {
  41. Instance* this = (Instance*) cast;
  42. Instance_done(this);
  43. free(this);
  44. }
  45. static void Instance_writeField(const Row* super, RichString* str, RowField field) {
  46. const Instance* this = (const Instance*) super;
  47. int instid = Instance_getId(this);
  48. const Settings* settings = super->host->settings;
  49. DynamicColumn* column = Hashtable_get(settings->dynamicColumns, field);
  50. PCPDynamicColumn* cp = (PCPDynamicColumn*) column;
  51. if (!cp)
  52. return;
  53. pmAtomValue atom;
  54. pmAtomValue* ap = &atom;
  55. const pmDesc* descp = Metric_desc(cp->id);
  56. if (!Metric_instance(cp->id, instid, this->offset, ap, descp->type))
  57. ap = NULL;
  58. PCPDynamicColumn_writeAtomValue(cp, str, settings, cp->id, instid, descp, ap);
  59. if (ap && descp->type == PM_TYPE_STRING)
  60. free(ap->cp);
  61. }
  62. static const char* Instance_externalName(Row* super) {
  63. Instance* this = (Instance*) super;
  64. if (!this->name)
  65. /* ignore any failure here - its safe and we try again next time */
  66. (void)pmNameInDom(InDom_getId(this), Instance_getId(this), &this->name);
  67. return this->name;
  68. }
  69. static int Instance_compareByKey(const Row* v1, const Row* v2, int key) {
  70. const Instance* i1 = (const Instance*)v1;
  71. const Instance* i2 = (const Instance*)v2;
  72. if (key < 0)
  73. return 0;
  74. Hashtable* dc = Platform_dynamicColumns();
  75. const PCPDynamicColumn* column = Hashtable_get(dc, key);
  76. if (!column)
  77. return -1;
  78. size_t metric = column->id;
  79. unsigned int type = Metric_type(metric);
  80. pmAtomValue atom1 = {0}, atom2 = {0};
  81. if (!Metric_instance(metric, i1->offset, i1->offset, &atom1, type) ||
  82. !Metric_instance(metric, i2->offset, i2->offset, &atom2, type)) {
  83. if (type == PM_TYPE_STRING) {
  84. free(atom1.cp);
  85. free(atom2.cp);
  86. }
  87. return -1;
  88. }
  89. switch (type) {
  90. case PM_TYPE_STRING: {
  91. int cmp = SPACESHIP_NULLSTR(atom2.cp, atom1.cp);
  92. free(atom2.cp);
  93. free(atom1.cp);
  94. return cmp;
  95. }
  96. case PM_TYPE_32:
  97. return SPACESHIP_NUMBER(atom2.l, atom1.l);
  98. case PM_TYPE_U32:
  99. return SPACESHIP_NUMBER(atom2.ul, atom1.ul);
  100. case PM_TYPE_64:
  101. return SPACESHIP_NUMBER(atom2.ll, atom1.ll);
  102. case PM_TYPE_U64:
  103. return SPACESHIP_NUMBER(atom2.ull, atom1.ull);
  104. case PM_TYPE_FLOAT:
  105. return SPACESHIP_NUMBER(atom2.f, atom1.f);
  106. case PM_TYPE_DOUBLE:
  107. return SPACESHIP_NUMBER(atom2.d, atom1.d);
  108. default:
  109. break;
  110. }
  111. return 0;
  112. }
  113. static int Instance_compare(const void* v1, const void* v2) {
  114. const Instance* i1 = (const Instance*)v1;
  115. const Instance* i2 = (const Instance*)v2;
  116. const ScreenSettings* ss = i1->super.host->settings->ss;
  117. RowField key = ScreenSettings_getActiveSortKey(ss);
  118. int result = Instance_compareByKey(v1, v2, key);
  119. // Implement tie-breaker (needed to make tree mode more stable)
  120. if (!result)
  121. return SPACESHIP_NUMBER(Instance_getId(i1), Instance_getId(i2));
  122. return (ScreenSettings_getActiveDirection(ss) == 1) ? result : -result;
  123. }
  124. const RowClass Instance_class = {
  125. .super = {
  126. .extends = Class(Row),
  127. .display = Row_display,
  128. .delete = Instance_delete,
  129. .compare = Instance_compare,
  130. },
  131. .sortKeyString = Instance_externalName,
  132. .writeField = Instance_writeField,
  133. };