aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/plugin_namestore_postgres.c')
-rw-r--r--src/namestore/plugin_namestore_postgres.c674
1 files changed, 335 insertions, 339 deletions
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
index f2e065882..ac35b01b4 100644
--- a/src/namestore/plugin_namestore_postgres.c
+++ b/src/namestore/plugin_namestore_postgres.c
@@ -1,22 +1,22 @@
1 /* 1/*
2 * This file is part of GNUnet 2 * This file is part of GNUnet
3 * Copyright (C) 2009-2013, 2016-2018 GNUnet e.V. 3 * Copyright (C) 2009-2013, 2016-2018 GNUnet e.V.
4 * 4 *
5 * GNUnet is free software: you can redistribute it and/or modify it 5 * GNUnet is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Affero General Public License as published 6 * under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, 7 * by the Free Software Foundation, either version 3 of the License,
8 * or (at your option) any later version. 8 * or (at your option) any later version.
9 * 9 *
10 * GNUnet is distributed in the hope that it will be useful, but 10 * GNUnet is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Affero General Public License for more details. 13 * Affero General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU Affero General Public License 15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19 */ 19 */
20 20
21/** 21/**
22 * @file namestore/plugin_namestore_postgres.c 22 * @file namestore/plugin_namestore_postgres.c
@@ -31,15 +31,13 @@
31#include "namestore.h" 31#include "namestore.h"
32 32
33 33
34#define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__) 34#define LOG(kind, ...) GNUNET_log_from(kind, "namestore-postgres", __VA_ARGS__)
35 35
36 36
37/** 37/**
38 * Context for all functions in this plugin. 38 * Context for all functions in this plugin.
39 */ 39 */
40struct Plugin 40struct Plugin {
41{
42
43 /** 41 /**
44 * Our configuration. 42 * Our configuration.
45 */ 43 */
@@ -49,7 +47,6 @@ struct Plugin
49 * Native Postgres database handle. 47 * Native Postgres database handle.
50 */ 48 */
51 PGconn *dbh; 49 PGconn *dbh;
52
53}; 50};
54 51
55 52
@@ -62,136 +59,136 @@ struct Plugin
62 * @return #GNUNET_OK on success 59 * @return #GNUNET_OK on success
63 */ 60 */
64static int 61static int
65database_setup (struct Plugin *plugin) 62database_setup(struct Plugin *plugin)
66{ 63{
67 struct GNUNET_PQ_ExecuteStatement es_temporary = 64 struct GNUNET_PQ_ExecuteStatement es_temporary =
68 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns098records (" 65 GNUNET_PQ_make_execute("CREATE TEMPORARY TABLE IF NOT EXISTS ns098records ("
69 " seq BIGSERIAL PRIMARY KEY," 66 " seq BIGSERIAL PRIMARY KEY,"
70 " zone_private_key BYTEA NOT NULL DEFAULT ''," 67 " zone_private_key BYTEA NOT NULL DEFAULT '',"
71 " pkey BYTEA DEFAULT ''," 68 " pkey BYTEA DEFAULT '',"
72 " rvalue BYTEA NOT NULL DEFAULT ''," 69 " rvalue BYTEA NOT NULL DEFAULT '',"
73 " record_count INTEGER NOT NULL DEFAULT 0," 70 " record_count INTEGER NOT NULL DEFAULT 0,"
74 " record_data BYTEA NOT NULL DEFAULT ''," 71 " record_data BYTEA NOT NULL DEFAULT '',"
75 " label TEXT NOT NULL DEFAULT ''," 72 " label TEXT NOT NULL DEFAULT '',"
76 " CONSTRAINT zl UNIQUE (zone_private_key,label)" 73 " CONSTRAINT zl UNIQUE (zone_private_key,label)"
77 ")" 74 ")"
78 "WITH OIDS"); 75 "WITH OIDS");
79 struct GNUNET_PQ_ExecuteStatement es_default = 76 struct GNUNET_PQ_ExecuteStatement es_default =
80 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records (" 77 GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS ns098records ("
81 " seq BIGSERIAL PRIMARY KEY," 78 " seq BIGSERIAL PRIMARY KEY,"
82 " zone_private_key BYTEA NOT NULL DEFAULT ''," 79 " zone_private_key BYTEA NOT NULL DEFAULT '',"
83 " pkey BYTEA DEFAULT ''," 80 " pkey BYTEA DEFAULT '',"
84 " rvalue BYTEA NOT NULL DEFAULT ''," 81 " rvalue BYTEA NOT NULL DEFAULT '',"
85 " record_count INTEGER NOT NULL DEFAULT 0," 82 " record_count INTEGER NOT NULL DEFAULT 0,"
86 " record_data BYTEA NOT NULL DEFAULT ''," 83 " record_data BYTEA NOT NULL DEFAULT '',"
87 " label TEXT NOT NULL DEFAULT ''," 84 " label TEXT NOT NULL DEFAULT '',"
88 " CONSTRAINT zl UNIQUE (zone_private_key,label)" 85 " CONSTRAINT zl UNIQUE (zone_private_key,label)"
89 ")" 86 ")"
90 "WITH OIDS"); 87 "WITH OIDS");
91 const struct GNUNET_PQ_ExecuteStatement *cr; 88 const struct GNUNET_PQ_ExecuteStatement *cr;
92 89
93 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, 90 plugin->dbh = GNUNET_PQ_connect_with_cfg(plugin->cfg,
94 "namestore-postgres"); 91 "namestore-postgres");
95 if (NULL == plugin->dbh) 92 if (NULL == plugin->dbh)
96 return GNUNET_SYSERR; 93 return GNUNET_SYSERR;
97 if (GNUNET_YES == 94 if (GNUNET_YES ==
98 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, 95 GNUNET_CONFIGURATION_get_value_yesno(plugin->cfg,
99 "namestore-postgres", 96 "namestore-postgres",
100 "ASYNC_COMMIT")) 97 "ASYNC_COMMIT"))
101 {
102 struct GNUNET_PQ_ExecuteStatement es[] = {
103 GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off"),
104 GNUNET_PQ_EXECUTE_STATEMENT_END
105 };
106
107 if (GNUNET_OK !=
108 GNUNET_PQ_exec_statements (plugin->dbh,
109 es))
110 { 98 {
111 PQfinish (plugin->dbh); 99 struct GNUNET_PQ_ExecuteStatement es[] = {
112 plugin->dbh = NULL; 100 GNUNET_PQ_make_try_execute("SET synchronous_commit TO off"),
113 return GNUNET_SYSERR; 101 GNUNET_PQ_EXECUTE_STATEMENT_END
102 };
103
104 if (GNUNET_OK !=
105 GNUNET_PQ_exec_statements(plugin->dbh,
106 es))
107 {
108 PQfinish(plugin->dbh);
109 plugin->dbh = NULL;
110 return GNUNET_SYSERR;
111 }
114 } 112 }
115 }
116 if (GNUNET_YES == 113 if (GNUNET_YES ==
117 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, 114 GNUNET_CONFIGURATION_get_value_yesno(plugin->cfg,
118 "namestore-postgres", 115 "namestore-postgres",
119 "TEMPORARY_TABLE")) 116 "TEMPORARY_TABLE"))
120 { 117 {
121 cr = &es_temporary; 118 cr = &es_temporary;
122 } 119 }
123 else 120 else
124 { 121 {
125 cr = &es_default; 122 cr = &es_default;
126 } 123 }
127 124
128 { 125 {
129 struct GNUNET_PQ_ExecuteStatement es[] = { 126 struct GNUNET_PQ_ExecuteStatement es[] = {
130 *cr, 127 *cr,
131 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse " 128 GNUNET_PQ_make_try_execute("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
132 "ON ns098records (zone_private_key,pkey)"), 129 "ON ns098records (zone_private_key,pkey)"),
133 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter " 130 GNUNET_PQ_make_try_execute("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
134 "ON ns098records (zone_private_key,seq)"), 131 "ON ns098records (zone_private_key,seq)"),
135 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label " 132 GNUNET_PQ_make_try_execute("CREATE INDEX IF NOT EXISTS ir_label "
136 "ON ns098records (label)"), 133 "ON ns098records (label)"),
137 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label " 134 GNUNET_PQ_make_try_execute("CREATE INDEX IF NOT EXISTS zone_label "
138 "ON ns098records (zone_private_key,label)"), 135 "ON ns098records (zone_private_key,label)"),
139 GNUNET_PQ_EXECUTE_STATEMENT_END 136 GNUNET_PQ_EXECUTE_STATEMENT_END
140 }; 137 };
141 138
142 if (GNUNET_OK != 139 if (GNUNET_OK !=
143 GNUNET_PQ_exec_statements (plugin->dbh, 140 GNUNET_PQ_exec_statements(plugin->dbh,
144 es)) 141 es))
145 { 142 {
146 PQfinish (plugin->dbh); 143 PQfinish(plugin->dbh);
147 plugin->dbh = NULL; 144 plugin->dbh = NULL;
148 return GNUNET_SYSERR; 145 return GNUNET_SYSERR;
149 } 146 }
150 } 147 }
151 148
152 { 149 {
153 struct GNUNET_PQ_PreparedStatement ps[] = { 150 struct GNUNET_PQ_PreparedStatement ps[] = {
154 GNUNET_PQ_make_prepare ("store_records", 151 GNUNET_PQ_make_prepare("store_records",
155 "INSERT INTO ns098records" 152 "INSERT INTO ns098records"
156 " (zone_private_key, pkey, rvalue, record_count, record_data, label)" 153 " (zone_private_key, pkey, rvalue, record_count, record_data, label)"
157 " VALUES ($1, $2, $3, $4, $5, $6)" 154 " VALUES ($1, $2, $3, $4, $5, $6)"
158 " ON CONFLICT ON CONSTRAINT zl" 155 " ON CONFLICT ON CONSTRAINT zl"
159 " DO UPDATE" 156 " DO UPDATE"
160 " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5" 157 " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
161 " WHERE ns098records.zone_private_key = $1" 158 " WHERE ns098records.zone_private_key = $1"
162 " AND ns098records.label = $6", 159 " AND ns098records.label = $6",
163 6), 160 6),
164 GNUNET_PQ_make_prepare ("delete_records", 161 GNUNET_PQ_make_prepare("delete_records",
165 "DELETE FROM ns098records " 162 "DELETE FROM ns098records "
166 "WHERE zone_private_key=$1 AND label=$2", 163 "WHERE zone_private_key=$1 AND label=$2",
167 2), 164 2),
168 GNUNET_PQ_make_prepare ("zone_to_name", 165 GNUNET_PQ_make_prepare("zone_to_name",
169 "SELECT seq,record_count,record_data,label FROM ns098records" 166 "SELECT seq,record_count,record_data,label FROM ns098records"
170 " WHERE zone_private_key=$1 AND pkey=$2", 167 " WHERE zone_private_key=$1 AND pkey=$2",
171 2), 168 2),
172 GNUNET_PQ_make_prepare ("iterate_zone", 169 GNUNET_PQ_make_prepare("iterate_zone",
173 "SELECT seq,record_count,record_data,label FROM ns098records " 170 "SELECT seq,record_count,record_data,label FROM ns098records "
174 "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3", 171 "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3",
175 3), 172 3),
176 GNUNET_PQ_make_prepare ("iterate_all_zones", 173 GNUNET_PQ_make_prepare("iterate_all_zones",
177 "SELECT seq,record_count,record_data,label,zone_private_key" 174 "SELECT seq,record_count,record_data,label,zone_private_key"
178 " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2", 175 " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2",
179 2), 176 2),
180 GNUNET_PQ_make_prepare ("lookup_label", 177 GNUNET_PQ_make_prepare("lookup_label",
181 "SELECT seq,record_count,record_data,label " 178 "SELECT seq,record_count,record_data,label "
182 "FROM ns098records WHERE zone_private_key=$1 AND label=$2", 179 "FROM ns098records WHERE zone_private_key=$1 AND label=$2",
183 2), 180 2),
184 GNUNET_PQ_PREPARED_STATEMENT_END 181 GNUNET_PQ_PREPARED_STATEMENT_END
185 }; 182 };
186 183
187 if (GNUNET_OK != 184 if (GNUNET_OK !=
188 GNUNET_PQ_prepare_statements (plugin->dbh, 185 GNUNET_PQ_prepare_statements(plugin->dbh,
189 ps)) 186 ps))
190 { 187 {
191 PQfinish (plugin->dbh); 188 PQfinish(plugin->dbh);
192 plugin->dbh = NULL; 189 plugin->dbh = NULL;
193 return GNUNET_SYSERR; 190 return GNUNET_SYSERR;
194 } 191 }
195 } 192 }
196 193
197 return GNUNET_OK; 194 return GNUNET_OK;
@@ -210,97 +207,97 @@ database_setup (struct Plugin *plugin)
210 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 207 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
211 */ 208 */
212static int 209static int
213namestore_postgres_store_records (void *cls, 210namestore_postgres_store_records(void *cls,
214 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, 211 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
215 const char *label, 212 const char *label,
216 unsigned int rd_count, 213 unsigned int rd_count,
217 const struct GNUNET_GNSRECORD_Data *rd) 214 const struct GNUNET_GNSRECORD_Data *rd)
218{ 215{
219 struct Plugin *plugin = cls; 216 struct Plugin *plugin = cls;
220 struct GNUNET_CRYPTO_EcdsaPublicKey pkey; 217 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
221 uint64_t rvalue; 218 uint64_t rvalue;
222 uint32_t rd_count32 = (uint32_t) rd_count; 219 uint32_t rd_count32 = (uint32_t)rd_count;
223 ssize_t data_size; 220 ssize_t data_size;
224 221
225 memset (&pkey, 222 memset(&pkey,
226 0, 223 0,
227 sizeof (pkey)); 224 sizeof(pkey));
228 for (unsigned int i=0;i<rd_count;i++) 225 for (unsigned int i = 0; i < rd_count; i++)
229 if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type) 226 if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type)
227 {
228 GNUNET_break(sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size);
229 GNUNET_memcpy(&pkey,
230 rd[i].data,
231 rd[i].data_size);
232 break;
233 }
234 rvalue = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
235 UINT64_MAX);
236 data_size = GNUNET_GNSRECORD_records_get_size(rd_count,
237 rd);
238 if (data_size < 0)
230 { 239 {
231 GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size); 240 GNUNET_break(0);
232 GNUNET_memcpy (&pkey, 241 return GNUNET_SYSERR;
233 rd[i].data,
234 rd[i].data_size);
235 break;
236 } 242 }
237 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
238 UINT64_MAX);
239 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
240 rd);
241 if (data_size < 0)
242 {
243 GNUNET_break (0);
244 return GNUNET_SYSERR;
245 }
246 if (data_size >= UINT16_MAX) 243 if (data_size >= UINT16_MAX)
247 { 244 {
248 GNUNET_break (0); 245 GNUNET_break(0);
249 return GNUNET_SYSERR; 246 return GNUNET_SYSERR;
250 } 247 }
251 /* if record set is empty, delete existing records */ 248 /* if record set is empty, delete existing records */
252 if (0 == rd_count) 249 if (0 == rd_count)
253 {
254 struct GNUNET_PQ_QueryParam params[] = {
255 GNUNET_PQ_query_param_auto_from_type (zone_key),
256 GNUNET_PQ_query_param_string (label),
257 GNUNET_PQ_query_param_end
258 };
259 enum GNUNET_DB_QueryStatus res;
260
261 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
262 "delete_records",
263 params);
264 if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) &&
265 (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != res) )
266 { 250 {
267 GNUNET_break (0); 251 struct GNUNET_PQ_QueryParam params[] = {
268 return GNUNET_SYSERR; 252 GNUNET_PQ_query_param_auto_from_type(zone_key),
253 GNUNET_PQ_query_param_string(label),
254 GNUNET_PQ_query_param_end
255 };
256 enum GNUNET_DB_QueryStatus res;
257
258 res = GNUNET_PQ_eval_prepared_non_select(plugin->dbh,
259 "delete_records",
260 params);
261 if ((GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) &&
262 (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != res))
263 {
264 GNUNET_break(0);
265 return GNUNET_SYSERR;
266 }
267 GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG,
268 "postgres",
269 "Record deleted\n");
270 return GNUNET_OK;
269 } 271 }
270 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
271 "postgres",
272 "Record deleted\n");
273 return GNUNET_OK;
274 }
275 /* otherwise, UPSERT (i.e. UPDATE if exists, otherwise INSERT) */ 272 /* otherwise, UPSERT (i.e. UPDATE if exists, otherwise INSERT) */
276 { 273 {
277 char data[data_size]; 274 char data[data_size];
278 struct GNUNET_PQ_QueryParam params[] = { 275 struct GNUNET_PQ_QueryParam params[] = {
279 GNUNET_PQ_query_param_auto_from_type (zone_key), 276 GNUNET_PQ_query_param_auto_from_type(zone_key),
280 GNUNET_PQ_query_param_auto_from_type (&pkey), 277 GNUNET_PQ_query_param_auto_from_type(&pkey),
281 GNUNET_PQ_query_param_uint64 (&rvalue), 278 GNUNET_PQ_query_param_uint64(&rvalue),
282 GNUNET_PQ_query_param_uint32 (&rd_count32), 279 GNUNET_PQ_query_param_uint32(&rd_count32),
283 GNUNET_PQ_query_param_fixed_size (data, data_size), 280 GNUNET_PQ_query_param_fixed_size(data, data_size),
284 GNUNET_PQ_query_param_string (label), 281 GNUNET_PQ_query_param_string(label),
285 GNUNET_PQ_query_param_end 282 GNUNET_PQ_query_param_end
286 }; 283 };
287 enum GNUNET_DB_QueryStatus res; 284 enum GNUNET_DB_QueryStatus res;
288 ssize_t ret; 285 ssize_t ret;
289 286
290 ret = GNUNET_GNSRECORD_records_serialize (rd_count, 287 ret = GNUNET_GNSRECORD_records_serialize(rd_count,
291 rd, 288 rd,
292 data_size, 289 data_size,
293 data); 290 data);
294 if ( (ret < 0) || 291 if ((ret < 0) ||
295 (data_size != ret) ) 292 (data_size != ret))
296 { 293 {
297 GNUNET_break (0); 294 GNUNET_break(0);
298 return GNUNET_SYSERR; 295 return GNUNET_SYSERR;
299 } 296 }
300 297
301 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, 298 res = GNUNET_PQ_eval_prepared_non_select(plugin->dbh,
302 "store_records", 299 "store_records",
303 params); 300 params);
304 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) 301 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res)
305 return GNUNET_SYSERR; 302 return GNUNET_SYSERR;
306 } 303 }
@@ -311,8 +308,7 @@ namestore_postgres_store_records (void *cls,
311/** 308/**
312 * Closure for #parse_result_call_iterator. 309 * Closure for #parse_result_call_iterator.
313 */ 310 */
314struct ParserContext 311struct ParserContext {
315{
316 /** 312 /**
317 * Function to call for each result. 313 * Function to call for each result.
318 */ 314 */
@@ -345,81 +341,81 @@ struct ParserContext
345 * @param num_result the number of results in @a result 341 * @param num_result the number of results in @a result
346 */ 342 */
347static void 343static void
348parse_result_call_iterator (void *cls, 344parse_result_call_iterator(void *cls,
349 PGresult *res, 345 PGresult *res,
350 unsigned int num_results) 346 unsigned int num_results)
351{ 347{
352 struct ParserContext *pc = cls; 348 struct ParserContext *pc = cls;
353 349
354 if (NULL == pc->iter) 350 if (NULL == pc->iter)
355 return; /* no need to do more work */ 351 return; /* no need to do more work */
356 for (unsigned int i=0;i<num_results;i++) 352 for (unsigned int i = 0; i < num_results; i++)
357 {
358 uint64_t serial;
359 void *data;
360 size_t data_size;
361 uint32_t record_count;
362 char *label;
363 struct GNUNET_CRYPTO_EcdsaPrivateKey zk;
364 struct GNUNET_PQ_ResultSpec rs_with_zone[] = {
365 GNUNET_PQ_result_spec_uint64 ("seq", &serial),
366 GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
367 GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
368 GNUNET_PQ_result_spec_string ("label", &label),
369 GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk),
370 GNUNET_PQ_result_spec_end
371 };
372 struct GNUNET_PQ_ResultSpec rs_without_zone[] = {
373 GNUNET_PQ_result_spec_uint64 ("seq", &serial),
374 GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
375 GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
376 GNUNET_PQ_result_spec_string ("label", &label),
377 GNUNET_PQ_result_spec_end
378 };
379 struct GNUNET_PQ_ResultSpec *rs;
380
381 rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone;
382 if (GNUNET_YES !=
383 GNUNET_PQ_extract_result (res,
384 rs,
385 i))
386 {
387 GNUNET_break (0);
388 return;
389 }
390
391 if (record_count > 64 * 1024)
392 {
393 /* sanity check, don't stack allocate far too much just
394 because database might contain a large value here */
395 GNUNET_break (0);
396 GNUNET_PQ_cleanup_result (rs);
397 return;
398 }
399
400 { 353 {
401 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(record_count)]; 354 uint64_t serial;
355 void *data;
356 size_t data_size;
357 uint32_t record_count;
358 char *label;
359 struct GNUNET_CRYPTO_EcdsaPrivateKey zk;
360 struct GNUNET_PQ_ResultSpec rs_with_zone[] = {
361 GNUNET_PQ_result_spec_uint64("seq", &serial),
362 GNUNET_PQ_result_spec_uint32("record_count", &record_count),
363 GNUNET_PQ_result_spec_variable_size("record_data", &data, &data_size),
364 GNUNET_PQ_result_spec_string("label", &label),
365 GNUNET_PQ_result_spec_auto_from_type("zone_private_key", &zk),
366 GNUNET_PQ_result_spec_end
367 };
368 struct GNUNET_PQ_ResultSpec rs_without_zone[] = {
369 GNUNET_PQ_result_spec_uint64("seq", &serial),
370 GNUNET_PQ_result_spec_uint32("record_count", &record_count),
371 GNUNET_PQ_result_spec_variable_size("record_data", &data, &data_size),
372 GNUNET_PQ_result_spec_string("label", &label),
373 GNUNET_PQ_result_spec_end
374 };
375 struct GNUNET_PQ_ResultSpec *rs;
376
377 rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone;
378 if (GNUNET_YES !=
379 GNUNET_PQ_extract_result(res,
380 rs,
381 i))
382 {
383 GNUNET_break(0);
384 return;
385 }
386
387 if (record_count > 64 * 1024)
388 {
389 /* sanity check, don't stack allocate far too much just
390 because database might contain a large value here */
391 GNUNET_break(0);
392 GNUNET_PQ_cleanup_result(rs);
393 return;
394 }
402 395
403 GNUNET_assert (0 != serial);
404 if (GNUNET_OK !=
405 GNUNET_GNSRECORD_records_deserialize (data_size,
406 data,
407 record_count,
408 rd))
409 { 396 {
410 GNUNET_break (0); 397 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL(record_count)];
411 GNUNET_PQ_cleanup_result (rs); 398
412 return; 399 GNUNET_assert(0 != serial);
400 if (GNUNET_OK !=
401 GNUNET_GNSRECORD_records_deserialize(data_size,
402 data,
403 record_count,
404 rd))
405 {
406 GNUNET_break(0);
407 GNUNET_PQ_cleanup_result(rs);
408 return;
409 }
410 pc->iter(pc->iter_cls,
411 serial,
412 (NULL == pc->zone_key) ? &zk : pc->zone_key,
413 label,
414 record_count,
415 rd);
413 } 416 }
414 pc->iter (pc->iter_cls, 417 GNUNET_PQ_cleanup_result(rs);
415 serial,
416 (NULL == pc->zone_key) ? &zk : pc->zone_key,
417 label,
418 record_count,
419 rd);
420 } 418 }
421 GNUNET_PQ_cleanup_result (rs);
422 }
423 pc->limit -= num_results; 419 pc->limit -= num_results;
424} 420}
425 421
@@ -435,34 +431,34 @@ parse_result_call_iterator (void *cls,
435 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR 431 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
436 */ 432 */
437static int 433static int
438namestore_postgres_lookup_records (void *cls, 434namestore_postgres_lookup_records(void *cls,
439 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 435 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
440 const char *label, 436 const char *label,
441 GNUNET_NAMESTORE_RecordIterator iter, 437 GNUNET_NAMESTORE_RecordIterator iter,
442 void *iter_cls) 438 void *iter_cls)
443{ 439{
444 struct Plugin *plugin = cls; 440 struct Plugin *plugin = cls;
445 struct GNUNET_PQ_QueryParam params[] = { 441 struct GNUNET_PQ_QueryParam params[] = {
446 GNUNET_PQ_query_param_auto_from_type (zone), 442 GNUNET_PQ_query_param_auto_from_type(zone),
447 GNUNET_PQ_query_param_string (label), 443 GNUNET_PQ_query_param_string(label),
448 GNUNET_PQ_query_param_end 444 GNUNET_PQ_query_param_end
449 }; 445 };
450 struct ParserContext pc; 446 struct ParserContext pc;
451 enum GNUNET_DB_QueryStatus res; 447 enum GNUNET_DB_QueryStatus res;
452 448
453 if (NULL == zone) 449 if (NULL == zone)
454 { 450 {
455 GNUNET_break (0); 451 GNUNET_break(0);
456 return GNUNET_SYSERR; 452 return GNUNET_SYSERR;
457 } 453 }
458 pc.iter = iter; 454 pc.iter = iter;
459 pc.iter_cls = iter_cls; 455 pc.iter_cls = iter_cls;
460 pc.zone_key = zone; 456 pc.zone_key = zone;
461 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, 457 res = GNUNET_PQ_eval_prepared_multi_select(plugin->dbh,
462 "lookup_label", 458 "lookup_label",
463 params, 459 params,
464 &parse_result_call_iterator, 460 &parse_result_call_iterator,
465 &pc); 461 &pc);
466 if (res < 0) 462 if (res < 0)
467 return GNUNET_SYSERR; 463 return GNUNET_SYSERR;
468 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) 464 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
@@ -484,12 +480,12 @@ namestore_postgres_lookup_records (void *cls,
484 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error 480 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
485 */ 481 */
486static int 482static int
487namestore_postgres_iterate_records (void *cls, 483namestore_postgres_iterate_records(void *cls,
488 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 484 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
489 uint64_t serial, 485 uint64_t serial,
490 uint64_t limit, 486 uint64_t limit,
491 GNUNET_NAMESTORE_RecordIterator iter, 487 GNUNET_NAMESTORE_RecordIterator iter,
492 void *iter_cls) 488 void *iter_cls)
493{ 489{
494 struct Plugin *plugin = cls; 490 struct Plugin *plugin = cls;
495 enum GNUNET_DB_QueryStatus res; 491 enum GNUNET_DB_QueryStatus res;
@@ -500,39 +496,39 @@ namestore_postgres_iterate_records (void *cls,
500 pc.zone_key = zone; 496 pc.zone_key = zone;
501 pc.limit = limit; 497 pc.limit = limit;
502 if (NULL == zone) 498 if (NULL == zone)
503 { 499 {
504 struct GNUNET_PQ_QueryParam params_without_zone[] = { 500 struct GNUNET_PQ_QueryParam params_without_zone[] = {
505 GNUNET_PQ_query_param_uint64 (&serial), 501 GNUNET_PQ_query_param_uint64(&serial),
506 GNUNET_PQ_query_param_uint64 (&limit), 502 GNUNET_PQ_query_param_uint64(&limit),
507 GNUNET_PQ_query_param_end 503 GNUNET_PQ_query_param_end
508 }; 504 };
509 505
510 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, 506 res = GNUNET_PQ_eval_prepared_multi_select(plugin->dbh,
511 "iterate_all_zones", 507 "iterate_all_zones",
512 params_without_zone, 508 params_without_zone,
513 &parse_result_call_iterator, 509 &parse_result_call_iterator,
514 &pc); 510 &pc);
515 } 511 }
516 else 512 else
517 { 513 {
518 struct GNUNET_PQ_QueryParam params_with_zone[] = { 514 struct GNUNET_PQ_QueryParam params_with_zone[] = {
519 GNUNET_PQ_query_param_auto_from_type (zone), 515 GNUNET_PQ_query_param_auto_from_type(zone),
520 GNUNET_PQ_query_param_uint64 (&serial), 516 GNUNET_PQ_query_param_uint64(&serial),
521 GNUNET_PQ_query_param_uint64 (&limit), 517 GNUNET_PQ_query_param_uint64(&limit),
522 GNUNET_PQ_query_param_end 518 GNUNET_PQ_query_param_end
523 }; 519 };
524 520
525 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, 521 res = GNUNET_PQ_eval_prepared_multi_select(plugin->dbh,
526 "iterate_zone", 522 "iterate_zone",
527 params_with_zone, 523 params_with_zone,
528 &parse_result_call_iterator, 524 &parse_result_call_iterator,
529 &pc); 525 &pc);
530 } 526 }
531 if (res < 0) 527 if (res < 0)
532 return GNUNET_SYSERR; 528 return GNUNET_SYSERR;
533 529
534 if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) || 530 if ((GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) ||
535 (pc.limit > 0) ) 531 (pc.limit > 0))
536 return GNUNET_NO; 532 return GNUNET_NO;
537 return GNUNET_OK; 533 return GNUNET_OK;
538} 534}
@@ -550,15 +546,15 @@ namestore_postgres_iterate_records (void *cls,
550 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error 546 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
551 */ 547 */
552static int 548static int
553namestore_postgres_zone_to_name (void *cls, 549namestore_postgres_zone_to_name(void *cls,
554 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 550 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
555 const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, 551 const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
556 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) 552 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
557{ 553{
558 struct Plugin *plugin = cls; 554 struct Plugin *plugin = cls;
559 struct GNUNET_PQ_QueryParam params[] = { 555 struct GNUNET_PQ_QueryParam params[] = {
560 GNUNET_PQ_query_param_auto_from_type (zone), 556 GNUNET_PQ_query_param_auto_from_type(zone),
561 GNUNET_PQ_query_param_auto_from_type (value_zone), 557 GNUNET_PQ_query_param_auto_from_type(value_zone),
562 GNUNET_PQ_query_param_end 558 GNUNET_PQ_query_param_end
563 }; 559 };
564 enum GNUNET_DB_QueryStatus res; 560 enum GNUNET_DB_QueryStatus res;
@@ -567,11 +563,11 @@ namestore_postgres_zone_to_name (void *cls,
567 pc.iter = iter; 563 pc.iter = iter;
568 pc.iter_cls = iter_cls; 564 pc.iter_cls = iter_cls;
569 pc.zone_key = zone; 565 pc.zone_key = zone;
570 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh, 566 res = GNUNET_PQ_eval_prepared_multi_select(plugin->dbh,
571 "zone_to_name", 567 "zone_to_name",
572 params, 568 params,
573 &parse_result_call_iterator, 569 &parse_result_call_iterator,
574 &pc); 570 &pc);
575 if (res < 0) 571 if (res < 0)
576 return GNUNET_SYSERR; 572 return GNUNET_SYSERR;
577 return GNUNET_OK; 573 return GNUNET_OK;
@@ -585,9 +581,9 @@ namestore_postgres_zone_to_name (void *cls,
585 * @param plugin the plugin context (state for this module) 581 * @param plugin the plugin context (state for this module)
586 */ 582 */
587static void 583static void
588database_shutdown (struct Plugin *plugin) 584database_shutdown(struct Plugin *plugin)
589{ 585{
590 PQfinish (plugin->dbh); 586 PQfinish(plugin->dbh);
591 plugin->dbh = NULL; 587 plugin->dbh = NULL;
592} 588}
593 589
@@ -599,7 +595,7 @@ database_shutdown (struct Plugin *plugin)
599 * @return NULL on error, othrewise the plugin context 595 * @return NULL on error, othrewise the plugin context
600 */ 596 */
601void * 597void *
602libgnunet_plugin_namestore_postgres_init (void *cls) 598libgnunet_plugin_namestore_postgres_init(void *cls)
603{ 599{
604 static struct Plugin plugin; 600 static struct Plugin plugin;
605 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 601 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
@@ -607,21 +603,21 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
607 603
608 if (NULL != plugin.cfg) 604 if (NULL != plugin.cfg)
609 return NULL; /* can only initialize once! */ 605 return NULL; /* can only initialize once! */
610 memset (&plugin, 0, sizeof (struct Plugin)); 606 memset(&plugin, 0, sizeof(struct Plugin));
611 plugin.cfg = cfg; 607 plugin.cfg = cfg;
612 if (GNUNET_OK != database_setup (&plugin)) 608 if (GNUNET_OK != database_setup(&plugin))
613 { 609 {
614 database_shutdown (&plugin); 610 database_shutdown(&plugin);
615 return NULL; 611 return NULL;
616 } 612 }
617 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); 613 api = GNUNET_new(struct GNUNET_NAMESTORE_PluginFunctions);
618 api->cls = &plugin; 614 api->cls = &plugin;
619 api->store_records = &namestore_postgres_store_records; 615 api->store_records = &namestore_postgres_store_records;
620 api->iterate_records = &namestore_postgres_iterate_records; 616 api->iterate_records = &namestore_postgres_iterate_records;
621 api->zone_to_name = &namestore_postgres_zone_to_name; 617 api->zone_to_name = &namestore_postgres_zone_to_name;
622 api->lookup_records = &namestore_postgres_lookup_records; 618 api->lookup_records = &namestore_postgres_lookup_records;
623 LOG (GNUNET_ERROR_TYPE_INFO, 619 LOG(GNUNET_ERROR_TYPE_INFO,
624 "Postgres namestore plugin running\n"); 620 "Postgres namestore plugin running\n");
625 return api; 621 return api;
626} 622}
627 623
@@ -633,16 +629,16 @@ libgnunet_plugin_namestore_postgres_init (void *cls)
633 * @return always NULL 629 * @return always NULL
634 */ 630 */
635void * 631void *
636libgnunet_plugin_namestore_postgres_done (void *cls) 632libgnunet_plugin_namestore_postgres_done(void *cls)
637{ 633{
638 struct GNUNET_NAMESTORE_PluginFunctions *api = cls; 634 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
639 struct Plugin *plugin = api->cls; 635 struct Plugin *plugin = api->cls;
640 636
641 database_shutdown (plugin); 637 database_shutdown(plugin);
642 plugin->cfg = NULL; 638 plugin->cfg = NULL;
643 GNUNET_free (api); 639 GNUNET_free(api);
644 LOG (GNUNET_ERROR_TYPE_DEBUG, 640 LOG(GNUNET_ERROR_TYPE_DEBUG,
645 "Postgres namestore plugin is finished\n"); 641 "Postgres namestore plugin is finished\n");
646 return NULL; 642 return NULL;
647} 643}
648 644