aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/plugin_namestore_sqlite.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/plugin_namestore_sqlite.c')
-rw-r--r--src/namestore/plugin_namestore_sqlite.c801
1 files changed, 0 insertions, 801 deletions
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
deleted file mode 100644
index 0b3aac84f..000000000
--- a/src/namestore/plugin_namestore_sqlite.c
+++ /dev/null
@@ -1,801 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-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 namestore/plugin_namestore_sqlite.c
23 * @brief sqlite-based namestore backend
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_namestore_plugin.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "gnunet_sq_lib.h"
32#include "namestore.h"
33#include <sqlite3.h>
34
35/**
36 * After how many ms "busy" should a DB operation fail for good? A
37 * low value makes sure that we are more responsive to requests
38 * (especially PUTs). A high value guarantees a higher success rate
39 * (SELECTs in iterate can take several seconds despite LIMIT=1).
40 *
41 * The default value of 1s should ensure that users do not experience
42 * huge latencies while at the same time allowing operations to
43 * succeed with reasonable probability.
44 */
45#define BUSY_TIMEOUT_MS 1000
46
47
48/**
49 * Log an error message at log-level 'level' that indicates
50 * a failure of the command 'cmd' on file 'filename'
51 * with the message given by strerror(errno).
52 */
53#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, \
54 "namestore-sqlite", _ ( \
55 "`%s' failed at %s:%d with error: %s\n"), \
56 cmd, \
57 __FILE__, __LINE__, \
58 sqlite3_errmsg ( \
59 db->dbh)); \
60} while (0)
61
62#define LOG(kind, ...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)
63
64
65/**
66 * Context for all functions in this plugin.
67 */
68struct Plugin
69{
70 const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72 /**
73 * Database filename.
74 */
75 char *fn;
76
77 /**
78 * Native SQLite database handle.
79 */
80 sqlite3 *dbh;
81
82 /**
83 * Precompiled SQL to store records.
84 */
85 sqlite3_stmt *store_records;
86
87 /**
88 * Precompiled SQL to deltete existing records.
89 */
90 sqlite3_stmt *delete_records;
91
92 /**
93 * Precompiled SQL for iterate records within a zone.
94 */
95 sqlite3_stmt *iterate_zone;
96
97 /**
98 * Precompiled SQL for iterate all records within all zones.
99 */
100 sqlite3_stmt *iterate_all_zones;
101
102 /**
103 * Precompiled SQL to for reverse lookup based on PKEY.
104 */
105 sqlite3_stmt *zone_to_name;
106
107 /**
108 * Precompiled SQL to lookup records based on label.
109 */
110 sqlite3_stmt *lookup_label;
111};
112
113
114/**
115 * Initialize the database connections and associated
116 * data structures (create tables and indices
117 * as needed as well).
118 *
119 * @param plugin the plugin context (state for this module)
120 * @return #GNUNET_OK on success
121 */
122static int
123database_setup (struct Plugin *plugin)
124{
125 char *sqlite_filename;
126 struct GNUNET_SQ_ExecuteStatement es[] = {
127 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
128 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
129 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
130 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
131 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
132 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"),
133 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
134 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
135 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
136 " uid INTEGER PRIMARY KEY,"
137 " zone_private_key BLOB NOT NULL,"
138 " pkey BLOB,"
139 " rvalue INT8 NOT NULL,"
140 " record_count INT NOT NULL,"
141 " record_data BLOB NOT NULL,"
142 " label TEXT NOT NULL"
143 ")"),
144 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
145 "ON ns098records (zone_private_key,pkey)"),
146 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
147 "ON ns098records (zone_private_key,uid)"),
148 GNUNET_SQ_EXECUTE_STATEMENT_END
149 };
150 struct GNUNET_SQ_PrepareStatement ps[] = {
151 GNUNET_SQ_make_prepare ("INSERT INTO ns098records "
152 "(zone_private_key,pkey,rvalue,record_count,record_data,label)"
153 " VALUES (?, ?, ?, ?, ?, ?)",
154 &plugin->store_records),
155 GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
156 "WHERE zone_private_key=? AND label=?",
157 &plugin->delete_records),
158 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
159 " FROM ns098records"
160 " WHERE zone_private_key=? AND pkey=?",
161 &plugin->zone_to_name),
162 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
163 " FROM ns098records"
164 " WHERE zone_private_key=? AND uid > ?"
165 " ORDER BY uid ASC"
166 " LIMIT ?",
167 &plugin->iterate_zone),
168 GNUNET_SQ_make_prepare (
169 "SELECT uid,record_count,record_data,label,zone_private_key"
170 " FROM ns098records"
171 " WHERE uid > ?"
172 " ORDER BY uid ASC"
173 " LIMIT ?",
174 &plugin->iterate_all_zones),
175 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
176 " FROM ns098records"
177 " WHERE zone_private_key=? AND label=?",
178 &plugin->lookup_label),
179 GNUNET_SQ_PREPARE_END
180 };
181
182 if (GNUNET_OK !=
183 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
184 "namestore-sqlite",
185 "FILENAME",
186 &sqlite_filename))
187 {
188 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
189 "namestore-sqlite",
190 "FILENAME");
191 return GNUNET_SYSERR;
192 }
193 if (GNUNET_OK !=
194 GNUNET_DISK_file_test (sqlite_filename))
195 {
196 if (GNUNET_OK !=
197 GNUNET_DISK_directory_create_for_file (sqlite_filename))
198 {
199 GNUNET_break (0);
200 GNUNET_free (sqlite_filename);
201 return GNUNET_SYSERR;
202 }
203 }
204 /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */
205 plugin->fn = sqlite_filename;
206
207 /* Open database and precompile statements */
208 if (SQLITE_OK !=
209 sqlite3_open (plugin->fn,
210 &plugin->dbh))
211 {
212 LOG (GNUNET_ERROR_TYPE_ERROR,
213 _ ("Unable to initialize SQLite: %s.\n"),
214 sqlite3_errmsg (plugin->dbh));
215 return GNUNET_SYSERR;
216 }
217 GNUNET_break (SQLITE_OK ==
218 sqlite3_busy_timeout (plugin->dbh,
219 BUSY_TIMEOUT_MS));
220 if (GNUNET_OK !=
221 GNUNET_SQ_exec_statements (plugin->dbh,
222 es))
223 {
224 GNUNET_break (0);
225 LOG (GNUNET_ERROR_TYPE_ERROR,
226 _ ("Failed to setup database at `%s'\n"),
227 plugin->fn);
228 return GNUNET_SYSERR;
229 }
230
231 if (GNUNET_OK !=
232 GNUNET_SQ_prepare (plugin->dbh,
233 ps))
234 {
235 GNUNET_break (0);
236 LOG (GNUNET_ERROR_TYPE_ERROR,
237 _ ("Failed to setup database at `%s'\n"),
238 plugin->fn);
239 return GNUNET_SYSERR;
240 }
241 return GNUNET_OK;
242}
243
244
245/**
246 * Shutdown database connection and associate data
247 * structures.
248 * @param plugin the plugin context (state for this module)
249 */
250static void
251database_shutdown (struct Plugin *plugin)
252{
253 int result;
254 sqlite3_stmt *stmt;
255
256 if (NULL != plugin->store_records)
257 sqlite3_finalize (plugin->store_records);
258 if (NULL != plugin->delete_records)
259 sqlite3_finalize (plugin->delete_records);
260 if (NULL != plugin->iterate_zone)
261 sqlite3_finalize (plugin->iterate_zone);
262 if (NULL != plugin->iterate_all_zones)
263 sqlite3_finalize (plugin->iterate_all_zones);
264 if (NULL != plugin->zone_to_name)
265 sqlite3_finalize (plugin->zone_to_name);
266 if (NULL != plugin->lookup_label)
267 sqlite3_finalize (plugin->lookup_label);
268 result = sqlite3_close (plugin->dbh);
269 if (result == SQLITE_BUSY)
270 {
271 LOG (GNUNET_ERROR_TYPE_WARNING,
272 _ (
273 "Tried to close sqlite without finalizing all prepared statements.\n"));
274 stmt = sqlite3_next_stmt (plugin->dbh,
275 NULL);
276 while (NULL != stmt)
277 {
278 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
279 "sqlite",
280 "Closing statement %p\n",
281 stmt);
282 result = sqlite3_finalize (stmt);
283 if (result != SQLITE_OK)
284 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
285 "sqlite",
286 "Failed to close statement %p: %d\n",
287 stmt,
288 result);
289 stmt = sqlite3_next_stmt (plugin->dbh,
290 NULL);
291 }
292 result = sqlite3_close (plugin->dbh);
293 }
294 if (SQLITE_OK != result)
295 LOG_SQLITE (plugin,
296 GNUNET_ERROR_TYPE_ERROR,
297 "sqlite3_close");
298
299 GNUNET_free (plugin->fn);
300}
301
302
303/**
304 * Store a record in the datastore. Removes any existing record in the
305 * same zone with the same name.
306 *
307 * @param cls closure (internal context for the plugin)
308 * @param zone_key private key of the zone
309 * @param label name that is being mapped (at most 255 characters long)
310 * @param rd_count number of entries in @a rd array
311 * @param rd array of records with data to store
312 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
313 */
314static int
315namestore_sqlite_store_records (void *cls,
316 const struct
317 GNUNET_IDENTITY_PrivateKey *zone_key,
318 const char *label,
319 unsigned int rd_count,
320 const struct GNUNET_GNSRECORD_Data *rd)
321{
322 struct Plugin *plugin = cls;
323 int n;
324 struct GNUNET_IDENTITY_PublicKey pkey;
325 uint64_t rvalue;
326 ssize_t data_size;
327
328 memset (&pkey,
329 0,
330 sizeof(pkey));
331 for (unsigned int i = 0; i < rd_count; i++)
332 {
333 LOG (GNUNET_ERROR_TYPE_DEBUG,
334 "Checking if `%d' is zonekey type\n",
335 rd[i].record_type);
336
337 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
338 {
339 GNUNET_break (GNUNET_YES ==
340 GNUNET_GNSRECORD_identity_from_data (rd[i].data,
341 rd[i].data_size,
342 rd[i].record_type,
343 &pkey));
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Storing delegation zone record value `%s'\n",
346 GNUNET_GNSRECORD_z2s (&pkey));
347
348 break;
349 }
350 }
351 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
352 UINT64_MAX);
353 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
354 rd);
355 if (data_size < 0)
356 {
357 GNUNET_break (0);
358 return GNUNET_SYSERR;
359 }
360 if (data_size > 64 * 65536)
361 {
362 GNUNET_break (0);
363 return GNUNET_SYSERR;
364 }
365 {
366 /* First delete 'old' records */
367 char data[data_size];
368 struct GNUNET_SQ_QueryParam dparams[] = {
369 GNUNET_SQ_query_param_auto_from_type (zone_key),
370 GNUNET_SQ_query_param_string (label),
371 GNUNET_SQ_query_param_end
372 };
373 ssize_t ret;
374
375 ret = GNUNET_GNSRECORD_records_serialize (rd_count,
376 rd,
377 data_size,
378 data);
379 if ((ret < 0) ||
380 (data_size != ret))
381 {
382 GNUNET_break (0);
383 return GNUNET_SYSERR;
384 }
385 if (GNUNET_OK !=
386 GNUNET_SQ_bind (plugin->delete_records,
387 dparams))
388 {
389 LOG_SQLITE (plugin,
390 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
391 "sqlite3_bind_XXXX");
392 GNUNET_SQ_reset (plugin->dbh,
393 plugin->delete_records);
394 return GNUNET_SYSERR;
395 }
396 n = sqlite3_step (plugin->delete_records);
397 GNUNET_SQ_reset (plugin->dbh,
398 plugin->delete_records);
399
400 if (0 != rd_count)
401 {
402 uint32_t rd_count32 = (uint32_t) rd_count;
403 struct GNUNET_SQ_QueryParam sparams[] = {
404 GNUNET_SQ_query_param_auto_from_type (zone_key),
405 GNUNET_SQ_query_param_auto_from_type (&pkey),
406 GNUNET_SQ_query_param_uint64 (&rvalue),
407 GNUNET_SQ_query_param_uint32 (&rd_count32),
408 GNUNET_SQ_query_param_fixed_size (data, data_size),
409 GNUNET_SQ_query_param_string (label),
410 GNUNET_SQ_query_param_end
411 };
412
413 if (GNUNET_OK !=
414 GNUNET_SQ_bind (plugin->store_records,
415 sparams))
416 {
417 LOG_SQLITE (plugin,
418 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
419 "sqlite3_bind_XXXX");
420 GNUNET_SQ_reset (plugin->dbh,
421 plugin->store_records);
422 return GNUNET_SYSERR;
423 }
424 n = sqlite3_step (plugin->store_records);
425 GNUNET_SQ_reset (plugin->dbh,
426 plugin->store_records);
427 }
428 }
429 switch (n)
430 {
431 case SQLITE_DONE:
432 if (0 != rd_count)
433 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
434 "sqlite",
435 "Record stored\n");
436 else
437 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
438 "sqlite",
439 "Record deleted\n");
440 return GNUNET_OK;
441
442 case SQLITE_BUSY:
443 LOG_SQLITE (plugin,
444 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
445 "sqlite3_step");
446 return GNUNET_NO;
447
448 default:
449 LOG_SQLITE (plugin,
450 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
451 "sqlite3_step");
452 return GNUNET_SYSERR;
453 }
454}
455
456
457/**
458 * The given 'sqlite' statement has been prepared to be run.
459 * It will return a record which should be given to the iterator.
460 * Runs the statement and parses the returned record.
461 *
462 * @param plugin plugin context
463 * @param stmt to run (and then clean up)
464 * @param zone_key private key of the zone
465 * @param limit maximum number of results to fetch
466 * @param iter iterator to call with the result
467 * @param iter_cls closure for @a iter
468 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
469 */
470static int
471get_records_and_call_iterator (struct Plugin *plugin,
472 sqlite3_stmt *stmt,
473 const struct
474 GNUNET_IDENTITY_PrivateKey *zone_key,
475 uint64_t limit,
476 GNUNET_NAMESTORE_RecordIterator iter,
477 void *iter_cls)
478{
479 int ret;
480 int sret;
481
482 ret = GNUNET_OK;
483 for (uint64_t i = 0; i < limit; i++)
484 {
485 sret = sqlite3_step (stmt);
486
487 if (SQLITE_DONE == sret)
488 {
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Iteration done (no results)\n");
491 ret = GNUNET_NO;
492 break;
493 }
494 if (SQLITE_ROW != sret)
495 {
496 LOG_SQLITE (plugin,
497 GNUNET_ERROR_TYPE_ERROR,
498 "sqlite_step");
499 ret = GNUNET_SYSERR;
500 break;
501 }
502
503 {
504 uint64_t seq;
505 uint32_t record_count;
506 size_t data_size;
507 void *data;
508 char *label;
509 struct GNUNET_IDENTITY_PrivateKey zk;
510 struct GNUNET_SQ_ResultSpec rs[] = {
511 GNUNET_SQ_result_spec_uint64 (&seq),
512 GNUNET_SQ_result_spec_uint32 (&record_count),
513 GNUNET_SQ_result_spec_variable_size (&data,
514 &data_size),
515 GNUNET_SQ_result_spec_string (&label),
516 GNUNET_SQ_result_spec_end
517 };
518 struct GNUNET_SQ_ResultSpec rsx[] = {
519 GNUNET_SQ_result_spec_uint64 (&seq),
520 GNUNET_SQ_result_spec_uint32 (&record_count),
521 GNUNET_SQ_result_spec_variable_size (&data,
522 &data_size),
523 GNUNET_SQ_result_spec_string (&label),
524 GNUNET_SQ_result_spec_auto_from_type (&zk),
525 GNUNET_SQ_result_spec_end
526 };
527
528 ret = GNUNET_SQ_extract_result (stmt,
529 (NULL == zone_key)
530 ? rsx
531 : rs);
532 if ((GNUNET_OK != ret) ||
533 (record_count > 64 * 1024))
534 {
535 /* sanity check, don't stack allocate far too much just
536 because database might contain a large value here */
537 GNUNET_break (0);
538 ret = GNUNET_SYSERR;
539 break;
540 }
541 else
542 {
543 struct GNUNET_GNSRECORD_Data rd[record_count];
544
545 GNUNET_assert (0 != seq);
546 if (GNUNET_OK !=
547 GNUNET_GNSRECORD_records_deserialize (data_size,
548 data,
549 record_count,
550 rd))
551 {
552 GNUNET_break (0);
553 ret = GNUNET_SYSERR;
554 break;
555 }
556 else
557 {
558 if (NULL != zone_key)
559 zk = *zone_key;
560 if (NULL != iter)
561 iter (iter_cls,
562 seq,
563 &zk,
564 label,
565 record_count,
566 rd);
567 }
568 }
569 GNUNET_SQ_cleanup_result (rs);
570 }
571 }
572 GNUNET_SQ_reset (plugin->dbh,
573 stmt);
574 return ret;
575}
576
577
578/**
579 * Lookup records in the datastore for which we are the authority.
580 *
581 * @param cls closure (internal context for the plugin)
582 * @param zone private key of the zone
583 * @param label name of the record in the zone
584 * @param iter function to call with the result
585 * @param iter_cls closure for @a iter
586 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
587 */
588static int
589namestore_sqlite_lookup_records (void *cls,
590 const struct
591 GNUNET_IDENTITY_PrivateKey *zone,
592 const char *label,
593 GNUNET_NAMESTORE_RecordIterator iter,
594 void *iter_cls)
595{
596 struct Plugin *plugin = cls;
597 struct GNUNET_SQ_QueryParam params[] = {
598 GNUNET_SQ_query_param_auto_from_type (zone),
599 GNUNET_SQ_query_param_string (label),
600 GNUNET_SQ_query_param_end
601 };
602
603 if (NULL == zone)
604 {
605 GNUNET_break (0);
606 return GNUNET_SYSERR;
607 }
608 if (GNUNET_OK !=
609 GNUNET_SQ_bind (plugin->lookup_label,
610 params))
611 {
612 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
613 "sqlite3_bind_XXXX");
614 GNUNET_SQ_reset (plugin->dbh,
615 plugin->lookup_label);
616 return GNUNET_SYSERR;
617 }
618 return get_records_and_call_iterator (plugin,
619 plugin->lookup_label,
620 zone,
621 1,
622 iter,
623 iter_cls);
624}
625
626
627/**
628 * Iterate over the results for a particular key and zone in the
629 * datastore. Will return at most one result to the iterator.
630 *
631 * @param cls closure (internal context for the plugin)
632 * @param zone hash of public key of the zone, NULL to iterate over all zones
633 * @param serial serial number to exclude in the list of all matching records
634 * @param limit maximum number of results to return
635 * @param iter function to call with the result
636 * @param iter_cls closure for @a iter
637 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
638 */
639static int
640namestore_sqlite_iterate_records (void *cls,
641 const struct
642 GNUNET_IDENTITY_PrivateKey *zone,
643 uint64_t serial,
644 uint64_t limit,
645 GNUNET_NAMESTORE_RecordIterator iter,
646 void *iter_cls)
647{
648 struct Plugin *plugin = cls;
649 sqlite3_stmt *stmt;
650 int err;
651
652 if (NULL == zone)
653 {
654 struct GNUNET_SQ_QueryParam params[] = {
655 GNUNET_SQ_query_param_uint64 (&serial),
656 GNUNET_SQ_query_param_uint64 (&limit),
657 GNUNET_SQ_query_param_end
658 };
659
660 stmt = plugin->iterate_all_zones;
661 err = GNUNET_SQ_bind (stmt,
662 params);
663 }
664 else
665 {
666 struct GNUNET_SQ_QueryParam params[] = {
667 GNUNET_SQ_query_param_auto_from_type (zone),
668 GNUNET_SQ_query_param_uint64 (&serial),
669 GNUNET_SQ_query_param_uint64 (&limit),
670 GNUNET_SQ_query_param_end
671 };
672
673 stmt = plugin->iterate_zone;
674 err = GNUNET_SQ_bind (stmt,
675 params);
676 }
677 if (GNUNET_OK != err)
678 {
679 LOG_SQLITE (plugin,
680 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
681 "sqlite3_bind_XXXX");
682 GNUNET_SQ_reset (plugin->dbh,
683 stmt);
684 return GNUNET_SYSERR;
685 }
686 return get_records_and_call_iterator (plugin,
687 stmt,
688 zone,
689 limit,
690 iter,
691 iter_cls);
692}
693
694
695/**
696 * Look for an existing PKEY delegation record for a given public key.
697 * Returns at most one result to the iterator.
698 *
699 * @param cls closure (internal context for the plugin)
700 * @param zone private key of the zone to look up in, never NULL
701 * @param value_zone public key of the target zone (value), never NULL
702 * @param iter function to call with the result
703 * @param iter_cls closure for @a iter
704 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
705 */
706static int
707namestore_sqlite_zone_to_name (void *cls,
708 const struct GNUNET_IDENTITY_PrivateKey *zone,
709 const struct
710 GNUNET_IDENTITY_PublicKey *value_zone,
711 GNUNET_NAMESTORE_RecordIterator iter,
712 void *iter_cls)
713{
714 struct Plugin *plugin = cls;
715 struct GNUNET_SQ_QueryParam params[] = {
716 GNUNET_SQ_query_param_auto_from_type (zone),
717 GNUNET_SQ_query_param_auto_from_type (value_zone),
718 GNUNET_SQ_query_param_end
719 };
720
721 if (GNUNET_OK !=
722 GNUNET_SQ_bind (plugin->zone_to_name,
723 params))
724 {
725 LOG_SQLITE (plugin,
726 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
727 "sqlite3_bind_XXXX");
728 GNUNET_SQ_reset (plugin->dbh,
729 plugin->zone_to_name);
730 return GNUNET_SYSERR;
731 }
732 LOG (GNUNET_ERROR_TYPE_DEBUG,
733 "Performing reverse lookup for `%s'\n",
734 GNUNET_GNSRECORD_z2s (value_zone));
735 return get_records_and_call_iterator (plugin,
736 plugin->zone_to_name,
737 zone,
738 1,
739 iter,
740 iter_cls);
741}
742
743
744/**
745 * Entry point for the plugin.
746 *
747 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
748 * @return NULL on error, otherwise the plugin context
749 */
750void *
751libgnunet_plugin_namestore_sqlite_init (void *cls)
752{
753 static struct Plugin plugin;
754 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
755 struct GNUNET_NAMESTORE_PluginFunctions *api;
756
757 if (NULL != plugin.cfg)
758 return NULL; /* can only initialize once! */
759 memset (&plugin,
760 0,
761 sizeof(struct Plugin));
762 plugin.cfg = cfg;
763 if (GNUNET_OK != database_setup (&plugin))
764 {
765 database_shutdown (&plugin);
766 return NULL;
767 }
768 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
769 api->cls = &plugin;
770 api->store_records = &namestore_sqlite_store_records;
771 api->iterate_records = &namestore_sqlite_iterate_records;
772 api->zone_to_name = &namestore_sqlite_zone_to_name;
773 api->lookup_records = &namestore_sqlite_lookup_records;
774 LOG (GNUNET_ERROR_TYPE_INFO,
775 _ ("Sqlite database running\n"));
776 return api;
777}
778
779
780/**
781 * Exit point from the plugin.
782 *
783 * @param cls the plugin context (as returned by "init")
784 * @return always NULL
785 */
786void *
787libgnunet_plugin_namestore_sqlite_done (void *cls)
788{
789 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
790 struct Plugin *plugin = api->cls;
791
792 database_shutdown (plugin);
793 plugin->cfg = NULL;
794 GNUNET_free (api);
795 LOG (GNUNET_ERROR_TYPE_DEBUG,
796 "sqlite plugin is finished\n");
797 return NULL;
798}
799
800
801/* end of plugin_namestore_sqlite.c */