aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-22 18:47:07 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-22 18:47:07 +0000
commit4c01d543d10a24b30e279cdb061d9ebe459cdcaf (patch)
tree3ccec82f8e23c009e7366f421dbfacbf43e01055
parent84b6e8491d8712f772a2297d59b2a1f4f21427fa (diff)
downloadgnunet-4c01d543d10a24b30e279cdb061d9ebe459cdcaf.tar.gz
gnunet-4c01d543d10a24b30e279cdb061d9ebe459cdcaf.zip
adding libgnunetpostgres for shared postgres functionality between postgres datastore/datacache backends
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am5
-rw-r--r--src/datacache/Makefile.am1
-rw-r--r--src/datacache/plugin_datacache_postgres.c180
-rw-r--r--src/datastore/plugin_datastore_postgres.c264
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_mysql_lib.h2
-rw-r--r--src/include/gnunet_postgres_lib.h163
-rw-r--r--src/postgres/Makefile.am20
-rw-r--r--src/postgres/postgres.c194
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
896src/peerinfo/Makefile 896src/peerinfo/Makefile
897src/peerinfo/peerinfo.conf 897src/peerinfo/peerinfo.conf
898src/peerinfo-tool/Makefile 898src/peerinfo-tool/Makefile
899src/postgres/Makefile
899src/pt/Makefile 900src/pt/Makefile
900src/statistics/Makefile 901src/statistics/Makefile
901src/statistics/statistics.conf 902src/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
16endif 16endif
17 17
18if HAVE_POSTGRES
19 POSTGRES_DIR = postgres
20endif
21
18 22
19SUBDIRS = \ 23SUBDIRS = \
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 = \
70libgnunet_plugin_datacache_postgres_la_SOURCES = \ 70libgnunet_plugin_datacache_postgres_la_SOURCES = \
71 plugin_datacache_postgres.c 71 plugin_datacache_postgres.c
72libgnunet_plugin_datacache_postgres_la_LIBADD = \ 72libgnunet_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 */
63static int
64check_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 */
94static int
95pq_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 */
118static int
119pq_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,
139static int 63static int
140init_connection (struct Plugin *plugin) 64init_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 */
258static int
259delete_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 */
77static int
78check_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 */
108static int
109pq_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 */
131static int
132pq_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,
151static int 71static int
152init_connection (struct Plugin *plugin) 72init_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 */
341static int
342delete_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 */
483static void 334static void
484process_result (struct Plugin *plugin, PluginDatumProcessor proc, 335process_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
32extern "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 */
54int
55GNUNET_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 */
84int
85GNUNET_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 */
109int
110GNUNET_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 */
134PGconn *
135GNUNET_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 */
148int
149GNUNET_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 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage
9endif
10
11lib_LTLIBRARIES = libgnunetpostgres.la
12
13libgnunetpostgres_la_SOURCES = \
14 postgres.c
15libgnunetpostgres_la_LIBADD = -lpq \
16 $(top_builddir)/src/util/libgnunetutil.la
17libgnunetpostgres_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 */
43int
44GNUNET_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 */
78int
79GNUNET_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 */
105int
106GNUNET_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 */
127PGconn *
128GNUNET_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 */
168int
169GNUNET_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 */