/** * Add value to the table. * * If it was already present, its lifetime is augmented by the aging delay. * * The key argument is freed immediately if there is a free routine for * keys and the key was present in the table. * * The previous value is freed and replaced by the new one if there is * an insertion conflict and the value pointers are different. */ void aging_insert(aging_table_t *ag, const void *key, void *value) { gboolean found; void *okey, *ovalue; time_t now = tm_time(); struct aging_value *aval; g_assert(ag->magic == AGING_MAGIC); found = g_hash_table_lookup_extended(ag->table, key, &okey, &ovalue); if (found) { aval = ovalue; g_assert(aval->key == okey); if (aval->key != key && ag->kvfree != NULL) { /* * We discard the new and keep the old key instead. * That way, we don't have to update the hash table. */ (*ag->kvfree)(deconstify_gpointer(key), aval->value); } g_assert(aval->cq_ev != NULL); /* * Value existed for this key, prolonge its life. */ aval->value = value; aval->ttl -= delta_time(now, aval->last_insert); aval->ttl += ag->delay; aval->ttl = MAX(aval->ttl, 1); aval->ttl = MIN(aval->ttl, INT_MAX / 1000); aval->last_insert = now; cq_resched(aval->cq_ev, 1000 * aval->ttl); } else { WALLOC(aval); aval->value = value; aval->key = deconstify_gpointer(key); aval->ttl = ag->delay; aval->ttl = MAX(aval->ttl, 1); aval->ttl = MIN(aval->ttl, INT_MAX / 1000); aval->last_insert = now; aval->ag = ag; aval->cq_ev = cq_insert(aging_cq, 1000 * aval->ttl, aging_expire, aval); gm_hash_table_insert_const(ag->table, key, aval); } }
/** * Adds the given node to the gui. */ void nodes_gui_add_node(gnet_node_info_t *n) { GtkCList *clist_nodes; const gchar *titles[c_gnet_num]; gchar proto_tmp[32]; gint row; g_assert(n != NULL); str_bprintf(proto_tmp, sizeof proto_tmp, "%d.%d", n->proto_major, n->proto_minor); titles[c_gnet_host] = host_addr_port_to_string(n->addr, n->port); titles[c_gnet_flags] = "..."; titles[c_gnet_user_agent] = n->vendor ? lazy_utf8_to_locale(n->vendor) : "..."; titles[c_gnet_loc] = iso3166_country_cc(n->country); titles[c_gnet_version] = proto_tmp; titles[c_gnet_connected] = "..."; titles[c_gnet_uptime] = "..."; titles[c_gnet_info] = "..."; clist_nodes = GTK_CLIST(gui_main_window_lookup("clist_nodes")); row = gtk_clist_append(clist_nodes, (gchar **) titles); /* override const */ gtk_clist_set_row_data(clist_nodes, row, deconstify_gpointer(nid_ref(n->node_id))); }
/** * Removes all references to the given node handle in the gui. */ void nodes_gui_remove_node(const struct nid *node_id) { GtkWidget *clist_nodes; gint row; clist_nodes = gui_main_window_lookup("clist_nodes"); /* * Make sure node is remove from the "changed" hash table so * we don't try an update. */ g_assert(NULL != hs_node_info_changed); g_assert(NULL != hs_node_flags_changed); remove_item(hs_node_info_changed, node_id); remove_item(hs_node_flags_changed, node_id); row = gtk_clist_find_row_from_data(GTK_CLIST(clist_nodes), deconstify_gpointer(node_id)); if (row != -1) { gtk_clist_remove(GTK_CLIST(clist_nodes), row); nid_unref(node_id); } else { g_warning("%s(): no matching row found", G_STRFUNC); } }
static inline void nodes_gui_reverse_lookup_selected_helper(GtkTreeModel *model, GtkTreePath *unused_path, GtkTreeIter *iter, gpointer unused_data) { struct node_data *data; gnet_node_info_t info; (void) unused_path; (void) unused_data; gtk_tree_model_get(model, iter, 0, &data, (-1)); g_assert(NULL != find_node(data->node_id)); if (hset_contains(ht_pending_lookups, data->node_id)) return; guc_node_fill_info(data->node_id, &info); g_assert(data->node_id == info.node_id); if (!info.is_pseudo) { const struct nid *key = nid_ref(data->node_id); WFREE_NULL(data->host, data->host_size); data->host_size = w_concat_strings(&data->host, _("Reverse lookup in progress..."), " (", host_addr_port_to_string(info.addr, info.port), ")", (void *) 0); hset_insert(ht_pending_lookups, key); adns_reverse_lookup(info.addr, host_lookup_callback, deconstify_gpointer(nid_ref(key))); } guc_node_clear_info(&info); }
void upload_stats_gui_add(struct ul_stats *us) { GtkCList *clist = clist_ul_stats(); const gchar *rowdata[c_us_num]; enum c_us i; int row; char size_tmp[16]; char attempts_tmp[16]; char complete_tmp[16]; char norm_tmp[16]; char rtime_tmp[64]; char dtime_tmp[64]; g_strlcpy(size_tmp, short_size(us->size, show_metric_units()), sizeof size_tmp); gm_snprintf(attempts_tmp, sizeof attempts_tmp, "%u", us->attempts); gm_snprintf(complete_tmp, sizeof complete_tmp, "%u", us->complete); gm_snprintf(norm_tmp, sizeof norm_tmp, "%.3f", us->norm); if (us->rtime) { timestamp_to_string_buf(us->rtime, rtime_tmp, sizeof rtime_tmp); } else { rtime_tmp[0] = '\0'; } if (us->dtime) { timestamp_to_string_buf(us->dtime, dtime_tmp, sizeof dtime_tmp); } else { dtime_tmp[0] = '\0'; } for (i = 0; i < c_us_num; i++) switch (i) { case c_us_filename: rowdata[i] = lazy_utf8_to_ui_string(us->filename); break; case c_us_size: rowdata[i] = size_tmp; break; case c_us_attempts: rowdata[i] = attempts_tmp; break; case c_us_complete: rowdata[i] = complete_tmp; break; case c_us_norm: rowdata[i] = norm_tmp; break; case c_us_rtime: rowdata[i] = rtime_tmp; break; case c_us_dtime: rowdata[i] = dtime_tmp; break; case c_us_num: g_assert_not_reached(); } row = gtk_clist_append(clist, deconstify_gpointer(rowdata)); g_return_if_fail(row >= 0); ul_stats_set_row(us, row); gtk_clist_set_row_data_full(clist, row, us, on_clist_ul_stats_row_removed); /* FIXME: should use auto_sort? */ if (0 == clist->freeze_count) { gtk_clist_sort(clist); clist_sync_rows(clist, on_clist_ul_stats_row_moved); } }
static inline void nodes_gui_remove_selected_helper(GtkTreeModel *model, GtkTreePath *unused_path, GtkTreeIter *iter, gpointer list_ptr) { GSList **list = list_ptr; const struct node_data *data; (void) unused_path; gtk_tree_model_get(model, iter, 0, &data, (-1)); *list = g_slist_prepend(*list, deconstify_gpointer(data->node_id)); }
/** * Update the row with the given nodeinfo. If row is -1 the row number * is determined by the node_id contained in the gnet_node_info_t. */ static void nodes_gui_update_node_info(gnet_node_info_t *n, gint row) { GtkCList *clist = GTK_CLIST(gui_main_window_lookup("clist_nodes")); g_assert(n != NULL); if (row == -1) { row = gtk_clist_find_row_from_data(clist, deconstify_gpointer(n->node_id)); } if (row != -1) { gchar ver_buf[64]; gnet_node_status_t status; time_t now = tm_time(); if (guc_node_get_status(n->node_id, &status)) { gtk_clist_set_text(clist, row, c_gnet_user_agent, n->vendor ? lazy_utf8_to_locale(n->vendor) : "..."); gtk_clist_set_text(clist, row, c_gnet_loc, deconstify_gchar(iso3166_country_cc(n->country))); str_bprintf(ver_buf, sizeof ver_buf, "%d.%d", n->proto_major, n->proto_minor); gtk_clist_set_text(clist, row, c_gnet_version, ver_buf); if (status.status == GTA_NODE_CONNECTED) gtk_clist_set_text(clist, row, c_gnet_connected, short_uptime(delta_time(now, status.connect_date))); if (status.up_date) gtk_clist_set_text(clist, row, c_gnet_uptime, status.up_date ? short_uptime(delta_time(now, status.up_date)) : "..."); gtk_clist_set_text(clist, row, c_gnet_info, nodes_gui_common_status_str(&status)); } } else { g_warning("%s(): no matching row found", G_STRFUNC); } }
/** * Updates the flags for given node and row. */ static void nodes_gui_update_node_flags(const struct nid *node_id, gnet_node_flags_t *flags, gint row) { GtkCList *clist = GTK_CLIST(gui_main_window_lookup("clist_nodes")); if (row == -1) row = gtk_clist_find_row_from_data(clist, deconstify_gpointer(node_id)); if (row != -1) { gtk_clist_set_text(clist, row, c_gnet_flags, guc_node_flags_to_string(flags)); if (NODE_P_LEAF == flags->peermode || NODE_P_NORMAL == flags->peermode) { GdkColor *color = &(gtk_widget_get_style(GTK_WIDGET(clist)) ->fg[GTK_STATE_INSENSITIVE]); gtk_clist_set_foreground(clist, row, color); } } else { g_warning("%s(): no matching row found", G_STRFUNC); } }
static void dbg_property_show_list(const GSList *props) { GtkCList *clist; const GSList *sl; clist = GTK_CLIST(gui_dlg_prefs_lookup("clist_dbg_property")); gtk_clist_freeze(clist); gtk_clist_clear(clist); for (sl = props; NULL != sl; sl = g_slist_next(sl)) { static const gchar * const titles[num_dbg_cols] = { "", "", "", "", }; property_t prop = GPOINTER_TO_UINT(sl->data); gint row; row = gtk_clist_append(clist, deconstify_gpointer(titles)); dbg_property_set_row(clist, row, prop); } gtk_clist_sort(clist); gtk_clist_columns_autosize(clist); gtk_clist_thaw(clist); }
/** * Writes the browse host data of the context ``ctx'' to the buffer * ``dest''. This must be called multiple times to retrieve the complete * data until zero is returned i.e., the end of file is reached. * * This routine deals with query hit data generation. * * @param ctx an initialized browse host context. * @param dest the destination buffer. * @param size the amount of bytes ``dest'' can hold. * * @return -1 on failure, zero at the end-of-file condition or if size * was zero. On success, the amount of bytes copied to ``dest'' * is returned. */ static ssize_t browse_host_read_qhits(struct special_upload *ctx, gpointer const dest, size_t size) { struct browse_host_upload *bh = cast_to_browse_host_upload(ctx); size_t remain = size; char *p = dest; /* * If we have no hit pending that we can send, build some more. */ if (NULL == bh->hits) { GSList *files = NULL; int i; for (i = 0; i < BH_SCAN_AHEAD; i++) { const shared_file_t *sf; do { /* Skip holes in indices */ bh->file_index++; sf = shared_file_sorted(bh->file_index); } while (NULL == sf && bh->file_index <= shared_files_scanned()); if (SHARE_REBUILDING == sf || NULL == sf) break; files = g_slist_prepend(files, deconstify_gpointer(sf)); } if (NULL == files) /* Did not find any more file to include */ return 0; /* We're done */ /* * Now build the query hits containing the files we selected. */ files = g_slist_reverse(files); /* Preserve order */ qhit_build_results(files, i, BH_MAX_QHIT_SIZE, browse_host_record_hit, bh, &blank_guid, FALSE, &zero_array); g_assert(bh->hits != NULL); /* At least 1 hit enqueued */ bh->hits = g_slist_reverse(bh->hits); /* Preserve order */ gm_slist_free_null(&files); } /* * Read each query hit in turn. */ while (remain > 0 && NULL != bh->hits) { pmsg_t *mb = bh->hits->data; int r; r = pmsg_read(mb, p, remain); p += r; remain -= r; if (r == 0 || 0 == pmsg_size(mb)) { bh->hits = g_slist_remove(bh->hits, mb); pmsg_free(mb); } } return size - remain; }
/** * Locate statistics structure for the file. * * If a SHA1 is given, we search by SHA1. Otherwise we search by (name, size) * and if the record is missing the SHA1, probably because it was not * available at the time of insertion, then it is added to the structure * and recorded as such. */ static struct ul_stats * upload_stats_find(const struct sha1 *sha1, const char *pathname, guint64 size) { struct ul_stats *s = NULL; if (upload_stats_list) { static const struct ul_stats zero_stats; struct ul_stats key; gconstpointer orig_key; g_assert(upload_stats_by_sha1); if (sha1) { s = g_hash_table_lookup(upload_stats_by_sha1, sha1); if (s) goto done; /* Found it by SHA1 */ } key = zero_stats; key.pathname = atom_str_get(pathname); key.size = size; if (hash_list_find(upload_stats_list, &key, &orig_key)) s = deconstify_gpointer(orig_key); atom_str_free_null(&key.pathname); if (s && sha1) { /* Was missing from the by-SHA1 table */ if (NULL == s->sha1) { /* SHA1 was unknown */ s->sha1 = atom_sha1_get(sha1); } else { /* SHA1 changed, file was modified */ struct ul_stats *old = g_hash_table_lookup(upload_stats_by_sha1, s->sha1); g_assert(old == s); /* Must be the same filename entry */ g_hash_table_remove(upload_stats_by_sha1, s->sha1); atom_sha1_free(s->sha1); s->sha1 = atom_sha1_get(sha1); } gm_hash_table_insert_const(upload_stats_by_sha1, s->sha1, s); } } done: /* We guarantee the SHA1 is present in the record if known */ g_assert(!(s && sha1) || s->sha1); /* Postcondition: if we return something, it must be "correct" */ if (s != NULL) { g_assert(atom_is_str(s->pathname)); g_assert(atom_is_str(s->filename)); g_assert(s->norm >= 0.0); } return s; }