Beispiel #1
0
/**
 * DBMW foreach iterator to remove old entries.
 * @return  TRUE if entry must be deleted.
 */
static gboolean
prune_old(gpointer key, gpointer value, size_t u_len, gpointer u_data)
{
    const kuid_t *id = key;
    const struct lifedata *ld = value;
    time_delta_t d;
    gboolean expired;
    double p;

    (void) u_len;
    (void) u_data;

    d = delta_time(tm_time(), ld->last_seen);

    if (d <= STABLE_EXPIRE) {
        expired = FALSE;
        p = 1.0;
    } else {
        p = stable_still_alive_probability(ld->first_seen, ld->last_seen);
        expired = p < STABLE_PROBA;
    }

    if (GNET_PROPERTY(dht_stable_debug) > 4) {
        g_debug("DHT STABLE node %s life=%s last_seen=%s, p=%.2f%%%s",
                kuid_to_hex_string(id),
                compact_time(delta_time(ld->last_seen, ld->first_seen)),
                compact_time2(d), p * 100.0,
                expired ? " [EXPIRED]" : "");
    }

    return expired;
}
Beispiel #2
0
/**
 * DBMW foreach iterator to remove old entries.
 * @return TRUE if entry must be deleted.
 */
static bool
guid_prune_old_entries(void *key, void *value, size_t u_len, void *u_data)
{
	const guid_t *guid = key;
	const struct guiddata *gd = value;
	time_delta_t d;
	double p = 0.0;
	bool expired;

	(void) u_len;
	(void) u_data;

	/*
	 * We reuse the statistical probability model of DHT nodes to project
	 * whether it makes sense to keep an entry.
	 */

	d = delta_time(tm_time(), gd->last_time);
	if (gd->create_time == gd->last_time) {
		expired = d > GUID_STABLE_LIFETIME;
	} else {
		p = stable_still_alive_probability(gd->create_time, gd->last_time);
		expired = p < GUID_STABLE_PROBA;
	}

	if (GNET_PROPERTY(guid_debug) > 5) {
		g_debug("GUID cached %s life=%s last_seen=%s, p=%.2f%%%s",
			guid_hex_str(guid),
			compact_time(delta_time(gd->last_time, gd->create_time)),
			compact_time2(d), p * 100.0,
			expired ? " [EXPIRED]" : "");
	}

	return expired;
}
Beispiel #3
0
/**
 * Convenience routine to compute theoretical probability of presence for
 * a node, adjusted down when RPC timeouts occurred recently.
 */
double
knode_still_alive_probability(const knode_t *kn)
{
	double p;
	static bool inited;
	static double decimation[KNODE_MAX_TIMEOUTS];

	knode_check(kn);

	if (G_UNLIKELY(!inited)) {
		size_t i;

		for (i = 0; i < G_N_ELEMENTS(decimation); i++) {
			decimation[i] = pow(KNODE_ALIVE_DECIMATION, (double) (i + 1));
		}

		inited = TRUE;
	}

	p = stable_still_alive_probability(kn->first_seen, kn->last_seen);

	/*
	 * If RPC timeouts occurred, the theoretical probability is further
	 * adjusted down.  The decimation is arbitrary of course, but the
	 * rationale is that an RPC timeout somehow is an information that the
	 * node may not be alive.  Of course, it could be an UDP drop, an IP
	 * drop somewhere, but this is why we don't use 0.0 as the decimation!
	 */

	if (0 == kn->rpc_timeouts)
		return p;
	else {
		size_t i = MIN(kn->rpc_timeouts, G_N_ELEMENTS(decimation)) - 1;
		return p * decimation[i];
	}
}