Blame src/application.h

Packit 76ec6a
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
Packit 76ec6a
#ifndef _GSM_APPLICATION_H_
Packit 76ec6a
#define _GSM_APPLICATION_H_
Packit 76ec6a
Packit 76ec6a
#include <gtkmm.h>
Packit 76ec6a
#include <glibtop/cpu.h>
Packit 76ec6a
Packit 76ec6a
#include <algorithm>
Packit 76ec6a
Packit 76ec6a
struct LoadGraph;
Packit 76ec6a
Packit 76ec6a
#include "smooth_refresh.h"
Packit 76ec6a
#include "prettytable.h"
Packit 76ec6a
#include "legacy/treeview.h"
Packit 76ec6a
#include "util.h"
Packit 76ec6a
Packit 76ec6a
static const unsigned MIN_UPDATE_INTERVAL =   1 * 1000;
Packit 76ec6a
static const unsigned MAX_UPDATE_INTERVAL = 100 * 1000;
Packit 76ec6a
Packit 76ec6a
Packit 76ec6a
enum ProcmanTab
Packit 76ec6a
{
Packit 76ec6a
    PROCMAN_TAB_PROCESSES,
Packit 76ec6a
    PROCMAN_TAB_RESOURCES,
Packit 76ec6a
    PROCMAN_TAB_DISKS
Packit 76ec6a
};
Packit 76ec6a
Packit 76ec6a
Packit 76ec6a
struct ProcConfig
Packit 76ec6a
  : private procman::NonCopyable
Packit 76ec6a
{
Packit 76ec6a
    ProcConfig()
Packit 76ec6a
      : update_interval(0),
Packit 76ec6a
	graph_update_interval(0),
Packit 76ec6a
	disks_update_interval(0),
Packit 76ec6a
	mem_color(),
Packit 76ec6a
	swap_color(),
Packit 76ec6a
	net_in_color(),
Packit 76ec6a
	net_out_color(),
Packit 76ec6a
	bg_color(),
Packit 76ec6a
	frame_color(),
Packit 76ec6a
	num_cpus(0),
Packit 76ec6a
	solaris_mode(false),
Packit 76ec6a
	draw_stacked(false),
Packit 76ec6a
	draw_smooth(true),
Packit 76ec6a
	network_in_bits(false)
Packit 76ec6a
    {
Packit 76ec6a
      std::fill(&this->cpu_color[0], &this->cpu_color[GLIBTOP_NCPU], GdkRGBA());
Packit 76ec6a
    }
Packit 76ec6a
Packit 76ec6a
    int             update_interval;
Packit 76ec6a
    int             graph_update_interval;
Packit 76ec6a
    int             disks_update_interval;
Packit 76ec6a
    GdkRGBA         cpu_color[GLIBTOP_NCPU];
Packit 76ec6a
    GdkRGBA         mem_color;
Packit 76ec6a
    GdkRGBA         swap_color;
Packit 76ec6a
    GdkRGBA         net_in_color;
Packit 76ec6a
    GdkRGBA         net_out_color;
Packit 76ec6a
    GdkRGBA         bg_color;
Packit 76ec6a
    GdkRGBA         frame_color;
Packit 76ec6a
    gint            num_cpus;
Packit 76ec6a
    bool solaris_mode;
Packit 76ec6a
    bool draw_stacked;
Packit 76ec6a
    bool draw_smooth;
Packit 76ec6a
    bool network_in_bits;
Packit 76ec6a
};
Packit 76ec6a
Packit 76ec6a
Packit 76ec6a
Packit 76ec6a
struct MutableProcInfo
Packit 76ec6a
  : private procman::NonCopyable
