2 * This file is part of GNUnet
3 * (C) 2009, 2011, 2012 Christian Grothoff (and other contributing authors)
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * @file namestore/plugin_namestore_sqlite.c
23 * @brief sqlite-based namestore backend
24 * @author Christian Grothoff
28 #include "gnunet_namestore_plugin.h"
32 * After how many ms "busy" should a DB operation fail for good?
33 * A low value makes sure that we are more responsive to requests
34 * (especially PUTs). A high value guarantees a higher success
35 * rate (SELECTs in iterate can take several seconds despite LIMIT=1).
37 * The default value of 1s should ensure that users do not experience
38 * huge latencies while at the same time allowing operations to succeed
39 * with reasonable probability.
41 #define BUSY_TIMEOUT_MS 1000
45 * Log an error message at log-level 'level' that indicates
46 * a failure of the command 'cmd' on file 'filename'
47 * with the message given by strerror(errno).
49 #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "namestore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
51 #define LOG(kind,...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)
55 * Context for all functions in this plugin.
60 const struct GNUNET_CONFIGURATION_Handle *cfg;
68 * Native SQLite database handle.
73 * Precompiled SQL for put record
75 sqlite3_stmt *put_records;
78 * Precompiled SQL for remove record
80 sqlite3_stmt *remove_records;
83 * Precompiled SQL for iterate over all records.
85 sqlite3_stmt *iterate_all;
88 * Precompiled SQL for iterate records with same name.
90 sqlite3_stmt *iterate_by_name;
93 * Precompiled SQL for iterate records with same zone.
95 sqlite3_stmt *iterate_by_zone;
98 * Precompiled SQL for iterate records with same name and zone.
100 sqlite3_stmt *iterate_records;
103 * Precompiled SQL for delete zone
105 sqlite3_stmt *delete_zone;
111 * Internal format of a record in the BLOB in the database.
117 * Expiration time for the DNS record.
119 struct GNUNET_TIME_AbsoluteNBO expiration;
122 * Number of bytes in 'data', network byte order.
127 * Type of the GNS/DNS record, network byte order.
129 uint32_t record_type;
132 * Flags for the record, network byte order.
140 * @brief Prepare a SQL statement
142 * @param dbh handle to the database
143 * @param zSql SQL statement, UTF-8 encoded
144 * @param ppStmt set to the prepared statement
145 * @return 0 on success
148 sq_prepare (sqlite3 * dbh, const char *zSql, sqlite3_stmt ** ppStmt)
154 sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt,
155 (const char **) &dummy);
156 LOG (GNUNET_ERROR_TYPE_DEBUG,
157 "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result);
163 * Create our database indices.
165 * @param dbh handle to the database
168 create_indices (sqlite3 * dbh)
172 sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_name_rv ON ns090records (zone_hash,record_name_hash,rvalue)",
173 NULL, NULL, NULL)) ||
175 sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone_rv ON ns090records (zone_hash,rvalue)",
176 NULL, NULL, NULL)) ||
178 sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_zone ON ns090records (zone_hash)",
179 NULL, NULL, NULL)) ||
181 sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_name_rv ON ns090records (record_name_hash,rvalue)",
182 NULL, NULL, NULL)) ||
184 sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_rv ON ns090records (rvalue)",
186 LOG (GNUNET_ERROR_TYPE_ERROR,
187 "Failed to create indices: %s\n", sqlite3_errmsg (dbh));
192 #define CHECK(a) GNUNET_break(a)
196 #define ENULL_DEFINED 1
197 #define CHECK(a) if (! a) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); }
202 * Initialize the database connections and associated
203 * data structures (create tables and indices
204 * as needed as well).
206 * @param plugin the plugin context (state for this module)
207 * @return GNUNET_OK on success
210 database_setup (struct Plugin *plugin)
219 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "namestore-sqlite",
220 "FILENAME", &afsdir))
222 LOG (GNUNET_ERROR_TYPE_ERROR,
223 _ ("Option `%s' in section `%s' missing in configuration!\n"),
224 "FILENAME", "namestore-sqlite");
225 return GNUNET_SYSERR;
227 if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
229 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
232 GNUNET_free (afsdir);
233 return GNUNET_SYSERR;
238 GNUNET_STRINGS_to_utf8 (afsdir, strlen (afsdir), nl_langinfo (CODESET));
240 plugin->fn = GNUNET_STRINGS_to_utf8 (afsdir, strlen (afsdir), "UTF-8"); /* good luck */
242 GNUNET_free (afsdir);
244 /* Open database and precompile statements */
245 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
247 LOG (GNUNET_ERROR_TYPE_ERROR,
248 _("Unable to initialize SQLite: %s.\n"),
249 sqlite3_errmsg (plugin->dbh));
250 return GNUNET_SYSERR;
253 sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL,
256 sqlite3_exec (plugin->dbh, "PRAGMA synchronous=NORMAL", NULL, NULL,
259 sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL,
262 sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL,
265 sqlite3_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"", NULL,
268 sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL,
271 sqlite3_exec (plugin->dbh, "PRAGMA count_changes=OFF", NULL, NULL,
274 sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL,
277 CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS));
282 sq_prepare (plugin->dbh,
283 "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns090records'",
285 if ((sqlite3_step (stmt) == SQLITE_DONE) &&
288 "CREATE TABLE ns090records ("
289 " zone_key BLOB NOT NULL DEFAULT '',"
290 " zone_hash BLOB NOT NULL DEFAULT '',"
291 " record_count INT NOT NULL DEFAULT 0,"
292 " record_data BLOB NOT NULL DEFAULT '',"
293 " block_expiration_time INT8 NOT NULL DEFAULT 0,"
294 " signature BLOB NOT NULL DEFAULT '',"
295 " record_name TEXT NOT NULL DEFAULT '',"
296 " record_name_hash BLOB NOT NULL DEFAULT '',"
297 " rvalue INT8 NOT NULL DEFAULT ''"
299 NULL, NULL, NULL) != SQLITE_OK))
301 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec");
302 sqlite3_finalize (stmt);
303 return GNUNET_SYSERR;
305 sqlite3_finalize (stmt);
307 create_indices (plugin->dbh);
309 #define ALL "zone_key, record_name, record_count, record_data, block_expiration_time, signature"
312 "INSERT INTO ns090records (" ALL ", zone_hash, record_name_hash, rvalue) VALUES "
313 "(?, ?, ?, ?, ?, ?, ?, ?, ?)",
314 &plugin->put_records) != SQLITE_OK) ||
317 "DELETE FROM ns090records WHERE zone_hash=? AND record_name_hash=?",
318 &plugin->remove_records) != SQLITE_OK) ||
322 " FROM ns090records WHERE zone_hash=? AND record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?",
323 &plugin->iterate_records) != SQLITE_OK) ||
327 " FROM ns090records WHERE zone_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?",
328 &plugin->iterate_by_zone) != SQLITE_OK) ||
332 " FROM ns090records WHERE record_name_hash=? ORDER BY rvalue LIMIT 1 OFFSET ?",
333 &plugin->iterate_by_name) != SQLITE_OK) ||
337 " FROM ns090records ORDER BY rvalue LIMIT 1 OFFSET ?",
338 &plugin->iterate_all) != SQLITE_OK) ||
341 "DELETE FROM ns090records WHERE zone_hash=?",
342 &plugin->delete_zone) != SQLITE_OK) )
344 LOG_SQLITE (plugin,GNUNET_ERROR_TYPE_ERROR, "precompiling");
345 return GNUNET_SYSERR;
353 * Shutdown database connection and associate data
355 * @param plugin the plugin context (state for this module)
358 database_shutdown (struct Plugin *plugin)
363 if (NULL != plugin->put_records)
364 sqlite3_finalize (plugin->put_records);
365 if (NULL != plugin->remove_records)
366 sqlite3_finalize (plugin->remove_records);
367 if (NULL != plugin->iterate_records)
368 sqlite3_finalize (plugin->iterate_records);
369 if (NULL != plugin->iterate_records)
370 sqlite3_finalize (plugin->iterate_by_zone);
371 if (NULL != plugin->iterate_records)
372 sqlite3_finalize (plugin->iterate_by_name);
373 if (NULL != plugin->iterate_records)
374 sqlite3_finalize (plugin->iterate_all);
375 if (NULL != plugin->delete_zone)
376 sqlite3_finalize (plugin->delete_zone);
377 result = sqlite3_close (plugin->dbh);
378 if (result == SQLITE_BUSY)
380 LOG (GNUNET_ERROR_TYPE_WARNING,
381 _("Tried to close sqlite without finalizing all prepared statements.\n"));
382 stmt = sqlite3_next_stmt (plugin->dbh, NULL);
385 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
386 "Closing statement %p\n", stmt);
387 result = sqlite3_finalize (stmt);
388 if (result != SQLITE_OK)
389 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
390 "Failed to close statement %p: %d\n", stmt, result);
391 stmt = sqlite3_next_stmt (plugin->dbh, NULL);
393 result = sqlite3_close (plugin->dbh);
395 if (SQLITE_OK != result)
396 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
398 GNUNET_free_non_null (plugin->fn);
403 * Removes any existing record in the given zone with the same name.
405 * @param cls closure (internal context for the plugin)
406 * @param zone hash of the public key of the zone
407 * @param name name to remove (at most 255 characters long)
408 * @return GNUNET_OK on success
411 namestore_sqlite_remove_records (void *cls,
412 const GNUNET_HashCode *zone,
415 struct Plugin *plugin = cls;
420 name_len = strlen (name);
421 GNUNET_CRYPTO_hash (name, name_len, &nh);
423 if ((SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
424 (SQLITE_OK != sqlite3_bind_blob (plugin->remove_records, 2, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC)))
426 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
427 "sqlite3_bind_XXXX");
428 if (SQLITE_OK != sqlite3_reset (plugin->remove_records))
430 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
432 return GNUNET_SYSERR;
434 n = sqlite3_step (plugin->remove_records);
435 if (SQLITE_OK != sqlite3_reset (plugin->remove_records))
436 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
441 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record removed\n");
444 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
448 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
450 return GNUNET_SYSERR;
456 * Store a record in the datastore. Removes any existing record in the
457 * same zone with the same name.
459 * @param cls closure (internal context for the plugin)
460 * @param zone_key public key of the zone
461 * @param expire when does the corresponding block in the DHT expire (until
462 * when should we never do a DHT lookup for the same name again)?
463 * @param name name that is being mapped (at most 255 characters long)
464 * @param rd_count number of entries in 'rd' array
465 * @param rd array of records with data to store
466 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
467 * because the user queried for a particular record type only)
468 * @return GNUNET_OK on success, else GNUNET_SYSERR
471 namestore_sqlite_put_records (void *cls,
472 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
473 struct GNUNET_TIME_Absolute expire,
475 unsigned int rd_count,
476 const struct GNUNET_NAMESTORE_RecordData *rd,
477 const struct GNUNET_CRYPTO_RsaSignature *signature)
479 struct Plugin *plugin = cls;
481 GNUNET_HashCode zone;
489 GNUNET_CRYPTO_hash (zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
490 (void) namestore_sqlite_remove_records (plugin, &zone, name);
491 name_len = strlen (name);
492 GNUNET_CRYPTO_hash (name, name_len, &nh);
493 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
494 data_size = rd_count * sizeof (struct DbRecord);
495 for (i=0;i<rd_count;i++)
496 data_size += rd[i].data_size;
497 if (data_size > 64 * 65536)
500 return GNUNET_SYSERR;
503 char data[data_size];
504 struct DbRecord *rec;
506 rec = (struct DbRecord *) data;
507 off = rd_count * sizeof (struct DbRecord);
508 for (i=0;i<rd_count;i++)
510 rec[i].expiration = GNUNET_TIME_absolute_hton (rd[i].expiration);
511 rec[i].data_size = htonl ((uint32_t) rd[i].data_size);
512 rec[i].record_type = htonl (rd[i].record_type);
513 rec[i].flags = htonl (rd[i].flags);
517 off += rd[i].data_size;
519 if ((SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 1, zone_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), SQLITE_STATIC)) ||
520 (SQLITE_OK != sqlite3_bind_text (plugin->put_records, 2, name, -1, SQLITE_STATIC)) ||
521 (SQLITE_OK != sqlite3_bind_int (plugin->put_records, 3, rd_count)) ||
522 (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 4, data, data_size, SQLITE_STATIC)) ||
523 (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 5, expire.abs_value)) ||
524 (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 6, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature), SQLITE_STATIC)) ||
525 (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 7, &zone, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
526 (SQLITE_OK != sqlite3_bind_blob (plugin->put_records, 8, &nh, sizeof (GNUNET_HashCode), SQLITE_STATIC)) ||
527 (SQLITE_OK != sqlite3_bind_int64 (plugin->put_records, 9, rvalue)) )
530 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
531 "sqlite3_bind_XXXX");
532 if (SQLITE_OK != sqlite3_reset (plugin->put_records))
534 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
536 return GNUNET_SYSERR;
539 n = sqlite3_step (plugin->put_records);
540 if (SQLITE_OK != sqlite3_reset (plugin->put_records))
541 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
547 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record stored\n");
550 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
554 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
556 return GNUNET_SYSERR;
562 * Iterate over the results for a particular key and zone in the
563 * datastore. Will return at most one result to the iterator.
565 * @param cls closure (internal context for the plugin)
566 * @param zone hash of public key of the zone, NULL to iterate over all zones
567 * @param name_hash hash of name, NULL to iterate over all records of the zone
568 * @param offset offset in the list of all matching records
569 * @param iter function to call with the result
570 * @param iter_cls closure for iter
571 * @return GNUNET_OK on success, GNUNET_NO if there were no results, GNUNET_SYSERR on error
574 namestore_sqlite_iterate_records (void *cls,
575 const GNUNET_HashCode *zone,
576 const GNUNET_HashCode *name_hash,
578 GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls)
580 struct Plugin *plugin = cls;
587 if (NULL == name_hash)
588 stmt = plugin->iterate_all;
590 stmt = plugin->iterate_by_name;
592 if (NULL == name_hash)
593 stmt = plugin->iterate_by_zone;
595 stmt = plugin->iterate_records;
598 if ( (NULL != zone) &&
599 (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff,
600 zone, sizeof (GNUNET_HashCode),
603 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
604 "sqlite3_bind_XXXX");
605 if (SQLITE_OK != sqlite3_reset (stmt))
607 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
609 return GNUNET_SYSERR;
611 if ( (NULL != name_hash) &&
612 (SQLITE_OK != sqlite3_bind_blob (stmt, ++boff,
613 name_hash, sizeof (GNUNET_HashCode),
616 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
617 "sqlite3_bind_XXXX");
618 if (SQLITE_OK != sqlite3_reset (stmt))
620 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
622 return GNUNET_SYSERR;
625 if (SQLITE_OK != sqlite3_bind_int64 (stmt, ++boff,
628 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
629 "sqlite3_bind_XXXX");
630 if (SQLITE_OK != sqlite3_reset (stmt))
632 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
634 return GNUNET_SYSERR;
637 if (SQLITE_ROW == (sret = sqlite3_step (stmt)))
639 unsigned int record_count;
641 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key;
642 const struct GNUNET_CRYPTO_RsaSignature *sig;
643 struct GNUNET_TIME_Absolute expiration;
648 zone_key = sqlite3_column_blob (stmt, 0);
649 name = (const char*) sqlite3_column_text (stmt, 1);
650 record_count = sqlite3_column_int (stmt, 2);
651 data_size = sqlite3_column_bytes (stmt, 3);
652 data = sqlite3_column_blob (stmt, 3);
653 expiration.abs_value = (uint64_t) sqlite3_column_int64 (stmt, 4);
654 sig = sqlite3_column_blob (stmt, 5);
656 if ( (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) != sqlite3_column_bytes (stmt, 0)) ||
657 (sizeof (struct GNUNET_CRYPTO_RsaSignature) != sqlite3_column_bytes (stmt, 5)) ||
658 (sizeof (struct DbRecord) * record_count > data_size) )
665 const struct DbRecord *db = (const struct DbRecord*) data;
666 struct GNUNET_NAMESTORE_RecordData rd[record_count];
670 off = record_count * sizeof (struct DbRecord);
671 for (i=0;i<record_count;i++)
673 if (off + ntohl (db[i].data_size) > data_size)
680 rd[i].expiration = GNUNET_TIME_absolute_ntoh (db[i].expiration);
681 rd[i].data_size = ntohl (db[i].data_size);
682 rd[i].data = &data[off];
683 rd[i].record_type = ntohl (db[i].record_type);
684 rd[i].flags = ntohl (db[i].flags);
685 off += rd[i].data_size;
687 iter (iter_cls, zone_key, expiration, name,
688 record_count, rd, sig);
693 if (SQLITE_DONE != sret)
694 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step");
695 iter (iter_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, NULL, 0, NULL, NULL);
697 if (SQLITE_OK != sqlite3_reset (stmt))
699 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
706 * Delete an entire zone (all records). Not used in normal operation.
708 * @param cls closure (internal context for the plugin)
709 * @param zone zone to delete
712 namestore_sqlite_delete_zone (void *cls,
713 const GNUNET_HashCode *zone)
715 struct Plugin *plugin = cls;
716 sqlite3_stmt *stmt = plugin->delete_zone;
719 if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (GNUNET_HashCode), SQLITE_STATIC))
721 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
722 "sqlite3_bind_XXXX");
723 if (SQLITE_OK != sqlite3_reset (stmt))
725 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
729 n = sqlite3_step (stmt);
730 if (SQLITE_OK != sqlite3_reset (stmt))
731 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
736 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Values deleted\n");
739 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
743 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
751 * Entry point for the plugin.
753 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
754 * @return NULL on error, othrewise the plugin context
757 libgnunet_plugin_namestore_sqlite_init (void *cls)
759 static struct Plugin plugin;
760 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
761 struct GNUNET_NAMESTORE_PluginFunctions *api;
763 if (NULL != plugin.cfg)
764 return NULL; /* can only initialize once! */
765 memset (&plugin, 0, sizeof (struct Plugin));
767 if (GNUNET_OK != database_setup (&plugin))
769 database_shutdown (&plugin);
772 api = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_PluginFunctions));
774 api->put_records = &namestore_sqlite_put_records;
775 api->remove_records = &namestore_sqlite_remove_records;
776 api->iterate_records = &namestore_sqlite_iterate_records;
777 api->delete_zone = &namestore_sqlite_delete_zone;
778 LOG (GNUNET_ERROR_TYPE_INFO,
779 _("Sqlite database running\n"));
785 * Exit point from the plugin.
787 * @param cls the plugin context (as returned by "init")
788 * @return always NULL
791 libgnunet_plugin_namestore_sqlite_done (void *cls)
793 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
794 struct Plugin *plugin = api->cls;
796 LOG (GNUNET_ERROR_TYPE_DEBUG,
797 "sqlite plugin is done\n");
798 database_shutdown (plugin);
801 LOG (GNUNET_ERROR_TYPE_DEBUG,
802 "sqlite plugin is finished\n");
806 /* end of plugin_namestore_sqlite.c */