GNUnet 0.22.2
gnunet-service-statistics.c File Reference

program that tracks statistics More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_time_lib.h"
#include "statistics.h"
Include dependency graph for gnunet-service-statistics.c:

Go to the source code of this file.

Data Structures

struct  WatchEntry
 Watch entry. More...
 
struct  StatsEntry
 Entry in the statistics list. More...
 
struct  SubsystemEntry
 We keep the statistics organized by subsystem for faster lookup during SET operations. More...
 
struct  ClientEntry
 Information about one of our clients. More...
 

Functions

static void save ()
 Write persistent statistics to disk. More...
 
static void transmit (struct ClientEntry *ce, const struct StatsEntry *e)
 Transmit the given stats value. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
 Callback called when a client connects to the service. More...
 
static int check_get (void *cls, const struct GNUNET_MessageHeader *message)
 Check integrity of GET-message. More...
 
static void handle_get (void *cls, const struct GNUNET_MessageHeader *message)
 Handle GET-message. More...
 
static void notify_change (struct StatsEntry *se)
 Notify all clients listening about a change to a value. More...
 
static struct SubsystemEntryfind_subsystem_entry (struct ClientEntry *ce, const char *service)
 Find the subsystem entry of the given name for the specified client. More...
 
static struct StatsEntryfind_stat_entry (struct SubsystemEntry *se, const char *name)
 Find the statistics entry of the given subsystem. More...
 
