int server_data_cmd(int sock, char *cmd, char **buffer) { char recv[RECV_BUFFER]; int n, size, completed; log_debug("server_data_cmd: command '%s'", cmd); if (server_reply(sock, cmd) == -1) { log_error("server_data_cmd: server_reply failed"); return -1; } n = read(sock, recv, sizeof recv); if (n == -1) { log_sys_error("server_data_cmd: read"); return -1; } size = atoi(recv); if (size < 0 || size > MAX_BUFFER) { log_error("server_data_cmd: bad buffer size"); return -1; } *buffer = (char *) malloc(size + 1); if (*buffer == NULL) { log_sys_error("server_data_cmd: malloc"); return -1; } if (server_ok(sock)) { log_error("server_data_cmd: server_ok failed"); return -1; } for (completed = 0; size > completed; completed += n) { n = read(sock, *buffer + completed, size - completed); if (n == -1) { log_sys_error("server_data_cmd: read"); return -1; } } (*buffer)[completed] = 0; if (server_check(sock)) { log_error("server_data_cmd: server_check failed"); return -1; } return 0; }
static int server_exec_cmd(int sock, char *cmd) { int argc = 0; char *argv[MAXARGS]; char *save, *p, *nil; server_function_t *sf; int r; log_debug("server_exec_cmd: %s", cmd); for (nil = cmd; (p = strtok_r(nil, " ", &save)) && argc < MAXARGS; nil = NULL, ++argc) { argv[argc] = p; } if (argc == MAXARGS) { server_reply(sock, "Too many arguments"); log_error("server_exec_cmd: Too many arguments"); return -1; } sf = sht_lookup(&server_function_table, argv[0]); if (sf == NULL) { sf = sht_lookup(&server_function_table, "help"); if (sf == NULL) { log_die(EX_SOFTWARE, "server_exec_cmd: help not found. This is impossible hence fatal."); } } r = sf->sf_callback(sock, argc, argv); switch (r) { case 0: server_reply(sock, "CLOSE"); break; case -1: log_error("server_exec_cmd: %s failed", argv[0]); server_reply(sock, "ERROR"); break; default: server_ok(sock); break; } return r; }
static void rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *msg) { rstatus_t status; struct msg *pmsg; struct msg *req; struct conn *c_conn; uint32_t msgsize; ASSERT(!s_conn->client && !s_conn->proxy); msgsize = msg->mlen; /* response from server implies that server is ok and heartbeating */ server_ok(ctx, s_conn); /* dequeue peer message (request) from server */ pmsg = rsp_get_peer(s_conn, msg); 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; msg->pre_coalesce(msg); c_conn = pmsg->owner; ASSERT(c_conn->client && !c_conn->proxy); req = pmsg->frag_id ? pmsg->frag_owner : pmsg; ASSERT(s_conn->need_sync || req == TAILQ_FIRST(&c_conn->omsg_q)); ASSERT(!s_conn->need_sync || req == pmsg->frag_owner); if (req_done(c_conn, req)) { status = event_add_out(ctx->evb, c_conn); if (status != NC_OK) { c_conn->err = errno; } } rsp_forward_stats(ctx, s_conn->owner, msg, msgsize); }
/* * 将回复发送至客户端 * conn 为与后端 Svr 的链接, msg 为完整的数据 */ static void rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *msg) { rstatus_t status; struct msg *pmsg; struct conn *c_conn; uint32_t msgsize; ASSERT(!s_conn->client && !s_conn->proxy); msgsize = msg->mlen; /* 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; /* 可能需要合并回复 */ /* 这里会将 msg 中的数据清空掉,数据整合至了所属 msg 中 */ msg->pre_coalesce(msg); c_conn = pmsg->owner; ASSERT(c_conn->client && !c_conn->proxy); /* 如果 client 请求数据队列中的头部数据没回复,依旧等待 */ 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, msgsize); }
static void server_rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *rsp) { rstatus_t status; struct msg *req; struct conn *c_conn; ASSERT(s_conn->type == CONN_SERVER); /* response from server implies that server is ok and heartbeating */ server_ok(ctx, s_conn); /* dequeue peer message (request) from server */ req = TAILQ_FIRST(&s_conn->omsg_q); ASSERT(req != NULL && req->peer == NULL); ASSERT(req->request && !req->done); conn_dequeue_outq(ctx, s_conn, req); req->done = 1; /* establish rsp <-> req (response <-> request) link */ req->peer = rsp; rsp->peer = req; rsp->pre_coalesce(rsp); c_conn = req->owner; log_info("c_conn %p %d:%d <-> %d:%d", c_conn, req->id, req->parent_id, rsp->id, rsp->parent_id); ASSERT((c_conn->type == CONN_CLIENT) || (c_conn->type == CONN_DNODE_PEER_CLIENT)); server_rsp_forward_stats(ctx, s_conn->owner, rsp); // this should really be the message's response handler be doing it if (req_done(c_conn, req)) { // handler owns the response now status = conn_handle_response(c_conn, c_conn->type == CONN_CLIENT ? req->id : req->parent_id, rsp); IGNORE_RET_VAL(status); } }
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); /* * msg <-> pmsg (response <-> request) link has been established * in rsp_filter */ pmsg = msg->peer; s_conn->dequeue_outq(ctx, s_conn, pmsg); pmsg->done = 1; msg->pre_coalesce(msg); if (msg->pre_rsp_forward != NULL && msg->pre_rsp_forward(ctx, s_conn, msg) != NC_OK) { return; } 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); }
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; log_error("AT peer matching %d to %d", msg->id, pmsg->id); /* establish msg <-> pmsg (response <-> request) link */ pmsg->peer = msg; msg->peer = pmsg; 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); }
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); }
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; /* * Readjust responses of fragmented messages by not including the end * marker for all but the last response * * Valid responses for a fragmented requests are MSG_RSP_VALUE or, * MSG_RSP_END. For an invalid response, we send out SERVER_ERRROR with * EINVAL errno */ if (pmsg->frag_id != 0) { if (msg->type != MSG_RSP_VALUE && msg->type != MSG_RSP_END) { pmsg->error = 1; pmsg->err = EINVAL; } else if (!pmsg->last_fragment) { ASSERT(msg->end != NULL); for (;;) { struct mbuf *mbuf; mbuf = STAILQ_LAST(&msg->mhdr, mbuf, next); ASSERT(mbuf != NULL); /* * We cannot assert that end marker points to the last mbuf * Consider a scenario where end marker points to the * penultimate mbuf and the last mbuf only contains spaces * and CRLF: mhdr -> [...END] -> [\r\n] */ if (msg->end >= mbuf->pos && msg->end < mbuf->last) { /* end marker is within this mbuf */ msg->mlen -= (uint32_t)(mbuf->last - msg->end); mbuf->last = msg->end; break; } /* end marker is not in this mbuf */ msg->mlen -= mbuf_length(mbuf); mbuf_remove(&msg->mhdr, mbuf); mbuf_put(mbuf); } } } 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->ep, c_conn); if (status != NC_OK) { c_conn->err = errno; } } rsp_forward_stats(ctx, s_conn->owner, msg); }