Sat, 22 Jan 2022 19:13:40 +0100
add first code for postgresql plugin: resourcepool type implementation
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * 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: * * 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 "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_register_type(const char *type_name, ResourceType *type_info) { if(ucx_map_cstr_put(resource_pool_types, type_name, type_info)) { log_ereport(LOG_CATASTROPHE, "resourcepool_register_type: OOM"); return 1; } return 0; } 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, name.ptr, 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; NSAPISession *session = (NSAPISession*)sn; ServerConfiguration *cfg = session->config; ResourceDataPrivate *res = NULL; // was this resource already used by this request? if(request->resources) { res = ucx_map_cstr_get(request->resources, name); if(res) { return (ResourceData*)res; } } // 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 }