/** * @returns the size of the global hsep table */ int hsep_get_table_size(void) { hsep_triple hsep_table[G_N_ELEMENTS(hsep_global_table)]; hsep_get_global_table(hsep_table, G_N_ELEMENTS(hsep_table)); return G_N_ELEMENTS(hsep_table); }
/** * @returns a static string of the cell contents of the given row and column. * * @attention * NB: The static buffers for each column are disjunct. */ const char * hsep_get_static_str(int row, int column) { const char *ret = NULL; hsep_triple hsep_table[G_N_ELEMENTS(hsep_global_table)]; hsep_triple other[1]; uint64 v; hsep_get_global_table(hsep_table, G_N_ELEMENTS(hsep_table)); hsep_get_non_hsep_triple(other); switch (column) { case HSEP_IDX_NODES: { static char buf[UINT64_DEC_BUFLEN]; v = hsep_table[row][HSEP_IDX_NODES] + other[0][HSEP_IDX_NODES]; uint64_to_string_buf(v, buf, sizeof buf); ret = buf; } break; case HSEP_IDX_FILES: { static char buf[UINT64_DEC_BUFLEN]; v = hsep_table[row][HSEP_IDX_FILES] + other[0][HSEP_IDX_FILES]; uint64_to_string_buf(v, buf, sizeof buf); ret = buf; } break; case HSEP_IDX_KIB: { static char buf[UINT64_DEC_BUFLEN]; /* Make a copy because concurrent usage of short_kb_size() * could be hard to discover. */ v = hsep_table[row][HSEP_IDX_KIB] + other[0][HSEP_IDX_KIB]; g_strlcpy(buf, short_kb_size(v, GNET_PROPERTY(display_metric_units)), sizeof buf); ret = buf; } break; } g_assert(ret != NULL); return ret; }
void hsep_add_global_table_listener(GCallback cb, frequency_t t, uint32 interval) { hsep_triple table[G_N_ELEMENTS(hsep_global_table)]; hsep_global_listener_t func = (hsep_global_listener_t) cb; /* add callback to the event subscriber list */ event_add_subscriber(hsep_global_table_changed_event, cb, t, interval); /* * Fire up the first event to the specified callback. We do it * manually, because we don't want to fire all listeners, but * just the newly added one, and we want it independent of the * given callback call constraints. */ hsep_get_global_table(table, G_N_ELEMENTS(table)); func(table, G_N_ELEMENTS(table)); }
static void hsep_fire_global_table_changed(time_t now) { /* store global table change time */ hsep_last_global_table_change = now; /* do nothing if we don't have any listeners */ if (event_subscriber_active(hsep_global_table_changed_event)) { hsep_triple table[N_ITEMS(hsep_global_table)]; /* * Make a copy of the global HSEP table and give that * copy and the number of included triples to the * listeners. */ hsep_get_global_table(table, N_ITEMS(table)); event_trigger(hsep_global_table_changed_event, T_NORMAL(hsep_global_listener_t, (table, N_ITEMS(table)))); } }
/** * Displays horizon size information. */ enum shell_reply shell_exec_horizon(struct gnutella_shell *sh, int argc, const char *argv[]) { const char *all; const option_t options[] = { { "a", &all }, }; char buf[200]; hsep_triple globaltable[HSEP_N_MAX + 1]; hsep_triple non_hsep[1]; int parsed; unsigned num_hsep, num_total; shell_check(sh); g_assert(argv); g_assert(argc > 0); parsed = shell_options_parse(sh, argv, options, G_N_ELEMENTS(options)); if (parsed < 0) return REPLY_ERROR; shell_write(sh, "100~\n"); hsep_get_global_table(globaltable, G_N_ELEMENTS(globaltable)); hsep_get_non_hsep_triple(non_hsep); num_hsep = globaltable[1][HSEP_IDX_NODES]; num_total = globaltable[1][HSEP_IDX_NODES] + non_hsep[0][HSEP_IDX_NODES]; str_bprintf(buf, sizeof buf, _("Total horizon size (%u/%u nodes support HSEP):"), num_hsep, num_total); shell_write(sh, buf); shell_write(sh, "\n\n"); print_hsep_table(sh, globaltable, HSEP_N_MAX, non_hsep); if (all) { const pslist_t *sl; hsep_triple table[HSEP_N_MAX + 1]; PSLIST_FOREACH(node_all_gnet_nodes(), sl) { const gnutella_node_t *n = sl->data; if ((!NODE_IS_ESTABLISHED(n)) || !(n->attrs & NODE_A_CAN_HSEP)) continue; shell_write(sh, "\n"); str_bprintf(buf, sizeof buf, _("Horizon size via HSEP node %s (%s):"), node_addr(n), node_peermode_to_string(n->peermode)); shell_write(sh, buf); shell_write(sh, "\n\n"); hsep_get_connection_table(n, table, G_N_ELEMENTS(table)); print_hsep_table(sh, table, NODE_IS_LEAF(n) ? 1 : HSEP_N_MAX, NULL); } } shell_write(sh, ".\n"); return REPLY_READY; }