add ResourcePool initialization webdav

Sat, 22 Jan 2022 11:06:11 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 22 Jan 2022 11:06:11 +0100
branch
webdav
changeset 269
3dfbd0b91950
parent 268
65ac1342ba1f
child 270
4cfaa02055cd

add ResourcePool initialization

src/server/config/serverconfig.c file | annotate | diff | comparison | revisions
src/server/config/serverconfig.h file | annotate | diff | comparison | revisions
src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/config.h file | annotate | diff | comparison | revisions
src/server/daemon/resourcepool.c file | annotate | diff | comparison | revisions
src/server/daemon/resourcepool.h file | annotate | diff | comparison | revisions
src/server/daemon/vfs.c file | annotate | diff | comparison | revisions
src/server/daemon/webserver.c file | annotate | diff | comparison | revisions
src/server/public/nsapi.h file | annotate | diff | comparison | revisions
--- a/src/server/config/serverconfig.c	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/config/serverconfig.c	Sat Jan 22 11:06:11 2022 +0100
@@ -193,7 +193,7 @@
         //printf("%s [%.*s]\n", token_type_str(token.type), (int)token.content.length, token.content.ptr);
         
         switch(token.type) {
-            CFG_NO_TOKEN: break;
+            case CFG_NO_TOKEN: break;
             case CFG_TOKEN_COMMENT: {
                 if(current->type == CONFIG_NODE_SPACE) {
                     current->type = CONFIG_NODE_COMMENT;
@@ -321,3 +321,20 @@
     }
     return scstrn(NULL, 0);
 }
+
+sstr_t serverconfig_arg_name_value(UcxAllocator *a, scstr_t str, scstr_t *name) {
+    int valstart = 0;
+    for(int i=0;i<str.length;i++) {
+        if(str.ptr[i] == '=') {
+            if(name) {
+                name->ptr = str.ptr;
+                name->length = i;
+            }
+            valstart = i + 1;
+            break;
+        }
+    }
+    
+    sstr_t ret;
+    return ret;
+}
--- a/src/server/config/serverconfig.h	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/config/serverconfig.h	Sat Jan 22 11:06:11 2022 +0100
@@ -102,6 +102,8 @@
 
 scstr_t serverconfig_directive_value(ConfigNode *obj, scstr_t name);
 
+sstr_t serverconfig_arg_name_value(UcxAllocator *a, scstr_t str, scstr_t *name);
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/server/daemon/config.c	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/daemon/config.c	Sat Jan 22 11:06:11 2022 +0100
@@ -48,6 +48,7 @@
 #include "threadpools.h"
 #include "ldap_auth.h"
 #include "configmanager.h"
+#include "resourcepool.h"
 
 #include "vserver.h"
 #include "../util/pblock.h"
@@ -268,6 +269,13 @@
     }
     ucx_list_free(list);
     
+    list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("ResourcePool"));
+    UCX_FOREACH(elm, list) {
+        ConfigNode *scfgobj = elm->data;
+        if(cfg_handle_resourcepool(serverconfig, scfgobj)) {
+            return NULL;
+        }
+    }
 
     // set VirtualServer for all listeners
     UcxList *ls = serverconfig->listeners;
@@ -416,6 +424,18 @@
     return create_event_handler(&evcfg);
 }
 
+int cfg_handle_resourcepool(ServerConfiguration *cfg, ConfigNode *obj) {
+    scstr_t name = serverconfig_directive_value(obj, SC("Name"));
+    scstr_t type = serverconfig_directive_value(obj, SC("Type"));
+    
+    int ret = 0;
+    if(resourcepool_new(cfg, name, type, obj)) {
+        ret = 1;
+    }
+    
+    return ret;
+}
+
 int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj) {
     // TODO: use a name to identify the log file
     
@@ -890,3 +910,15 @@
     
     return ret;
 }
+
+pblock* config_obj2pblock(pool_handle_t *pool, ConfigNode *obj) {
+    pblock *pb = pblock_create_pool(pool, 8);
+    UCX_FOREACH(elm, obj->children) {
+        ConfigNode *d = elm->data;
+        if(d->type == CONFIG_NODE_DIRECTIVE && d->name.length > 0 && ucx_list_size(d->args) == 1) {
+            ConfigArg *arg = d->args->data;
+            pblock_nvlinsert(d->name.ptr, d->name.length, arg->value.ptr, arg->value.length, pb);
+        }
+    }
+    return pb;
+}
--- a/src/server/daemon/config.h	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/daemon/config.h	Sat Jan 22 11:06:11 2022 +0100
@@ -88,6 +88,8 @@
 
 int cfg_handle_eventhandler(ServerConfiguration *cfg, ConfigNode *obj);
 
