コード例 #1
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);
}
コード例 #2
0
ファイル: nc_request.c プロジェクト: altogother/twemproxy
/*
 * Return true if request is in error, false otherwise
 *
 * A request is in error, if there was an error in receiving response for the
 * given request. A multiget request is in error if there was an error in
 * receiving response for any its fragments.
 */
bool
req_error(struct conn *conn, struct msg *msg)
{
    struct msg *cmsg; /* current message */
    uint64_t id;
    uint32_t nfragment;

    ASSERT(msg->request && req_done(conn, msg));

    if (msg->error) {
        return true;
    }

    id = msg->frag_id;
    if (id == 0) {
        return false;
    }

    if (msg->ferror) {
        /* request has already been marked to be in error */
        return true;
    }

    /* check if any of the fragments of the given request are in error */

    for (cmsg = TAILQ_PREV(msg, msg_tqh, c_tqe);
         cmsg != NULL && cmsg->frag_id == id;
         cmsg = TAILQ_PREV(cmsg, msg_tqh, c_tqe)) {

        if (cmsg->error) {
            goto ferror;
        }
    }

    for (cmsg = TAILQ_NEXT(msg, c_tqe);
         cmsg != NULL && cmsg->frag_id == id;
         cmsg = TAILQ_NEXT(cmsg, c_tqe)) {

        if (cmsg->error) {
            goto ferror;
        }
    }

    return false;

ferror:

    /*
     * Mark all fragments of the given request to be in error to speed up
     * future req_error calls for any of fragments of this request
     */

    msg->ferror = 1;
    nfragment = 1;

    for (cmsg = TAILQ_PREV(msg, msg_tqh, c_tqe);
         cmsg != NULL && cmsg->frag_id == id;
         cmsg = TAILQ_PREV(cmsg, msg_tqh, c_tqe)) {
        cmsg->ferror = 1;
        nfragment++;
    }

    for (cmsg = TAILQ_NEXT(msg, c_tqe);
         cmsg != NULL && cmsg->frag_id == id;
         cmsg = TAILQ_NEXT(cmsg, c_tqe)) {
        cmsg->ferror = 1;
        nfragment++;
    }

    log_debug(LOG_DEBUG, "req from c %d with fid %"PRIu64" and %"PRIu32" "
              "fragments is in error", conn->sd, id, nfragment);

    return true;
}
コード例 #3
0
ファイル: nc_server.c プロジェクト: CoolCloud/twemproxy
void
server_close(struct context *ctx, struct conn *conn)
{
    rstatus_t status;
    struct msg *msg, *nmsg; /* current and next message */
    struct conn *c_conn;    /* peer client connection */

    ASSERT(!conn->client && !conn->proxy);

    server_close_stats(ctx, conn->owner, conn->err, conn->eof,
                       conn->connected);

    if (conn->sd < 0) {
        server_failure(ctx, conn->owner);
        conn->unref(conn);
        conn_put(conn);
        return;
    }

    for (msg = TAILQ_FIRST(&conn->imsg_q); msg != NULL; msg = nmsg) {
        nmsg = TAILQ_NEXT(msg, s_tqe);

        /* dequeue the message (request) from server inq */
        conn->dequeue_inq(ctx, conn, msg);

        /*
         * Don't send any error response, if
         * 1. request is tagged as noreply or,
         * 2. client has already closed its connection
         */
        if (msg->swallow || msg->noreply) {
            log_debug(LOG_INFO, "close s %d swallow req %"PRIu64" len %"PRIu32
                      " type %d", conn->sd, msg->id, msg->mlen, msg->type);
            req_put(msg);
        } else {
            c_conn = msg->owner;
            ASSERT(c_conn->client && !c_conn->proxy);

            msg->done = 1;
            msg->error = 1;
            msg->err = conn->err;

            if (req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) {
                event_add_out(ctx->ep, msg->owner);
            }

            log_debug(LOG_INFO, "close s %d schedule error for req %"PRIu64" "
                      "len %"PRIu32" type %d from c %d%c %s", conn->sd, msg->id,
                      msg->mlen, msg->type, c_conn->sd, conn->err ? ':' : ' ',
                      conn->err ? strerror(conn->err): " ");
        }
    }
    ASSERT(TAILQ_EMPTY(&conn->imsg_q));

    for (msg = TAILQ_FIRST(&conn->omsg_q); msg != NULL; msg = nmsg) {
        nmsg = TAILQ_NEXT(msg, s_tqe);

        /* dequeue the message (request) from server outq */
        conn->dequeue_outq(ctx, conn, msg);

        if (msg->swallow) {
            log_debug(LOG_INFO, "close s %d swallow req %"PRIu64" len %"PRIu32
                      " type %d", conn->sd, msg->id, msg->mlen, msg->type);
            req_put(msg);
        } else {
            c_conn = msg->owner;
            ASSERT(c_conn->client && !c_conn->proxy);

            msg->done = 1;
            msg->error = 1;
            msg->err = conn->err;

            if (req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) {
                event_add_out(ctx->ep, msg->owner);
            }

            log_debug(LOG_INFO, "close s %d schedule error for req %"PRIu64" "
                      "len %"PRIu32" type %d from c %d%c %s", conn->sd, msg->id,
                      msg->mlen, msg->type, c_conn->sd, conn->err ? ':' : ' ',
                      conn->err ? strerror(conn->err): " ");
        }
    }
    ASSERT(TAILQ_EMPTY(&conn->omsg_q));

    msg = conn->rmsg;
    if (msg != NULL) {
        conn->rmsg = NULL;

        ASSERT(!msg->request);
        ASSERT(msg->peer == NULL);

        rsp_put(msg);

        log_debug(LOG_INFO, "close s %d discarding rsp %"PRIu64" len %"PRIu32" "
                  "in error", conn->sd, msg->id, msg->mlen);
    }

    ASSERT(conn->smsg == NULL);

    server_failure(ctx, conn->owner);

    conn->unref(conn);

    status = close(conn->sd);
    if (status < 0) {
        log_error("close s %d failed, ignored: %s", conn->sd, strerror(errno));
    }
    conn->sd = -1;

    conn_put(conn);
}
コード例 #4
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);
}
コード例 #5
0
ファイル: dyn_dnode_request.c プロジェクト: amit-git/dynomite
bool
dnode_req_done(struct conn *conn, struct msg *msg)
{
	ASSERT(!conn->dnode_client && !conn->dnode_server);
	return req_done(conn, msg);
}
コード例 #6
0
ファイル: dyn_response.c プロジェクト: DynomiteDB/dynomite
struct msg *
rsp_send_next(struct context *ctx, struct conn *conn)
{
    rstatus_t status;
    struct msg *rsp, *req; /* response and it's peer request */

    ASSERT_LOG((conn->type == CONN_DNODE_PEER_CLIENT) ||
               (conn->type = CONN_CLIENT), "conn %s", conn_get_type_string(conn));

    req = TAILQ_FIRST(&conn->omsg_q);
    if (req == NULL || (!req->selected_rsp && !req_done(conn, req))) {
        /* nothing is outstanding, initiate close? */
        if (req == NULL && conn->eof) {
            conn->done = 1;
            log_debug(LOG_INFO, "c %d is done", conn->sd);
        }

        status = event_del_out(ctx->evb, conn);
        if (status != DN_OK) {
            conn->err = errno;
        }

        return NULL;
    }

    rsp = conn->smsg;
    if (rsp != NULL) {
        ASSERT(!rsp->request);
        ASSERT(rsp->peer != NULL);
        req = TAILQ_NEXT(rsp->peer, c_tqe);
    }

    if (req == NULL || !req_done(conn, req)) {
        conn->smsg = NULL;
        return NULL;
    }
    ASSERT(req->request && !req->swallow);

    if (req_error(conn, req)) {
        rsp = rsp_make_error(ctx, conn, req);
        if (rsp == NULL) {
            conn->err = errno;
            return NULL;
        }
        rsp->peer = req;
        req->selected_rsp = rsp;
        log_debug(LOG_VERB, "creating new error rsp %p", rsp);
        if (conn->dyn_mode) {
      	  stats_pool_incr(ctx, peer_forward_error);
        } else {
      	  stats_pool_incr(ctx, forward_error);
        }
    } else {
        rsp = req->selected_rsp;
    }
    ASSERT(!rsp->request);

    conn->smsg = rsp;

    if (log_loggable(LOG_VVERB)) {
       log_debug(LOG_VVERB, "send next rsp %"PRIu64" on c %d", rsp->id, conn->sd);
    }

    return rsp;
}
コード例 #7
0
ファイル: dyn_response.c プロジェクト: jongyeol/dynomite
struct msg *
rsp_send_next(struct context *ctx, struct conn *conn)
{
    rstatus_t status;
    struct msg *msg, *pmsg; /* response and it's peer request */

    ASSERT((conn->client && !conn->proxy) || (conn->dnode_client && !conn->dnode_server));

    pmsg = TAILQ_FIRST(&conn->omsg_q);
    if (pmsg == NULL || !req_done(conn, pmsg)) {
        /* nothing is outstanding, initiate close? */
        if (pmsg == NULL && conn->eof) {
            conn->done = 1;
            log_debug(LOG_INFO, "c %d is done", conn->sd);
        }

        status = event_del_out(ctx->evb, conn);
        if (status != DN_OK) {
            conn->err = errno;
        }

        return NULL;
    }

    msg = conn->smsg;
    if (msg != NULL) {
        ASSERT(!msg->request && msg->peer != NULL);
        ASSERT(req_done(conn, msg->peer));
        pmsg = TAILQ_NEXT(msg->peer, c_tqe);
    }

    if (pmsg == NULL || !req_done(conn, pmsg)) {
        conn->smsg = NULL;
        return NULL;
    }
    ASSERT(pmsg->request && !pmsg->swallow);

    if (req_error(conn, pmsg)) {
        msg = rsp_make_error(ctx, conn, pmsg);
        if (msg == NULL) {
            conn->err = errno;
            return NULL;
        }
        msg->peer = pmsg;
        pmsg->peer = msg;
        if (!conn->dyn_mode) {
           stats_pool_incr(ctx, conn->owner, forward_error);
        } else {  //dyn_mode
           stats_pool_incr(ctx, conn->owner, peer_forward_error);
        }
    } else {
        msg = pmsg->peer;
    }
    ASSERT(!msg->request);

    conn->smsg = msg;

    log_debug(LOG_VVERB, "send next rsp %"PRIu64" on c %d", msg->id, conn->sd);

    return msg;
}