src/server/plugins/postgresql/resource.c

changeset 385
a1f4cb076d2f
parent 382
9e2289c77b04
child 389
c6c5638e97b8
equal deleted inserted replaced
210:21274e5950af 385:a1f4cb076d2f
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2022 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "resource.h"
30
31 static ResourceType pg_resource_type = {
32 (resource_pool_init_func)pg_resourcepool_init,
33 (resource_pool_destroy_func)pg_resourcepool_destroy,
34 (resource_pool_createresource_func)pg_resourcepool_createresource,
35 (resource_pool_freeresource_func)pg_resourcepool_freeresource,
36 (resource_pool_prepare_func)pg_resourcepool_prepare,
37 (resource_pool_finish_func)pg_resourcepool_finish,
38 (resource_pool_getresourcedata_func)pg_resourcepool_getresourcedata
39 };
40
41 ResourceType* pg_get_resource_type(void) {
42 return &pg_resource_type;
43 }
44
45 void * pg_resourcepool_init(pool_handle_t *pool, const char *rpname, pblock *pb) {
46 char *connection = pblock_findval("Connection", pb);
47 if(!connection) {
48 log_ereport(LOG_MISCONFIG, "Resource pool %s: Missing Connection parameter", rpname);
49 return NULL;
50 }
51
52 // test connection
53 PGconn *test_connection = PQconnectdb(connection);
54 if(pg_check_connection(LOG_WARN, rpname, test_connection)) {
55 log_ereport(LOG_WARN, "Resource pool %s: Connection check failed", rpname);
56 }
57 if(test_connection) PQfinish(test_connection);
58
59 PgResourcePool *pg = pool_malloc(pool, sizeof(PgResourcePool));
60 if(!pg) {
61 return NULL;
62 }
63 pg->pool = pool;
64 pg->name = rpname;
65 pg->connection = connection;
66
67 return pg;
68
69 }
70
71 int pg_check_connection(int loglevel, const char *rpname, PGconn *connection) {
72 if(!connection) {
73 log_ereport(loglevel, "Resource pool %s: Cannot create PQ connection", rpname);
74 return 1;
75 }
76 if(PQstatus(connection) != CONNECTION_OK) {
77 char *err = PQerrorMessage(connection);
78 int errlen = 0;
79 if(err) {
80 errlen = strlen(err);
81 if(errlen > 0 && err[errlen-1] == '\n') {
82 errlen--;
83 }
84 }
85 log_ereport(loglevel, "Resource pool %s: Failed to connect to database: %.*s", rpname, errlen, err);
86 PQfinish(connection);
87 return 1;
88 }
89 return 0;
90 }
91
92
93 void pg_resourcepool_destroy(PgResourcePool *pg) {
94 // unused
95 }
96
97 void * pg_resourcepool_createresource(PgResourcePool *pg) {
98 PGconn *connection = PQconnectdb(pg->connection);
99 if(pg_check_connection(LOG_FAILURE, pg->name, connection)) {
100 return NULL;
101 }
102
103 PgResource *res = pool_malloc(pg->pool, sizeof(PgResource));
104 if(!res) {
105 PQfinish(connection);
106 log_ereport(LOG_CATASTROPHE, "pg_resourcepool_createresource: OOM");
107 return NULL;
108 }
109 res->connection = connection;
110
111 return res;
112 }
113
114 void pg_resourcepool_freeresource(PgResourcePool *pg, PgResource *res) {
115 if(res->connection) {
116 PQfinish(res->connection);
117 }
118 pool_free(pg->pool, res);
119 }
120
121 int pg_resourcepool_prepare(PgResourcePool *pg, PgResource *res) {
122 PGresult *result = PQexec(res->connection, "BEGIN");
123 PQclear(result); // TODO: handle error
124 return 0;
125 }
126
127 int pg_resourcepool_finish(PgResourcePool *pg, PgResource *res) {
128 PGresult *result = PQexec(res->connection, "COMMIT");
129 if(PQresultStatus(result) != PGRES_COMMAND_OK) {
130 log_ereport(LOG_FAILURE, "pg_dav_proppatch_finish: COMMIT failed failed: %s", PQerrorMessage(res->connection));
131 }
132 PQclear(result);
133 return 0;
134 }
135
136 void * pg_resourcepool_getresourcedata(PgResource *res) {
137 return res->connection;
138 }

mercurial