Ejemplo n.º 1
0
/**
 * Fill supplied value vector with all the DHT values we have under the key.
 *
 * This is an internal call, not the result of an external query, so no
 * statistics are updated.
 *
 * @param id				the primary key of the value
 * @param valvec			value vector where results are stored
 * @param valcnt			size of value vector
 *
 * @return amount of values filled into valvec.  The values are dynamically
 * created and must be freed by caller through dht_value_free().
 */
int
keys_get_all(const kuid_t *id, dht_value_t **valvec, int valcnt)
{
	struct keyinfo *ki;
	struct keydata *kd;
	int i;
	int vcnt = valcnt;
	dht_value_t **vvec = valvec;

	g_assert(valvec);
	g_assert(valcnt > 0);

	ki = hikset_lookup(keys, id);
	if (ki == NULL)
		return 0;

	kd = get_keydata(id);
	if (kd == NULL)				/* DB failure */
		return 0;

	for (i = 0; i < kd->values && vcnt > 0; i++) {
		uint64 dbkey = kd->dbkeys[i];
		dht_value_t *v;

		g_assert(0 != dbkey);

		v = values_get(dbkey, DHT_VT_ANY);
		if (v == NULL)
			continue;

		g_assert(kuid_eq(dht_value_key(v), id));

		*vvec++ = v;
		vcnt--;
	}

	return vvec - valvec;		/* Amount of entries filled */
}
Ejemplo n.º 2
0
int cmd_exec( REPLY *r, int argc, char **argv ) {
	char addrbuf[FULL_ADDSTRLEN+1];
	time_t lifetime;
	int minutes;
	IP addrs[16];
	int port;
	int count;
	static struct value_t *value;
	char *p;
	int rc = 0;

	if( argc == 0 ) {

		/* Print usage */
		r_printf( r, cmd_usage );
		if( r->allow_debug ) {
			r_printf( r, cmd_usage_debug );
		}
		rc = 1;

	} else if( match( argv[0], "import" ) && argc == 2 ) {

		rc = cmd_import( r, argv[1] );
#if 0
	} else if( match( argv[0], "lookup_node" ) && argc == 2 ) {

		/* Check searches for node */
		rc = kad_lookup_node( argv[1], &addrs[0] );
		if( rc == 0 ) {
			r_printf( r, "%s\n", str_addr( &addrs[0], addrbuf ) );
		} else if( rc == 1 ) {
			r_printf( r ,"No search found.\n" );
			rc = 1;
		} else if( rc == 2 ) {
			r_printf( r ,"Invalid id format. 20 digit hex string expected.\n" );
			rc = 1;
		} else {
			rc = 1;
		}
#endif
	} else if( match( argv[0], "lookup" ) && argc == 2 ) {

		size_t num = N_ELEMS(addrs);
		size_t i;

		/* Check searches for node */
		rc = kad_lookup_value( argv[1], addrs, &num );

		if( rc >= 0 && num > 0 ) {
			for( i = 0; i < num; ++i ) {
				r_printf( r, "%s\n", str_addr( &addrs[i], addrbuf ) );
			}
		} else if( rc < 0 ) {
			r_printf( r ,"Some error occured.\n" );
			rc = 1;
		} else if( rc == 0 ) {
			r_printf( r ,"Search in progress.\n" );
			rc = 1;
		} else {
			r_printf( r ,"Search started.\n" );
			rc = 1;
		}
	} else if( match( argv[0], "status" ) && argc == 1 ) {

		/* Print node id and statistics */
		cmd_print_status( r );

	} else if( match( argv[0], "announce" ) && (argc == 1 || argc == 2 || argc == 3) ) {

		if( argc == 1 ) {
			/* Announce all values; does not update value.refreshed */
			count = 0;
			value = values_get();
			while( value ) {
				kad_announce_once( value->id, value->port );
				count++;
				value = value->next;
			}
			r_printf( r ,"%d announcements started.\n", count );
			rc = 0;
			goto end;
		} else if( argc == 2 ) {
			minutes = 0;
			lifetime = 0;
		} else if( argc == 3 ) {
			minutes = atoi( argv[2] );
			if( minutes < 0 ) {
				minutes = 0;
				lifetime = LONG_MAX;
			} else {
				/* Round up to multiple of 30 minutes */
				minutes = (30 * (minutes/30 + 1));
				lifetime = (time_now_sec() + (minutes * 60));
			}
		} else {
			/* Make compilers happy */
			exit( 1 );
		}

		int is_random_port = 0;

		/* Find <id>:<port> delimiter */
		p = strchr( argv[1], ':' );

		if( p ) {
			*p = '\0';
			port = port_parse( p + 1, -1 );
		} else {
			/* A valid port will be choosen inside kad_announce() */
			port = 0;
			is_random_port = 1;
		}

		if( kad_announce( argv[1], port, lifetime ) >= 0 ) {
#ifdef FWD
			if( !is_random_port ) {
				forwardings_add( port, lifetime);
			}
#endif
			if( lifetime == 0 ) {
				r_printf( r ,"Start single announcement now.\n" );
			} else if( lifetime == LONG_MAX ) {
				r_printf( r ,"Start regular announcements for the entire run time (%sport %d).\n", (is_random_port ? "random " : ""), port );
			} else {
				r_printf( r ,"Start regular announcements for %d minutes (%sport %d).\n", minutes, (is_random_port ? "random " : ""), port );
			}
		} else {
			r_printf( r ,"Invalid port or query too long.\n" );
			rc = 1;
		}

	} else if( match( argv[0], "blacklist" ) && argc == 2 ) {

		rc = cmd_blacklist( r, argv[1] );

	} else if( match( argv[0], "export" ) && argc == 1 ) {

		rc = cmd_export( r );

	} else if( match( argv[0], "list" ) && argc == 2 && r->allow_debug ) {

		if( gconf->is_daemon == 1 ) {
			r_printf( r ,"The 'list' command is not available while KadNode runs as daemon.\n" );
			rc = 1;
			goto end;
		} else if( match( argv[1], "blacklist" ) ) {
			kad_debug_blacklist( STDOUT_FILENO );
			rc = 0;
		} else if( match( argv[1], "buckets" ) ) {
			kad_debug_buckets( STDOUT_FILENO );
			rc = 0;
		} else if( match( argv[1], "constants" ) ) {
			kad_debug_constants( STDOUT_FILENO );
			rc = 0;
#ifdef FWD
		} else if( match( argv[1], "forwardings" ) ) {
			forwardings_debug( STDOUT_FILENO );
			rc = 0;
#endif
#ifdef AUTH
		} else if( match( argv[1], "pkeys" ) ) {
			auth_debug_pkeys( STDOUT_FILENO );
			rc = 0;
		} else if( match( argv[1], "skeys" ) ) {
			auth_debug_skeys( STDOUT_FILENO );
			rc = 0;
#endif
		} else if( match( argv[1], "results" ) ) {
			results_debug( STDOUT_FILENO );
			rc = 0;
		} else if( match( argv[1], "searches" ) ) {
			kad_debug_searches( STDOUT_FILENO );
			rc = 0;
		} else if( match( argv[1], "storage" ) ) {
			kad_debug_storage( STDOUT_FILENO );
			rc = 0;
		} else if( match( argv[1], "values" ) ) {
			values_debug( STDOUT_FILENO );
			rc = 0;
		} else {
			dprintf( STDERR_FILENO, "Unknown argument.\n" );
			rc = 1;
		}
		r_printf( r ,"\nOutput send to console.\n" );

	} else {
		/* print usage */
		r_printf( r, cmd_usage );
		if( r->allow_debug ) {
			r_printf( r, cmd_usage_debug );
		}
		rc = 1;
	}

end:
	;
	return rc;
}
Ejemplo n.º 3
0
/**
 * Fill supplied value vector with the DHT values we have under the key that
 * match the specifications: among those bearing the specified secondary keys
 * (or all of them if no secondary keys are supplied), return only those with
 * the proper DHT value type.
 *
 * @param id				the primary key of the value
 * @param type				type of DHT value they want
 * @param secondary			optional secondary keys
 * @param secondary_count	amount of secondary keys supplied
 * @param valvec			value vector where results are stored
 * @param valcnt			size of value vector
 * @param loadptr			where to write the average request load for key
 * @param cached			if non-NULL, filled with whether key was cached
 *
 * @return amount of values filled into valvec.  The values are dynamically
 * created and must be freed by caller through dht_value_free().
 */
