static void conf_server_deinit(struct conf_server *cs) { string_deinit(&cs->pname); string_deinit(&cs->name); cs->valid = 0; log_debug(LOG_VVERB, "deinit conf server %p", cs); }
static rstatus_t conf_pool_init(struct conf_pool *cp, struct string *name) { rstatus_t status; string_init(&cp->name); string_init(&cp->listen.pname); string_init(&cp->listen.name); cp->listen.port = 0; memset(&cp->listen.info, 0, sizeof(cp->listen.info)); cp->listen.valid = 0; cp->hash = CONF_UNSET_HASH; string_init(&cp->hash_tag); cp->distribution = CONF_UNSET_DIST; cp->timeout = CONF_UNSET_NUM; cp->backlog = CONF_UNSET_NUM; cp->client_connections = CONF_UNSET_NUM; cp->tcpkeepalive = CONF_UNSET_NUM; string_init(&cp->redis_auth); cp->redis_db = CONF_UNSET_NUM; cp->server_connections = CONF_UNSET_NUM; array_null(&cp->groups); cp->sentinel_heartbeat = CONF_UNSET_NUM; array_null(&cp->sentinels); cp->valid = 0; status = string_duplicate(&cp->name, name); if (status != NC_OK) { return status; } status = array_init(&cp->groups, CONF_DEFAULT_GROUPS, sizeof(struct string)); if (status != NC_OK) { string_deinit(&cp->name); return status; } status = array_init(&cp->sentinels, CONF_DEFAULT_SENTINELS, sizeof(struct conf_server)); if (status != NC_OK) { array_deinit(&cp->groups); string_deinit(&cp->name); return status; } log_debug(LOG_VVERB, "init conf pool %p, '%.*s'", cp, name->len, name->data); return NC_OK; }
rstatus_t dnode_peer_replace(void *rmsg) { //rstatus_t status; struct ring_msg *msg = rmsg; struct server_pool *sp = msg->sp; struct node *node = array_get(&msg->nodes, 0); log_debug(LOG_VVERB, "dyn: peer has a replaced message '%.*s'", node->name.len, node->name.data); struct array *peers = &sp->peers; struct server *s = NULL; uint32_t i,nelem; //bool node_exist = false; //TODOs: use hash table here for (i=1, nelem = array_n(peers); i< nelem; i++) { struct server * peer = (struct server *) array_get(peers, i); if (string_compare(&peer->rack, &node->rack) == 0) { //TODOs: now only compare 1st token and support vnode later - use hash string on a tokens for comparison struct dyn_token *ptoken = (struct dyn_token *) array_get(&peer->tokens, 0); struct dyn_token *ntoken = &node->token; if (cmp_dyn_token(ptoken, ntoken) == 0) { s = peer; //found a node to replace } } } if (s != NULL) { log_debug(LOG_INFO, "Found an old node to replace '%.*s'", s->name.len, s->name.data); log_debug(LOG_INFO, "Replace with address '%.*s'", node->name.len, node->name.data); string_deinit(&s->pname); string_deinit(&s->name); string_copy(&s->pname, node->pname.data, node->pname.len); string_copy(&s->name, node->name.data, node->name.len); //TODOs: need to free the previous s->addr? //if (s->addr != NULL) { // dn_free(s->addr); //} 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 dnode_peer_each_disconnect(s, NULL); dnode_peer_each_preconnect(s, NULL); } else { log_debug(LOG_INFO, "Unable to find any node matched the token"); } return DN_OK; }
static void conf_pool_deinit(struct conf_pool *cp) { string_deinit(&cp->name); string_deinit(&cp->listen.pname); string_deinit(&cp->listen.name); while (array_n(&cp->server) != 0) { conf_server_deinit(array_pop(&cp->server)); } array_deinit(&cp->server); log_debug(LOG_VVERB, "deinit conf pool %p", cp); }
void sentinel_deinit(struct server *sentinel) { if (sentinel == NULL) { return; } ASSERT(TAILQ_EMPTY(&sentinel->s_conn_q) && sentinel->ns_conn_q == 0); string_deinit(&sentinel->name); string_deinit(&sentinel->pname); if (sentinel->addr != NULL) { nc_free(sentinel->addr); } nc_free(sentinel); }
rstatus_t dc_deinit(struct datacenter *dc) { array_each(&dc->racks, rack_destroy, NULL); string_deinit(dc->name); //dictRelease(dc->dict_rack); return DN_OK; }
static void conf_pop_scalar(struct conf *cf) { struct string *value; value = array_pop(&cf->arg); log_debug(LOG_VVERB, "pop '%.*s'", value->len, value->data); string_deinit(value); }
void dict_string_destructor(void *privdata, void *val) { DICT_NOTUSED(privdata); struct string *s = val; string_deinit(s); dn_free(s); }
static rstatus_t conf_pool_init(struct conf_pool *cp, struct string *name) { rstatus_t status; string_init(&cp->name); string_init(&cp->listen.pname); string_init(&cp->listen.name); string_init(&cp->redis_auth); cp->listen.port = 0; memset(&cp->listen.info, 0, sizeof(cp->listen.info)); cp->listen.valid = 0; cp->hash = CONF_UNSET_HASH; string_init(&cp->hash_tag); cp->distribution = CONF_UNSET_DIST; cp->timeout = CONF_UNSET_NUM; cp->backlog = CONF_UNSET_NUM; cp->client_connections = CONF_UNSET_NUM; cp->redis = CONF_UNSET_NUM; cp->tcpkeepalive = CONF_UNSET_NUM; cp->redis_db = CONF_UNSET_NUM; cp->proto = CONF_UNSET_PROTO; cp->preconnect = CONF_UNSET_NUM; cp->auto_eject_hosts = CONF_UNSET_NUM; cp->server_connections = CONF_UNSET_NUM; cp->server_retry_timeout = CONF_UNSET_NUM; cp->server_failure_limit = CONF_UNSET_NUM; array_null(&cp->server); cp->valid = 0; status = string_duplicate(&cp->name, name); if (status != NC_OK) { return status; } status = array_init(&cp->server, CONF_DEFAULT_SERVERS, sizeof(struct conf_server)); if (status != NC_OK) { string_deinit(&cp->name); return status; } log_debug(LOG_VVERB, "init conf pool %p, '%.*s'", cp, name->len, name->data); return NC_OK; }
static rstatus_t gossip_replace_node(struct server_pool *sp, struct node *node, struct string *new_address, struct string *new_ip, uint8_t state) { rstatus_t status; log_debug(LOG_WARN, "gossip_replace_node : dc[%.*s] rack[%.*s] oldaddr[%.*s] newaddr[%.*s] newip[%.*s]", node->dc, node->rack, node->name, new_address->len, new_address->data, new_ip->len, new_ip->data); string_deinit(&node->name); string_deinit(&node->pname); status = string_copy(&node->name, new_ip->data, new_ip->len); status = string_copy(&node->pname, new_address->data, new_address->len); //port is supposed to be the same node->state = state; gossip_msg_to_core(sp, node, dnode_peer_replace); //should check for status return status; }
/* Free a slow log entry. The argument is void so that the prototype of this * function matches the one of the 'free' method of adlist.c. * * This function will take care to release all the retained object. */ static void slowlog_free_entry(slowlog_entry *se) { if (se->keys) { struct string *key; while (array_n(se->keys) > 0) { key = array_pop(se->keys); string_deinit(key); } array_destroy(se->keys); } nc_free(se); }
void stats_pool_copy_deinit(struct stats_pool *stp, struct hash_table **sit) { uint32_t nserver; uint32_t i; struct stats_server *sts; stats_metric_deinit(&stp->metric); string_deinit(&stp->name); nserver = array_n(&stp->server); for (i = 0;i < nserver;i++) { sts = array_pop(&stp->server); string_deinit(&stp->name); stats_metric_deinit(&sts->metric); } array_deinit(&stp->server); assoc_destroy_table(*sit); (*sit) = NULL; }
static void conf_pool_deinit(struct conf_pool *cp) { string_deinit(&cp->name); string_deinit(&cp->listen.pname); string_deinit(&cp->listen.name); if (cp->redis_auth.len > 0) { string_deinit(&cp->redis_auth); } if (cp->mode.len > 0) { string_deinit(&cp->mode); } while (array_n(&cp->server) != 0) { conf_server_deinit(array_pop(&cp->server)); } array_deinit(&cp->server); log_debug(LOG_VVERB, "deinit conf pool %p", cp); }
static rstatus_t gossip_add_node_if_absent(struct server_pool *sp, struct string *dc, struct string *rack, struct string *address, struct string *ip, struct string *port, struct dyn_token *token, uint8_t state, uint64_t timestamp) { rstatus_t status; bool rack_existed = false; log_debug(LOG_VERB, "gossip_add_node_if_absent : '%.*s'", address->len, address->data); struct gossip_dc * g_dc = dictFetchValue(gn_pool.dict_dc, dc); if (g_dc == NULL) { log_debug(LOG_VERB, "We don't have this datacenter? '%.*s' ", dc->len, dc->data); g_dc = array_push(&gn_pool.datacenters); gossip_dc_init(g_dc, dc); dictAdd(gn_pool.dict_dc, &g_dc->name, g_dc); } else { log_debug(LOG_VERB, "We got a datacenter in dict for '%.*s' ", dc->len, dc->data); } struct gossip_rack *g_rack = dictFetchValue(g_dc->dict_rack, rack); if (g_rack == NULL) { log_debug(LOG_VERB, "We don't have this rack? '%.*s' ", rack->len, rack->data); g_rack = array_push(&g_dc->racks); gossip_rack_init(g_rack, dc, rack); dictAdd(g_dc->dict_rack, &g_rack->name, g_rack); } else { log_debug(LOG_VERB, "We got a rack for '%.*s' ", rack->len, rack->data); } struct string *token_str = token_to_string(token); struct node *g_node = dictFetchValue(g_rack->dict_token_nodes, token_str); if (g_node == NULL) { //never existed log_debug(LOG_VERB, "Node not found! We need to add it"); log_debug(LOG_VERB, "adding node : dc[%.*s]", dc->len, dc->data); log_debug(LOG_VERB, "adding node : g_rack[%.*s]", g_rack->name.len, g_rack->name.data); log_debug(LOG_VERB, "adding node : address[%.*s]", address->len, address->data); log_debug(LOG_VERB, "adding node : ip[%.*s]", ip->len, ip->data); log_debug(LOG_VERB, "adding node : port[%.*s]", port->len, port->data); log_debug(LOG_VERB, "suggested state : %d", state); //print_dyn_token(token, 6); gossip_add_node(sp, dc, g_rack, address, ip, port, token, state); } else if (dictFind(g_rack->dict_name_nodes, ip) != NULL) { log_debug(LOG_VERB, "Node found"); if (!g_node->is_local) { //don't update myself here if (string_compare(&g_node->name, ip) != 0) { log_debug(LOG_WARN, "Replacing an existing token with new info"); gossip_replace_node(sp, g_node, address, ip, state); } else { //update state gossip_update_state(sp, g_node, state, timestamp); } } } else { log_debug(LOG_WARN, "Replacing an existing token with new IP or address"); gossip_replace_node(sp, g_node, address, ip, state); dictAdd(g_rack->dict_name_nodes, &g_node->name, g_node); } //free token_str string_deinit(token_str); dn_free(token_str); return 0; }
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 void rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *msg) { rstatus_t status; struct msg *pmsg; struct conn *c_conn; ASSERT(!s_conn->client && !s_conn->proxy); /* response from server implies that server is ok and heartbeating */ server_ok(ctx, s_conn); /* dequeue peer message (request) from server */ pmsg = TAILQ_FIRST(&s_conn->omsg_q); ASSERT(pmsg != NULL && pmsg->peer == NULL); ASSERT(pmsg->request && !pmsg->done); s_conn->dequeue_outq(ctx, s_conn, pmsg); pmsg->done = 1; /* establish msg <-> pmsg (response <-> request) link */ pmsg->peer = msg; msg->peer = pmsg; #if 1 //shenzheng 2015-6-25 replace server if(pmsg->replace_server) { log_debug(LOG_DEBUG, "msg->error : %d", msg->error); struct server_pool *sp; struct conf_server *cs; struct server *ser_curr, *ser_new; struct conf_pool *cp; struct string host; struct stats_pool *stp; struct stats_server *sts; uint32_t p_idx, s_idx; uint8_t *p, *q, *last; int k = 0; ser_new = s_conn->owner; ASSERT(pmsg->server == ser_new); ASSERT(pmsg->conf_version_curr == ctx->conf_version); while(msg->error == 0 && k < 1) { string_init(&host); sp = ser_new->owner; p_idx = sp->idx; cp = array_get(&(ctx->cf->pool), p_idx); s_idx = ser_new->idx; ser_curr = array_get(&sp->server, s_idx); cs = array_get(&cp->server, s_idx); ASSERT(ser_curr->idx == ser_new->idx); ASSERT(ser_curr->owner == ser_new->owner); ASSERT(ser_curr->weight == ser_new->weight); ASSERT(ser_curr->name_null == ser_new->name_null); p = ser_new->pname.data; last = ser_new->pname.data + ser_new->pname.len; q = nc_strchr(p, last, ':'); if(q == NULL || q >= last || q <= ser_new->pname.data) { log_debug(LOG_DEBUG, "new server address(%s) error", ser_new->pname.data); break; } string_copy(&host, ser_new->pname.data, (uint32_t)(q - ser_new->pname.data)); log_debug(LOG_DEBUG, "new server host : %.*s", host.len, host.data); log_debug(LOG_DEBUG, "new server port : %d", ser_new->port); status = nc_resolve(&host, ser_new->port, &cs->info); if (status != NC_OK) { log_debug(LOG_DEBUG, "resolve new server address error(%d)", status); string_deinit(&host); break; } k ++; while (!TAILQ_EMPTY(&ser_curr->s_conn_q)) { struct conn *conn; ASSERT(ser_curr->ns_conn_q > 0); conn = TAILQ_FIRST(&ser_curr->s_conn_q); conn->err = ERROR_REPLACE_SERVER_TRY_AGAIN; status = event_del_conn(ctx->evb, conn); if (status < 0) { log_warn("event del conn s %d failed, ignored: %s", conn->sd, strerror(errno)); } conn->close(ctx, conn); } log_debug(LOG_DEBUG, "ser_curr->pname : %.*s", ser_curr->pname.len, ser_curr->pname.data); log_debug(LOG_DEBUG, "ser_new->pname : %.*s", ser_new->pname.len, ser_new->pname.data); status = conf_write_back_yaml(ctx, &ser_curr->pname, &ser_new->pname); if(status != NC_OK) { log_warn("warning: conf file write back error, but replace_server %.*s %.*s success.", ser_curr->pname.len, ser_curr->pname.data, ser_new->pname.len, ser_new->pname.data); } string_deinit(&cs->pname); cs->pname = ser_new->pname; string_init(&ser_new->pname); ser_curr->pname = cs->pname; if(ser_curr->name_null) { string_deinit(&cs->name); cs->name = ser_new->name; string_init(&ser_new->name); ser_curr->name = cs->name; stp = array_get(&ctx->stats->current, p_idx); sts = array_get(&stp->server, s_idx); sts->name = ser_curr->name; stp = array_get(&ctx->stats->shadow, p_idx); sts = array_get(&stp->server, s_idx); sts->name = ser_curr->name; stp = array_get(&ctx->stats->sum, p_idx); sts = array_get(&stp->server, s_idx); sts->name = ser_curr->name; } ser_curr->port = ser_new->port; ser_curr->family = cs->info.family; ser_curr->addrlen = cs->info.addrlen; ser_curr->addr = (struct sockaddr *)&cs->info.addr; ser_curr->next_retry = 0; ser_curr->failure_count = 0; string_deinit(&host); while (!TAILQ_EMPTY(&ser_new->s_conn_q)) { struct conn *conn; ASSERT(ser_new->ns_conn_q > 0); conn = TAILQ_FIRST(&ser_new->s_conn_q); ASSERT(conn->replace_server == 1); conn->replace_server = 0; conn->conf_version_curr = -1; conn->ctx = NULL; conn->unref(conn); conn->ref(conn, ser_curr); } } } #endif //shenzheng 2015-6-25 replace server msg->pre_coalesce(msg); c_conn = pmsg->owner; ASSERT(c_conn->client && !c_conn->proxy); if (req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) { status = event_add_out(ctx->evb, c_conn); if (status != NC_OK) { c_conn->err = errno; } } rsp_forward_stats(ctx, s_conn->owner, msg); }
struct server * sentinel_init(uint16_t sentinel_port, char *sentinel_ip) { rstatus_t status; struct server *sentinel; struct string address; struct sockinfo info; char pname[NC_PNAME_MAXLEN]; string_init(&address); sentinel_status = SENTINEL_CONN_DISCONNECTED; sentinel = (struct server *)nc_alloc(sizeof(*sentinel)); if(sentinel == NULL) { goto error; } /* sentinel server don't have owner server pool */ sentinel->owner = NULL; sentinel->ns_conn_q = 0; TAILQ_INIT(&sentinel->s_conn_q); sentinel->addr = NULL; string_init(&sentinel->pname); string_init(&sentinel->name); nc_snprintf(pname, NC_PNAME_MAXLEN, "%s:%d:0", sentinel_ip, sentinel_port); status = string_copy(&sentinel->pname, pname, (uint32_t)(nc_strlen(pname))); if (status != NC_OK) { goto error; } string_copy(&sentinel->name, pname, (uint32_t)(nc_strlen(pname)) - 2); if (status != NC_OK) { goto error; } sentinel->port = sentinel_port; status = string_copy(&address, sentinel_ip, (uint32_t)(nc_strlen(sentinel_ip))); if (status != NC_OK) { goto error; } status = nc_resolve(&address, sentinel_port, &info); if (status != NC_OK) { goto error; } sentinel->family = info.family; sentinel->addrlen = info.addrlen; sentinel->addr = (struct sockaddr*)nc_alloc(info.addrlen); if (sentinel->addr == NULL) { goto error; } nc_memcpy(sentinel->addr, &info.addr, info.addrlen); done: string_deinit(&address); return sentinel; error: sentinel_deinit(sentinel); sentinel = NULL; goto done; }
static rstatus_t sentinel_proc_pub(struct context *ctx, struct msg *msg) { rstatus_t status; struct string pool_name, server_name, server_ip, tmp_string, pub_titile, pub_event; struct mbuf *line_buf; int server_port; string_init(&tmp_string); string_init(&pool_name); string_init(&server_name); string_init(&server_ip); string_set_text(&pub_titile, "pmessage"); string_set_text(&pub_event, "+switch-master"); line_buf = mbuf_get(); if (line_buf == NULL) { goto error; } /* get line in line num 3 for pub titile */ msg_read_line(msg, line_buf, 3); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel pmessage when skip line not used."); goto error; } status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK || string_compare(&pub_titile, &tmp_string)) { log_error("pub title error(lineinfo %.*s)", tmp_string.len, tmp_string.data); goto error; } /* get line in line num 7 for pub event */ msg_read_line(msg, line_buf, 4); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel pmessage when skip line not used."); goto error; } status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK || string_compare(&pub_event, &tmp_string)) { log_error("pub channel error(lineinfo %.*s)", tmp_string.len, tmp_string.data); goto error; } /* get line in line num 9 for pub info */ msg_read_line(msg, line_buf, 2); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel pmessage when skip line not used."); goto error; } /* parse switch master info */ /* get pool name */ status = mbuf_read_string(line_buf, SENTINEL_SERVERNAME_SPLIT, &pool_name); if (status != NC_OK) { log_error("get pool name string failed."); goto error; } /* get server name */ status = mbuf_read_string(line_buf, ' ', &server_name); if (status != NC_OK) { log_error("get server name string failed."); goto error; } /* skip old ip and port string */ status = mbuf_read_string(line_buf, ' ', NULL); if (status != NC_OK) { log_error("skip old ip string failed."); goto error; } status = mbuf_read_string(line_buf, ' ', NULL); if (status != NC_OK) { log_error("skip old port string failed."); goto error; } /* get new server ip string */ status = mbuf_read_string(line_buf, ' ', &server_ip); if (status != NC_OK) { log_error("get new server ip string failed."); goto error; } /* get new server port */ status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK) { log_error("get new server port string failed."); goto error; } server_port = nc_atoi(tmp_string.data, tmp_string.len); if (server_port < 0) { log_error("tanslate server port string to int failed."); goto error; } status = server_switch(ctx, &pool_name, &server_name, &server_ip, server_port); if (status == NC_OK) { conf_rewrite(ctx); } status = NC_OK; done: if (line_buf != NULL) { mbuf_put(line_buf); } string_deinit(&tmp_string); string_deinit(&server_ip); string_deinit(&server_name); string_deinit(&pool_name); return status; error: status = NC_ERROR; goto done; }
static rstatus_t sentinel_proc_acksub(struct context *ctx, struct msg *msg) { rstatus_t status; struct string sub_titile, sub_channel, sub_ok, tmp_string; struct mbuf *line_buf; string_init(&tmp_string); string_set_text(&sub_titile, "psubscribe"); string_set_text(&sub_channel, "+switch-master"); string_set_text(&sub_ok, ":1"); line_buf = mbuf_get(); if (line_buf == NULL) { goto error; } /* get line in line num 3 for sub titile */ msg_read_line(msg, line_buf, 3); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel ack sub when skip line not used."); goto error; } status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK || string_compare(&sub_titile, &tmp_string)) { goto error; } /* get line in line num 5 for sub channel */ msg_read_line(msg, line_buf, 2); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel ack sub when skip line not used."); goto error; } status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK || string_compare(&sub_channel, &tmp_string)) { goto error; } /* get sub status */ msg_read_line(msg, line_buf, 1); if (line_buf == 0) { log_error("read line failed from sentinel ack sub when skip line not used."); goto error; } status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK || string_compare(&sub_ok, &tmp_string)) { goto error; } log_debug(LOG_INFO, "success sub channel %.*s from sentinel", sub_channel.len, sub_channel.data); status = NC_OK; done: if (line_buf != NULL) { mbuf_put(line_buf); } string_deinit(&tmp_string); return status; error: status = NC_ERROR; goto done; }
static rstatus_t sentinel_proc_sentinel_info(struct context *ctx, struct msg *msg) { rstatus_t status; int i, master_num, switch_num; struct string pool_name, server_name, server_ip, tmp_string, sentinel_masters_prefix, master_ok; struct mbuf *line_buf; int server_port; string_init(&tmp_string); string_init(&pool_name); string_init(&server_name); string_init(&server_ip); string_set_text(&sentinel_masters_prefix, "sentinel_masters"); string_set_text(&master_ok, "status=ok"); line_buf = mbuf_get(); if (line_buf == NULL) { goto error; } /* get sentinel master num at line 3 */ msg_read_line(msg, line_buf, 3); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel ack info when skip line not used."); goto error; } status = mbuf_read_string(line_buf, ':', &tmp_string); if (status != NC_OK || string_compare(&sentinel_masters_prefix, &tmp_string)) { goto error; } status = mbuf_read_string(line_buf, CR, &tmp_string); if (status != NC_OK) { goto error; } master_num = nc_atoi(tmp_string.data, tmp_string.len); if (master_num < 0) { log_error("parse master number from sentinel ack info failed."); goto error; } /* skip 3 line in ack info which is not used. */ msg_read_line(msg, line_buf, 3); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel ack info when skip line not used."); goto error; } /* parse master info from sentinel ack info */ switch_num = 0; for (i = 0; i < master_num; i++) { msg_read_line(msg, line_buf, 1); if (mbuf_length(line_buf) == 0) { log_error("read line failed from sentinel ack info when parse master item."); goto error; } log_debug(LOG_INFO, "master item line : %.*s", mbuf_length(line_buf), line_buf->pos); /* skip master item prefix */ status = mbuf_read_string(line_buf, ':', NULL); if (status != NC_OK) { log_error("skip master item prefix failed"); goto error; } /* skip master item server name prefix */ status = mbuf_read_string(line_buf, '=', NULL); if (status != NC_OK) { log_error("skip master item server name prefix failed."); goto error; } /* get server pool name */ status = mbuf_read_string(line_buf, SENTINEL_SERVERNAME_SPLIT, &pool_name); if (status != NC_OK) { log_error("get server pool name failed."); goto error; } /* get server name */ status = mbuf_read_string(line_buf, ',', &server_name); if (status != NC_OK) { log_error("get server name failed."); goto error; } /* get master status */ status = mbuf_read_string(line_buf, ',', &tmp_string); if (status != NC_OK) { log_error("get master status failed."); goto error; } if (string_compare(&master_ok, &tmp_string)) { log_error("master item status is not ok, use it anyway"); } /* skip ip string prefix name */ status = mbuf_read_string(line_buf, '=', NULL); if (status != NC_OK) { log_error("skip master item address prefix failed."); goto error; } /* get server ip string */ status = mbuf_read_string(line_buf, ':', &server_ip); if (status != NC_OK) { log_error("get server ip string failed."); goto error; } /* get server port */ status = mbuf_read_string(line_buf, ',', &tmp_string); if (status != NC_OK) { log_error("get server port string failed."); goto error; } server_port = nc_atoi(tmp_string.data, tmp_string.len); if (server_port < 0) { log_error("tanslate server port string to int failed."); goto error; } status = server_switch(ctx, &pool_name, &server_name, &server_ip, server_port); /* if server is switched, add switch number */ if (status == NC_OK) { switch_num++; } } if (switch_num > 0) { conf_rewrite(ctx); } status = NC_OK; done: if (line_buf != NULL) { mbuf_put(line_buf); } string_deinit(&tmp_string); string_deinit(&pool_name); string_deinit(&server_name); string_deinit(&server_ip); return status; error: status = NC_ERROR; goto done; }
static rstatus_t stats_send_rsp(struct stats *st) { rstatus_t status; int sd; //TODO: move this to an appropriate place that need it. status = stats_make_rsp(st); if (status != DN_OK) { return status; } sd = accept(st->sd, NULL, NULL); if (sd < 0) { log_error("accept on m %d failed: %s", st->sd, strerror(errno)); return DN_ERROR; } struct stats_cmd st_cmd; parse_request(sd, &st_cmd); stats_cmd_t cmd = st_cmd.cmd; log_debug(LOG_VERB, "cmd %d", cmd); if (cmd == CMD_INFO) { log_debug(LOG_VERB, "send stats on sd %d %d bytes", sd, st->buf.len); return stats_http_rsp(sd, st->buf.data, st->buf.len); } else if (cmd == CMD_NORMAL) { st->ctx->dyn_state = NORMAL; return stats_http_rsp(sd, ok.data, ok.len); } else if (cmd == CMD_STANDBY) { st->ctx->dyn_state = STANDBY; return stats_http_rsp(sd, ok.data, ok.len); } else if (cmd == CMD_WRITES_ONLY) { st->ctx->dyn_state = WRITES_ONLY; return stats_http_rsp(sd, ok.data, ok.len); } else if (cmd == CMD_RESUMING) { st->ctx->dyn_state = RESUMING; return stats_http_rsp(sd, ok.data, ok.len); } else if (cmd == CMD_PEER_DOWN || cmd == CMD_PEER_UP || cmd == CMD_PEER_RESET) { log_debug(LOG_VERB, "st_cmd.req_data '%.*s' ", st_cmd.req_data); struct server_pool *sp = array_get(&st->ctx->pool, 0); int i, len; //I think it is ok to keep this simple without a synchronization for (i = 0, len = array_n(&sp->peers); i < len; i++) { struct server *peer = array_get(&sp->peers, i); log_debug(LOG_VERB, "peer '%.*s' ", peer->name); if (string_compare(&st_cmd.req_data, &all) == 0) { log_debug(LOG_VERB, "\t\tSetting peer '%.*s' to state %d due to RESET/ALL command", st_cmd.req_data, cmd); peer->state = RESET; } else if (string_compare(&peer->name, &st_cmd.req_data) == 0) { log_debug(LOG_VERB, "\t\tSetting peer '%.*s' to state %d due to RESET command", st_cmd.req_data, cmd); switch (cmd) { case CMD_PEER_UP: peer->state = NORMAL; break; case CMD_PEER_RESET: peer->state = RESET; break; case CMD_PEER_DOWN: peer->state = DOWN; break; default: peer->state = NORMAL; } break; } } string_deinit(&st_cmd.req_data); } else { log_debug(LOG_VERB, "Unsupported cmd"); } stats_http_rsp(sd, ok.data, ok.len); close(sd); return DN_OK; }
static rstatus_t gossip_pool_each_init(void *elem, void *data) { rstatus_t status; struct server_pool *sp = elem; gn_pool.ctx = sp->ctx; gn_pool.name = &sp->name; gn_pool.idx = sp->idx; gn_pool.g_interval = sp->g_interval; //dictDisableResize(); gn_pool.dict_dc = dictCreate(&string_table_dict_type, NULL); gossip_set_seeds_provider(&sp->seed_provider); uint32_t n_dc = array_n(&sp->datacenters); if (n_dc == 0) return DN_OK; if (n_dc > 0) { status = array_init(&gn_pool.datacenters, n_dc, sizeof(struct gossip_dc)); if (status != DN_OK) { return status; } } //add racks and datacenters uint32_t dc_cnt = array_n(&sp->datacenters); uint32_t dc_index; for(dc_index = 0; dc_index < dc_cnt; dc_index++) { struct datacenter *dc = array_get(&sp->datacenters, dc_index); uint32_t rack_cnt = array_n(&dc->racks); uint32_t rack_index; for(rack_index = 0; rack_index < rack_cnt; rack_index++) { struct rack *rack = array_get(&dc->racks, rack_index); if (dictFind(gn_pool.dict_dc, rack->dc) == NULL) { struct gossip_dc *g_dc = array_push(&gn_pool.datacenters); gossip_dc_init(g_dc, rack->dc); dictAdd(gn_pool.dict_dc, &g_dc->name, g_dc); } struct gossip_dc *g_dc = dictFetchValue(gn_pool.dict_dc, rack->dc); if (dictFind(g_dc->dict_rack, rack->name) == NULL) { log_debug(LOG_VERB, "What?? No rack in Dict for rack : '%.*s'", g_dc->name); struct gossip_rack *g_rack = array_push(&g_dc->racks); gossip_rack_init(g_rack, rack->dc, rack->name); dictAdd(g_dc->dict_rack, &g_rack->name, g_rack); } } } uint32_t i, nelem; for (i = 0, nelem = array_n(&sp->peers); i < nelem; i++) { struct server *peer = array_get(&sp->peers, i); struct gossip_dc *g_dc = dictFetchValue(gn_pool.dict_dc, &peer->dc); struct gossip_rack *g_rack = dictFetchValue(g_dc->dict_rack, &peer->rack); struct node *gnode = array_push(&g_rack->nodes); node_init(gnode); string_copy(&gnode->dc, peer->dc.data, peer->dc.len); string_copy(&gnode->rack, g_rack->name.data, g_rack->name.len); string_copy(&gnode->name, peer->name.data, peer->name.len); string_copy(&gnode->pname, peer->pname.data, peer->pname.len); //ignore the port for now gnode->port = peer->port; gnode->is_local = peer->is_local; if (i == 0) { //Don't override its own state gnode->state = sp->ctx->dyn_state; //likely it is JOINING state gnode->ts = (uint64_t)time(NULL); current_node = gnode; char *b_address = get_broadcast_address(sp); string_deinit(&gnode->name); string_copy(&gnode->name, b_address, dn_strlen(b_address)); } else { gnode->state = DOWN; gnode->ts = 1010101; //make this to be a very aged ts } struct dyn_token *ptoken = array_get(&peer->tokens, 0); copy_dyn_token(ptoken, &gnode->token); //copy socket stuffs g_rack->nnodes++; //add into dicts dictAdd(g_rack->dict_name_nodes, &gnode->name, gnode); dictAdd(g_rack->dict_token_nodes, token_to_string(&gnode->token), gnode); node_count++; } //gossip_debug(); status = gossip_start(sp); if (status != DN_OK) { goto error; } return DN_OK; error: gossip_destroy(sp); return DN_OK; }
char * conf_add_server(struct conf *cf, struct command *cmd, void *conf) { rstatus_t status; struct array *a; struct string *value; struct conf_server *field; uint8_t *p, *q, *start; uint8_t *pname, *addr, *port, *weight, *name; uint32_t k, pnamelen, addrlen, portlen, weightlen, namelen; struct string address; char delim[] = " ::"; string_init(&address); p = conf; a = (struct array *)(p + cmd->offset); field = array_push(a); if (field == NULL) { return CONF_ERROR; } conf_server_init(field); value = array_top(&cf->arg); /* parse "hostname:port:weight [name]" from the end */ p = value->data + value->len - 1; start = value->data; addr = NULL; addrlen = 0; weight = NULL; weightlen = 0; port = NULL; portlen = 0; name = NULL; namelen = 0; for (k = 0; k < sizeof(delim); k++) { q = nc_strrchr(p, start, delim[k]); if (q == NULL) { if (k == 0) { /* * name in "hostname:port:weight [name]" format string is * optional */ continue; } break; } switch (k) { case 0: name = q + 1; namelen = (uint32_t)(p - name + 1); break; case 1: weight = q + 1; weightlen = (uint32_t)(p - weight + 1); break; case 2: port = q + 1; portlen = (uint32_t)(p - port + 1); break; default: NOT_REACHED(); } p = q - 1; } if (k != 3) { return "has an invalid \"hostname:port:weight [name]\" format string"; } pname = value->data; pnamelen = namelen > 0 ? value->len - (namelen + 1) : value->len; status = string_copy(&field->pname, pname, pnamelen); if (status != NC_OK) { array_pop(a); return CONF_ERROR; } addr = start; addrlen = (uint32_t)(p - start + 1); field->weight = nc_atoi(weight, weightlen); if (field->weight < 0) { return "has an invalid weight in \"hostname:port:weight [name]\" format string"; } field->port = nc_atoi(port, portlen); if (field->port < 0 || !nc_valid_port(field->port)) { return "has an invalid port in \"hostname:port:weight [name]\" format string"; } if (name == NULL) { /* * To maintain backward compatibility with libmemcached, we don't * include the port as the part of the input string to the consistent * hashing algorithm, when it is equal to 11211. */ if (field->port == CONF_DEFAULT_KETAMA_PORT) { name = addr; namelen = addrlen; } else { name = addr; namelen = addrlen + 1 + portlen; } } status = string_copy(&field->name, name, namelen); if (status != NC_OK) { return CONF_ERROR; } status = string_copy(&address, addr, addrlen); if (status != NC_OK) { return CONF_ERROR; } status = nc_resolve(&address, field->port, &field->info); if (status != NC_OK) { string_deinit(&address); return CONF_ERROR; } string_deinit(&address); field->valid = 1; return CONF_OK; }