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.c347
1 files changed, 0 insertions, 347 deletions
diff --git a/src/namecache/plugin_namecache_postgres.c b/src/namecache/plugin_namecache_postgres.c
deleted file mode 100644
index ae0f71a1f..000000000
--- a/src/namecache/plugin_namecache_postgres.c
+++ /dev/null
@@ -1,347 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2013, 2016, 2017 GNUnet e.V.
4 *
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
7 * by the Free Software Foundation, either version 3 of the License,
8 * or (at your option) any later version.
9 *
10 * GNUnet is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Affero General Public License for more details.
14 *
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file namecache/plugin_namecache_postgres.c
23 * @brief postgres-based namecache backend
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_namecache_plugin.h"
28#include "gnunet_namecache_service.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_pq_lib.h"
31#include "namecache.h"
32
33
34#define LOG(kind, ...) GNUNET_log_from (kind, "namecache-postgres", __VA_ARGS__)
35
36
37/**
38 * Context for all functions in this plugin.
39 */
40struct Plugin
41{
42 const struct GNUNET_CONFIGURATION_Handle *cfg;
43
44 /**
45 * Postgres database handle.
46 */
47 struct GNUNET_PQ_Context *dbh;
48};
49
50
51/**
52 * Initialize the database connections and associated
53 * data structures (create tables and indices
54 * as needed as well).
55 *
56 * @param plugin the plugin context (state for this module)
57 * @return #GNUNET_OK on success
58 */
59static int
60database_setup (struct Plugin *plugin)
61{
62 struct GNUNET_PQ_ExecuteStatement es_temporary =
63 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns096blocks ("
64 " query BYTEA NOT NULL DEFAULT '',"
65 " block BYTEA NOT NULL DEFAULT '',"
66 " expiration_time BIGINT NOT NULL DEFAULT 0"
67 ")");
68 struct GNUNET_PQ_ExecuteStatement es_default =
69 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns096blocks ("
70 " query BYTEA NOT NULL DEFAULT '',"
71 " block BYTEA NOT NULL DEFAULT '',"
72 " expiration_time BIGINT NOT NULL DEFAULT 0"
73 ")");
74 const struct GNUNET_PQ_ExecuteStatement *cr;
75
76 if (GNUNET_YES ==
77 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
78 "namecache-postgres",
79 "TEMPORARY_TABLE"))
80 {
81 cr = &es_temporary;
82 }
83 else
84 {
85 cr = &es_default;
86 }
87 {
88 struct GNUNET_PQ_ExecuteStatement es[] = {
89 *cr,
90 GNUNET_PQ_make_try_execute (
91 "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)"),
92 GNUNET_PQ_make_try_execute (
93 "CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)"),
94 GNUNET_PQ_EXECUTE_STATEMENT_END
95 };
96 struct GNUNET_PQ_PreparedStatement ps[] = {
97 GNUNET_PQ_make_prepare ("cache_block",
98 "INSERT INTO ns096blocks (query, block, expiration_time) VALUES "
99 "($1, $2, $3)", 3),
100 GNUNET_PQ_make_prepare ("expire_blocks",
101 "DELETE FROM ns096blocks WHERE expiration_time<$1",
102 1),
103 GNUNET_PQ_make_prepare ("delete_block",
104 "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2",
105 2),
106 GNUNET_PQ_make_prepare ("lookup_block",
107 "SELECT block FROM ns096blocks WHERE query=$1"
108 " ORDER BY expiration_time DESC LIMIT 1", 1),
109 GNUNET_PQ_PREPARED_STATEMENT_END
110 };
111
112 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
113 "namecache-postgres",
114 NULL,
115 es,
116 ps);
117 }
118 if (NULL == plugin->dbh)
119 return GNUNET_SYSERR;
120 return GNUNET_OK;
121}
122
123
124/**
125 * Removes any expired block.
126 *
127 * @param plugin the plugin
128 */
129static void
130namecache_postgres_expire_blocks (struct Plugin *plugin)
131{
132 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
133 struct GNUNET_PQ_QueryParam params[] = {
134 GNUNET_PQ_query_param_absolute_time (&now),
135 GNUNET_PQ_query_param_end
136 };
137 enum GNUNET_DB_QueryStatus res;
138
139 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
140 "expire_blocks",
141 params);
142 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res);
143}
144
145
146/**
147 * Delete older block in the datastore.
148 *
149 * @param plugin the plugin
150 * @param query query for the block
151 * @param expiration_time how old does the block have to be for deletion
152 */
153static void
154delete_old_block (struct Plugin *plugin,
155 const struct GNUNET_HashCode *query,
156 struct GNUNET_TIME_Absolute expiration_time)
157{
158 struct GNUNET_PQ_QueryParam params[] = {
159 GNUNET_PQ_query_param_auto_from_type (query),
160 GNUNET_PQ_query_param_absolute_time (&expiration_time),
161 GNUNET_PQ_query_param_end
162 };
163 enum GNUNET_DB_QueryStatus res;
164
165 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
166 "delete_block",
167 params);
168 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res);
169}
170
171
172/**
173 * Cache a block in the datastore.
174 *
175 * @param cls closure (internal context for the plugin)
176 * @param block block to cache
177 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
178 */
179static int
180namecache_postgres_cache_block (void *cls,
181 const struct GNUNET_GNSRECORD_Block *block)
182{
183 struct Plugin *plugin = cls;
184 struct GNUNET_HashCode query;
185 size_t block_size = GNUNET_GNSRECORD_block_get_size (block);
186 struct GNUNET_TIME_Absolute exp;
187 exp = GNUNET_GNSRECORD_block_get_expiration (block);
188 struct GNUNET_PQ_QueryParam params[] = {
189 GNUNET_PQ_query_param_auto_from_type (&query),
190 GNUNET_PQ_query_param_fixed_size (block, block_size),
191 GNUNET_PQ_query_param_absolute_time (&exp),
192 GNUNET_PQ_query_param_end
193 };
194 enum GNUNET_DB_QueryStatus res;
195
196 namecache_postgres_expire_blocks (plugin);
197 GNUNET_GNSRECORD_query_from_block (block,
198 &query);
199 if (block_size > 64 * 65536)
200 {
201 GNUNET_break (0);
202 return GNUNET_SYSERR;
203 }
204 delete_old_block (plugin,
205 &query,
206 exp);
207
208 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
209 "cache_block",
210 params);
211 if (0 > res)
212 return GNUNET_SYSERR;
213 return GNUNET_OK;
214}
215
216
217/**
218 * Get the block for a particular zone and label in the
219 * datastore. Will return at most one result to the iterator.
220 *
221 * @param cls closure (internal context for the plugin)
222 * @param query hash of public key derived from the zone and the label
223 * @param iter function to call with the result
224 * @param iter_cls closure for @a iter
225 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
226 */
227static int
228namecache_postgres_lookup_block (void *cls,
229 const struct GNUNET_HashCode *query,
230 GNUNET_NAMECACHE_BlockCallback iter,
231 void *iter_cls)
232{
233 struct Plugin *plugin = cls;
234 size_t bsize;
235 struct GNUNET_GNSRECORD_Block *block;
236 struct GNUNET_PQ_QueryParam params[] = {
237 GNUNET_PQ_query_param_auto_from_type (query),
238 GNUNET_PQ_query_param_end
239 };
240 struct GNUNET_PQ_ResultSpec rs[] = {
241 GNUNET_PQ_result_spec_variable_size ("block",
242 (void **) &block,
243 &bsize),
244 GNUNET_PQ_result_spec_end
245 };
246 enum GNUNET_DB_QueryStatus res;
247
248 res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh,
249 "lookup_block",
250 params,
251 rs);
252 if (0 > res)
253 {
254 LOG (GNUNET_ERROR_TYPE_WARNING,
255 "Failing lookup block in namecache (postgres error)\n");
256 return GNUNET_SYSERR;
257 }
258 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
259 {
260 /* no result */
261 LOG (GNUNET_ERROR_TYPE_DEBUG,
262 "Ending iteration (no more results)\n");
263 return GNUNET_NO;
264 }
265 if ((bsize < sizeof(*block)))
266 {
267 GNUNET_break (0);
268 LOG (GNUNET_ERROR_TYPE_DEBUG,
269 "Failing lookup (corrupt block)\n");
270 GNUNET_PQ_cleanup_result (rs);
271 return GNUNET_SYSERR;
272 }
273 iter (iter_cls,
274 block);
275 GNUNET_PQ_cleanup_result (rs);
276 return GNUNET_OK;
277}
278
279
280/**
281 * Shutdown database connection and associate data
282 * structures.
283 *
284 * @param plugin the plugin context (state for this module)
285 */
286static void
287database_shutdown (struct Plugin *plugin)
288{
289 GNUNET_PQ_disconnect (plugin->dbh);
290 plugin->dbh = NULL;
291}
292
293
294/**
295 * Entry point for the plugin.
296 *
297 * @param cls the `struct GNUNET_NAMECACHE_PluginEnvironment *`
298 * @return NULL on error, otherwise the plugin context
299 */
300void *
301libgnunet_plugin_namecache_postgres_init (void *cls)
302{
303 static struct Plugin plugin;
304 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
305 struct GNUNET_NAMECACHE_PluginFunctions *api;
306
307 if (NULL != plugin.cfg)
308 return NULL; /* can only initialize once! */
309 memset (&plugin, 0, sizeof(struct Plugin));
310 plugin.cfg = cfg;
311 if (GNUNET_OK != database_setup (&plugin))
312 {
313 database_shutdown (&plugin);
314 return NULL;
315 }
316 api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions);
317 api->cls = &plugin;
318 api->cache_block = &namecache_postgres_cache_block;
319 api->lookup_block = &namecache_postgres_lookup_block;
320 LOG (GNUNET_ERROR_TYPE_INFO,
321 "Postgres namecache plugin running\n");
322 return api;
323}
324
325
326/**
327 * Exit point from the plugin.
328 *
329 * @param cls the plugin context (as returned by "init")
330 * @return always NULL
331 */
332void *
333libgnunet_plugin_namecache_postgres_done (void *cls)
334{
335 struct GNUNET_NAMECACHE_PluginFunctions *api = cls;
336 struct Plugin *plugin = api->cls;
337
338 database_shutdown (plugin);
339 plugin->cfg = NULL;
340 GNUNET_free (api);
341 LOG (GNUNET_ERROR_TYPE_DEBUG,
342 "Postgres namecache plugin is finished\n");
343 return NULL;
344}
345
346
347/* end of plugin_namecache_postgres.c */