int
keys_get(const kuid_t *id, dht_value_type_t type,
	kuid_t **secondary, int secondary_count, dht_value_t **valvec, int valcnt,
	float *loadptr, bool *cached)
{
	struct keyinfo *ki;
	struct keydata *kd;
	int i;
	int vcnt = valcnt;
	dht_value_t **vvec = valvec;

	g_assert(secondary_count == 0 || secondary != NULL);
	g_assert(valvec);
	g_assert(valcnt > 0);
	g_assert(loadptr);

	ki = hikset_lookup(keys, id);

	g_assert(ki);	/* If called, we know the key exists */

	if (GNET_PROPERTY(dht_storage_debug) > 5)
		g_debug("DHT FETCH key %s (load = %g, current reqs = %u) type %s"
			" with %d secondary key%s",
			kuid_to_hex_string(id), ki->get_req_load, ki->get_requests,
			dht_value_type_to_string(type),
			secondary_count, plural(secondary_count));

	*loadptr = ki->get_req_load;
	ki->get_requests++;

	kd = get_keydata(id);
	if (kd == NULL)				/* DB failure */
		return 0;

	/*
	 * If secondary keys were requested, lookup them up and make sure
	 * they have the right DHT type (or skip them).
	 */

	for (i = 0; i < secondary_count && vcnt > 0; i++) {
		uint64 dbkey = lookup_secondary(kd, secondary[i]);
		dht_value_t *v;

		if (0 == dbkey)
			continue;

		v = values_get(dbkey, type);
		if (v == NULL)
			continue;

		g_assert(kuid_eq(dht_value_key(v), id));

		if (GNET_PROPERTY(dht_storage_debug) > 5)
			g_debug("DHT FETCH key %s via secondary key %s has matching %s",
				kuid_to_hex_string(id), kuid_to_hex_string2(secondary[i]),
				dht_value_to_string(v));

		*vvec++ = v;
		vcnt--;
	}

	/*
	 * Don't count secondary-key fetches in the local hit stats: in order to
	 * be able to get these fetches, we must have initially provided the
	 * list of these keys, and thus we have already traversed the code below
	 * for that fetch, which accounted the hit already.
	 */

	if (secondary_count) {
		int n = vvec - valvec;		/* Amount of entries filled */

		gnet_stats_count_general(GNR_DHT_CLAIMED_SECONDARY_KEYS, n);
		if (ki->flags & DHT_KEY_F_CACHED)
			gnet_stats_count_general(GNR_DHT_CLAIMED_CACHED_SECONDARY_KEYS, n);

		goto done;
	}

	/*
	 * No secondary keys specified.  Look them all up.
	 */

	for (i = 0; i < kd->values && vcnt > 0; i++) {
		uint64 dbkey = kd->dbkeys[i];
		dht_value_t *v;

		g_assert(0 != dbkey);

		v = values_get(dbkey, type);
		if (v == NULL)
			continue;

		g_assert(kuid_eq(dht_value_key(v), id));

		if (GNET_PROPERTY(dht_storage_debug) > 5)
			g_debug("DHT FETCH key %s has matching %s",
				kuid_to_hex_string(id), dht_value_to_string(v));

		*vvec++ = v;
		vcnt--;
	}

	/*
	 * Stats update: we count all the hits, plus successful hits on keys
	 * that do not fall within our k-ball, i.e. keys for which we act as
	 * a "cache".  Note that our k-ball frontier can evolve through time,
	 * so we rely on the DHT_KEY_F_CACHED flag, positionned at creation time.
	 */

	if (vvec != valvec) {
		gnet_stats_inc_general(GNR_DHT_FETCH_LOCAL_HITS);
		if (ki->flags & DHT_KEY_F_CACHED)
			gnet_stats_inc_general(GNR_DHT_FETCH_LOCAL_CACHED_HITS);
	}

done:

	if (cached)
		*cached = (ki->flags & DHT_KEY_F_CACHED) ? TRUE : FALSE;

	return vvec - valvec;		/* Amount of entries filled */
}