static int check_set (void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
 Check format of SET-message. More...
 
static void handle_set (void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
 Handle SET-message. More...
 
static int check_watch (void *cls, const struct GNUNET_MessageHeader *message)
 Check integrity of WATCH-message. More...
 
static void handle_watch (void *cls, const struct GNUNET_MessageHeader *message)
 Handle WATCH-message. More...
 
static void handle_disconnect (void *cls, const struct GNUNET_MessageHeader *message)
 Handle DISCONNECT-message. More...
 
static void do_shutdown ()
 Actually perform the shutdown. More...
 
static void shutdown_task (void *cls)
 Task run during shutdown. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
 A client disconnected. More...
 
static int inject_message (void *cls, const struct GNUNET_MessageHeader *message)
 We've read a struct GNUNET_STATISTICS_SetMessage * from disk. More...
 
static void load ()
 Load persistent values from disk. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
 Process statistics requests. More...
 
 GNUNET_SERVICE_MAIN (GNUNET_OS_project_data_gnunet(), "statistics", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(set, GNUNET_MESSAGE_TYPE_STATISTICS_SET, struct GNUNET_STATISTICS_SetMessage, NULL), GNUNET_MQ_hd_var_size(get, GNUNET_MESSAGE_TYPE_STATISTICS_GET, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_var_size(watch, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(disconnect, GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration. More...
 
static struct SubsystemEntrysub_head
 Head of linked list of subsystems with active statistics. More...
 
static struct SubsystemEntrysub_tail
 Tail of linked list of subsystems with active statistics. More...
 
static unsigned int client_count
 Number of connected clients. More...
 
static struct GNUNET_NotificationContextnc
 Our notification context. More...
 
static uint32_t uidgen
 Counter used to generate unique values. More...
 
static int in_shutdown
 Set to GNUNET_YES if we are shutting down as soon as possible. More...
 

Detailed Description

program that tracks statistics

Author
Christian Grothoff

Definition in file gnunet-service-statistics.c.

Function Documentation

◆ save()

static void save ( )
static

Write persistent statistics to disk.

Definition at line 237 of file gnunet-service-statistics.c.

238{
239 struct SubsystemEntry *se;
240 struct StatsEntry *pos;
241 char *fn;
242 struct GNUNET_BIO_WriteHandle *wh;
243 uint16_t size;
244 unsigned long long total;
245 size_t nlen;
246 size_t slen;
248
250 "STATISTICS",
251 "DATABASE",
252 &fn))
253 {
255 "STATISTICS",
256 "DATABASE");
257 return;
258 }
261 total = 0;
262 while (NULL != (se = sub_head))
263 {
265 slen = strlen (se->service) + 1;
266 while (NULL != (pos = se->stat_head))
267 {
269 if ((pos->persistent) && (NULL != wh))
270 {
271 nlen = strlen (pos->name) + 1;
272 size = sizeof(struct GNUNET_STATISTICS_SetMessage) + nlen + slen;
273 GNUNET_assert (size < UINT16_MAX);
275
276 msg->header.size = htons ((uint16_t) size);
278 GNUNET_assert (nlen + slen ==
279 GNUNET_STRINGS_buffer_fill ((char *) &msg[1],
280 nlen + slen,
281 2,
282 se->service,
283 pos->name));
284 msg->flags =
286 msg->value = GNUNET_htonll (pos->value);
287 if (GNUNET_OK != GNUNET_BIO_write (wh, "statistics-save-msg", msg,
288 size))
289 {
291 if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
293 wh = NULL;
294 }
295 else
296 {
297 total += size;
298 }
300 }
301 GNUNET_free (pos);
302 }
303 GNUNET_free (se);
304 }
305 if (NULL != wh)
306 {
307 if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
309 if (0 == total)
310 GNUNET_break (0 == unlink (fn));
311 else
313 _ ("Wrote %llu bytes of statistics to `%s'\n"),
314 total,
315 fn);
316 }
317 GNUNET_free (fn);
318}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static struct SubsystemEntry * sub_tail
Tail of linked list of subsystems with active statistics.
static struct SubsystemEntry * sub_head
Head of linked list of subsystems with active statistics.
enum GNUNET_GenericReturnValue GNUNET_BIO_write_close(struct GNUNET_BIO_WriteHandle *h, char **emsg)
Close an IO handle.
Definition: bio.c:556
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open_file(const char *fn)
Open a file for writing.
Definition: bio.c:508
enum GNUNET_GenericReturnValue GNUNET_BIO_write(struct GNUNET_BIO_WriteHandle *h, const char *what, const void *buffer, size_t n)
Write a buffer to a handle.
Definition: bio.c:750
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:606
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MESSAGE_TYPE_STATISTICS_SET
Set a statistical value.
size_t GNUNET_STRINGS_buffer_fill(char *buffer, size_t size, unsigned int count,...)
Fill a buffer of the given size with count 0-terminated strings (given as varargs).
Definition: strings.c:43
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_STATISTICS_SETFLAG_PERSISTENT
The value being set is to be persistent (note that this bit can be combined with GNUNET_STATISTICS_SE...
Definition: statistics.h:83
Handle for buffered writing.
Definition: bio.c:466
Message to set a statistic.
Definition: statistics.h:92
Entry in the statistics list.
uint64_t value
Our value.
int persistent
Is this value persistent?
const char * name
Name for the value stored by this entry, allocated at the end of this struct.
We keep the statistics organized by subsystem for faster lookup during SET operations.
struct StatsEntry * stat_head
Head of list of values kept for this subsystem.
struct StatsEntry * stat_tail
Tail of list of values kept for this subsystem.
const char * service
Name of the subsystem this entry is for, allocated at the end of this struct, do not free().

References _, cfg, GNUNET_assert, GNUNET_BIO_write(), GNUNET_BIO_write_close(), GNUNET_BIO_write_open_file(), GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONTAINER_DLL_remove, GNUNET_DISK_directory_create_for_file(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_htonll(), GNUNET_log, GNUNET_log_config_missing(), GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_MESSAGE_TYPE_STATISTICS_SET, GNUNET_OK, GNUNET_STATISTICS_SETFLAG_PERSISTENT, GNUNET_STRINGS_buffer_fill(), msg, StatsEntry::name, StatsEntry::persistent, SubsystemEntry::service, GNUNET_MessageHeader::size, size, SubsystemEntry::stat_head, SubsystemEntry::stat_tail, sub_head, sub_tail, GNUNET_MessageHeader::type, and StatsEntry::value.

Referenced by do_shutdown(), GNUNET_STRINGS_parse_ipv6_policy(), iterate_save_entries(), iterate_save_links(), iterate_save_messages(), and save_message_store().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit()

static void transmit ( struct ClientEntry ce,
const struct StatsEntry e 
)
static

Transmit the given stats value.

Parameters
cereceiver of the value
evalue to transmit

Definition at line 328 of file gnunet-service-statistics.c.

329{
330 struct GNUNET_MQ_Envelope *env;
332 size_t size;
333
334 size = strlen (e->subsystem->service) + 1 + strlen (e->name) + 1;
337 m->uid = htonl (e->uid);
338 if (e->persistent)
339 m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT);
340 m->value = GNUNET_htonll (e->value);
342 size,
343 2,
344 e->subsystem->service,
345 e->name));
347 "Transmitting value for `%s:%s' (%d): %llu\n",
348 e->subsystem->service,
349 e->name,
350 e->persistent,
351 (unsigned long long) e->value);
352 GNUNET_MQ_send (ce->mq, env);
353}
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:103
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
@ GNUNET_ERROR_TYPE_DEBUG
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:305
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:61
#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE
Response to a STATISTICS_GET message (with value).
#define GNUNET_STATISTICS_PERSIST_BIT
Flag for the struct GNUNET_STATISTICS_ReplyMessage UID only.
Definition: statistics.h:65
struct GNUNET_MQ_Handle * mq
Queue for transmissions to client.
Statistics message.
Definition: statistics.h:41
struct SubsystemEntry * subsystem
Subsystem this entry belongs to.
uint32_t uid
Unique ID.

