aboutsummaryrefslogtreecommitdiff
path: root/src/namecache/plugin_namecache_postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namecache/plugin_namecache_postgres.c')
-rw-r--r--src/namecache/plugin_namecache_postgres.c329
1 files changed, 163 insertions, 166 deletions
diff --git a/src/namecache/plugin_namecache_postgres.c b/src/namecache/plugin_namecache_postgres.c
index 1d6d9f392..6d0e4e918 100644
--- a/src/namecache/plugin_namecache_postgres.c
+++ b/src/namecache/plugin_namecache_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, 2017 GNUnet e.V. 3 * Copyright (C) 2009-2013, 2016, 2017 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 namecache/plugin_namecache_postgres.c 22 * @file namecache/plugin_namecache_postgres.c
@@ -31,22 +31,19 @@
31#include "namecache.h" 31#include "namecache.h"
32 32
33 33
34#define LOG(kind,...) GNUNET_log_from (kind, "namecache-postgres", __VA_ARGS__) 34#define LOG(kind, ...) GNUNET_log_from(kind, "namecache-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 const struct GNUNET_CONFIGURATION_Handle *cfg; 41 const struct GNUNET_CONFIGURATION_Handle *cfg;
44 42
45 /** 43 /**
46 * Native Postgres database handle. 44 * Native Postgres database handle.
47 */ 45 */
48 PGconn *dbh; 46 PGconn *dbh;
49
50}; 47};
51 48
52 49
@@ -59,81 +56,81 @@ struct Plugin
59 * @return #GNUNET_OK on success 56 * @return #GNUNET_OK on success
60 */ 57 */
61static int 58static int
62database_setup (struct Plugin *plugin) 59database_setup(struct Plugin *plugin)
63{ 60{
64 struct GNUNET_PQ_ExecuteStatement es_temporary = 61 struct GNUNET_PQ_ExecuteStatement es_temporary =
65 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns096blocks (" 62 GNUNET_PQ_make_execute("CREATE TEMPORARY TABLE IF NOT EXISTS ns096blocks ("
66 " query BYTEA NOT NULL DEFAULT ''," 63 " query BYTEA NOT NULL DEFAULT '',"
67 " block BYTEA NOT NULL DEFAULT ''," 64 " block BYTEA NOT NULL DEFAULT '',"
68 " expiration_time BIGINT NOT NULL DEFAULT 0" 65 " expiration_time BIGINT NOT NULL DEFAULT 0"
69 ")" 66 ")"
70 "WITH OIDS"); 67 "WITH OIDS");
71 struct GNUNET_PQ_ExecuteStatement es_default = 68 struct GNUNET_PQ_ExecuteStatement es_default =
72 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns096blocks (" 69 GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS ns096blocks ("
73 " query BYTEA NOT NULL DEFAULT ''," 70 " query BYTEA NOT NULL DEFAULT '',"
74 " block BYTEA NOT NULL DEFAULT ''," 71 " block BYTEA NOT NULL DEFAULT '',"
75 " expiration_time BIGINT NOT NULL DEFAULT 0" 72 " expiration_time BIGINT NOT NULL DEFAULT 0"
76 ")" 73 ")"
77 "WITH OIDS"); 74 "WITH OIDS");
78 const struct GNUNET_PQ_ExecuteStatement *cr; 75 const struct GNUNET_PQ_ExecuteStatement *cr;
79 76
80 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg, 77 plugin->dbh = GNUNET_PQ_connect_with_cfg(plugin->cfg,
81 "namecache-postgres"); 78 "namecache-postgres");
82 if (NULL == plugin->dbh) 79 if (NULL == plugin->dbh)
83 return GNUNET_SYSERR; 80 return GNUNET_SYSERR;
84 if (GNUNET_YES == 81 if (GNUNET_YES ==
85 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, 82 GNUNET_CONFIGURATION_get_value_yesno(plugin->cfg,
86 "namecache-postgres", 83 "namecache-postgres",
87 "TEMPORARY_TABLE")) 84 "TEMPORARY_TABLE"))
88 { 85 {
89 cr = &es_temporary; 86 cr = &es_temporary;
90 } 87 }
91 else 88 else
92 { 89 {
93 cr = &es_default; 90 cr = &es_default;
94 } 91 }
95 92
96 { 93 {
97 struct GNUNET_PQ_ExecuteStatement es[] = { 94 struct GNUNET_PQ_ExecuteStatement es[] = {
98 *cr, 95 *cr,
99 GNUNET_PQ_make_try_execute ("CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)"), 96 GNUNET_PQ_make_try_execute("CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)"),
100 GNUNET_PQ_make_try_execute ("CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)"), 97 GNUNET_PQ_make_try_execute("CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)"),
101 GNUNET_PQ_EXECUTE_STATEMENT_END 98 GNUNET_PQ_EXECUTE_STATEMENT_END
102 }; 99 };
103 100
104 if (GNUNET_OK != 101 if (GNUNET_OK !=
105 GNUNET_PQ_exec_statements (plugin->dbh, 102 GNUNET_PQ_exec_statements(plugin->dbh,
106 es)) 103 es))
107 { 104 {
108 PQfinish (plugin->dbh); 105 PQfinish(plugin->dbh);
109 plugin->dbh = NULL; 106 plugin->dbh = NULL;
110 return GNUNET_SYSERR; 107 return GNUNET_SYSERR;
111 } 108 }
112 } 109 }
113 110
114 { 111 {
115 struct GNUNET_PQ_PreparedStatement ps[] = { 112 struct GNUNET_PQ_PreparedStatement ps[] = {
116 GNUNET_PQ_make_prepare ("cache_block", 113 GNUNET_PQ_make_prepare("cache_block",
117 "INSERT INTO ns096blocks (query, block, expiration_time) VALUES " 114 "INSERT INTO ns096blocks (query, block, expiration_time) VALUES "
118 "($1, $2, $3)", 3), 115 "($1, $2, $3)", 3),
119 GNUNET_PQ_make_prepare ("expire_blocks", 116 GNUNET_PQ_make_prepare("expire_blocks",
120 "DELETE FROM ns096blocks WHERE expiration_time<$1", 1), 117 "DELETE FROM ns096blocks WHERE expiration_time<$1", 1),
121 GNUNET_PQ_make_prepare ("delete_block", 118 GNUNET_PQ_make_prepare("delete_block",
122 "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2), 119 "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2),
123 GNUNET_PQ_make_prepare ("lookup_block", 120 GNUNET_PQ_make_prepare("lookup_block",
124 "SELECT block FROM ns096blocks WHERE query=$1" 121 "SELECT block FROM ns096blocks WHERE query=$1"
125 " ORDER BY expiration_time DESC LIMIT 1", 1), 122 " ORDER BY expiration_time DESC LIMIT 1", 1),
126 GNUNET_PQ_PREPARED_STATEMENT_END 123 GNUNET_PQ_PREPARED_STATEMENT_END
127 }; 124 };
128 125
129 if (GNUNET_OK != 126 if (GNUNET_OK !=
130 GNUNET_PQ_prepare_statements (plugin->dbh, 127 GNUNET_PQ_prepare_statements(plugin->dbh,
131 ps)) 128 ps))
132 { 129 {
133 PQfinish (plugin->dbh); 130 PQfinish(plugin->dbh);
134 plugin->dbh = NULL; 131 plugin->dbh = NULL;
135 return GNUNET_SYSERR; 132 return GNUNET_SYSERR;
136 } 133 }
137 } 134 }
138 135
139 return GNUNET_OK; 136 return GNUNET_OK;
@@ -146,19 +143,19 @@ database_setup (struct Plugin *plugin)
146 * @param plugin the plugin 143 * @param plugin the plugin
147 */ 144 */
148static void 145static void
149namecache_postgres_expire_blocks (struct Plugin *plugin) 146namecache_postgres_expire_blocks(struct Plugin *plugin)
150{ 147{
151 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 148 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
152 struct GNUNET_PQ_QueryParam params[] = { 149 struct GNUNET_PQ_QueryParam params[] = {
153 GNUNET_PQ_query_param_absolute_time (&now), 150 GNUNET_PQ_query_param_absolute_time(&now),
154 GNUNET_PQ_query_param_end 151 GNUNET_PQ_query_param_end
155 }; 152 };
156 enum GNUNET_DB_QueryStatus res; 153 enum GNUNET_DB_QueryStatus res;
157 154
158 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, 155 res = GNUNET_PQ_eval_prepared_non_select(plugin->dbh,
159 "expire_blocks", 156 "expire_blocks",
160 params); 157 params);
161 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res); 158 GNUNET_break(GNUNET_DB_STATUS_HARD_ERROR != res);
162} 159}
163 160
164 161
@@ -170,21 +167,21 @@ namecache_postgres_expire_blocks (struct Plugin *plugin)
170 * @param expiration_time how old does the block have to be for deletion 167 * @param expiration_time how old does the block have to be for deletion
171 */ 168 */
172static void 169static void
173delete_old_block (struct Plugin *plugin, 170delete_old_block(struct Plugin *plugin,
174 const struct GNUNET_HashCode *query, 171 const struct GNUNET_HashCode *query,
175 struct GNUNET_TIME_AbsoluteNBO expiration_time) 172 struct GNUNET_TIME_AbsoluteNBO expiration_time)
176{ 173{
177 struct GNUNET_PQ_QueryParam params[] = { 174 struct GNUNET_PQ_QueryParam params[] = {
178 GNUNET_PQ_query_param_auto_from_type (query), 175 GNUNET_PQ_query_param_auto_from_type(query),
179 GNUNET_PQ_query_param_absolute_time_nbo (&expiration_time), 176 GNUNET_PQ_query_param_absolute_time_nbo(&expiration_time),
180 GNUNET_PQ_query_param_end 177 GNUNET_PQ_query_param_end
181 }; 178 };
182 enum GNUNET_DB_QueryStatus res; 179 enum GNUNET_DB_QueryStatus res;
183 180
184 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, 181 res = GNUNET_PQ_eval_prepared_non_select(plugin->dbh,
185 "delete_block", 182 "delete_block",
186 params); 183 params);
187 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res); 184 GNUNET_break(GNUNET_DB_STATUS_HARD_ERROR != res);
188} 185}
189 186
190 187
@@ -196,38 +193,38 @@ delete_old_block (struct Plugin *plugin,
196 * @return #GNUNET_OK on success, else #GNUNET_SYSERR 193 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
197 */ 194 */
198static int 195static int
199namecache_postgres_cache_block (void *cls, 196namecache_postgres_cache_block(void *cls,
200 const struct GNUNET_GNSRECORD_Block *block) 197 const struct GNUNET_GNSRECORD_Block *block)
201{ 198{
202 struct Plugin *plugin = cls; 199 struct Plugin *plugin = cls;
203 struct GNUNET_HashCode query; 200 struct GNUNET_HashCode query;
204 size_t block_size = ntohl (block->purpose.size) + 201 size_t block_size = ntohl(block->purpose.size) +
205 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + 202 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) +
206 sizeof (struct GNUNET_CRYPTO_EcdsaSignature); 203 sizeof(struct GNUNET_CRYPTO_EcdsaSignature);
207 struct GNUNET_PQ_QueryParam params[] = { 204 struct GNUNET_PQ_QueryParam params[] = {
208 GNUNET_PQ_query_param_auto_from_type (&query), 205 GNUNET_PQ_query_param_auto_from_type(&query),
209 GNUNET_PQ_query_param_fixed_size (block, block_size), 206 GNUNET_PQ_query_param_fixed_size(block, block_size),
210 GNUNET_PQ_query_param_absolute_time_nbo (&block->expiration_time), 207 GNUNET_PQ_query_param_absolute_time_nbo(&block->expiration_time),
211 GNUNET_PQ_query_param_end 208 GNUNET_PQ_query_param_end
212 }; 209 };
213 enum GNUNET_DB_QueryStatus res; 210 enum GNUNET_DB_QueryStatus res;
214 211
215 namecache_postgres_expire_blocks (plugin); 212 namecache_postgres_expire_blocks(plugin);
216 GNUNET_CRYPTO_hash (&block->derived_key, 213 GNUNET_CRYPTO_hash(&block->derived_key,
217 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), 214 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
218 &query); 215 &query);
219 if (block_size > 64 * 65536) 216 if (block_size > 64 * 65536)
220 { 217 {
221 GNUNET_break (0); 218 GNUNET_break(0);
222 return GNUNET_SYSERR; 219 return GNUNET_SYSERR;
223 } 220 }
224 delete_old_block (plugin, 221 delete_old_block(plugin,
225 &query, 222 &query,
226 block->expiration_time); 223 block->expiration_time);
227 224
228 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh, 225 res = GNUNET_PQ_eval_prepared_non_select(plugin->dbh,
229 "cache_block", 226 "cache_block",
230 params); 227 params);
231 if (0 > res) 228 if (0 > res)
232 return GNUNET_SYSERR; 229 return GNUNET_SYSERR;
233 return GNUNET_OK; 230 return GNUNET_OK;
@@ -245,57 +242,57 @@ namecache_postgres_cache_block (void *cls,
245 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error 242 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
246 */ 243 */
247static int 244static int
248namecache_postgres_lookup_block (void *cls, 245namecache_postgres_lookup_block(void *cls,
249 const struct GNUNET_HashCode *query, 246 const struct GNUNET_HashCode *query,
250 GNUNET_NAMECACHE_BlockCallback iter, 247 GNUNET_NAMECACHE_BlockCallback iter,
251 void *iter_cls) 248 void *iter_cls)
252{ 249{
253 struct Plugin *plugin = cls; 250 struct Plugin *plugin = cls;
254 size_t bsize; 251 size_t bsize;
255 struct GNUNET_GNSRECORD_Block *block; 252 struct GNUNET_GNSRECORD_Block *block;
256 struct GNUNET_PQ_QueryParam params[] = { 253 struct GNUNET_PQ_QueryParam params[] = {
257 GNUNET_PQ_query_param_auto_from_type (query), 254 GNUNET_PQ_query_param_auto_from_type(query),
258 GNUNET_PQ_query_param_end 255 GNUNET_PQ_query_param_end
259 }; 256 };
260 struct GNUNET_PQ_ResultSpec rs[] = { 257 struct GNUNET_PQ_ResultSpec rs[] = {
261 GNUNET_PQ_result_spec_variable_size ("block", 258 GNUNET_PQ_result_spec_variable_size("block",
262 (void **) &block, 259 (void **)&block,
263 &bsize), 260 &bsize),
264 GNUNET_PQ_result_spec_end 261 GNUNET_PQ_result_spec_end
265 }; 262 };
266 enum GNUNET_DB_QueryStatus res; 263 enum GNUNET_DB_QueryStatus res;
267 264
268 res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh, 265 res = GNUNET_PQ_eval_prepared_singleton_select(plugin->dbh,
269 "lookup_block", 266 "lookup_block",
270 params, 267 params,
271 rs); 268 rs);
272 if (0 > res) 269 if (0 > res)
273 { 270 {
274 LOG (GNUNET_ERROR_TYPE_WARNING, 271 LOG(GNUNET_ERROR_TYPE_WARNING,
275 "Failing lookup block in namecache (postgres error)\n"); 272 "Failing lookup block in namecache (postgres error)\n");
276 return GNUNET_SYSERR; 273 return GNUNET_SYSERR;
277 } 274 }
278 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) 275 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
279 { 276 {
280 /* no result */ 277 /* no result */
281 LOG (GNUNET_ERROR_TYPE_DEBUG, 278 LOG(GNUNET_ERROR_TYPE_DEBUG,
282 "Ending iteration (no more results)\n"); 279 "Ending iteration (no more results)\n");
283 return GNUNET_NO; 280 return GNUNET_NO;
284 } 281 }
285 if ( (bsize < sizeof (*block)) || 282 if ((bsize < sizeof(*block)) ||
286 (bsize != ntohl (block->purpose.size) + 283 (bsize != ntohl(block->purpose.size) +
287 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + 284 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) +
288 sizeof (struct GNUNET_CRYPTO_EcdsaSignature)) ) 285 sizeof(struct GNUNET_CRYPTO_EcdsaSignature)))
289 { 286 {
290 GNUNET_break (0); 287 GNUNET_break(0);
291 LOG (GNUNET_ERROR_TYPE_DEBUG, 288 LOG(GNUNET_ERROR_TYPE_DEBUG,
292 "Failing lookup (corrupt block)\n"); 289 "Failing lookup (corrupt block)\n");
293 GNUNET_PQ_cleanup_result (rs); 290 GNUNET_PQ_cleanup_result(rs);
294 return GNUNET_SYSERR; 291 return GNUNET_SYSERR;
295 } 292 }
296 iter (iter_cls, 293 iter(iter_cls,
297 block); 294 block);
298 GNUNET_PQ_cleanup_result (rs); 295 GNUNET_PQ_cleanup_result(rs);
299 return GNUNET_OK; 296 return GNUNET_OK;
300} 297}
301 298
@@ -307,9 +304,9 @@ namecache_postgres_lookup_block (void *cls,
307 * @param plugin the plugin context (state for this module) 304 * @param plugin the plugin context (state for this module)
308 */ 305 */
309static void 306static void
310database_shutdown (struct Plugin *plugin) 307database_shutdown(struct Plugin *plugin)
311{ 308{
312 PQfinish (plugin->dbh); 309 PQfinish(plugin->dbh);
313 plugin->dbh = NULL; 310 plugin->dbh = NULL;
314} 311}
315 312
@@ -321,7 +318,7 @@ database_shutdown (struct Plugin *plugin)
321 * @return NULL on error, otherwise the plugin context 318 * @return NULL on error, otherwise the plugin context
322 */ 319 */
323void * 320void *
324libgnunet_plugin_namecache_postgres_init (void *cls) 321libgnunet_plugin_namecache_postgres_init(void *cls)
325{ 322{
326 static struct Plugin plugin; 323 static struct Plugin plugin;
327 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 324 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
@@ -329,19 +326,19 @@ libgnunet_plugin_namecache_postgres_init (void *cls)
329 326
330 if (NULL != plugin.cfg) 327 if (NULL != plugin.cfg)
331 return NULL; /* can only initialize once! */ 328 return NULL; /* can only initialize once! */
332 memset (&plugin, 0, sizeof (struct Plugin)); 329 memset(&plugin, 0, sizeof(struct Plugin));
333 plugin.cfg = cfg; 330 plugin.cfg = cfg;
334 if (GNUNET_OK != database_setup (&plugin)) 331 if (GNUNET_OK != database_setup(&plugin))
335 { 332 {
336 database_shutdown (&plugin); 333 database_shutdown(&plugin);
337 return NULL; 334 return NULL;
338 } 335 }
339 api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions); 336 api = GNUNET_new(struct GNUNET_NAMECACHE_PluginFunctions);
340 api->cls = &plugin; 337 api->cls = &plugin;
341 api->cache_block = &namecache_postgres_cache_block; 338 api->cache_block = &namecache_postgres_cache_block;
342 api->lookup_block = &namecache_postgres_lookup_block; 339 api->lookup_block = &namecache_postgres_lookup_block;
343 LOG (GNUNET_ERROR_TYPE_INFO, 340 LOG(GNUNET_ERROR_TYPE_INFO,
344 "Postgres namecache plugin running\n"); 341 "Postgres namecache plugin running\n");
345 return api; 342 return api;
346} 343}
347 344
@@ -353,16 +350,16 @@ libgnunet_plugin_namecache_postgres_init (void *cls)
353 * @return always NULL 350 * @return always NULL
354 */ 351 */
355void * 352void *
356libgnunet_plugin_namecache_postgres_done (void *cls) 353libgnunet_plugin_namecache_postgres_done(void *cls)
357{ 354{
358 struct GNUNET_NAMECACHE_PluginFunctions *api = cls; 355 struct GNUNET_NAMECACHE_PluginFunctions *api = cls;
359 struct Plugin *plugin = api->cls; 356 struct Plugin *plugin = api->cls;
360 357
361 database_shutdown (plugin); 358 database_shutdown(plugin);
362 plugin->cfg = NULL; 359 plugin->cfg = NULL;
363 GNUNET_free (api); 360 GNUNET_free(api);
364 LOG (GNUNET_ERROR_TYPE_DEBUG, 361 LOG(GNUNET_ERROR_TYPE_DEBUG,
365 "Postgres namecache plugin is finished\n"); 362 "Postgres namecache plugin is finished\n");
366 return NULL; 363 return NULL;
367} 364}
368 365