added support for asynchronous safs

Sat, 15 Dec 2012 16:05:03 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 15 Dec 2012 16:05:03 +0100
changeset 37
360b9aabe17e
parent 36
450d2d5f4735
child 38
d07810b02147

added support for asynchronous safs

src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/config.h file | annotate | diff | comparison | revisions
src/server/daemon/configmanager.c file | annotate | diff | comparison | revisions
src/server/daemon/httplistener.c file | annotate | diff | comparison | revisions
src/server/daemon/httplistener.h file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.c file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.h file | annotate | diff | comparison | revisions
src/server/daemon/session.h file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.c file | annotate | diff | comparison | revisions
src/server/daemon/threadpools.c file | annotate | diff | comparison | revisions
src/server/daemon/threadpools.h file | annotate | diff | comparison | revisions
src/server/daemon/ws-fn.c file | annotate | diff | comparison | revisions
src/server/safs/common.c file | annotate | diff | comparison | revisions
src/server/safs/common.h file | annotate | diff | comparison | revisions
src/server/safs/objs.mk file | annotate | diff | comparison | revisions
src/server/util/pblock.cpp file | annotate | diff | comparison | revisions
src/server/util/pblock.h file | annotate | diff | comparison | revisions
templates/conf/server.conf file | annotate | diff | comparison | revisions
--- a/src/server/daemon/config.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/config.c	Sat Dec 15 16:05:03 2012 +0100
@@ -123,7 +123,7 @@
      * convert ServerConfig to ServerConfiguration
      * 
      * its important to do this in the correct order:
-     * LogFile (we want an open log file first to log possible errors)
+     * LogFile (open log file first to log possible errors)
      * Runtime
      * Threadpool
      * EventHandler
@@ -159,14 +159,23 @@
     
     list = ucx_map_sstr_get(serverconf->objects, sstrn("Threadpool", 10));
     UCX_FOREACH(UcxList*, list, elm) {
-        ServerConfigObject *scfgobj = elm->data;
-        // TODO: threadpool
+        cfg_handle_threadpool(serverconfig, elm->data);
+    }
+    // check thread pool config
+    if(check_thread_pool_cfg() != 0) {
+        /* critical error */
+        return NULL;
     }
     
     list = ucx_map_sstr_get(serverconf->objects, sstrn("EventHandler", 12));
     UCX_FOREACH(UcxList*, list, elm) {
         cfg_handle_eventhandler(serverconfig, (ServerConfigObject*)elm->data);
     }
+    // check event handler config
+    if(check_event_handler_cfg() != 0) {
+        /* critical error */
+        return NULL;
+    }
     
     list = ucx_map_sstr_get(serverconf->objects, sstrn("AuthDB", 6));
     UCX_FOREACH(UcxList*, list, elm) {
@@ -185,18 +194,7 @@
         ServerConfigObject *scfgobj = elm->data;
         cfg_handle_vs(serverconfig, scfgobj);
     }
-
-    // check event handler config
-    if(check_event_handler_cfg() != 0) {
-        /* critical error */
-        return NULL;
-    }
     
-    // check thread pool config
-    if(check_thread_pool_cfg() != 0) {
-        /* critical error */
-        return NULL;
-    }
 
     // set VirtualServer for all listeners
     UcxList *ls = serverconfig->listeners;
@@ -271,6 +269,63 @@
     return ret;
 }
 
