diff options
Diffstat (limited to 'src/namestore/plugin_namestore_postgres.c')
-rw-r--r-- | src/namestore/plugin_namestore_postgres.c | 674 |
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 | */ |
40 | struct Plugin | 40 | struct 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 | */ |
64 | static int | 61 | static int |
65 | database_setup (struct Plugin *plugin) | 62 | database_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 | */ |
212 | static int | 209 | static int |
213 | namestore_postgres_store_records (void *cls, | 210 | namestore_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 | */ |
314 | struct ParserContext | 311 | struct 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 | */ |
347 | static void | 343 | static void |
348 | parse_result_call_iterator (void *cls, | 344 | parse_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 | */ |
437 | static int | 433 | static int |
438 | namestore_postgres_lookup_records (void *cls, | 434 | namestore_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 | */ |
486 | static int | 482 | static int |
487 | namestore_postgres_iterate_records (void *cls, | 483 | namestore_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 | */ |
552 | static int | 548 | static int |
553 | namestore_postgres_zone_to_name (void *cls, | 549 | namestore_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 | */ |
587 | static void | 583 | static void |
588 | database_shutdown (struct Plugin *plugin) | 584 | database_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 | */ |
601 | void * | 597 | void * |
602 | libgnunet_plugin_namestore_postgres_init (void *cls) | 598 | libgnunet_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 | */ |
635 | void * | 631 | void * |
636 | libgnunet_plugin_namestore_postgres_done (void *cls) | 632 | libgnunet_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 | ||