diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-03-22 18:47:07 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-03-22 18:47:07 +0000 |
commit | 4c01d543d10a24b30e279cdb061d9ebe459cdcaf (patch) | |
tree | 3ccec82f8e23c009e7366f421dbfacbf43e01055 | |
parent | 84b6e8491d8712f772a2297d59b2a1f4f21427fa (diff) | |
download | gnunet-4c01d543d10a24b30e279cdb061d9ebe459cdcaf.tar.gz gnunet-4c01d543d10a24b30e279cdb061d9ebe459cdcaf.zip |
adding libgnunetpostgres for shared postgres functionality between postgres datastore/datacache backends
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/datacache/Makefile.am | 1 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_postgres.c | 180 | ||||
-rw-r--r-- | src/datastore/plugin_datastore_postgres.c | 264 | ||||
-rw-r--r-- | src/include/Makefile.am | 1 | ||||
-rw-r--r-- | src/include/gnunet_mysql_lib.h | 2 | ||||
-rw-r--r-- | src/include/gnunet_postgres_lib.h | 163 | ||||
-rw-r--r-- | src/postgres/Makefile.am | 20 | ||||
-rw-r--r-- | src/postgres/postgres.c | 194 |
10 files changed, 466 insertions, 365 deletions
diff --git a/configure.ac b/configure.ac index c9f3d1177..fe5de4c12 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -896,6 +896,7 @@ src/nse/nse.conf | |||
896 | src/peerinfo/Makefile | 896 | src/peerinfo/Makefile |
897 | src/peerinfo/peerinfo.conf | 897 | src/peerinfo/peerinfo.conf |
898 | src/peerinfo-tool/Makefile | 898 | src/peerinfo-tool/Makefile |
899 | src/postgres/Makefile | ||
899 | src/pt/Makefile | 900 | src/pt/Makefile |
900 | src/statistics/Makefile | 901 | src/statistics/Makefile |
901 | src/statistics/statistics.conf | 902 | src/statistics/statistics.conf |
diff --git a/src/Makefile.am b/src/Makefile.am index 06b2aedc4..fc9518558 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -15,6 +15,10 @@ if HAVE_MYSQL | |||
15 | MYSQL_DIR = mysql | 15 | MYSQL_DIR = mysql |
16 | endif | 16 | endif |
17 | 17 | ||
18 | if HAVE_POSTGRES | ||
19 | POSTGRES_DIR = postgres | ||
20 | endif | ||
21 | |||
18 | 22 | ||
19 | SUBDIRS = \ | 23 | SUBDIRS = \ |
20 | include $(INTLEMU_SUBDIRS) \ | 24 | include $(INTLEMU_SUBDIRS) \ |
@@ -26,6 +30,7 @@ SUBDIRS = \ | |||
26 | arm \ | 30 | arm \ |
27 | peerinfo \ | 31 | peerinfo \ |
28 | $(MYSQL_DIR) \ | 32 | $(MYSQL_DIR) \ |
33 | $(POSTGRES_DIR) \ | ||
29 | datacache \ | 34 | datacache \ |
30 | datastore \ | 35 | datastore \ |
31 | namestore \ | 36 | namestore \ |
diff --git a/src/datacache/Makefile.am b/src/datacache/Makefile.am index 88545dcdc..d34e6e8c7 100644 --- a/src/datacache/Makefile.am +++ b/src/datacache/Makefile.am | |||
@@ -70,6 +70,7 @@ libgnunet_plugin_datacache_mysql_la_LDFLAGS = \ | |||
70 | libgnunet_plugin_datacache_postgres_la_SOURCES = \ | 70 | libgnunet_plugin_datacache_postgres_la_SOURCES = \ |
71 | plugin_datacache_postgres.c | 71 | plugin_datacache_postgres.c |
72 | libgnunet_plugin_datacache_postgres_la_LIBADD = \ | 72 | libgnunet_plugin_datacache_postgres_la_LIBADD = \ |
73 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | ||
73 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 74 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
74 | $(top_builddir)/src/util/libgnunetutil.la \ | 75 | $(top_builddir)/src/util/libgnunetutil.la \ |
75 | $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq | 76 | $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq |
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c index 0fabdb4c2..cd4286b92 100644 --- a/src/datacache/plugin_datacache_postgres.c +++ b/src/datacache/plugin_datacache_postgres.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors) | 3 | (C) 2006, 2009, 2010, 2012 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | #include "platform.h" | 26 | #include "platform.h" |
27 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_postgres_lib.h" | ||
28 | #include "gnunet_datacache_plugin.h" | 29 | #include "gnunet_datacache_plugin.h" |
29 | #include <postgresql/libpq-fe.h> | 30 | #include <postgresql/libpq-fe.h> |
30 | 31 | ||
@@ -54,83 +55,6 @@ struct Plugin | |||
54 | 55 | ||
55 | 56 | ||
56 | /** | 57 | /** |
57 | * Check if the result obtained from Postgres has | ||
58 | * the desired status code. If not, log an error, clear the | ||
59 | * result and return GNUNET_SYSERR. | ||
60 | * | ||
61 | * @return GNUNET_OK if the result is acceptable | ||
62 | */ | ||
63 | static int | ||
64 | check_result (struct Plugin *plugin, PGresult * ret, int expected_status, | ||
65 | const char *command, const char *args, int line) | ||
66 | { | ||
67 | if (ret == NULL) | ||
68 | { | ||
69 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
70 | "datastore-postgres", | ||
71 | "Postgres failed to allocate result for `%s:%s' at %d\n", | ||
72 | command, args, line); | ||
73 | return GNUNET_SYSERR; | ||
74 | } | ||
75 | if (PQresultStatus (ret) != expected_status) | ||
76 | { | ||
77 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
78 | "datastore-postgres", | ||
79 | _("`%s:%s' failed at %s:%d with error: %s"), command, args, | ||
80 | __FILE__, line, PQerrorMessage (plugin->dbh)); | ||
81 | PQclear (ret); | ||
82 | return GNUNET_SYSERR; | ||
83 | } | ||
84 | return GNUNET_OK; | ||
85 | } | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Run simple SQL statement (without results). | ||
90 | * | ||
91 | * @param plugin global context | ||
92 | * @param sql statement to run | ||
93 | * @param line code line for error reporting */ | ||
94 | static int | ||
95 | pq_exec (struct Plugin *plugin, const char *sql, int line) | ||
96 | { | ||
97 | PGresult *ret; | ||
98 | |||
99 | ret = PQexec (plugin->dbh, sql); | ||
100 | if (GNUNET_OK != | ||
101 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexec", sql, line)) | ||
102 | return GNUNET_SYSERR; | ||
103 | PQclear (ret); | ||
104 | return GNUNET_OK; | ||
105 | } | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Prepare SQL statement. | ||
110 | * | ||
111 | * @param plugin global context | ||
112 | * @param name name for the prepared SQL statement | ||
113 | * @param sql SQL code to prepare | ||
114 | * @param nparams number of parameters in sql | ||
115 | * @param line code line for error reporting | ||
116 | * @return GNUNET_OK on success | ||
117 | */ | ||
118 | static int | ||
119 | pq_prepare (struct Plugin *plugin, const char *name, const char *sql, | ||
120 | int nparms, int line) | ||
121 | { | ||
122 | PGresult *ret; | ||
123 | |||
124 | ret = PQprepare (plugin->dbh, name, sql, nparms, NULL); | ||
125 | if (GNUNET_OK != | ||
126 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQprepare", sql, line)) | ||
127 | return GNUNET_SYSERR; | ||
128 | PQclear (ret); | ||
129 | return GNUNET_OK; | ||
130 | } | ||
131 | |||
132 | |||
133 | /** | ||
134 | * @brief Get a database handle | 58 | * @brief Get a database handle |
135 | * | 59 | * |
136 | * @param plugin global context | 60 | * @param plugin global context |
@@ -139,31 +63,12 @@ pq_prepare (struct Plugin *plugin, const char *name, const char *sql, | |||
139 | static int | 63 | static int |
140 | init_connection (struct Plugin *plugin) | 64 | init_connection (struct Plugin *plugin) |
141 | { | 65 | { |
142 | char *conninfo; | ||
143 | PGresult *ret; | 66 | PGresult *ret; |
144 | 67 | ||
145 | /* Open database and precompile statements */ | 68 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->env->cfg, |
146 | if (GNUNET_OK != | 69 | "datacache-postgres"); |
147 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | ||
148 | "datacache-postgres", "CONFIG", | ||
149 | &conninfo)) | ||
150 | conninfo = NULL; | ||
151 | plugin->dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); | ||
152 | GNUNET_free_non_null (conninfo); | ||
153 | if (NULL == plugin->dbh) | 70 | if (NULL == plugin->dbh) |
154 | { | ||
155 | /* FIXME: warn about out-of-memory? */ | ||
156 | return GNUNET_SYSERR; | 71 | return GNUNET_SYSERR; |
157 | } | ||
158 | if (PQstatus (plugin->dbh) != CONNECTION_OK) | ||
159 | { | ||
160 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "datacache-postgres", | ||
161 | _("Unable to initialize Postgres: %s"), | ||
162 | PQerrorMessage (plugin->dbh)); | ||
163 | PQfinish (plugin->dbh); | ||
164 | plugin->dbh = NULL; | ||
165 | return GNUNET_SYSERR; | ||
166 | } | ||
167 | ret = | 72 | ret = |
168 | PQexec (plugin->dbh, | 73 | PQexec (plugin->dbh, |
169 | "CREATE TEMPORARY TABLE gn090dc (" | 74 | "CREATE TEMPORARY TABLE gn090dc (" |
@@ -176,8 +81,8 @@ init_connection (struct Plugin *plugin) | |||
176 | (ret, | 81 | (ret, |
177 | PG_DIAG_SQLSTATE))))) | 82 | PG_DIAG_SQLSTATE))))) |
178 | { | 83 | { |
179 | (void) check_result (plugin, ret, PGRES_COMMAND_OK, "CREATE TABLE", | 84 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "CREATE TABLE", |
180 | "gn090dc", __LINE__); | 85 | "gn090dc"); |
181 | PQfinish (plugin->dbh); | 86 | PQfinish (plugin->dbh); |
182 | plugin->dbh = NULL; | 87 | plugin->dbh = NULL; |
183 | return GNUNET_SYSERR; | 88 | return GNUNET_SYSERR; |
@@ -185,10 +90,9 @@ init_connection (struct Plugin *plugin) | |||
185 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) | 90 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) |
186 | { | 91 | { |
187 | if ((GNUNET_OK != | 92 | if ((GNUNET_OK != |
188 | pq_exec (plugin, "CREATE INDEX idx_key ON gn090dc (key)", __LINE__)) || | 93 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_key ON gn090dc (key)")) || |
189 | (GNUNET_OK != | 94 | (GNUNET_OK != |
190 | pq_exec (plugin, "CREATE INDEX idx_dt ON gn090dc (discard_time)", | 95 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_dt ON gn090dc (discard_time)"))) |
191 | __LINE__))) | ||
192 | { | 96 | { |
193 | PQclear (ret); | 97 | PQclear (ret); |
194 | PQfinish (plugin->dbh); | 98 | PQfinish (plugin->dbh); |
@@ -201,8 +105,7 @@ init_connection (struct Plugin *plugin) | |||
201 | PQexec (plugin->dbh, | 105 | PQexec (plugin->dbh, |
202 | "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"); | 106 | "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"); |
203 | if (GNUNET_OK != | 107 | if (GNUNET_OK != |
204 | check_result (plugin, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc", | 108 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc")) |
205 | __LINE__)) | ||
206 | { | 109 | { |
207 | PQfinish (plugin->dbh); | 110 | PQfinish (plugin->dbh); |
208 | plugin->dbh = NULL; | 111 | plugin->dbh = NULL; |
@@ -211,8 +114,7 @@ init_connection (struct Plugin *plugin) | |||
211 | PQclear (ret); | 114 | PQclear (ret); |
212 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"); | 115 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"); |
213 | if (GNUNET_OK != | 116 | if (GNUNET_OK != |
214 | check_result (plugin, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc", | 117 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc")) |
215 | __LINE__)) | ||
216 | { | 118 | { |
217 | PQfinish (plugin->dbh); | 119 | PQfinish (plugin->dbh); |
218 | plugin->dbh = NULL; | 120 | plugin->dbh = NULL; |
@@ -220,24 +122,23 @@ init_connection (struct Plugin *plugin) | |||
220 | } | 122 | } |
221 | PQclear (ret); | 123 | PQclear (ret); |
222 | if ((GNUNET_OK != | 124 | if ((GNUNET_OK != |
223 | pq_prepare (plugin, "getkt", | 125 | GNUNET_POSTGRES_prepare (plugin->dbh, "getkt", |
224 | "SELECT discard_time,type,value FROM gn090dc " | 126 | "SELECT discard_time,type,value FROM gn090dc " |
225 | "WHERE key=$1 AND type=$2 ", 2, __LINE__)) || | 127 | "WHERE key=$1 AND type=$2 ", 2)) || |
226 | (GNUNET_OK != | 128 | (GNUNET_OK != |
227 | pq_prepare (plugin, "getk", | 129 | GNUNET_POSTGRES_prepare (plugin->dbh, "getk", |
228 | "SELECT discard_time,type,value FROM gn090dc " | 130 | "SELECT discard_time,type,value FROM gn090dc " |
229 | "WHERE key=$1", 1, __LINE__)) || | 131 | "WHERE key=$1", 1)) || |
230 | (GNUNET_OK != | 132 | (GNUNET_OK != |
231 | pq_prepare (plugin, "getm", | 133 | GNUNET_POSTGRES_prepare (plugin->dbh, "getm", |
232 | "SELECT length(value),oid,key FROM gn090dc " | 134 | "SELECT length(value),oid,key FROM gn090dc " |
233 | "ORDER BY discard_time ASC LIMIT 1", 0, __LINE__)) || | 135 | "ORDER BY discard_time ASC LIMIT 1", 0)) || |
234 | (GNUNET_OK != | 136 | (GNUNET_OK != |
235 | pq_prepare (plugin, "delrow", "DELETE FROM gn090dc WHERE oid=$1", 1, | 137 | GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090dc WHERE oid=$1", 1)) || |
236 | __LINE__)) || | ||
237 | (GNUNET_OK != | 138 | (GNUNET_OK != |
238 | pq_prepare (plugin, "put", | 139 | GNUNET_POSTGRES_prepare (plugin->dbh, "put", |
239 | "INSERT INTO gn090dc (type, discard_time, key, value) " | 140 | "INSERT INTO gn090dc (type, discard_time, key, value) " |
240 | "VALUES ($1, $2, $3, $4)", 4, __LINE__))) | 141 | "VALUES ($1, $2, $3, $4)", 4))) |
241 | { | 142 | { |
242 | PQfinish (plugin->dbh); | 143 | PQfinish (plugin->dbh); |
243 | plugin->dbh = NULL; | 144 | plugin->dbh = NULL; |
@@ -248,37 +149,6 @@ init_connection (struct Plugin *plugin) | |||
248 | 149 | ||
249 | 150 | ||
250 | /** | 151 | /** |
251 | * Delete the row identified by the given rowid (qid | ||
252 | * in postgres). | ||
253 | * | ||
254 | * @param plugin global context | ||
255 | * @param rowid which row to delete | ||
256 | * @return GNUNET_OK on success | ||
257 | */ | ||
258 | static int | ||
259 | delete_by_rowid (struct Plugin *plugin, uint32_t rowid) | ||
260 | { | ||
261 | uint32_t brow = htonl (rowid); | ||
262 | const char *paramValues[] = { (const char *) &brow }; | ||
263 | int paramLengths[] = { sizeof (brow) }; | ||
264 | const int paramFormats[] = { 1 }; | ||
265 | PGresult *ret; | ||
266 | |||
267 | ret = | ||
268 | PQexecPrepared (plugin->dbh, "delrow", 1, paramValues, paramLengths, | ||
269 | paramFormats, 1); | ||
270 | if (GNUNET_OK != | ||
271 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexecPrepared", "delrow", | ||
272 | __LINE__)) | ||
273 | { | ||
274 | return GNUNET_SYSERR; | ||
275 | } | ||
276 | PQclear (ret); | ||
277 | return GNUNET_OK; | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Store an item in the datastore. | 152 | * Store an item in the datastore. |
283 | * | 153 | * |
284 | * @param cls closure (our "struct Plugin") | 154 | * @param cls closure (our "struct Plugin") |
@@ -317,8 +187,7 @@ postgres_plugin_put (void *cls, const GNUNET_HashCode * key, size_t size, | |||
317 | PQexecPrepared (plugin->dbh, "put", 4, paramValues, paramLengths, | 187 | PQexecPrepared (plugin->dbh, "put", 4, paramValues, paramLengths, |
318 | paramFormats, 1); | 188 | paramFormats, 1); |
319 | if (GNUNET_OK != | 189 | if (GNUNET_OK != |
320 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put", | 190 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put")) |
321 | __LINE__)) | ||
322 | return GNUNET_SYSERR; | 191 | return GNUNET_SYSERR; |
323 | PQclear (ret); | 192 | PQclear (ret); |
324 | return size + OVERHEAD; | 193 | return size + OVERHEAD; |
@@ -364,8 +233,8 @@ postgres_plugin_get (void *cls, const GNUNET_HashCode * key, | |||
364 | (type == 0) ? 1 : 2, paramValues, paramLengths, | 233 | (type == 0) ? 1 : 2, paramValues, paramLengths, |
365 | paramFormats, 1); | 234 | paramFormats, 1); |
366 | if (GNUNET_OK != | 235 | if (GNUNET_OK != |
367 | check_result (plugin, res, PGRES_TUPLES_OK, "PQexecPrepared", | 236 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", |
368 | (type == 0) ? "getk" : "getkt", __LINE__)) | 237 | (type == 0) ? "getk" : "getkt")) |
369 | { | 238 | { |
370 | #if DEBUG_POSTGRES | 239 | #if DEBUG_POSTGRES |
371 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datacache-postgres", | 240 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datacache-postgres", |
@@ -442,8 +311,7 @@ postgres_plugin_del (void *cls) | |||
442 | 311 | ||
443 | res = PQexecPrepared (plugin->dbh, "getm", 0, NULL, NULL, NULL, 1); | 312 | res = PQexecPrepared (plugin->dbh, "getm", 0, NULL, NULL, NULL, 1); |
444 | if (GNUNET_OK != | 313 | if (GNUNET_OK != |
445 | check_result (plugin, res, PGRES_TUPLES_OK, "PQexecPrepared", "getm", | 314 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", "getm")) |
446 | __LINE__)) | ||
447 | { | 315 | { |
448 | #if DEBUG_POSTGRES | 316 | #if DEBUG_POSTGRES |
449 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datacache-postgres", | 317 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datacache-postgres", |
@@ -473,7 +341,7 @@ postgres_plugin_del (void *cls) | |||
473 | oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); | 341 | oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); |
474 | memcpy (&key, PQgetvalue (res, 0, 2), sizeof (GNUNET_HashCode)); | 342 | memcpy (&key, PQgetvalue (res, 0, 2), sizeof (GNUNET_HashCode)); |
475 | PQclear (res); | 343 | PQclear (res); |
476 | if (GNUNET_OK != delete_by_rowid (plugin, oid)) | 344 | if (GNUNET_OK != GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, "delrow", oid)) |
477 | return GNUNET_SYSERR; | 345 | return GNUNET_SYSERR; |
478 | plugin->env->delete_notify (plugin->env->cls, &key, size + OVERHEAD); | 346 | plugin->env->delete_notify (plugin->env->cls, &key, size + OVERHEAD); |
479 | return GNUNET_OK; | 347 | return GNUNET_OK; |
diff --git a/src/datastore/plugin_datastore_postgres.c b/src/datastore/plugin_datastore_postgres.c index 31ba09a87..b9c27c7b1 100644 --- a/src/datastore/plugin_datastore_postgres.c +++ b/src/datastore/plugin_datastore_postgres.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | #include "gnunet_datastore_plugin.h" | 28 | #include "gnunet_datastore_plugin.h" |
29 | #include "gnunet_postgres_lib.h" | ||
29 | #include <postgresql/libpq-fe.h> | 30 | #include <postgresql/libpq-fe.h> |
30 | 31 | ||
31 | #define DEBUG_POSTGRES GNUNET_EXTRA_LOGGING | 32 | #define DEBUG_POSTGRES GNUNET_EXTRA_LOGGING |
@@ -62,87 +63,6 @@ struct Plugin | |||
62 | 63 | ||
63 | 64 | ||
64 | /** | 65 | /** |
65 | * Check if the result obtained from Postgres has | ||
66 | * the desired status code. If not, log an error, clear the | ||
67 | * result and return GNUNET_SYSERR. | ||
68 | * | ||
69 | * @param plugin global context | ||
70 | * @param ret result to check | ||
71 | * @param expected_status expected return value | ||
72 | * @param command name of SQL command that was run | ||
73 | * @param args arguments to SQL command | ||
74 | * @param line line number for error reporting | ||
75 | * @return GNUNET_OK if the result is acceptable | ||
76 | */ | ||
77 | static int | ||
78 | check_result (struct Plugin *plugin, PGresult * ret, int expected_status, | ||
79 | const char *command, const char *args, int line) | ||
80 | { | ||
81 | if (ret == NULL) | ||
82 | { | ||
83 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
84 | "datastore-postgres", | ||
85 | "Postgres failed to allocate result for `%s:%s' at %d\n", | ||
86 | command, args, line); | ||
87 | return GNUNET_SYSERR; | ||
88 | } | ||
89 | if (PQresultStatus (ret) != expected_status) | ||
90 | { | ||
91 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
92 | "datastore-postgres", | ||
93 | _("`%s:%s' failed at %s:%d with error: %s"), command, args, | ||
94 | __FILE__, line, PQerrorMessage (plugin->dbh)); | ||
95 | PQclear (ret); | ||
96 | return GNUNET_SYSERR; | ||
97 | } | ||
98 | return GNUNET_OK; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Run simple SQL statement (without results). | ||
103 | * | ||
104 | * @param plugin global context | ||
105 | * @param sql statement to run | ||
106 | * @param line code line for error reporting | ||
107 | */ | ||
108 | static int | ||
109 | pq_exec (struct Plugin *plugin, const char *sql, int line) | ||
110 | { | ||
111 | PGresult *ret; | ||
112 | |||
113 | ret = PQexec (plugin->dbh, sql); | ||
114 | if (GNUNET_OK != | ||
115 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexec", sql, line)) | ||
116 | return GNUNET_SYSERR; | ||
117 | PQclear (ret); | ||
118 | return GNUNET_OK; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Prepare SQL statement. | ||
123 | * | ||
124 | * @param plugin global context | ||
125 | * @param name name for the prepared SQL statement | ||
126 | * @param sql SQL code to prepare | ||
127 | * @param nparams number of parameters in sql | ||
128 | * @param line code line for error reporting | ||
129 | * @return GNUNET_OK on success | ||
130 | */ | ||
131 | static int | ||
132 | pq_prepare (struct Plugin *plugin, const char *name, const char *sql, | ||
133 | int nparams, int line) | ||
134 | { | ||
135 | PGresult *ret; | ||
136 | |||
137 | ret = PQprepare (plugin->dbh, name, sql, nparams, NULL); | ||
138 | if (GNUNET_OK != | ||
139 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQprepare", sql, line)) | ||
140 | return GNUNET_SYSERR; | ||
141 | PQclear (ret); | ||
142 | return GNUNET_OK; | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * @brief Get a database handle | 66 | * @brief Get a database handle |
147 | * | 67 | * |
148 | * @param plugin global context | 68 | * @param plugin global context |
@@ -151,33 +71,11 @@ pq_prepare (struct Plugin *plugin, const char *name, const char *sql, | |||
151 | static int | 71 | static int |
152 | init_connection (struct Plugin *plugin) | 72 | init_connection (struct Plugin *plugin) |
153 | { | 73 | { |
154 | char *conninfo; | ||
155 | PGresult *ret; | 74 | PGresult *ret; |
156 | 75 | ||
157 | /* Open database and precompile statements */ | 76 | plugin->dbh = GNUNET_POSTGRES_connect (plugin->env->cfg, "datastore-postgres"); |
158 | conninfo = NULL; | ||
159 | (void) GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | ||
160 | "datastore-postgres", "CONFIG", | ||
161 | &conninfo); | ||
162 | plugin->dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); | ||
163 | if (NULL == plugin->dbh) | 77 | if (NULL == plugin->dbh) |
164 | { | ||
165 | /* FIXME: warn about out-of-memory? */ | ||
166 | GNUNET_free_non_null (conninfo); | ||
167 | return GNUNET_SYSERR; | 78 | return GNUNET_SYSERR; |
168 | } | ||
169 | if (PQstatus (plugin->dbh) != CONNECTION_OK) | ||
170 | { | ||
171 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "datastore-postgres", | ||
172 | _ | ||
173 | ("Unable to initialize Postgres with configuration `%s': %s"), | ||
174 | conninfo, PQerrorMessage (plugin->dbh)); | ||
175 | PQfinish (plugin->dbh); | ||
176 | plugin->dbh = NULL; | ||
177 | GNUNET_free_non_null (conninfo); | ||
178 | return GNUNET_SYSERR; | ||
179 | } | ||
180 | GNUNET_free_non_null (conninfo); | ||
181 | ret = | 79 | ret = |
182 | PQexec (plugin->dbh, | 80 | PQexec (plugin->dbh, |
183 | "CREATE TABLE gn090 (" " repl INTEGER NOT NULL DEFAULT 0," | 81 | "CREATE TABLE gn090 (" " repl INTEGER NOT NULL DEFAULT 0," |
@@ -194,8 +92,7 @@ init_connection (struct Plugin *plugin) | |||
194 | (ret, | 92 | (ret, |
195 | PG_DIAG_SQLSTATE))))) | 93 | PG_DIAG_SQLSTATE))))) |
196 | { | 94 | { |
197 | (void) check_result (plugin, ret, PGRES_COMMAND_OK, "CREATE TABLE", "gn090", | 95 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "CREATE TABLE", "gn090"); |
198 | __LINE__); | ||
199 | PQfinish (plugin->dbh); | 96 | PQfinish (plugin->dbh); |
200 | plugin->dbh = NULL; | 97 | plugin->dbh = NULL; |
201 | return GNUNET_SYSERR; | 98 | return GNUNET_SYSERR; |
@@ -203,29 +100,23 @@ init_connection (struct Plugin *plugin) | |||
203 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) | 100 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) |
204 | { | 101 | { |
205 | if ((GNUNET_OK != | 102 | if ((GNUNET_OK != |
206 | pq_exec (plugin, "CREATE INDEX idx_hash ON gn090 (hash)", __LINE__)) || | 103 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_hash ON gn090 (hash)")) || |
207 | (GNUNET_OK != | 104 | (GNUNET_OK != |
208 | pq_exec (plugin, "CREATE INDEX idx_hash_vhash ON gn090 (hash,vhash)", | 105 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_hash_vhash ON gn090 (hash,vhash)")) || |
209 | __LINE__)) || | ||
210 | (GNUNET_OK != | 106 | (GNUNET_OK != |
211 | pq_exec (plugin, "CREATE INDEX idx_prio ON gn090 (prio)", __LINE__)) || | 107 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_prio ON gn090 (prio)")) || |
212 | (GNUNET_OK != | 108 | (GNUNET_OK != |
213 | pq_exec (plugin, "CREATE INDEX idx_expire ON gn090 (expire)", | 109 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_expire ON gn090 (expire)")) || |
214 | __LINE__)) || | ||
215 | (GNUNET_OK != | 110 | (GNUNET_OK != |
216 | pq_exec (plugin, | 111 | GNUNET_POSTGRES_exec (plugin->dbh, |
217 | "CREATE INDEX idx_prio_anon ON gn090 (prio,anonLevel)", | 112 | "CREATE INDEX idx_prio_anon ON gn090 (prio,anonLevel)")) || |
218 | __LINE__)) || | ||
219 | (GNUNET_OK != | 113 | (GNUNET_OK != |
220 | pq_exec (plugin, | 114 | GNUNET_POSTGRES_exec (plugin->dbh, |
221 | "CREATE INDEX idx_prio_hash_anon ON gn090 (prio,hash,anonLevel)", | 115 | "CREATE INDEX idx_prio_hash_anon ON gn090 (prio,hash,anonLevel)")) || |
222 | __LINE__)) || | ||
223 | (GNUNET_OK != | 116 | (GNUNET_OK != |
224 | pq_exec (plugin, "CREATE INDEX idx_repl_rvalue ON gn090 (repl,rvalue)", | 117 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_repl_rvalue ON gn090 (repl,rvalue)")) || |
225 | __LINE__)) || | ||
226 | (GNUNET_OK != | 118 | (GNUNET_OK != |
227 | pq_exec (plugin, "CREATE INDEX idx_expire_hash ON gn090 (expire,hash)", | 119 | GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_expire_hash ON gn090 (expire,hash)"))) |
228 | __LINE__))) | ||
229 | { | 120 | { |
230 | PQclear (ret); | 121 | PQclear (ret); |
231 | PQfinish (plugin->dbh); | 122 | PQfinish (plugin->dbh); |
@@ -238,8 +129,7 @@ init_connection (struct Plugin *plugin) | |||
238 | PQexec (plugin->dbh, | 129 | PQexec (plugin->dbh, |
239 | "ALTER TABLE gn090 ALTER value SET STORAGE EXTERNAL"); | 130 | "ALTER TABLE gn090 ALTER value SET STORAGE EXTERNAL"); |
240 | if (GNUNET_OK != | 131 | if (GNUNET_OK != |
241 | check_result (plugin, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090", | 132 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) |
242 | __LINE__)) | ||
243 | { | 133 | { |
244 | PQfinish (plugin->dbh); | 134 | PQfinish (plugin->dbh); |
245 | plugin->dbh = NULL; | 135 | plugin->dbh = NULL; |
@@ -248,8 +138,7 @@ init_connection (struct Plugin *plugin) | |||
248 | PQclear (ret); | 138 | PQclear (ret); |
249 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER hash SET STORAGE PLAIN"); | 139 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER hash SET STORAGE PLAIN"); |
250 | if (GNUNET_OK != | 140 | if (GNUNET_OK != |
251 | check_result (plugin, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090", | 141 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) |
252 | __LINE__)) | ||
253 | { | 142 | { |
254 | PQfinish (plugin->dbh); | 143 | PQfinish (plugin->dbh); |
255 | plugin->dbh = NULL; | 144 | plugin->dbh = NULL; |
@@ -258,8 +147,7 @@ init_connection (struct Plugin *plugin) | |||
258 | PQclear (ret); | 147 | PQclear (ret); |
259 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER vhash SET STORAGE PLAIN"); | 148 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER vhash SET STORAGE PLAIN"); |
260 | if (GNUNET_OK != | 149 | if (GNUNET_OK != |
261 | check_result (plugin, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090", | 150 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) |
262 | __LINE__)) | ||
263 | { | 151 | { |
264 | PQfinish (plugin->dbh); | 152 | PQfinish (plugin->dbh); |
265 | plugin->dbh = NULL; | 153 | plugin->dbh = NULL; |
@@ -267,60 +155,56 @@ init_connection (struct Plugin *plugin) | |||
267 | } | 155 | } |
268 | PQclear (ret); | 156 | PQclear (ret); |
269 | if ((GNUNET_OK != | 157 | if ((GNUNET_OK != |
270 | pq_prepare (plugin, "getvt", | 158 | GNUNET_POSTGRES_prepare (plugin->dbh, "getvt", |
271 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 159 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
272 | "WHERE hash=$1 AND vhash=$2 AND type=$3 " | 160 | "WHERE hash=$1 AND vhash=$2 AND type=$3 " |
273 | "ORDER BY oid ASC LIMIT 1 OFFSET $4", 4, __LINE__)) || | 161 | "ORDER BY oid ASC LIMIT 1 OFFSET $4", 4)) || |
274 | (GNUNET_OK != | 162 | (GNUNET_OK != |
275 | pq_prepare (plugin, "gett", | 163 | GNUNET_POSTGRES_prepare (plugin->dbh, "gett", |
276 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 164 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
277 | "WHERE hash=$1 AND type=$2 " | 165 | "WHERE hash=$1 AND type=$2 " |
278 | "ORDER BY oid ASC LIMIT 1 OFFSET $3", 3, __LINE__)) || | 166 | "ORDER BY oid ASC LIMIT 1 OFFSET $3", 3)) || |
279 | (GNUNET_OK != | 167 | (GNUNET_OK != |
280 | pq_prepare (plugin, "getv", | 168 | GNUNET_POSTGRES_prepare (plugin->dbh, "getv", |
281 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 169 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
282 | "WHERE hash=$1 AND vhash=$2 " | 170 | "WHERE hash=$1 AND vhash=$2 " |
283 | "ORDER BY oid ASC LIMIT 1 OFFSET $3", 3, __LINE__)) || | 171 | "ORDER BY oid ASC LIMIT 1 OFFSET $3", 3)) || |
284 | (GNUNET_OK != | 172 | (GNUNET_OK != |
285 | pq_prepare (plugin, "get", | 173 | GNUNET_POSTGRES_prepare (plugin->dbh, "get", |
286 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 174 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
287 | "WHERE hash=$1 " "ORDER BY oid ASC LIMIT 1 OFFSET $2", 2, | 175 | "WHERE hash=$1 " "ORDER BY oid ASC LIMIT 1 OFFSET $2", 2)) || |
288 | __LINE__)) || | ||
289 | (GNUNET_OK != | 176 | (GNUNET_OK != |
290 | pq_prepare (plugin, "put", | 177 | GNUNET_POSTGRES_prepare (plugin->dbh, "put", |
291 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " | 178 | "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " |
292 | "VALUES ($1, $2, $3, $4, $5, RANDOM(), $6, $7, $8)", 9, | 179 | "VALUES ($1, $2, $3, $4, $5, RANDOM(), $6, $7, $8)", 9)) || |
293 | __LINE__)) || | ||
294 | (GNUNET_OK != | 180 | (GNUNET_OK != |
295 | pq_prepare (plugin, "update", | 181 | GNUNET_POSTGRES_prepare (plugin->dbh, "update", |
296 | "UPDATE gn090 SET prio = prio + $1, expire = CASE WHEN expire < $2 THEN $2 ELSE expire END " | 182 | "UPDATE gn090 SET prio = prio + $1, expire = CASE WHEN expire < $2 THEN $2 ELSE expire END " |
297 | "WHERE oid = $3", 3, __LINE__)) || | 183 | "WHERE oid = $3", 3)) || |
298 | (GNUNET_OK != | 184 | (GNUNET_OK != |
299 | pq_prepare (plugin, "decrepl", | 185 | GNUNET_POSTGRES_prepare (plugin->dbh, "decrepl", |
300 | "UPDATE gn090 SET repl = GREATEST (repl - 1, 0) " | 186 | "UPDATE gn090 SET repl = GREATEST (repl - 1, 0) " |
301 | "WHERE oid = $1", 1, __LINE__)) || | 187 | "WHERE oid = $1", 1)) || |
302 | (GNUNET_OK != | 188 | (GNUNET_OK != |
303 | pq_prepare (plugin, "select_non_anonymous", | 189 | GNUNET_POSTGRES_prepare (plugin->dbh, "select_non_anonymous", |
304 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 190 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
305 | "WHERE anonLevel = 0 AND type = $1 ORDER BY oid DESC LIMIT 1 OFFSET $2", | 191 | "WHERE anonLevel = 0 AND type = $1 ORDER BY oid DESC LIMIT 1 OFFSET $2", |
306 | 1, __LINE__)) || | 192 | 1)) || |
307 | (GNUNET_OK != | 193 | (GNUNET_OK != |
308 | pq_prepare (plugin, "select_expiration_order", | 194 | GNUNET_POSTGRES_prepare (plugin->dbh, "select_expiration_order", |
309 | "(SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 195 | "(SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
310 | "WHERE expire < $1 ORDER BY prio ASC LIMIT 1) " "UNION " | 196 | "WHERE expire < $1 ORDER BY prio ASC LIMIT 1) " "UNION " |
311 | "(SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 197 | "(SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
312 | "ORDER BY prio ASC LIMIT 1) " "ORDER BY expire ASC LIMIT 1", | 198 | "ORDER BY prio ASC LIMIT 1) " "ORDER BY expire ASC LIMIT 1", |
313 | 1, __LINE__)) || | 199 | 1)) || |
314 | (GNUNET_OK != | 200 | (GNUNET_OK != |
315 | pq_prepare (plugin, "select_replication_order", | 201 | GNUNET_POSTGRES_prepare (plugin->dbh, "select_replication_order", |
316 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " | 202 | "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " |
317 | "ORDER BY repl DESC,RANDOM() LIMIT 1", 0, __LINE__)) || | 203 | "ORDER BY repl DESC,RANDOM() LIMIT 1", 0)) || |
318 | (GNUNET_OK != | 204 | (GNUNET_OK != |
319 | pq_prepare (plugin, "delrow", "DELETE FROM gn090 " "WHERE oid=$1", 1, | 205 | GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090 " "WHERE oid=$1", 1)) || |
320 | __LINE__)) || | ||
321 | (GNUNET_OK != | 206 | (GNUNET_OK != |
322 | pq_prepare (plugin, "get_keys", "SELECT hash FROM gn090", 0, | 207 | GNUNET_POSTGRES_prepare (plugin->dbh, "get_keys", "SELECT hash FROM gn090", 0))) |
323 | __LINE__))) | ||
324 | { | 208 | { |
325 | PQfinish (plugin->dbh); | 209 | PQfinish (plugin->dbh); |
326 | plugin->dbh = NULL; | 210 | plugin->dbh = NULL; |
@@ -331,38 +215,6 @@ init_connection (struct Plugin *plugin) | |||
331 | 215 | ||
332 | 216 | ||
333 | /** | 217 | /** |
334 | * Delete the row identified by the given rowid (qid | ||
335 | * in postgres). | ||
336 | * | ||
337 | * @param plugin global context | ||
338 | * @param rowid which row to delete | ||
339 | * @return GNUNET_OK on success | ||
340 | */ | ||
341 | static int | ||
342 | delete_by_rowid (struct Plugin *plugin, uint32_t rowid) | ||
343 | { | ||
344 | uint32_t browid; | ||
345 | const char *paramValues[] = { (const char *) &browid }; | ||
346 | int paramLengths[] = { sizeof (browid) }; | ||
347 | const int paramFormats[] = { 1 }; | ||
348 | PGresult *ret; | ||
349 | |||
350 | browid = htonl (rowid); | ||
351 | ret = | ||
352 | PQexecPrepared (plugin->dbh, "delrow", 1, paramValues, paramLengths, | ||
353 | paramFormats, 1); | ||
354 | if (GNUNET_OK != | ||
355 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexecPrepared", "delrow", | ||
356 | __LINE__)) | ||
357 | { | ||
358 | return GNUNET_SYSERR; | ||
359 | } | ||
360 | PQclear (ret); | ||
361 | return GNUNET_OK; | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * Get an estimate of how much space the database is | 218 | * Get an estimate of how much space the database is |
367 | * currently using. | 219 | * currently using. |
368 | * | 220 | * |
@@ -381,8 +233,7 @@ postgres_plugin_estimate_size (void *cls) | |||
381 | "SELECT SUM(LENGTH(value))+256*COUNT(*) FROM gn090", 0, | 233 | "SELECT SUM(LENGTH(value))+256*COUNT(*) FROM gn090", 0, |
382 | NULL, NULL, NULL, NULL, 1); | 234 | NULL, NULL, NULL, NULL, 1); |
383 | if (GNUNET_OK != | 235 | if (GNUNET_OK != |
384 | check_result (plugin, ret, PGRES_TUPLES_OK, "PQexecParams", "get_size", | 236 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_TUPLES_OK, "PQexecParams", "get_size")) |
385 | __LINE__)) | ||
386 | { | 237 | { |
387 | return 0; | 238 | return 0; |
388 | } | 239 | } |
@@ -457,8 +308,7 @@ postgres_plugin_put (void *cls, const GNUNET_HashCode * key, uint32_t size, | |||
457 | PQexecPrepared (plugin->dbh, "put", 8, paramValues, paramLengths, | 308 | PQexecPrepared (plugin->dbh, "put", 8, paramValues, paramLengths, |
458 | paramFormats, 1); | 309 | paramFormats, 1); |
459 | if (GNUNET_OK != | 310 | if (GNUNET_OK != |
460 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put", | 311 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put")) |
461 | __LINE__)) | ||
462 | return GNUNET_SYSERR; | 312 | return GNUNET_SYSERR; |
463 | PQclear (ret); | 313 | PQclear (ret); |
464 | plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 314 | plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD); |
@@ -478,11 +328,13 @@ postgres_plugin_put (void *cls, const GNUNET_HashCode * key, uint32_t size, | |||
478 | * @param proc function to call the value (once only). | 328 | * @param proc function to call the value (once only). |
479 | * @param proc_cls closure for proc | 329 | * @param proc_cls closure for proc |
480 | * @param res result from exec | 330 | * @param res result from exec |
331 | * @param filename filename for error messages | ||
481 | * @param line line number for error messages | 332 | * @param line line number for error messages |
482 | */ | 333 | */ |
483 | static void | 334 | static void |
484 | process_result (struct Plugin *plugin, PluginDatumProcessor proc, | 335 | process_result (struct Plugin *plugin, PluginDatumProcessor proc, |
485 | void *proc_cls, PGresult * res, int line) | 336 | void *proc_cls, PGresult * res, |
337 | const char *filename, int line) | ||
486 | { | 338 | { |
487 | int iret; | 339 | int iret; |
488 | enum GNUNET_BLOCK_Type type; | 340 | enum GNUNET_BLOCK_Type type; |
@@ -494,8 +346,8 @@ process_result (struct Plugin *plugin, PluginDatumProcessor proc, | |||
494 | GNUNET_HashCode key; | 346 | GNUNET_HashCode key; |
495 | 347 | ||
496 | if (GNUNET_OK != | 348 | if (GNUNET_OK != |
497 | check_result (plugin, res, PGRES_TUPLES_OK, "PQexecPrepared", "select", | 349 | GNUNET_POSTGRES_check_result_ (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", "select", |
498 | line)) | 350 | filename, line)) |
499 | { | 351 | { |
500 | #if DEBUG_POSTGRES | 352 | #if DEBUG_POSTGRES |
501 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", | 353 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", |
@@ -534,7 +386,7 @@ process_result (struct Plugin *plugin, PluginDatumProcessor proc, | |||
534 | { | 386 | { |
535 | GNUNET_break (0); | 387 | GNUNET_break (0); |
536 | PQclear (res); | 388 | PQclear (res); |
537 | delete_by_rowid (plugin, rowid); | 389 | GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, "delrow", rowid); |
538 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 390 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
539 | return; | 391 | return; |
540 | } | 392 | } |
@@ -562,7 +414,7 @@ process_result (struct Plugin *plugin, PluginDatumProcessor proc, | |||
562 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 414 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
563 | "Processor asked for item %u to be removed.\n", rowid); | 415 | "Processor asked for item %u to be removed.\n", rowid); |
564 | #endif | 416 | #endif |
565 | if (GNUNET_OK == delete_by_rowid (plugin, rowid)) | 417 | if (GNUNET_OK == GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, "delrow", rowid)) |
566 | { | 418 | { |
567 | #if DEBUG_POSTGRES | 419 | #if DEBUG_POSTGRES |
568 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", | 420 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", |
@@ -679,8 +531,7 @@ postgres_plugin_get_key (void *cls, uint64_t offset, | |||
679 | } | 531 | } |
680 | } | 532 | } |
681 | if (GNUNET_OK != | 533 | if (GNUNET_OK != |
682 | check_result (plugin, ret, PGRES_TUPLES_OK, "PQexecParams", pname, | 534 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_TUPLES_OK, "PQexecParams", pname)) |
683 | __LINE__)) | ||
684 | { | 535 | { |
685 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); | 536 | proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); |
686 | return; | 537 | return; |
@@ -704,7 +555,7 @@ postgres_plugin_get_key (void *cls, uint64_t offset, | |||
704 | ret = | 555 | ret = |
705 | PQexecPrepared (plugin->dbh, pname, nparams, paramValues, paramLengths, | 556 | PQexecPrepared (plugin->dbh, pname, nparams, paramValues, paramLengths, |
706 | paramFormats, 1); | 557 | paramFormats, 1); |
707 | process_result (plugin, proc, proc_cls, ret, __LINE__); | 558 | process_result (plugin, proc, proc_cls, ret, __FILE__, __LINE__); |
708 | } | 559 | } |
709 | 560 | ||
710 | 561 | ||
@@ -739,7 +590,7 @@ postgres_plugin_get_zero_anonymity (void *cls, uint64_t offset, | |||
739 | ret = | 590 | ret = |
740 | PQexecPrepared (plugin->dbh, "select_non_anonymous", 2, paramValues, | 591 | PQexecPrepared (plugin->dbh, "select_non_anonymous", 2, paramValues, |
741 | paramLengths, paramFormats, 1); | 592 | paramLengths, paramFormats, 1); |
742 | process_result (plugin, proc, proc_cls, ret, __LINE__); | 593 | process_result (plugin, proc, proc_cls, ret, __FILE__, __LINE__); |
743 | } | 594 | } |
744 | 595 | ||
745 | 596 | ||
@@ -815,8 +666,8 @@ repl_proc (void *cls, const GNUNET_HashCode * key, uint32_t size, | |||
815 | PQexecPrepared (plugin->dbh, "decrepl", 1, paramValues, paramLengths, | 666 | PQexecPrepared (plugin->dbh, "decrepl", 1, paramValues, paramLengths, |
816 | paramFormats, 1); | 667 | paramFormats, 1); |
817 | if (GNUNET_OK != | 668 | if (GNUNET_OK != |
818 | check_result (plugin, qret, PGRES_COMMAND_OK, "PQexecPrepared", | 669 | GNUNET_POSTGRES_check_result (plugin->dbh, qret, PGRES_COMMAND_OK, "PQexecPrepared", |
819 | "decrepl", __LINE__)) | 670 | "decrepl")) |
820 | return GNUNET_SYSERR; | 671 | return GNUNET_SYSERR; |
821 | PQclear (qret); | 672 | PQclear (qret); |
822 | } | 673 | } |
@@ -848,7 +699,7 @@ postgres_plugin_get_replication (void *cls, PluginDatumProcessor proc, | |||
848 | ret = | 699 | ret = |
849 | PQexecPrepared (plugin->dbh, "select_replication_order", 0, NULL, NULL, | 700 | PQexecPrepared (plugin->dbh, "select_replication_order", 0, NULL, NULL, |
850 | NULL, 1); | 701 | NULL, 1); |
851 | process_result (plugin, &repl_proc, &rc, ret, __LINE__); | 702 | process_result (plugin, &repl_proc, &rc, ret, __FILE__, __LINE__); |
852 | } | 703 | } |
853 | 704 | ||
854 | 705 | ||
@@ -875,7 +726,7 @@ postgres_plugin_get_expiration (void *cls, PluginDatumProcessor proc, | |||
875 | ret = | 726 | ret = |
876 | PQexecPrepared (plugin->dbh, "select_expiration_order", 1, paramValues, | 727 | PQexecPrepared (plugin->dbh, "select_expiration_order", 1, paramValues, |
877 | paramLengths, paramFormats, 1); | 728 | paramLengths, paramFormats, 1); |
878 | process_result (plugin, proc, proc_cls, ret, __LINE__); | 729 | process_result (plugin, proc, proc_cls, ret, __FILE__, __LINE__); |
879 | } | 730 | } |
880 | 731 | ||
881 | 732 | ||
@@ -928,8 +779,7 @@ postgres_plugin_update (void *cls, uint64_t uid, int delta, | |||
928 | PQexecPrepared (plugin->dbh, "update", 3, paramValues, paramLengths, | 779 | PQexecPrepared (plugin->dbh, "update", 3, paramValues, paramLengths, |
929 | paramFormats, 1); | 780 | paramFormats, 1); |
930 | if (GNUNET_OK != | 781 | if (GNUNET_OK != |
931 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQexecPrepared", "update", | 782 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "update")) |
932 | __LINE__)) | ||
933 | return GNUNET_SYSERR; | 783 | return GNUNET_SYSERR; |
934 | PQclear (ret); | 784 | PQclear (ret); |
935 | return GNUNET_OK; | 785 | return GNUNET_OK; |
@@ -978,7 +828,7 @@ postgres_plugin_drop (void *cls) | |||
978 | { | 828 | { |
979 | struct Plugin *plugin = cls; | 829 | struct Plugin *plugin = cls; |
980 | 830 | ||
981 | pq_exec (plugin, "DROP TABLE gn090", __LINE__); | 831 | GNUNET_POSTGRES_exec (plugin->dbh, "DROP TABLE gn090"); |
982 | } | 832 | } |
983 | 833 | ||
984 | 834 | ||
diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 4c7ea4703..626aae0ec 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am | |||
@@ -62,6 +62,7 @@ gnunetinclude_HEADERS = \ | |||
62 | gnunet_peer_lib.h \ | 62 | gnunet_peer_lib.h \ |
63 | gnunet_peerinfo_service.h \ | 63 | gnunet_peerinfo_service.h \ |
64 | gnunet_plugin_lib.h \ | 64 | gnunet_plugin_lib.h \ |
65 | gnunet_postgres_lib.h \ | ||
65 | gnunet_program_lib.h \ | 66 | gnunet_program_lib.h \ |
66 | gnunet_protocols.h \ | 67 | gnunet_protocols.h \ |
67 | gnunet_pseudonym_lib.h \ | 68 | gnunet_pseudonym_lib.h \ |
diff --git a/src/include/gnunet_mysql_lib.h b/src/include/gnunet_mysql_lib.h index 7311c2c52..c61bdcab1 100644 --- a/src/include/gnunet_mysql_lib.h +++ b/src/include/gnunet_mysql_lib.h | |||
@@ -26,8 +26,6 @@ | |||
26 | #define GNUNET_MYSQL_LIB_H | 26 | #define GNUNET_MYSQL_LIB_H |
27 | 27 | ||
28 | #include "gnunet_util_lib.h" | 28 | #include "gnunet_util_lib.h" |
29 | #include "gnunet_bandwidth_lib.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include <mysql/mysql.h> | 29 | #include <mysql/mysql.h> |
32 | 30 | ||
33 | #ifdef __cplusplus | 31 | #ifdef __cplusplus |
diff --git a/src/include/gnunet_postgres_lib.h b/src/include/gnunet_postgres_lib.h new file mode 100644 index 000000000..12c0110b5 --- /dev/null +++ b/src/include/gnunet_postgres_lib.h | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file include/gnunet_postgres_lib.h | ||
22 | * @brief library to help with access to a Postgres database | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #ifndef GNUNET_POSTGRES_LIB_H | ||
26 | #define GNUNET_POSTGRES_LIB_H | ||
27 | |||
28 | #include "gnunet_util_lib.h" | ||
29 | #include <postgresql/libpq-fe.h> | ||
30 | |||
31 | #ifdef __cplusplus | ||
32 | extern "C" | ||
33 | { | ||
34 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
35 | } | ||
36 | #endif | ||
37 | #endif | ||
38 | |||
39 | |||
40 | /** | ||
41 | * Check if the result obtained from Postgres has | ||
42 | * the desired status code. If not, log an error, clear the | ||
43 | * result and return GNUNET_SYSERR. | ||
44 | * | ||
45 | * @param dbh database handle | ||
46 | * @param ret return value from database operation to check | ||
47 | * @param expected_status desired status | ||
48 | * @param command description of the command that was run | ||
49 | * @param args arguments given to the command | ||
50 | * @param filename name of the source file where the command was run | ||
51 | * @param line line number in the source file | ||
52 | * @return GNUNET_OK if the result is acceptable | ||
53 | */ | ||
54 | int | ||
55 | GNUNET_POSTGRES_check_result_ (PGconn *dbh, PGresult * ret, int expected_status, | ||
56 | const char *command, const char *args, | ||
57 | const char *filename, int line); | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Check if the result obtained from Postgres has | ||
62 | * the desired status code. If not, log an error, clear the | ||
63 | * result and return GNUNET_SYSERR. | ||
64 | * | ||
65 | * @param dbh database handle | ||
66 | * @param ret return value from database operation to check | ||
67 | * @param expected_status desired status | ||
68 | * @param command description of the command that was run | ||
69 | * @param args arguments given to the command | ||
70 | * @return GNUNET_OK if the result is acceptable | ||
71 | */ | ||
72 | #define GNUNET_POSTGRES_check_result(dbh,ret,expected_status,command,args) GNUNET_POSTGRES_check_result_(dbh,ret,expected_status,command,args,__FILE__,__LINE__) | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Run simple SQL statement (without results). | ||
77 | * | ||
78 | * @param dbh database handle | ||
79 | * @param sql statement to run | ||
80 | * @param filename filename for error reporting | ||
81 | * @param line code line for error reporting | ||
82 | * @return GNUNET_OK on success | ||
83 | */ | ||
84 | int | ||
85 | GNUNET_POSTGRES_exec_ (PGconn *dbh, const char *sql, const char *filename, int line); | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Run simple SQL statement (without results). | ||
90 | * | ||
91 | * @param dbh database handle | ||
92 | * @param sql statement to run | ||
93 | * @return GNUNET_OK on success | ||
94 | */ | ||
95 | #define GNUNET_POSTGRES_exec(dbh,sql) GNUNET_POSTGRES_exec_(dbh,sql,__FILE__,__LINE__) | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Prepare SQL statement. | ||
100 | * | ||
101 | * @param dbh database handle | ||
102 | * @param name name for the prepared SQL statement | ||
103 | * @param sql SQL code to prepare | ||
104 | * @param nparams number of parameters in sql | ||
105 | * @param filename filename for error reporting | ||
106 | * @param line code line for error reporting | ||
107 | * @return GNUNET_OK on success | ||
108 | */ | ||
109 | int | ||
110 | GNUNET_POSTGRES_prepare_ (PGconn *dbh, const char *name, const char *sql, | ||
111 | int nparms, | ||
112 | const char *filename, int line); | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Prepare SQL statement. | ||
117 | * | ||
118 | * @param dbh database handle | ||
119 | * @param name name for the prepared SQL statement | ||
120 | * @param sql SQL code to prepare | ||
121 | * @param nparams number of parameters in sql | ||
122 | * @return GNUNET_OK on success | ||
123 | */ | ||
124 | #define GNUNET_POSTGRES_prepare(dbh,name,sql,nparams) GNUNET_POSTGRES_prepare_(dbh,name,sql,nparams,__FILE__,__LINE__) | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Connect to a postgres database | ||
129 | * | ||
130 | * @param cfg configuration | ||
131 | * @param section configuration section to use to get Postgres configuration options | ||
132 | * @return the postgres handle | ||
133 | */ | ||
134 | PGconn * | ||
135 | GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
136 | const char *section); | ||
137 | |||
138 | |||
139 | /** | ||
140 | * Delete the row identified by the given rowid (qid | ||
141 | * in postgres). | ||
142 | * | ||
143 | * @param dbh database handle | ||
144 | * @param stmt name of the prepared statement | ||
145 | * @param rowid which row to delete | ||
146 | * @return GNUNET_OK on success | ||
147 | */ | ||
148 | int | ||
149 | GNUNET_POSTGRES_delete_by_rowid (PGconn *dbh, | ||
150 | const char *stmt, | ||
151 | uint32_t rowid); | ||
152 | |||
153 | |||
154 | |||
155 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
156 | { | ||
157 | #endif | ||
158 | #ifdef __cplusplus | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | /* end of gnunet_postgres_lib.h */ | ||
163 | #endif | ||
diff --git a/src/postgres/Makefile.am b/src/postgres/Makefile.am new file mode 100644 index 000000000..0b3be5e2b --- /dev/null +++ b/src/postgres/Makefile.am | |||
@@ -0,0 +1,20 @@ | |||
1 | INCLUDES = -I$(top_srcdir)/src/include | ||
2 | |||
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage | ||
9 | endif | ||
10 | |||
11 | lib_LTLIBRARIES = libgnunetpostgres.la | ||
12 | |||
13 | libgnunetpostgres_la_SOURCES = \ | ||
14 | postgres.c | ||
15 | libgnunetpostgres_la_LIBADD = -lpq \ | ||
16 | $(top_builddir)/src/util/libgnunetutil.la | ||
17 | libgnunetpostgres_la_LDFLAGS = \ | ||
18 | $(GN_LIB_LDFLAGS) \ | ||
19 | -version-info 0:0:0 | ||
20 | |||
diff --git a/src/postgres/postgres.c b/src/postgres/postgres.c new file mode 100644 index 000000000..c6b9a5aa6 --- /dev/null +++ b/src/postgres/postgres.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file postgres/postgres.c | ||
22 | * @brief library to help with access to a Postgres database | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_postgres_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Check if the result obtained from Postgres has | ||
31 | * the desired status code. If not, log an error, clear the | ||
32 | * result and return GNUNET_SYSERR. | ||
33 | * | ||
34 | * @param dbh database handle | ||
35 | * @param ret return value from database operation to check | ||
36 | * @param expected_status desired status | ||
37 | * @param command description of the command that was run | ||
38 | * @param args arguments given to the command | ||
39 | * @param filename name of the source file where the command was run | ||
40 | * @param line line number in the source file | ||
41 | * @return GNUNET_OK if the result is acceptable | ||
42 | */ | ||
43 | int | ||
44 | GNUNET_POSTGRES_check_result_ (PGconn *dbh, PGresult * ret, int expected_status, | ||
45 | const char *command, const char *args, const char *filename, | ||
46 | int line) | ||
47 | { | ||
48 | if (ret == NULL) | ||
49 | { | ||
50 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
51 | "postgres", | ||
52 | "Postgres failed to allocate result for `%s:%s' at %s:%d\n", | ||
53 | command, args, filename, line); | ||
54 | return GNUNET_SYSERR; | ||
55 | } | ||
56 | if (PQresultStatus (ret) != expected_status) | ||
57 | { | ||
58 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
59 | "postgres", | ||
60 | _("`%s:%s' failed at %s:%d with error: %s"), command, args, | ||
61 | filename, line, PQerrorMessage (dbh)); | ||
62 | PQclear (ret); | ||
63 | return GNUNET_SYSERR; | ||
64 | } | ||
65 | return GNUNET_OK; | ||
66 | } | ||
67 | |||
68 | |||
69 | /** | ||
70 | * Run simple SQL statement (without results). | ||
71 | * | ||
72 | * @param dbh database handle | ||
73 | * @param sql statement to run | ||
74 | * @param filename filename for error reporting | ||
75 | * @param line code line for error reporting | ||
76 | * @return GNUNET_OK on success | ||
77 | */ | ||
78 | int | ||
79 | GNUNET_POSTGRES_exec_ (PGconn *dbh, const char *sql, | ||
80 | const char *filename, | ||
81 | int line) | ||
82 | { | ||
83 | PGresult *ret; | ||
84 | |||
85 | ret = PQexec (dbh, sql); | ||
86 | if (GNUNET_OK != | ||
87 | GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQexec", sql, filename, line)) | ||
88 | return GNUNET_SYSERR; | ||
89 | PQclear (ret); | ||
90 | return GNUNET_OK; | ||
91 | } | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Prepare SQL statement. | ||
96 | * | ||
97 | * @param dbh database handle | ||
98 | * @param name name for the prepared SQL statement | ||
99 | * @param sql SQL code to prepare | ||
100 | * @param nparams number of parameters in sql | ||
101 | * @param filename filename for error reporting | ||
102 | * @param line code line for error reporting | ||
103 | * @return GNUNET_OK on success | ||
104 | */ | ||
105 | int | ||
106 | GNUNET_POSTGRES_prepare_ (PGconn *dbh, const char *name, const char *sql, | ||
107 | int nparms, const char *filename, int line) | ||
108 | { | ||
109 | PGresult *ret; | ||
110 | |||
111 | ret = PQprepare (dbh, name, sql, nparms, NULL); | ||
112 | if (GNUNET_OK != | ||
113 | GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQprepare", sql, filename, line)) | ||
114 | return GNUNET_SYSERR; | ||
115 | PQclear (ret); | ||
116 | return GNUNET_OK; | ||
117 | } | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Connect to a postgres database | ||
122 | * | ||
123 | * @param cfg configuration | ||
124 | * @param section configuration section to use to get Postgres configuration options | ||
125 | * @return the postgres handle | ||
126 | */ | ||
127 | PGconn * | ||
128 | GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
129 | const char *section) | ||
130 | { | ||
131 | PGconn *dbh; | ||
132 | char *conninfo; | ||
133 | |||
134 | /* Open database and precompile statements */ | ||
135 | if (GNUNET_OK != | ||
136 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
137 | section, "CONFIG", | ||
138 | &conninfo)) | ||
139 | conninfo = NULL; | ||
140 | dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); | ||
141 | GNUNET_free_non_null (conninfo); | ||
142 | if (NULL == dbh) | ||
143 | { | ||
144 | /* FIXME: warn about out-of-memory? */ | ||
145 | return NULL; | ||
146 | } | ||
147 | if (PQstatus (dbh) != CONNECTION_OK) | ||
148 | { | ||
149 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "postgres", | ||
150 | _("Unable to initialize Postgres: %s"), | ||
151 | PQerrorMessage (dbh)); | ||
152 | PQfinish (dbh); | ||
153 | return NULL; | ||
154 | } | ||
155 | return dbh; | ||
156 | } | ||
157 | |||
158 | |||
159 | /** | ||
160 | * Delete the row identified by the given rowid (qid | ||
161 | * in postgres). | ||
162 | * | ||
163 | * @param database handle | ||
164 | * @param stmt name of the prepared statement | ||
165 | * @param rowid which row to delete | ||
166 | * @return GNUNET_OK on success | ||
167 | */ | ||
168 | int | ||
169 | GNUNET_POSTGRES_delete_by_rowid (PGconn *dbh, | ||
170 | const char *stmt, | ||
171 | uint32_t rowid) | ||
172 | { | ||
173 | uint32_t brow = htonl (rowid); | ||
174 | const char *paramValues[] = { (const char *) &brow }; | ||
175 | int paramLengths[] = { sizeof (brow) }; | ||
176 | const int paramFormats[] = { 1 }; | ||
177 | PGresult *ret; | ||
178 | |||
179 | ret = | ||
180 | PQexecPrepared (dbh, stmt, 1, paramValues, paramLengths, | ||
181 | paramFormats, 1); | ||
182 | if (GNUNET_OK != | ||
183 | GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "delrow", | ||
184 | __FILE__, | ||
185 | __LINE__)) | ||
186 | { | ||
187 | return GNUNET_SYSERR; | ||
188 | } | ||
189 | PQclear (ret); | ||
190 | return GNUNET_OK; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* end of postgres.c */ | ||