Apache发布存储在PostGIS数据库栅格数据的数据库连接池版本(效率好像没有提升)

直接上代码:

#ifndef CDATABASE_CONNECTION_POOL_H
#define CDATABASE_CONNECTION_POOL_H

#include <libpq-fe.h>
#include <windows.h>  // 使用 Windows 线程库

// Initialize the database connection pool
void initConnectionPool(int poolSize, const char* conninfo);

// Get a connection from the pool
PGconn* getConnectionFromPool();

// Return a connection to the pool
void releaseConnectionToPool(PGconn* conn);

#endif // CDATABASE_CONNECTION_POOL_H
#include "CDatabaseConnectionPool.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    PGconn** connections;
    int poolSize;
    int currentSize;
    CRITICAL_SECTION lock;  // 使用 Windows 的临界区对象来替代 pthread_mutex_t
} ConnectionPool;

static ConnectionPool pool;

void initConnectionPool(int poolSize, const char* conninfo) {
    pool.connections = (PGconn**)malloc(poolSize * sizeof(PGconn*));
    if (!pool.connections) {
        fprintf(stderr, "Failed to allocate memory for connection pool.\n");
        return;
    }
    pool.poolSize = poolSize;
    pool.currentSize = 0;
    InitializeCriticalSection(&pool.lock);  // 初始化临界区对象

    for (int i = 0; i < poolSize; i++) {
        PGconn* conn = PQconnectdb(conninfo);
        if (PQstatus(conn) == CONNECTION_BAD) {
            fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn));
            PQfinish(conn);
        }
        else {
            pool.connections[pool.currentSize++] = conn;
            fprintf(stderr, "Connection %d created and added to pool.\n", i);
        }
    }
}

PGconn* getConnectionFromPool() {
    PGconn* conn = NULL;
    EnterCriticalSection(&pool.lock);  // 进入临界区

    if (pool.currentSize > 0) {
        conn = pool.connections[--pool.currentSize];
        fprintf(stderr, "Connection retrieved from pool. Remaining connections: %d\n", pool.currentSize);
    }
    else {
        fprintf(stderr, "No connections available in pool.\n");
    }

    LeaveCriticalSection(&pool.lock);  // 离开临界区
    return conn;
}

void releaseConnectionToPool(PGconn* conn) {
    EnterCriticalSection(&pool.lock);  // 进入临界区

    if (pool.currentSize < pool.poolSize) {
        pool.connections[pool.currentSize++] = conn;
        fprintf(stderr, "Connection returned to pool. Available connections: %d\n", pool.currentSize);
    }
    else {
        PQfinish(conn);  // 如果连接池已满,则关闭此连接
        fprintf(stderr, "Connection discarded as pool is full.\n");
    }

    LeaveCriticalSection(&pool.lock);  // 离开临界区
}
#ifndef TILE_DATABASE_HANDLER_H
#define TILE_DATABASE_HANDLER_H

#include <libpq-fe.h>
#include <stdlib.h>

typedef struct {
    PGconn* conn;
} TileDatabaseHandler;

// Create and initialize the TileDatabaseHandler from the connection pool
TileDatabaseHandler* createTileDatabaseHandlerFromPool();

// Destroy the TileDatabaseHandler and free its resources
void destroyTileDatabaseHandler(TileDatabaseHandler* handler);

// Get the tile data from the database given z, x, y coordinates
char* getTile(TileDatabaseHandler* handler, int z, int x, int y, size_t* dataLength);

#endif // TILE_DATABASE_HANDLER_H
#include "TileDatabaseHandler.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "CDatabaseConnectionPool.h"

// Function to create and initialize TileDatabaseHandler from the connection pool
TileDatabaseHandler* createTileDatabaseHandlerFromPool() {
    PGconn* conn = getConnectionFromPool();
    if (!conn) {
        fprintf(stderr, "Failed to get a connection from the pool\n");
        return NULL;
    }
    TileDatabaseHandler* handler = (TileDatabaseHandler*)malloc(sizeof(TileDatabaseHandler));
    if (!handler) {
        releaseConnectionToPool(conn);
        fprintf(stderr, "Failed to allocate memory for TileDatabaseHandler\n");
        return NULL;
    }
    handler->conn = conn;
    return handler;
}

// Function to destroy the TileDatabaseHandler and return the connection to the pool
void destroyTileDatabaseHandler(TileDatabaseHandler* handler) {
    if (handler) {
        if (handler->conn) {
            releaseConnectionToPool(handler->conn);
        }
        free(handler);
    }
}