References env, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_htonll(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_MESSAGE_TYPE_STATISTICS_VALUE, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_STATISTICS_PERSIST_BIT, GNUNET_STRINGS_buffer_fill(), m, ClientEntry::mq, StatsEntry::name, StatsEntry::persistent, SubsystemEntry::service, size, StatsEntry::subsystem, StatsEntry::uid, and StatsEntry::value.

Referenced by handle_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

static void * client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
struct GNUNET_MQ_Handle mq 
)
static

Callback called when a client connects to the service.

Parameters
clsclosure for the service
cthe new client that connected to the service
mqthe message queue used to send messages to the client
Returns
c

Definition at line 365 of file gnunet-service-statistics.c.

368{
369 struct ClientEntry *ce;
370
371 ce = GNUNET_new (struct ClientEntry);
372 ce->client = c;
373 ce->mq = mq;
374 client_count++;
376 return ce;
377}
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static unsigned int client_count
Number of connected clients.
static struct GNUNET_NotificationContext * nc
Our notification context.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:161
Information about one of our clients.
struct GNUNET_SERVICE_Client * client
Handle identifying the client.

References ClientEntry::client, client_count, GNUNET_new, GNUNET_notification_context_add(), mq, ClientEntry::mq, and nc.

Here is the call graph for this function:

◆ check_get()

static int check_get ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Check integrity of GET-message.

Parameters
clsidentification of the client
messagethe actual message
Returns
GNUNET_OK if message is well-formed

Definition at line 388 of file gnunet-service-statistics.c.

389{
390 const char *service;
391 const char *name;
392 size_t size;
393
394 size = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
395 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
396 size,
397 2,
398 &service,
399 &name))
400 {
401 GNUNET_break (0);
402 return GNUNET_SYSERR;
403 }
404 return GNUNET_OK;
405}
static char * name
Name (label) of the records to list.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
@ GNUNET_SYSERR
unsigned int GNUNET_STRINGS_buffer_tokenize(const char *buffer, size_t size, unsigned int count,...)
Given a buffer of a given size, find "count" 0-terminated strings in the buffer and assign the count ...
Definition: strings.c:71
Header for all communications.

References GNUNET_break, GNUNET_OK, GNUNET_STRINGS_buffer_tokenize(), GNUNET_SYSERR, name, service, GNUNET_MessageHeader::size, and size.

Here is the call graph for this function:

◆ handle_get()

static void handle_get ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle GET-message.

Parameters
clsidentification of the client
messagethe actual message

Definition at line 415 of file gnunet-service-statistics.c.

416{
417 struct ClientEntry *ce = cls;
418 struct GNUNET_MQ_Envelope *env;
420 const char *service;
421 const char *name;
422 size_t slen;
423 size_t nlen;
424 struct SubsystemEntry *se;
425 struct StatsEntry *pos;
426 size_t size;
427
428 size = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
430 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
431 size,
432 2,
433 &service,
434 &name));
435 slen = strlen (service);
436 nlen = strlen (name);
438 "Received request for statistics on `%s:%s'\n",
439 slen ? service : "*",
440 nlen ? name : "*");
441 for (se = sub_head; NULL != se; se = se->next)
442 {
443 if (! ((0 == slen) || (0 == strcmp (service, se->service))))
444 continue;
445 for (pos = se->stat_head; NULL != pos; pos = pos->next)
446 {
447 if (! ((0 == nlen) || (0 == strcmp (name, pos->name))))
448 continue;
449 transmit (ce, pos);
450 }
451 }
453 GNUNET_MQ_send (ce->mq, env);
455}
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:33
static void transmit(struct ClientEntry *ce, const struct StatsEntry *e)
Transmit the given stats value.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:76
#define GNUNET_MESSAGE_TYPE_STATISTICS_END
Response to a STATISTICS_GET message (end of value stream).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
struct StatsEntry * next
This is a linked list.
struct SubsystemEntry * next
Subsystems are kept in a DLL.

References ClientEntry::client, end, env, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_STATISTICS_END, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_STRINGS_buffer_tokenize(), ClientEntry::mq, name, StatsEntry::name, StatsEntry::next, SubsystemEntry::next, service, SubsystemEntry::service, GNUNET_MessageHeader::size, size, SubsystemEntry::stat_head, sub_head, and transmit().