+int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj) {
+    ThreadPoolConfig poolcfg;
+    poolcfg.min_threads = 4;
+    poolcfg.min_threads = 4;
+    poolcfg.max_threads = 8;
+    poolcfg.queue_size = 64;
+    poolcfg.stack_size = 262144;
+    
+    sstr_t name = cfg_directivelist_get_str(
+            obj->directives,
+            sstr("Name"));
+    sstr_t min = cfg_directivelist_get_str(
+            obj->directives,
+            sstr("MinThreads"));
+    sstr_t max = cfg_directivelist_get_str(
+            obj->directives,
+            sstr("MaxThreads"));
+    sstr_t stack = cfg_directivelist_get_str(
+            obj->directives,
+            sstr("StackSize"));
+    sstr_t queue = cfg_directivelist_get_str(
+            obj->directives,
+            sstr("QueueSize"));
+    // TODO: Type
+    
+    if(name.length == 0) {
+        // TODO: log error
+        return 1;
+    }
+    
+    if(min.length != 0) {
+        min = sstrdup(min);
+        poolcfg.min_threads = atoi(min.ptr);
+        free(min.ptr);
+    }
+    
+    if(max.length != 0) {
+        max = sstrdup(max);
+        poolcfg.max_threads = atoi(max.ptr);
+        free(max.ptr);
+    }
+    
+    if(stack.length != 0) {
+        stack = sstrdup(stack);
+        poolcfg.stack_size = atoi(stack.ptr);
+        free(stack.ptr);
+    }
+    
+    if(queue.length != 0) {
+        queue = sstrdup(queue);
+        poolcfg.queue_size = atoi(queue.ptr);
+        free(queue.ptr);
+    }
+    
+    create_threadpool(name, &poolcfg);
+}
+
 int cfg_handle_eventhandler(ServerConfiguration *c, ServerConfigObject *obj) {
     EventHandlerConfig evcfg;
     
@@ -317,12 +372,16 @@
     lc.vs = sstrdup(cfg_directivelist_get_str(
             obj->directives,
             sstr("DefaultVS")));
+    lc.threadpool = sstrdup(cfg_directivelist_get_str(
+            obj->directives,
+            sstr("Threadpool")));
     
-
+    // TODO: check if all important configs are set
+    
     HttpListener *listener = http_listener_create(&lc);
     listener->default_vs.vs_name = lc.vs.ptr;
     cfg->listeners = ucx_list_append(cfg->listeners, listener); 
-
+    
     return 0;
 }
 
--- a/src/server/daemon/config.h	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/config.h	Sat Dec 15 16:05:03 2012 +0100
@@ -80,6 +80,8 @@
 
 int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj);
 
+int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj);
+
 int cfg_handle_eventhandler(ServerConfiguration *cfg, ServerConfigObject *obj);
 
 int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj);
--- a/src/server/daemon/configmanager.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/configmanager.c	Sat Dec 15 16:05:03 2012 +0100
@@ -64,10 +64,11 @@
      * ServerConfiguration and VirtualServer
      */
     http_listener_ref(ls);
-    ls->cfg = cfg;
     
+    // TODO: this is non atomar
     sstr_t vsname = ls->default_vs.vs->name;
     ls->default_vs.vs = ucx_map_sstr_get(cfg->host_vs, vsname);
+    ls->cfg = cfg;
     
     return ls;
 }
--- a/src/server/daemon/httplistener.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/httplistener.c	Sat Dec 15 16:05:03 2012 +0100
@@ -84,11 +84,20 @@
     }
     
     newls->cfg = conf->cfg;
-    newls->default_vs.vs_name = conf->vs.ptr;
+    newls->default_vs.vs_name = conf->vs.ptr;  
     newls->port = fl->port;
     newls->server_socket = fl->server_socket;
+    newls->ref = 2; // 1 reference is fl->next
+    
     newls->session_handler = fl->session_handler; // TODO
-    newls->ref = 2; // 1 reference is fl->next
+    
+    // the listener threadpool might be changed
+    if(conf->threadpool.ptr != NULL) {
+        newls->threadpool = get_threadpool(conf->threadpool);
+    }
+    if(newls->threadpool == NULL) {
+        newls->threadpool = get_default_threadpool();
+    }
     
     // create acceptor threads
     newls->acceptors = calloc(newls->nacceptors, sizeof(void*));
@@ -129,6 +138,13 @@
 
     HttpListener *listener = malloc(sizeof(HttpListener));
     listener->name = conf->name;
+    listener->default_vs.vs_name = conf->vs.ptr;
+    if(conf->threadpool.ptr != NULL) {
+        listener->threadpool = get_threadpool(conf->threadpool);
+    }
+    if(listener->threadpool == NULL) {
+        listener->threadpool = get_default_threadpool();
+    }
     //listener->session_handler = create_basic_session_handler();
     listener->session_handler = create_event_session_handler();
     listener->nacceptors = conf->nacceptors;
--- a/src/server/daemon/httplistener.h	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/httplistener.h	Sat Dec 15 16:05:03 2012 +0100
@@ -30,7 +30,7 @@
 #define	HTTPLISTENER_H
 
 #include "sessionhandler.h"
-
+#include "threadpools.h"
 #include "config.h"
 
 #ifdef	__cplusplus