+int cfg_handle_resourcepool(ServerConfiguration *cfg, ConfigNode *obj);
+
 int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj);
 
 int cfg_handle_authdb(ServerConfiguration *cfg, ConfigNode *obj);
@@ -107,7 +109,7 @@
 ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl);
 AuthDB* keyfile_load(ServerConfiguration *cfg, scstr_t file);
 
-
+pblock* config_obj2pblock(pool_handle_t *pool, ConfigNode *obj);
 
 #ifdef	__cplusplus
 }
--- a/src/server/daemon/resourcepool.c	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/daemon/resourcepool.c	Sat Jan 22 11:06:11 2022 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2020 Olaf Wintermann. All rights reserved.
+ * Copyright 2022 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:
@@ -29,6 +29,100 @@
 #include "resourcepool.h"
 #include "request.h"
 #include "session.h"
+#include "../public/nsapi.h"
+
+#define RESOURCE_POOL_MAX_DEFAULT 32
+
+#define RESOURCE_POOL_MAX_ALLOC 268435455
+
+static UcxMap *resource_pool_types;
+
+int init_resource_pools(void) {
+    resource_pool_types = ucx_map_new(4);
+    return resource_pool_types ? 0 : 1;
+}
+
+
+
+int resourcepool_new(ServerConfiguration *cfg, scstr_t type, scstr_t name, ConfigNode *node) {
+    ResourceType *restype = ucx_map_sstr_get(resource_pool_types, type);
+    if(!restype) {
+        log_ereport(LOG_MISCONFIG, "Unknown resource pool type: %s", type.ptr);
+        return 1;
+    }
+    
+    // convert ConfigNode to pblock
+    // no sub-objects allowed for this specific ConfigNode, therefore
+    // it can be represented as key-value-pairs
+    pblock *param = config_obj2pblock(cfg->pool, node);
+    if(!param) {
+        log_ereport(LOG_FAILURE, "resourcepool_new: OOM");
+        return 1;
+    }
+    
+    ResourcePool *respool = pool_malloc(cfg->pool, sizeof(ResourcePool));
+    if(!respool) {
+        log_ereport(LOG_FAILURE, "resourcepool_new: OOM");
+        return 1;
+    }
+    respool->pool = cfg->pool;
+    
+    void *respool_data = restype->init(cfg->pool, param);
+    if(!respool_data) {
+        log_ereport(LOG_FAILURE, "Cannot create resource pool data: pool: %s type: %s", name.ptr, type.ptr);
+        return 1;
+    }
+    
+    respool->type = restype;
+    respool->data = respool_data;
+    respool->min = 0; // TODO: get from node
+    respool->max = RESOURCE_POOL_MAX_DEFAULT; // TODO: get from node
+    
+    // don't allow too large resource pools
+    // this prevents the need to check malloc integer overflows
+    if(respool->max > RESOURCE_POOL_MAX_ALLOC) {
+        respool->max = RESOURCE_POOL_MAX_ALLOC;
+        log_ereport(LOG_WARN, "Resource pool %s: limit max to %d", name.ptr, respool->max);
+    }
+    
+    respool->resalloc = respool->max;
+    respool->resources = pool_malloc(cfg->pool, respool->resalloc * sizeof(void*));
+    
+    if(!respool->resources || ucx_map_sstr_put(cfg->resources, name, respool)) {
+        log_ereport(LOG_FAILURE, "Cannot add resource pool: OOM");
+        // the only cleanup we have to do
+        restype->destroy(respool_data);
+        return 1;
+    }
+    
+    pthread_mutex_init(&respool->lock, NULL);
+    pthread_cond_init(&respool->available, NULL);
+    
+    if(resourcepool_create_resources(respool, respool->max)) {
+        log_ereport(LOG_FAILURE, "Resource pool %s: Cannot create resources", name.ptr);
+        resourcepool_destroy(respool);
+        return 1;
+    }
+    
+    return 0;
+}
+
+int resourcepool_create_resources(ResourcePool *pool, int num_res) {
+    if(num_res > pool->resalloc) {
+        num_res = pool->resalloc;
+    }
+    
+    for(int i=pool->numresources;i<num_res;i++) {
+        void *resource = pool->type->createresource(pool->data);
+        if(resource) {
+            pool->resources[pool->numresources++] = resource;
+        } else {
+            return 1; // error
+        }
+    }
+    
+    return 0;
+}
 
 ResourceData* resourcepool_lookup(Session *sn, Request *rq, const char *name, int flags) {
     NSAPIRequest *request = (NSAPIRequest*)rq;
@@ -47,12 +141,21 @@
     
     // TODO: get cached resource
     
+    /*
     ResourceType *type = ucx_map_cstr_get(cfg->resources, name);
     if(!type) {
         return NULL;
     }
+    */
+    
+    
+    return NULL;
 }
 
 void resourcepool_free(ResourceData *data) {
     
 }
