This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository evisum.

View the commit online.

commit 1d83c6440561d751d79f37306b50d890f7edfff9
Author: Alastair Poole <[email protected]>
AuthorDate: Thu May 28 19:35:18 2026 +0100

    network: calculate usage
---
 src/bin/engine/evisum_engine.c              |  50 +++++++--
 src/bin/engine/evisum_engine.h              |   3 +-
 src/bin/enigmatic/Events.h                  |  68 ++++++------
 src/bin/enigmatic/client/enigmatic_client.c |   8 ++
 src/bin/enigmatic/enigmatic_config.h        |   2 +-
 src/bin/enigmatic/monitor/file_systems.c    |  21 +++-
 src/bin/enigmatic/system/file_systems.c     | 160 ++++++++++++++++++++++------
 src/bin/enigmatic/system/file_systems.h     |   2 +
 src/bin/ui/evisum_ui_process_list.c         |  22 ++--
 9 files changed, 249 insertions(+), 87 deletions(-)

diff --git a/src/bin/engine/evisum_engine.c b/src/bin/engine/evisum_engine.c
index 0f8112f..b4ab12b 100644
--- a/src/bin/engine/evisum_engine.c
+++ b/src/bin/engine/evisum_engine.c
@@ -621,6 +621,19 @@ _engine_history_logs_get(Eina_Bool refresh, uint32_t since)
     return logs;
 }
 
+static Eina_Bool
+_engine_history_logs_time_available_get(Eina_List *logs, uint32_t history_time)
+{
+    Eina_List *l;
+    Evisum_Engine_History_Log *log;
+
+    EINA_LIST_FOREACH(logs, l, log) {
+        if ((history_time >= log->start_time) && (history_time <= log->end_time)) return EINA_TRUE;
+    }
+
+    return EINA_FALSE;
+}
+
 Eina_Bool
 evisum_engine_history_bounds_since_get(uint32_t since, uint32_t *start_time, uint32_t *end_time)
 {
@@ -705,23 +718,40 @@ evisum_engine_history_bounds_get(uint32_t *start_time, uint32_t *end_time)
 }
 
 Eina_Bool
-evisum_engine_history_time_available_get(uint32_t time)
+evisum_engine_history_time_available_get(uint32_t history_time)
 {
-    Eina_List *logs, *l;
-    Evisum_Engine_History_Log *log;
-    Eina_Bool available = EINA_FALSE;
+    return evisum_engine_history_time_available_since_get(history_time, 0);
+}
 