Here is the call graph for this function:

◆ notify_change()

static void notify_change ( struct StatsEntry se)
static

Notify all clients listening about a change to a value.

Parameters
sevalue that changed

Definition at line 464 of file gnunet-service-statistics.c.

465{
466 struct GNUNET_MQ_Envelope *env;
468 struct WatchEntry *pos;
469
470 for (pos = se->we_head; NULL != pos; pos = pos->next)
471 {
472 if (GNUNET_YES == pos->last_value_set)
473 {
474 if (pos->last_value == se->value)
475 continue;
476 }
477 else
478 {
480 }
482 wvm->flags =
484 wvm->wid = htonl (pos->wid);
485 wvm->reserved = htonl (0);
486 wvm->value = GNUNET_htonll (se->value);
487 GNUNET_MQ_send (pos->ce->mq, env);
488 pos->last_value = se->value;
489 }
490}
@ GNUNET_YES
#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
Changes to a watched value.
Message transmitted if a watched value changes.
Definition: statistics.h:116
uint32_t reserved
Reserved (always 0).
Definition: statistics.h:139
uint32_t flags
0 for absolute value, 1 for relative value; 2 to make persistent (see GNUNET_STATISTICS_SETFLAG_*).
Definition: statistics.h:126
uint32_t wid
Unique watch identification number (watch requests are enumerated in the order they are received,...
Definition: statistics.h:134
struct WatchEntry * we_head
Watch context for changes to this value, or NULL for none.
struct WatchEntry * next
Watch entries are kept in a linked list.
uint64_t last_value
Last value we communicated to the client for this watch entry.
int last_value_set
Is last_value valid GNUNET_NO : last_value is n/a, GNUNET_YES: last_value is valid.
uint32_t wid
Unique watch number for this client and this watched value.
struct ClientEntry * ce
For which client is this watch entry?

References WatchEntry::ce, env, GNUNET_STATISTICS_WatchValueMessage::flags, GNUNET_htonll(), GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_STATISTICS_SETFLAG_PERSISTENT, GNUNET_YES, WatchEntry::last_value, WatchEntry::last_value_set, ClientEntry::mq, WatchEntry::next, StatsEntry::persistent, GNUNET_STATISTICS_WatchValueMessage::reserved, StatsEntry::value, GNUNET_STATISTICS_WatchValueMessage::value, StatsEntry::we_head, WatchEntry::wid, and GNUNET_STATISTICS_WatchValueMessage::wid.

Referenced by handle_set(), and handle_watch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_subsystem_entry()

static struct SubsystemEntry * find_subsystem_entry ( struct ClientEntry ce,
const char *  service 
)
static

Find the subsystem entry of the given name for the specified client.

Parameters
ceclient looking for the subsystem, may contain a hint to find the entry faster, can be NULL
servicename of the subsystem to look for
Returns
subsystem entry, never NULL (subsystem entry is created if necessary)

Definition at line 502 of file gnunet-service-statistics.c.

503{
504 size_t slen;
505 struct SubsystemEntry *se;
506
507 if (NULL != ce)
508 se = ce->subsystem;
509 else
510 se = NULL;
511 if ((NULL == se) || (0 != strcmp (service, se->service)))
512 {
513 for (se = sub_head; NULL != se; se = se->next)
514 if (0 == strcmp (service, se->service))
515 break;
516 if (NULL != ce)
517 ce->subsystem = se;
518 }
519 if (NULL != se)
520 return se;
522 "Allocating new subsystem entry `%s'\n",
523 service);
524 slen = strlen (service) + 1;
525 se = GNUNET_malloc (sizeof(struct SubsystemEntry) + slen);
526 GNUNET_memcpy (&se[1], service, slen);
527 se->service = (const char *) &se[1];
529 if (NULL != ce)
530 ce->subsystem = se;
531 return se;
532}
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct SubsystemEntry * subsystem
Which subsystem is this client writing to (SET/UPDATE)?

References GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, SubsystemEntry::next, service, SubsystemEntry::service, sub_head, sub_tail, and ClientEntry::subsystem.

Referenced by handle_set(), and handle_watch().

Here is the caller graph for this function:

◆ find_stat_entry()

static struct StatsEntry * find_stat_entry ( struct SubsystemEntry se,
const char *  name 
)
static

Find the statistics entry of the given subsystem.

Parameters
sesubsystem to look in
namename of the entry to look for
Returns
statistics entry, or NULL if not found

Definition at line 543 of file gnunet-service-statistics.c.

