Beispiel #1
0
/**
 * Unregister callbacks in the backend and clean up.
 */
void
nodes_gui_shutdown(void)
{
	tree_view_motion_clear_callback(&tvm_nodes);
	tree_view_save_widths(treeview_nodes, PROP_NODES_COL_WIDTHS);
	tree_view_save_visibility(treeview_nodes, PROP_NODES_COL_VISIBLE);

    guc_node_remove_node_added_listener(nodes_gui_node_added);
    guc_node_remove_node_removed_listener(nodes_gui_node_removed);
    guc_node_remove_node_info_changed_listener(nodes_gui_node_info_changed);
    guc_node_remove_node_flags_changed_listener(nodes_gui_node_flags_changed);

	gtk_list_store_clear(nodes_model);
	g_object_unref(G_OBJECT(nodes_model));
	nodes_model = NULL;
	gtk_tree_view_set_model(treeview_nodes, NULL);

	htable_foreach(nodes_handles, free_node_data, NULL);
	htable_free_null(&nodes_handles);

	hset_foreach(ht_node_info_changed, free_node_id, NULL);
    hset_free_null(&ht_node_info_changed);

	hset_foreach(ht_node_flags_changed, free_node_id, NULL);
    hset_free_null(&ht_node_flags_changed);

	hset_foreach(ht_pending_lookups, free_node_id, NULL);
    hset_free_null(&ht_pending_lookups);
}
/**
 * Destroys the UDP TX scheduler, which must no longer be attached to anything.
 */
void
udp_sched_free(udp_sched_t *us)
{
	udp_sched_check(us);
	unsigned i;

	/*
	 * TX stacks are asynchronously collected, so we need to force collection
	 * now to make sure nobody references us any longer.
	 */

	tx_collect();

	g_assert(0 == hash_list_length(us->stacks));

	for (i = 0; i < N_ITEMS(us->lifo); i++) {
		udp_sched_drop_all(us, &us->lifo[i]);
	}
	udp_sched_tx_release(us);
	udp_sched_seen_clear(us);
	pool_free(us->txpool);
	hset_free_null(&us->seen);
	hash_list_free(&us->stacks);
	udp_sched_clear_sockets(us);

	us->magic = 0;
	WFREE(us);
}
Beispiel #3
0
/**
 * Free queue and all queued searches.
 */
void
sq_free(squeue_t *sq)
{
	g_assert(sq);

	sq_clear(sq);
	hset_free_null(&sq->handles);
	WFREE(sq);
}
Beispiel #4
0
/**
 * Called when servent shuts down.
 */
void
gwc_close(void)
{
    int i;

    gwc_store();
    hset_free_null(&gwc_known_url);
    hset_foreach(gwc_failed_url, free_failed_url, NULL);
    hset_free_null(&gwc_failed_url);

    for (i = 0; i < MAX_GWC_URLS; i++) {
        const char *url = gwc_url[i].url;
        if (url == NULL)
            continue;
        atom_str_free(url);
    }

    gwc_clear_current_url(FALSE);
}
Beispiel #5
0
/**
 * Unregister callbacks in the backend and clean up.
 */
