MEDIUM: stick-table: make the use of 'gpc' excluding the use of 'gpc0/1''

This patch makes the use of 'gpc' excluding the use of the legacy
types 'gpc0' and 'gpc1" on the same table.

It also makes the use of 'gpc_rate' excluding the use of the legacy
types 'gpc0_rate' and 'gpc1_rate" on the same table.

The 'gpc0' and 'gpc1' related fetches and actions will apply
to the first two elements of the 'gpc' array if stored in table.

The 'gpc0_rate' and 'gpc1_rate' related fetches and actions will apply
to the first two elements of the 'gpc_rate' array if stored in table.
diff --git a/src/stick_table.c b/src/stick_table.c
index 03c7a38..7a02a19 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -955,6 +955,18 @@
 				err_code |= ERR_ALERT | ERR_FATAL;
 				goto out;
 			}
+			else if (t->data_ofs[STKTABLE_DT_GPC] && (t->data_ofs[STKTABLE_DT_GPC0] || t->data_ofs[STKTABLE_DT_GPC1])) {
+				ha_alert("parsing [%s:%d] : %s: simultaneous usage of 'gpc' and 'gpc[0/1]' in a same table is not permitted as 'gpc' overrides 'gpc[0/1]'.\n",
+					 file, linenum, args[0]);
+				err_code |= ERR_ALERT | ERR_FATAL;
+				goto out;
+			}
+			else if (t->data_ofs[STKTABLE_DT_GPC_RATE] && (t->data_ofs[STKTABLE_DT_GPC0_RATE] || t->data_ofs[STKTABLE_DT_GPC1_RATE])) {
+				ha_alert("parsing [%s:%d] : %s: simultaneous usage of 'gpc_rate' and 'gpc[0/1]_rate' in a same table is not permitted as 'gpc_rate' overrides 'gpc[0/1]_rate'.\n",
+					 file, linenum, args[0]);
+				err_code |= ERR_ALERT | ERR_FATAL;
+				goto out;
+			}
 		}
 		else if (strcmp(args[idx], "srvkey") == 0) {
 			char *keytype;
@@ -1601,6 +1613,11 @@
 		return 1;
 
 	ptr = stktable_data_ptr(t, ts, STKTABLE_DT_GPC0);
+	if (!ptr) {
+		/* fallback on the gpc array */
+		ptr = stktable_data_ptr_idx(t, ts, STKTABLE_DT_GPC, 0);
+	}
+
 	if (ptr)
 		smp->data.u.sint = stktable_data_cast(ptr, std_t_uint);
 
@@ -1640,6 +1657,13 @@
 	if (ptr)
 		smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
                                                        t->data_arg[STKTABLE_DT_GPC0_RATE].u);
+	else {
+		/* fallback on the gpc array */
+		ptr = stktable_data_ptr_idx(t, ts, STKTABLE_DT_GPC_RATE, 0);
+		if (ptr)
+			smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
+			                                        t->data_arg[STKTABLE_DT_GPC_RATE].u);
+	}
 
 	stktable_release(t, ts);
 	return !!ptr;
@@ -1674,6 +1698,11 @@
 		return 1;
 
 	ptr = stktable_data_ptr(t, ts, STKTABLE_DT_GPC1);
+	if (!ptr) {
+		/* fallback on the gpc array */
+		ptr = stktable_data_ptr_idx(t, ts, STKTABLE_DT_GPC, 1);
+	}
+
 	if (ptr)
 		smp->data.u.sint = stktable_data_cast(ptr, std_t_uint);
 
@@ -1713,6 +1742,13 @@
 	if (ptr)
 		smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
                                                        t->data_arg[STKTABLE_DT_GPC1_RATE].u);
+	else {
+		/* fallback on the gpc array */
+		ptr = stktable_data_ptr_idx(t, ts, STKTABLE_DT_GPC_RATE, 1);
+		if (ptr)
+			smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
+			                                        t->data_arg[STKTABLE_DT_GPC_RATE].u);
+	}
 
 	stktable_release(t, ts);
 	return !!ptr;
@@ -2202,6 +2238,7 @@
 {
 	struct stksess *ts;
 	struct stkctr *stkctr;
+	unsigned int period;
 
 	/* Extract the stksess, return OK if no stksess available. */
 	if (s)
@@ -2215,13 +2252,28 @@
 
 		/* First, update gpc0_rate if it's tracked. Second, update its gpc0 if tracked. */
 		ptr1 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_GPC0_RATE);
