src/session.c
static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
{
	struct proxy    *px   = s->be;
	struct sticking_rule  *rule;
	int i;

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

	list_for_each_entry(rule, &px->storersp_rules, list) {
		int ret = 1 ;
		int storereqidx = -1;

		for (i = 0; i < s->store_count; i++) {
			if (rule->table.t == s->store[i].table) {
				if (!(s->store[i].flags))
					storereqidx = i;
				break;
			}
		}

		if ((i !=  s->store_count) && (storereqidx == -1))
			continue;

		if (rule->cond) {
	                ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
	                ret = acl_pass(ret);
			if (rule->cond->pol == ACL_COND_UNLESS)
				ret = !ret;
		}

		if (ret) {
			struct stktable_key *key;

			key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr);
			if (!key)
				continue;

			if (storereqidx != -1) {
				stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
				s->store[storereqidx].flags = 1;
			}
			else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
				struct stksess *ts;

				ts = stksess_new(rule->table.t, key);
				if (ts) {
					s->store[s->store_count].table = rule->table.t;
					s->store[s->store_count].flags = 1;
					s->store[s->store_count++].ts = ts;
				}
			}
		}
	}

	/* process store request and store response */
	for (i = 0; i < s->store_count; i++) {
		struct stksess *ts;
		void *ptr;

		if (objt_server(s->target) && objt_server(s->target)->state & SRV_NON_STICK) {
			stksess_free(s->store[i].table, s->store[i].ts);
			s->store[i].ts = NULL;
			continue;
		}

		ts = stktable_lookup(s->store[i].table, s->store[i].ts);
		if (ts) {
			/* the entry already existed, we can free ours */
			stktable_touch(s->store[i].table, ts, 1);
			stksess_free(s->store[i].table, s->store[i].ts);
		}
		else
			ts = stktable_store(s->store[i].table, s->store[i].ts, 1);

		s->store[i].ts = NULL;
		ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
		stktable_data_cast(ptr, server_id) = objt_server(s->target)->puid;
	}
	s->store_count = 0; /* everything is stored */

	rep->analysers &= ~an_bit;
	rep->analyse_exp = TICK_ETERNITY;
	return 1;
}
/* This stream analyser works on a response. It applies all store rules on it
 * then returns 1. The data must already be present in the buffer otherwise
 * they won't match. It always returns 1.
 */