-    if (!time) return EINA_FALSE;
+Eina_Bool
+evisum_engine_history_time_available_since_get(uint32_t history_time, uint32_t since)
+{
+    Eina_List *logs;
+    Eina_Bool available = EINA_FALSE;
+    Eina_Bool cached = EINA_FALSE;
+    time_t now;
+
+    if (!history_time) return EINA_FALSE;
     if (!evisum_engine_ensure_started()) return EINA_FALSE;
 
-    logs = _engine_history_logs_get(EINA_FALSE, 0);
-    EINA_LIST_FOREACH(logs, l, log) {
-        if ((time >= log->start_time) && (time <= log->end_time)) {
-            available = EINA_TRUE;
-            break;
+    now = time(NULL);
+
+    if (_state.lock_init) {
+        LOCK();
+        if (!since) {
+            cached = _state.history_logs && ((now - _state.history_logs_scan_at) < HISTORY_LOG_CACHE_TTL);
+            if (cached) available = _engine_history_logs_time_available_get(_state.history_logs, history_time);
+        } else {
+            cached = _state.history_recent_logs && (since >= _state.history_recent_since)
+                     && ((now - _state.history_recent_logs_scan_at) < HISTORY_LOG_CACHE_TTL);
+            if (cached) available = _engine_history_logs_time_available_get(_state.history_recent_logs, history_time);
         }
+        UNLOCK();
+        if (cached) return available;
     }
 
+    logs = _engine_history_logs_get(EINA_FALSE, since);
+    available = _engine_history_logs_time_available_get(logs, history_time);
     _engine_history_logs_free(logs);
 
     return available;
diff --git a/src/bin/engine/evisum_engine.h b/src/bin/engine/evisum_engine.h
index 6f57064..16a047a 100644
--- a/src/bin/engine/evisum_engine.h
+++ b/src/bin/engine/evisum_engine.h
@@ -57,7 +57,8 @@ Eina_Bool evisum_engine_history_bounds_since_get(uint32_t since, uint32_t *start
 Eina_Bool evisum_engine_history_contiguous_bounds_since_get(uint32_t since, uint32_t *start_time, uint32_t *end_time);
 
 /* Checks whether history data exists for a given time. */
-Eina_Bool evisum_engine_history_time_available_get(uint32_t time);
+Eina_Bool evisum_engine_history_time_available_get(uint32_t history_time);
+Eina_Bool evisum_engine_history_time_available_since_get(uint32_t history_time, uint32_t since);
 
 /* Switches the engine view to a chosen history time. */
 Eina_Bool evisum_engine_history_time_set(uint32_t time);
diff --git a/src/bin/enigmatic/Events.h b/src/bin/enigmatic/Events.h
index 50f8310..5fdb869 100644
--- a/src/bin/enigmatic/Events.h
+++ b/src/bin/enigmatic/Events.h
@@ -45,39 +45,41 @@ typedef enum
    FILE_SYSTEM            = 26,
    FILE_SYSTEM_TOTAL      = 27,
    FILE_SYSTEM_USED       = 28,
-   PROCESS                = 29,
-   PROCESS_PPID           = 30,
-   PROCESS_UID            = 31,
-   PROCESS_NICE           = 32,
-   PROCESS_PRIORITY       = 33,
-   PROCESS_CPU_ID         = 34,
-   PROCESS_NUM_THREAD     = 35,
-   PROCESS_CPU_TIME       = 36,
-   PROCESS_RUN_TIME       = 37,
-   PROCESS_START          = 38,
-   PROCESS_MEM_SIZE       = 39,
-   PROCESS_MEM_RSS        = 40,
-   PROCESS_MEM_SHARED     = 41,
-   PROCESS_MEM_VIRT       = 42,
-   PROCESS_NET_IN         = 43,
-   PROCESS_NET_OUT        = 44,
-   PROCESS_DISK_READ      = 45,
-   PROCESS_DISK_WRITE     = 46,
-   PROCESS_COMMAND        = 47,
-   PROCESS_ARGUMENTS      = 48,
-   PROCESS_STATE          = 49,
-   PROCESS_WCHAN          = 50,
-   PROCESS_NUM_FILES      = 51,
-   PROCESS_WAS_ZERO       = 52,
-   PROCESS_IS_KERNEL      = 53,
-   PROCESS_IS_NEW         = 54,
-   PROCESS_TID            = 55,
-   PROCESS_THREAD_NAME    = 56,
-   PROCESS_FDS_COUNT      = 57,
-   PROCESS_THREADS_COUNT  = 58,
-   PROCESS_CHILDREN_COUNT = 59,
-   PROCESS_PATH           = 60,
-   PROCESS_CPU_USAGE      = 61,
+   FILE_SYSTEM_READ       = 29,
+   FILE_SYSTEM_WRITE      = 30,
+   PROCESS                = 31,
+   PROCESS_PPID           = 32,
+   PROCESS_UID            = 33,
+   PROCESS_NICE           = 34,
+   PROCESS_PRIORITY       = 35,
+   PROCESS_CPU_ID         = 36,
+   PROCESS_NUM_THREAD     = 37,
+   PROCESS_CPU_TIME       = 38,
+   PROCESS_RUN_TIME       = 39,
+   PROCESS_START          = 40,
+   PROCESS_MEM_SIZE       = 41,
+   PROCESS_MEM_RSS        = 42,
+   PROCESS_MEM_SHARED     = 43,
+   PROCESS_MEM_VIRT       = 44,
+   PROCESS_NET_IN         = 45,
+   PROCESS_NET_OUT        = 46,
+   PROCESS_DISK_READ      = 47,
+   PROCESS_DISK_WRITE     = 48,
+   PROCESS_COMMAND        = 49,
+   PROCESS_ARGUMENTS      = 50,
+   PROCESS_STATE          = 51,
+   PROCESS_WCHAN          = 52,
+   PROCESS_NUM_FILES      = 53,
+   PROCESS_WAS_ZERO       = 54,
+   PROCESS_IS_KERNEL      = 55,
+   PROCESS_IS_NEW         = 56,
+   PROCESS_TID            = 57,
+   PROCESS_THREAD_NAME    = 58,
+   PROCESS_FDS_COUNT      = 59,
+   PROCESS_THREADS_COUNT  = 60,
+   PROCESS_CHILDREN_COUNT = 61,
+   PROCESS_PATH           = 62,
+   PROCESS_CPU_USAGE      = 63,
 } Object_Type;
 
 typedef enum
diff --git a/src/bin/enigmatic/client/enigmatic_client.c b/src/bin/enigmatic/client/enigmatic_client.c
index 891489d..55ff55d 100644
--- a/src/bin/enigmatic/client/enigmatic_client.c
+++ b/src/bin/enigmatic/client/enigmatic_client.c
@@ -450,6 +450,8 @@ message_file_system(Enigmatic_Client *client)
                             {
                                fs2->usage.total = fs->usage.total;
                                fs2->usage.used = fs->usage.used;
+                               fs2->usage.read = fs->usage.read;
+                               fs2->usage.write = fs->usage.write;
                             }
                        }
                      free(fs);
@@ -487,6 +489,10 @@ message_file_system(Enigmatic_Client *client)
                        fs->usage.total += change;
                      else if (msg->object_type == FILE_SYSTEM_USED)
                        fs->usage.used += change;
+                     else if (msg->object_type == FILE_SYSTEM_READ)
+                       fs->usage.read += change;
+                     else if (msg->object_type == FILE_SYSTEM_WRITE)
+                       fs->usage.write += change;
                   }
              }
            break;