+		if (ptr1) {
+			period = stkctr->table->data_arg[STKTABLE_DT_GPC0_RATE].u;
+		}
+		else {
+			/* fallback on the gpc array */
+			ptr1 = stktable_data_ptr_idx(stkctr->table, ts, STKTABLE_DT_GPC_RATE, 0);
+			if (ptr1)
+				period = stkctr->table->data_arg[STKTABLE_DT_GPC_RATE].u;
+		}
+
 		ptr2 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_GPC0);
+		if (!ptr2) {
+			/* fallback on the gpc array */
+			ptr2 = stktable_data_ptr_idx(stkctr->table, ts, STKTABLE_DT_GPC, 0);
+		}
+
 		if (ptr1 || ptr2) {
 			HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
 
 			if (ptr1)
 				update_freq_ctr_period(&stktable_data_cast(ptr1, std_t_frqp),
-					       stkctr->table->data_arg[STKTABLE_DT_GPC0_RATE].u, 1);
+				                       period, 1);
 
 			if (ptr2)
 				stktable_data_cast(ptr2, std_t_uint)++;
@@ -2241,6 +2293,7 @@
 {
 	struct stksess *ts;
 	struct stkctr *stkctr;
+	unsigned int period;
 
 	/* Extract the stksess, return OK if no stksess available. */
 	if (s)
@@ -2254,13 +2307,28 @@
 
 		/* First, update gpc1_rate if it's tracked. Second, update its gpc1 if tracked. */
 		ptr1 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_GPC1_RATE);
+		if (ptr1) {
+			period = stkctr->table->data_arg[STKTABLE_DT_GPC1_RATE].u;
+		}
+		else {
+			/* fallback on the gpc array */
+			ptr1 = stktable_data_ptr_idx(stkctr->table, ts, STKTABLE_DT_GPC_RATE, 1);
+			if (ptr1)
+				period = stkctr->table->data_arg[STKTABLE_DT_GPC_RATE].u;
+		}
+
 		ptr2 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_GPC1);
+		if (!ptr2) {
+			/* fallback on the gpc array */
+			ptr2 = stktable_data_ptr_idx(stkctr->table, ts, STKTABLE_DT_GPC, 1);
+		}
+
 		if (ptr1 || ptr2) {
 			HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
 
 			if (ptr1)
 				update_freq_ctr_period(&stktable_data_cast(ptr1, std_t_frqp),
-					       stkctr->table->data_arg[STKTABLE_DT_GPC1_RATE].u, 1);
+				                       period, 1);
 
 			if (ptr2)
 				stktable_data_cast(ptr2, std_t_uint)++;
@@ -2920,6 +2988,11 @@
 
 		ptr  = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC0);
 		if (!ptr) {
+			/* fallback on the gpc array */
+			ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC, 0);
+		}
+
+		if (!ptr) {
 			if (stkctr == &tmpstkctr)
 				stktable_release(stkctr->table, stkctr_entry(stkctr));
 			return 0; /* parameter not stored */
@@ -2961,6 +3034,11 @@
 
 		ptr  = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC1);
 		if (!ptr) {
+			/* fallback on the gpc array */
+			ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC, 1);
+		}
+
+		if (!ptr) {
 			if (stkctr == &tmpstkctr)
 				stktable_release(stkctr->table, stkctr_entry(stkctr));
 			return 0; /* parameter not stored */
@@ -3033,6 +3111,7 @@
 {
 	struct stkctr tmpstkctr;
 	struct stkctr *stkctr;
+	unsigned int period;
 
 	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
 	if (!stkctr)
@@ -3045,6 +3124,16 @@
 		void *ptr;
 
 		ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC0_RATE);
+		if (ptr) {
+			period = stkctr->table->data_arg[STKTABLE_DT_GPC0_RATE].u;
+		}
+		else {
+			/* fallback on the gpc array */
+			ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC_RATE, 0);
+			if (ptr)
+				period = stkctr->table->data_arg[STKTABLE_DT_GPC_RATE].u;
+		}
+
 		if (!ptr) {
 			if (stkctr == &tmpstkctr)
 				stktable_release(stkctr->table, stkctr_entry(stkctr));
@@ -3053,8 +3142,7 @@
 
 		HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
 
-		smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
-		                  stkctr->table->data_arg[STKTABLE_DT_GPC0_RATE].u);
+		smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp), period);
 
 		HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
 
