Beispiel #1
0
static rstatus_t
dnode_peer_add_node(struct server_pool *sp, struct node *node)
{
	rstatus_t status;
	struct array *peers = &sp->peers;
	struct server *s = array_push(peers);

	s->owner = sp;

	uint32_t i,nelem;
	s->idx = array_idx(peers, s);

	//log_debug(LOG_VERB, "node rack_name         : '%.*s'", node->rack.len, node->rack.data);
	//log_debug(LOG_VERB, "node dc_name        : '%.*s'", node->dc.len, node->dc.data);
	//log_debug(LOG_VERB, "node address          : '%.*s'", node->pname.len, node->pname.data);
	//log_debug(LOG_VERB, "node ip         : '%.*s'", node->name.len, node->name.data);


	string_copy(&s->pname, node->pname.data, node->pname.len);
	string_copy(&s->name, node->name.data, node->name.len);
	string_copy(&s->rack, node->rack.data, node->rack.len);
	string_copy(&s->dc, node->dc.data, node->dc.len);

	s->port = (uint16_t) node->port;
	s->is_local = node->is_local;
	s->state = node->state;
	s->processed = 0;

	array_init(&s->tokens, 1, sizeof(struct dyn_token));
	struct dyn_token *src_token = &node->token;
	struct dyn_token *dst_token = array_push(&s->tokens);
	copy_dyn_token(src_token, dst_token);

	struct sockinfo  *info =  dn_alloc(sizeof(*info)); //need to free this
	dn_resolve(&s->name, s->port, info);
	s->family = info->family;
	s->addrlen = info->addrlen;
	s->addr = (struct sockaddr *)&info->addr;  //TODOs: fix this by copying, not reference
	s->ns_conn_q = 0;
	TAILQ_INIT(&s->s_conn_q);

	s->next_retry = 0LL;
	s->failure_count = 0;
	s->is_seed = node->is_seed;

	log_debug(LOG_VERB, "add a node to peer %"PRIu32" '%.*s'",
			s->idx, s->pname.len, s->pname.data);

	dnode_peer_relink_conn_owner(sp);

	status = dnode_peer_pool_run(sp);
	if (status != DN_OK)
		return status;

	status = dnode_peer_each_preconnect(s, NULL);

	return status;
}
static void
dnode_peer_failure(struct context *ctx, struct server *server)
{
	struct server_pool *pool = server->owner;
	int64_t now, next;
	rstatus_t status;

	//fix me
	if (!pool->auto_eject_hosts) {
		return;
	}

	server->failure_count++;

	log_debug(LOG_VERB, "dyn: peer '%.*s' failure count %"PRIu32" limit %"PRIu32,
			server->pname.len, server->pname.data, server->failure_count,
			pool->server_failure_limit);

	if (server->failure_count < pool->server_failure_limit) {
		return;
	}

	now = dn_usec_now();
	if (now < 0) {
		return;
	}

	//fix me
	//stats_server_set_ts(ctx, server, server_ejected_at, now);

	//fix me
	next = now + pool->server_retry_timeout;

	log_debug(LOG_INFO, "dyn: update peer pool %"PRIu32" '%.*s' to delete peer '%.*s' "
			"for next %"PRIu32" secs", pool->idx, pool->name.len,
			pool->name.data, server->pname.len, server->pname.data,
			pool->server_retry_timeout / 1000 / 1000);

	stats_pool_incr(ctx, pool, peer_ejects);

	server->failure_count = 0;
	server->next_retry = next;

	status = dnode_peer_pool_run(pool);
	if (status != DN_OK) {
		log_error("dyn: updating peer pool %"PRIu32" '%.*s' failed: %s", pool->idx,
				pool->name.len, pool->name.data, strerror(errno));
	}
}
rstatus_t
dnode_peer_pool_update(struct server_pool *pool)
{
	rstatus_t status;
	int64_t now;
	uint32_t pnlive_server; /* prev # live server */


	//fix me
	if (!pool->auto_eject_hosts) {
		return DN_OK;
	}

	//fix me
	if (pool->next_rebuild == 0LL) {
		return DN_OK;
	}

	now = dn_usec_now();
	if (now < 0) {
		return DN_ERROR;
	}

	//fix me
	if (now <= pool->next_rebuild) {
		if (pool->nlive_server == 0) {
			errno = ECONNREFUSED;
			return DN_ERROR;
		}
		return DN_OK;
	}

	//fixe me to use anotehr variable
	pnlive_server = pool->nlive_server;

	status = dnode_peer_pool_run(pool);
	if (status != DN_OK) {
		log_error("dyn: updating peer pool %"PRIu32" with dist %d failed: %s", pool->idx,
				pool->dist_type, strerror(errno));
		return status;
	}

	log_debug(LOG_INFO, "dyn: update peer pool %"PRIu32" '%.*s' to add %"PRIu32" servers",
			pool->idx, pool->name.len, pool->name.data,
			pool->nlive_server - pnlive_server);


	return DN_OK;
}
struct conn *
dnode_peer_pool_conn(struct context *ctx, struct server_pool *pool, struct rack *rack,
		uint8_t *key, uint32_t keylen, uint8_t msg_type)
{
	rstatus_t status;
	struct server *server;
	struct conn *conn;

	//status = dnode_peer_pool_update(pool);
	status = dnode_peer_pool_run(pool);
	if (status != DN_OK) {
		return NULL;
	}

	if (msg_type == 1) {  //always local
		server = array_get(&pool->peers, 0);
	} else {
		/* from a given {key, keylen} pick a server from pool */
		server = dnode_peer_pool_server(pool, rack, key, keylen);
		if (server == NULL) {
			return NULL;
		}
	}

	/* pick a connection to a given server */
	conn = dnode_peer_conn(server);
	if (conn == NULL) {
		return NULL;
	}

	if (server->is_local)
		return conn; //Don't bother to connect

	status = dnode_peer_connect(ctx, server, conn);
	if (status != DN_OK) {
		dnode_peer_close(ctx, conn);
		return NULL;
	}

	return conn;
}
rstatus_t
dnode_peer_each_pool_init(void *elem, void *context)
{
	struct server_pool *sp = (struct server_pool *) elem;
	//struct context *ctx = context;
	struct array *conf_seeds = &sp->conf_pool->dyn_seeds;

	struct array * seeds = &sp->seeds;
	struct array * peers = &sp->peers;
	rstatus_t status;
	uint32_t nseed;

	/* init seeds list */
	nseed = array_n(conf_seeds);
	if(nseed == 0) {
		log_debug(LOG_INFO, "dyn: look like you are running with no seeds deifined. This is ok for running with just one node.");

		// add current node to peers array
		status = array_init(peers, CONF_DEFAULT_PEERS, sizeof(struct server));
		if (status != DN_OK) {
			return status;
		}

		struct server *peer = array_push(peers);
		ASSERT(peer != NULL);
		status = dnode_peer_add_local(sp, peer);
		if (status != DN_OK) {
			dnode_peer_deinit(peers);
		}
		dnode_peer_pool_run(sp);
		return status;
	}

	ASSERT(array_n(seeds) == 0);

	status = array_init(seeds, nseed, sizeof(struct server));
	if (status != DN_OK) {
		return status;
	}

	/* transform conf seeds to seeds */
	status = array_each(conf_seeds, conf_seed_each_transform, seeds);
	if (status != DN_OK) {
		dnode_peer_deinit(seeds);
		return status;
	}
	ASSERT(array_n(seeds) == nseed);

	/* set seed owner */
	status = array_each(seeds, dnode_peer_each_set_owner, sp);
	if (status != DN_OK) {
		dnode_peer_deinit(seeds);
		return status;
	}


	/* initialize peers list = seeds list */
	ASSERT(array_n(peers) == 0);

	// add current node to peers array
	uint32_t peer_cnt = nseed + 1;
	status = array_init(peers, CONF_DEFAULT_PEERS, sizeof(struct server));
	if (status != DN_OK) {
		return status;
	}

	struct server *peer = array_push(peers);
	ASSERT(peer != NULL);
	status = dnode_peer_add_local(sp, peer);
	if (status != DN_OK) {
		dnode_peer_deinit(seeds);
		dnode_peer_deinit(peers);
		return status;
	}

	status = array_each(conf_seeds, conf_seed_each_transform, peers);
	if (status != DN_OK) {
		dnode_peer_deinit(seeds);
		dnode_peer_deinit(peers);
		return status;
	}
	ASSERT(array_n(peers) == peer_cnt);

	status = array_each(peers, dnode_peer_each_set_owner, sp);
	if (status != DN_OK) {
		dnode_peer_deinit(seeds);
		dnode_peer_deinit(peers);
		return status;
	}

	dnode_peer_pool_run(sp);

	log_debug(LOG_DEBUG, "init %"PRIu32" seeds and peers in pool %"PRIu32" '%.*s'",
			nseed, sp->idx, sp->name.len, sp->name.data);

	return DN_OK;
}