This stream analyser works on a response. It applies all store rules on it
then returns 1. The data must already be present in the buffer otherwise
they won't match. It always returns 1.
This stream analyser works on a response . It applies all store rules on it then returns 1 . The data must already be present in the buffer otherwise they won ' t match . It always returns 1 .
static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
{
	struct proxy    *px   = s->be;
	struct sticking_rule  *rule;
	int i;
	DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
		now_ms, __FUNCTION__,
		s,
		rep,
		rep->rex, rep->wex,
		rep->flags,
		rep->buf->i,
		rep->analysers);
	list_for_each_entry(rule, &px->storersp_rules, list) {
		int ret = 1 ;
		int storereqidx = -1;
		for (i = 0; i < s->store_count; i++) {
			if (rule->table.t == s->store[i].table) {
				if (!(s->store[i].flags))
					storereqidx = i;
				break;
			}
		}
		if ((i !=  s->store_count) && (storereqidx == -1))
			continue;
		if (rule->cond) {
	                ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
	                ret = acl_pass(ret);
			if (rule->cond->pol == ACL_COND_UNLESS)
				ret = !ret;
		}
		if (ret) {
			struct stktable_key *key;
			key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr);
			if (!key)
				continue;
			if (storereqidx != -1) {
				stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
				s->store[storereqidx].flags = 1;
			}
			else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
				struct stksess *ts;
				ts = stksess_new(rule->table.t, key);
				if (ts) {
					s->store[s->store_count].table = rule->table.t;
					s->store[s->store_count].flags = 1;
					s->store[s->store_count++].ts = ts;
				}
			}
		}
	}
	for (i = 0; i < s->store_count; i++) {
		struct stksess *ts;
		void *ptr;
		if (objt_server(s->target) && objt_server(s->target)->state & SRV_NON_STICK) {
			stksess_free(s->store[i].table, s->store[i].ts);
			s->store[i].ts = NULL;
			continue;
		}
		ts = stktable_lookup(s->store[i].table, s->store[i].ts);
		if (ts) {
			stktable_touch(s->store[i].table, ts, 1);
			stksess_free(s->store[i].table, s->store[i].ts);
		}
		else
			ts = stktable_store(s->store[i].table, s->store[i].ts, 1);
		s->store[i].ts = NULL;
		ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
		stktable_data_cast(ptr, server_id) = objt_server(s->target)->puid;
	}
	s->store_count = 0; 
	rep->analysers &= ~an_bit;
	rep->analyse_exp = TICK_ETERNITY;
	return 1;
}
static int process_store_rules ( struct session * s , struct channel * rep , int an_bit ) { struct proxy * px = s -> be ; struct sticking_rule * rule ; int i ; DPRINTF ( stderr , " \n " , now_ms , __FUNCTION__ , s , rep , rep -> rex , rep -> wex , rep -> flags , rep -> buf -> i , rep -> analysers ) ; list_for_each_entry ( rule , & px -> storersp_rules , list ) { int ret = 1 ; int storereqidx = -1 ; for ( i = 0 ; i < s -> store_count ; i ++ ) { if ( rule -> table . t == s -> store [ i ] . table ) { if ( ! ( s -> store [ i ] . flags ) ) storereqidx = i ; break ; } } if ( ( i != s -> store_count ) && ( storereqidx == -1 ) ) continue ; if ( rule -> cond ) { ret = acl_exec_cond ( rule -> cond , px , s , & s -> txn , SMP_OPT_DIR_RES | SMP_OPT_FINAL ) ; ret = acl_pass ( ret ) ; if ( rule -> cond -> pol == ACL_COND_UNLESS ) ret = ! ret ; } if ( ret ) { struct stktable_key * key ; key = stktable_fetch_key ( rule -> table . t , px , s , & s -> txn , SMP_OPT_DIR_RES | SMP_OPT_FINAL , rule -> expr ) ; if ( ! key ) continue ; if ( storereqidx != -1 ) { stksess_setkey ( s -> store [ storereqidx ] . table , s -> store [ storereqidx ] . ts , key ) ; s -> store [ storereqidx ] . flags = 1 ; } else if ( s -> store_count < ( sizeof ( s -> store ) / sizeof ( s -> store [ 0 ] ) ) ) { struct stksess * ts ; ts = stksess_new ( rule -> table . t , key ) ; if ( ts ) { s -> store [ s -> store_count ] . table = rule -> table . t ; s -> store [ s -> store_count ] . flags = 1 ; s -> store [ s -> store_count ++ ] . ts = ts ; } } } } for ( i = 0 ; i < s -> store_count ; i ++ ) { struct stksess * ts ; void * ptr ; if ( objt_server ( s -> target ) && objt_server ( s -> target ) -> state & SRV_NON_STICK ) { stksess_free ( s -> store [ i ] . table , s -> store [ i ] . ts ) ; s -> store [ i ] . ts = NULL ; continue ; } ts = stktable_lookup ( s -> store [ i ] . table , s -> store [ i ] . ts ) ; if ( ts ) { stktable_touch ( s -> store [ i ] . table , ts , 1 ) ; stksess_free ( s -> store [ i ] . table , s -> store [ i ] . ts ) ; } else ts = stktable_store ( s -> store [ i ] . table , s -> store [ i ] . ts , 1 ) ; s -> store [ i ] . ts = NULL ; ptr = stktable_data_ptr ( s -> store [ i ] . table , ts , STKTABLE_DT_SERVER_ID ) ; stktable_data_cast ( ptr , server_id ) = objt_server ( s -> target ) -> puid ; } s -> store_count = 0 ; rep -> analysers &= ~ an_bit ; rep -> analyse_exp = TICK_ETERNITY ; return 1 ; }
This stream analyser works on a response.
This stream analyser works on a response .
/* process store request and store response */ /* the entry already existed, we can free ours */ /* everything is stored */