1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
53 PGconn *test_connection = PQconnectdb(connection);
54
55
56 pg_check_connection(
LOG_WARN, rpname, test_connection);
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 return 1;
87 }
88 return 0;
89 }
90
91
92 void pg_resourcepool_destroy(PgResourcePool *pg) {
93
94 }
95
96 void * pg_resourcepool_createresource(PgResourcePool *pg) {
97 PGconn *connection = PQconnectdb(pg->connection);
98 if(pg_check_connection(
LOG_FAILURE, pg->name, connection)) {
99 return NULL;
100 }
101
102 PgResource *res = pool_malloc(pg->pool,
sizeof(PgResource));
103 if(!res) {
104 PQfinish(connection);
105 log_ereport(
LOG_CATASTROPHE,
"pg_resourcepool_createresource: OOM");
106 return NULL;
107 }
108 res->connection = connection;
109
110 return res;
111 }
112
113 void pg_resourcepool_freeresource(PgResourcePool *pg, PgResource *res) {
114 if(res->connection) {
115 PQfinish(res->connection);
116 }
117 pool_free(pg->pool, res);
118 }
119
120 int pg_resourcepool_prepare(PgResourcePool *pg, PgResource *res) {
121 PGresult *result = PQexec(res->connection,
"BEGIN");
122 PQclear(result);
123 return 0;
124 }
125
126 int pg_resourcepool_finish(PgResourcePool *pg, PgResource *res) {
127 PGresult *result = PQexec(res->connection,
"COMMIT");
128 if(PQresultStatus(result) !=
PGRES_COMMAND_OK) {
129 log_ereport(
LOG_FAILURE,
"pg_dav_proppatch_finish: COMMIT failed failed: %s", PQerrorMessage(res->connection));
130 }
131 PQclear(result);
132 return 0;
133 }
134
135 void * pg_resourcepool_getresourcedata(PgResource *res) {
136 return res->connection;
137 }
138