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; }
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; }