/** * 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; }
/** * 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; }
/** * 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]; } }