544{
545 struct StatsEntry *pos;
546
547 for (pos = se->stat_head; NULL != pos; pos = pos->next)
548 if (0 == strcmp (name, pos->name))
549 return pos;
550 return NULL;
551}

References name, StatsEntry::name, StatsEntry::next, and SubsystemEntry::stat_head.

Referenced by handle_set(), and handle_watch().

Here is the caller graph for this function:

◆ check_set()

static int check_set ( void *  cls,
const struct GNUNET_STATISTICS_SetMessage msg 
)
static

Check format of SET-message.

Parameters
clsthe struct ClientEntry
msgthe actual message
Returns
GNUNET_OK if message is well-formed

Definition at line 562 of file gnunet-service-statistics.c.

563{
564 const char *service;
565 const char *name;
566 size_t msize;
567
568 msize = ntohs (msg->header.size) - sizeof(*msg);
569 if (msize != GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1],
570 msize,
571 2,
572 &service,
573 &name))
574 {
575 GNUNET_break (0);
576 return GNUNET_SYSERR;
577 }
578 return GNUNET_OK;
579}

References GNUNET_break, GNUNET_OK, GNUNET_STRINGS_buffer_tokenize(), GNUNET_SYSERR, msg, name, service, and GNUNET_MessageHeader::size.

Referenced by inject_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_set()

static void handle_set ( void *  cls,
const struct GNUNET_STATISTICS_SetMessage msg 
)
static

Handle SET-message.

Parameters
clsthe struct ClientEntry
msgthe actual message

Definition at line 589 of file gnunet-service-statistics.c.

590{
591 struct ClientEntry *ce = cls;
592 const char *service;
593 const char *name;
594 size_t nlen;
595 uint16_t msize;
596 uint16_t size;
597 struct SubsystemEntry *se;
598 struct StatsEntry *pos;
599 uint32_t flags;
600 uint64_t value;
601 int64_t delta;
602 int changed;
603 int initial_set;
604
605 msize = ntohs (msg->header.size);
606 size = msize - sizeof(struct GNUNET_STATISTICS_SetMessage);
608 size,
609 2,
610 &service,
611 &name));
612 se = find_subsystem_entry (ce, service);
613 flags = ntohl (msg->flags);
614 value = GNUNET_ntohll (msg->value);
616 "Received request to update statistic on `%s:%s' (%u) to/by %llu\n",
617 service,
618 name,
619 (unsigned int) flags,
620 (unsigned long long) value);
621 pos = find_stat_entry (se, name);
622 if (NULL != pos)
623 {
624 initial_set = 0;
626 {
627 changed = (pos->value != value);
628 pos->value = value;
629 }
630 else
631 {
632 delta = (int64_t) value;
633 if ((delta < 0) && (pos->value < -delta))
634 {
635 changed = (0 != pos->value);
636 pos->value = 0;
637 }
638 else
639 {
640 changed = (0 != delta);
641 GNUNET_break ((delta <= 0) || (pos->value + delta > pos->value));
642 pos->value += delta;
643 }
644 }
645 if (GNUNET_NO == pos->set)
646 {
647 pos->set = GNUNET_YES;
648 initial_set = 1;
649 }
651 if (pos != se->stat_head)
652 {
653 /* move to front for faster setting next time! */
656 }
658 "Statistic `%s:%s' updated to value %llu (%d).\n",
659 service,
660 name,
661 (unsigned long long) pos->value,
662 pos->persistent);
663 if ((changed) || (1 == initial_set))
664 notify_change (pos);
666 return;
667 }
668 /* not found, create a new entry */
669 nlen = strlen (name) + 1;
670 pos = GNUNET_malloc (sizeof(struct StatsEntry) + nlen);
671 GNUNET_memcpy (&pos[1], name, nlen);
672 pos->name = (const char *) &pos[1];
673 pos->subsystem = se;
675 (0 < (int64_t) GNUNET_ntohll (msg->value)))
676 {
677 pos->value = GNUNET_ntohll (msg->value);
678 pos->set = GNUNET_YES;
679 }
680 else
681 {
682 pos->set = GNUNET_NO;
683 }
684 pos->uid = uidgen++;
688 "New statistic on `%s:%s' with value %llu created.\n",
689 service,
690 name,
691 (unsigned long long) pos->value);
692 if (NULL != ce)
694}
static char * value
Value of the record to add/remove.
static struct SubsystemEntry * find_subsystem_entry(struct ClientEntry *ce, const char *service)
Find the subsystem entry of the given name for the specified client.
static void notify_change(struct StatsEntry *se)
Notify all clients listening about a change to a value.
static struct StatsEntry * find_stat_entry(struct SubsystemEntry *se, const char *name)
Find the statistics entry of the given subsystem.
static uint32_t uidgen
Counter used to generate unique values.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
@ GNUNET_NO
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
#define GNUNET_STATISTICS_SETFLAG_RELATIVE
The value being set is a relative change.
Definition: statistics.h:75
uint32_t flags
0 for absolute value, 1 for relative value; 2 to make persistent (see GNUNET_STATISTICS_SETFLAG_*).
Definition: statistics.h:102
int set
Is this value set? GNUNET_NO: value is n/a, GNUNET_YES: value is valid.