// Function to get tile data from the database given z, x, y coordinates
char* getTile(TileDatabaseHandler* handler, int z, int x, int y, size_t* dataLength) {
    if (!handler || !handler->conn) return NULL;

    const char* queryTemplate = "SELECT data FROM Tile WHERE z = $1 AND x = $2 AND y = $3";

    const char* params[3];
    char zStr[12];
    char xStr[12];
    char yStr[12];

    snprintf(zStr, sizeof(zStr), "%d", z - 1);
    snprintf(xStr, sizeof(xStr), "%d", x);
    snprintf(yStr, sizeof(yStr), "%d", y);

    params[0] = zStr;
    params[1] = xStr;
    params[2] = yStr;

    PGresult* res = PQexecParams(handler->conn, queryTemplate, 3, NULL, params, NULL, NULL, 1);

    if (PQresultStatus(res) != PGRES_TUPLES_OK) {
        fprintf(stderr, "SELECT failed: %s", PQerrorMessage(handler->conn));
        PQclear(res);
        return NULL;
    }

    if (PQntuples(res) == 0) {
        PQclear(res);
        return NULL;
    }

    *dataLength = PQgetlength(res, 0, 0);
    if (*dataLength == 0) {
        PQclear(res);
        return NULL;
    }

    char* tileData = (char*)malloc(*dataLength);
    if (!tileData) {
        PQclear(res);
        fprintf(stderr, "Failed to allocate memory for tile data\n");
        return NULL;
    }

    memcpy(tileData, PQgetvalue(res, 0, 0), *dataLength);
    PQclear(res);

    return tileData;
}
#include "httpd.h"
#include "http_log.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <apr_pools.h>
#include <apr_tables.h>
#include <apr_strings.h>
#include <apr_hash.h>

#include "TileDatabaseHandler.h"
#include "CDatabaseConnectionPool.h"

typedef struct {
    TileDatabaseHandler* dbHandler;
    char* tileDataBuffer;
    size_t tileDataLength;
} tilehandler_context;

static apr_hash_t* tileCache;
static tilehandler_context* sharedContext = NULL;

tilehandler_context* create_tilehandler_context() {
    tilehandler_context* context = (tilehandler_context*)malloc(sizeof(tilehandler_context));
    if (context) {
        context->dbHandler = createTileDatabaseHandlerFromPool();
        context->tileDataBuffer = NULL;
        context->tileDataLength = 0;
    }
    return context;
}

void destroy_tilehandler_context(tilehandler_context* context) {
    if (context) {
        if (context->tileDataBuffer) {
            free(context->tileDataBuffer);
        }
        destroyTileDatabaseHandler(context->dbHandler);
        free(context);
    }
}

const char* get_tile_data(tilehandler_context* context, int z, int x, int y) {
    if (!context) return NULL;

    char key[64];
    snprintf(key, sizeof(key), "%d:%d:%d", z, x, y);

    char* cachedTileData = apr_hash_get(tileCache, key, APR_HASH_KEY_STRING);

    if (cachedTileData) {
        context->tileDataBuffer = cachedTileData;
        context->tileDataLength = strlen(cachedTileData);
        return context->tileDataBuffer;
    }

    context->tileDataBuffer = getTile(context->dbHandler, z, x, y, &(context->tileDataLength));

    if (context->tileDataBuffer && context->tileDataLength > 0) {
        char* tileDataCopy = apr_pstrdup(apr_hash_pool_get(tileCache), context->tileDataBuffer);
        apr_hash_set(tileCache, apr_pstrdup(apr_hash_pool_get(tileCache), key), APR_HASH_KEY_STRING, tileDataCopy);
    }

    return context->tileDataBuffer;
}

static int tilehandler_module_handler(request_rec* r) {
    if (strcmp(r->handler, "tilehandler_module")) {
        return DECLINED;
    }

    if (r->method_number != M_GET) {
        return HTTP_METHOD_NOT_ALLOWED;
    }

    int z, x, y;
    if (sscanf(r->uri, "/tiles/%d/%d/%d", &z, &x, &y) != 3) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Failed to parse URI: %s", r->uri);
        return HTTP_BAD_REQUEST;
    }

    if (!sharedContext) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Shared context is not initialized");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    const char* tileData = get_tile_data(sharedContext, z, x, y);

    if (tileData && sharedContext->tileDataLength > 0) {
        ap_set_content_type(r, "image/jpeg");
        apr_table_setn(r->headers_out, "Content-Length", apr_psprintf(r->pool, "%zu", sharedContext->tileDataLength));
        ap_rwrite(tileData, sharedContext->tileDataLength, r);
    }
    else {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Tile not found for z=%d, x=%d, y=%d", z, x, y);
        ap_set_content_type(r, "text/plain");
        ap_rprintf(r, "Tile not found");
        return HTTP_NOT_FOUND;
    }

    return OK;
}

static int tilehandler_module_init(apr_pool_t* pool, apr_pool_t* plog, apr_pool_t* ptemp, server_rec* s) {
    sharedContext = create_tilehandler_context();
    if (!sharedContext) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Failed to initialize shared tilehandler context");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    tileCache = apr_hash_make(pool);
    return OK;
}

static void tilehandler_module_child_init(apr_pool_t* p, server_rec* s) {
    initConnectionPool(10, "host=192.168.101.201 port=4321 dbname=Tile user=postgres password=root");
}

static void tilehandler_module_register_hooks(apr_pool_t* p) {
    ap_hook_child_init(tilehandler_module_child_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_handler(tilehandler_module_handler, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_config(tilehandler_module_init, NULL, NULL, APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA tilehandler_module = {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    tilehandler_module_register_hooks
};

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值