Packit 76ec6a
{
Packit 76ec6a
Packit 76ec6a
MutableProcInfo()
Packit 76ec6a
  : vmsize(0UL),
Packit 76ec6a
    memres(0UL),
Packit 76ec6a
    memshared(0UL),
Packit 76ec6a
    memwritable(0UL),
Packit 76ec6a
    mem(0UL),
Packit 76ec6a
#ifdef HAVE_WNCK
Packit 76ec6a
    memxserver(0UL),
Packit 76ec6a
#endif
Packit 76ec6a
    start_time(0UL),
Packit 76ec6a
    cpu_time(0ULL),
Packit 76ec6a
    disk_read_bytes_total(0ULL),
Packit 76ec6a
    disk_write_bytes_total(0ULL),
Packit 76ec6a
    disk_read_bytes_current(0ULL),
Packit 76ec6a
    disk_write_bytes_current(0ULL),
Packit 76ec6a
    status(0U),
Packit 76ec6a
    pcpu(0U),
Packit 76ec6a
    nice(0)
Packit 76ec6a
    {
Packit 76ec6a
    }
Packit 76ec6a
Packit 76ec6a
    std::string user;
Packit 76ec6a
Packit 76ec6a
    std::string wchan;
Packit 76ec6a
Packit 76ec6a
    // all these members are filled with libgtop which uses
Packit 76ec6a
    // guint64 (to have fixed size data) but we don't need more
Packit 76ec6a
    // than an unsigned long (even for 32bit apps on a 64bit
Packit 76ec6a
    // kernel) as these data are amounts, not offsets.
Packit 76ec6a
    gulong vmsize;
Packit 76ec6a
    gulong memres;
Packit 76ec6a
    gulong memshared;
Packit 76ec6a
    gulong memwritable;
Packit 76ec6a
    gulong mem;
Packit 76ec6a
Packit 76ec6a
#ifdef HAVE_WNCK
Packit 76ec6a
    // wnck gives an unsigned long
Packit 76ec6a
    gulong memxserver;
Packit 76ec6a
#endif
Packit 76ec6a
Packit 76ec6a
    gulong start_time;
Packit 76ec6a
    guint64 cpu_time;
Packit 76ec6a
    guint64 disk_read_bytes_total;
Packit 76ec6a
    guint64 disk_write_bytes_total;
Packit 76ec6a
    guint64 disk_read_bytes_current;
Packit 76ec6a
    guint64 disk_write_bytes_current;
Packit 76ec6a
    guint status;
Packit 76ec6a
    guint pcpu;
Packit 76ec6a
    gint nice;
Packit 76ec6a
    std::string cgroup_name;
Packit 76ec6a
Packit 76ec6a
    std::string unit;
Packit 76ec6a
    std::string session;
Packit 76ec6a
    std::string seat;
Packit 76ec6a
Packit 76ec6a
    std::string owner;
Packit 76ec6a
};
Packit 76ec6a
Packit 76ec6a
Packit 76ec6a
class ProcInfo
Packit 76ec6a
: public MutableProcInfo
Packit 76ec6a
{
Packit 76ec6a
  public:
Packit 76ec6a
    ProcInfo& operator=(const ProcInfo&) = delete;
Packit 76ec6a
    ProcInfo(const ProcInfo&) = delete;
Packit 76ec6a
    ProcInfo(pid_t pid);
Packit 76ec6a
    // adds one more ref to icon
Packit 76ec6a
    void set_icon(Glib::RefPtr<Gdk::Pixbuf> icon);
Packit 76ec6a
    void set_user(guint uid);
Packit 76ec6a
    std::string lookup_user(guint uid);
Packit 76ec6a
Packit 76ec6a
    GtkTreeIter     node;
Packit 76ec6a
    Glib::RefPtr<Gdk::Pixbuf> pixbuf;
Packit 76ec6a
    std::string     tooltip;
Packit 76ec6a
    std::string     name;
Packit 76ec6a
    std::string     arguments;
Packit 76ec6a
Packit 76ec6a
    std::string     security_context;
Packit 76ec6a
Packit 76ec6a
    const pid_t     pid;
Packit 76ec6a
    pid_t           ppid;
Packit 76ec6a
    guint           uid;
Packit 76ec6a
};
Packit 76ec6a
Packit 76ec6a
class ProcList {
Packit 76ec6a
    // TODO: use a set instead
Packit 76ec6a
    // sorted by pid. The map has a nice property : it is sorted
Packit 76ec6a
    // by pid so this helps a lot when looking for the parent node
Packit 76ec6a
    // as ppid is nearly always < pid.
Packit 76ec6a
    typedef std::map<pid_t, ProcInfo> List;
Packit 76ec6a
    List data;
Packit 76ec6a
    std::mutex data_lock;
Packit 76ec6a
public:
Packit 76ec6a
    std::map<pid_t, unsigned long> cpu_times;
Packit 76ec6a
    typedef List::iterator Iterator;
Packit 76ec6a
    Iterator begin() { return std::begin(data); }
Packit 76ec6a
    Iterator end() { return std::end(data); }
Packit 76ec6a
    Iterator erase(Iterator it) {
Packit 76ec6a
        std::lock_guard<std::mutex> lg(data_lock);
Packit 76ec6a
        return data.erase(it);
Packit 76ec6a
    }
Packit 76ec6a
    ProcInfo* add(pid_t pid) { return &data.emplace(std::piecewise_construct, std::forward_as_tuple(pid), std::forward_as_tuple(pid)).first->second; }
Packit 76ec6a
    void clear() { return data.clear(); }
Packit 76ec6a
Packit 76ec6a
    ProcInfo* find(pid_t pid);
Packit 76ec6a
};
Packit 76ec6a
Packit 76ec6a
class GsmApplication : public Gtk::Application, private procman::NonCopyable
Packit 76ec6a
Packit 76ec6a
{
Packit 76ec6a
private:
Packit 76ec6a
    void load_settings();
Packit 76ec6a
    void load_resources();
Packit 76ec6a
Packit 76ec6a
    void on_preferences_activate(const Glib::VariantBase&);
Packit 76ec6a
    void on_lsof_activate(const Glib::VariantBase&);
Packit 76ec6a
    void on_help_activate(const Glib::VariantBase&);
Packit 76ec6a
    void on_quit_activate(const Glib::VariantBase&);
Packit 76ec6a
protected:
Packit 76ec6a
    GsmApplication();
Packit 76ec6a
public:
Packit 76ec6a
    static Glib::RefPtr<GsmApplication> get ();
Packit 76ec6a
Packit 76ec6a
    void save_config();
Packit 76ec6a
    void shutdown();
Packit 76ec6a
Packit 76ec6a
    ProcList         processes;
Packit 76ec6a
    GsmTreeView      *tree;
Packit 76ec6a
    GtkRevealer      *proc_actionbar_revealer;
Packit 76ec6a
    GtkMenu          *popup_menu;
Packit 76ec6a
    GsmTreeView      *disk_list;
Packit 76ec6a
    GtkStack         *stack;
Packit 76ec6a
    GtkButton        *refresh_button;
Packit 76ec6a
    GtkMenuButton    *process_menu_button;
Packit 76ec6a
    GtkButton        *end_process_button;
Packit 76ec6a
    GtkButton        *search_button;
Packit 76ec6a
    GtkSearchEntry   *search_entry;
Packit 76ec6a
    GtkSearchBar     *search_bar;
Packit 76ec6a
    ProcConfig        config;
Packit 76ec6a
    LoadGraph        *cpu_graph;
Packit 76ec6a
    LoadGraph        *mem_graph;
Packit 76ec6a
    LoadGraph        *net_graph;
Packit 76ec6a
    gint              cpu_label_fixed_width;
Packit 76ec6a
    gint              net_label_fixed_width;
Packit 76ec6a
    GtkTreeSelection *selection;
Packit 76ec6a
    guint             timeout;
Packit 76ec6a
    guint             disk_timeout;
Packit 76ec6a
Packit 76ec6a
    GtkTreePath      *top_of_tree;
Packit 76ec6a
    gdouble          last_vscroll_max;
Packit 76ec6a
    gdouble          last_vscroll_value;
Packit 76ec6a
Packit 76ec6a
    PrettyTable      *pretty_table;
Packit 76ec6a
Packit 76ec6a
    Glib::RefPtr<Gio::Settings> settings;
Packit 76ec6a
    GtkApplicationWindow *main_window;
Packit 76ec6a
Packit 76ec6a
    unsigned         frequency;
Packit 76ec6a
Packit 76ec6a
    SmoothRefresh    *smooth_refresh;
Packit 76ec6a
Packit 76ec6a
    guint64           cpu_total_time;
Packit 76ec6a
    guint64           cpu_total_time_last;
Packit 76ec6a
Packit 76ec6a
protected:
Packit 76ec6a
    virtual void on_activate();
Packit 76ec6a
    virtual int on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>& command_line);
Packit 76ec6a
    virtual void on_startup();
Packit 76ec6a
};
Packit 76ec6a
Packit 76ec6a
#endif /* _GSM_APPLICATION_H_ */