@@ -50,6 +50,7 @@
     ServerConfiguration  *cfg;
     sstr_t               name;
     sstr_t               vs;
+    sstr_t               threadpool;
     char                 *address;
     int                  port;
     int                  nacceptors;
@@ -67,6 +68,7 @@
     int                  port;
     int                  server_socket;
     SessionHandler       *session_handler;
+    threadpool_t         *threadpool;
     HttpListener         *next;
     Acceptor             **acceptors;
     int                  nacceptors;
--- a/src/server/daemon/httprequest.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/httprequest.c	Sat Dec 15 16:05:03 2012 +0100
@@ -57,7 +57,7 @@
     return req;
 }
 
-int handle_request(HTTPRequest *request) {
+int handle_request(HTTPRequest *request, threadpool_t *thrpool) {
     // handle nsapi request
 
     // create pool
@@ -250,9 +250,20 @@
         sn->sn.inbuf = NULL;
     }
     
-    
+    //
     // Send the request to the NSAPI system
-    nsapi_handle_request(sn, rq);
+    //
+    
+    // compare current and listener thread pool
+    threadpool_t *lstp = request->connection->listener->threadpool;
+    sn->defaultpool = lstp;
+    if(lstp == thrpool) {
+        sn->currentpool = thrpool;
+        nsapi_handle_request(sn, rq);
+    } else {
+        // execute nsapi functions on a different thread pool
+        nsapi_change_threadpool(sn, rq, lstp);
+    }
 
     return 0;
 }
@@ -283,8 +294,6 @@
  */
 
 int nsapi_handle_request(NSAPISession *sn, NSAPIRequest *rq) {
-    // TODO: threadpool
-
     int r = REQ_NOACTION;
 
     do {
@@ -350,7 +359,9 @@
         
     } while (r == REQ_RESTART);
 
-    r = nsapi_finish_request(sn, rq);
+    if(r != REQ_PROCESSING) {
+        r = nsapi_finish_request(sn, rq);
+    }
 
     return r;
 }