References ClientEntry::client, delta, find_stat_entry(), find_subsystem_entry(), GNUNET_STATISTICS_SetMessage::flags, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_SETFLAG_PERSISTENT, GNUNET_STATISTICS_SETFLAG_RELATIVE, GNUNET_STRINGS_buffer_tokenize(), GNUNET_YES, msg, name, StatsEntry::name, notify_change(), StatsEntry::persistent, service, StatsEntry::set, GNUNET_MessageHeader::size, size, SubsystemEntry::stat_head, SubsystemEntry::stat_tail, StatsEntry::subsystem, StatsEntry::uid, uidgen, value, and StatsEntry::value.

Referenced by inject_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_watch()

static int check_watch ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Check integrity of WATCH-message.

Parameters
clsthe struct ClientEntry *
messagethe actual message
Returns
GNUNET_OK if message is well-formed

Definition at line 705 of file gnunet-service-statistics.c.

706{
707 size_t size;
708 const char *service;
709 const char *name;
710
711 size = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
712 if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
713 size,
714 2,
715 &service,
716 &name))
717 {
718 GNUNET_break (0);
719 return GNUNET_SYSERR;
720 }
721 return GNUNET_OK;
722}

References GNUNET_break, GNUNET_OK, GNUNET_STRINGS_buffer_tokenize(), GNUNET_SYSERR, name, service, GNUNET_MessageHeader::size, and size.

Here is the call graph for this function:

◆ handle_watch()

static void handle_watch ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle WATCH-message.

Parameters
clsthe struct ClientEntry *
messagethe actual message

Definition at line 732 of file gnunet-service-statistics.c.

733{
734 struct ClientEntry *ce = cls;
735 const char *service;
736 const char *name;
737 uint16_t msize;
738 uint16_t size;
739 struct SubsystemEntry *se;
740 struct StatsEntry *pos;
741 struct WatchEntry *we;
742 size_t nlen;
743
744 if (NULL == nc)
745 {
747 return;
748 }
750 msize = ntohs (message->size);
751 size = msize - sizeof(struct GNUNET_MessageHeader);
753 GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
754 size,
755 2,
756 &service,
757 &name));
759 "Received request to watch statistic on `%s:%s'\n",
760 service,
761 name);
762 se = find_subsystem_entry (ce, service);
763 pos = find_stat_entry (se, name);
764 if (NULL == pos)
765 {
766 nlen = strlen (name) + 1;
767 pos = GNUNET_malloc (sizeof(struct StatsEntry) + nlen);
768 GNUNET_memcpy (&pos[1], name, nlen);
769 pos->name = (const char *) &pos[1];
770 pos->subsystem = se;
772 pos->uid = uidgen++;
773 pos->set = GNUNET_NO;
775 "New statistic on `%s:%s' with value %llu created.\n",
776 service,
777 name,
778 (unsigned long long) pos->value);
779 }
780 we = GNUNET_new (struct WatchEntry);
781 we->ce = ce;
783 we->wid = ce->max_wid++;
785 if (0 != pos->value)
786 notify_change (pos);
788}
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2483
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
uint32_t max_wid
Maximum watch ID used by this client so far.
struct WatchEntry * we_tail
Watch context for changes to this value, or NULL for none.

References WatchEntry::ce, ClientEntry::client, find_stat_entry(), find_subsystem_entry(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_SERVICE_client_mark_monitor(), GNUNET_STRINGS_buffer_tokenize(), WatchEntry::last_value_set, ClientEntry::max_wid, name, StatsEntry::name, nc, notify_change(), service, StatsEntry::set, GNUNET_MessageHeader::size, size, SubsystemEntry::stat_head, SubsystemEntry::stat_tail, StatsEntry::subsystem, StatsEntry::uid, uidgen, StatsEntry::value, StatsEntry::we_head, StatsEntry::we_tail, and WatchEntry::wid.

Here is the call graph for this function:

◆ handle_disconnect()

static void handle_disconnect ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle DISCONNECT-message.

Sync to disk and send back a GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM message.

Parameters
clsthe struct ClientEntry *
messagethe actual message

Definition at line 800 of file gnunet-service-statistics.c.

801{
802 struct ClientEntry *ce = cls;
803 struct GNUNET_MQ_Envelope *env;
805
807 GNUNET_MQ_send (ce->mq, env);
809}
#define GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM
Service confirms disconnect and that it is done processing all requests from the client.

References ClientEntry::client, env, GNUNET_MESSAGE_TYPE_STATISTICS_DISCONNECT_CONFIRM, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), ClientEntry::mq, and msg.

