Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
void
dict_string_destructor(void *privdata, void *val)
{
    DICT_NOTUSED(privdata);

    struct string *s = val;
    string_deinit(s);
    dn_free(s);
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
/* 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);
}
Beispiel #12
0
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;
}
Beispiel #13
0
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);
}
Beispiel #14
0
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;
}
Beispiel #15
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;
}
Beispiel #16
0
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);
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
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;

}
Beispiel #23
0
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;
}