G_GNUC_COLD void
nodes_gui_shutdown(void)
{
	GtkCList *clist;

	clist = GTK_CLIST(gui_main_window_lookup("clist_nodes"));
	clist_save_visibility(clist, PROP_NODES_COL_VISIBLE);
	clist_save_widths(clist, PROP_NODES_COL_WIDTHS);

    guc_node_remove_node_added_listener(nodes_gui_node_added);
    guc_node_remove_node_removed_listener(nodes_gui_node_removed);
    guc_node_remove_node_info_changed_listener(nodes_gui_node_info_changed);
    guc_node_remove_node_flags_changed_listener(nodes_gui_node_flags_changed);

	hset_foreach_remove(hs_node_info_changed, free_node_id, NULL);
    hset_free_null(&hs_node_info_changed);

	hset_foreach_remove(hs_node_flags_changed, free_node_id, NULL);
    hset_free_null(&hs_node_flags_changed);

	nodes_gui_remove_all_nodes();
}
Beispiel #6
0
static GSList *
resolve_hostname(const char *host, enum net_type net)
#ifdef HAS_GETADDRINFO
{
	static const struct addrinfo zero_hints;
	struct addrinfo hints, *ai, *ai0 = NULL;
	hset_t *hs;
	GSList *sl_addr;
	int error;

	g_assert(host);
	
	hints = zero_hints;
	hints.ai_family = net_type_to_pf(net);

	error = getaddrinfo(host, NULL, &hints, &ai0);
	if (error) {
		g_message("getaddrinfo() failed for \"%s\": %s",
				host, gai_strerror(error));
		return NULL;
	}

	sl_addr = NULL;
	hs = hset_create_any(host_addr_hash_func, NULL, host_addr_eq_func);
	for (ai = ai0; ai; ai = ai->ai_next) {
		host_addr_t addr;

		if (!ai->ai_addr)
			continue;

		addr = addrinfo_to_addr(ai);

		if (is_host_addr(addr) && !hset_contains(hs, &addr)) {
			host_addr_t *addr_copy;

			addr_copy = wcopy(&addr, sizeof addr);
			sl_addr = g_slist_prepend(sl_addr, addr_copy);
			hset_insert(hs, addr_copy);
		}
	}
	hset_free_null(&hs);

	if (ai0)
		freeaddrinfo(ai0);

	return g_slist_reverse(sl_addr);
}
Beispiel #7
0
/**
 * Free the callout queue and all contained event objects.
 */
static void
cq_free(cqueue_t *cq)
{
	cevent_t *ev;
	cevent_t *ev_next;
	int i;
	struct chash *ch;

	cqueue_check(cq);

	if (cq->cq_current != NULL) {
		s_carp("%s(): %squeue \"%s\" still within cq_clock()", G_STRFUNC,
			CSUBQUEUE_MAGIC == cq->cq_magic ? "sub" : "", cq->cq_name);
	}

	mutex_lock(&cq->cq_lock);

	for (ch = cq->cq_hash, i = 0; i < HASH_SIZE; i++, ch++) {
		for (ev = ch->ch_head; ev; ev = ev_next) {
			ev_next = ev->ce_bnext;
			ev->ce_magic = 0;
			WFREE(ev);
		}
	}

	if (cq->cq_periodic) {
		hset_foreach_remove(cq->cq_periodic, cq_free_periodic, NULL);
		hset_free_null(&cq->cq_periodic);
	}

	if (cq->cq_idle) {
		hset_foreach_remove(cq->cq_idle, cq_free_idle, cq);
		hset_free_null(&cq->cq_idle);
	}

	XFREE_NULL(cq->cq_hash);
	atom_str_free_null(&cq->cq_name);

	/*
	 * Unlocking the cq->cq_lock mutex (taken above) prevents a loud warning in
	 * mutex_destroy() in case the mutex was already locked by our thread,
	 * meaning we were already in cq_clock().  In that situation however,
	 * we already warned upon entry, and therefore there is no need for a
	 * second warning.
	 *
	 * If the mutex was not taken and someone else attempts to grab it at that
	 * stage, there will be a slight window which fortunately will be loudly
	 * detected by mutex_destroy(), as a case of a mutex being destroyed
	 * whilst owned by another thread.
	 *
	 * No valid application code should attempt to sneak in at this stage to
	 * grab that mutex anyway, so our logic is safe and we will be copiously
	 * warned if something unexpected happens.
	 *		--RAM, 2012-12-04.
	 */

	mutex_unlock(&cq->cq_lock);
	mutex_destroy(&cq->cq_lock);
	mutex_destroy(&cq->cq_idle_lock);

	/*
	 * If freeing a sub-queue, the object is a bit larger than a queue,
	 * and we have more cleanup to do...
	 */

	if (CSUBQUEUE_MAGIC == cq->cq_magic) {
		cq_subqueue_free((struct csubqueue *) cq);
	} else {
		cq->cq_magic = 0;
		WFREE(cq);
	}
}
Beispiel #8
0
/**
 * Recreate keyinfo data from persisted information.
 */
