diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-08 19:55:45 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-08 19:55:45 +0000 |
commit | be86840fb6144a631ff18237bc31abb7a97938f7 (patch) | |
tree | dfa68dcd690a40c5c060cd6ad7ad017696333655 /src/namestore | |
parent | 5049585e7942ad3fe3f8742832a2b4f76ec5a954 (diff) | |
download | gnunet-be86840fb6144a631ff18237bc31abb7a97938f7.tar.gz gnunet-be86840fb6144a631ff18237bc31abb7a97938f7.zip |
towards implementing postgres backend for namestore (#2987)
Diffstat (limited to 'src/namestore')
-rw-r--r-- | src/namestore/Makefile.am | 38 | ||||
-rw-r--r-- | src/namestore/plugin_namestore_postgres.c | 780 |
2 files changed, 430 insertions, 388 deletions
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index f19c9bff9..f6aa2a085 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am | |||
@@ -22,19 +22,17 @@ endif | |||
22 | if HAVE_SQLITE | 22 | if HAVE_SQLITE |
23 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la | 23 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la |
24 | if HAVE_TESTING | 24 | if HAVE_TESTING |
25 | SQLITE_TESTS = test_plugin_namestore_sqlite | 25 | SQLITE_TESTS = test_plugin_namestore_sqlite |
26 | endif | 26 | endif |
27 | endif | 27 | endif |
28 | 28 | ||
29 | if HAVE_POSTGRES | 29 | if HAVE_POSTGRES |
30 | # postgres doesn't even build yet; thus: experimental! | 30 | # postgres doesn't even build yet; thus: experimental! |
31 | if HAVE_EXPERIMENTAL | ||
32 | POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la | 31 | POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la |
33 | if HAVE_TESTING | 32 | if HAVE_TESTING |
34 | POSTGRES_TESTS = test_plugin_namestore_postgres | 33 | POSTGRES_TESTS = test_plugin_namestore_postgres |
35 | endif | 34 | endif |
36 | endif | 35 | endif |
37 | endif | ||
38 | 36 | ||
39 | # testcases do not even build yet; thus: experimental! | 37 | # testcases do not even build yet; thus: experimental! |
40 | if HAVE_TESTING | 38 | if HAVE_TESTING |
@@ -50,7 +48,7 @@ TESTING_TESTS = \ | |||
50 | test_namestore_api_zone_iteration_stop \ | 48 | test_namestore_api_zone_iteration_stop \ |
51 | test_namestore_api_monitoring \ | 49 | test_namestore_api_monitoring \ |
52 | test_namestore_api_monitoring_existing | 50 | test_namestore_api_monitoring_existing |
53 | #test_namestore_api_zone_to_name | 51 | #test_namestore_api_zone_to_name |
54 | endif | 52 | endif |
55 | 53 | ||
56 | if HAVE_SQLITE | 54 | if HAVE_SQLITE |
@@ -65,7 +63,7 @@ endif | |||
65 | if ENABLE_TEST_RUN | 63 | if ENABLE_TEST_RUN |
66 | TESTS = \ | 64 | TESTS = \ |
67 | $(check_PROGRAMS) \ | 65 | $(check_PROGRAMS) \ |
68 | $(check_SCRIPTS) | 66 | $(check_SCRIPTS) |
69 | endif | 67 | endif |
70 | 68 | ||
71 | lib_LTLIBRARIES = \ | 69 | lib_LTLIBRARIES = \ |
@@ -80,16 +78,16 @@ libgnunetnamestore_la_LIBADD = \ | |||
80 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 78 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
81 | $(top_builddir)/src/dns/libgnunetdnsparser.la \ | 79 | $(top_builddir)/src/dns/libgnunetdnsparser.la \ |
82 | $(top_builddir)/src/util/libgnunetutil.la \ | 80 | $(top_builddir)/src/util/libgnunetutil.la \ |
83 | $(GN_LIBINTL) | 81 | $(GN_LIBINTL) |
84 | libgnunetnamestore_la_LDFLAGS = \ | 82 | libgnunetnamestore_la_LDFLAGS = \ |
85 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 83 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
86 | -version-info 0:1:0 | 84 | -version-info 0:1:0 |
87 | 85 | ||
88 | libexec_PROGRAMS = \ | 86 | libexec_PROGRAMS = \ |
89 | gnunet-service-namestore | 87 | gnunet-service-namestore |
90 | 88 | ||
91 | bin_PROGRAMS = \ | 89 | bin_PROGRAMS = \ |
92 | gnunet-namestore | 90 | gnunet-namestore |
93 | 91 | ||
94 | if HAVE_MHD | 92 | if HAVE_MHD |
95 | libexec_PROGRAMS += \ | 93 | libexec_PROGRAMS += \ |
@@ -97,7 +95,7 @@ libexec_PROGRAMS += \ | |||
97 | endif | 95 | endif |
98 | 96 | ||
99 | gnunet_namestore_SOURCES = \ | 97 | gnunet_namestore_SOURCES = \ |
100 | gnunet-namestore.c | 98 | gnunet-namestore.c |
101 | gnunet_namestore_LDADD = \ | 99 | gnunet_namestore_LDADD = \ |
102 | $(top_builddir)/src/util/libgnunetutil.la \ | 100 | $(top_builddir)/src/util/libgnunetutil.la \ |
103 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 101 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
@@ -110,7 +108,7 @@ gnunet_namestore_DEPENDENCIES = \ | |||
110 | 108 | ||
111 | 109 | ||
112 | gnunet_namestore_fcfsd_SOURCES = \ | 110 | gnunet_namestore_fcfsd_SOURCES = \ |
113 | gnunet-namestore-fcfsd.c | 111 | gnunet-namestore-fcfsd.c |
114 | gnunet_namestore_fcfsd_LDADD = -lmicrohttpd \ | 112 | gnunet_namestore_fcfsd_LDADD = -lmicrohttpd \ |
115 | $(top_builddir)/src/util/libgnunetutil.la \ | 113 | $(top_builddir)/src/util/libgnunetutil.la \ |
116 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 114 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
@@ -141,7 +139,7 @@ plugin_LTLIBRARIES = \ | |||
141 | $(POSTGRES_PLUGIN) | 139 | $(POSTGRES_PLUGIN) |
142 | 140 | ||
143 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ | 141 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ |
144 | plugin_namestore_sqlite.c | 142 | plugin_namestore_sqlite.c |
145 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ | 143 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ |
146 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 144 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
147 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 145 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
@@ -156,7 +154,7 @@ libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ | |||
156 | 154 | ||
157 | 155 | ||
158 | libgnunet_plugin_namestore_postgres_la_SOURCES = \ | 156 | libgnunet_plugin_namestore_postgres_la_SOURCES = \ |
159 | plugin_namestore_postgres.c | 157 | plugin_namestore_postgres.c |
160 | libgnunet_plugin_namestore_postgres_la_LIBADD = \ | 158 | libgnunet_plugin_namestore_postgres_la_LIBADD = \ |
161 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 159 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
162 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ | 160 | $(top_builddir)/src/postgres/libgnunetpostgres.la \ |
@@ -239,48 +237,48 @@ test_namestore_api_monitoring_SOURCES = \ | |||
239 | test_namestore_api_monitoring_LDADD = \ | 237 | test_namestore_api_monitoring_LDADD = \ |
240 | $(top_builddir)/src/testing/libgnunettesting.la \ | 238 | $(top_builddir)/src/testing/libgnunettesting.la \ |
241 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 239 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
242 | $(top_builddir)/src/util/libgnunetutil.la | 240 | $(top_builddir)/src/util/libgnunetutil.la |
243 | 241 | ||
244 | test_namestore_api_monitoring_existing_SOURCES = \ | 242 | test_namestore_api_monitoring_existing_SOURCES = \ |
245 | test_namestore_api_monitoring_existing.c | 243 | test_namestore_api_monitoring_existing.c |
246 | test_namestore_api_monitoring_existing_LDADD = \ | 244 | test_namestore_api_monitoring_existing_LDADD = \ |
247 | $(top_builddir)/src/testing/libgnunettesting.la \ | 245 | $(top_builddir)/src/testing/libgnunettesting.la \ |
248 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | 246 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ |
249 | $(top_builddir)/src/util/libgnunetutil.la | 247 | $(top_builddir)/src/util/libgnunetutil.la |
250 | 248 | ||
251 | test_namestore_api_zone_iteration_SOURCES = \ | 249 | test_namestore_api_zone_iteration_SOURCES = \ |
252 | test_namestore_api_zone_iteration.c | 250 | test_namestore_api_zone_iteration.c |
253 | test_namestore_api_zone_iteration_LDADD = \ | 251 | test_namestore_api_zone_iteration_LDADD = \ |
254 | $(top_builddir)/src/testing/libgnunettesting.la \ | 252 | $(top_builddir)/src/testing/libgnunettesting.la \ |
255 | $(top_builddir)/src/util/libgnunetutil.la \ | 253 | $(top_builddir)/src/util/libgnunetutil.la \ |
256 | $(top_builddir)/src/namestore/libgnunetnamestore.la | 254 | $(top_builddir)/src/namestore/libgnunetnamestore.la |
257 | 255 | ||
258 | test_namestore_api_zone_iteration_specific_zone_SOURCES = \ | 256 | test_namestore_api_zone_iteration_specific_zone_SOURCES = \ |
259 | test_namestore_api_zone_iteration_specific_zone.c | 257 | test_namestore_api_zone_iteration_specific_zone.c |
260 | test_namestore_api_zone_iteration_specific_zone_LDADD = \ | 258 | test_namestore_api_zone_iteration_specific_zone_LDADD = \ |
261 | $(top_builddir)/src/testing/libgnunettesting.la \ | 259 | $(top_builddir)/src/testing/libgnunettesting.la \ |
262 | $(top_builddir)/src/util/libgnunetutil.la \ | 260 | $(top_builddir)/src/util/libgnunetutil.la \ |
263 | $(top_builddir)/src/namestore/libgnunetnamestore.la | 261 | $(top_builddir)/src/namestore/libgnunetnamestore.la |
264 | 262 | ||
265 | test_namestore_api_zone_iteration_stop_SOURCES = \ | 263 | test_namestore_api_zone_iteration_stop_SOURCES = \ |
266 | test_namestore_api_zone_iteration_stop.c | 264 | test_namestore_api_zone_iteration_stop.c |
267 | test_namestore_api_zone_iteration_stop_LDADD = \ | 265 | test_namestore_api_zone_iteration_stop_LDADD = \ |
268 | $(top_builddir)/src/testing/libgnunettesting.la \ | 266 | $(top_builddir)/src/testing/libgnunettesting.la \ |
269 | $(top_builddir)/src/util/libgnunetutil.la \ | 267 | $(top_builddir)/src/util/libgnunetutil.la \ |
270 | $(top_builddir)/src/namestore/libgnunetnamestore.la | 268 | $(top_builddir)/src/namestore/libgnunetnamestore.la |
271 | 269 | ||
272 | test_namestore_record_serialization_SOURCES = \ | 270 | test_namestore_record_serialization_SOURCES = \ |
273 | test_namestore_record_serialization.c | 271 | test_namestore_record_serialization.c |
274 | test_namestore_record_serialization_LDADD = \ | 272 | test_namestore_record_serialization_LDADD = \ |
275 | $(top_builddir)/src/testing/libgnunettesting.la \ | 273 | $(top_builddir)/src/testing/libgnunettesting.la \ |
276 | $(top_builddir)/src/util/libgnunetutil.la \ | 274 | $(top_builddir)/src/util/libgnunetutil.la \ |
277 | $(top_builddir)/src/namestore/libgnunetnamestore.la | 275 | $(top_builddir)/src/namestore/libgnunetnamestore.la |
278 | 276 | ||
279 | test_plugin_namestore_sqlite_SOURCES = \ | 277 | test_plugin_namestore_sqlite_SOURCES = \ |
280 | test_plugin_namestore.c | 278 | test_plugin_namestore.c |
281 | test_plugin_namestore_sqlite_LDADD = \ | 279 | test_plugin_namestore_sqlite_LDADD = \ |
282 | $(top_builddir)/src/testing/libgnunettesting.la \ | 280 | $(top_builddir)/src/testing/libgnunettesting.la \ |
283 | $(top_builddir)/src/util/libgnunetutil.la | 281 | $(top_builddir)/src/util/libgnunetutil.la |
284 | 282 | ||
285 | test_plugin_namestore_postgres_SOURCES = \ | 283 | test_plugin_namestore_postgres_SOURCES = \ |
286 | test_plugin_namestore.c | 284 | test_plugin_namestore.c |
@@ -291,7 +289,7 @@ test_plugin_namestore_postgres_LDADD = \ | |||
291 | check_SCRIPTS = \ | 289 | check_SCRIPTS = \ |
292 | test_namestore_put.sh \ | 290 | test_namestore_put.sh \ |
293 | test_namestore_lookup.sh \ | 291 | test_namestore_lookup.sh \ |
294 | test_namestore_delete.sh | 292 | test_namestore_delete.sh |
295 | 293 | ||
296 | EXTRA_DIST = \ | 294 | EXTRA_DIST = \ |
297 | test_namestore_api.conf \ | 295 | test_namestore_api.conf \ |
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c index fe4280a3c..4697923d0 100644 --- a/src/namestore/plugin_namestore_postgres.c +++ b/src/namestore/plugin_namestore_postgres.c | |||
@@ -23,7 +23,6 @@ | |||
23 | * @brief postgres-based namestore backend | 23 | * @brief postgres-based namestore backend |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | */ | 25 | */ |
26 | |||
27 | #include "platform.h" | 26 | #include "platform.h" |
28 | #include "gnunet_namestore_plugin.h" | 27 | #include "gnunet_namestore_plugin.h" |
29 | #include "gnunet_namestore_service.h" | 28 | #include "gnunet_namestore_service.h" |
@@ -80,17 +79,20 @@ create_indices (PGconn * dbh) | |||
80 | { | 79 | { |
81 | /* create indices */ | 80 | /* create indices */ |
82 | if ( (GNUNET_OK != | 81 | if ( (GNUNET_OK != |
83 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)")) || | 82 | GNUNET_POSTGRES_exec (dbh, |
84 | (GNUNET_OK != | 83 | "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)")) || |
85 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX is_block_expiration ON ns096blocks (expiration_time)")) || | ||
86 | (GNUNET_OK != | 84 | (GNUNET_OK != |
87 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX is_pkey_reverse ON ns097records (zone_private_key,pkey)")) || | 85 | GNUNET_POSTGRES_exec (dbh, |
86 | "CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)")) || | ||
88 | (GNUNET_OK != | 87 | (GNUNET_OK != |
89 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_zone ON ns091records (zone_hash)")) || | 88 | GNUNET_POSTGRES_exec (dbh, |
89 | "CREATE INDEX ir_pkey_reverse ON ns097records (zone_private_key,pkey)")) || | ||
90 | (GNUNET_OK != | 90 | (GNUNET_OK != |
91 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_name_rv ON ns091records (record_name_hash,rvalue)")) || | 91 | GNUNET_POSTGRES_exec (dbh, |
92 | "CREATE INDEX ir_pkey_iter ON ns097records (zone_private_key,rvalue)")) || | ||
92 | (GNUNET_OK != | 93 | (GNUNET_OK != |
93 | GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_rv ON ns091records (rvalue)")) ) | 94 | GNUNET_POSTGRES_exec (dbh, |
95 | "CREATE INDEX it_iter ON ns097records (rvalue)")) ) | ||
94 | LOG (GNUNET_ERROR_TYPE_ERROR, | 96 | LOG (GNUNET_ERROR_TYPE_ERROR, |
95 | _("Failed to create indices\n")); | 97 | _("Failed to create indices\n")); |
96 | } | 98 | } |
@@ -120,42 +122,77 @@ database_setup (struct Plugin *plugin) | |||
120 | { | 122 | { |
121 | res = | 123 | res = |
122 | PQexec (plugin->dbh, | 124 | PQexec (plugin->dbh, |
123 | "CREATE TEMPORARY TABLE ns091records (" | 125 | "CREATE TEMPORARY TABLE ns097records (" |
124 | " zone_key BYTEA NOT NULL DEFAULT ''," | 126 | " zone_private_key BYTEA NOT NULL DEFAULT ''," |
125 | " zone_delegation BYTEA NOT NULL DEFAULT ''," | 127 | " pkey BYTEA DEFAULT ''," |
126 | " zone_hash BYTEA NOT NULL DEFAULT ''," | 128 | " rvalue BYTEA NOT NULL DEFAULT ''," |
127 | " record_count INTEGER NOT NULL DEFAULT 0," | 129 | " record_count INTEGER NOT NULL DEFAULT 0," |
128 | " record_data BYTEA NOT NULL DEFAULT ''," | 130 | " record_data BYTEA NOT NULL DEFAULT ''," |
129 | " block_expiration_time BIGINT NOT NULL DEFAULT 0," | 131 | " label TEXT NOT NULL DEFAULT ''" |
130 | " signature BYTEA NOT NULL DEFAULT ''," | ||
131 | " record_name TEXT NOT NULL DEFAULT ''," | ||
132 | " record_name_hash BYTEA NOT NULL DEFAULT ''," | ||
133 | " rvalue BIGINT NOT NULL DEFAULT 0" | ||
134 | ")" "WITH OIDS"); | 132 | ")" "WITH OIDS"); |
135 | } | 133 | } |
136 | else | 134 | else |
135 | { | ||
137 | res = | 136 | res = |
138 | PQexec (plugin->dbh, | 137 | PQexec (plugin->dbh, |
139 | "CREATE TABLE ns091records (" | 138 | "CREATE TABLE ns097records (" |
140 | " zone_key BYTEA NOT NULL DEFAULT ''," | 139 | " zone_private_key BYTEA NOT NULL DEFAULT ''," |
141 | " zone_delegation BYTEA NOT NULL DEFAULT ''," | 140 | " pkey BYTEA DEFAULT ''," |
142 | " zone_hash BYTEA NOT NULL DEFAULT ''," | 141 | " rvalue BYTEA NOT NULL DEFAULT ''," |
143 | " record_count INTEGER NOT NULL DEFAULT 0," | 142 | " record_count INTEGER NOT NULL DEFAULT 0," |
144 | " record_data BYTEA NOT NULL DEFAULT ''," | 143 | " record_data BYTEA NOT NULL DEFAULT ''," |
145 | " block_expiration_time BIGINT NOT NULL DEFAULT 0," | 144 | " label TEXT NOT NULL DEFAULT ''" |
146 | " signature BYTEA NOT NULL DEFAULT ''," | ||
147 | " record_name TEXT NOT NULL DEFAULT ''," | ||
148 | " record_name_hash BYTEA NOT NULL DEFAULT ''," | ||
149 | " rvalue BIGINT NOT NULL DEFAULT 0" | ||
150 | ")" "WITH OIDS"); | 145 | ")" "WITH OIDS"); |
146 | } | ||
147 | if ( (NULL == res) || | ||
148 | ((PQresultStatus (res) != PGRES_COMMAND_OK) && | ||
149 | (0 != strcmp ("42P07", /* duplicate table */ | ||
150 | PQresultErrorField | ||
151 | (res, | ||
152 | PG_DIAG_SQLSTATE))))) | ||
153 | { | ||
154 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, | ||
155 | PGRES_COMMAND_OK, "CREATE TABLE", | ||
156 | "ns097records"); | ||
157 | PQfinish (plugin->dbh); | ||
158 | plugin->dbh = NULL; | ||
159 | return GNUNET_SYSERR; | ||
160 | } | ||
161 | |||
151 | 162 | ||
152 | if ((NULL == res) || ((PQresultStatus (res) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ | 163 | if (GNUNET_YES == |
153 | PQresultErrorField | 164 | GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, |
154 | (res, | 165 | "namestore-postgres", |
155 | PG_DIAG_SQLSTATE))))) | 166 | "TEMPORARY_TABLE")) |
156 | { | 167 | { |
157 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "CREATE TABLE", | 168 | res = |
158 | "ns091records"); | 169 | PQexec (plugin->dbh, |
170 | "CREATE TEMPORARY TABLE ns096blocks (" | ||
171 | " query BYTEA NOT NULL DEFAULT ''," | ||
172 | " block BYTEA NOT NULL DEFAULT ''," | ||
173 | " expiration_time BIGINT NOT NULL DEFAULT 0" | ||
174 | ")" "WITH OIDS"); | ||
175 | } | ||
176 | else | ||
177 | { | ||
178 | res = | ||
179 | PQexec (plugin->dbh, | ||
180 | "CREATE TABLE ns096blocks (" | ||
181 | " query BYTEA NOT NULL DEFAULT ''," | ||
182 | " block BYTEA NOT NULL DEFAULT ''," | ||
183 | " expiration_time BIGINT NOT NULL DEFAULT 0" | ||
184 | ")" "WITH OIDS"); | ||
185 | } | ||
186 | if ( (NULL == res) || | ||
187 | ((PQresultStatus (res) != PGRES_COMMAND_OK) && | ||
188 | (0 != strcmp ("42P07", /* duplicate table */ | ||
189 | PQresultErrorField | ||
190 | (res, | ||
191 | PG_DIAG_SQLSTATE))))) | ||
192 | { | ||
193 | (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, | ||
194 | PGRES_COMMAND_OK, "CREATE TABLE", | ||
195 | "ns096blocks"); | ||
159 | PQfinish (plugin->dbh); | 196 | PQfinish (plugin->dbh); |
160 | plugin->dbh = NULL; | 197 | plugin->dbh = NULL; |
161 | return GNUNET_SYSERR; | 198 | return GNUNET_SYSERR; |
@@ -166,43 +203,46 @@ database_setup (struct Plugin *plugin) | |||
166 | 203 | ||
167 | if ((GNUNET_OK != | 204 | if ((GNUNET_OK != |
168 | GNUNET_POSTGRES_prepare (plugin->dbh, | 205 | GNUNET_POSTGRES_prepare (plugin->dbh, |
169 | "put_records", | 206 | "cache_block", |
170 | "INSERT INTO ns091records (zone_key, record_name, record_count, record_data, block_expiration_time, signature" | 207 | "INSERT INTO ns096blocks (query, block, expiration_time) VALUES " |
171 | ", zone_delegation, zone_hash, record_name_hash, rvalue) VALUES " | 208 | "($1, $2, $3)", 3)) || |
172 | "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", 10)) || | ||
173 | (GNUNET_OK != | 209 | (GNUNET_OK != |
174 | GNUNET_POSTGRES_prepare (plugin->dbh, | 210 | GNUNET_POSTGRES_prepare (plugin->dbh, |
175 | "remove_records", | 211 | "expire_blocks", |
176 | "DELETE FROM ns091records WHERE zone_hash=$1 AND record_name_hash=$2", 2)) || | 212 | "DELETE FROM ns096blocks WHERE expiration_time<$1", 1)) || |
177 | (GNUNET_OK != | 213 | (GNUNET_OK != |
178 | GNUNET_POSTGRES_prepare (plugin->dbh, | 214 | GNUNET_POSTGRES_prepare (plugin->dbh, |
179 | "iterate_records", | 215 | "delete_block", |
180 | "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" | 216 | "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2)) || |
181 | " FROM ns091records WHERE zone_hash=$1 AND record_name_hash=$2 ORDER BY rvalue LIMIT 1 OFFSET $3", 3)) || | ||
182 | (GNUNET_OK != | 217 | (GNUNET_OK != |
183 | GNUNET_POSTGRES_prepare (plugin->dbh, | 218 | GNUNET_POSTGRES_prepare (plugin->dbh, |
184 | "iterate_by_zone", | 219 | "lookup_block", |
185 | "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" | 220 | "SELECT block FROM ns096blocks WHERE query=$1" |
186 | " FROM ns091records WHERE zone_hash=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || | 221 | " ORDER BY expiration_time DESC LIMIT 1", 1)) || |
187 | (GNUNET_OK != | 222 | (GNUNET_OK != |
188 | GNUNET_POSTGRES_prepare (plugin->dbh, | 223 | GNUNET_POSTGRES_prepare (plugin->dbh, |
189 | "iterate_by_name", | 224 | "store_records", |
190 | "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" | 225 | "INSERT INTO ns097records (zone_private_key, pkey, value, record_count, record_data, label) VALUES " |
191 | " FROM ns091records WHERE record_name_hash=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || | 226 | "($1, $2, $3, $4, $5, $6)", 6)) || |
192 | (GNUNET_OK != | 227 | (GNUNET_OK != |
193 | GNUNET_POSTGRES_prepare (plugin->dbh, | 228 | GNUNET_POSTGRES_prepare (plugin->dbh, |
194 | "iterate_all", | 229 | "delete_records", |
195 | "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" | 230 | "DELETE FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)) || |
196 | " FROM ns091records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)) || | ||
197 | (GNUNET_OK != | 231 | (GNUNET_OK != |
198 | GNUNET_POSTGRES_prepare (plugin->dbh, | 232 | GNUNET_POSTGRES_prepare (plugin->dbh, |
199 | "zone_to_name", | 233 | "zone_to_name", |
200 | "SELECT zone_key, record_name, record_count, record_data, block_expiration_time, signature" | 234 | "SELECT record_count,record_data,label FROM ns097records" |
201 | " FROM ns091records WHERE zone_hash=$1 AND zone_delegation=$2", 2)) || | 235 | " WHERE zone_private_key=$1 AND pkey=$2", 2)) || |
236 | (GNUNET_OK != | ||
237 | GNUNET_POSTGRES_prepare (plugin->dbh, | ||
238 | "iterate_zone", | ||
239 | "SELECT record_count, record_data, label FROM ns097records" | ||
240 | " WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || | ||
202 | (GNUNET_OK != | 241 | (GNUNET_OK != |
203 | GNUNET_POSTGRES_prepare (plugin->dbh, | 242 | GNUNET_POSTGRES_prepare (plugin->dbh, |
204 | "delete_zone", | 243 | "iterate_all_zones", |
205 | "DELETE FROM ns091records WHERE zone_hash=$1", 1))) | 244 | "SELECT record_count,record_data,label,zone_private_key" |
245 | " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1))) | ||
206 | { | 246 | { |
207 | PQfinish (plugin->dbh); | 247 | PQfinish (plugin->dbh); |
208 | plugin->dbh = NULL; | 248 | plugin->dbh = NULL; |
@@ -211,99 +251,236 @@ database_setup (struct Plugin *plugin) | |||
211 | return GNUNET_OK; | 251 | return GNUNET_OK; |
212 | } | 252 | } |
213 | 253 | ||
214 | #if 0 | ||
215 | 254 | ||
216 | TODO: removed | 255 | /** |
256 | * Removes any expired block. | ||
257 | * | ||
258 | * @param plugin the plugin | ||
259 | */ | ||
260 | static void | ||
261 | namestore_postgres_expire_blocks (struct Plugin *plugin) | ||
262 | { | ||
263 | struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); | ||
264 | struct GNUNET_TIME_AbsoluteNBO now_be = GNUNET_TIME_absolute_hton (now); | ||
265 | const char *paramValues[] = { | ||
266 | (const char *) &now_be | ||
267 | }; | ||
268 | int paramLengths[] = { | ||
269 | sizeof (now_be) | ||
270 | }; | ||
271 | const int paramFormats[] = { 1 }; | ||
272 | PGresult *res; | ||
273 | |||
274 | res = | ||
275 | PQexecPrepared (plugin->dbh, "expire_blocks", 1, | ||
276 | paramValues, paramLengths, paramFormats, 1); | ||
277 | if (GNUNET_OK != | ||
278 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
279 | res, | ||
280 | PGRES_COMMAND_OK, | ||
281 | "PQexecPrepared", | ||
282 | "expire_blocks")) | ||
283 | return; | ||
284 | PQclear (res); | ||
285 | } | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Delete older block in the datastore. | ||
290 | * | ||
291 | * @param the plugin | ||
292 | * @param query query for the block | ||
293 | * @param expiration time how old does the block have to be for deletion | ||
294 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
295 | */ | ||
296 | static void | ||
297 | delete_old_block (struct Plugin *plugin, | ||
298 | const struct GNUNET_HashCode *query, | ||
299 | struct GNUNET_TIME_AbsoluteNBO expiration_time) | ||
300 | { | ||
301 | const char *paramValues[] = { | ||
302 | (const char *) query, | ||
303 | (const char *) &expiration_time | ||
304 | }; | ||
305 | int paramLengths[] = { | ||
306 | sizeof (*query), | ||
307 | sizeof (expiration_time) | ||
308 | }; | ||
309 | const int paramFormats[] = { 1, 1 }; | ||
310 | PGresult *res; | ||
311 | |||
312 | res = | ||
313 | PQexecPrepared (plugin->dbh, "delete_block", 2, | ||
314 | paramValues, paramLengths, paramFormats, 1); | ||
315 | if (GNUNET_OK != | ||
316 | GNUNET_POSTGRES_check_result (plugin->dbh, | ||
317 | res, | ||
318 | PGRES_COMMAND_OK, | ||
319 | "PQexecPrepared", | ||
320 | "delete_block")) | ||
321 | return; | ||
322 | PQclear (res); | ||
323 | } | ||
324 | |||
217 | 325 | ||
218 | /** | 326 | /** |
219 | * Removes any existing record in the given zone with the same name. | 327 | * Cache a block in the datastore. |
220 | * | 328 | * |
221 | * @param cls closure (internal context for the plugin) | 329 | * @param cls closure (internal context for the plugin) |
222 | * @param zone hash of the public key of the zone | 330 | * @param block block to cache |
223 | * @param name name to remove (at most 255 characters long) | 331 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR |
224 | * @return GNUNET_OK on success | ||
225 | */ | 332 | */ |
226 | static int | 333 | static int |
227 | namestore_postgres_remove_records (void *cls, | 334 | namestore_postgres_cache_block (void *cls, |
228 | const struct GNUNET_CRYPTO_ShortHashCode *zone, | 335 | const struct GNUNET_NAMESTORE_Block *block) |
229 | const char *name) | ||
230 | { | 336 | { |
231 | struct Plugin *plugin = cls; | 337 | struct Plugin *plugin = cls; |
232 | PGresult *ret; | 338 | struct GNUNET_HashCode query; |
233 | struct GNUNET_CRYPTO_ShortHashCode nh; | 339 | size_t block_size = ntohl (block->purpose.size) + |
340 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) + | ||
341 | sizeof (struct GNUNET_CRYPTO_EccSignature); | ||
234 | const char *paramValues[] = { | 342 | const char *paramValues[] = { |
235 | (const char *) zone, | 343 | (const char *) &query, |
236 | (const char *) &nh | 344 | (const char *) block, |
345 | (const char *) &block->expiration_time | ||
237 | }; | 346 | }; |
238 | int paramLengths[] = { | 347 | int paramLengths[] = { |
239 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | 348 | sizeof (query), |
240 | sizeof (struct GNUNET_CRYPTO_ShortHashCode) | 349 | (int) block_size, |
350 | sizeof (block->expiration_time) | ||
241 | }; | 351 | }; |
242 | const int paramFormats[] = { 1, 1 }; | 352 | const int paramFormats[] = { 1, 1, 1 }; |
243 | size_t name_len; | 353 | PGresult *res; |
244 | 354 | ||
245 | name_len = strlen (name); | 355 | namestore_postgres_expire_blocks (plugin); |
246 | GNUNET_CRYPTO_short_hash (name, name_len, &nh); | 356 | GNUNET_CRYPTO_hash (&block->derived_key, |
247 | ret = | 357 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), |
248 | PQexecPrepared (plugin->dbh, "remove_records", 2, paramValues, paramLengths, | 358 | &query); |
249 | paramFormats, 1); | 359 | if (block_size > 64 * 65536) |
360 | { | ||
361 | GNUNET_break (0); | ||
362 | return GNUNET_SYSERR; | ||
363 | } | ||
364 | delete_old_block (plugin, &query, block->expiration_time); | ||
365 | |||
366 | res = | ||
367 | PQexecPrepared (plugin->dbh, "cache_block", 3, | ||
368 | paramValues, paramLengths, paramFormats, 1); | ||
250 | if (GNUNET_OK != | 369 | if (GNUNET_OK != |
251 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "remove_records")) | 370 | GNUNET_POSTGRES_check_result (plugin->dbh, |
371 | res, | ||
372 | PGRES_COMMAND_OK, | ||
373 | "PQexecPrepared", | ||
374 | "cache_block")) | ||
252 | return GNUNET_SYSERR; | 375 | return GNUNET_SYSERR; |
253 | PQclear (ret); | 376 | PQclear (res); |
254 | return GNUNET_OK; | 377 | return GNUNET_OK; |
255 | } | 378 | } |
256 | 379 | ||
257 | 380 | ||
381 | /** | ||
382 | * Get the block for a particular zone and label in the | ||
383 | * datastore. Will return at most one result to the iterator. | ||
384 | * | ||
385 | * @param cls closure (internal context for the plugin) | ||
386 | * @param query hash of public key derived from the zone and the label | ||
387 | * @param iter function to call with the result | ||
388 | * @param iter_cls closure for @a iter | ||
389 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
390 | */ | ||
391 | static int | ||
392 | namestore_postgres_lookup_block (void *cls, | ||
393 | const struct GNUNET_HashCode *query, | ||
394 | GNUNET_NAMESTORE_BlockCallback iter, void *iter_cls) | ||
395 | { | ||
396 | struct Plugin *plugin = cls; | ||
397 | const char *paramValues[] = { | ||
398 | (const char *) query | ||
399 | }; | ||
400 | int paramLengths[] = { | ||
401 | sizeof (*query) | ||
402 | }; | ||
403 | const int paramFormats[] = { 1 }; | ||
404 | PGresult *res; | ||
405 | unsigned int cnt; | ||
406 | size_t bsize; | ||
407 | const struct GNUNET_NAMESTORE_Block *block; | ||
408 | |||
409 | res = PQexecPrepared (plugin->dbh, | ||
410 | "lookup_block", 1, | ||
411 | paramValues, paramLengths, paramFormats, | ||
412 | 1); | ||
413 | if (GNUNET_OK != | ||
414 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, | ||
415 | "PQexecPrepared", | ||
416 | "lookup_block")) | ||
417 | { | ||
418 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
419 | "Failing lookup (postgres error)\n"); | ||
420 | return GNUNET_SYSERR; | ||
421 | } | ||
422 | if (0 == (cnt = PQntuples (res))) | ||
423 | { | ||
424 | /* no result */ | ||
425 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
426 | "Ending iteration (no more results)\n"); | ||
427 | PQclear (res); | ||
428 | return GNUNET_NO; | ||
429 | } | ||
430 | GNUNET_assert (1 == cnt); | ||
431 | GNUNET_assert (1 != PQnfields (res)); | ||
432 | bsize = PQgetlength (res, 0, 0); | ||
433 | block = (const struct GNUNET_NAMESTORE_Block *) PQgetvalue (res, 0, 0); | ||
434 | if ( (bsize < sizeof (*block)) || | ||
435 | (bsize != ntohl (block->purpose.size) + | ||
436 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) + | ||
437 | sizeof (struct GNUNET_CRYPTO_EccSignature)) ) | ||
438 | { | ||
439 | GNUNET_break (0); | ||
440 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
441 | "Failing lookup (corrupt block)\n"); | ||
442 | PQclear (res); | ||
443 | return GNUNET_SYSERR; | ||
444 | } | ||
445 | iter (iter_cls, block); | ||
446 | PQclear (res); | ||
447 | return GNUNET_OK; | ||
448 | } | ||
449 | |||
258 | 450 | ||
259 | /** | 451 | /** |
260 | * Store a record in the datastore. Removes any existing record in the | 452 | * Store a record in the datastore. Removes any existing record in the |
261 | * same zone with the same name. | 453 | * same zone with the same name. |
262 | * | 454 | * |
263 | * @param cls closure (internal context for the plugin) | 455 | * @param cls closure (internal context for the plugin) |
264 | * @param zone_key public key of the zone | 456 | * @param zone_key private key of the zone |
265 | * @param expire when does the corresponding block in the DHT expire (until | 457 | * @param label name that is being mapped (at most 255 characters long) |
266 | * when should we never do a DHT lookup for the same name again)? | 458 | * @param rd_count number of entries in @a rd array |
267 | * @param name name that is being mapped (at most 255 characters long) | ||
268 | * @param rd_count number of entries in 'rd' array | ||
269 | * @param rd array of records with data to store | 459 | * @param rd array of records with data to store |
270 | * @param signature signature of the record block, NULL if signature is unavailable (i.e. | 460 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR |
271 | * because the user queried for a particular record type only) | ||
272 | * @return GNUNET_OK on success, else GNUNET_SYSERR | ||
273 | */ | 461 | */ |
274 | static int | 462 | static int |
275 | namestore_postgres_put_records (void *cls, | 463 | namestore_postgres_store_records (void *cls, |
276 | const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key, | 464 | const struct GNUNET_CRYPTO_EccPrivateKey *zone_key, |
277 | struct GNUNET_TIME_Absolute expire, | 465 | const char *label, |
278 | const char *name, | 466 | unsigned int rd_count, |
279 | unsigned int rd_count, | 467 | const struct GNUNET_NAMESTORE_RecordData *rd) |
280 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
281 | const struct GNUNET_CRYPTO_EccSignature *signature) | ||
282 | { | 468 | { |
283 | struct Plugin *plugin = cls; | 469 | struct Plugin *plugin = cls; |
284 | PGresult *ret; | 470 | struct GNUNET_CRYPTO_EccPublicSignKey pkey; |
285 | struct GNUNET_CRYPTO_ShortHashCode zone; | ||
286 | struct GNUNET_CRYPTO_ShortHashCode zone_delegation; | ||
287 | struct GNUNET_CRYPTO_ShortHashCode nh; | ||
288 | size_t name_len; | ||
289 | uint64_t rvalue; | 471 | uint64_t rvalue; |
472 | uint32_t rd_count_nbo = htonl ((uint32_t) rd_count); | ||
290 | size_t data_size; | 473 | size_t data_size; |
291 | unsigned int i; | 474 | unsigned int i; |
292 | 475 | ||
293 | GNUNET_CRYPTO_short_hash (zone_key, | 476 | memset (&pkey, 0, sizeof (pkey)); |
294 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), | ||
295 | &zone); | ||
296 | (void) namestore_postgres_remove_records (plugin, &zone, name); | ||
297 | name_len = strlen (name); | ||
298 | GNUNET_CRYPTO_short_hash (name, name_len, &nh); | ||
299 | memset (&zone_delegation, 0, sizeof (zone_delegation)); | ||
300 | for (i=0;i<rd_count;i++) | 477 | for (i=0;i<rd_count;i++) |
301 | if (rd[i].record_type == GNUNET_NAMESTORE_TYPE_PKEY) | 478 | if (GNUNET_NAMESTORE_TYPE_PKEY == rd[i].record_type) |
302 | { | 479 | { |
303 | GNUNET_assert (sizeof (struct GNUNET_CRYPTO_ShortHashCode) == rd[i].data_size); | 480 | GNUNET_break (sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) == rd[i].data_size); |
304 | memcpy (&zone_delegation, | 481 | memcpy (&pkey, |
305 | rd[i].data, | 482 | rd[i].data, |
306 | sizeof (struct GNUNET_CRYPTO_ShortHashCode)); | 483 | rd[i].data_size); |
307 | break; | 484 | break; |
308 | } | 485 | } |
309 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | 486 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); |
@@ -315,34 +492,24 @@ namestore_postgres_put_records (void *cls, | |||
315 | } | 492 | } |
316 | { | 493 | { |
317 | char data[data_size]; | 494 | char data[data_size]; |
318 | uint64_t expire_be = GNUNET_htonll (expire.abs_value_us); | ||
319 | uint64_t rvalue_be = GNUNET_htonll (rvalue); | ||
320 | uint32_t rd_count_be = htonl ((uint32_t) rd_count); | ||
321 | const char *paramValues[] = { | 495 | const char *paramValues[] = { |
322 | (const char *) zone_key, | 496 | (const char *) zone_key, |
323 | (const char *) name, | 497 | (const char *) &pkey, |
324 | (const char *) &rd_count_be, | 498 | (const char *) &rvalue, |
499 | (const char *) &rd_count_nbo, | ||
325 | (const char *) data, | 500 | (const char *) data, |
326 | (const char *) &expire_be, | 501 | label |
327 | (const char *) signature, | ||
328 | (const char *) &zone_delegation, | ||
329 | (const char *) &zone, | ||
330 | (const char *) &nh, | ||
331 | (const char *) &rvalue_be | ||
332 | }; | 502 | }; |
333 | int paramLengths[] = { | 503 | int paramLengths[] = { |
334 | sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), | 504 | sizeof (*zone_key), |
335 | name_len, | 505 | sizeof (pkey), |
336 | sizeof (uint32_t), | 506 | sizeof (rvalue), |
507 | sizeof (rd_count_nbo), | ||
337 | data_size, | 508 | data_size, |
338 | sizeof (uint64_t), | 509 | strlen (label) |
339 | sizeof (struct GNUNET_CRYPTO_EccSignature), | ||
340 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | ||
341 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | ||
342 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | ||
343 | sizeof (uint64_t) | ||
344 | }; | 510 | }; |
345 | const int paramFormats[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; | 511 | const int paramFormats[] = { 1, 1, 1, 1, 1, 1 }; |
512 | PGresult *res; | ||
346 | 513 | ||
347 | if (data_size != GNUNET_NAMESTORE_records_serialize (rd_count, rd, | 514 | if (data_size != GNUNET_NAMESTORE_records_serialize (rd_count, rd, |
348 | data_size, data)) | 515 | data_size, data)) |
@@ -350,89 +517,89 @@ namestore_postgres_put_records (void *cls, | |||
350 | GNUNET_break (0); | 517 | GNUNET_break (0); |
351 | return GNUNET_SYSERR; | 518 | return GNUNET_SYSERR; |
352 | } | 519 | } |
353 | ret = | 520 | |
354 | PQexecPrepared (plugin->dbh, "put_records", 10, paramValues, paramLengths, | 521 | res = |
355 | paramFormats, 1); | 522 | PQexecPrepared (plugin->dbh, "store_records", 6, |
523 | paramValues, paramLengths, paramFormats, 1); | ||
356 | if (GNUNET_OK != | 524 | if (GNUNET_OK != |
357 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put_records")) | 525 | GNUNET_POSTGRES_check_result (plugin->dbh, |
526 | res, | ||
527 | PGRES_COMMAND_OK, | ||
528 | "PQexecPrepared", | ||
529 | "store_records")) | ||
358 | return GNUNET_SYSERR; | 530 | return GNUNET_SYSERR; |
359 | PQclear (ret); | 531 | PQclear (res); |
532 | return GNUNET_OK; | ||
360 | } | 533 | } |
361 | return GNUNET_OK; | ||
362 | } | 534 | } |
363 | #endif | ||
364 | 535 | ||
365 | #if 0 | 536 | |
366 | /** | 537 | /** |
367 | * The given 'postgres' result was obtained from the database. | 538 | * A statement has been run. We should evaluate the result, and if possible |
368 | * Parse the record and give it to the iterator. | 539 | * call the given @a iter with the result. |
369 | * | 540 | * |
370 | * @param plugin plugin context | 541 | * @param plugin plugin context |
371 | * @param stmt_name name of the prepared statement that was executed | 542 | * @param res result from the statement that was run (to be cleaned up) |
372 | * @param res result from postgres to interpret (and then clean up) | 543 | * @param zone_key private key of the zone, could be NULL, in which case we should |
544 | * get the zone from @a res | ||
373 | * @param iter iterator to call with the result | 545 | * @param iter iterator to call with the result |
374 | * @param iter_cls closure for 'iter' | 546 | * @param iter_cls closure for @a iter |
375 | * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error | 547 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error |
376 | * 'iter' will have been called unless the return value is 'GNUNET_SYSERR' | ||
377 | */ | 548 | */ |
378 | static int | 549 | static int |
379 | get_record_and_call_iterator (struct Plugin *plugin, | 550 | get_record_and_call_iterator (struct Plugin *plugin, |
380 | const char *stmt_name, | 551 | PGresult *res, |
381 | PGresult *res, | 552 | const struct GNUNET_CRYPTO_EccPrivateKey *zone_key, |
382 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | 553 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) |
383 | { | 554 | { |
384 | unsigned int record_count; | ||
385 | size_t data_size; | ||
386 | /* const struct GNUNET_CRYPTO_EccPublicSignKey *zone_key; */ | ||
387 | const struct GNUNET_CRYPTO_EccPrivateKey *zone_key; | ||
388 | /* const struct GNUNET_CRYPTO_EccSignature *sig; */ | ||
389 | /* struct GNUNET_TIME_Absolute expiration; */ | ||
390 | const char *data; | 555 | const char *data; |
391 | const char *name; | 556 | size_t data_size; |
557 | uint32_t record_count; | ||
558 | const char *label; | ||
559 | size_t label_len; | ||
392 | unsigned int cnt; | 560 | unsigned int cnt; |
393 | size_t name_len; | ||
394 | 561 | ||
395 | if (GNUNET_OK != | 562 | if (GNUNET_OK != |
396 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", | 563 | GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, |
397 | stmt_name)) | 564 | "PQexecPrepared", |
565 | "iteration")) | ||
398 | { | 566 | { |
399 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 567 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
400 | "Ending iteration (postgres error)\n"); | 568 | "Failing lookup (postgres error)\n"); |
401 | return GNUNET_SYSERR; | 569 | return GNUNET_SYSERR; |
402 | } | 570 | } |
403 | |||
404 | if (0 == (cnt = PQntuples (res))) | 571 | if (0 == (cnt = PQntuples (res))) |
405 | { | 572 | { |
406 | /* no result */ | 573 | /* no result */ |
407 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 574 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
408 | "Ending iteration (no more results)\n"); | 575 | "Ending iteration (no more results)\n"); |
409 | PQclear (res); | 576 | PQclear (res); |
410 | |||
411 | iter (iter_cls, NULL, NULL, 0, NULL); | ||
412 | return GNUNET_NO; | 577 | return GNUNET_NO; |
413 | } | 578 | } |
414 | GNUNET_assert (1 == cnt); | 579 | GNUNET_assert (1 == cnt); |
415 | if ((6 != PQnfields (res)) || | 580 | GNUNET_assert (3 + ((NULL == zone_key) ? 1 : 0) == PQnfields (res)); |
416 | (sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) != PQgetlength (res, 0, 0)) || | 581 | if (NULL == zone_key) |
417 | (sizeof (uint32_t) != PQfsize (res, 2)) || | 582 | { |
418 | (sizeof (uint64_t) != PQfsize (res, 4)) || | 583 | if (sizeof (struct GNUNET_CRYPTO_EccPrivateKey) != PQgetlength (res, 0, 3)) |
419 | (sizeof (struct GNUNET_CRYPTO_EccSignature) != PQgetlength (res, 0, 5))) | 584 | { |
585 | GNUNET_break (0); | ||
586 | PQclear (res); | ||
587 | return GNUNET_SYSERR; | ||
588 | } | ||
589 | zone_key = (const struct GNUNET_CRYPTO_EccPrivateKey *) PQgetvalue (res, 0, 3); | ||
590 | } | ||
591 | if (sizeof (uint32_t) != PQfsize (res, 0)) | ||
420 | { | 592 | { |
421 | GNUNET_break (0); | 593 | GNUNET_break (0); |
422 | PQclear (res); | 594 | PQclear (res); |
423 | return GNUNET_SYSERR; | 595 | return GNUNET_SYSERR; |
424 | } | 596 | } |
425 | zone_key = (const struct GNUNET_CRYPTO_EccPrivateKey *) PQgetvalue (res, 0, 0); | 597 | |
426 | /* zone_key = (const struct GNUNET_CRYPTO_EccPublicSignKey *) PQgetvalue (res, 0, 0); */ | 598 | record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); |
427 | name = PQgetvalue (res, 0, 1); | 599 | data = PQgetvalue (res, 0, 1); |
428 | name_len = PQgetlength (res, 0, 1); | 600 | data_size = PQgetlength (res, 0, 1); |
429 | record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 2)); | 601 | label = PQgetvalue (res, 0, 2); |
430 | data_size = PQgetlength (res, 0, 3); | 602 | label_len = PQgetlength (res, 0, 1); |
431 | data = PQgetvalue (res, 0, 3); | ||
432 | /* | ||
433 | expiration.abs_value_us = | ||
434 | GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, 0, 4)); | ||
435 | sig = (const struct GNUNET_CRYPTO_EccSignature*) PQgetvalue (res, 0, 5); */ | ||
436 | if (record_count > 64 * 1024) | 603 | if (record_count > 64 * 1024) |
437 | { | 604 | { |
438 | /* sanity check, don't stack allocate far too much just | 605 | /* sanity check, don't stack allocate far too much just |
@@ -443,10 +610,10 @@ get_record_and_call_iterator (struct Plugin *plugin, | |||
443 | } | 610 | } |
444 | { | 611 | { |
445 | struct GNUNET_NAMESTORE_RecordData rd[record_count]; | 612 | struct GNUNET_NAMESTORE_RecordData rd[record_count]; |
446 | char buf[name_len + 1]; | 613 | char buf[label_len + 1]; |
447 | 614 | ||
448 | memcpy (buf, name, name_len); | 615 | memcpy (buf, label, label_len); |
449 | buf[name_len] = '\0'; | 616 | buf[label_len] = '\0'; |
450 | if (GNUNET_OK != | 617 | if (GNUNET_OK != |
451 | GNUNET_NAMESTORE_records_deserialize (data_size, data, | 618 | GNUNET_NAMESTORE_records_deserialize (data_size, data, |
452 | record_count, rd)) | 619 | record_count, rd)) |
@@ -460,7 +627,7 @@ get_record_and_call_iterator (struct Plugin *plugin, | |||
460 | PQclear (res); | 627 | PQclear (res); |
461 | return GNUNET_OK; | 628 | return GNUNET_OK; |
462 | } | 629 | } |
463 | #endif | 630 | |
464 | 631 | ||
465 | /** | 632 | /** |
466 | * Iterate over the results for a particular key and zone in the | 633 | * Iterate over the results for a particular key and zone in the |
@@ -470,81 +637,60 @@ get_record_and_call_iterator (struct Plugin *plugin, | |||
470 | * @param zone hash of public key of the zone, NULL to iterate over all zones | 637 | * @param zone hash of public key of the zone, NULL to iterate over all zones |
471 | * @param offset offset in the list of all matching records | 638 | * @param offset offset in the list of all matching records |
472 | * @param iter function to call with the result | 639 | * @param iter function to call with the result |
473 | * @param iter_cls closure for iter | 640 | * @param iter_cls closure for @a iter |
474 | * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error | 641 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error |
475 | * 'iter' will have been called unless the return value is 'GNUNET_SYSERR' | ||
476 | */ | 642 | */ |
477 | static int | 643 | static int |
478 | namestore_postgres_iterate_records (void *cls, | 644 | namestore_postgres_iterate_records (void *cls, |
479 | const struct GNUNET_CRYPTO_EccPrivateKey *zone, | 645 | const struct GNUNET_CRYPTO_EccPrivateKey *zone, |
480 | uint64_t offset, | 646 | uint64_t offset, |
481 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | 647 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) |
482 | { | 648 | { |
483 | #if 0 | ||
484 | struct Plugin *plugin = cls; | 649 | struct Plugin *plugin = cls; |
485 | const char *stmt_name; | ||
486 | struct GNUNET_CRYPTO_ShortHashCode name_hase; | ||
487 | uint64_t offset_be = GNUNET_htonll (offset); | 650 | uint64_t offset_be = GNUNET_htonll (offset); |
488 | const char *paramValues[] = { | ||
489 | (const char *) zone, | ||
490 | (const char *) &name_hase, | ||
491 | (const char *) &offset_be, | ||
492 | (const char *) zone, | ||
493 | (const char *) &offset_be, | ||
494 | }; | ||
495 | int paramLengths[] = { | ||
496 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | ||
497 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | ||
498 | sizeof (uint64_t), | ||
499 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | ||
500 | sizeof (uint64_t) | ||
501 | }; | ||
502 | const int paramFormats[] = { 1, 1, 1, 1, 1 }; | ||
503 | unsigned int num_params; | ||
504 | unsigned int first_param; | ||
505 | PGresult *res; | ||
506 | 651 | ||
507 | if (NULL == zone) | 652 | if (NULL == zone) |
508 | if (NULL == name) | 653 | { |
509 | { | 654 | const char *paramValues[] = { |
510 | stmt_name = "iterate_all"; | 655 | (const char *) &offset_be |
511 | num_params = 1; | 656 | }; |
512 | first_param = 2; | 657 | int paramLengths[] = { |
513 | } | 658 | sizeof (offset_be) |
514 | else | 659 | }; |
515 | { | 660 | const int paramFormats[] = { 1 }; |
516 | /* TODO Adapt to new API | 661 | PGresult *res; |
517 | * GNUNET_CRYPTO_short_hash (name, strlen(name), &name_hase); | 662 | |
518 | */ | 663 | res = PQexecPrepared (plugin->dbh, |
519 | stmt_name = "iterate_by_name"; | 664 | "iterate_all_zones", 1, |
520 | num_params = 2; | 665 | paramValues, paramLengths, paramFormats, |
521 | first_param = 1; | 666 | 1); |
522 | } | 667 | return get_record_and_call_iterator (plugin, |
668 | res, | ||
669 | NULL, | ||
670 | iter, iter_cls); | ||
671 | } | ||
523 | else | 672 | else |
524 | if (NULL == name) | 673 | { |
525 | { | 674 | const char *paramValues[] = { |
526 | stmt_name = "iterate_by_zone"; | 675 | (const char *) zone, |
527 | num_params = 2; | 676 | (const char *) &offset_be |
528 | first_param = 3; | 677 | }; |
529 | } | 678 | int paramLengths[] = { |
530 | else | 679 | sizeof (*zone), |
531 | { | 680 | sizeof (offset_be) |
532 | /* TODO Adapt to new API | 681 | }; |
533 | * GNUNET_CRYPTO_short_hash (name, strlen(name), &name_hase); | 682 | const int paramFormats[] = { 1, 1 }; |
534 | */ | 683 | PGresult *res; |
535 | stmt_name = "iterate_records"; | 684 | |
536 | num_params = 3; | 685 | res = PQexecPrepared (plugin->dbh, |
537 | first_param = 0; | 686 | "iterate_zone", 2, |
538 | } | 687 | paramValues, paramLengths, paramFormats, |
539 | res = | 688 | 1); |
540 | PQexecPrepared (plugin->dbh, stmt_name, num_params, | 689 | return get_record_and_call_iterator (plugin, |
541 | ¶mValues[first_param], | 690 | res, |
542 | ¶mLengths[first_param], | 691 | zone, |
543 | ¶mFormats[first_param], 1); | 692 | iter, iter_cls); |
544 | return get_record_and_call_iterator (plugin, stmt_name, res, iter, iter_cls); | 693 | } |
545 | #endif | ||
546 | GNUNET_break (0); | ||
547 | return GNUNET_SYSERR; | ||
548 | } | 694 | } |
549 | 695 | ||
550 | 696 | ||
@@ -553,137 +699,38 @@ namestore_postgres_iterate_records (void *cls, | |||
553 | * Returns at most one result to the iterator. | 699 | * Returns at most one result to the iterator. |
554 | * | 700 | * |
555 | * @param cls closure (internal context for the plugin) | 701 | * @param cls closure (internal context for the plugin) |
556 | * @param zone hash of public key of the zone to look up in, never NULL | 702 | * @param zone private key of the zone to look up in, never NULL |
557 | * @param value_zone hash of the public key of the target zone (value), never NULL | 703 | * @param value_zone public key of the target zone (value), never NULL |
558 | * @param iter function to call with the result | 704 | * @param iter function to call with the result |
559 | * @param iter_cls closure for iter | 705 | * @param iter_cls closure for @a iter |
560 | * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error | 706 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error |
561 | * 'iter' will have been called unless the return value is 'GNUNET_SYSERR' | ||
562 | */ | 707 | */ |
563 | static int | 708 | static int |
564 | namestore_postgres_zone_to_name (void *cls, | 709 | namestore_postgres_zone_to_name (void *cls, |
565 | const struct GNUNET_CRYPTO_EccPrivateKey *zone, | 710 | const struct GNUNET_CRYPTO_EccPrivateKey *zone, |
566 | const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone, | 711 | const struct GNUNET_CRYPTO_EccPublicSignKey *value_zone, |
567 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | 712 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) |
568 | { | 713 | { |
569 | #if 0 | ||
570 | struct Plugin *plugin = cls; | 714 | struct Plugin *plugin = cls; |
571 | const char *paramValues[] = { | 715 | const char *paramValues[] = { |
572 | (const char *) zone, | 716 | (const char *) zone, |
573 | (const char *) value_zone | 717 | (const char *) value_zone |
574 | }; | 718 | }; |
575 | int paramLengths[] = { | 719 | int paramLengths[] = { |
576 | sizeof (struct GNUNET_CRYPTO_ShortHashCode), | 720 | sizeof (*zone), |
577 | sizeof (struct GNUNET_CRYPTO_ShortHashCode) | 721 | sizeof (*value_zone) |
578 | }; | 722 | }; |
579 | const int paramFormats[] = { 1, 1 }; | 723 | const int paramFormats[] = { 1, 1 }; |
580 | PGresult *res; | 724 | PGresult *res; |
581 | 725 | ||
582 | res = | 726 | res = PQexecPrepared (plugin->dbh, |
583 | PQexecPrepared (plugin->dbh, "zone_to_name", 2, | 727 | "zone_to_name", 2, |
584 | paramValues, paramLengths, paramFormats, 1); | 728 | paramValues, paramLengths, paramFormats, |
585 | return get_record_and_call_iterator (plugin, "zone_to_name", res, iter, iter_cls); | 729 | 1); |
586 | #endif | 730 | return get_record_and_call_iterator (plugin, |
587 | GNUNET_break (0); | 731 | res, |
588 | return GNUNET_SYSERR; | 732 | zone, |
589 | } | 733 | iter, iter_cls); |
590 | |||
591 | #if 0 | ||
592 | /** | ||
593 | * Delete an entire zone (all records). Not used in normal operation. | ||
594 | * | ||
595 | * @param cls closure (internal context for the plugin) | ||
596 | * @param zone zone to delete | ||
597 | */ | ||
598 | static void | ||
599 | namestore_postgres_delete_zone (void *cls, | ||
600 | const struct GNUNET_CRYPTO_ShortHashCode *zone) | ||
601 | { | ||
602 | struct Plugin *plugin = cls; | ||
603 | PGresult *ret; | ||
604 | const char *paramValues[] = { | ||
605 | (const char *) zone, | ||
606 | }; | ||
607 | |||
608 | int paramLengths[] = { | ||
609 | sizeof (struct GNUNET_CRYPTO_ShortHashCode) | ||
610 | }; | ||
611 | const int paramFormats[] = { 1 }; | ||
612 | |||
613 | ret = | ||
614 | PQexecPrepared (plugin->dbh, "delete_zone", 1, paramValues, paramLengths, | ||
615 | paramFormats, 1); | ||
616 | if (GNUNET_OK != | ||
617 | GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "delete_zone")) | ||
618 | { | ||
619 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
620 | "Deleting zone failed!\n"); | ||
621 | return; | ||
622 | } | ||
623 | PQclear (ret); | ||
624 | } | ||
625 | #endif | ||
626 | |||
627 | /** | ||
628 | * Cache a block in the datastore. | ||
629 | * | ||
630 | * @param cls closure (internal context for the plugin) | ||
631 | * @param block block to cache | ||
632 | * @return GNUNET_OK on success, else GNUNET_SYSERR | ||
633 | */ | ||
634 | static int | ||
635 | namestore_postgres_cache_block (void *cls, | ||
636 | const struct GNUNET_NAMESTORE_Block *block) | ||
637 | { | ||
638 | // struct Plugin *plugin = cls; | ||
639 | GNUNET_break (0); | ||
640 | /* To be implemented */ | ||
641 | return GNUNET_OK; | ||
642 | } | ||
643 | |||
644 | /** | ||
645 | * Get the block for a particular zone and label in the | ||
646 | * datastore. Will return at most one result to the iterator. | ||
647 | * | ||
648 | * @param cls closure (internal context for the plugin) | ||
649 | * @param query hash of public key derived from the zone and the label | ||
650 | * @param iter function to call with the result | ||
651 | * @param iter_cls closure for iter | ||
652 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
653 | */ | ||
654 | static int | ||
655 | namestore_postgres_lookup_block (void *cls, | ||
656 | const struct GNUNET_HashCode *query, | ||
657 | GNUNET_NAMESTORE_BlockCallback iter, void *iter_cls) | ||
658 | { | ||
659 | // struct Plugin *plugin = cls; | ||
660 | GNUNET_break (0); | ||
661 | /* To be implemented */ | ||
662 | return GNUNET_OK; | ||
663 | } | ||
664 | |||
665 | /** | ||
666 | * Store a record in the datastore. Removes any existing record in the | ||
667 | * same zone with the same name. | ||
668 | * | ||
669 | * @param cls closure (internal context for the plugin) | ||
670 | * @param zone_key private key of the zone | ||
671 | * @param label name that is being mapped (at most 255 characters long) | ||
672 | * @param rd_count number of entries in 'rd' array | ||
673 | * @param rd array of records with data to store | ||
674 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
675 | */ | ||
676 | static int | ||
677 | namestore_postgres_store_records (void *cls, | ||
678 | const struct GNUNET_CRYPTO_EccPrivateKey *zone_key, | ||
679 | const char *label, | ||
680 | unsigned int rd_count, | ||
681 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
682 | { | ||
683 | // struct Plugin *plugin = cls; | ||
684 | GNUNET_break (0); | ||
685 | /* To be implemented */ | ||
686 | return GNUNET_OK; | ||
687 | } | 734 | } |
688 | 735 | ||
689 | 736 | ||
@@ -723,16 +770,13 @@ libgnunet_plugin_namestore_postgres_init (void *cls) | |||
723 | database_shutdown (&plugin); | 770 | database_shutdown (&plugin); |
724 | return NULL; | 771 | return NULL; |
725 | } | 772 | } |
726 | api = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_PluginFunctions)); | 773 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); |
727 | api->cls = &plugin; | 774 | api->cls = &plugin; |
728 | /* api->put_records = &namestore_postgres_put_records; */ | ||
729 | /* api->remove_records = &namestore_postgres_remove_records; */ | ||
730 | api->cache_block = &namestore_postgres_cache_block; | 775 | api->cache_block = &namestore_postgres_cache_block; |
731 | api->lookup_block = &namestore_postgres_lookup_block; | 776 | api->lookup_block = &namestore_postgres_lookup_block; |
732 | api->store_records = &namestore_postgres_store_records; | 777 | api->store_records = &namestore_postgres_store_records; |
733 | api->iterate_records = &namestore_postgres_iterate_records; | 778 | api->iterate_records = &namestore_postgres_iterate_records; |
734 | api->zone_to_name = &namestore_postgres_zone_to_name; | 779 | api->zone_to_name = &namestore_postgres_zone_to_name; |
735 | /* api->delete_zone = &namestore_postgres_delete_zone; */ | ||
736 | LOG (GNUNET_ERROR_TYPE_INFO, | 780 | LOG (GNUNET_ERROR_TYPE_INFO, |
737 | _("Postgres database running\n")); | 781 | _("Postgres database running\n")); |
738 | return api; | 782 | return api; |