[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r18501 - in gnunet-gtk: contrib src/statistics
From: |
gnunet |
Subject: |
[GNUnet-SVN] r18501 - in gnunet-gtk: contrib src/statistics |
Date: |
Wed, 7 Dec 2011 23:03:34 +0100 |
Author: grothoff
Date: 2011-12-07 23:03:34 +0100 (Wed, 07 Dec 2011)
New Revision: 18501
Modified:
gnunet-gtk/contrib/gnunet_statistics_gtk_main_window.glade
gnunet-gtk/src/statistics/gnunet-statistics-gtk.c
Log:
-towards gnunet-statistics-gtk
Modified: gnunet-gtk/contrib/gnunet_statistics_gtk_main_window.glade
===================================================================
--- gnunet-gtk/contrib/gnunet_statistics_gtk_main_window.glade 2011-12-07
21:27:12 UTC (rev 18500)
+++ gnunet-gtk/contrib/gnunet_statistics_gtk_main_window.glade 2011-12-07
22:03:34 UTC (rev 18501)
@@ -2,24 +2,6 @@
<interface>
<requires lib="gtk+" version="2.20"/>
<!-- interface-naming-policy project-wide -->
- <object class="GtkListStore" id="GNUNET_STATISTICS_GTK_list_store">
- <columns>
- <!-- column-name peer_identity -->
- <column type="gchararray"/>
- <!-- column-name number_of_known_addresses -->
- <column type="guint"/>
- <!-- column-name country_name -->
- <column type="gchararray"/>
- <!-- column-name country_flag -->
- <column type="GdkPixbuf"/>
- <!-- column-name bandwidth_in -->
- <column type="guint64"/>
- <!-- column-name bandwidth_out -->
- <column type="guint64"/>
- <!-- column-name addresses -->
- <column type="gchararray"/>
- </columns>
- </object>
<object class="GtkWindow" id="GNUNET_STATISTICS_GTK_main_window">
<property name="title" translatable="yes">gnunet-statistics-gtk</property>
<property name="window_position">center</property>
@@ -68,9 +50,10 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
- <object class="GtkImage"
id="GNUNET_STATISTICS_GTK_main_notebook_connectivity_image">
+ <object class="GtkDrawingArea"
id="GNUNET_STATISTICS_GTK_main_notebook_connectivity_drawingarea">
<property name="visible">True</property>
- <property name="stock">gtk-missing-image</property>
+ <signal name="expose_event"
handler="GNUNET_STATISTICS_connection_graph_expose"/>
+ <signal name="configure_event"
handler="GNUNET_STATISTICS_connection_graph_configure"/>
</object>
</child>
<child type="tab">
@@ -84,9 +67,8 @@
</packing>
</child>
<child>
- <object class="GtkImage"
id="GNUNET_STATISTICS_GTK_main_notebook_traffic_image">
+ <object class="GtkDrawingArea"
id="GNUNET_STATISTICS_GTK_main_notebook_traffic_drawingarea">
<property name="visible">True</property>
- <property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="position">1</property>
@@ -104,9 +86,8 @@
</packing>
</child>
<child>
- <object class="GtkImage"
id="GNUNET_STATISTICS_GTK_main_notebook_storage_image">
+ <object class="GtkDrawingArea"
id="GNUNET_STATISTICS_GTK_main_notebook_storage_drawingarea">
<property name="visible">True</property>
- <property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="position">2</property>
@@ -131,16 +112,4 @@
</object>
</child>
</object>
- <object class="GtkAdjustment" id="adjustment3">
- <property name="upper">100</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- <property name="page_size">10</property>
- </object>
- <object class="GtkAdjustment" id="adjustment4">
- <property name="upper">100</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- <property name="page_size">10</property>
- </object>
</interface>
Modified: gnunet-gtk/src/statistics/gnunet-statistics-gtk.c
===================================================================
--- gnunet-gtk/src/statistics/gnunet-statistics-gtk.c 2011-12-07 21:27:12 UTC
(rev 18500)
+++ gnunet-gtk/src/statistics/gnunet-statistics-gtk.c 2011-12-07 22:03:34 UTC
(rev 18501)
@@ -24,20 +24,87 @@
* @author Christian Grothoff
*/
#include "gnunet_gtk.h"
+
+#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_statistics_service.h>
+#define MAX_HISTORY 1280
+
/**
- * Information we track for each peer outside of the model.
+ * Information about a value we received.
*/
-struct Statistics
+struct HistoricValue
{
+ /**
+ * A value we recorded.
+ */
+ uint64_t value;
+ /**
+ * Time when the value was recorded.
+ */
+ struct GNUNET_TIME_Absolute timestamp;
+};
+
+/**
+ * Historic information we recorded for a value.
+ */
+struct ValueHistory
+{
+
+ /**
+ * Name of the subsystem.
+ */
+ char *subsystem;
+
+ /**
+ * Name of the statistic.
+ */
+ char *name;
+
+ /**
+ * Recent values for this number.
+ */
+ struct HistoricValue history[MAX_HISTORY];
+
+ /**
+ * Last offset we wrote to in history.
+ */
+ unsigned int last_history_offset;
+
+ /**
+ * Number of valid entries in the history.
+ */
+ unsigned int history_size;
};
/**
+ * Information about how to plot certain values.
+ */
+struct PlotInfo
+{
+ /**
+ * Subsystem originating the value to plot.
+ */
+ const char *subsystem;
+
+ /**
+ * Name of the value to plot.
+ */
+ const char *name;
+
+ /**
+ * Name of color to use when plotting.
+ */
+ const char *color_name;
+
+};
+
+
+/**
* Handle to our main loop.
*/
static struct GNUNET_GTK_MainLoop *ml;
@@ -52,19 +119,111 @@
*/
static struct GNUNET_STATISTICS_Handle *statistics;
+/**
+ * Map from keys (subsystem+value) to 'struct ValueHistory'.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *stat_map;
+/**
+ * Task that refreshes connection graphic.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier connection_task;
/**
- * Get cfg.
+ * Pixmap where we have the connection image.
*/
-static const struct GNUNET_CONFIGURATION_Handle *
-get_configuration ()
+static GdkPixmap *connection_pixmap;
+
+/**
+ * How often do we refresh?
+ */
+static struct GNUNET_TIME_Relative refresh_delay;
+
+
+/**
+ * Obtain key for 'stat_map' for a given subsystem and name.
+ *
+ * @param subsystem subsystem
+ * @param name name
+ * @param key set to the hash map key
+ */
+static void
+get_key (const char *subsystem,
+ const char *name,
+ GNUNET_HashCode *key)
{
- return GNUNET_GTK_main_loop_get_configuration (ml);
+ GNUNET_HashCode h1;
+ GNUNET_HashCode h2;
+
+ GNUNET_CRYPTO_hash (subsystem, strlen(subsystem), &h1);
+ GNUNET_CRYPTO_hash (name, strlen(name), &h2);
+ GNUNET_CRYPTO_hash_xor (&h1, &h2, key);
}
/**
+ * Callback function to process statistic values.
+ *
+ * @param cls the 'struct ValueHistory' to update
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
+ * @return GNUNET_OK to continue
+ */
+static int
+process_value_update (void *cls, const char *subsystem,
+ const char *name, uint64_t value,
+ int is_persistent)
+{
+ struct ValueHistory *vh = cls;
+ GNUNET_HashCode key;
+
+ get_key (subsystem, name, &key);
+ if (++vh->last_history_offset == MAX_HISTORY)
+ vh->last_history_offset = 0;
+ if (vh->history_size < MAX_HISTORY)
+ vh->history_size++;
+ vh->history[vh->last_history_offset].value = value;
+ vh->history[vh->last_history_offset].timestamp = GNUNET_TIME_absolute_get
();
+ return GNUNET_OK;
+}
+
+
+/**
+ * Begin monitoring a particular value.
+ *
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ */
+static void
+monitor (const char *subsystem,
+ const char *name)
+{
+ GNUNET_HashCode key;
+ struct ValueHistory *vh;
+
+ get_key (subsystem, name, &key);
+ vh = GNUNET_CONTAINER_multihashmap_get (stat_map, &key);
+ if (NULL != vh)
+ return;
+ vh = GNUNET_malloc (sizeof (struct ValueHistory));
+ vh->subsystem = GNUNET_strdup (subsystem);
+ vh->name = GNUNET_strdup (name);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (stat_map,
+ &key,
+ vh,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+ GNUNET_STATISTICS_watch (statistics,
+ subsystem,
+ name,
+ &process_value_update,
+ vh);
+}
+
+
+/**
* Get an object from the main window.
*
* @param name name of the object
@@ -78,6 +237,179 @@
/**
+ * Actually draw a plot based on collected data.
+ *
+ * @param widget size and style information for the plot
+ * @param info what to draw
+ * @return pixmap with the drawing
+ */
+static GdkPixmap *
+create_plot (GtkWidget *widget,
+ const struct PlotInfo *info)
+{
+ GdkPixmap *ret;
+ GdkGC *gc;
+ unsigned int i;
+ GNUNET_HashCode key;
+ struct ValueHistory *vh;
+ GdkColor color;
+ GdkColormap *colormap;
+
+ ret = gdk_pixmap_new (widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ gtk_widget_get_visual (widget)->depth);
+ colormap = gdk_window_get_colormap (widget->window);
+ gc = gdk_gc_new (widget->window);
+ gdk_gc_copy (gc, widget->style->white_gc);
+ gdk_color_parse ("black", &color);
+ gdk_colormap_alloc_color (colormap, &color, TRUE, TRUE);
+ gdk_gc_set_foreground (gc, &color);
+ gdk_draw_rectangle (GDK_DRAWABLE (ret),
+ widget->style->black_gc,
+ TRUE, 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+ for (i=0; NULL != info[i].subsystem; i++)
+ {
+ get_key (info[i].subsystem, info[i].name, &key);
+ vh = GNUNET_CONTAINER_multihashmap_get (stat_map, &key);
+ if (NULL == vh)
+ continue;
+ gdk_color_parse (info[i].color_name, &color);
+ gdk_colormap_alloc_color (colormap, &color, TRUE, TRUE);
+ gdk_gc_set_foreground (gc, &color);
+
+
+
+ }
+
+ // FIXME
+ return ret;
+}
+
+
+/**
+ * Redraw the 'connection_pixmap'.
+ *
+ * @param widget where to render it to in the end (also for size to use)
+ */
+static void
+plot_connection_graph (GtkWidget *widget)
+{
+ static const struct PlotInfo connection_data[] =
+ {
+ { "core", "entries in session map", "white" },
+ { NULL, NULL, NULL}
+ };
+ if (NULL != connection_pixmap)
+ {
+ gdk_pixmap_unref (connection_pixmap);
+ connection_pixmap = NULL;
+ }
+ connection_pixmap = create_plot (widget,
+ connection_data);
+}
+
+
+/**
+ * Part of the connection graph got re-exposed; refresh the area.
+ *
+ * @param widget the drawing area of the connection graph
+ * @param event expose event
+ * @param data_ptr unused
+ * @return FALSE
+ */
+gint
+GNUNET_STATISTICS_connection_graph_expose (GtkWidget * widget,
+ GdkEventExpose * event,
+ gpointer data_ptr)
+{
+ gdk_draw_pixmap (widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ connection_pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ return FALSE;
+}
+
+
+/**
+ * The window size was changed, forcing us to re-draw the connection
+ * graph.
+ *
+ * @param widget the drawing area of the connection graph
+ * @param event configure event
+ * @param data_ptr unused
+ * @return TRUE
+ */
+gint
+GNUNET_STATISTICS_connection_graph_configure (GtkWidget * widget,
+ GdkEventConfigure * event,
+ gpointer data_ptr)
+{
+ plot_connection_graph (widget);
+ gdk_draw_pixmap (widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ connection_pixmap,
+ 0, 0,
+ 0, 0,
+ widget->allocation.width, widget->allocation.height);
+ return TRUE;
+}
+
+
+/**
+ * Refresh the 'connections' graphic.
+ *
+ * @param cls closure
+ * @param tc scheduler context
+ */
+static void
+refresh_connections (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GtkWidget *area;
+
+ connection_task = GNUNET_SCHEDULER_add_delayed (refresh_delay,
+ &refresh_connections,
+ NULL);
+ area = GTK_WIDGET (get_object
("GNUNET_STATISTICS_GTK_main_notebook_connectivity_drawingarea"));
+ plot_connection_graph (area);
+ gdk_draw_pixmap (area->window,
+ area->style->fg_gc[GTK_WIDGET_STATE (area)],
+ connection_pixmap,
+ 0, 0,
+ 0, 0,
+ area->allocation.width,
+ area->allocation.height);
+}
+
+
+/**
+ * Free entries in the value history.
+ *
+ * @param cls unused
+ * @param key unused
+ * @param value 'struct ValueHistory' to free
+ * @return GNUNET_OK (continue iteration)
+ */
+static int
+free_history (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
+{
+ struct ValueHistory *vh = value;
+
+ GNUNET_free (vh->subsystem);
+ GNUNET_free (vh->name);
+ GNUNET_free (vh);
+ return GNUNET_OK;
+}
+
+
+/**
* Task run on shutdown.
*
* @param cls unused
@@ -88,6 +420,9 @@
{
GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
statistics = NULL;
+ GNUNET_CONTAINER_multihashmap_iterate (stat_map, &free_history, NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (stat_map);
+ stat_map = NULL;
}
@@ -99,6 +434,16 @@
{
GNUNET_GTK_tray_icon_destroy ();
GNUNET_GTK_main_loop_quit (ml);
+ if (connection_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (connection_task);
+ connection_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != connection_pixmap)
+ {
+ gdk_pixmap_unref (connection_pixmap);
+ connection_pixmap = NULL;
+ }
GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
}
@@ -110,19 +455,40 @@
static void
run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
+ static const struct
+ {
+ const char *subsystem;
+ const char *name;
+ } moma[] =
+ {
+ { "core", "entries in session map" },
+ { NULL, NULL }
+ };
GtkWidget *main_window;
+ unsigned int i;
ml = cls;
statistics = GNUNET_STATISTICS_create ("gnunet-statistics-gtk",
- get_configuration());
+ GNUNET_GTK_main_loop_get_configuration
(ml));
if (NULL == statistics)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Failed to initiate connection with statistics service\n"));
return;
}
+ stat_map = GNUNET_CONTAINER_multihashmap_create (128);
GNUNET_GTK_set_icon_search_path ();
GNUNET_GTK_setup_nls ();
+ refresh_delay = GNUNET_TIME_UNIT_SECONDS; /* fixme: make option / cmd-line
option */
+
+ i = 0;
+ while (moma[i].subsystem != NULL)
+ {
+ monitor (moma[i].subsystem,
+ moma[i].name);
+ i++;
+ }
+
/* setup main window */
main_window = GTK_WIDGET (get_object ("GNUNET_STATISTICS_GTK_main_window"));
gtk_window_maximize (GTK_WINDOW (main_window));
@@ -130,6 +496,9 @@
"gnunet-gtk" /* FIXME: different icon? */ ,
"gnunet-statistics-gtk");
+ /* FIXME: only schedule this task if the respective tab is open!? */
+ connection_task = GNUNET_SCHEDULER_add_now (&refresh_connections, NULL);
+
/* make GUI visible */
if (!tray_only)
{
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r18501 - in gnunet-gtk: contrib src/statistics,
gnunet <=