Move statistics output to systeminfo plugin
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 14 Feb 2017 14:13:05 +0000 (15:13 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 14 Feb 2017 14:13:05 +0000 (15:13 +0100)
src-plugins/generic/remotecontrol/README_REMOTECONTROL
src-plugins/generic/remotecontrol/remotecontrol.c
src-plugins/generic/systeminfo/systeminfo.c
src-plugins/subsystems/oonf_socket.c
src-plugins/subsystems/oonf_socket.h
src-plugins/subsystems/oonf_timer.c
src-plugins/subsystems/oonf_timer.h

index c678dcd..d548796 100644 (file)
@@ -5,7 +5,7 @@ REMOTECONTROL plugin by Henning Rogge
 The plugin implements three telnet commands to configure and debug the
 running agent.
 
-'resource' allows to display the current active memory blocks and timers.
+'route' can read and modify the kernel routing table.
 'log' can activate an additional configurable logging sink which will dump
 its output into the telnet session.
 'config' allows to read and modify the configuration of the agent.
index 1954884..f8ee78d 100644 (file)
@@ -97,16 +97,12 @@ struct _remotecontrol_session {
 static int _init(void);
 static void _cleanup(void);
 
-static enum oonf_telnet_result _cb_handle_resource(struct oonf_telnet_data *data);
 static enum oonf_telnet_result _cb_handle_route(struct oonf_telnet_data *data);
 static enum oonf_telnet_result _cb_handle_log(struct oonf_telnet_data *data);
 static enum oonf_telnet_result _cb_handle_config(struct oonf_telnet_data *data);
 static enum oonf_telnet_result _update_logfilter(struct oonf_telnet_data *data,
     uint8_t *mask, const char *current, bool value);
 
-static void _print_memory(struct autobuf *buf);
-static void _print_timer(struct autobuf *buf);
-
 static enum oonf_telnet_result _start_logging(struct oonf_telnet_data *data,
     struct _remotecontrol_session *rc_session);
 static void _stop_logging(struct oonf_telnet_data *data);
@@ -148,7 +144,7 @@ static struct oonf_subsystem _oonf_remotecontrol_subsystem = {
   .name = OONF_REMOTECONTROL_SUBSYSTEM,
   .dependencies = _dependencies,
   .dependencies_count = ARRAYSIZE(_dependencies),
-  .descr = "OONFD remote control and debug plugin",
+  .descr = "OONF remote control and debug plugin",
   .author = "Henning Rogge",
 
   .cfg_section = &_remotecontrol_section,
@@ -160,11 +156,6 @@ DECLARE_OONF_PLUGIN(_oonf_remotecontrol_subsystem);
 
 /* command callbacks and names */
 static struct oonf_telnet_command _telnet_cmds[] = {
-  TELNET_CMD("resources", _cb_handle_resource,
-      "\"resources memory\": display information about memory usage\n"
-      "\"resources timer\": display information about active timers\n"
-      "\"resources socket\": display information about socket usage\n",
-      .acl = &_remotecontrol_config.acl),
   TELNET_CMD("log", _cb_handle_log,
       "\"log\":      continuous output of logging to this console\n"
       "\"log show\": show configured logging option for debuginfo output\n"
@@ -248,78 +239,6 @@ _cleanup(void)
   netaddr_acl_remove(&_remotecontrol_config.acl);
 }
 
-/**
- * Print current resources known to memory manager
- * @param buf output buffer
- */
-static void
-_print_memory(struct autobuf *buf) {
-  struct oonf_class *c;
-
-  avl_for_each_element(oonf_class_get_tree(), c, _node) {
-    abuf_appendf(buf, "%-25s (MEMORY) size: %"PRINTF_SIZE_T_SPECIFIER
-        " usage: %u freelist: %u allocations: %u/%u\n",
-        c->name, c->size,
-        oonf_class_get_usage(c),
-        oonf_class_get_free(c),
-        oonf_class_get_allocations(c),
-        oonf_class_get_recycled(c));
-  }
-}
-
-/**
- * Print current resources known to timer scheduler
- * @param buf output buffer
- */
-static void
-_print_timer(struct autobuf *buf) {
-  struct oonf_timer_class *t;
-
-  list_for_each_element(oonf_timer_get_list(), t, _node) {
-    abuf_appendf(buf, "%-25s (TIMER) usage: %u changes: %u\n",
-        t->name, t->usage, t->changes);
-  }
-}
-
-/**
- * Print current sockets
- * @param buf output buffer
- */
-static void
-_print_socket(struct autobuf *buf) {
-  struct oonf_socket_entry *sock;
-
-  list_for_each_element(oonf_socket_get_list(), sock, _node) {
-    abuf_appendf(buf, "%-25s (SOCKET) usage_r: %u usage_s: %u usage_long: %u\n",
-        sock->name, sock->usage_r, sock->usage_s, sock->usage_long);
-  }
-}
-
-/**
- * Handle resource command
- * @param data pointer to telnet data
- * @return telnet result constant
- */
-static enum oonf_telnet_result
-_cb_handle_resource(struct oonf_telnet_data *data) {
-  if (data->parameter == NULL || strcasecmp(data->parameter, "memory") == 0) {
-    abuf_puts(data->out, "Memory blocks:\n");
-    _print_memory(data->out);
-  }
-
-  if (data->parameter == NULL || strcasecmp(data->parameter, "timer") == 0) {
-    abuf_puts(data->out, "\nTimer Classes:\n");
-    _print_timer(data->out);
-  }
-
-  if (data->parameter == NULL || strcasecmp(data->parameter, "socket") == 0) {
-    abuf_puts(data->out, "Sockets:\n");
-    _print_socket(data->out);
-  }
-
-  return TELNET_RESULT_ACTIVE;
-}
-
 /**
  * Update the remotecontrol logging filter
  * @param data pointer to telnet data
index 2faf8e0..775d35b 100644 (file)
@@ -72,9 +72,18 @@ static enum oonf_telnet_result _cb_systeminfo_help(struct oonf_telnet_data *con)
 
 static void _initialize_time_values(struct oonf_viewer_template *template);
 static void _initialize_version_values(struct oonf_viewer_template *template);
+static void _initialize_memory_values(
+    struct oonf_viewer_template *template, struct oonf_class *c);
+static void _initialize_timer_values(
+    struct oonf_viewer_template *template, struct oonf_timer_class *tc);
+static void _initialize_socket_values(
+    struct oonf_viewer_template *template, struct oonf_socket_entry *sock);
 
 static int _cb_create_text_time(struct oonf_viewer_template *);
 static int _cb_create_text_version(struct oonf_viewer_template *);
+static int _cb_create_text_memory(struct oonf_viewer_template *);
+static int _cb_create_text_timer(struct oonf_viewer_template *);
+static int _cb_create_text_socket(struct oonf_viewer_template *);
 
 /*
  * list of template keys and corresponding buffers for values.
@@ -94,6 +103,42 @@ static int _cb_create_text_version(struct oonf_viewer_template *);
 /*! template key for version git commit */
 #define KEY_VERSION_COMMIT              "version_commit"
 
+/*! template key for statistic object name */
+#define KEY_STATISTICS_NAME             "statistics_name"
+
+/*! template key for current memory usage */
+#define KEY_MEMORY_USAGE                "memory_usage"
+
+/*! template key for memory freelist size */
+#define KEY_MEMORY_FREELIST             "memory_freelist"
+
+/*! template key for total memory allocations */
+#define KEY_MEMORY_ALLOC                "memory_alloc"
+
+/*! template key for recycled memory blocks */
+#define KEY_MEMORY_RECYCLED             "memory_recycled"
+
+/*! template key for timer usage */
+#define KEY_TIMER_USAGE                 "timer_usage"
+
+/*! template key for timer changes */
+#define KEY_TIMER_CHANGE                "timer_change"
+
+/*! template key for timer fired */
+#define KEY_TIMER_FIRE                  "timer_fire"
+
+/*! template key for timer long usage events*/
+#define KEY_TIMER_LONG                  "timer_long"
+
+/*! template key for socket receive events */
+#define KEY_SOCKET_RECV                 "socket_recv"
+
+/*! template key for socket send events */
+#define KEY_SOCKET_SEND                 "socket_send"
+
+/*! template key for socket long usage events */
+#define KEY_SOCKET_LONG                 "socket_long"
+
 /*
  * buffer space for values that will be assembled
  * into the output of the plugin
@@ -104,6 +149,22 @@ static struct isonumber_str             _value_internal_time;
 static char                             _value_version_text[256];
 static char                             _value_version_commit[21];
 
+static char                             _value_stat_name[256];
+
+static struct isonumber_str             _value_memory_usage;
+static struct isonumber_str             _value_memory_freelist;
+static struct isonumber_str             _value_memory_alloc;
+static struct isonumber_str             _value_memory_recycled;
+
+static struct isonumber_str             _value_timer_usage;
+static struct isonumber_str             _value_timer_change;
+static struct isonumber_str             _value_timer_fire;
+static struct isonumber_str             _value_timer_long;
+
+static struct isonumber_str             _value_socket_recv;
+static struct isonumber_str             _value_socket_send;
+static struct isonumber_str             _value_socket_long;
+
 /* definition of the template data entries for JSON and table output */
 static struct abuf_template_data_entry _tde_time_key[] = {
     { KEY_TIME_SYSTEM, _value_system_time.buf, true },
@@ -113,6 +174,26 @@ static struct abuf_template_data_entry _tde_version_key[] = {
     { KEY_VERSION_TEXT, _value_version_text, true },
     { KEY_VERSION_COMMIT, _value_version_commit, true },
 };
+static struct abuf_template_data_entry _tde_memory_key[] = {
+    { KEY_STATISTICS_NAME, _value_stat_name, true },
+    { KEY_MEMORY_USAGE, _value_memory_usage.buf, false },
+    { KEY_MEMORY_FREELIST, _value_memory_freelist.buf, false },
+    { KEY_MEMORY_ALLOC, _value_memory_alloc.buf, false },
+    { KEY_MEMORY_RECYCLED, _value_memory_recycled.buf, false },
+};
+static struct abuf_template_data_entry _tde_timer_key[] = {
+    { KEY_STATISTICS_NAME, _value_stat_name, true },
+    { KEY_TIMER_USAGE, _value_timer_usage.buf, false },
+    { KEY_TIMER_CHANGE, _value_timer_change.buf, false },
+    { KEY_TIMER_FIRE, _value_timer_fire.buf, false },
+    { KEY_TIMER_LONG, _value_timer_long.buf, false },
+};
+static struct abuf_template_data_entry _tde_socket_key[] = {
+    { KEY_STATISTICS_NAME, _value_stat_name, true },
+    { KEY_SOCKET_RECV, _value_socket_recv.buf, false },
+    { KEY_SOCKET_SEND, _value_socket_send.buf, false },
+    { KEY_SOCKET_LONG, _value_socket_long.buf, false },
+};
 
 static struct abuf_template_storage _template_storage;
 
@@ -123,6 +204,15 @@ static struct abuf_template_data _td_time[] = {
 static struct abuf_template_data _td_version[] = {
     { _tde_version_key, ARRAYSIZE(_tde_version_key) },
 };
+static struct abuf_template_data _td_memory[] = {
+    { _tde_memory_key, ARRAYSIZE(_tde_memory_key) },
+};
+static struct abuf_template_data _td_timer[] = {
+    { _tde_timer_key, ARRAYSIZE(_tde_timer_key) },
+};
+static struct abuf_template_data _td_socket[] = {
+    { _tde_socket_key, ARRAYSIZE(_tde_socket_key) },
+};
 
 /* OONF viewer templates (based on Template Data arrays) */
 static struct oonf_viewer_template _templates[] = {
@@ -138,6 +228,24 @@ static struct oonf_viewer_template _templates[] = {
         .json_name = "version",
         .cb_function = _cb_create_text_version,
     },
+    {
+        .data = _td_memory,
+        .data_size = ARRAYSIZE(_td_memory),
+        .json_name = "memory",
+        .cb_function = _cb_create_text_memory,
+    },
+    {
+        .data = _td_timer,
+        .data_size = ARRAYSIZE(_td_timer),
+        .json_name = "timer",
+        .cb_function = _cb_create_text_timer,
+    },
+    {
+        .data = _td_socket,
+        .data_size = ARRAYSIZE(_td_socket),
+        .json_name = "socket",
+        .cb_function = _cb_create_text_socket,
+    },
 };
 
 /* telnet command of this plugin */
@@ -227,6 +335,58 @@ _initialize_version_values(
       sizeof(_value_version_commit));
 }
 
+/**
+ * Initialize the value buffers for a memory class
+ */
+static void
+_initialize_memory_values(struct oonf_viewer_template *template,
+    struct oonf_class *cl) {
+  strscpy(_value_stat_name, cl->name, sizeof(_value_stat_name));
+
+  isonumber_from_u64(&_value_memory_usage,
+      oonf_class_get_usage(cl), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_memory_freelist,
+      oonf_class_get_free(cl), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_memory_alloc,
+      oonf_class_get_allocations(cl), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_memory_recycled,
+      oonf_class_get_recycled(cl), "", 0, false, template->create_raw);
+}
+
+/**
+ * Initialize the value buffers for a timer class
+ */
+static void
+_initialize_timer_values(struct oonf_viewer_template *template,
+    struct oonf_timer_class *tc) {
+  strscpy(_value_stat_name, tc->name, sizeof(_value_stat_name));
+
+  isonumber_from_u64(&_value_timer_usage,
+      oonf_timer_get_usage(tc), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_timer_change,
+      oonf_timer_get_changes(tc), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_timer_fire,
+      oonf_timer_get_fired(tc), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_timer_long,
+      oonf_timer_get_long(tc), "", 0, false, template->create_raw);
+}
+
+/**
+ * Initialize the value buffers for a timer class
+ */
+static void
+_initialize_socket_values(struct oonf_viewer_template *template,
+    struct oonf_socket_entry *sock) {
+  strscpy(_value_stat_name, sock->name, sizeof(_value_stat_name));
+
+  isonumber_from_u64(&_value_socket_recv,
+      oonf_socket_get_recv(sock), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_socket_send,
+      oonf_socket_get_send(sock), "", 0, false, template->create_raw);
+  isonumber_from_u64(&_value_socket_long,
+      oonf_socket_get_long(sock), "", 0, false, template->create_raw);
+}
+
 /**
  * Callback to generate text/json description of current time
  * @param template viewer template
@@ -256,3 +416,60 @@ _cb_create_text_version(struct oonf_viewer_template *template) {
   oonf_viewer_output_print_line(template);
   return 0;
 }
+
+/**
+ * Callback to generate text/json description of registered memory blocks
+ * @param template viewer template
+ * @return -1 if an error happened, 0 otherwise
+ */
+static int
+_cb_create_text_memory(struct oonf_viewer_template *template) {
+  struct oonf_class *c;
+
+  avl_for_each_element(oonf_class_get_tree(), c, _node) {
+    _initialize_memory_values(template, c);
+
+    /* generate template output */
+    oonf_viewer_output_print_line(template);
+  }
+
+  return 0;
+}
+
+/**
+ * Callback to generate text/json description of registered timers
+ * @param template viewer template
+ * @return -1 if an error happened, 0 otherwise
+ */
+static int
+_cb_create_text_timer(struct oonf_viewer_template *template) {
+  struct oonf_timer_class *tc;
+
+  list_for_each_element(oonf_timer_get_list(), tc, _node) {
+    _initialize_timer_values(template, tc);
+
+    /* generate template output */
+    oonf_viewer_output_print_line(template);
+  }
+
+  return 0;
+}
+
+/**
+ * Callback to generate text/json description of registered sockets
+ * @param template viewer template
+ * @return -1 if an error happened, 0 otherwise
+ */
+static int
+_cb_create_text_socket(struct oonf_viewer_template *template) {
+  struct oonf_socket_entry *sock;
+
+  list_for_each_element(oonf_socket_get_list(), sock, _node) {
+    _initialize_socket_values(template, sock);
+
+    /* generate template output */
+    oonf_viewer_output_print_line(template);
+  }
+
+  return 0;
+}
index ef8be27..c63c02f 100644 (file)
@@ -285,10 +285,10 @@ _handle_scheduling(void)
 
         /* handle statistics */
         if (os_fd_event_is_read(sock)) {
-          sock_entry->usage_r++;
+          sock_entry->_stat_recv++;
         }
         if (os_fd_event_is_write(sock)) {
-          sock_entry->usage_s++;
+          sock_entry->_stat_send++;
         }
         os_clock_gettime64(&start_time);
         sock_entry->process(sock_entry);
@@ -298,7 +298,7 @@ _handle_scheduling(void)
           OONF_WARN(LOG_SOCKET, "Socket '%s' (%d) scheduling took %"PRIu64" ms",
               sock_entry->name,
               os_fd_get_fd(&sock_entry->fd), end_time - start_time);
-          sock_entry->usage_long++;
+          sock_entry->_stat_long++;
         }
       }
     }
index 1b2f956..a0bbf3f 100644 (file)
@@ -72,16 +72,16 @@ struct oonf_socket_entry {
   void (*process) (struct oonf_socket_entry *entry);
 
   /*! usage counter, will be increased every times the socket receives data */
-  uint32_t usage_r;
+  uint32_t _stat_recv;
 
   /*! usage counter, will be increased every times the socket sends data */
-  uint32_t usage_s;
+  uint32_t _stat_send;
 
   /*!
    * usage counter, will be increased every times a socket processing takes
    * more than a TIMER slice
    */
-  uint32_t usage_long;
+  uint32_t _stat_long;
 
   /*! list of socket handlers */
   struct list_entity _node;
@@ -119,7 +119,35 @@ oonf_socket_is_write(struct oonf_socket_entry *entry) {
  */
 static INLINE void
 oonf_socket_register_direct_send(struct oonf_socket_entry *entry) {
-  entry->usage_s++;
+  entry->_stat_send++;
 }
 
+/**
+ * @param sock pointer to socket entry
+ * @return number of recv events of socket
+ */
+static INLINE uint32_t
+oonf_socket_get_recv(struct oonf_socket_entry *sock) {
+  return sock->_stat_recv;
+}
+
+/**
+ * @param sock pointer to socket entry
+ * @return number of send events of socket
+ */
+static INLINE uint32_t
+oonf_socket_get_send(struct oonf_socket_entry *sock) {
+  return sock->_stat_send;
+}
+
+/**
+ * @param sock pointer to socket entry
+ * @return number of times socket handling took more than a timer slice
+ */
+static INLINE uint32_t
+oonf_socket_get_long(struct oonf_socket_entry *sock) {
+  return sock->_stat_long;
+}
+
+
 #endif /* OONF_SOCKET_H_ */
index b01b395..fe90675 100644 (file)
@@ -174,12 +174,12 @@ oonf_timer_start_ext(struct oonf_timer_instance *timer, uint64_t first, uint64_t
 
   if (timer->_clock) {
     avl_remove(&_timer_tree, &timer->_node);
+    timer->class->_stat_changes++;
   }
   else {
     timer->_node.key = timer;
-    timer->class->usage++;
+    timer->class->_stat_usage++;
   }
-  timer->class->changes++;
 
   /*
    * Compute random numbers only once.
@@ -222,8 +222,7 @@ oonf_timer_stop(struct oonf_timer_instance *timer)
   avl_remove(&_timer_tree, &timer->_node);
   timer->_clock = 0;
   timer->_random = 0;
-  timer->class->usage--;
-  timer->class->changes++;
+  timer->class->_stat_usage--;
 
   if (timer->class->_timer_in_callback == timer) {
     timer->class->_timer_stopped = true;
@@ -283,7 +282,7 @@ oonf_timer_walk(void)
     info->_timer_stopped = false;
 
     /* update statistics */
-    info->changes++;
+    info->_stat_fired++;
 
     if (timer->_period == 0) {
       /* stop now, the data structure might not be available anymore later */
@@ -298,6 +297,7 @@ oonf_timer_walk(void)
     if (end_time - start_time > OONF_TIMER_SLICE) {
       OONF_WARN(LOG_TIMER, "Timer %s scheduling took %"PRIu64" ms",
           timer->class->name, end_time - start_time);
+      info->_stat_long++;
     }
 
     /*
index 2715987..38cd187 100644 (file)
@@ -80,11 +80,17 @@ struct oonf_timer_class {
   /*! true if this is a class of periodic timers */
   bool periodic;
 
-  /*! Stats, resource usage */
-  uint32_t usage;
+  /*! Number of times the timer is currently running */
+  uint32_t _stat_usage;
 
-  /*! Stats, resource churn */
-  uint32_t changes;
+  /*! Number of times the timer was reset */
+  uint32_t _stat_changes;
+
+  /*! number of times the timer fired */
+  uint32_t _stat_fired;
+
+  /*! number of times the timer took more than a timeslice */
+  uint32_t _stat_long;
 
   /*! pointer to timer currently in callback */
   struct oonf_timer_instance *_timer_in_callback;
@@ -180,4 +186,40 @@ oonf_timer_start(struct oonf_timer_instance *timer, uint64_t rel_time) {
   oonf_timer_start_ext(timer, rel_time, rel_time);
 }
 
+/**
+ * @param timer pointer to timer class
+ * @return number of timers currently in use
+ */
+static INLINE uint32_t
+oonf_timer_get_usage(struct oonf_timer_class *tc) {
+  return tc->_stat_usage;
+}
+
+/**
+ * @param timer pointer to timer class
+ * @return number of times the timer was reset
+ */
+static INLINE uint32_t
+oonf_timer_get_changes(struct oonf_timer_class *tc) {
+  return tc->_stat_changes;
+}
+
+/**
+ * @param timer pointer to timer class
+ * @return number of times the timer was fired
+ */
+static INLINE uint32_t
+oonf_timer_get_fired(struct oonf_timer_class *tc) {
+  return tc->_stat_fired;
+}
+
+/**
+ * @param timer pointer to timer class
+ * @return number of times the timer took more than a timeslice
+ */
+static INLINE uint32_t
+oonf_timer_get_long(struct oonf_timer_class *tc) {
+  return tc->_stat_long;
+}
+
 #endif /* OONF_TIMER_H_ */