Here is the call graph for this function:

◆ do_shutdown()

static void do_shutdown ( )
static

Actually perform the shutdown.

Definition at line 816 of file gnunet-service-statistics.c.

817{
818 struct WatchEntry *we;
819 struct StatsEntry *pos;
820 struct SubsystemEntry *se;
821
822 if (NULL == nc)
823 return;
824 save ();
826 nc = NULL;
828 while (NULL != (se = sub_head))
829 {
831 while (NULL != (pos = se->stat_head))
832 {
834 while (NULL != (we = pos->we_head))
835 {
836 GNUNET_break (0);
838 GNUNET_free (we);
839 }
840 GNUNET_free (pos);
841 }
842 GNUNET_free (se);
843 }
844}
static void save()
Write persistent statistics to disk.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:138

References client_count, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_notification_context_destroy(), nc, save(), SubsystemEntry::stat_head, SubsystemEntry::stat_tail, sub_head, sub_tail, StatsEntry::we_head, and StatsEntry::we_tail.

Referenced by client_disconnect_cb(), and shutdown_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task run during shutdown.

Parameters
clsunused

Definition at line 853 of file gnunet-service-statistics.c.

854{
856 if (0 != client_count)
857 return;
858 do_shutdown ();
859}
static int in_shutdown
Set to GNUNET_YES if we are shutting down as soon as possible.
static void do_shutdown()
Actually perform the shutdown.

References client_count, do_shutdown(), GNUNET_YES, and in_shutdown.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_cls 
)
static

A client disconnected.

Remove all of its data structure entries.

Parameters
clsclosure, NULL
clientidentification of the client
app_clsthe struct ClientEntry *

Definition at line 870 of file gnunet-service-statistics.c.

873{
874 struct ClientEntry *ce = app_cls;
875 struct WatchEntry *we;
876 struct WatchEntry *wen;
877 struct StatsEntry *pos;
878 struct SubsystemEntry *se;
879
880 client_count--;
881 for (se = sub_head; NULL != se; se = se->next)
882 {
883 for (pos = se->stat_head; NULL != pos; pos = pos->next)
884 {
885 wen = pos->we_head;
886 while (NULL != (we = wen))
887 {
888 wen = we->next;
889 if (we->ce != ce)
890 continue;
892 GNUNET_free (we);
893 }
894 }
895 }
896 GNUNET_free (ce);
897 if ((0 == client_count) && (GNUNET_YES == in_shutdown))
898 do_shutdown ();
899}

References WatchEntry::ce, client_count, do_shutdown(), GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_YES, in_shutdown, WatchEntry::next, StatsEntry::next, SubsystemEntry::next, SubsystemEntry::stat_head, sub_head, StatsEntry::we_head, and StatsEntry::we_tail.

Here is the call graph for this function:

◆ inject_message()

static int inject_message ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

We've read a struct GNUNET_STATISTICS_SetMessage * from disk.

Check that it is well-formed, and if so pass it to the handler for set messages.

Parameters
clsNULL
messagethe message found on disk
Returns
GNUNET_OK on success, GNUNET_NO to stop further processing (no error) GNUNET_SYSERR to stop further processing with error

Definition at line 914 of file gnunet-service-statistics.c.