@@ -1150,6 +1156,8 @@ message_mod(Enigmatic_Client *client)
            break;
         case FILE_SYSTEM_TOTAL:
         case FILE_SYSTEM_USED:
+        case FILE_SYSTEM_READ:
+        case FILE_SYSTEM_WRITE:
            message_file_system(client);
            break;
         case PROCESS_PPID:
diff --git a/src/bin/enigmatic/enigmatic_config.h b/src/bin/enigmatic/enigmatic_config.h
index 9eb56b4..8f18f6b 100644
--- a/src/bin/enigmatic/enigmatic_config.h
+++ b/src/bin/enigmatic/enigmatic_config.h
@@ -3,7 +3,7 @@
 #include "Events.h"
 
 #define ENIGMATIC_CONFIG_VERSION_MAJOR 0x0001
-#define ENIGMATIC_CONFIG_VERSION_MINOR 0x0005
+#define ENIGMATIC_CONFIG_VERSION_MINOR 0x0006
 
 #define ENIGMATIC_CONFIG_VERSION ((ENIGMATIC_CONFIG_VERSION_MAJOR << 16) | ENIGMATIC_CONFIG_VERSION_MINOR)
 
diff --git a/src/bin/enigmatic/monitor/file_systems.c b/src/bin/enigmatic/monitor/file_systems.c
index b160662..1208e85 100644
--- a/src/bin/enigmatic/monitor/file_systems.c
+++ b/src/bin/enigmatic/monitor/file_systems.c
@@ -174,11 +174,30 @@ enigmatic_monitor_file_systems(Enigmatic *enigmatic, Eina_Hash **cache_hash)
              DEBUG("%s :%i", key, (int) ((fs->usage.used - fs2->usage.used)));
              changed = 1;
           }
+        if (fs2->usage.read != fs->usage.read)
+          {
+             msg.object_type = FILE_SYSTEM_READ;
+             msg.number = fs2->unique_id;
+             enigmatic_log_diff(enigmatic, msg, (fs->usage.read - fs2->usage.read));
+
+             DEBUG("%s read :%i", key, (int) ((fs->usage.read - fs2->usage.read)));
+             changed = 1;
+          }
+        if (fs2->usage.write != fs->usage.write)
+          {
+             msg.object_type = FILE_SYSTEM_WRITE;
+             msg.number = fs2->unique_id;
+             enigmatic_log_diff(enigmatic, msg, (fs->usage.write - fs2->usage.write));
+
+             DEBUG("%s write :%i", key, (int) ((fs->usage.write - fs2->usage.write)));
+             changed = 1;
+          }
         fs2->usage.total = fs->usage.total;
         fs2->usage.used = fs->usage.used;
