2 * This file is part of GNUnet
3 * (C) 2009-2013 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 t * 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 psycstore/plugin_psycstore_sqlite.c
23 * @brief sqlite-based psycstore backend
24 * @author Gabor X Toth
25 * @author Christian Grothoff
29 #include "gnunet_psycstore_plugin.h"
30 #include "gnunet_psycstore_service.h"
31 #include "psycstore.h"
35 * After how many ms "busy" should a DB operation fail for good? A
36 * low value makes sure that we are more responsive to requests
37 * (especially PUTs). A high value guarantees a higher success rate
38 * (SELECTs in iterate can take several seconds despite LIMIT=1).
40 * The default value of 1s should ensure that users do not experience
41 * huge latencies while at the same time allowing operations to
42 * succeed with reasonable probability.
44 #define BUSY_TIMEOUT_MS 1000
48 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' on file 'filename'
50 * with the message given by strerror(errno).
52 #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "psycstore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0)
54 #define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__)
58 * Context for all functions in this plugin.
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
71 * Native SQLite database handle.
76 * Precompiled SQL for channel_key_store()
78 sqlite3_stmt *insert_channel_key;
81 * Precompiled SQL for slave_key_store()
83 sqlite3_stmt *insert_slave_key;
87 * Precompiled SQL for membership_store()
89 sqlite3_stmt *insert_membership;
92 * Precompiled SQL for membership_test()
94 sqlite3_stmt *select_membership;
98 * Precompiled SQL for fragment_store()
100 sqlite3_stmt *insert_fragment;
103 * Precompiled SQL for fragment_add_flags()
105 sqlite3_stmt *update_fragment_flags;
108 * Precompiled SQL for fragment_get()
110 sqlite3_stmt *select_fragment;
113 * Precompiled SQL for message_get()
115 sqlite3_stmt *select_message;
118 * Precompiled SQL for message_get_fragment()
120 sqlite3_stmt *select_message_fragment;
123 * Precompiled SQL for counters_get_master()
125 sqlite3_stmt *select_master_counters;
128 * Precompiled SQL for counters_get_slave()
130 sqlite3_stmt *select_slave_counters;
134 * Precompiled SQL for state_set()
136 sqlite3_stmt *insert_state_current;
139 * Precompiled SQL for state_set()
141 sqlite3_stmt *update_state_current;
144 * Precompiled SQL for state_set_signed()
146 sqlite3_stmt *update_state_signed;
149 * Precompiled SQL for state_sync()
151 sqlite3_stmt *insert_state_sync;
154 * Precompiled SQL for state_sync()
156 sqlite3_stmt *delete_state;
159 * Precompiled SQL for state_sync()
161 sqlite3_stmt *insert_state_from_sync;
164 * Precompiled SQL for state_sync()
166 sqlite3_stmt *delete_state_sync;
169 * Precompiled SQL for state_get()
171 sqlite3_stmt *select_state_one;
174 * Precompiled SQL for state_get_all()
176 sqlite3_stmt *select_state_prefix;
182 * @brief Prepare a SQL statement
184 * @param dbh handle to the database
185 * @param sql SQL statement, UTF-8 encoded
186 * @param stmt set to the prepared statement
187 * @return 0 on success
190 sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt)
195 result = sqlite3_prepare_v2 (dbh, sql, strlen (sql), stmt,
196 (const char **) &tail);
197 LOG (GNUNET_ERROR_TYPE_DEBUG,
198 "Prepared `%s' / %p: %d\n", sql, *stmt, result);
199 if (result != SQLITE_OK)
200 LOG (GNUNET_ERROR_TYPE_ERROR,
201 _("Error preparing SQL query: %s\n %s\n"),
202 sqlite3_errmsg (dbh), sql);
208 * @brief Prepare a SQL statement
210 * @param dbh handle to the database
211 * @param zSql SQL statement, UTF-8 encoded
212 * @param ppStmt set to the prepared statement
213 * @return 0 on success
216 sql_exec (sqlite3 *dbh, const char *sql)
220 result = sqlite3_exec (dbh, sql, NULL, NULL, NULL);
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "Executed `%s' / %d\n", sql, result);
223 if (result != SQLITE_OK)
224 LOG (GNUNET_ERROR_TYPE_ERROR,
225 _("Error executing SQL query: %s\n %s\n"),
226 sqlite3_errmsg (dbh), sql);
232 * Initialize the database connections and associated
233 * data structures (create tables and indices
234 * as needed as well).
236 * @param plugin the plugin context (state for this module)
237 * @return GNUNET_OK on success
240 database_setup (struct Plugin *plugin)
245 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "psycstore-sqlite",
246 "FILENAME", &filename))
248 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
249 "psycstore-sqlite", "FILENAME");
250 return GNUNET_SYSERR;
252 if (GNUNET_OK != GNUNET_DISK_file_test (filename))
254 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (filename))
257 GNUNET_free (filename);
258 return GNUNET_SYSERR;
261 /* filename should be UTF-8-encoded. If it isn't, it's a bug */
262 plugin->fn = filename;
264 /* Open database and precompile statements */
265 if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
267 LOG (GNUNET_ERROR_TYPE_ERROR,
268 _("Unable to initialize SQLite: %s.\n"),
269 sqlite3_errmsg (plugin->dbh));
270 return GNUNET_SYSERR;
273 sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY");
274 sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL");
275 sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF");
276 sql_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL");
277 sql_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"");
278 sql_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE");
279 sql_exec (plugin->dbh, "PRAGMA count_changes=OFF");
280 sql_exec (plugin->dbh, "PRAGMA page_size=4096");
282 sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS);
286 sql_exec (plugin->dbh,
287 "CREATE TABLE IF NOT EXISTS channels ("
288 " id INTEGER PRIMARY KEY,"
289 " pub_key BLOB UNIQUE"
292 sql_exec (plugin->dbh,
293 "CREATE TABLE IF NOT EXISTS slaves ("
294 " id INTEGER PRIMARY KEY,"
295 " pub_key BLOB UNIQUE"
298 sql_exec (plugin->dbh,
299 "CREATE TABLE IF NOT EXISTS membership ("
300 " channel_id INTEGER NOT NULL REFERENCES channels(id),"
301 " slave_id INTEGER NOT NULL REFERENCES slaves(id),"
302 " did_join INTEGER NOT NULL,"
303 " announced_at INTEGER NOT NULL,"
304 " effective_since INTEGER NOT NULL,"
305 " group_generation INTEGER NOT NULL"
307 sql_exec (plugin->dbh,
308 "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id "
309 "ON membership (channel_id, slave_id);");
311 sql_exec (plugin->dbh,
312 "CREATE TABLE IF NOT EXISTS messages ("
313 " channel_id INTEGER NOT NULL,"
314 " hop_counter INTEGER NOT NULL,"
317 " fragment_id INTEGER NOT NULL,"
318 " fragment_offset INTEGER NOT NULL,"
319 " message_id INTEGER NOT NULL,"
320 " group_generation INTEGER NOT NULL,"
321 " multicast_flags INTEGER NOT NULL,"
322 " psyc_flags INTEGER NOT NULL,"
324 " PRIMARY KEY (channel_id, fragment_id),"
325 " UNIQUE (channel_id, message_id, fragment_offset)"
328 sql_exec (plugin->dbh,
329 "CREATE TABLE IF NOT EXISTS state ("
330 " channel_id INTEGER NOT NULL,"
331 " name TEXT NOT NULL,"
332 " value_current BLOB, "
333 " value_signed BLOB, "
334 " PRIMARY KEY (channel_id, name)"
337 sql_exec (plugin->dbh,
338 "CREATE TABLE IF NOT EXISTS state_sync ("
339 " channel_id INTEGER NOT NULL,"
340 " name TEXT NOT NULL,"
342 " PRIMARY KEY (channel_id, name)"
345 /* Prepare statements */
347 sql_prepare (plugin->dbh,
348 "INSERT OR IGNORE INTO channels (pub_key) VALUES (?);",
349 &plugin->insert_channel_key);
351 sql_prepare (plugin->dbh,
352 "INSERT OR IGNORE INTO slaves (pub_key) VALUES (?);",
353 &plugin->insert_slave_key);
355 sql_prepare (plugin->dbh,
356 "INSERT INTO membership "
357 " (channel_id, slave_id, did_join, announced_at, "
358 " effective_since, group_generation) "
359 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), "
360 " (SELECT id FROM slaves WHERE pub_key = ?), "
362 &plugin->insert_membership);
364 sql_prepare (plugin->dbh,
365 "SELECT did_join FROM membership "
366 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
367 " AND slave_id = ? AND effective_since <= ? "
368 "ORDER BY announced_at DESC LIMIT 1;",
369 &plugin->select_membership);
371 sql_prepare (plugin->dbh,
372 "INSERT INTO messages "
373 " (channel_id, hop_counter, signature, purpose, "
374 " fragment_id, fragment_offset, message_id, "
375 " group_generation, multicast_flags, psyc_flags, data) "
376 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), "
377 " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
378 &plugin->insert_fragment);
380 sql_prepare (plugin->dbh,
382 "SET multicast_flags = multicast_flags | ?, "
383 " psyc_flags = psyc_flags | ? "
384 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
385 " AND message_id = ?;",
386 &plugin->update_fragment_flags);
388 sql_prepare (plugin->dbh,
389 "SELECT hop_counter, signature, purpose, "
390 " fragment_offset, message_id, group_generation, "
391 " multicast_flags, psyc_flags, data "
393 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
394 " AND fragment_id = ?;",
395 &plugin->select_fragment);
397 sql_prepare (plugin->dbh,
398 "SELECT hop_counter, signature, purpose, "
399 " fragment_id, fragment_offset, group_generation, "
400 " multicast_flags, psyc_flags, data "
402 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
403 " AND message_id = ?;",
404 &plugin->select_message);
406 sql_prepare (plugin->dbh,
407 "SELECT hop_counter, signature, purpose, "
408 " fragment_id, message_id, group_generation, "
409 " multicast_flags, psyc_flags, data "
411 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
412 " AND message_id = ? AND fragment_offset = ?;",
413 &plugin->select_message_fragment);
415 sql_prepare (plugin->dbh,
416 "SELECT max(fragment_id), max(message_id), max(group_generation) "
418 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
419 &plugin->select_master_counters);
421 sql_prepare (plugin->dbh,
422 "SELECT max(message_id) "
424 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
425 " AND psyc_flags & ?;",
426 &plugin->select_slave_counters);
428 sql_prepare (plugin->dbh,
429 "INSERT OR REPLACE INTO state (channel_id, name, value_current) "
430 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
431 &plugin->insert_state_current);
433 sql_prepare (plugin->dbh,
435 "SET value_current = ? "
436 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
438 &plugin->update_state_current);
440 sql_prepare (plugin->dbh,
442 "SET value_signed = value_current "
443 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) ",
444 &plugin->update_state_signed);
446 sql_prepare (plugin->dbh,
447 "INSERT INTO state_sync (channel_id, name, value) "
448 "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
449 &plugin->insert_state_sync);
451 sql_prepare (plugin->dbh,
453 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
454 &plugin->delete_state);
456 sql_prepare (plugin->dbh,
458 " (channel_id, name, value_current, value_signed) "
459 "SELECT channel_id, name, value, value "
461 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
462 &plugin->insert_state_from_sync);
464 sql_prepare (plugin->dbh,
465 "DELETE FROM state_sync "
466 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);",
467 &plugin->delete_state_sync);
469 sql_prepare (plugin->dbh,
470 "SELECT value_current "
472 "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?) "
474 &plugin->select_state_one);
476 sql_prepare (plugin->dbh,
477 "SELECT value_current "
479 "WHERE name LIKE ? OR name LIKE ?;",
480 &plugin->select_state_prefix);
487 * Shutdown database connection and associate data
489 * @param plugin the plugin context (state for this module)
492 database_shutdown (struct Plugin *plugin)
497 if (NULL != plugin->insert_channel_key)
498 sqlite3_finalize (plugin->insert_channel_key);
500 if (NULL != plugin->insert_slave_key)
501 sqlite3_finalize (plugin->insert_slave_key);
503 if (NULL != plugin->insert_membership)
504 sqlite3_finalize (plugin->insert_membership);
506 if (NULL != plugin->select_membership)
507 sqlite3_finalize (plugin->select_membership);
509 if (NULL != plugin->insert_fragment)
510 sqlite3_finalize (plugin->insert_fragment);
512 if (NULL != plugin->update_fragment_flags)
513 sqlite3_finalize (plugin->update_fragment_flags);
515 if (NULL != plugin->select_fragment)
516 sqlite3_finalize (plugin->select_fragment);
518 if (NULL != plugin->select_message)
519 sqlite3_finalize (plugin->select_message);
521 if (NULL != plugin->select_message_fragment)
522 sqlite3_finalize (plugin->select_message_fragment);
524 if (NULL != plugin->select_master_counters)
525 sqlite3_finalize (plugin->select_master_counters);
527 if (NULL != plugin->select_slave_counters)
528 sqlite3_finalize (plugin->select_slave_counters);
530 if (NULL != plugin->insert_state_current)
531 sqlite3_finalize (plugin->insert_state_current);
533 if (NULL != plugin->update_state_current)
534 sqlite3_finalize (plugin->update_state_current);
536 if (NULL != plugin->update_state_signed)
537 sqlite3_finalize (plugin->update_state_signed);
539 if (NULL != plugin->insert_state_sync)
540 sqlite3_finalize (plugin->insert_state_sync);
542 if (NULL != plugin->delete_state)
543 sqlite3_finalize (plugin->delete_state);
545 if (NULL != plugin->insert_state_from_sync)
546 sqlite3_finalize (plugin->insert_state_from_sync);
548 if (NULL != plugin->delete_state_sync)
549 sqlite3_finalize (plugin->delete_state_sync);
551 if (NULL != plugin->select_state_one)
552 sqlite3_finalize (plugin->select_state_one);
554 if (NULL != plugin->select_state_prefix)
555 sqlite3_finalize (plugin->select_state_prefix);
557 result = sqlite3_close (plugin->dbh);
558 if (result == SQLITE_BUSY)
560 LOG (GNUNET_ERROR_TYPE_WARNING,
561 _("Tried to close sqlite without finalizing all prepared statements.\n"));
562 stmt = sqlite3_next_stmt (plugin->dbh, NULL);
565 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
566 "Closing statement %p\n", stmt);
567 result = sqlite3_finalize (stmt);
568 if (result != SQLITE_OK)
569 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
570 "Failed to close statement %p: %d\n", stmt, result);
571 stmt = sqlite3_next_stmt (plugin->dbh, NULL);
573 result = sqlite3_close (plugin->dbh);
575 if (SQLITE_OK != result)
576 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
578 GNUNET_free_non_null (plugin->fn);
583 * Store join/leave events for a PSYC channel in order to be able to answer
584 * membership test queries later.
586 * @see GNUNET_PSYCSTORE_membership_store()
588 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
591 libgnunet_plugin_psycstore_sqlite_membership_store
593 const struct GNUNET_HashCode *channel_key,
594 const struct GNUNET_HashCode *slave_key,
596 uint64_t announced_at,
597 uint64_t effective_since,
598 uint64_t group_generation) {
604 * Test if a member was admitted to the channel at the given message ID.
606 * @see GNUNET_PSYCSTORE_membership_test()
608 * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
609 * #GNUNET_SYSERR if there was en error.
612 libgnunet_plugin_psycstore_sqlite_membership_test
614 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
615 const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
617 uint64_t group_generation) {
622 * Store a message fragment sent to a channel.
624 * @see GNUNET_PSYCSTORE_fragment_store()
626 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
629 libgnunet_plugin_psycstore_sqlite_fragment_store
631 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
632 const struct GNUNET_MULTICAST_MessageHeader *message) {
637 * Set additional flags for a given message.
639 * @param message_id ID of the message.
640 * @param flags Flags to add.
642 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
645 libgnunet_plugin_psycstore_sqlite_fragment_add_flags
647 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
649 uint64_t multicast_flags,
650 uint64_t psyc_flags) {
655 * Retrieve a message fragment by fragment ID.
657 * @see GNUNET_PSYCSTORE_fragment_get()
659 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
662 libgnunet_plugin_psycstore_sqlite_fragment_get
664 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
665 uint64_t fragment_id,
666 GNUNET_PSYCSTORE_FragmentCallback cb,
672 * Retrieve all fragments of a message.
674 * @see GNUNET_PSYCSTORE_message_get()
676 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
679 libgnunet_plugin_psycstore_sqlite_message_get
681 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
683 GNUNET_PSYCSTORE_FragmentCallback cb,
689 * Retrieve a fragment of message specified by its message ID and fragment
692 * @see GNUNET_PSYCSTORE_message_get_fragment()
694 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
697 libgnunet_plugin_psycstore_sqlite_message_get_fragment
699 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
701 uint64_t fragment_offset,
702 GNUNET_PSYCSTORE_FragmentCallback cb,
709 * Retrieve latest values of counters for a channel master.
711 * @see GNUNET_PSYCSTORE_counters_get_master()
713 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
716 libgnunet_plugin_psycstore_sqlite_counters_get_master
718 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
719 uint64_t *fragment_id,
720 uint64_t *message_id,
721 uint64_t *group_generation)
727 * Retrieve latest values of counters for a channel slave.
729 * @see GNUNET_PSYCSTORE_counters_get_slave()
731 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
734 libgnunet_plugin_psycstore_sqlite_counters_get_slave
736 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
737 uint64_t *max_state_msg_id) {
742 * Set a state variable to the given value.
744 * @see GNUNET_PSYCSTORE_state_modify()
746 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
749 libgnunet_plugin_psycstore_sqlite_state_set
750 (struct GNUNET_PSYCSTORE_Handle *h,
751 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
759 * Retrieve a state variable by name.
761 * @param name Name of the variable to retrieve.
762 * @param[out] value_size Size of value.
763 * @param[out] value Returned value.
765 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
768 libgnunet_plugin_psycstore_sqlite_state_get
769 (struct GNUNET_PSYCSTORE_Handle *h,
770 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
772 GNUNET_PSYCSTORE_StateCallback cb,
778 * Retrieve all state variables for a channel with the given prefix.
780 * @see GNUNET_PSYCSTORE_state_get_all()
782 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
785 libgnunet_plugin_psycstore_sqlite_state_get_all
786 (struct GNUNET_PSYCSTORE_Handle *h,
787 const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
789 GNUNET_PSYCSTORE_StateCallback cb,
796 * Entry point for the plugin.
798 * @param cls the "struct GNUNET_PSYCSTORE_PluginEnvironment*"
799 * @return NULL on error, otherwise the plugin context
802 libgnunet_plugin_psycstore_sqlite_init (void *cls)
804 static struct Plugin plugin;
805 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
806 struct GNUNET_PSYCSTORE_PluginFunctions *api;
808 if (NULL != plugin.cfg)
809 return NULL; /* can only initialize once! */
810 memset (&plugin, 0, sizeof (struct Plugin));
812 if (GNUNET_OK != database_setup (&plugin))
814 database_shutdown (&plugin);
817 api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions);
819 api->membership_store = &libgnunet_plugin_psycstore_sqlite_membership_store;
820 api->membership_test = &libgnunet_plugin_psycstore_sqlite_membership_test;
821 api->fragment_store = &libgnunet_plugin_psycstore_sqlite_fragment_store;
822 api->fragment_add_flags = &libgnunet_plugin_psycstore_sqlite_fragment_add_flags;
823 api->fragment_get = &libgnunet_plugin_psycstore_sqlite_fragment_get;
824 api->message_get = &libgnunet_plugin_psycstore_sqlite_message_get;
825 api->message_get_fragment = &libgnunet_plugin_psycstore_sqlite_message_get_fragment;
826 api->counters_get_master = &libgnunet_plugin_psycstore_sqlite_counters_get_master;
827 api->counters_get_slave = &libgnunet_plugin_psycstore_sqlite_counters_get_slave;
828 api->state_set = &libgnunet_plugin_psycstore_sqlite_state_set;
829 api->state_get = &libgnunet_plugin_psycstore_sqlite_state_get;
830 api->state_get_all = &libgnunet_plugin_psycstore_sqlite_state_get_all;
832 LOG (GNUNET_ERROR_TYPE_INFO,
833 _("Sqlite database running\n"));
839 * Exit point from the plugin.
841 * @param cls the plugin context (as returned by "init")
842 * @return always NULL
845 libgnunet_plugin_psycstore_sqlite_done (void *cls)
847 struct GNUNET_PSYCSTORE_PluginFunctions *api = cls;
848 struct Plugin *plugin = api->cls;
850 database_shutdown (plugin);
853 LOG (GNUNET_ERROR_TYPE_DEBUG,
854 "sqlite plugin is finished\n");
858 /* end of plugin_psycstore_sqlite.c */