Sat, 22 Jan 2022 11:06:11 +0100
add ResourcePool initialization
--- 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