diff --git a/configure.ac b/configure.ac index 1762fa8d..1524bed7 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ LT_INIT # Package dependencies GLIB_REQUIRED=2.50.0 -LIBGTOP_REQUIRED=2.23.1 +LIBGTOP_REQUIRED=2.37.2 GIOMM_REQUIRED=2.26.0 GLIBMM_REQUIRED=2.22 GTK_REQUIRED=3.22.0 diff --git a/src/org.mate.system-monitor.gschema.xml.in b/src/org.mate.system-monitor.gschema.xml.in index 703923d0..7482621f 100644 --- a/src/org.mate.system-monitor.gschema.xml.in +++ b/src/org.mate.system-monitor.gschema.xml.in @@ -397,11 +397,43 @@ 100 - Width of process 'Priority' column + Width of process “Disk Write Total” column + false + Show process “Disk Write Total” column on startup + + + 100 + Width of process “Disk Read Total” column + + + false + Show process “Disk Read Total” column on startup + + + 100 + Width of process “Disk Read” column + + + false + Show process “Disk Read” column on startup + + + 100 + Width of process “Disk Write” column + + + false + Show process “Disk Write” column on startup + + + 100 + Width of process “Priority” column + + true - Show process 'Priority' column on startup + Show process “Priority” column on startup diff --git a/src/procman.h b/src/procman.h index d7f1ce9b..44ef2bc6 100644 --- a/src/procman.h +++ b/src/procman.h @@ -114,7 +114,11 @@ struct ProcConfig struct MutableProcInfo { MutableProcInfo() -: status(0) + : disk_write_bytes_current(0ULL), + disk_read_bytes_current(0ULL), + disk_write_bytes_total(0ULL), + disk_read_bytes_total(0ULL), + status(0U) { } std::string user; @@ -136,6 +140,10 @@ MutableProcInfo() gulong start_time; guint64 cpu_time; + guint64 disk_write_bytes_current; + guint64 disk_read_bytes_current; + guint64 disk_write_bytes_total; + guint64 disk_read_bytes_total; guint status; guint pcpu; gint nice; diff --git a/src/procproperties.cpp b/src/procproperties.cpp index 1570bdbf..d07da69a 100644 --- a/src/procproperties.cpp +++ b/src/procproperties.cpp @@ -101,6 +101,15 @@ format_memsize(guint64 size) return g_format_size_full(size, G_FORMAT_SIZE_IEC_UNITS); } +static gchar* +format_size(guint64 size) +{ + if (size == 0) + return g_strdup(_("N/A")); + else + return g_format_size(size); +} + static void fill_proc_properties (GtkWidget *tree, ProcInfo *info) { @@ -122,6 +131,8 @@ fill_proc_properties (GtkWidget *tree, ProcInfo *info) { N_("Writable Memory"), format_memsize(info->memwritable)}, { N_("Shared Memory"), format_memsize(info->memshared)}, { N_("X Server Memory"), format_memsize(info->memxserver)}, + { N_("Disk Read Total"), format_size(info->disk_read_bytes_total)}, + { N_("Disk Write Total"), format_size(info->disk_write_bytes_total)}, { N_("CPU"), g_strdup_printf("%d%%", info->pcpu)}, { N_("CPU Time"), procman::format_duration_for_display(100 * info->cpu_time / ProcData::get_instance()->frequency) }, { N_("Started"), procman_format_date_for_display(info->start_time) }, diff --git a/src/proctable.cpp b/src/proctable.cpp index 2e0a4acc..94bf63f1 100644 --- a/src/proctable.cpp +++ b/src/proctable.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -263,6 +264,10 @@ proctable_new (ProcData * const procdata) for multi-seat environments. See http://en.wikipedia.org/wiki/Multiseat_configuration */ N_("Seat"), N_("Owner"), + N_("Disk Read Total"), + N_("Disk Write Total"), + N_("Disk Read"), + N_("Disk Write"), N_("Priority"), NULL, "POINTER" @@ -298,6 +303,10 @@ proctable_new (ProcData * const procdata) G_TYPE_STRING, /* Session */ G_TYPE_STRING, /* Seat */ G_TYPE_STRING, /* Owner */ + G_TYPE_UINT64, /* Disk read total */ + G_TYPE_UINT64, /* Disk write total*/ + G_TYPE_UINT64, /* Disk read */ + G_TYPE_UINT64, /* Disk write */ G_TYPE_STRING, /* Priority */ GDK_TYPE_PIXBUF, /* Icon */ G_TYPE_POINTER, /* ProcInfo */ @@ -397,15 +406,32 @@ proctable_new (ProcData * const procdata) GUINT_TO_POINTER(i), NULL); break; + + case COL_DISK_READ_TOTAL: + case COL_DISK_WRITE_TOTAL: + gtk_tree_view_column_set_cell_data_func(col, cell, + &procman::storage_size_na_cell_data_func, + GUINT_TO_POINTER(i), + NULL); + break; + + case COL_DISK_READ_CURRENT: + case COL_DISK_WRITE_CURRENT: + gtk_tree_view_column_set_cell_data_func(col, cell, + &procman::io_rate_cell_data_func, + GUINT_TO_POINTER(i), + NULL); + break; + case COL_PRIORITY: gtk_tree_view_column_set_cell_data_func(col, cell, &procman::priority_cell_data_func, GUINT_TO_POINTER(COL_NICE), NULL); break; + default: gtk_tree_view_column_set_attributes(col, cell, "text", i, NULL); - break; } // sorting @@ -418,6 +444,10 @@ proctable_new (ProcData * const procdata) case COL_MEMWRITABLE: case COL_CPU: case COL_CPU_TIME: + case COL_DISK_READ_TOTAL: + case COL_DISK_WRITE_TOTAL: + case COL_DISK_READ_CURRENT: + case COL_DISK_WRITE_CURRENT: case COL_START_TIME: gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), i, procman::number_compare_func, GUINT_TO_POINTER(i), @@ -443,6 +473,10 @@ proctable_new (ProcData * const procdata) case COL_CPU: case COL_NICE: case COL_PID: + case COL_DISK_READ_TOTAL: + case COL_DISK_WRITE_TOTAL: + case COL_DISK_READ_CURRENT: + case COL_DISK_WRITE_CURRENT: case COL_CPU_TIME: case COL_MEM: g_object_set(G_OBJECT(cell), "xalign", 1.0f, NULL); @@ -650,6 +684,10 @@ update_info_mutable_cols(ProcInfo *info) tree_store_update(model, &info->node, COL_MEMXSERVER, info->memxserver); tree_store_update(model, &info->node, COL_CPU, info->pcpu); tree_store_update(model, &info->node, COL_CPU_TIME, info->cpu_time); + tree_store_update(model, &info->node, COL_DISK_READ_TOTAL, info->disk_read_bytes_total); + tree_store_update(model, &info->node, COL_DISK_WRITE_TOTAL, info->disk_write_bytes_total); + tree_store_update(model, &info->node, COL_DISK_READ_CURRENT, info->disk_read_bytes_current); + tree_store_update(model, &info->node, COL_DISK_WRITE_CURRENT, info->disk_write_bytes_current); tree_store_update(model, &info->node, COL_START_TIME, info->start_time); tree_store_update(model, &info->node, COL_NICE, info->nice); tree_store_update(model, &info->node, COL_MEM, info->mem); @@ -785,6 +823,7 @@ update_info (ProcData *procdata, ProcInfo *info) glibtop_proc_uid procuid; glibtop_proc_time proctime; glibtop_proc_kernel prockernel; + glibtop_proc_io procio; glibtop_get_proc_kernel(&prockernel, info->pid); g_strlcpy(info->wchan, prockernel.wchan, sizeof info->wchan); @@ -794,6 +833,7 @@ update_info (ProcData *procdata, ProcInfo *info) glibtop_get_proc_uid (&procuid, info->pid); glibtop_get_proc_time (&proctime, info->pid); + glibtop_get_proc_io (&procio, info->pid); get_process_memory_info(info); @@ -813,6 +853,15 @@ update_info (ProcData *procdata, ProcInfo *info) ProcInfo::cpu_times[info->pid] = info->cpu_time = proctime.rtime; info->nice = procuid.nice; + gdouble update_interval_seconds = procdata->config.update_interval / 1000.0; + difference = procio.disk_wbytes - info->disk_write_bytes_total; + info->disk_write_bytes_current = difference > update_interval_seconds ? difference/update_interval_seconds : 0ULL; + difference = procio.disk_rbytes - info->disk_read_bytes_total; + info->disk_read_bytes_current = difference > update_interval_seconds ? difference/update_interval_seconds : 0ULL; + + info->disk_write_bytes_total = procio.disk_wbytes; + info->disk_read_bytes_total = procio.disk_rbytes; + // set the ppid only if one can exist // i.e. pid=0 can never have a parent if (info->pid > 0) { diff --git a/src/proctable.h b/src/proctable.h index aca6e19d..a3dce059 100644 --- a/src/proctable.h +++ b/src/proctable.h @@ -48,6 +48,10 @@ enum COL_SESSION, COL_SEAT, COL_OWNER, + COL_DISK_WRITE_TOTAL, + COL_DISK_READ_TOTAL, + COL_DISK_WRITE_CURRENT, + COL_DISK_READ_CURRENT, COL_PRIORITY, COL_PIXBUF, COL_POINTER, diff --git a/src/util.cpp b/src/util.cpp index a6f46af1..14c559dd 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -422,6 +422,47 @@ namespace procman } } + void io_rate_cell_data_func(GtkTreeViewColumn *, GtkCellRenderer *renderer, + GtkTreeModel *model, GtkTreeIter *iter, + gpointer user_data) + { + const guint index = GPOINTER_TO_UINT(user_data); + + guint64 size; + GValue value = { 0 }; + + gtk_tree_model_get_value(model, iter, index, &value); + + switch (G_VALUE_TYPE(&value)) { + case G_TYPE_ULONG: + size = g_value_get_ulong(&value); + break; + + case G_TYPE_UINT64: + size = g_value_get_uint64(&value); + break; + + default: + g_assert_not_reached(); + } + + g_value_unset(&value); + + if (size == 0) { + char *str = g_strdup_printf ("%s", _("N/A")); + g_object_set(renderer, "markup", str, NULL); + g_free(str); + } + else { + char *str = g_format_size(size); + char *formatted_str = g_strdup_printf(_("%s/s"), str); + g_object_set(renderer, "text", formatted_str, NULL); + g_free(formatted_str); + g_free(str); + } + + } + void duration_cell_data_func(GtkTreeViewColumn *, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) @@ -568,4 +609,4 @@ namespace procman g_free(current_value); } -} \ No newline at end of file +} diff --git a/src/util.h b/src/util.h index 9b1b498a..03816987 100644 --- a/src/util.h +++ b/src/util.h @@ -50,6 +50,10 @@ namespace procman GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data); + void io_rate_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, + GtkTreeModel *model, GtkTreeIter *iter, + gpointer user_data); + void memory_size_na_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);