diff options
Diffstat (limited to 'FileDescriptorMeter.c')
-rw-r--r-- | FileDescriptorMeter.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/FileDescriptorMeter.c b/FileDescriptorMeter.c new file mode 100644 index 0000000..cf1ec93 --- /dev/null +++ b/FileDescriptorMeter.c @@ -0,0 +1,118 @@ +/* +htop - FileDescriptorMeter.c +(C) 2022 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 "FileDescriptorMeter.h" + +#include <math.h> + +#include "CRT.h" +#include "Macros.h" +#include "Meter.h" +#include "Object.h" +#include "Platform.h" +#include "RichString.h" +#include "XUtils.h" + + +#define FD_EFFECTIVE_UNLIMITED(x) (!isgreaterequal((double)(1<<30), (x))) + +static const int FileDescriptorMeter_attributes[] = { + FILE_DESCRIPTOR_USED, + FILE_DESCRIPTOR_MAX +}; + +static void FileDescriptorMeter_updateValues(Meter* this) { + this->values[0] = 0; + this->values[1] = 1; + + Platform_getFileDescriptors(&this->values[0], &this->values[1]); + + /* only print bar for first value */ + this->curItems = 1; + + /* Use maximum value for scaling of bar mode + * + * As the plain total value can be very large compared to + * the actually used value, this is capped in the following way: + * + * 1. If the maximum value is below (or equal to) 1<<16, use it directly + * 2. If the maximum value is above, use powers of 2 starting at 1<<16 and + * double it until it's larger than 16 times the used file handles + * (capped at the maximum number of files) + * 3. If the maximum is effectively unlimited (AKA > 1<<30), + * Do the same as for 2, but cap at 1<<30. + */ + if (this->values[1] <= 1 << 16) { + this->total = this->values[1]; + } else { + if (this->total < 16 * this->values[0]) { + for (this->total = 1 << 16; this->total < 16 * this->values[0]; this->total *= 2) { + if (this->total >= 1 << 30) { + break; + } + } + } + + if (this->total > this->values[1]) { + this->total = this->values[1]; + } + + if (this->total > 1 << 30) { + this->total = 1 << 30; + } + } + + if (!isNonnegative(this->values[0])) { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "unknown/unknown"); + } else if (FD_EFFECTIVE_UNLIMITED(this->values[1])) { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.0lf/unlimited", this->values[0]); + } else { + xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.0lf/%.0lf", this->values[0], this->values[1]); + } +} + +static void FileDescriptorMeter_display(const Object* cast, RichString* out) { + const Meter* this = (const Meter*)cast; + char buffer[50]; + int len; + + if (!isNonnegative(this->values[0])) { + RichString_appendAscii(out, CRT_colors[METER_TEXT], "unknown"); + return; + } + + RichString_appendAscii(out, CRT_colors[METER_TEXT], "used: "); + len = xSnprintf(buffer, sizeof(buffer), "%.0lf", this->values[0]); + RichString_appendnAscii(out, CRT_colors[FILE_DESCRIPTOR_USED], buffer, len); + + RichString_appendAscii(out, CRT_colors[METER_TEXT], " max: "); + if (FD_EFFECTIVE_UNLIMITED(this->values[1])) { + RichString_appendAscii(out, CRT_colors[FILE_DESCRIPTOR_MAX], "unlimited"); + } else { + len = xSnprintf(buffer, sizeof(buffer), "%.0lf", this->values[1]); + RichString_appendnAscii(out, CRT_colors[FILE_DESCRIPTOR_MAX], buffer, len); + } +} + +const MeterClass FileDescriptorMeter_class = { + .super = { + .extends = Class(Meter), + .delete = Meter_delete, + .display = FileDescriptorMeter_display, + }, + .updateValues = FileDescriptorMeter_updateValues, + .defaultMode = TEXT_METERMODE, + .maxItems = 2, + .total = 65536.0, + .attributes = FileDescriptorMeter_attributes, + .name = "FileDescriptors", + .uiName = "File Descriptors", + .caption = "FDs: ", + .description = "Number of allocated/available file descriptors" +}; |