X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fpeerstore%2Fplugin_peerstore_sqlite.c;h=898db2231a9e35fe7b8911dd70d318f9aecffc00;hb=e3cb893de32c0d29528283fe2a4644994dc2ba8a;hp=4598bbf241ae966b8bc08d2ce3e6777b265fefcf;hpb=d743a7e758a4fd96f5997a2b6d0f2ce4d62e13cf;p=oweals%2Fgnunet.git diff --git a/src/peerstore/plugin_peerstore_sqlite.c b/src/peerstore/plugin_peerstore_sqlite.c index 4598bbf24..898db2231 100644 --- a/src/peerstore/plugin_peerstore_sqlite.c +++ b/src/peerstore/plugin_peerstore_sqlite.c @@ -1,32 +1,34 @@ /* * This file is part of GNUnet - * (C) 2013 Christian Grothoff (and other contributing authors) + * Copyright (C) 2013, 2017 GNUnet e.V. * - * GNUnet is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 3, or (at your - * option) any later version. + * GNUnet is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Affero General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNUnet; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later */ /** * @file peerstore/plugin_peerstore_sqlite.c * @brief sqlite-based peerstore backend * @author Omar Tarabai + * @author Christian Grothoff */ #include "platform.h" #include "gnunet_peerstore_plugin.h" #include "gnunet_peerstore_service.h" +#include "gnunet_sq_lib.h" #include "peerstore.h" #include @@ -90,157 +92,336 @@ struct Plugin /** * Precompiled SQL for selecting from peerstoredata */ - sqlite3_stmt *select_peerstoredata_by_ss; + sqlite3_stmt *select_peerstoredata_by_key; /** * Precompiled SQL for selecting from peerstoredata */ - sqlite3_stmt *select_peerstoredata_by_both; + sqlite3_stmt *select_peerstoredata_by_all; + + /** + * Precompiled SQL for deleting expired + * records from peerstoredata + */ + sqlite3_stmt *expire_peerstoredata; + + /** + * Precompiled SQL for deleting records + * with given key + */ + sqlite3_stmt *delete_peerstoredata; }; + /** - * The given 'sqlite' statement has been prepared to be run. - * It will return a record which should be given to the iterator. - * Runs the statement and parses the returned record. + * Delete records with the given key * - * @param plugin plugin context - * @param stmt to run (and then clean up) - * @param iter iterator to call with the result - * @param iter_cls closure for @a iter - * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error + * @param cls closure (internal context for the plugin) + * @param sub_system name of sub system + * @param peer Peer identity (can be NULL) + * @param key entry key string (can be NULL) + * @return number of deleted records, #GNUNE_SYSERR on error */ static int -get_record_and_call_iterator (struct Plugin *plugin, - sqlite3_stmt *stmt, - GNUNET_PEERSTORE_RecordIterator iter, void *iter_cls) +peerstore_sqlite_delete_records (void *cls, + const char *sub_system, + const struct GNUNET_PeerIdentity *peer, + const char *key) { + struct Plugin *plugin = cls; + sqlite3_stmt *stmt = plugin->delete_peerstoredata; + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_string (sub_system), + GNUNET_SQ_query_param_auto_from_type (peer), + GNUNET_SQ_query_param_string (key), + GNUNET_SQ_query_param_end + }; int ret; - int sret; - struct GNUNET_PeerIdentity *pid; - char *sub_system; - void *value; - size_t value_size; - ret = GNUNET_NO; - if (SQLITE_ROW == (sret = sqlite3_step (stmt))) + if (GNUNET_OK != + GNUNET_SQ_bind (stmt, + params)) { - pid = sqlite3_column_blob(stmt, 0); - sub_system = sqlite3_column_text(stmt, 1); - value = sqlite3_column_blob(stmt, 2); - value_size = sqlite3_column_bytes(stmt, 2); - if (NULL != iter) - iter (iter_cls, pid, sub_system, value, value_size); - ret = GNUNET_YES; + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind"); + GNUNET_SQ_reset (plugin->dbh, + stmt); + return GNUNET_SYSERR; + } + if (SQLITE_DONE != + sqlite3_step (stmt)) + { + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + ret = GNUNET_SYSERR; } else { - if (SQLITE_DONE != sret) - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); + ret = sqlite3_changes (plugin->dbh); } - if (SQLITE_OK != sqlite3_reset (stmt)) - LOG_SQLITE (plugin, - GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_reset"); + GNUNET_SQ_reset (plugin->dbh, + stmt); return ret; +} + +/** + * Delete expired records (expiry < now) + * + * @param cls closure (internal context for the plugin) + * @param now time to use as reference + * @param cont continuation called with the number of records expired + * @param cont_cls continuation closure + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and cont is not + * called + */ +static int +peerstore_sqlite_expire_records (void *cls, struct GNUNET_TIME_Absolute now, + GNUNET_PEERSTORE_Continuation cont, + void *cont_cls) +{ + struct Plugin *plugin = cls; + sqlite3_stmt *stmt = plugin->expire_peerstoredata; + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_absolute_time (&now), + GNUNET_SQ_query_param_end + }; + + if (GNUNET_OK != + GNUNET_SQ_bind (stmt, + params)) + { + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind"); + GNUNET_SQ_reset (plugin->dbh, + stmt); + return GNUNET_SYSERR; + } + if (SQLITE_DONE != sqlite3_step (stmt)) + { + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); + GNUNET_SQ_reset (plugin->dbh, + stmt); + return GNUNET_SYSERR; + } + if (NULL != cont) + cont (cont_cls, + sqlite3_changes (plugin->dbh)); + GNUNET_SQ_reset (plugin->dbh, + stmt); + return GNUNET_OK; } + /** * Iterate over the records given an optional peer id - * and/or sub system. + * and/or key. * * @param cls closure (internal context for the plugin) + * @param sub_system name of sub system * @param peer Peer identity (can be NULL) - * @param sub_system name of sub system (can be NULL) - * @param iter function to call with the result + * @param key entry key string (can be NULL) + * @param iter function to call asynchronously with the results, terminated + * by a NULL result * @param iter_cls closure for @a iter - * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and iter is not + * called */ static int peerstore_sqlite_iterate_records (void *cls, - const struct GNUNET_PeerIdentity *peer, - const char *sub_system, - GNUNET_PEERSTORE_RecordIterator iter, void *iter_cls) + const char *sub_system, + const struct GNUNET_PeerIdentity *peer, + const char *key, + GNUNET_PEERSTORE_Processor iter, + void *iter_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; - int err; + int err = 0; + int sret; + struct GNUNET_PEERSTORE_Record rec; - if(NULL == sub_system && NULL == peer) - stmt = plugin->select_peerstoredata; - else if(NULL == sub_system) - { - stmt = plugin->select_peerstoredata_by_pid; - err = (SQLITE_OK != sqlite3_bind_blob(stmt, 1, peer, sizeof(struct GNUNET_PeerIdentity), SQLITE_STATIC)); - } - else if(NULL == peer) + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Executing iterate request on sqlite db.\n"); + if (NULL == peer) { - stmt = plugin->select_peerstoredata_by_ss; - err = (SQLITE_OK != sqlite3_bind_text(stmt, 1, sub_system, strlen(sub_system) + 1, SQLITE_STATIC)); + if (NULL == key) + { + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_string (sub_system), + GNUNET_SQ_query_param_end + }; + + stmt = plugin->select_peerstoredata; + err = GNUNET_SQ_bind (stmt, + params); + } + else + { + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_string (sub_system), + GNUNET_SQ_query_param_string (key), + GNUNET_SQ_query_param_end + }; + + stmt = plugin->select_peerstoredata_by_key; + err = GNUNET_SQ_bind (stmt, + params); + } } else { - stmt = plugin->select_peerstoredata_by_both; - err = - (SQLITE_OK != sqlite3_bind_blob(stmt, 1, peer, sizeof(struct GNUNET_PeerIdentity), SQLITE_STATIC)) - || (SQLITE_OK != sqlite3_bind_text(stmt, 2, sub_system, strlen(sub_system) + 1, SQLITE_STATIC)); + if (NULL == key) + { + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_string (sub_system), + GNUNET_SQ_query_param_auto_from_type (peer), + GNUNET_SQ_query_param_end + }; + + stmt = plugin->select_peerstoredata_by_pid; + err = GNUNET_SQ_bind (stmt, + params); + } + else + { + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_string (sub_system), + GNUNET_SQ_query_param_auto_from_type (peer), + GNUNET_SQ_query_param_string (key), + GNUNET_SQ_query_param_end + }; + + stmt = plugin->select_peerstoredata_by_all; + err = GNUNET_SQ_bind (stmt, + params); + } } - if (err) + if (GNUNET_OK != err) { - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_bind_XXXX"); - if (SQLITE_OK != sqlite3_reset (stmt)) - LOG_SQLITE (plugin, - GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_reset"); + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind_XXXX"); + GNUNET_SQ_reset (plugin->dbh, + stmt); return GNUNET_SYSERR; } - return get_record_and_call_iterator (plugin, stmt, iter, iter_cls); + + err = 0; + while (SQLITE_ROW == (sret = sqlite3_step (stmt))) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Returning a matched record.\n"); + struct GNUNET_SQ_ResultSpec rs[] = { + GNUNET_SQ_result_spec_string (&rec.sub_system), + GNUNET_SQ_result_spec_auto_from_type (&rec.peer), + GNUNET_SQ_result_spec_string (&rec.key), + GNUNET_SQ_result_spec_variable_size (&rec.value, &rec.value_size), + GNUNET_SQ_result_spec_absolute_time (&rec.expiry), + GNUNET_SQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_SQ_extract_result (stmt, + rs)) + { + GNUNET_break (0); + break; + } + if (NULL != iter) + iter (iter_cls, + &rec, + NULL); + GNUNET_SQ_cleanup_result (rs); + } + if (SQLITE_DONE != sret) + { + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR, + "sqlite_step"); + err = 1; + } + GNUNET_SQ_reset (plugin->dbh, + stmt); + if (NULL != iter) + iter (iter_cls, + NULL, + err ? "sqlite error" : NULL); + return GNUNET_OK; } + /** * Store a record in the peerstore. * Key is the combination of sub system and peer identity. * One key can store multiple values. * * @param cls closure (internal context for the plugin) - * @param peer peer identity * @param sub_system name of the GNUnet sub system responsible + * @param peer peer identity + * @param key record key string * @param value value to be stored * @param size size of value to be stored - * @return #GNUNET_OK on success, else #GNUNET_SYSERR + * @param expiry absolute time after which the record is (possibly) deleted + * @param options options related to the store operation + * @param cont continuation called when record is stored + * @param cont_cls continuation closure + * @return #GNUNET_OK on success, else #GNUNET_SYSERR and cont is not called */ static int peerstore_sqlite_store_record (void *cls, - const struct GNUNET_PeerIdentity *peer, - const char *sub_system, - const void *value, - size_t size) + const char *sub_system, + const struct GNUNET_PeerIdentity *peer, + const char *key, + const void *value, + size_t size, + struct GNUNET_TIME_Absolute expiry, + enum GNUNET_PEERSTORE_StoreOption options, + GNUNET_PEERSTORE_Continuation cont, + void *cont_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->insert_peerstoredata; - - //FIXME: check if value exists with the same key first - - if(SQLITE_OK != sqlite3_bind_blob(stmt, 1, peer, sizeof(struct GNUNET_PeerIdentity), SQLITE_STATIC) - || SQLITE_OK != sqlite3_bind_text(stmt, 2, sub_system, strlen(sub_system) + 1, SQLITE_STATIC) - || SQLITE_OK != sqlite3_bind_blob(stmt, 3, value, size, SQLITE_STATIC)) - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_bind"); - else if (SQLITE_DONE != sqlite3_step (stmt)) + struct GNUNET_SQ_QueryParam params[] = { + GNUNET_SQ_query_param_string (sub_system), + GNUNET_SQ_query_param_auto_from_type (peer), + GNUNET_SQ_query_param_string (key), + GNUNET_SQ_query_param_fixed_size (value, size), + GNUNET_SQ_query_param_absolute_time (&expiry), + GNUNET_SQ_query_param_end + }; + + if (GNUNET_PEERSTORE_STOREOPTION_REPLACE == options) { - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_step"); + peerstore_sqlite_delete_records (cls, + sub_system, + peer, + key); } - if (SQLITE_OK != sqlite3_reset (stmt)) + if (GNUNET_OK != + GNUNET_SQ_bind (stmt, + params)) + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_bind"); + else if (SQLITE_DONE != sqlite3_step (stmt)) { - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "sqlite3_reset"); - return GNUNET_SYSERR; + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, + "sqlite3_step"); } - + GNUNET_SQ_reset (plugin->dbh, + stmt); + if (NULL != cont) + cont (cont_cls, + GNUNET_OK); return GNUNET_OK; } @@ -253,20 +434,29 @@ peerstore_sqlite_store_record (void *cls, * @return 0 on success */ static int -sql_exec (sqlite3 *dbh, const char *sql) +sql_exec (sqlite3 *dbh, + const char *sql) { int result; - result = sqlite3_exec (dbh, sql, NULL, NULL, NULL); + result = sqlite3_exec (dbh, + sql, + NULL, + NULL, + NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Executed `%s' / %d\n", sql, result); - if (result != SQLITE_OK) + "Executed `%s' / %d\n", + sql, + result); + if (SQLITE_OK != result) LOG (GNUNET_ERROR_TYPE_ERROR, - _("Error executing SQL query: %s\n %s\n"), - sqlite3_errmsg (dbh), sql); + _("Error executing SQL query: %s\n %s\n"), + sqlite3_errmsg (dbh), + sql); return result; } + /** * @brief Prepare a SQL statement * @@ -276,29 +466,39 @@ sql_exec (sqlite3 *dbh, const char *sql) * @return 0 on success */ static int -sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt) +sql_prepare (sqlite3 *dbh, + const char *sql, + sqlite3_stmt ** stmt) { char *tail; int result; - result = sqlite3_prepare_v2 (dbh, sql, strlen (sql), stmt, + result = sqlite3_prepare_v2 (dbh, + sql, + strlen (sql), + stmt, (const char **) &tail); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Prepared `%s' / %p: %d\n", sql, *stmt, result); - if (result != SQLITE_OK) + "Prepared `%s' / %p: %d\n", + sql, + *stmt, + result); + if (SQLITE_OK != result) LOG (GNUNET_ERROR_TYPE_ERROR, - _("Error preparing SQL query: %s\n %s\n"), - sqlite3_errmsg (dbh), sql); + _("Error preparing SQL query: %s\n %s\n"), + sqlite3_errmsg (dbh), + sql); return result; } + /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param plugin the plugin context (state for this module) - * @return GNUNET_OK on success + * @return #GNUNET_OK on success */ static int database_setup (struct Plugin *plugin) @@ -306,11 +506,14 @@ database_setup (struct Plugin *plugin) char *filename; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "peerstore-sqlite", - "FILENAME", &filename)) + GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, + "peerstore-sqlite", + "FILENAME", + &filename)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "peerstore-sqlite", "FILENAME"); + "peerstore-sqlite", + "FILENAME"); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_DISK_file_test (filename)) @@ -324,56 +527,88 @@ database_setup (struct Plugin *plugin) } /* filename should be UTF-8-encoded. If it isn't, it's a bug */ plugin->fn = filename; - /* Open database and precompile statements */ - if (SQLITE_OK != sqlite3_open (plugin->fn, &plugin->dbh)) + if (SQLITE_OK != sqlite3_open (plugin->fn, + &plugin->dbh)) { LOG (GNUNET_ERROR_TYPE_ERROR, - _("Unable to initialize SQLite: %s.\n"), - sqlite3_errmsg (plugin->dbh)); + _("Unable to initialize SQLite: %s.\n"), + sqlite3_errmsg (plugin->dbh)); return GNUNET_SYSERR; } - - sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY"); - sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL"); - sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF"); - sql_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL"); - sql_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\""); - sql_exec (plugin->dbh, "PRAGMA count_changes=OFF"); - sql_exec (plugin->dbh, "PRAGMA page_size=4096"); - - sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS); - + sql_exec (plugin->dbh, + "PRAGMA temp_store=MEMORY"); + sql_exec (plugin->dbh, + "PRAGMA synchronous=OFF"); + sql_exec (plugin->dbh, + "PRAGMA legacy_file_format=OFF"); + sql_exec (plugin->dbh, + "PRAGMA auto_vacuum=INCREMENTAL"); + sql_exec (plugin->dbh, + "PRAGMA encoding=\"UTF-8\""); + sql_exec (plugin->dbh, + "PRAGMA page_size=4096"); + sqlite3_busy_timeout (plugin->dbh, + BUSY_TIMEOUT_MS); /* Create tables */ - sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS peerstoredata (\n" - " peer_id BLOB NOT NULL,\n" " sub_system TEXT NOT NULL,\n" - " value BLOB NULL" - ");"); - + " peer_id BLOB NOT NULL,\n" + " key TEXT NOT NULL,\n" + " value BLOB NULL,\n" + " expiry INT8 NOT NULL" ");"); + /* Create Indices */ + if (SQLITE_OK != + sqlite3_exec (plugin->dbh, + "CREATE INDEX IF NOT EXISTS peerstoredata_key_index ON peerstoredata (sub_system, peer_id, key)", + NULL, + NULL, + NULL)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Unable to create indices: %s.\n"), + sqlite3_errmsg (plugin->dbh)); + return GNUNET_SYSERR; + } /* Prepare statements */ sql_prepare (plugin->dbh, - "INSERT INTO peerstoredata (peer_id, sub_system, value) VALUES (?,?,?);", - &plugin->insert_peerstoredata); - sql_prepare(plugin->dbh, - "SELECT peer_id, sub_system, value FROM peerstoredata", - &plugin->select_peerstoredata); - sql_prepare(plugin->dbh, - "SELECT peer_id, sub_system, value FROM peerstoredata WHERE peer_id = ?", - &plugin->select_peerstoredata_by_pid); - sql_prepare(plugin->dbh, - "SELECT peer_id, sub_system, value FROM peerstoredata WHERE sub_system = ?", - &plugin->select_peerstoredata_by_ss); - sql_prepare(plugin->dbh, - "SELECT peer_id, sub_system, value FROM peerstoredata WHERE peer_id = ? AND sub_system = ?", - &plugin->select_peerstoredata_by_both); - + "INSERT INTO peerstoredata (sub_system, peer_id, key, value, expiry)" + " VALUES (?,?,?,?,?);", + &plugin->insert_peerstoredata); + sql_prepare (plugin->dbh, + "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata" + " WHERE sub_system = ?", + &plugin->select_peerstoredata); + sql_prepare (plugin->dbh, + "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata" + " WHERE sub_system = ?" + " AND peer_id = ?", + &plugin->select_peerstoredata_by_pid); + sql_prepare (plugin->dbh, + "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata" + " WHERE sub_system = ?" + " AND key = ?", + &plugin->select_peerstoredata_by_key); + sql_prepare (plugin->dbh, + "SELECT sub_system,peer_id,key,value,expiry FROM peerstoredata" + " WHERE sub_system = ?" + " AND peer_id = ?" " AND key = ?", + &plugin->select_peerstoredata_by_all); + sql_prepare (plugin->dbh, + "DELETE FROM peerstoredata" + " WHERE expiry < ?", + &plugin->expire_peerstoredata); + sql_prepare (plugin->dbh, + "DELETE FROM peerstoredata" + " WHERE sub_system = ?" + " AND peer_id = ?" " AND key = ?", + &plugin->delete_peerstoredata); return GNUNET_OK; } + /** * Shutdown database connection and associate data * structures. @@ -384,19 +619,25 @@ database_shutdown (struct Plugin *plugin) { int result; sqlite3_stmt *stmt; - while (NULL != (stmt = sqlite3_next_stmt (plugin->dbh, NULL))) + + while (NULL != (stmt = sqlite3_next_stmt (plugin->dbh, + NULL))) { result = sqlite3_finalize (stmt); if (SQLITE_OK != result) LOG (GNUNET_ERROR_TYPE_WARNING, - "Failed to close statement %p: %d\n", stmt, result); + "Failed to close statement %p: %d\n", + stmt, + result); } if (SQLITE_OK != sqlite3_close (plugin->dbh)) - LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); - + LOG_SQLITE (plugin, + GNUNET_ERROR_TYPE_ERROR, + "sqlite3_close"); GNUNET_free_non_null (plugin->fn); } + /** * Entry point for the plugin. * @@ -412,7 +653,9 @@ libgnunet_plugin_peerstore_sqlite_init (void *cls) if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); + memset (&plugin, + 0, + sizeof (struct Plugin)); plugin.cfg = cfg; if (GNUNET_OK != database_setup (&plugin)) { @@ -423,10 +666,13 @@ libgnunet_plugin_peerstore_sqlite_init (void *cls) api->cls = &plugin; api->store_record = &peerstore_sqlite_store_record; api->iterate_records = &peerstore_sqlite_iterate_records; - LOG(GNUNET_ERROR_TYPE_DEBUG, "Sqlite plugin is running\n"); + api->expire_records = &peerstore_sqlite_expire_records; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sqlite plugin is running\n"); return api; } + /** * Exit point from the plugin. * @@ -442,9 +688,9 @@ libgnunet_plugin_peerstore_sqlite_done (void *cls) database_shutdown (plugin); plugin->cfg = NULL; GNUNET_free (api); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Sqlite plugin is finished\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sqlite plugin is finished\n"); return NULL; - } /* end of plugin_peerstore_sqlite.c */