[MEDIUM] Create updates tree on stick table to manage sync.
diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h
index 4365fcd..5da327c 100644
--- a/include/proto/stick_table.h
+++ b/include/proto/stick_table.h
@@ -41,8 +41,8 @@
 int stktable_init(struct stktable *t);
 int stktable_parse_type(char **args, int *idx, unsigned long *type, size_t *key_size);
 struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key *key);
-struct stksess *stktable_store(struct stktable *t, struct stksess *ts);
-struct stksess *stktable_touch(struct stktable *t, struct stksess *ts);
+struct stksess *stktable_store(struct stktable *t, struct stksess *ts, int local);
+struct stksess *stktable_touch(struct stktable *t, struct stksess *ts, int local);
 struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts);
 struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key);
 struct stksess *stktable_update_key(struct stktable *table, struct stktable_key *key);
diff --git a/include/types/stick_table.h b/include/types/stick_table.h
index b835066..cb3fb3b 100644
--- a/include/types/stick_table.h
+++ b/include/types/stick_table.h
@@ -130,16 +130,23 @@
 	unsigned int expire;      /* session expiration date */
 	unsigned int ref_cnt;     /* reference count, can only purge when zero */
 	struct eb32_node exp;     /* ebtree node used to hold the session in expiration tree */
+	struct eb32_node upd;     /* ebtree node used to hold the update sequence tree */
 	struct ebmb_node key;     /* ebtree node used to hold the session in table */
 	/* WARNING! do not put anything after <keys>, it's used by the key */
 };
 
+
 /* stick table */
 struct stktable {
+	char *id;		  /* table id name */
 	struct eb_root keys;      /* head of sticky session tree */
 	struct eb_root exps;      /* head of sticky session expiration tree */
+	struct eb_root updates;   /* head of sticky updates sequence tree */
 	struct pool_head *pool;   /* pool used to allocate sticky sessions */
 	struct task *exp_task;    /* expiration task */
+	struct task *sync_task;   /* sync task */
+	unsigned int update;
+	unsigned int localupdate;
 	unsigned long type;       /* type of table (determines key format) */
 	size_t key_size;          /* size of a key, maximum size in case of string */
 	unsigned int size;        /* maximum number of sticky sessions in table */
diff --git a/src/session.c b/src/session.c
index 4d2b605..5432266 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1077,7 +1077,7 @@
 							}
 						}
 					}
-					stktable_touch(rule->table.t, ts);
+					stktable_touch(rule->table.t, ts, 1);
 				}
 			}
 			if (rule->flags & STK_IS_STORE) {
@@ -1172,11 +1172,11 @@
 		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);
+			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);
+			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);
diff --git a/src/stick_table.c b/src/stick_table.c
index bf8df0f..fb75d3f 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -51,6 +51,7 @@
 		return;
 
 	eb32_delete(&ts->exp);
+	eb32_delete(&ts->upd);
 	ebmb_delete(&ts->key);
 	stksess_free(t, ts);
 }
@@ -80,6 +81,7 @@
 	ts->ref_cnt = 0;
 	ts->key.node.leaf_p = NULL;
 	ts->exp.node.leaf_p = NULL;
+	ts->upd.node.leaf_p = NULL;
 	return ts;
 }
 
@@ -137,6 +139,7 @@
 
 		/* session expired, trash it */
 		ebmb_delete(&ts->key);
+		eb32_delete(&ts->upd);
 		stksess_free(t, ts);
 		batched++;
 	}
@@ -204,12 +207,12 @@
 
 	ts = stktable_lookup_key(table, key);
 	if (likely(ts))
-		return stktable_touch(table, ts);
+		return stktable_touch(table, ts, 1);
 
 	/* entry does not exist, initialize a new one */
 	ts = stksess_new(table, key);
 	if (likely(ts))
-		stktable_store(table, ts);
+		stktable_store(table, ts, 1);
 	return ts;
 }
 
@@ -235,13 +238,26 @@
 /* Update the expiration timer for <ts> but do not touch its expiration node.
  * The table's expiration timer is updated if set.
  */
-struct stksess *stktable_touch(struct stktable *t, struct stksess *ts)
+struct stksess *stktable_touch(struct stktable *t, struct stksess *ts, int local)
 {
+	struct eb32_node * eb;
 	ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire));
 	if (t->expire) {
 		t->exp_task->expire = t->exp_next = tick_first(ts->expire, t->exp_next);
 		task_queue(t->exp_task);
 	}
+
+	if (t->sync_task && local) {
+		ts->upd.key = ++t->update;
+		t->localupdate = t->update;
+		eb32_delete(&ts->upd);
+		eb = eb32_insert(&t->updates, &ts->upd);
+		if (eb != &ts->upd)  {
+			eb32_delete(eb);
+			eb32_insert(&t->updates, &ts->upd);
+		}
+		task_wakeup(t->sync_task, TASK_WOKEN_MSG);
+	}
 	return ts;
 }
 
@@ -249,10 +265,10 @@
  * yet exist (the caller must check this). The table's timeout is updated if it
  * is set. <ts> is returned.
  */
-struct stksess *stktable_store(struct stktable *t, struct stksess *ts)
+struct stksess *stktable_store(struct stktable *t, struct stksess *ts, int local)
 {
 	ebmb_insert(&t->keys, &ts->key, t->key_size);
-	stktable_touch(t, ts);
+	stktable_touch(t, ts, local);
 	ts->exp.key = ts->expire;
 	eb32_insert(&t->exps, &ts->exp);
 	return ts;
@@ -275,10 +291,10 @@
 		ts = stksess_new(table, key);
 		if (!ts)
 			return NULL;
-		stktable_store(table, ts);
+		stktable_store(table, ts, 1);
 	}
 	else
-		stktable_touch(table, ts);
+		stktable_touch(table, ts, 1);
 	return ts;
 }
 
@@ -339,6 +355,7 @@
 
 		/* session expired, trash it */
 		ebmb_delete(&ts->key);
+		eb32_delete(&ts->upd);
 		stksess_free(t, ts);
 	}