@@ -3074,6 +3162,7 @@
 {
 	struct stkctr tmpstkctr;
 	struct stkctr *stkctr;
+	unsigned int period;
 
 	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
 	if (!stkctr)
@@ -3086,6 +3175,16 @@
 		void *ptr;
 
 		ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC1_RATE);
+		if (ptr) {
+			period = stkctr->table->data_arg[STKTABLE_DT_GPC1_RATE].u;
+		}
+		else {
+			/* fallback on the gpc array */
+			ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC_RATE, 1);
+			if (ptr)
+				period = stkctr->table->data_arg[STKTABLE_DT_GPC_RATE].u;
+		}
+
 		if (!ptr) {
 			if (stkctr == &tmpstkctr)
 				stktable_release(stkctr->table, stkctr_entry(stkctr));
@@ -3094,8 +3193,7 @@
 
 		HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
 
-		smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
-		                  stkctr->table->data_arg[STKTABLE_DT_GPC1_RATE].u);
+		smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp), period);
 
 		HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
 
@@ -3171,6 +3269,7 @@
 {
 	struct stkctr tmpstkctr;
 	struct stkctr *stkctr;
+	unsigned int period;
 
 	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
 	if (!stkctr)
@@ -3191,13 +3290,28 @@
 		 * gpc0 if tracked. Returns gpc0's value otherwise the curr_ctr.
 		 */
 		ptr1 = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC0_RATE);
+		if (ptr1) {
+			period = stkctr->table->data_arg[STKTABLE_DT_GPC0_RATE].u;
+		}
+		else {
+			/* fallback on the gpc array */
+			ptr1 = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC_RATE, 0);
+			if (ptr1)
+				period = stkctr->table->data_arg[STKTABLE_DT_GPC_RATE].u;
+		}
+
 		ptr2 = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC0);
+		if (!ptr2) {
+			/* fallback on the gpc array */
+			ptr2 = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC, 0);
+		}
+
 		if (ptr1 || ptr2) {
 			HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
 
 			if (ptr1) {
 				update_freq_ctr_period(&stktable_data_cast(ptr1, std_t_frqp),
-						       stkctr->table->data_arg[STKTABLE_DT_GPC0_RATE].u, 1);
+						       period, 1);
 				smp->data.u.sint = (&stktable_data_cast(ptr1, std_t_frqp))->curr_ctr;
 			}
 
@@ -3224,6 +3338,7 @@
 {
 	struct stkctr tmpstkctr;
 	struct stkctr *stkctr;
+	unsigned int period;
 
 	stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
 	if (!stkctr)
@@ -3244,13 +3359,28 @@
 		 * gpc1 if tracked. Returns gpc1's value otherwise the curr_ctr.
 		 */
 		ptr1 = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC1_RATE);
+		if (ptr1) {
+			period = stkctr->table->data_arg[STKTABLE_DT_GPC1_RATE].u;
+		}
+		else {
+			/* fallback on the gpc array */
+			ptr1 = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC_RATE, 1);
+			if (ptr1)
+				period = stkctr->table->data_arg[STKTABLE_DT_GPC_RATE].u;
+		}
+
 		ptr2 = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC1);
+		if (!ptr2) {
+			/* fallback on the gpc array */
+			ptr2 = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC, 1);
+		}
+
 		if (ptr1 || ptr2) {
 			HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
 
 			if (ptr1) {
 				update_freq_ctr_period(&stktable_data_cast(ptr1, std_t_frqp),
-						       stkctr->table->data_arg[STKTABLE_DT_GPC1_RATE].u, 1);
+						       period, 1);
 				smp->data.u.sint = (&stktable_data_cast(ptr1, std_t_frqp))->curr_ctr;
 			}
 
@@ -3342,6 +3472,11 @@
 
 		ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC0);
 		if (!ptr) {
+			/* fallback on the gpc array */
+			ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC, 0);
+		}
+
+		if (!ptr) {
 			if (stkctr == &tmpstkctr)
 				stktable_release(stkctr->table, stkctr_entry(stkctr));
 			return 0; /* parameter not stored */
@@ -3386,6 +3521,11 @@
 
 		ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC1);
 		if (!ptr) {
+			/* fallback on the gpc array */
+			ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPC, 1);
+		}
+
+		if (!ptr) {
 			if (stkctr == &tmpstkctr)
 				stktable_release(stkctr->table, stkctr_entry(stkctr));
 			return 0; /* parameter not stored */