@@ -375,9 +386,11 @@
 
     int ret = rq->context.last_req_code;
     for(int i=NCX_DI(rq);i<dt->ndir;i++) {
-        directive *d = dt->dirs[i];
-
-        ret = d->func->func(d->param, (Session*)sn, (Request*)rq);
+        if(ret == REQ_NOACTION) {
+            directive *d = dt->dirs[i];
+            ret = nsapi_exec(d, sn, rq);
+        }
+        
         if(ret != REQ_NOACTION) {
             /*
              * if a saf is still processing, we need to save the context, to
@@ -413,9 +426,10 @@
     char *name = NULL;
     char *ppath = NULL;
     for(int i=NCX_DI(rq);i<dt->ndir;i++) {
-        directive *d = dt->dirs[i];
-
-        ret = d->func->func(d->param, (Session*)sn, (Request*)rq);
+        if(ret == REQ_NOACTION) {
+            directive *d = dt->dirs[i];
+            ret = nsapi_exec(d, sn, rq);
+        }
 
         /* check for name or ppath */
         name = pblock_findkeyval(pb_key_name, rq->rq.vars);
@@ -486,11 +500,12 @@
         dtable *dt = object_get_dtable(obj, NSAPIPathCheck);
 
         // execute directives
-        for(int j=0;j<dt->ndir;j++) {
-            directive *d = dt->dirs[j];   
-
-            /* execute the saf */
-            ret = d->func->func(d->param, (Session*)sn, (Request*)rq);
+        for(int j=NCX_DI(rq);j<dt->ndir;j++) {
+            if(ret == REQ_NOACTION) {
+                directive *d = dt->dirs[j];
+                ret = nsapi_exec(d, sn, rq);
+            }
+            
             if(ret != REQ_NOACTION) {
                 if(ret == REQ_PROCESSING) {
                     /* save nsapi context */
@@ -528,10 +543,12 @@
         dtable *dt = object_get_dtable(obj, NSAPIObjectType);
 
         // execute directives
-        for(int j=0;j<dt->ndir;j++) {
-            directive *d = dt->dirs[j];
-
-            ret = d->func->func(d->param, (Session*)sn, (Request*)rq);
+        for(int j=NCX_DI(rq);j<dt->ndir;j++) {
+            if(ret == REQ_NOACTION) {
+                directive *d = dt->dirs[j];
+                ret = nsapi_exec(d, sn, rq);
+            }
+            
             switch(ret) {
                 case REQ_PROCEED: {
                     char *type = pblock_findkeyval(
@@ -596,38 +613,42 @@
         dtable *dt = object_get_dtable(obj, NSAPIService);
 
         // execute directives
-        for(int j=0;j<dt->ndir;j++) {
-            directive *d = dt->dirs[j];
+        for(int j=NCX_DI(rq);j<dt->ndir;j++) {
+            if(ret == REQ_NOACTION) {
+                directive *d = dt->dirs[j];
 
-            /* check type parameter */           
-            char *dtp = pblock_findkeyval(pb_key_type, d->param);
-            if(dtp) {
-                /* type parameter for directive */
-                if(!content_type) {
-                    content_type = pblock_findkeyval(
-                            pb_key_content_type,
-                            rq->rq.srvhdrs);
-                }
-                /* compare types */
-                if(strcmp(dtp, content_type) != 0) {
-                    continue;
-                }
-            }
-
-            /* check method parameter */
-            char *dmt = pblock_findkeyval(pb_key_method, d->param);
-            if(dmt) {
-                if(!method) {
-                    method = pblock_findkeyval(pb_key_method, rq->rq.reqpb);
+                /* check type parameter */           
+                char *dtp = pblock_findkeyval(pb_key_type, d->param);
+                if(dtp) {
+                    /* type parameter for directive */
+                    if(!content_type) {
+                        content_type = pblock_findkeyval(
+                                pb_key_content_type,
+                                rq->rq.srvhdrs);
+                    }
+                    /* compare types */
+                    if(strcmp(dtp, content_type) != 0) {
+                        continue;
+                    }
                 }
 
-                if(!method_match(dmt, method)) {
-                    continue;
+                /* check method parameter */
+                char *dmt = pblock_findkeyval(pb_key_method, d->param);
+                if(dmt) {
+                    if(!method) {
+                        method = pblock_findkeyval(pb_key_method, rq->rq.reqpb);
+                    }
+                    
+                    if(!method_match(dmt, method)) {
+                        continue;
+                    }
                 }
+
+                /* execute the saf */
+                ret = nsapi_exec(d, sn, rq);
             }
-
-            /* execute the saf */
-            ret = d->func->func(d->param, (Session*)sn, (Request*)rq);
+            
+            
             if(ret != REQ_PROCEED) {
                 fprintf(stderr, "saf not proceed\n");
             }
@@ -648,6 +669,105 @@
     return ret;
 }
 
+struct _tpd_data {
+    NSAPISession *sn;
+    NSAPIRequest *rq;
+    directive    *directive;
+    threadpool_t *threadpool;
+};
+
+int nsapi_exec(directive *d, NSAPISession *sn, NSAPIRequest *rq) {
+    // TODO: condition
+    
+    char *poolname = pblock_findkeyval(pb_key_pool, d->param);
+    if(poolname) {
+        threadpool_t *pool = get_threadpool(sstr(poolname));
+        if(pool && pool != sn->currentpool) {
+            // execute directive in different thread pool
+            return nsapi_exec_tp(d, sn, rq, pool);
+        }
+    } else if(sn->currentpool != sn->defaultpool) {
+        // if no pool is set, use always the default thread pool
+        return nsapi_exec_tp(d, sn, rq, sn->defaultpool);
+    }
+    
+    return d->func->func(d->param, (Session*)sn, (Request*)rq);
+}
+
+int nsapi_exec_tp(
+        directive *d,
+        NSAPISession *sn,
+        NSAPIRequest *rq,
+        threadpool_t *pool)
+{
+    struct  _tpd_data *data = malloc(sizeof(struct _tpd_data));
+    if(data == NULL) {
+        // TODO: set error
+        return REQ_ABORTED;
+    }
+    data->sn = sn;
+    data->rq = rq;
+    data->directive  = d;
+    data->threadpool = pool;
+    
+    sn->currentpool = pool;
+    threadpool_run(pool, thrpool_exec, data);
+    
+    return REQ_PROCESSING;
+}
+
+void nsapi_function_return(Session *session, Request *request, int ret) {
+    NSAPISession *sn = (NSAPISession*)session;
+    NSAPIRequest *rq = (NSAPIRequest*)request;
+    
+    rq->context.last_req_code = ret;
+    
+    if(sn->currentpool != sn->defaultpool) {
+        nsapi_change_threadpool(sn, rq, sn->defaultpool);
+    } else {
+        nsapi_handle_request(sn, rq);
+    }
+}
+
+void nsapi_change_threadpool(
+        NSAPISession *sn,
+        NSAPIRequest *rq,
+        threadpool_t *thrpool)
+{ 
+    struct  _tpd_data *data = malloc(sizeof(struct _tpd_data));
+    data->sn = sn;
+    data->rq = rq;
+    data->threadpool = thrpool;
+    
+    threadpool_run(thrpool, thrpool_change, data);
+}
+
+void* thrpool_exec(void *d) {
+    struct _tpd_data *data = d;
+    
+    data->sn->currentpool = data->threadpool;
+    int r = data->directive->func->func(
+            data->directive->param,
+            (Session*)data->sn,
+            (Request*)data->rq);
+    
+    free(data);
+    
+    nsapi_function_return((Session*)data->sn, (Request*)data->rq, r);
+    
+    return NULL;
+}
+
+void* thrpool_change(void *d) {
+    struct _tpd_data *data = d;
+    
+    data->sn->currentpool = data->threadpool;
+    nsapi_handle_request(data->sn, data->rq);
+    
+    free(data);
+    return NULL;
+}
+
 
 /*
  * checks if the method matches the cmp string
--- a/src/server/daemon/httprequest.h	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/httprequest.h	Sat Dec 15 16:05:03 2012 +0100
@@ -71,7 +71,13 @@
 
 HTTPRequest *http_request_new();
 
-int handle_request(HTTPRequest *request);
+/*
+ * starts request processing after reading the request header
+ * 
+ * request: request object
+ * pool:    current thread pool or NULL
+ */
+int handle_request(HTTPRequest *request, threadpool_t *pool);
 
 
 
@@ -87,6 +93,25 @@
 int nsapi_objecttype(NSAPISession *sn, NSAPIRequest *rq);
 int nsapi_service(NSAPISession *sn, NSAPIRequest *rq);
 
+int nsapi_exec(directive *d, NSAPISession *sn, NSAPIRequest *rq);
+
+int nsapi_exec_tp(
+        directive *d,
+        NSAPISession *sn,
+        NSAPIRequest *rq,
+        threadpool_t *pool);
+
+void nsapi_function_return(Session *sn, Request *rq, int ret);
+
+void nsapi_change_threadpool(
+        NSAPISession *sn,
+        NSAPIRequest *rq,
+        threadpool_t *thrpool);
+
+void* thrpool_exec(void *d);
+
+void* thrpool_change(void *data);
+
 
 int add_objects(
         HTTPObjectConfig *objs,
--- a/src/server/daemon/session.h	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/session.h	Sat Dec 15 16:05:03 2012 +0100
@@ -30,6 +30,7 @@
 #define	SESSION_H
 
 #include "../public/nsapi.h"
+#include "../util/thrpool.h"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -38,8 +39,10 @@
 typedef struct NSAPISession NSAPISession;
 
 struct NSAPISession {
-    Session sn; /* public session structure */
-    int sys_fd; /* system file descriptor */
+    Session      sn; /* public session structure */
+    int          sys_fd; /* system file descriptor */
+    threadpool_t *currentpool;
+    threadpool_t *defaultpool;
 };
 
 NSAPI_PUBLIC char *session_dns_lookup(Session *s, int verify);
--- a/src/server/daemon/sessionhandler.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/sessionhandler.c	Sat Dec 15 16:05:03 2012 +0100
@@ -99,7 +99,7 @@
     }
 
     // process request
-    r = handle_request(request);
+    r = handle_request(request, NULL); // TODO: use correct thread pool
 
 
     return NULL;
@@ -212,5 +212,5 @@
     }
     
     // process request
-    r = handle_request(request);
+    r = handle_request(request, NULL);
 }
--- a/src/server/daemon/threadpools.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/threadpools.c	Sat Dec 15 16:05:03 2012 +0100
@@ -42,6 +42,8 @@
 threadpool_t *last_thrpool_c = NULL;
 
 int create_threadpool(sstr_t name, ThreadPoolConfig *cfg) {
+    // TODO: use ThreadPoolConfig
+    
     if(thread_pool_map == NULL) {
         thread_pool_map = ucx_map_new(16);
     }
@@ -87,3 +89,6 @@
     return default_thread_pool;
 }
 
+threadpool_t* get_threadpool(sstr_t name) {
+    return ucx_map_sstr_get(thread_pool_map, name);
+}
--- a/src/server/daemon/threadpools.h	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/threadpools.h	Sat Dec 15 16:05:03 2012 +0100
@@ -49,6 +49,7 @@
 int check_thread_pool_cfg();
 
 threadpool_t* get_default_threadpool();
+threadpool_t* get_threadpool(sstr_t name);
 
 #ifdef	__cplusplus
 }
--- a/src/server/daemon/ws-fn.c	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/daemon/ws-fn.c	Sat Dec 15 16:05:03 2012 +0100
@@ -34,6 +34,7 @@
 #include "../safs/objecttype.h"
 #include "../safs/service.h"
 #include "../safs/init.h"
+#include "../safs/common.h"
 #include "../webdav/webdav.h"
 
 #include "../admin/adminui.h"
@@ -52,5 +53,6 @@
     { "admin-index", adm_index, NULL, 0},
     { "auth-basic", auth_basic, NULL, 0 },
     { "require-auth", require_auth, NULL, 0},
+    { "print-message", print_message, NULL, 0},
     {NULL, NULL, NULL, 0}
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/safs/common.c	Sat Dec 15 16:05:03 2012 +0100
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "common.h"
+
+#include "../daemon/httprequest.h"
+#include "../daemon/log.h"
+
+int print_message(pblock *pb, Session *sn, Request *rq) {
+    char *msg = pblock_findval("msg", pb);
+    if(msg) {
+        printf("%s\n", msg);
+        log_ereport(LOG_LEVEL_INFO, "%s", msg);
+    }    
+    
+    return REQ_NOACTION;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/safs/common.h	Sat Dec 15 16:05:03 2012 +0100
@@ -0,0 +1,46 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef COMMON_H
+#define	COMMON_H
+
+#include "../public/nsapi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+int print_message(pblock *pb, Session *sn, Request *rq);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* COMMON_H */
+
--- a/src/server/safs/objs.mk	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/safs/objs.mk	Sat Dec 15 16:05:03 2012 +0100
@@ -36,6 +36,7 @@
 SAFOBJ += init.o
 SAFOBJ += auth.o
 SAFOBJ += pathcheck.o
+SAFOBJ += common.o
 
 SAFOBJS = $(SAFOBJ:%=$(SAFS_OBJPRE)%)
 SAFSOURCE = $(SAFOBJ:%.o=safs/%.c)
--- a/src/server/util/pblock.cpp	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/util/pblock.cpp	Sat Dec 15 16:05:03 2012 +0100
@@ -251,6 +251,7 @@
 const pb_key *const pb_key_path_info = _create_key("path-info");
 const pb_key *const pb_key_pblock = _create_key("pblock");
 const pb_key *const pb_key_poll_interval = _create_key("poll-interval");
+const pb_key *const pb_key_pool = _create_key("pool"); // new
 const pb_key *const pb_key_port = _create_key("port");
 const pb_key *const pb_key_ppath = _create_key("ppath");
 const pb_key *const pb_key_pragma = _create_key("pragma");
--- a/src/server/util/pblock.h	Sat Oct 06 13:00:07 2012 +0200
+++ b/src/server/util/pblock.h	Sat Dec 15 16:05:03 2012 +0100
@@ -229,6 +229,7 @@
 BASE_DLL extern const pb_key *const pb_key_path_info;
 BASE_DLL extern const pb_key *const pb_key_pblock;
 BASE_DLL extern const pb_key *const pb_key_poll_interval;
+BASE_DLL extern const pb_key *const pb_key_pool; // new
 BASE_DLL extern const pb_key *const pb_key_port;
 BASE_DLL extern const pb_key *const pb_key_ppath;
 BASE_DLL extern const pb_key *const pb_key_pragma;
--- a/templates/conf/server.conf	Sat Oct 06 13:00:07 2012 +0200
+++ b/templates/conf/server.conf	Sat Dec 15 16:05:03 2012 +0100
@@ -18,6 +18,12 @@
     Default     true
 </EventHandler>
 
+<Threadpool>
+    Name        default
+    MinThreads  4
+    MaxThreads  32
+</Threadpool>
+
 <AuthDB>
     Name        keyfile
     Type        keyfile

mercurial