src/server/daemon/httplistener.c

changeset 36
450d2d5f4735
parent 35
4417619a9bbd
child 37
360b9aabe17e
--- a/src/server/daemon/httplistener.c	Sat Aug 18 11:39:34 2012 +0200
+++ b/src/server/daemon/httplistener.c	Sat Oct 06 13:00:07 2012 +0200
@@ -47,6 +47,7 @@
 #include <pthread.h>
 
 #include "../ucx/map.h"
+#include "../ucx/atomic.h"
 #include "httplistener.h"
 
 #include "session.h"
@@ -67,8 +68,55 @@
     return 0;
 }
 
+HttpListener* http_listener_create(ListenerConfig *conf) {
+    if(listener_map == NULL) {
+        listener_map = ucx_map_new(16);
+    }
+
+    HttpListener *fl = ucx_map_sstr_get(listener_map, conf->name);
+    if(fl == NULL) {
+        return http_listener_new(conf);
+    }
+    
+    HttpListener* newls = malloc(sizeof(HttpListener));
+    if(newls == NULL) {
+        // TODO: error
+    }
+    
+    newls->cfg = conf->cfg;
+    newls->default_vs.vs_name = conf->vs.ptr;
+    newls->port = fl->port;
+    newls->server_socket = fl->server_socket;
+    newls->session_handler = fl->session_handler; // TODO
+    newls->ref = 2; // 1 reference is fl->next
+    
+    // create acceptor threads
+    newls->acceptors = calloc(newls->nacceptors, sizeof(void*));
+    for (int i=0;i<newls->nacceptors;i++) {
+        newls->acceptors[i] = acceptor_new(newls);
+    }
+    
+    // fl hold one reference of newls
+    fl->next = newls;
+    
+    
+    ucx_map_sstr_put(listener_map, newls->name, newls);
+    
+    for (int i=0;i<newls->nacceptors;i++) {
+        acceptor_start(newls->acceptors[i]);
+    }
+    
+    // check if a restart is required to apply all changes
+    
+    if(newls->port != conf->port) {
+        // TODO: log
+    }
+    
+    return newls;
+}
 
 HttpListener* http_listener_new(ListenerConfig *conf) {
+    // TODO: remove
     if(listener_map == NULL) {
         listener_map = ucx_map_new(16);
     }
@@ -77,6 +125,7 @@
     if(fl != NULL) {
         return fl;
     }
+    // end remove
 
     HttpListener *listener = malloc(sizeof(HttpListener));
     listener->name = conf->name;
@@ -84,6 +133,8 @@
     listener->session_handler = create_event_session_handler();
     listener->nacceptors = conf->nacceptors;
     listener->port = conf->port;
+    listener->ref = 1;
+    listener->next = NULL;
     ucx_map_sstr_put(listener_map, listener->name, listener);
 
     struct sockaddr_in servaddr;   /* server address */
@@ -140,6 +191,20 @@
     return 0;
 }
 
+void http_listener_ref(HttpListener *listener) {
+    ucx_atomic_inc_32(&listener->ref);
+}
+
+void http_listener_unref(HttpListener *listener) {
+    uint32_t ref = ucx_atomic_dec_32_nv(&listener->ref);
+    if(ref == 0) {
+        free(listener->acceptors);
+        // TODO: unref cfg
+        // TODO: unref session handler
+        free(listener);
+    }
+}
+
 
 
 Acceptor* acceptor_new(HttpListener *listener) {
@@ -178,22 +243,33 @@
             continue;
         }
         
+        // check listener
+        HttpListener *ls = listener;
+        int acceptor_exit = 0;
+        while(ls->next) {
+            ls = ls->next;
+            acceptor_exit = 1;
+        }
+        
         /* create Connection object */
         Connection *conn = malloc(sizeof(Connection));
         conn->address = ca;
         conn->fd = clientfd;
-        conn->listener = listener;
+        conn->listener = ls;
 
         /* enqueue the connection */
-        listener->session_handler->enqueue_connection(
-                listener->session_handler,
+        ls->session_handler->enqueue_connection(
+                ls->session_handler,
                 conn);
 
         /* ready for new connection */
-        if(0) {
+        if(acceptor_exit) {
             break;
         }
     }
     
+    http_listener_unref(listener->next);
+    http_listener_unref(listener);
+    
     return NULL;
 }

mercurial