+
+void resourcepool_destroy(ResourcePool *respool) {
+    // TODO
+}
--- a/src/server/daemon/resourcepool.h	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/daemon/resourcepool.h	Sat Jan 22 11:06:11 2022 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2020 Olaf Wintermann. All rights reserved.
+ * Copyright 2021 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:
@@ -31,6 +31,10 @@
 
 #include "../public/nsapi.h"
 
+#include "config.h"
+
+#include <pthread.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -45,14 +49,62 @@
 };
 
 struct ResourcePool {
+    /*
+     * Memory pool
+     */
+    pool_handle_t *pool;
+    
+    /*
+     * Type information of this resource pool
+     * The type object is stored in the registered types map and should not
+     * be freed, when the resource pool is destroyed
+     */
     ResourceType *type;
     
+    /*
+     * Data returned by the ResourceType init function
+     * When the pool is destroyed, the data should be passed to
+     * ResourceType.destroy
+     */
+    void *data;
     
+    pthread_mutex_t lock;
+    pthread_cond_t available;
+    
+    /*
+     * Array of available resources
+     * each entry is created with ResourceType.createresource
+     */
+    void **resources;
     
+    /*
+     * Allocated size of the resources array
+     */
+    size_t resalloc;
+    
+    /*
+     * Number of currently available resources in the array
+     */
+    size_t numresources;
+    
+    /*
+     * resource pool min parameter
+     */
     int min;
+    
+    /*
+     * resource pool max parameter
+     */
     int max;
 };
 
+int init_resource_pools(void);
+
+int resourcepool_new(ServerConfiguration *cfg, scstr_t type, scstr_t name, ConfigNode *node);
+
+int resourcepool_create_resources(ResourcePool *pool, int num_res);
+
+void resourcepool_destroy(ResourcePool *respool);
 
 #ifdef __cplusplus
 }
--- a/src/server/daemon/vfs.c	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/daemon/vfs.c	Sat Jan 22 11:06:11 2022 +0100
@@ -419,6 +419,9 @@
     DIR *sys_dir = fdopendir(dir_fd);
 #endif
     if(!sys_dir) {
+        if(dir_fd > 0) {
+            close(dir_fd);
+        }
         if(ctx) {
             ctx->vfs_errno = errno;
             sys_set_error_status(ctx);
--- a/src/server/daemon/webserver.c	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/daemon/webserver.c	Sat Jan 22 11:06:11 2022 +0100
@@ -60,6 +60,7 @@
 #include "log.h"
 #include "auth.h"
 #include "srvctrl.h"
+#include "resourcepool.h"
 
 extern struct FuncStruct webserver_funcs[];
 
@@ -78,6 +79,11 @@
     func_init();
     add_functions(webserver_funcs);
     
+    // init resource pools
+    if(init_resource_pools()) {
+        return -1;
+    }
+    
     // load init.conf
     if(load_init_conf("config/init.conf")) {
         return -1;
--- a/src/server/public/nsapi.h	Thu Jan 20 16:04:58 2022 +0100
+++ b/src/server/public/nsapi.h	Sat Jan 22 11:06:11 2022 +0100
@@ -768,21 +768,23 @@
 typedef struct _http_listener HttpListener;
 
 typedef struct ResourceType ResourceType;
-typedef struct ResourceData    ResourceData;
+typedef struct ResourceData ResourceData;
 
 struct ResourceType {
-    ResourceType * (*init)(pool_handle_t *, pblock *);
-    void           (*destroy)(ResourceType *);
+    void * (*init)(pool_handle_t *, pblock *);
+    void   (*destroy)(void *);
     
-    void *         (*createresource)(ResourceType *, pblock *);
-    void           (*freeresource)(ResourceType *, void *);
+    void * (*createresource)(void *);
+    void   (*freeresource)(void *, void *);
+    int    (*prepare)(void *, void *);
+    int    (*finish)(void *, void *);
 };
 
 struct ResourceData {
+    void *resourcepool;
     void *data;
 };
 
-
 //////
 /*
  * VSInitFunc, VSDestroyFunc, VSDirectiveInitFunc and VSDirectiveDestroyFunc

mercurial