static G_GNUC_COLD void
keys_init_keyinfo(void)
{
	struct keys_create_context ctx;

	if (GNET_PROPERTY(dht_keys_debug)) {
		size_t count = dbmw_count(db_keydata);
		g_debug("DHT KEYS scanning %u persisted key%s",
			(unsigned) count, plural(count));
	}

	ctx.our_kuid = get_our_kuid();
	ctx.dbkeys = hset_create(HASH_KEY_FIXED, sizeof(uint64));

	dbmw_foreach_remove(db_keydata, reload_ki, &ctx);

	if (GNET_PROPERTY(dht_keys_debug)) {
		size_t count = dbmw_count(db_keydata);
		g_debug("DHT KEYS kept %u key%s, now loading associated values",
			(unsigned) count, plural(count));
	}

	/*
	 * FIXME:
	 * Unfortunately, we have to reset the keydata database for each of
	 * the keys we're going to recreate, because the logic adding values
	 * back to the key will fill each of the keydata appropriately, and it
	 * expects the amount of values in the keyinfo and the keydata to match.
	 *
	 * Therefore, we need to rename the old keydata database, open a new one,
	 * write empty keydata values in it, then discard the old keydata if
	 * everything goes well.  In case of a crash in the middle of the
	 * restoration, we'll be able to recover by opening the old keydata first
	 * if it exists.
	 *
	 * It is far from critical though: if we reset the keydata database and
	 * we crash in the middle of the restore, then we'll lose all the persisted
	 * keys and values and will simply restart with an empty storage.
	 *
	 * Given the contorsions needed to fix that, and the little value for
	 * the user, just leaving a FIXME note.
	 *		--RAM, 2012-11-17
	 */

	hikset_foreach(keys, keys_reset_keydata, NULL);
	values_init_data(ctx.dbkeys);

	hset_foreach(ctx.dbkeys, keys_free_dbkey, NULL);
	hset_free_null(&ctx.dbkeys);

	hikset_foreach_remove(keys, keys_discard_if_empty, NULL);
	dbmw_foreach_remove(db_keydata, keys_delete_if_empty, NULL);
	dbstore_compact(db_keydata);

	g_soft_assert_log(hikset_count(keys) == dbmw_count(db_keydata),
		"keys reloaded: %zu, key data persisted: %zu",
		hikset_count(keys), dbmw_count(db_keydata));

	if (GNET_PROPERTY(dht_keys_debug)) {
		g_debug("DHT KEYS reloaded %zu key%s",
			hikset_count(keys), plural(hikset_count(keys)));
	}

	gnet_stats_set_general(GNR_DHT_KEYS_HELD, hikset_count(keys));
}
Beispiel #9
0
/**
 * Extended XML formatting of a tree.
 *
 * Namespaces, if any, are automatically assigned a prefix, whose format
 * is "ns%u", the counter being incremented from 0.
 *
 * Users can supply a vector mapping namespaces to prefixes, so that they
 * can force specific prefixes for a given well-known namespace.
 *
 * If there is a default namespace, all the tags belonging to that namespace
 * are emitted without any prefix.
 *
 * The output stream must be explicitly closed by the user upon return.
 *
 * Options can be supplied to tune the output:
 *
 * - XFMT_O_SKIP_BLANKS will skip pure white space nodes.
 * - XFMT_O_COLLAPSE_BLANKS will replace consecutive blanks with 1 space
 * - XFMT_O_NO_INDENT requests that no indentation of the tree be made.
 * - XFMT_O_PROLOGUE emits a leading <?xml?> prologue.
 * - XFMT_O_FORCE_10 force generation of XML 1.0
 * - XFMT_O_SINGLE_LINE emits XML as one big line (implies XFMT_O_NO_INDENT).
 *
 * @param root			the root of the tree to dump
 * @param os			the output stream where tree is dumped
 * @param options		formatting options, as documented above
 * @param pvec			a vector of prefixes to be used for namespaces
 * @param pvcnt			amount of entries in vector
 * @param default_ns	default namespace to install at root element
 *
 * @return TRUE on success.
 */
