void conf_destroy(struct conf *cf) { while (array_n(&cf->arg) != 0) { conf_pop_scalar(cf); } array_deinit(&cf->arg); while (array_n(&cf->pool) != 0) { conf_pool_deinit(array_pop(&cf->pool)); } array_deinit(&cf->pool); nc_free(cf); }
void proxy_deinit(struct context *ctx) { rstatus_t status; ASSERT(array_n(&ctx->pool) != 0); status = array_each(&ctx->pool, proxy_each_deinit, NULL); if (status != NC_OK) { return; } log_debug(LOG_VVERB, "deinit proxy with %"PRIu32" pools", array_n(&ctx->pool)); }
static void conf_dump(struct conf *cf) { uint32_t i, j, npool, nserver; struct conf_pool *cp; struct string *s; npool = array_n(&cf->pool); if (npool == 0) { return; } log_debug(LOG_VVERB, "%"PRIu32" pools in configuration file '%s'", npool, cf->fname); for (i = 0; i < npool; i++) { cp = array_get(&cf->pool, i); log_debug(LOG_VVERB, "%.*s", cp->name.len, cp->name.data); log_debug(LOG_VVERB, " listen: %.*s", cp->listen.pname.len, cp->listen.pname.data); log_debug(LOG_VVERB, " timeout: %d", cp->timeout); log_debug(LOG_VVERB, " backlog: %d", cp->backlog); log_debug(LOG_VVERB, " hash: %d", cp->hash); log_debug(LOG_VVERB, " hash_tag: \"%.*s\"", cp->hash_tag.len, cp->hash_tag.data); log_debug(LOG_VVERB, " distribution: %d", cp->distribution); log_debug(LOG_VVERB, " client_connections: %d", cp->client_connections); log_debug(LOG_VVERB, " redis: %d", cp->redis); log_debug(LOG_VVERB, " preconnect: %d", cp->preconnect); log_debug(LOG_VVERB, " auto_eject_hosts: %d", cp->auto_eject_hosts); log_debug(LOG_VVERB, " server_connections: %d", cp->server_connections); log_debug(LOG_VVERB, " server_retry_timeout: %d", cp->server_retry_timeout); log_debug(LOG_VVERB, " server_failure_limit: %d", cp->server_failure_limit); nserver = array_n(&cp->server); log_debug(LOG_VVERB, " servers: %"PRIu32"", nserver); for (j = 0; j < nserver; j++) { s = array_get(&cp->server, j); log_debug(LOG_VVERB, " %.*s", s->len, s->data); } } }
void ffi_pool_clear_servers(struct server_pool *pool) { uint32_t n = array_n(&pool->ffi_server); while (n--) { array_pop(&pool->ffi_server); } }
rstatus_t gossip_msg_peer_update(void *rmsg) { rstatus_t status; struct ring_msg *msg = rmsg; struct server_pool *sp = msg->sp; //TODOs: need to fix this as it is breaking warm bootstrap current_node->state = NORMAL; sp->ctx->dyn_state = NORMAL; int i=0; int n = array_n(&msg->nodes); for(i=0; i<n; i++) { struct node *node = array_get(&msg->nodes, i); log_debug(LOG_VVERB, "Processing msg gossip_msg_peer_update '%.*s'", node->name.len, node->name.data); log_debug(LOG_VVERB, "Processing gossip_msg_peer_update : datacenter '%.*s'", node->dc.len, node->dc.data); log_debug(LOG_VVERB, "Processing gossip_msg_peer_update : rack '%.*s'", node->rack.len, node->rack.data); log_debug(LOG_VVERB, "Processing gossip_msg_peer_update : name '%.*s'", node->name.len, node->name.data); log_debug(LOG_VVERB, "State %d", node->state); print_dyn_token(&node->token, 10); status = gossip_add_node_if_absent(sp, &node->dc, &node->rack, &node->name, &node->name, (node->port == 8101)? &PEER_PORT : &PEER_SSL_PORT, &node->token, node->state, node->ts); } gossip_debug(); return status; }
static int conf_validate_group(struct conf *cf, struct conf_pool *cp) { uint32_t i, n; bool valid; n = array_n(&cp->groups); if (n == 0) { log_error("conf: pool '%.*s' has no groups", cp->name.len, cp->name.data); return NC_ERROR; } array_sort(&cp->groups, conf_group_name_cmp); for (valid = true, i = 0; i < n -1; i++) { struct string *s1, *s2; s1 = array_get(&cp->groups, i); s2 = array_get(&cp->groups, i + 1); if (string_compare(s1, s2) == 0) { log_error("conf: pool '%.*s' has group with same name '%.*s'", cp->name.len, cp->name.data, s1->len, s1->data); valid = false; break; } } if (!valid) { return NC_ERROR; } return NC_OK; }
static void req_forward_remote_dc(struct context *ctx, struct conn *c_conn, struct msg *msg, struct mbuf *orig_mbuf, uint8_t *key, uint32_t keylen, struct datacenter *dc) { uint32_t rack_cnt = array_n(&dc->racks); if (rack_cnt == 0) return; struct rack *rack = dc->preselected_rack_for_replication; if (rack == NULL) rack = array_get(&dc->racks, 0); struct msg *rack_msg = msg_get(c_conn, msg->request, __FUNCTION__); if (rack_msg == NULL) { log_debug(LOG_VERB, "whelp, looks like yer screwed now, buddy. no inter-rack messages for you!"); msg_put(rack_msg); return; } msg_clone(msg, orig_mbuf, rack_msg); log_info("msg (%d:%d) clone to remote rack msg (%d:%d)", msg->id, msg->parent_id, rack_msg->id, rack_msg->parent_id); rack_msg->swallow = true; if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "forwarding request to conn '%s' on rack '%.*s'", dn_unresolve_peer_desc(c_conn->sd), rack->name->len, rack->name->data); } remote_req_forward(ctx, c_conn, rack_msg, rack, key, keylen); }
//把每个server_pool对应的name信息赋值给stats_server->name,同时赋值metric //stats_pool->server, server_pool->server也就是大server配置中的server:配置列表 static rstatus_t stats_server_map(struct array *stats_server, struct array *server) { rstatus_t status; uint32_t i, nserver; nserver = array_n(server); ASSERT(nserver != 0); status = array_init(stats_server, nserver, sizeof(struct stats_server)); if (status != NC_OK) { return status; } for (i = 0; i < nserver; i++) { //配置文件中有多少个server,这里就需要赋值多少次 struct server *s = array_get(server, i); struct stats_server *sts = array_push(stats_server); status = stats_server_init(sts, s); //对stats_server中的每一个metric数组进行stats_server_codec填充 if (status != NC_OK) { return status; } } log_debug(LOG_VVVERB, "map %"PRIu32" stats servers", nserver); return NC_OK; }
struct rack * server_get_rack(struct server_pool *pool, struct string *rackname, struct string *dcname) { uint32_t i, len; for (i = 0, len = array_n(&pool->racks); i < len; i++) { struct rack *rack = (struct rack *) array_get(&pool->racks, i); ASSERT(rack != NULL); ASSERT(rack->name != NULL); //TODOs: use dict for fast access/check-up if (string_compare(rack->name, rackname) == 0 && string_compare(rack->dc, dcname) == 0) { //log_debug(LOG_VERB, "server_get_rack : Rack name : '%.*s'", rack->name->len, rack->name->data); //log_debug(LOG_VERB, "server_get_rack : Rack's DC name : '%.*s'", rack->dc->len, rack->dc->data); //log_debug(LOG_VERB, "server_get_rack : Input's Rack name : '%.*s'", rackname->len, rackname->data); //log_debug(LOG_VERB, "server_get_rack : Input's DC name : '%.*s'", dcname->len, dcname->data); //log_debug(LOG_VERB, "rack->ncontinuum == %d ", rack->ncontinuum); //log_debug(LOG_VERB, "rack->nserver_continuum == %d ", rack->nserver_continuum); return rack; } } //log_debug(LOG_VERB, "There is no rack associated with the name '%.*s' ", rackname->len, rackname->data); return NULL; }
rstatus_t proxy_each_init(void *elem, void *data) { rstatus_t status; struct server_pool *pool = elem; struct conn *p; p = conn_get_proxy(pool); if (p == NULL) { return NC_ENOMEM; } status = proxy_listen(pool->ctx, p); if (status != NC_OK) { p->close(pool->ctx, p); return status; } log_debug(LOG_NOTICE, "p %d listening on '%.*s' in %s pool %"PRIu32" '%.*s'" " with %"PRIu32" servers", p->sd, pool->addrstr.len, pool->addrstr.data, pool->redis ? "redis" : "memcache", pool->idx, pool->name.len, pool->name.data, array_n(&pool->server)); return NC_OK; }
struct datacenter * server_get_dc(struct server_pool *pool, struct string *dcname) { struct datacenter *dc; uint32_t i, len; if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "server_get_dc pool '%.*s'", dcname->len, dcname->data); } for (i = 0, len = array_n(&pool->datacenters); i < len; i++) { dc = (struct datacenter *) array_get(&pool->datacenters, i); ASSERT(dc != NULL); ASSERT(dc->name != NULL); if (string_compare(dc->name, dcname) == 0) { return dc; } } dc = array_push(&pool->datacenters); dc_init(dc); string_copy(dc->name, dcname->data, dcname->len); if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "server_get_dc pool about to exit '%.*s'", dc->name->len, dc->name->data); } return dc; }
static void stats_aggregate_metric(struct array *dst, struct array *src) { uint32_t i; for (i = 0; i < array_n(src); i++) { struct stats_metric *stm1, *stm2; stm1 = array_get(src, i); stm2 = array_get(dst, i); ASSERT(stm1->type == stm2->type); switch (stm1->type) { case STATS_COUNTER: stm2->value.counter += stm1->value.counter; break; case STATS_GAUGE: stm2->value.counter += stm1->value.counter; break; case STATS_TIMESTAMP: if (stm1->value.timestamp) { stm2->value.timestamp = stm1->value.timestamp; } break; default: NOT_REACHED(); } } }
void conf_value_destroy(conf_value *cv) { conf_value **cv_sub; if(cv == NULL){ return; } if(cv->type == CONF_VALUE_UNKNOW){ rmt_free(cv); return; }else if(cv->type == CONF_VALUE_STRING){ if(cv->value != NULL){ sdsfree(cv->value); } }else if(cv->type == CONF_VALUE_ARRAY){ if(cv->value != NULL){ while(array_n(cv->value) > 0){ cv_sub = array_pop(cv->value); conf_value_destroy(*cv_sub); } array_destroy(cv->value); } }else{ NOT_REACHED(); } rmt_free(cv); }
static rstatus_t stats_server_map(struct array *stats_server, struct array *server) { rstatus_t status; uint32_t i, nserver; nserver = array_n(server); ASSERT(nserver != 0); status = array_init(stats_server, nserver, sizeof(struct stats_server)); if (status != NC_OK) { return status; } for (i = 0; i < nserver; i++) { struct server *s = array_get(server, i); struct stats_server *sts = array_push(stats_server); status = stats_server_init(sts, s); if (status != NC_OK) { return status; } } log_debug(LOG_VVVERB, "map %"PRIu32" stats servers", nserver); return NC_OK; }
static rstatus_t stats_pool_map(struct array *stats_pool, struct array *server_pool) { rstatus_t status; uint32_t i, npool; npool = array_n(server_pool); ASSERT(npool != 0); status = array_init(stats_pool, npool, sizeof(struct stats_pool)); if (status != NC_OK) { return status; } for (i = 0; i < npool; i++) { struct server_pool *sp = array_get(server_pool, i); struct stats_pool *stp = array_push(stats_pool); status = stats_pool_init(stp, sp); if (status != NC_OK) { return status; } } log_debug(LOG_VVVERB, "map %"PRIu32" stats pools", npool); return NC_OK; }
void server_pool_deinit(struct array *server_pool) { uint32_t i, npool; for (i = 0, npool = array_n(server_pool); i < npool; i++) { struct server_pool *sp; sp = array_pop(server_pool); ASSERT(sp->p_conn == NULL); ASSERT(TAILQ_EMPTY(&sp->c_conn_q) && sp->nc_conn_q == 0); if (sp->continuum != NULL) { nc_free(sp->continuum); sp->ncontinuum = 0; sp->nserver_continuum = 0; sp->nlive_server = 0; } server_deinit(&sp->server); log_debug(LOG_DEBUG, "deinit pool %"PRIu32" '%.*s'", sp->idx, sp->name.len, sp->name.data); } array_deinit(server_pool); log_debug(LOG_DEBUG, "deinit %"PRIu32" pools", npool); }
int server_pools_idx(struct array *pools, uint8_t *pool_name, uint32_t namelen) { uint32_t idx; uint32_t len; uint8_t find = 0; struct server_pool *sp; for (idx = 0; idx < array_n(pools); idx ++) { sp = array_get(pools, idx); len = MIN(sp->name.len, namelen); if (memcmp(sp->name.data, pool_name, len) == 0) { find = 1; break; } } if (!find) { return -1; } return (int)idx; }
static uint32_t server_pool_hash(struct server_pool *pool, uint8_t *key, uint32_t keylen) { ASSERT(array_n(&pool->server) != 0); ASSERT(key != NULL); if (array_n(&pool->server) == 1) { return 0; } if (keylen == 0) { return 0; } return pool->key_hash((char *)key, keylen); }
static rstatus_t conf_parse(struct conf *cf) { rstatus_t status; ASSERT(cf->sound && !cf->parsed); ASSERT(array_n(&cf->arg) == 0); status = conf_begin_parse(cf); if (status != NC_OK) { return status; } status = conf_parse_core(cf, NULL); if (status != NC_OK) { return status; } status = conf_end_parse(cf); if (status != NC_OK) { return status; } cf->parsed = 1; return NC_OK; }
void dnode_peer_pool_deinit(struct array *server_pool) { uint32_t i, npool; for (i = 0, npool = array_n(server_pool); i < npool; i++) { struct server_pool *sp; sp = array_pop(server_pool); ASSERT(sp->p_conn == NULL); //fixe me to use different variables ASSERT(TAILQ_EMPTY(&sp->c_conn_q) && sp->dn_conn_q == 0); dnode_peer_deinit(&sp->peers); array_each(&sp->racks, rack_destroy, NULL); sp->nlive_server = 0; log_debug(LOG_DEBUG, "dyn: deinit peer pool %"PRIu32" '%.*s'", sp->idx, sp->name.len, sp->name.data); } //array_deinit(server_pool); log_debug(LOG_DEBUG, "deinit %"PRIu32" peer pools", npool); }
rstatus_t server_pool_run(struct server_pool *pool) { ASSERT(array_n(&pool->server) != 0); switch (pool->dist_type) { case DIST_KETAMA: return ketama_update(pool); case DIST_VNODE: //return vnode_update(pool); break; case DIST_MODULA: return modula_update(pool); case DIST_RANDOM: return random_update(pool); case DIST_SINGLE: return DN_OK; default: NOT_REACHED(); return DN_ERROR; } return DN_OK; }
static void conf_pool_dump(conf_pool *cp, int log_level) { uint32_t j, nserver; sds *s; if(cp == NULL){ return; } log_debug(log_level, " type : %d", cp->type); log_debug(log_level, " hash : %d", cp->hash); log_debug(log_level, " hash_tag : %s", cp->hash_tag); log_debug(log_level, " distribution : %d", cp->distribution); log_debug(log_level, " redis_auth : %s", cp->redis_auth); log_debug(log_level, " redis_db : %d", cp->redis_db); log_debug(log_level, " timeout : %d", cp->timeout); log_debug(log_level, " backlog : %d", cp->backlog); nserver = array_n(cp->servers); log_debug(log_level, " servers: %"PRIu32"", nserver); for (j = 0; j < nserver; j++) { s = array_get(cp->servers, j); log_debug(log_level, " %.*s", sdslen(*s), *s); } }
/* * Post-coalesce handler is invoked when the message is a response to * the fragmented multi vector request - 'get' or 'gets' and all the * responses to the fragmented request vector has been received and * the fragmented request is consider to be done */ void memcache_post_coalesce(struct msg *request) { struct msg *response = request->peer; struct msg *sub_msg; uint32_t i; rstatus_t status; ASSERT(!response->request); ASSERT(request->request && (request->frag_owner == request)); if (request->error || request->ferror) { response->owner->err = 1; return; } for (i = 0; i < array_n(request->keys); i++) { /* for each key */ sub_msg = request->frag_seq[i]->peer; /* get it's peer response */ if (sub_msg == NULL) { response->owner->err = 1; return; } status = memcache_copy_bulk(response, sub_msg); if (status != NC_OK) { response->owner->err = 1; return; } } /* append END\r\n */ status = msg_append(response, (uint8_t *)"END\r\n", 5); if (status != NC_OK) { response->owner->err = 1; return; } }
static void req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg) { rstatus_t status; struct conn *s_conn; struct server_pool *pool; uint8_t *key; uint32_t keylen; struct keypos *kpos; ASSERT(c_conn->client && !c_conn->proxy); /* enqueue message (request) into client outq, if response is expected */ if (!msg->noreply) { c_conn->enqueue_outq(ctx, c_conn, msg); } pool = c_conn->owner; ASSERT(array_n(msg->keys) > 0); kpos = array_get(msg->keys, 0); key = kpos->start; keylen = (uint32_t)(kpos->end - kpos->start); s_conn = server_pool_conn(ctx, c_conn->owner, key, keylen); if (s_conn == NULL) { req_forward_error(ctx, c_conn, msg); return; } ASSERT(!s_conn->client && !s_conn->proxy); /* enqueue the message (request) into server inq */ if (TAILQ_EMPTY(&s_conn->imsg_q)) { status = event_add_out(ctx->evb, s_conn); if (status != NC_OK) { req_forward_error(ctx, c_conn, msg); s_conn->err = errno; return; } } if (s_conn->need_auth) { status = msg->add_auth(ctx, c_conn, s_conn); if (status != NC_OK) { req_forward_error(ctx, c_conn, msg); s_conn->err = errno; return; } } s_conn->enqueue_inq(ctx, s_conn, msg); req_forward_stats(ctx, s_conn->owner, msg); log_debug(LOG_VERB, "forward from c %d to s %d req %"PRIu64" len %"PRIu32 " type %d with key '%.*s'", c_conn->sd, s_conn->sd, msg->id, msg->mlen, msg->type, keylen, key); }
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; }
rstatus_t proxy_init(struct context *ctx) { //为alpha等大server的bind创建套接字并接收客户端连接 rstatus_t status; ASSERT(array_n(&ctx->pool) != 0); status = array_each(&ctx->pool, proxy_each_init, NULL); if (status != NC_OK) { proxy_deinit(ctx); return status; } log_debug(LOG_VVERB, "init proxy with %"PRIu32" pools", array_n(&ctx->pool)); return NC_OK; }
bool _ShaderNode_test_input_link(const char* _file, euint32 _line, ShaderNode _sn, ShaderObject _so) { euint n = array_n(_sn->input_links); euint max = array_n(_sn->input_param_table); if (n >= max) return false; ShaderObject obj = _sn->input_param_table[n]; if (!ShaderObject_equal(obj, _so)) { elog("%s %d invalid input link", _file, _line); return false; } else { return true; } }
rstatus_t proxy_init(struct context *ctx) { rstatus_t status; ASSERT(array_n(&ctx->pool) != 0); status = array_each(&ctx->pool, proxy_each_init, NULL); if (status != DN_OK) { proxy_deinit(ctx); return status; } log_debug(LOG_VVERB, "init proxy with %"PRIu32" pools", array_n(&ctx->pool)); return DN_OK; }
static rstatus_t conf_validate_server(struct conf *cf, struct conf_pool *cp) { uint32_t i, nserver; bool valid; nserver = array_n(&cp->server); if (nserver == 0) { log_error("conf: pool '%.*s' has no servers", cp->name.len, cp->name.data); return NC_ERROR; } /* * Disallow duplicate servers - servers with identical "host:port:weight" * or "name" combination are considered as duplicates */ array_sort(&cp->server, conf_server_pname_cmp); for (valid = true, i = 0; i < nserver - 1; i++) { struct conf_server *cs1, *cs2; cs1 = array_get(&cp->server, i); cs2 = array_get(&cp->server, i + 1); if (string_compare(&cs1->pname, &cs2->pname) == 0) { log_error("conf: pool '%.*s' has servers with same name '%.*s'", cp->name.len, cp->name.data, cs1->pname.len, cs1->pname.data); valid = false; break; } } if (!valid) { return NC_ERROR; } array_sort(&cp->server, conf_server_name_cmp); for (valid = true, i = 0; i < nserver - 1; i++) { struct conf_server *cs1, *cs2; cs1 = array_get(&cp->server, i); cs2 = array_get(&cp->server, i + 1); if (string_compare(&cs1->name, &cs2->name) == 0) { log_error("conf: pool '%.*s' has servers with same name '%.*s'", cp->name.len, cp->name.data, cs1->name.len, cs1->name.data); valid = false; break; } } if (!valid) { return NC_ERROR; } return NC_OK; }
void FunctionClosures_execute(ParserEnv* e, FunctionClosures _self) { e->curt_func = _self; int n = (int)array_n(_self->cmds); for (_self->cmd_cnt = 0; _self->cmd_cnt < n; _self->cmd_cnt++) { CommandClosures cc = _self->cmds[_self->cmd_cnt]; CommandClosures_execute(e, cc); } }