+        fs2->usage.read = fs->usage.read;
+        fs2->usage.write = fs->usage.write;
         free(fs);
      }
 
    return changed;
 }
-
diff --git a/src/bin/enigmatic/system/file_systems.c b/src/bin/enigmatic/system/file_systems.c
index 8765d4f..a4afbb5 100644
--- a/src/bin/enigmatic/system/file_systems.c
+++ b/src/bin/enigmatic/system/file_systems.c
@@ -1,6 +1,5 @@
 #include "file_systems.h"
 
-#include <stdio.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -28,73 +27,164 @@
 # include <sys/mount.h>
 #endif
 
+#if defined(__linux__)
+typedef struct
+{
+   uint64_t read;
+   uint64_t write;
+} Linux_Disk_Usage;
+
+static void
+_linux_proc_unescape(char *s)
+{
+   char *src, *dst;
+
+   src = "" = s;
+   while (*src)
+     {
+        if ((src[0] == '\\') &&
+            (src[1] >= '0') && (src[1] <= '7') &&
+            (src[2] >= '0') && (src[2] <= '7') &&
+            (src[3] >= '0') && (src[3] <= '7'))
+          {
+             *dst++ = (char) (((src[1] - '0') << 6) |
+                              ((src[2] - '0') << 3) |
+                              (src[3] - '0'));
+             src += 4;
+          }
+        else
+          {
+             *dst++ = *src++;
+          }
+     }
+   *dst = '\0';
+}
+
+static Eina_Hash *
+_linux_disk_usage_hash_get(void)
+{
+   Eina_Hash *hash;
+   FILE *f;
+   char buf[4096];
+
+   f = fopen("/proc/diskstats", "r");
+   if (!f) return NULL;
+
+   hash = eina_hash_string_superfast_new(free);
+   if (!hash)
+     {
+        fclose(f);
+        return NULL;
+     }
+
+   while (fgets(buf, sizeof(buf), f))
+     {
+        unsigned int major_id, minor_id;
+        unsigned long long reads, reads_merged, sectors_read, ms_read;
+        unsigned long long writes, writes_merged, sectors_written;
+        char name[128];
+
+        if (sscanf(buf, " %u %u %127s %llu %llu %llu %llu %llu %llu %llu",
+                   &major_id, &minor_id, name, &reads, &reads_merged,
+                   &sectors_read, &ms_read, &writes, &writes_merged,
+                   &sectors_written) == 10)
+          {
+             Linux_Disk_Usage *usage;
+             char key[64];
+
+             usage = calloc(1, sizeof(Linux_Disk_Usage));
+             if (!usage) continue;
+
+             usage->read = sectors_read * 512ULL;
+             usage->write = sectors_written * 512ULL;
+             snprintf(key, sizeof(key), "%u:%u", major_id, minor_id);
+             eina_hash_set(hash, key, usage);
+          }
+     }
+
+   fclose(f);
+
+   return hash;
+}
+
+static void
+_linux_file_system_disk_usage_set(File_System *fs, Eina_Hash *disk_usage, unsigned int major_id, unsigned int minor_id)
+{
+   Linux_Disk_Usage *usage;
+   char key[64];
+
+   if (!disk_usage) return;
+
+   snprintf(key, sizeof(key), "%u:%u", major_id, minor_id);
+   usage = eina_hash_find(disk_usage, key);
+   if (!usage) return;
+
+   fs->usage.read = usage->read;
+   fs->usage.write = usage->write;
+}
+#endif
+
 Eina_List *
 file_systems_find(void)
 {
    Eina_List *list = NULL;
 # if defined(__linux__)
    FILE *f;
-   char *dev, *mount, *type_name, *cp, *end;
+   char *separator, *post_separator;
    struct statfs stats;
    char buf[4096];
+   Eina_Hash *disk_usage;
 
-   f = fopen("/proc/mounts", "r");
+   f = fopen("/proc/self/mountinfo", "r");
    if (!f) return NULL;
 
+   disk_usage = _linux_disk_usage_hash_get();
+
    while ((fgets(buf, sizeof(buf), f)) != NULL)
      {
-        cp = strchr(buf, ' ');
-        if (!cp) continue;
-        mount = cp + 1;
-        dev = strndup(buf, mount - buf - 1);
-        if (!dev) continue;
+        unsigned int major_id, minor_id;
+        char mount[PATH_MAX], path[PATH_MAX], type_name[64], options[4096];
 
-        cp = strchr(mount, ' ');
-        if (!cp) {
-           free(dev);
-           continue;
-        }
-        end = cp;
-        *end = '\0';
-        cp++;
-        end = strchr(cp, ' ');
-        if (!end) {
-           free(dev);
-           continue;
-        }
-        type_name = strndup(cp, end - cp);
-        if (!type_name) {
-           free(dev);
-           continue;
-        }
+        separator = strstr(buf, " - ");
+        if (!separator) continue;
 
-        cp = end + 1; /* options field */
+        *separator = '\0';
+        post_separator = separator + 3;
+
+        if (sscanf(buf, "%*u %*u %u:%u %*4095s %4095s %4095s",
+                   &major_id, &minor_id, mount, options) != 4)
+          continue;
+
+        if (sscanf(post_separator, "%63s %4095s", type_name, path) != 2)
+          continue;
+
+        _linux_proc_unescape(mount);
+        _linux_proc_unescape(path);
+        _linux_proc_unescape(type_name);
 
         Eina_Bool ok = EINA_TRUE;
         if ((strcmp(type_name, "fuseblk")) && (strcmp(type_name, "exfat"))) ok = EINA_FALSE;
 
-        if (((!ok) && strstr(cp, "nodev")) ||
+        if (((!ok) && strstr(options, "nodev")) ||
             (statfs(mount, &stats) < 0) ||
             (stats.f_blocks == 0 && stats.f_bfree == 0))
-          {
-             free(dev);
-             free(type_name);
-             continue;
-          }
+          continue;
 
         File_System *fs = calloc(1, sizeof(File_System));
         if (fs)
           {
              snprintf(fs->mount, sizeof(fs->mount), "%s", mount);
-             snprintf(fs->path, sizeof(fs->path), "%s", dev);
+             snprintf(fs->path, sizeof(fs->path), "%s", path);
              snprintf(fs->type_name, sizeof(fs->type_name), "%s", type_name);
              fs->usage.total = stats.f_bsize * stats.f_blocks;
              fs->usage.used  = fs->usage.total - (stats.f_bsize * stats.f_bfree);
-             free(dev); free(type_name);
+             _linux_file_system_disk_usage_set(fs, disk_usage, major_id, minor_id);
              list = eina_list_append(list, fs);
           }
      }
    fclose(f);
+   if (disk_usage)
+     eina_hash_free(disk_usage);
 # else
    struct statfs *mounts;
    int i, count;
diff --git a/src/bin/enigmatic/system/file_systems.h b/src/bin/enigmatic/system/file_systems.h
index c92a05e..77b377d 100644
--- a/src/bin/enigmatic/system/file_systems.h
+++ b/src/bin/enigmatic/system/file_systems.h
@@ -12,6 +12,8 @@
 typedef struct {
    uint64_t total;
    uint64_t used;
+   uint64_t read;
+   uint64_t write;
 } _Usage;
 
 typedef struct _File_System {
diff --git a/src/bin/ui/evisum_ui_process_list.c b/src/bin/ui/evisum_ui_process_list.c
index a53ed87..3cfe8b2 100644
--- a/src/bin/ui/evisum_ui_process_list.c
+++ b/src/bin/ui/evisum_ui_process_list.c
@@ -662,6 +662,16 @@ _evisum_ui_process_list_history_time_format(uint32_t t, char *buf, size_t len) {
     strftime(buf, len, "%Y-%m-%d %H:%M:%S", &tm_buf);
 }
 
+static Eina_Bool
+_evisum_ui_process_list_history_time_available_get(Evisum_Ui_Process_List_View *view, uint32_t t) {
+    uint32_t since = 0;
+
+    if (!view) return EINA_FALSE;
+    if (!view->ui->proc.history_whole) since = view->history.start_time;
+
+    return evisum_engine_history_time_available_since_get(t, since);
+}
+
 static void
 _evisum_ui_process_list_history_tooltip_set(Evisum_Ui_Process_List_View *view, uint32_t t) {
     char time_buf[32];
@@ -672,7 +682,7 @@ _evisum_ui_process_list_history_tooltip_set(Evisum_Ui_Process_List_View *view, u
 
     if (view->history.tooltip_time == t) available = view->history.tooltip_available;
     else {
-        available = evisum_engine_history_time_available_get(t);
+        available = _evisum_ui_process_list_history_time_available_get(view, t);
         view->history.tooltip_time = t;
         view->history.tooltip_available = available;
     }
@@ -799,7 +809,7 @@ _evisum_ui_process_list_history_apply_timer_cb(void *data) {
 static Eina_Bool
 _evisum_ui_process_list_history_request_deferred(Evisum_Ui_Process_List_View *view, uint32_t t) {
     if (!view->history.lock_init) return EINA_FALSE;
-    if (!evisum_engine_history_time_available_get(t)) {
+    if (!_evisum_ui_process_list_history_time_available_get(view, t)) {
         _evisum_ui_process_list_history_tooltip_set(view, t);
         _evisum_ui_process_list_history_tooltip_pinned_set(view, EINA_TRUE);
         return EINA_FALSE;
@@ -1037,7 +1047,7 @@ _evisum_ui_process_list_history_slider_mouse_move_cb(void *data, Evas *e EINA_UN
 
     t = _evisum_ui_process_list_history_time_at_x_get(view, ev->cur.canvas.x);
     if (view->history.sliding) {
-        if (evisum_engine_history_time_available_get(t)) _evisum_ui_process_list_history_preview_set(view, t);
+        if (_evisum_ui_process_list_history_time_available_get(view, t)) _evisum_ui_process_list_history_preview_set(view, t);
         else _evisum_ui_process_list_history_tooltip_set(view, t);
     } else
         _evisum_ui_process_list_history_tooltip_set(view, t);
@@ -1067,7 +1077,7 @@ _evisum_ui_process_list_history_slider_mouse_down_cb(void *data, Evas *e EINA_UN
     if (!view->history.lock_init) return;
 
     t = _evisum_ui_process_list_history_time_at_x_get(view, ev->canvas.x);
-    if (!evisum_engine_history_time_available_get(t)) {
+    if (!_evisum_ui_process_list_history_time_available_get(view, t)) {
         _evisum_ui_process_list_history_tooltip_set(view, t);
         _evisum_ui_process_list_history_tooltip_pinned_set(view, EINA_TRUE);
         return;
@@ -1100,7 +1110,7 @@ _evisum_ui_process_list_history_slider_mouse_up_cb(void *data, Evas *e EINA_UNUS
 
     view->history.sliding = EINA_FALSE;
     t = _evisum_ui_process_list_history_time_at_x_get(view, ev->canvas.x);
-    if (!evisum_engine_history_time_available_get(t)) {
+    if (!_evisum_ui_process_list_history_time_available_get(view, t)) {
         _evisum_ui_process_list_history_tooltip_set(view, t);
         _evisum_ui_process_list_history_tooltip_pinned_set(view, EINA_TRUE);
         return;
@@ -2035,7 +2045,7 @@ _evisum_ui_process_list_history_key_step(Evisum_Ui_Process_List_View *view, Evas
         else t++;
     }
 
-    if (!evisum_engine_history_time_available_get(t)) {
+    if (!_evisum_ui_process_list_history_time_available_get(view, t)) {
         _evisum_ui_process_list_history_tooltip_set(view, t);
         _evisum_ui_process_list_history_tooltip_pinned_set(view, EINA_TRUE);
         return EINA_TRUE;

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to