static rstatus_t
dnode_peer_each_preconnect(void *elem, void *data)
{
	rstatus_t status;
	struct server *peer;
	struct server_pool *sp;
	struct conn *conn;

	peer = elem;
	sp = peer->owner;

    if (peer->is_local)  //don't bother to connect if it is a self-connection
        return DN_OK;

	conn = dnode_peer_conn(peer);
	if (conn == NULL) {
		return DN_ENOMEM;
	}

	status = dnode_peer_connect(sp->ctx, peer, conn);
	if (status != DN_OK) {
		log_warn("dyn: connect to peer '%.*s' failed, ignored: %s",
				peer->pname.len, peer->pname.data, strerror(errno));
		dnode_peer_close(sp->ctx, conn);
	}

	return DN_OK;
}
rstatus_t
dnode_peer_forward_state(void *rmsg)
{
	rstatus_t status;
	struct ring_msg *msg = rmsg;
	struct server_pool *sp = msg->sp;
	log_debug(LOG_VVERB, "dnode_peer_forward_state: forwarding");

	//we assume one mbuf is enough for now - will enhance with multiple mbufs later
	struct mbuf *mbuf = mbuf_get();
	if (mbuf == NULL) {
		log_debug(LOG_VVERB, "Too bad, not enough memory!");
		return DN_ENOMEM;
	}

	mbuf_copy(mbuf, msg->data, msg->len);

	struct array *peers = &sp->peers;
	uint32_t i,nelem;
	nelem = array_n(peers);

	//pick a random peer
	int ran_index = rand() % nelem;

	if (ran_index == 0)
	   ran_index += 1;

	struct server *peer = (struct server *) array_get(peers, ran_index);

	//log_debug(LOG_VVERB, "Gossiping to node  '%.*s'", peer->name.len, peer->name.data);

	struct conn * conn = dnode_peer_conn(peer);
	if (conn == NULL) {
		//running out of connection due to memory exhaust
		log_debug(LOG_ERR, "Unable to obtain a connection object");
		return DN_ERROR;
	}

	status = dnode_peer_connect(sp->ctx, peer, conn);
	if (status != DN_OK ) {
		dnode_peer_close(sp->ctx, conn);
		log_debug(LOG_ERR, "Error happened in connecting on conn %d", conn->sd);
		return DN_ERROR;
	}

	dnode_peer_gossip_forward(sp->ctx, conn, sp->redis, mbuf);

	//free this as nobody else will do
	//mbuf_put(mbuf);

	return status;
}
Exemple #3
0
void
dnode_peer_attemp_reconnect_or_close(struct context *ctx, struct conn *conn)
{
	rstatus_t status;

	if (conn->attempted_reconnect < 30) {
		status = close(conn->sd);
		if (status < 0) {
			log_error("dyn: close s %d failed, ignored: %s", conn->sd, strerror(errno));
		}
		conn->sd = -1;
	   if (dnode_peer_connect(ctx, conn->owner, conn) != DN_OK)
	      conn->attempted_reconnect++;
	   else conn->attempted_reconnect = 0;
	} else {
		dnode_peer_close(ctx, conn);
	}
}
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_handshake_announcing(void *rmsg)
{
	rstatus_t status;
	struct ring_msg *msg = rmsg;
	struct server_pool *sp = msg->sp;
	log_debug(LOG_VVERB, "dyn: handshaking peers");
	struct array *peers = &sp->peers;

	uint32_t i,nelem;
	nelem = array_n(peers);

	//we assume one mbuf is enough for now - will enhance with multiple mbufs later
	struct mbuf *mbuf = mbuf_get();
	if (mbuf == NULL) {
		log_debug(LOG_VVERB, "Too bad, not enough memory!");
		return DN_ENOMEM;
	}

	//annoucing myself by sending msg: 'dc$rack$token,started_ts,node_state,node_dns'
	mbuf_write_string(mbuf, &sp->dc);
	mbuf_write_char(mbuf, '$');
	mbuf_write_string(mbuf, &sp->rack);
	mbuf_write_char(mbuf, '$');
	struct dyn_token *token = (struct dyn_token *) array_get(&sp->tokens, 0);
	if (token == NULL) {
		log_debug(LOG_VVERB, "Why? This should not be null!");
		mbuf_put(mbuf);
		return DN_ERROR;
	}

	mbuf_write_uint32(mbuf, token->mag[0]);
	mbuf_write_char(mbuf, ',');
	int64_t cur_ts = (int64_t)time(NULL);
	mbuf_write_uint64(mbuf, cur_ts);
	mbuf_write_char(mbuf, ',');
	mbuf_write_uint8(mbuf, sp->ctx->dyn_state);
	mbuf_write_char(mbuf, ',');

	char *broadcast_addr = get_broadcast_address(sp);
	mbuf_write_bytes(mbuf, broadcast_addr, dn_strlen(broadcast_addr));

	//for each peer, send a registered msg
	for (i = 0; i < nelem; i++) {
		struct server *peer = (struct server *) array_get(peers, i);
		if (peer->is_local)
			continue;

		log_debug(LOG_VVERB, "Gossiping to node  '%.*s'", peer->name.len, peer->name.data);

		struct conn * conn = dnode_peer_conn(peer);
		if (conn == NULL) {
			//running out of connection due to memory exhaust
			log_debug(LOG_DEBUG, "Unable to obtain a connection object");
			return DN_ERROR;
		}


		status = dnode_peer_connect(sp->ctx, peer, conn);
		if (status != DN_OK ) {
			dnode_peer_close(sp->ctx, conn);
			log_debug(LOG_DEBUG, "Error happened in connecting on conn %d", conn->sd);
			return DN_ERROR;
		}

		//conn->

		dnode_peer_gossip_forward(sp->ctx, conn, sp->redis, mbuf);
		//peer_gossip_forward1(sp->ctx, conn, sp->redis, &data);
	}

	//free this as nobody else will do
	//mbuf_put(mbuf);

	return DN_OK;
}