static void dmsg_parse_host_id(uint8_t *start, uint32_t len, struct string *dc, struct string *rack, struct dyn_token *token) { uint8_t *p, *q; uint8_t *dc_p, *rack_p, *token_p; uint32_t k, delimlen, dc_len, rack_len, token_len; char delim[] = "$$"; delimlen = 2; /* parse "dc$rack$token : don't support vnode for now */ //log_hexdump(LOG_VERB, start, len, "host_addr testing: "); p = start + len - 1; dc_p = NULL; rack_p = NULL; token_p = NULL; dc_len = rack_len = token_len = 0; for (k = 0; k < sizeof(delim)-1; k++) { q = dn_strrchr(p, start, delim[k]); switch (k) { case 0: //no support for vnode at this time token_p = q + 1; token_len = (uint32_t)(p - token_p + 1); parse_dyn_token(token_p, token_len, token); break; case 1: rack_p = q + 1; rack_len = (uint32_t)(p - rack_p + 1); string_copy(rack, rack_p, rack_len); break; default: NOT_REACHED(); } p = q - 1; } if (k != delimlen) { loga("Error: this should not happen"); return;// DN_ERROR; } dc_p = start; dc_len = len - (token_len + rack_len + 2); string_copy(dc, dc_p, dc_len); }
static rstatus_t dnode_peer_add_local(struct server_pool *pool, struct server *peer) { ASSERT(peer != NULL); peer->idx = 0; /* this might be psychotic, trying it for now */ peer->pname = pool->d_addrstr; uint8_t *p = pool->d_addrstr.data + pool->d_addrstr.len - 1; uint8_t *start = pool->d_addrstr.data; string_copy(&peer->name, start, dn_strrchr(p, start, ':') - start); //peer->name = pool->d_addrstr; peer->port = pool->d_port; peer->weight = 0; /* hacking this out of the way for now */ peer->rack = pool->rack; peer->is_local = true; //TODO-jeb might need to copy over tokens, not sure if this is good enough peer->tokens = pool->tokens; peer->family = pool->d_family; peer->addrlen = pool->d_addrlen; peer->addr = pool->d_addr; peer->ns_conn_q = 0; TAILQ_INIT(&peer->s_conn_q); peer->next_retry = 0LL; peer->failure_count = 0; peer->is_seed = 1; string_copy(&peer->dc, pool->dc.data, pool->dc.len); peer->owner = pool; log_debug(LOG_VERB, "dyn: transform to local node to peer %"PRIu32" '%.*s'", peer->idx, pool->name.len, pool->name.data); return DN_OK; }
static struct ring_msg * dmsg_parse(struct dmsg *dmsg) { //rstatus_t status; uint8_t *p, *q, *start, *end, *pipe_p; uint8_t *host_id, *host_addr, *ts, *node_state; uint32_t k, delimlen, host_id_len, host_addr_len, ts_len, node_state_len; char delim[] = ",,,"; delimlen = 3; /* parse "host_id1,generation_ts1,host_state1,host_broadcast_address1|host_id2,generation_ts2,host_state2,host_broadcast_address2" */ /* host_id = dc-rack-token */ //p = dmsg->data + dmsg->mlen - 1; //p = dmsg->owner->pos + dmsg->owner->mlen - 1; p = dmsg->payload + dmsg->plen - 1; end = p; //start = dmsg->data; //start = dmsg->owner->pos; start = dmsg->payload; host_id = NULL; host_addr = NULL; ts = NULL; node_state = NULL; host_id_len = 0; host_addr_len = 0; ts_len = 0; node_state_len = 0; pipe_p = start; int count = 0; do { q = dn_strrchr(p, start, '|'); count++; p = q - 1; } while (q != NULL); struct ring_msg *ring_msg = create_ring_msg_with_size(count, true); if (ring_msg == NULL) { log_debug(LOG_ERR, "Error: unable to create a new ring msg!"); //we just drop this msg return NULL; } struct server_pool *sp = (struct server_pool *) dmsg->owner->owner->owner; ring_msg->sp = sp; ring_msg->cb = gossip_msg_peer_update; count = 0; //p = dmsg->data + dmsg->mlen - 1; p = dmsg->payload + dmsg->plen - 1; do { for (k = 0; k < sizeof(delim)-1; k++) { q = dn_strrchr(p, start, delim[k]); switch (k) { case 0: host_addr = q + 1; host_addr_len = (uint32_t)(p - host_addr + 1); break; case 1: node_state = q + 1; node_state_len = (uint32_t)(p - node_state + 1); break; case 2: ts = q + 1; ts_len = (uint32_t)(p - ts + 1); break; default: NOT_REACHED(); } p = q - 1; } if (k != delimlen) { loga("Error: this is insanely bad"); return NULL;// DN_ERROR; } pipe_p = dn_strrchr(p, start, '|'); if (pipe_p == NULL) { pipe_p = start; } else { pipe_p = pipe_p + 1; p = pipe_p - 2; } //host_id = dmsg->data; //host_id_len = dmsg->mlen - (host_addr_len + node_state_len + ts_len + 3); host_id = pipe_p; host_id_len = end - pipe_p - (host_addr_len + node_state_len + ts_len + 3) + 1; end = p; struct node *rnode = (struct node *) array_get(&ring_msg->nodes, count); dmsg_parse_host_id(host_id, host_id_len, &rnode->dc, &rnode->rack, &rnode->token); string_copy(&rnode->name, host_addr, host_addr_len); string_copy(&rnode->pname, host_addr, host_addr_len); //need to add port rnode->port = sp->d_port; rnode->is_local = false; rnode->is_seed = false; ts[ts_len] = '\0'; rnode->ts = atol(ts); node_state[node_state_len] = '\0'; rnode->state = (uint8_t) atoi(node_state); count++; } while (pipe_p != start); //TODOs: should move this outside dmsg_to_gossip(ring_msg); return ring_msg; }
static rstatus_t gossip_update_seeds(struct server_pool *sp, struct mbuf *seeds) { struct string rack_name; struct string dc_name; struct string port_str; struct string address; struct string ip; //struct array tokens; struct dyn_token token; struct string temp; string_init(&rack_name); string_init(&dc_name); string_init(&port_str); string_init(&address); string_init(&ip); init_dyn_token(&token); uint8_t *p, *q, *start; start = seeds->start; p = seeds->last - 1; q = dn_strrchr(p, start, '|'); uint8_t *seed_node; uint32_t seed_node_len; while (q > start) { seed_node = q + 1; seed_node_len = (uint32_t)(p - seed_node + 1); string_copy(&temp, seed_node, seed_node_len); //array_init(&tokens, 1, sizeof(struct dyn_token)); init_dyn_token(&token); parse_seeds(&temp, &dc_name, &rack_name, &port_str, &address, &ip, &token); log_debug(LOG_VERB, "address : '%.*s'", address.len, address.data); log_debug(LOG_VERB, "rack_name : '%.*s'", rack_name.len, rack_name.data); log_debug(LOG_VERB, "dc_name : '%.*s'", dc_name.len, dc_name.data); log_debug(LOG_VERB, "ip : '%.*s'", ip.len, ip.data); //struct dyn_token *token = array_get(&tokens, 0); gossip_add_node_if_absent(sp, &dc_name, &rack_name, &address, &ip, &port_str, &token, NORMAL, (uint64_t) time(NULL)); p = q - 1; q = dn_strrchr(p, start, '|'); string_deinit(&temp); //array_deinit(&tokens); deinit_dyn_token(&token); string_deinit(&rack_name); string_deinit(&dc_name); string_deinit(&port_str); string_deinit(&address); string_deinit(&ip); } if (q == NULL) { seed_node_len = (uint32_t)(p - start + 1); seed_node = start; string_copy(&temp, seed_node, seed_node_len); //array_init(&tokens, 1, sizeof(struct dyn_token)); init_dyn_token(&token); parse_seeds(&temp, &dc_name, &rack_name, &port_str, &address, &ip, &token); //struct dyn_token *token = array_get(&tokens, 0); gossip_add_node_if_absent(sp, &dc_name, &rack_name, &address, &ip, &port_str, &token, NORMAL, (uint64_t) time(NULL)); } string_deinit(&temp); //array_deinit(&tokens); deinit_dyn_token(&token); string_deinit(&rack_name); string_deinit(&dc_name); string_deinit(&port_str); string_deinit(&address); string_deinit(&ip); gossip_debug(); return DN_OK; }
static rstatus_t parse_seeds(struct string *seeds, struct string *dc_name, struct string *rack_name, struct string *port_str, struct string *address, struct string *name, struct dyn_token *ptoken) { rstatus_t status; uint8_t *p, *q, *start; uint8_t *pname, *port, *rack, *dc, *token, *addr; uint32_t k, delimlen, pnamelen, portlen, racklen, dclen, tokenlen, addrlen; char delim[] = "::::"; /* parse "hostname:port:rack:dc:tokens" */ p = seeds->data + seeds->len - 1; start = seeds->data; rack = NULL; dc = NULL; racklen = 0; dclen = 0; token = NULL; tokenlen = 0; port = NULL; portlen = 0; delimlen = 4; for (k = 0; k < sizeof(delim)-1; k++) { q = dn_strrchr(p, start, delim[k]); switch (k) { case 0: token = q + 1; tokenlen = (uint32_t)(p - token + 1); break; case 1: dc = q + 1; dclen = (uint32_t)(p - dc + 1); string_copy(dc_name, dc, dclen); break; case 2: rack = q + 1; racklen = (uint32_t)(p - rack + 1); string_copy(rack_name, rack, racklen); break; case 3: port = q + 1; portlen = (uint32_t)(p - port + 1); string_copy(port_str, port, portlen); break; default: NOT_REACHED(); } p = q - 1; } if (k != delimlen) { return GOS_ERROR; } //pname = hostname:port pname = seeds->data; pnamelen = seeds->len - (tokenlen + racklen + dclen + 3); status = string_copy(address, pname, pnamelen); //addr = hostname or ip only addr = start; addrlen = (uint32_t)(p - start + 1); //if it is a dns name, convert to IP or otherwise keep that IP if (!isdigit( (char) addr[0])) { addr[addrlen] = '\0'; char *local_ip4 = hostname_to_private_ip4( (char *) addr); if (local_ip4 != NULL) { status = string_copy_c(name, local_ip4); } else status = string_copy(name, addr, addrlen); } else { status = string_copy(name, addr, addrlen); } if (status != DN_OK) { return GOS_ERROR; } uint8_t *t_end = token + tokenlen; status = derive_token(ptoken, token, t_end); if (status != DN_OK) { return GOS_ERROR; } //status = dn_resolve(&address, field->port, &field->info); //if (status != DN_OK) { // string_deinit(&address); // return CONF_ERROR; //} return GOS_OK; }