src/session.c
static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
{
	struct persist_rule *prst_rule;

	req->analysers &= ~an_bit;
	req->analyse_exp = TICK_ETERNITY;

	DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
		now_ms, __FUNCTION__,
		s,
		req,
		req->rex, req->wex,
		req->flags,
		req->buf->i,
		req->analysers);

	/* now check whether we have some switching rules for this request */
	if (!(s->flags & SN_BE_ASSIGNED)) {
		struct switching_rule *rule;

		list_for_each_entry(rule, &s->fe->switching_rules, list) {
			int ret;

			ret = acl_exec_cond(rule->cond, s->fe, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
			ret = acl_pass(ret);
			if (rule->cond->pol == ACL_COND_UNLESS)
				ret = !ret;

			if (ret) {
				if (!session_set_backend(s, rule->be.backend))
					goto sw_failed;
				break;
			}
		}

		/* To ensure correct connection accounting on the backend, we
		 * have to assign one if it was not set (eg: a listen). This
		 * measure also takes care of correctly setting the default
		 * backend if any.
		 */
		if (!(s->flags & SN_BE_ASSIGNED))
			if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
				goto sw_failed;
	}

	/* we don't want to run the TCP or HTTP filters again if the backend has not changed */
	if (s->fe == s->be) {
		s->req->analysers &= ~AN_REQ_INSPECT_BE;
		s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
	}

	/* as soon as we know the backend, we must check if we have a matching forced or ignored
	 * persistence rule, and report that in the session.
	 */
	list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
		int ret = 1;

		if (prst_rule->cond) {
	                ret = acl_exec_cond(prst_rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
			ret = acl_pass(ret);
			if (prst_rule->cond->pol == ACL_COND_UNLESS)
				ret = !ret;
		}

		if (ret) {
			/* no rule, or the rule matches */
			if (prst_rule->type == PERSIST_TYPE_FORCE) {
				s->flags |= SN_FORCE_PRST;
			} else {
				s->flags |= SN_IGNORE_PRST;
			}
			break;
		}
	}

	return 1;

 sw_failed:
	/* immediately abort this request in case of allocation failure */
	channel_abort(s->req);
	channel_abort(s->rep);

	if (!(s->flags & SN_ERR_MASK))
		s->flags |= SN_ERR_RESOURCE;
	if (!(s->flags & SN_FINST_MASK))
		s->flags |= SN_FINST_R;

	s->txn.status = 500;
	s->req->analysers = 0;
	s->req->analyse_exp = TICK_ETERNITY;
	return 0;
}
/* This stream analyser checks the switching rules and changes the backend
 * if appropriate. The default_backend rule is also considered, then the
 * target backend's forced persistence rules are also evaluated last if any.
 * It returns 1 if the processing can continue on next analysers, or zero if it
 * either needs more data or wants to immediately abort the request.
 */
