MEDIUM: threads/filters: Add init/deinit callback per thread

Now, it is possible to define init_per_thread and deinit_per_thread callbacks to
deal with ressources allocation for each thread.

This is the filter responsibility to deal with concurrency. This is also the
filter responsibility to know if HAProxy is started with some threads. A good
way to do so is to check "global.nbthread" value. If it is greater than 1, then
_per_thread callbacks will be called.
diff --git a/src/filters.c b/src/filters.c
index 0d0e5e8..c1d3f87 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -18,6 +18,7 @@
 #include <common/errors.h>
 #include <common/namespace.h>
 #include <common/standard.h>
+#include <common/hathreads.h>
 
 #include <types/filters.h>
 #include <types/proto_http.h>
@@ -263,6 +264,23 @@
 	return 0;
 }
 
+/*
+ * Calls 'init_per_thread' callback for all filters attached to a proxy for each
+ * threads. This happens after the thread creation. Filters can finish to fill
+ * their config. Returns (ERR_ALERT|ERR_FATAL) if an error occurs, 0 otherwise.
+ */
+static int
+flt_init_per_thread(struct proxy *proxy)
+{
+	struct flt_conf *fconf;
+
+	list_for_each_entry(fconf, &proxy->filter_configs, list) {
+		if (fconf->ops->init_per_thread && fconf->ops->init_per_thread(proxy, fconf) < 0)
+			return ERR_ALERT|ERR_FATAL;
+	}
+	return 0;
+}
+
 /* Calls flt_init() for all proxies, see above */
 static int
 flt_init_all()
@@ -281,6 +299,25 @@
 	return 0;
 }
 
+/* Calls flt_init_per_thread() for all proxies, see above.  Be carefull here, it
+ * returns 0 if an error occured. This is the opposite of flt_init_all. */
+static int
+flt_init_all_per_thread()
+{
+	struct proxy *px;
+	int err_code = 0;
+
+	for (px = proxy; px; px = px->next) {
+		err_code = flt_init_per_thread(px);
+		if (err_code & (ERR_ABORT|ERR_FATAL)) {
+			Alert("Failed to initialize filters for proxy '%s' for thread %u.\n",
+			      px->id, tid);
+			return 0;
+		}
+	}
+	return 1;
+}
+
 /*
  * Calls 'check' callback for all filters attached to a proxy. This happens
  * after the configuration parsing but before filters initialization. Returns
@@ -317,6 +354,32 @@
 	}
 }
 
+/*
+ * Calls 'denit_per_thread' callback for all filters attached to a proxy for
+ * each threads. This happens before exiting a thread.
+ */
+void
+flt_deinit_per_thread(struct proxy *proxy)
+{
+	struct flt_conf *fconf, *back;
+
+	list_for_each_entry_safe(fconf, back, &proxy->filter_configs, list) {
+		if (fconf->ops->deinit_per_thread)
+			fconf->ops->deinit_per_thread(proxy, fconf);
+	}
+}
+
+
+/* Calls flt_deinit_per_thread() for all proxies, see above */
+static void
+flt_deinit_all_per_thread()
+{
+	struct proxy *px;
+
+	for (px = proxy; px; px = px->next)
+		flt_deinit_per_thread(px);
+}
+
 /* Attaches a filter to a stream. Returns -1 if an error occurs, 0 otherwise. */
 static int
 flt_stream_add_filter(struct stream *s, struct flt_conf *fconf, unsigned int flags)
@@ -1124,6 +1187,8 @@
         pool2_filter = create_pool("filter", sizeof(struct filter), MEM_F_SHARED);
 	cfg_register_keywords(&cfg_kws);
 	hap_register_post_check(flt_init_all);
+	hap_register_per_thread_init(flt_init_all_per_thread);
+	hap_register_per_thread_deinit(flt_deinit_all_per_thread);
 }
 
 __attribute__((destructor))