aboutsummaryrefslogtreecommitdiff
path: root/src/datacache
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 /src/datacache
parent84b6e8491d8712f772a2297d59b2a1f4f21427fa (diff)
downloadgnunet-4c01d543d10a24b30e279cdb061d9ebe459cdcaf.tar.gz
gnunet-4c01d543d10a24b30e279cdb061d9ebe459cdcaf.zip
adding libgnunetpostgres for shared postgres functionality between postgres datastore/datacache backends
Diffstat (limited to 'src/datacache')
-rw-r--r--src/datacache/Makefile.am1
-rw-r--r--src/datacache/plugin_datacache_postgres.c180
2 files changed, 25 insertions, 156 deletions
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;