This stream analyser checks the switching rules and changes the backend
if appropriate. The default_backend rule is also considered, then the
target backend's forced persistence rules are also evaluated last if any.
It returns 1 if the processing can continue on next analysers, or zero if it
either needs more data or wants to immediately abort the request.
This stream analyser checks the switching rules and changes the backend if appropriate . The default_backend rule is also considered then the target backend ' s forced persistence rules are also evaluated last if any . It returns 1 if the processing can continue on next analysers or zero if it either needs more data or wants to immediately abort the request .
static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
{
	struct persist_rule *prst_rule;
	req->analysers &= ~an_bit;
	req->analyse_exp = TICK_ETERNITY;
	DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
		now_ms, __FUNCTION__,
		s,
		req,
		req->rex, req->wex,
		req->flags,
		req->buf->i,
		req->analysers);
	if (!(s->flags & SN_BE_ASSIGNED)) {
		struct switching_rule *rule;
		list_for_each_entry(rule, &s->fe->switching_rules, list) {
			int ret;
			ret = acl_exec_cond(rule->cond, s->fe, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
			ret = acl_pass(ret);
			if (rule->cond->pol == ACL_COND_UNLESS)
				ret = !ret;
			if (ret) {
				if (!session_set_backend(s, rule->be.backend))
					goto sw_failed;
				break;
			}
		}
		if (!(s->flags & SN_BE_ASSIGNED))
			if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
				goto sw_failed;
	}
	if (s->fe == s->be) {
		s->req->analysers &= ~AN_REQ_INSPECT_BE;
		s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
	}
	list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
		int ret = 1;
		if (prst_rule->cond) {
	                ret = acl_exec_cond(prst_rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
			ret = acl_pass(ret);
			if (prst_rule->cond->pol == ACL_COND_UNLESS)
				ret = !ret;
		}
		if (ret) {
			if (prst_rule->type == PERSIST_TYPE_FORCE) {
				s->flags |= SN_FORCE_PRST;
			} else {
				s->flags |= SN_IGNORE_PRST;
			}
			break;
		}
	}
	return 1;
 sw_failed:
	channel_abort(s->req);
	channel_abort(s->rep);
	if (!(s->flags & SN_ERR_MASK))
		s->flags |= SN_ERR_RESOURCE;
	if (!(s->flags & SN_FINST_MASK))
		s->flags |= SN_FINST_R;
	s->txn.status = 500;
	s->req->analysers = 0;
	s->req->analyse_exp = TICK_ETERNITY;
	return 0;
}
static int process_switching_rules ( struct session * s , struct channel * req , int an_bit ) { struct persist_rule * prst_rule ; req -> analysers &= ~ an_bit ; req -> analyse_exp = TICK_ETERNITY ; DPRINTF ( stderr , " \n " , now_ms , __FUNCTION__ , s , req , req -> rex , req -> wex , req -> flags , req -> buf -> i , req -> analysers ) ; if ( ! ( s -> flags & SN_BE_ASSIGNED ) ) { struct switching_rule * rule ; list_for_each_entry ( rule , & s -> fe -> switching_rules , list ) { int ret ; ret = acl_exec_cond ( rule -> cond , s -> fe , s , & s -> txn , SMP_OPT_DIR_REQ | SMP_OPT_FINAL ) ; ret = acl_pass ( ret ) ; if ( rule -> cond -> pol == ACL_COND_UNLESS ) ret = ! ret ; if ( ret ) { if ( ! session_set_backend ( s , rule -> be . backend ) ) goto sw_failed ; break ; } } if ( ! ( s -> flags & SN_BE_ASSIGNED ) ) if ( ! session_set_backend ( s , s -> fe -> defbe . be ? s -> fe -> defbe . be : s -> be ) ) goto sw_failed ; } if ( s -> fe == s -> be ) { s -> req -> analysers &= ~ AN_REQ_INSPECT_BE ; s -> req -> analysers &= ~ AN_REQ_HTTP_PROCESS_BE ; } list_for_each_entry ( prst_rule , & s -> be -> persist_rules , list ) { int ret = 1 ; if ( prst_rule -> cond ) { ret = acl_exec_cond ( prst_rule -> cond , s -> be , s , & s -> txn , SMP_OPT_DIR_REQ | SMP_OPT_FINAL ) ; ret = acl_pass ( ret ) ; if ( prst_rule -> cond -> pol == ACL_COND_UNLESS ) ret = ! ret ; } if ( ret ) { if ( prst_rule -> type == PERSIST_TYPE_FORCE ) { s -> flags |= SN_FORCE_PRST ; } else { s -> flags |= SN_IGNORE_PRST ; } break ; } } return 1 ; sw_failed : channel_abort ( s -> req ) ; channel_abort ( s -> rep ) ; if ( ! ( s -> flags & SN_ERR_MASK ) ) s -> flags |= SN_ERR_RESOURCE ; if ( ! ( s -> flags & SN_FINST_MASK ) ) s -> flags |= SN_FINST_R ; s -> txn . status = 500 ; s -> req -> analysers = 0 ; s -> req -> analyse_exp = TICK_ETERNITY ; return 0 ; }
This stream analyser checks the switching rules and changes the backend
 if appropriate.
This stream analyser checks the switching rules and changes the backend if appropriate .
/* now check whether we have some switching rules for this request */ /* To ensure correct connection accounting on the backend, we
		 * have to assign one if it was not set (eg: a listen). This
		 * measure also takes care of correctly setting the default
		 * backend if any.
		 */ /* we don't want to run the TCP or HTTP filters again if the backend has not changed */ /* as soon as we know the backend, we must check if we have a matching forced or ignored
	 * persistence rule, and report that in the session.
	 */ /* no rule, or the rule matches */ /* immediately abort this request in case of allocation failure */