MINOR: hlua/event_hdl: per-server event subscription

Now that event_hdl api is properly implemented in hlua, we may add the
per-server event subscription in addition to the global event
subscription.

Per-server subscription allows to be notified for events related to
single server. It is useful to track a server UP/DOWN and DEL events.

It works exactly like core.event_sub() except that the subscription
will be performed within the server dedicated subscription list instead
of the global one.
The callback function will only be called for server events affecting
the server from which the subscription was performed.

Regarding the implementation, it is pretty trivial at this point, we add
more doc than code this time.

Usage examples have been added to the (lua) documentation.
diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst
index 24c52cf..f25f9dc 100644
--- a/doc/lua-api/index.rst
+++ b/doc/lua-api/index.rst
@@ -924,6 +924,7 @@
   :param array event_types: array of string containing the event types you want to subscribe to
   :param function func: is the Lua function called when one of the subscribed events occur.
   :returns: A :ref:`event_sub_class` object.
+  :see: :js:func:`Server.event_sub()`.
 
   List of available event types :
 
@@ -1298,6 +1299,69 @@
   :param class_server sv: A :ref:`server_class` which indicates the manipulated
     server.
 
+.. js:function:: Server.event_sub(sv, event_types, func)
+
+  Register a function that will be called on specific server events.
+  It works exactly like :js:func:`core.event_sub()` except that the subscription
+  will be performed within the server dedicated subscription list instead of the
+  global one.
+  (Your callback function will only be called for server events affecting sv)
+
+  See :js:func:`core.event_sub()` for function usage.
+
+  A key advantage to using :js:func:`Server.event_sub()` over
+  :js:func:`core.event_sub()` for servers is that :js:func:`Server.event_sub()`
+  allows you to be notified for servers events of a single server only.
+  It removes the needs for extra filtering in your callback function if you only
+  care about a single server, and also prevents useless wakeups.
+
+  For instance, if you want to be notified for UP/DOWN events on a given set of
+  servers, it is recommended to peform multiple per-server subscriptions since
+  it will be more efficient that doing a single global subscription that will
+  filter the received events.
+  Unless you really want to be notified for servers events of ALL servers of
+  course, which could make sense given you setup but should be avoided if you
+  have an important number of servers as it will add a significant load on your
+  haproxy process in case of multiple servers state change in a short amount of
+  time.
+
+  .. Note::
+     You may also combine :js:func:`core.event_sub()` with
+     :js:func:`Server.event_sub()`.
+
+     Also, don't forget that you can use :js:func:`core.register_task()` from
+     your callback function if needed. (ie: parallel work)
+
+  Here is a working example combining :js:func:`core.event_sub()` with
+  :js:func:`Server.event_sub()` and :js:func:`core.register_task()`
+  (This only serves as a demo, this is not necessarily useful to do so)
+
+.. code-block:: lua
+
+  core.event_sub({"SERVER_ADD"}, function(event, data, sub)
+    -- in the global event handler
+    if data["reference"] ~= nil then
+      print("Tracking new server: ", data["name"])
+      data["reference"]:event_sub({"SERVER_UP", "SERVER_DOWN"}, function(event, data, sub)
+        -- in the per-server event handler
+	if data["reference"] ~= nil then
+          core.register_task(function(server)
+            -- subtask to perform some async work (e.g.: HTTP API calls, sending emails...)
+            print("ASYNC: SERVER ", server:get_name(), " is ", event == "SERVER_UP" and "UP" or "DOWN")
+          end, data["reference"])
+        end
+      end)
+    end
+  end)
+
+..
+
+  In this example, we will first track global server addition events.
+  For each newly added server ("add server" on the cli), we will register a
+  UP/DOWN server subscription.
+  Then, the callback function will schedule the event handling in an async
+  subtask which will receive the server reference as an argument.
+
 .. _listener_class:
 
 Listener class
diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c
index c7495bd..5a46a0d 100644
--- a/src/hlua_fcn.c
+++ b/src/hlua_fcn.c
@@ -1374,6 +1374,27 @@
 	return 0;
 }
 
+/* hlua_event_sub wrapper for per-server subscription:
+ *
+ * hlua_event_sub() is called with sv->e_subs subscription list and
+ * lua arguments are passed as-is (skipping the first argument which
+ * is the server ctx)
+ */
+int hlua_server_event_sub(lua_State *L)
+{
+	struct server *sv;
+
+	sv = hlua_check_server(L, 1);
+	if (sv == NULL) {
+		return 0;
+	}
+	/* remove first argument from the stack (server) */
+	lua_remove(L, 1);
+
+	/* try to subscribe within server's subscription list */
+	return hlua_event_sub(L, &sv->e_subs);
+}
+
 int hlua_fcn_new_server(lua_State *L, struct server *srv)
 {
 	lua_newtable(L);
@@ -1413,6 +1434,7 @@
 	hlua_class_function(L, "agent_disable", hlua_server_agent_disable);
 	hlua_class_function(L, "agent_force_up", hlua_server_agent_force_up);
 	hlua_class_function(L, "agent_force_down", hlua_server_agent_force_down);
+	hlua_class_function(L, "event_sub", hlua_server_event_sub);
 
 	return 1;
 }