⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statistics.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
字号:
/*  This file is part of GNUnet.  (C) 2001, 2002, 2004, 2006, 2007 Christian Grothoff (and other contributing authors)  GNUnet is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published  by the Free Software Foundation; either version 2, or (at your  option) any later version.  GNUnet is distributed in the hope that it will be useful, but  WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  General Public License for more details.  You should have received a copy of the GNU General Public License  along with GNUnet; see the file COPYING.  If not, write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,  Boston, MA 02111-1307, USA.*//** * @file applications/stats/statistics.c * @brief keeping statistics of GNUnet activities * @author Christian Grothoff * * This module keeps a mapping of strings to (unsigned long long) * values. Every entry in the mapping can be accessed with a handle * (int) which can be obtained from the string. The module can be used * to keep track of certain statistical information, such as the * number of bytes received, messages sent, kilobytes stored, and so * on.<p> * * When loaded by gnunetd, the gnunet-stats tool can be used to * print the statistical information stored in this module. */#include "platform.h"#include "gnunet_util.h"#include "gnunet_core.h"#include "gnunet_protocols.h"#include "gnunet_stats_service.h"#include "statistics.h"/** * Should we generate *very* costly statistics about * the SQStore?  Only set to GNUNET_YES for debugging, never * in production! */#define HAVE_SQSTATS GNUNET_NO/* *************** service *************** *//** * When did the module start? */static GNUNET_CronTime startTime;struct StatEntry{  unsigned long long value;  char *description;  unsigned int descStrLen;};static struct StatEntry *entries;/** * Size of the entries array */static unsigned int statCounters;/** * lock for the stat module */static struct GNUNET_Mutex *statLock;/** * The core API. */static GNUNET_CoreAPIForPlugins *coreAPI;/** * Get a handle to a statistical entity. * * @param name a description of the entity * @return a handle for updating the associated value */static intstatHandle (const char *name){  int i;  GNUNET_GE_ASSERT (NULL, name != NULL);  GNUNET_mutex_lock (statLock);  for (i = 0; i < statCounters; i++)    if (0 == strcmp (entries[i].description, name))      {        GNUNET_mutex_unlock (statLock);        return i;      }  GNUNET_array_grow (entries, statCounters, statCounters + 1);  i = statCounters - 1;  entries[i].description = GNUNET_strdup (name);  entries[i].descStrLen = strlen (name);  entries[i].value = 0;  GNUNET_mutex_unlock (statLock);  return i;}/** * Manipulate statistics. Sets the statistics associated with the * handle to value. * * @param handle the handle for the value to change * @param value to what the value should be set */static voidstatSet (const int handle, const unsigned long long value){  GNUNET_mutex_lock (statLock);  if ((handle < 0) || (handle >= statCounters))    {      GNUNET_GE_BREAK (NULL, 0);      GNUNET_mutex_unlock (statLock);      return;    }  entries[handle].value = value;  GNUNET_mutex_unlock (statLock);}static unsigned long longstatGet (const int handle){  unsigned long long ret;  GNUNET_mutex_lock (statLock);  if ((handle < 0) || (handle >= statCounters))    {      GNUNET_GE_BREAK (NULL, 0);      GNUNET_mutex_unlock (statLock);      return -1;    }  ret = entries[handle].value;  GNUNET_mutex_unlock (statLock);  return ret;}/** * Manipulate statistics. Changes the statistics associated with the * value by delta. * * @param handle the handle for the value to change * @param delta by how much should the value be changed */static voidstatChange (const int handle, const int delta){  GNUNET_mutex_lock (statLock);  if ((handle < 0) || (handle >= statCounters))    {      GNUNET_GE_BREAK (NULL, 0);      GNUNET_mutex_unlock (statLock);      return;    }  entries[handle].value += delta;  GNUNET_mutex_unlock (statLock);}/** * Shutdown the statistics module. */voidrelease_module_stats (){  int i;  GNUNET_mutex_destroy (statLock);  for (i = 0; i < statCounters; i++)    GNUNET_free (entries[i].description);  GNUNET_array_grow (entries, statCounters, 0);}/** * Initialize the statistics module. */GNUNET_Stats_ServiceAPI *provide_module_stats (GNUNET_CoreAPIForPlugins * capi){  static GNUNET_Stats_ServiceAPI api;  coreAPI = capi;  api.create = &statHandle;  api.set = &statSet;  api.change = &statChange;  api.get = &statGet;  startTime = GNUNET_get_time ();  statLock = GNUNET_mutex_create (GNUNET_YES);  return &api;}/* *************** protocol *************** *//* ********* special stats that are updated   always just before we send the reply ******* */static int stat_handle_network_load_up;static int stat_handle_network_load_down;static int stat_handle_cpu_load;static int stat_handle_io_load;static int stat_bytes_noise_received;static int stat_connected;#ifdef MINGWstatic int stat_handles;#endifstatic GNUNET_Stats_ServiceAPI *stats;static GNUNET_CoreAPIForPlugins *myCoreAPI;#if HAVE_SQSTATS#include "sqstats.c"#endifextern unsigned int uiHandleCount;static voidinitializeStats (){  stat_handle_network_load_up = statHandle (gettext_noop (      /* xgettext:no-c-format */                                                           "% of allowed network load (up)"));  stat_handle_network_load_down = statHandle (gettext_noop (    /* xgettext:no-c-format */                                                             "% of allowed network load (down)"));  stat_handle_cpu_load =    statHandle (gettext_noop                ( /* xgettext:no-c-format */ "% of allowed cpu load"));  stat_handle_io_load =    statHandle (gettext_noop                ( /* xgettext:no-c-format */ "% of allowed io load"));  stat_connected = statHandle (gettext_noop ("# of connected peers"));  stat_bytes_noise_received    = statHandle (gettext_noop ("# bytes of noise received"));#ifdef MINGW  stat_handles = statHandle (gettext_noop ("# plibc handles"));#endif}static voidimmediateUpdates (){  int load;#if HAVE_SQSTATS  update_sqstore_stats ();#endif  load = GNUNET_cpu_get_load (coreAPI->ectx, coreAPI->cfg);  if (load == -1)    load = 0;  statSet (stat_handle_cpu_load, load);  load = GNUNET_disk_get_load (coreAPI->ectx, coreAPI->cfg);  if (load == -1)    load = 0;  statSet (stat_handle_io_load, load);  load =    GNUNET_network_monitor_get_load (coreAPI->load_monitor, GNUNET_ND_UPLOAD);  if (load == -1)    load = 0;  statSet (stat_handle_network_load_up, load);  load =    GNUNET_network_monitor_get_load (coreAPI->load_monitor,                                     GNUNET_ND_DOWNLOAD);  if (load == -1)    load = 0;  statSet (stat_handle_network_load_down, load);  statSet (stat_connected, coreAPI->p2p_connections_iterate (NULL, NULL));#ifdef MINGW  statSet (stat_handles, plibc_get_handle_count ());#endif}/** * Send statistics to a TCP socket.  May send multiple messages if the * overall size would be too big otherwise. * * @param originalRequestMessage ignored at this point. */static intsendStatistics (struct GNUNET_ClientHandle *sock,                const GNUNET_MessageHeader * originalRequestMessage){  CS_stats_reply_MESSAGE *statMsg;  int pos;                      /* position in the values-descriptions */  int start;  int end;  int mpos;                     /* postion in the message */  immediateUpdates ();  statMsg = GNUNET_malloc (GNUNET_MAX_BUFFER_SIZE);  statMsg->header.type = htons (GNUNET_CS_PROTO_STATS_STATISTICS);  statMsg->totalCounters = htonl (statCounters);  statMsg->statCounters = htons (0);  statMsg->startTime = GNUNET_htonll (startTime);  start = 0;  while (start < statCounters)    {      pos = start;      /* first pass: gauge how many statistic numbers         and their descriptions we can send in one message */      mpos = 0;      while ((pos < statCounters) &&             (mpos + sizeof (unsigned long long)              + entries[pos].descStrLen + 1              < GNUNET_MAX_BUFFER_SIZE - sizeof (CS_stats_reply_MESSAGE)))        {          mpos += sizeof (unsigned long long);  /* value */          mpos += entries[pos].descStrLen + 1;          pos++;        }      end = pos;      /* second pass: copy values and messages to message */      for (pos = start; pos < end; pos++)        ((CS_stats_reply_MESSAGE_GENERIC *) statMsg)->values[pos -                                                             start] =          GNUNET_htonll (entries[pos].value);      mpos = sizeof (unsigned long long) * (end - start);      for (pos = start; pos < end; pos++)        {          memcpy (&                  ((char                    *) (((CS_stats_reply_MESSAGE_GENERIC *)                         statMsg))->values)[mpos], entries[pos].description,                  entries[pos].descStrLen + 1);          mpos += entries[pos].descStrLen + 1;        }      statMsg->statCounters = htonl (end - start);      GNUNET_GE_ASSERT (NULL,                        mpos + sizeof (CS_stats_reply_MESSAGE) <                        GNUNET_MAX_BUFFER_SIZE);      statMsg->header.size = htons (mpos + sizeof (CS_stats_reply_MESSAGE));      /* printf("writing message of size %d with stats %d to %d out of %d to socket\n",         ntohs(statMsg->header.size),         start, end, statCounters); */      if (GNUNET_SYSERR ==          coreAPI->cs_send_message (sock, &statMsg->header, GNUNET_YES))        break;                  /* abort, socket error! */      start = end;    }  GNUNET_free (statMsg);  return GNUNET_OK;}/** * Handle a request to see if a particular p2p message is supported. */static inthandleMessageSupported (struct GNUNET_ClientHandle *sock,                        const GNUNET_MessageHeader * message){  unsigned short type;  unsigned short htype;  int supported;  CS_stats_get_supported_MESSAGE *cmsg;  if (ntohs (message->size) != sizeof (CS_stats_get_supported_MESSAGE))    {      GNUNET_GE_BREAK (NULL, 0);      return GNUNET_SYSERR;    }  cmsg = (CS_stats_get_supported_MESSAGE *) message;  type = ntohs (cmsg->type);  htype = ntohs (cmsg->handlerType);  supported = coreAPI->p2p_message_handler_registered_test (type, htype);  return coreAPI->cs_send_value (sock, supported);}/** * We received a request from a client to provide the number * of directly connected peers.  Sends the response. * * @param client the socket connecting to the client * @param msg the request from the client * @returns GNUNET_OK if ok, GNUNET_SYSERR if not. */static intprocessGetConnectionCountRequest (struct GNUNET_ClientHandle *client,                                  const GNUNET_MessageHeader * msg){  if (ntohs (msg->size) != sizeof (GNUNET_MessageHeader))    {      GNUNET_GE_BREAK (NULL, 0);      return GNUNET_SYSERR;    }  return coreAPI->cs_send_value    (client, coreAPI->p2p_connections_iterate (NULL, NULL));}/** * Handler for processing noise. */static intprocessNoise (const GNUNET_PeerIdentity * sender,              const GNUNET_MessageHeader * msg){  statChange (stat_bytes_noise_received, ntohs (msg->size));  return GNUNET_OK;}intinitialize_module_stats (GNUNET_CoreAPIForPlugins * capi){  GNUNET_GE_ASSERT (capi->ectx, myCoreAPI == NULL);  myCoreAPI = capi;  stats = capi->service_request ("stats");  if (stats == NULL)    {      GNUNET_GE_BREAK (capi->ectx, 0);      myCoreAPI = NULL;      return GNUNET_SYSERR;    }  initializeStats ();  GNUNET_GE_LOG (capi->ectx,                 GNUNET_GE_INFO | GNUNET_GE_USER | GNUNET_GE_REQUEST,                 _                 ("`%s' registering client handlers %d %d %d and p2p handler %d\n"),                 "stats", GNUNET_CS_PROTO_TRAFFIC_COUNT,                 GNUNET_CS_PROTO_STATS_GET_STATISTICS,                 GNUNET_CS_PROTO_STATS_GET_P2P_MESSAGE_SUPPORTED,                 GNUNET_P2P_PROTO_NOISE);  capi->cs_handler_register (GNUNET_CS_PROTO_STATS_GET_STATISTICS,                             &sendStatistics);  capi->cs_handler_register    (GNUNET_CS_PROTO_STATS_GET_P2P_MESSAGE_SUPPORTED,     &handleMessageSupported);  capi->cs_handler_register    (GNUNET_CS_PROTO_STATS_GET_CS_MESSAGE_SUPPORTED, &handleMessageSupported);  capi->cs_handler_register (GNUNET_CS_PROTO_TRAFFIC_COUNT,                             &processGetConnectionCountRequest);  capi->p2p_ciphertext_handler_register (GNUNET_P2P_PROTO_NOISE,                                         &processNoise);  GNUNET_GE_ASSERT (capi->ectx,                    0 == GNUNET_GC_set_configuration_value_string (capi->cfg,                                                                   capi->ectx,                                                                   "ABOUT",                                                                   "stats",                                                                   gettext_noop                                                                   ("keeps statistics about gnunetd's operation")));#if HAVE_SQSTATS  init_sqstore_stats ();#endif  immediateUpdates ();  return GNUNET_OK;}intdone_module_stats (){#if HAVE_SQSTATS  done_sqstore_stats ();#endif  GNUNET_GE_ASSERT (NULL, myCoreAPI != NULL);  coreAPI->cs_handler_unregister (GNUNET_CS_PROTO_STATS_GET_STATISTICS,                                  &sendStatistics);  coreAPI->cs_handler_unregister    (GNUNET_CS_PROTO_STATS_GET_P2P_MESSAGE_SUPPORTED,     &handleMessageSupported);  coreAPI->cs_handler_unregister    (GNUNET_CS_PROTO_STATS_GET_CS_MESSAGE_SUPPORTED, &handleMessageSupported);  coreAPI->cs_handler_unregister (GNUNET_CS_PROTO_TRAFFIC_COUNT,                                  &processGetConnectionCountRequest);  coreAPI->p2p_ciphertext_handler_unregister (GNUNET_P2P_PROTO_NOISE,                                              &processNoise);  myCoreAPI->service_release (stats);  stats = NULL;  myCoreAPI = NULL;  return GNUNET_OK;}/* end of statistics.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -