コード例 #1
0
ファイル: nc_response.c プロジェクト: bigbes/twemproxy
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);
}
コード例 #2
0
/*
 * 将回复发送至客户端
 * 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);
}
コード例 #3
0
ファイル: nc_response.c プロジェクト: crask/redisproxy
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);
}
コード例 #4
0
ファイル: nc_response.c プロジェクト: Funnerator/twemproxy
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);
}
コード例 #5
0
ファイル: nc_response.c プロジェクト: 7758285/twemproxy-vip
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);
}
コード例 #6
0
ファイル: nc_response.c プロジェクト: alepharchives/twemproxy
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);
}