915{
916 uint16_t msize = ntohs (message->size);
917 const struct GNUNET_STATISTICS_SetMessage *sm;
918
919 sm = (const struct GNUNET_STATISTICS_SetMessage *) message;
920 if ((sizeof(struct GNUNET_STATISTICS_SetMessage) > msize) ||
921 (GNUNET_OK != check_set (NULL, sm)))
922 {
923 GNUNET_break (0);
924 return GNUNET_SYSERR;
925 }
926 handle_set (NULL, sm);
927 return GNUNET_OK;
928}
static void handle_set(void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
Handle SET-message.
static int check_set(void *cls, const struct GNUNET_STATISTICS_SetMessage *msg)
Check format of SET-message.

References check_set(), GNUNET_break, GNUNET_OK, GNUNET_SYSERR, handle_set(), and GNUNET_MessageHeader::size.

Referenced by load().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load()

static void load ( )
static

Load persistent values from disk.

Disk format is exactly the same format that we also use for setting the values over the network.

Definition at line 936 of file gnunet-service-statistics.c.

937{
938 char *fn;
939 struct GNUNET_BIO_ReadHandle *rh;
940 uint64_t fsize;
941 char *buf;
943
945 "STATISTICS",
946 "DATABASE",
947 &fn))
948 {
950 "STATISTICS",
951 "DATABASE");
952 return;
953 }
954 if ((GNUNET_OK !=
956 (0 == fsize))
957 {
958 GNUNET_free (fn);
959 return;
960 }
961 buf = GNUNET_malloc (fsize);
963 if (! rh)
964 {
965 GNUNET_free (buf);
966 GNUNET_free (fn);
967 return;
968 }
969 if (GNUNET_OK != GNUNET_BIO_read (rh, fn, buf, fsize))
970 {
973 GNUNET_free (buf);
974 GNUNET_free (fn);
975 return;
976 }
978 _ ("Loading %llu bytes of statistics from `%s'\n"),
979 (unsigned long long) fsize,
980 fn);
981 mst = GNUNET_MST_create (&inject_message, NULL);
983 GNUNET_OK ==
984 GNUNET_MST_from_buffer (mst, buf, (size_t) fsize, GNUNET_YES, GNUNET_NO));
985 GNUNET_MST_destroy (mst);
986 GNUNET_free (buf);
988 GNUNET_free (fn);
989}
static int inject_message(void *cls, const struct GNUNET_MessageHeader *message)
We've read a struct GNUNET_STATISTICS_SetMessage * from disk.
enum GNUNET_GenericReturnValue GNUNET_BIO_read(struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len)
Read some contents into a buffer.
Definition: bio.c:291
enum GNUNET_GenericReturnValue GNUNET_BIO_read_close(struct GNUNET_BIO_ReadHandle *h, char **emsg)
Close an open handle.
Definition: bio.c:162
struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open_file(const char *fn)
Open a file for reading.
Definition: bio.c:114
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:222
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:101
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
Handle for buffered reading.
Definition: bio.c:69
Handle to a message stream tokenizer.
Definition: mst.c:45

References _, cfg, GNUNET_BIO_read(), GNUNET_BIO_read_close(), GNUNET_BIO_read_open_file(), GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_DISK_file_size(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_MST_create(), GNUNET_MST_destroy(), GNUNET_MST_from_buffer(), GNUNET_NO, GNUNET_OK, GNUNET_YES, and inject_message().

Referenced by calculate_load(), GNUNET_LOAD_get_average(), GNUNET_LOAD_get_load(), GNUNET_LOAD_update(), GNUNET_LOAD_value_set_decline(), internal_update(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Process statistics requests.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

Definition at line 1000 of file gnunet-service-statistics.c.

1003{
1004 cfg = c;
1006 load ();
1008}
static void shutdown_task(void *cls)
Task run during shutdown.
static void load()
Load persistent values from disk.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:122
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1339

References cfg, GNUNET_notification_context_create(), GNUNET_SCHEDULER_add_shutdown(), load(), nc, and shutdown_task().

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

Variable Documentation

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 200 of file gnunet-service-statistics.c.

Referenced by load(), run(), and save().

◆ sub_head

struct SubsystemEntry* sub_head
static

Head of linked list of subsystems with active statistics.

Definition at line 205 of file gnunet-service-statistics.c.

Referenced by client_disconnect_cb(), do_shutdown(), find_subsystem_entry(), handle_get(), and save().

◆ sub_tail

struct SubsystemEntry* sub_tail
static

Tail of linked list of subsystems with active statistics.

Definition at line 210 of file gnunet-service-statistics.c.

Referenced by do_shutdown(), find_subsystem_entry(), and save().

◆ client_count

unsigned int client_count
static

Number of connected clients.

Definition at line 215 of file gnunet-service-statistics.c.

Referenced by client_connect_cb(), client_disconnect_cb(), do_shutdown(), and shutdown_task().

◆ nc

struct GNUNET_NotificationContext* nc
static

Our notification context.

Definition at line 220 of file gnunet-service-statistics.c.

Referenced by client_connect_cb(), do_shutdown(), handle_watch(), and run().

◆ uidgen

uint32_t uidgen
static

Counter used to generate unique values.

Definition at line 225 of file gnunet-service-statistics.c.

Referenced by handle_set(), and handle_watch().

◆ in_shutdown

int in_shutdown
static

Set to GNUNET_YES if we are shutting down as soon as possible.

Definition at line 230 of file gnunet-service-statistics.c.

Referenced by client_disconnect_cb(), and shutdown_task().