bool
xfmt_tree_extended(const xnode_t *root, ostream_t *os, uint32 options,
                   const struct xfmt_prefix *pvec, size_t pvcnt, const char *default_ns)
{
    struct xfmt_pass1 xp1;
    struct xfmt_pass2 xp2;
    struct xfmt_invert_ctx ictx;
    const char *dflt_ns;

    g_assert(root != NULL);
    g_assert(os != NULL);

    if (options & XFMT_O_COLLAPSE_BLANKS) {
        /* FIXME */
        g_carp("XFMT_O_COLLAPSE_BLANKS not supported yet");
        stacktrace_where_print(stderr);
    }

    if (options & XFMT_O_SINGLE_LINE)
        options |= XFMT_O_NO_INDENT;

    /*
     * First pass: look at namespaces and construct a table recording the
     * earliest tree depth at which a namespace is used.
     */

    ZERO(&xp1);
    xp1.uri2node = htable_create(HASH_KEY_STRING, 0);
    xp1.uri2prefix = nv_table_make(FALSE);

    if (default_ns != NULL)
        xp1.attr_uris = hset_create(HASH_KEY_STRING, 0);

    htable_insert_const(xp1.uri2node, VXS_XML_URI, root);

    xnode_tree_enter_leave(deconstify_pointer(root),
                           xfmt_handle_pass1_enter, xfmt_handle_pass1_leave, &xp1);

    g_assert(0 == xp1.depth);		/* Sound traversal */

    /*
     * If there was a default namespace, make sure it is used in the tree.
     * Otherwise, discard it.
     */

    if (default_ns != NULL) {
        if (NULL == htable_lookup(xp1.uri2node, default_ns)) {
            g_carp("XFMT default namespace '%s' is not needed", default_ns);
            dflt_ns = NULL;
        } else {
            dflt_ns = default_ns;
        }
    } else {
        dflt_ns = NULL;
    }

    /*
     * Prepare context for second pass.
     */

    ZERO(&xp2);
    xp2.node2uri = htable_create(HASH_KEY_SELF, 0);
    xp2.os = os;
    xp2.options = options;
    xp2.default_ns = dflt_ns;
    xp2.attr_uris = xp1.attr_uris;
    xp2.uri2prefix = xp1.uri2prefix;
    xp2.uris = symtab_make();
    xp2.prefixes = symtab_make();
    xp2.depth = 0;
    xp2.pcount = 0;
    xp2.last_was_nl = TRUE;

    /*
     * Iterate over the hash table we've built to create a table indexed
     * by tree node and listing the namespaces to declare for that node.
     */

    ictx.uri2node = xp1.uri2node;
    ictx.node2uri = xp2.node2uri;

    htable_foreach(xp1.uri2node, xfmt_invert_uri_kv, &ictx);
    htable_free_null(&xp1.uri2node);

    /*
     * Emit prologue if requested.
     */

    if (options & XFMT_O_PROLOGUE) {
        if (options & XFMT_O_FORCE_10) {
            ostream_write(os, XFMT_DECL_10, CONST_STRLEN(XFMT_DECL_10));
        } else {
            ostream_write(os, XFMT_DECL, CONST_STRLEN(XFMT_DECL));
        }
        if (!(options & XFMT_O_SINGLE_LINE)) {
            ostream_putc(os, '\n');
        }
    }

    xfmt_prefix_declare(&xp2, VXS_XML_URI, VXS_XML);

    /*
     * Prepare user-defined URI -> prefix mappings.
     */

    if (pvcnt != 0) {
        size_t i;

        for (i = 0; i < pvcnt; i++) {
            const struct xfmt_prefix *p = &pvec[i];

            xfmt_prefix_declare(&xp2, p->uri, p->prefix);
        }
    }

    /*
     * Second pass: generation.
     */

    xnode_tree_enter_leave(deconstify_pointer(root),
                           xfmt_handle_pass2_enter, xfmt_handle_pass2_leave, &xp2);

    g_assert(0 == xp2.depth);		/* Sound traversal */

    /*
     * Done, cleanup.
     */

    nv_table_free_null(&xp2.uri2prefix);
    symtab_free_null(&xp2.prefixes);
    symtab_free_null(&xp2.uris);
    htable_free_null(&xp2.node2uri);
    hset_free_null(&xp2.attr_uris);

    return !ostream_has_ioerr(os);
}