[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r28896 - in gnunet/src: include psycstore
From: |
gnunet |
Subject: |
[GNUnet-SVN] r28896 - in gnunet/src: include psycstore |
Date: |
Thu, 29 Aug 2013 17:14:17 +0200 |
Author: tg
Date: 2013-08-29 17:14:17 +0200 (Thu, 29 Aug 2013)
New Revision: 28896
Added:
gnunet/src/include/gnunet_psycstore_plugin.h
gnunet/src/psycstore/plugin_psycstore_sqlite.c
Modified:
gnunet/src/include/gnunet_protocols.h
gnunet/src/include/gnunet_psycstore_service.h
gnunet/src/psycstore/Makefile.am
gnunet/src/psycstore/gnunet-service-psycstore.c
gnunet/src/psycstore/psycstore.conf
gnunet/src/psycstore/psycstore_api.c
Log:
psycstore: sqlite plugin
Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h 2013-08-29 10:01:15 UTC (rev
28895)
+++ gnunet/src/include/gnunet_protocols.h 2013-08-29 15:14:17 UTC (rev
28896)
@@ -1944,8 +1944,18 @@
*/
#define GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE 650
+/**
+ * Store a membership event.
+ */
+#define GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE 651
/**
+ * Test for membership of a member at a particular point in time.
+ */
+#define GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST 652
+
+
+/**
* Next available: 670
*/
Added: gnunet/src/include/gnunet_psycstore_plugin.h
===================================================================
--- gnunet/src/include/gnunet_psycstore_plugin.h
(rev 0)
+++ gnunet/src/include/gnunet_psycstore_plugin.h 2013-08-29 15:14:17 UTC
(rev 28896)
@@ -0,0 +1,237 @@
+/*
+ This file is part of GNUnet
+ (C) 2012, 2013 Christian Grothoff (and other contributing authors)
+
+ 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 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.
+
+ 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.
+*/
+
+/**
+ * @file include/gnunet_psycstore_plugin.h
+ * @brief plugin API for the PSYCstore database backend
+ * @author Gabor X Toth
+ */
+#ifndef GNUNET_PSYCSTORE_PLUGIN_H
+#define GNUNET_PSYCSTORE_PLUGIN_H
+
+#include "gnunet_common.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_psycstore_service.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct GNUNET_PSYCSTORE_PluginFunctions
+{
+
+ /**
+ * Closure to pass to all plugin functions.
+ */
+ void *cls;
+
+ /**
+ * Store join/leave events for a PSYC channel in order to be able to answer
+ * membership test queries later.
+ *
+ * @see GNUNET_PSYCSTORE_membership_store()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*membership_store) (void *cls,
+ const struct GNUNET_HashCode *channel_key,
+ const struct GNUNET_HashCode *slave_key,
+ int did_join,
+ uint64_t announced_at,
+ uint64_t effective_since,
+ uint64_t group_generation);
+
+ /**
+ * Test if a member was admitted to the channel at the given message ID.
+ *
+ * @see GNUNET_PSYCSTORE_membership_test()
+ *
+ * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
+ * #GNUNET_SYSERR if there was en error.
+ */
+ int
+ (*membership_test) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
+ uint64_t message_id,
+ uint64_t group_generation);
+
+ /**
+ * Store a message fragment sent to a channel.
+ *
+ * @see GNUNET_PSYCSTORE_fragment_store()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*fragment_store) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const struct GNUNET_MULTICAST_MessageHeader *message);
+
+ /**
+ * Set additional flags for a given message.
+ *
+ * @param message_id ID of the message.
+ * @param flags Flags to add.
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*fragment_add_flags) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t message_id,
+ uint64_t multicast_flags,
+ uint64_t psyc_flags);
+
+ /**
+ * Retrieve a message fragment by fragment ID.
+ *
+ * @see GNUNET_PSYCSTORE_fragment_get()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*fragment_get) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t fragment_id,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls);
+
+ /**
+ * Retrieve all fragments of a message.
+ *
+ * @see GNUNET_PSYCSTORE_message_get()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*message_get) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t message_id,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls);
+
+ /**
+ * Retrieve a fragment of message specified by its message ID and fragment
+ * offset.
+ *
+ * @see GNUNET_PSYCSTORE_message_get_fragment()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*message_get_fragment) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey
*channel_key,
+ uint64_t message_id,
+ uint64_t fragment_offset,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls);
+
+ /**
+ * Retrieve latest values of counters for a channel master.
+ *
+ * @see GNUNET_PSYCSTORE_counters_get_master()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*counters_get_master) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t *fragment_id,
+ uint64_t *message_id,
+ uint64_t *group_generation);
+
+ /**
+ * Retrieve latest values of counters for a channel slave.
+ *
+ * @see GNUNET_PSYCSTORE_counters_get_slave()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*counters_get_slave) (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t *max_state_msg_id);
+
+ /**
+ * Set a state variable to the given value.
+ *
+ * @see GNUNET_PSYCSTORE_state_modify()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*state_set) (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const char *name,
+ size_t value_size,
+ const void *value);
+
+ /**
+ * Retrieve a state variable by name.
+ *
+ * @param name Name of the variable to retrieve.
+ * @param[out] value_size Size of value.
+ * @param[out] value Returned value.
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*state_get) (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const char *name,
+ GNUNET_PSYCSTORE_StateCallback cb,
+ void *cb_cls);
+
+ /**
+ * Retrieve all state variables for a channel with the given prefix.
+ *
+ * @see GNUNET_PSYCSTORE_state_get_all()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+ int
+ (*state_get_all) (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const char *name,
+ GNUNET_PSYCSTORE_StateCallback cb,
+ void *cb_cls);
+
+};
+
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* end of gnunet_psycstore_plugin.h */
+#endif
Modified: gnunet/src/include/gnunet_psycstore_service.h
===================================================================
--- gnunet/src/include/gnunet_psycstore_service.h 2013-08-29 10:01:15 UTC
(rev 28895)
+++ gnunet/src/include/gnunet_psycstore_service.h 2013-08-29 15:14:17 UTC
(rev 28896)
@@ -78,43 +78,6 @@
/**
- * Callback used to return the latest value of counters of a channel.
- *
- * @see GNUNET_PSYCSTORE_counters_get()
- *
- * @param *cls Closure.
- * @param fragment_id Latest message fragment ID, used by multicast.
- * @param message_id Latest message ID, used by PSYC.
- * @param group_generation Latest group generation, used by PSYC.
- */
-typedef void
-(*GNUNET_PSYCSTORE_CountersCallback) (void *cls,
- uint64_t fragment_id,
- uint64_t message_id,
- uint64_t group_generation);
-
-
-/**
- * Retrieve latest values of counters for a channel.
- *
- * The current value of counters are needed when a channel master is restarted,
- * so that it can continue incrementing the counters from their last value.
- *
- * @param h Handle for the PSYCstore.
- * @param channel_key Public key that identifies the channel.
- * @param cb Callback to call with the result.
- * @param cb_cls Closure for the callback.
- *
- * @return
- */
-struct GNUNET_PSYCSTORE_OperationHandle *
-GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h,
- struct GNUNET_CRYPTO_EccPublicKey *channel_key,
- GNUNET_PSYCSTORE_CountersCallback *cb,
- void *cb_cls);
-
-
-/**
* Function called with the result of an asynchronous operation.
*
* @param result #GNUNET_SYSERR on error,
@@ -159,9 +122,12 @@
/**
- * Test if a peer was a member of the channel during the given period
specified by the group generation.
+ * Test if a member was admitted to the channel at the given message ID.
*
- * This is useful when relaying and replaying messages to check if a
particular slave has access to the message fragment with a given group
generation. It is also used when handling join requests to determine whether
the slave is currently admitted to the channel.
+ * This is useful when relaying and replaying messages to check if a particular
+ * slave has access to the message fragment with a given group generation. It
+ * is also used when handling join requests to determine whether the slave is
+ * currently admitted to the channel.
*
* @param h Handle for the PSYCstore.
* @param channel_key The channel we are interested in.
@@ -239,7 +205,7 @@
/**
- * Retrieve a message by ID.
+ * Retrieve all fragments of a message.
*
* @param h Handle for the PSYCstore.
* @param channel_key The channel we are interested in.
@@ -258,6 +224,97 @@
/**
+ * Retrieve a fragment of message specified by its message ID and fragment
offset.
+ *
+ * @param h Handle for the PSYCstore.
+ * @param channel_key The channel we are interested in.
+ * @param message_id Message ID to check. Use 0 to get the latest message.
+ * @param fragment_offset Offset of the fragment to retrieve.
+ * @param cb Callback to call with the retrieved fragments.
+ * @param cb_cls Closure for the callback.
+ *
+ * @return Handle that can be used to cancel the operation.
+ */
+struct GNUNET_PSYCSTORE_OperationHandle *
+GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey
*channel_key,
+ uint64_t message_id,
+ uint64_t fragment_offset,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls);
+
+
+/**
+ * Callback used to return the latest value of counters for the channel master.
+ *
+ * @see GNUNET_PSYCSTORE_counters_get_master()
+ *
+ * @param cls Closure.
+ * @param fragment_id Latest message fragment ID, used by multicast.
+ * @param message_id Latest message ID, used by PSYC.
+ * @param group_generation Latest group generation, used by PSYC.
+ */
+typedef void
+(*GNUNET_PSYCSTORE_MasterCountersCallback) (void *cls,
+ uint64_t fragment_id,
+ uint64_t message_id,
+ uint64_t group_generation);
+
+
+/**
+ * Callback used to return the latest value of counters for a channel slave.
+ *
+ * @see GNUNET_PSYCSTORE_counters_get_slave()
+ *
+ * @param cls Closure.
+ * @param max_state_msg_id Latest message ID containing state modifiers that
was applied to the state store. Used for the state sync process.
+ */
+typedef void
+(*GNUNET_PSYCSTORE_SlaveCountersCallback) (void *cls,
+ uint64_t max_state_msg_id);
+
+
+/**
+ * Retrieve latest values of counters for a channel master.
+ *
+ * The current value of counters are needed when a channel master is restarted,
+ * so that it can continue incrementing the counters from their last value.
+ *
+ * @param h Handle for the PSYCstore.
+ * @param channel_key Public key that identifies the channel.
+ * @param cb Callback to call with the result.
+ * @param cb_cls Closure for the callback.
+ *
+ * @return
+ */
+struct GNUNET_PSYCSTORE_OperationHandle *
+GNUNET_PSYCSTORE_counters_get_master (struct GNUNET_PSYCSTORE_Handle *h,
+ struct GNUNET_CRYPTO_EccPublicKey
*channel_key,
+ GNUNET_PSYCSTORE_MasterCountersCallback
*cb,
+ void *cb_cls);
+
+
+/**
+ * Retrieve latest values of counters for a channel slave.
+ *
+ * The current value of counters are needed when a channel slave rejoins
+ * and starts the state synchronization process.
+ *
+ * @param h Handle for the PSYCstore.
+ * @param channel_key Public key that identifies the channel.
+ * @param cb Callback to call with the result.
+ * @param cb_cls Closure for the callback.
+ *
+ * @return
+ */
+struct GNUNET_PSYCSTORE_OperationHandle *
+GNUNET_PSYCSTORE_counters_get_slave (struct GNUNET_PSYCSTORE_Handle *h,
+ struct GNUNET_CRYPTO_EccPublicKey
*channel_key,
+ GNUNET_PSYCSTORE_SlaveCountersCallback
*cb,
+ void *cb_cls);
+
+
+/**
* Apply modifiers of a message to the current channel state.
*
* An error is returned if there are missing messages containing state
Modified: gnunet/src/psycstore/Makefile.am
===================================================================
--- gnunet/src/psycstore/Makefile.am 2013-08-29 10:01:15 UTC (rev 28895)
+++ gnunet/src/psycstore/Makefile.am 2013-08-29 15:14:17 UTC (rev 28896)
@@ -1,7 +1,17 @@
INCLUDES = -I$(top_srcdir)/src/include
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfg_DATA = \
+ psycstore.conf
+
+
if MINGW
- WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
endif
if USE_COVERAGE
@@ -9,14 +19,13 @@
XLIB = -lgcov
endif
-pkgcfgdir= $(pkgdatadir)/config.d/
+if HAVE_SQLITE
+SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la
+if HAVE_TESTING
+#SQLITE_TESTS = test_plugin_psycstore_sqlite
+endif
+endif
-libexecdir= $(pkglibdir)/libexec/
-
-pkgcfg_DATA = \
- psycstore.conf
-
-
lib_LTLIBRARIES = libgnunetpsycstore.la
libgnunetpsycstore_la_SOURCES = \
@@ -29,30 +38,50 @@
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
-version-info 0:0:0
libgnunetpsycstore_la_DEPENDENCIES = \
- $(top_builddir)/src/util/libgnunetutil.la
+ $(top_builddir)/src/util/libgnunetutil.la
bin_PROGRAMS =
libexec_PROGRAMS = \
- gnunet-service-psycstore
+ gnunet-service-psycstore
gnunet_service_psycstore_SOURCES = \
- gnunet-service-psycstore.c
+ gnunet-service-psycstore.c
gnunet_service_psycstore_LDADD = \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL)
gnunet_service_psycstore_DEPENDENCIES = \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
- $(top_builddir)/src/util/libgnunetutil.la
+ $(top_builddir)/src/util/libgnunetutil.la
+
+plugin_LTLIBRARIES = \
+ $(SQLITE_PLUGIN)
+
+libgnunet_plugin_psycstore_sqlite_la_SOURCES = \
+ plugin_psycstore_sqlite.c
+libgnunet_plugin_psycstore_sqlite_la_LIBADD = \
+ $(top_builddir)/src/psycstore/libgnunetpsycstore.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
+ $(LTLIBINTL)
+libgnunet_plugin_psycstore_sqlite_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+libgnunet_plugin_psycstore_sqlite_la_DEPENDENCIES = \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ libgnunetpsycstore.la
+
+
if HAVE_TESTING
check_PROGRAMS = \
- test_psycstore
+ test_psycstore \
+ $(SQLITE_TESTS)
endif
if ENABLE_TEST_RUN
-TESTS = $(check_PROGRAMS)
+TESTS = $(check_PROGRAMS)
endif
test_psycstore_SOURCES = \
@@ -60,13 +89,13 @@
test_psycstore_LDADD = \
libgnunetpsycstore.la \
$(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la
+ $(top_builddir)/src/util/libgnunetutil.la
test_psycstore_DEPENDENCIES = \
libgnunetpsycstore.la \
$(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la
+ $(top_builddir)/src/util/libgnunetutil.la
EXTRA_DIST = \
- test_psycstore.conf
+ test_psycstore.conf
Modified: gnunet/src/psycstore/gnunet-service-psycstore.c
===================================================================
--- gnunet/src/psycstore/gnunet-service-psycstore.c 2013-08-29 10:01:15 UTC
(rev 28895)
+++ gnunet/src/psycstore/gnunet-service-psycstore.c 2013-08-29 15:14:17 UTC
(rev 28896)
@@ -34,6 +34,7 @@
#include "gnunet_protocols.h"
#include "gnunet_statistics_service.h"
#include "gnunet_psycstore_service.h"
+#include "gnunet_psycstore_plugin.h"
#include "psycstore.h"
@@ -53,11 +54,16 @@
static struct GNUNET_SERVER_NotificationContext *nc;
/**
- * Database file.
+ * Database handle
*/
-static char *db_file;
+static struct GNUNET_PSYCSTORE_PluginFunctions *db;
+/**
+ * Name of the database plugin
+ */
+static char *db_lib_name;
+
/**
* Task run during shutdown.
*
@@ -77,8 +83,9 @@
GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
stats = NULL;
}
- GNUNET_free (db_file);
- db_file = NULL;
+ GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
+ GNUNET_free (db_lib_name);
+ db_lib_name = NULL;
}
@@ -123,7 +130,7 @@
* @param c configuration to use
*/
static void
-run (void *cls,
+run (void *cls,
struct GNUNET_SERVER_Handle *server,
const struct GNUNET_CONFIGURATION_Handle *c)
{
@@ -132,15 +139,30 @@
};
cfg = c;
+
+ /* Loading database plugin */
+ char *database;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "psycstore",
- "DB_FILE",
- &db_file))
+ GNUNET_CONFIGURATION_get_value_string (cfg, "psycstore", "database",
+ &database))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "psycstore",
"DB_FILE");
- GNUNET_SCHEDULER_shutdown ();
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
+ }
+ else
+ {
+ GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_psycstore_%s", database);
+ db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
+ GNUNET_free (database);
+ }
+ if (NULL == db)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not load database backend `%s'\n",
+ db_lib_name);
+ GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
return;
}
+
stats = GNUNET_STATISTICS_create ("psycstore", cfg);
GNUNET_SERVER_add_handlers (server, handlers);
nc = GNUNET_SERVER_notification_context_create (server, 1);
@@ -160,7 +182,7 @@
main (int argc, char *const *argv)
{
return (GNUNET_OK ==
- GNUNET_SERVICE_run (argc, argv, "psycstore",
+ GNUNET_SERVICE_run (argc, argv, "psycstore",
GNUNET_SERVICE_OPTION_NONE,
&run, NULL)) ? 0 : 1;
}
Added: gnunet/src/psycstore/plugin_psycstore_sqlite.c
===================================================================
--- gnunet/src/psycstore/plugin_psycstore_sqlite.c
(rev 0)
+++ gnunet/src/psycstore/plugin_psycstore_sqlite.c 2013-08-29 15:14:17 UTC
(rev 28896)
@@ -0,0 +1,858 @@
+ /*
+ * This file is part of GNUnet
+ * (C) 2009-2013 Christian Grothoff (and other contributing authors)
+ *
+ * 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 distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+t * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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.
+ */
+
+/**
+ * @file psycstore/plugin_psycstore_sqlite.c
+ * @brief sqlite-based psycstore backend
+ * @author Gabor X Toth
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_psycstore_plugin.h"
+#include "gnunet_psycstore_service.h"
+#include "psycstore.h"
+#include <sqlite3.h>
+
+/**
+ * After how many ms "busy" should a DB operation fail for good? A
+ * low value makes sure that we are more responsive to requests
+ * (especially PUTs). A high value guarantees a higher success rate
+ * (SELECTs in iterate can take several seconds despite LIMIT=1).
+ *
+ * The default value of 1s should ensure that users do not experience
+ * huge latencies while at the same time allowing operations to
+ * succeed with reasonable probability.
+ */
+#define BUSY_TIMEOUT_MS 1000
+
+
+/**
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' on file 'filename'
+ * with the message given by strerror(errno).
+ */
+#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)
+
+#define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__)
+
+
+/**
+ * Context for all functions in this plugin.
+ */
+struct Plugin
+{
+
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Database filename.
+ */
+ char *fn;
+
+ /**
+ * Native SQLite database handle.
+ */
+ sqlite3 *dbh;
+
+ /**
+ * Precompiled SQL for channel_key_store()
+ */
+ sqlite3_stmt *insert_channel_key;
+
+ /**
+ * Precompiled SQL for slave_key_store()
+ */
+ sqlite3_stmt *insert_slave_key;
+
+
+ /**
+ * Precompiled SQL for membership_store()
+ */
+ sqlite3_stmt *insert_membership;
+
+ /**
+ * Precompiled SQL for membership_test()
+ */
+ sqlite3_stmt *select_membership;
+
+
+ /**
+ * Precompiled SQL for fragment_store()
+ */
+ sqlite3_stmt *insert_fragment;
+
+ /**
+ * Precompiled SQL for fragment_add_flags()
+ */
+ sqlite3_stmt *update_fragment_flags;
+
+ /**
+ * Precompiled SQL for fragment_get()
+ */
+ sqlite3_stmt *select_fragment;
+
+ /**
+ * Precompiled SQL for message_get()
+ */
+ sqlite3_stmt *select_message;
+
+ /**
+ * Precompiled SQL for message_get_fragment()
+ */
+ sqlite3_stmt *select_message_fragment;
+
+ /**
+ * Precompiled SQL for counters_get_master()
+ */
+ sqlite3_stmt *select_master_counters;
+
+ /**
+ * Precompiled SQL for counters_get_slave()
+ */
+ sqlite3_stmt *select_slave_counters;
+
+
+ /**
+ * Precompiled SQL for state_set()
+ */
+ sqlite3_stmt *insert_state_current;
+
+ /**
+ * Precompiled SQL for state_set()
+ */
+ sqlite3_stmt *update_state_current;
+
+ /**
+ * Precompiled SQL for state_set_signed()
+ */
+ sqlite3_stmt *update_state_signed;
+
+ /**
+ * Precompiled SQL for state_sync()
+ */
+ sqlite3_stmt *insert_state_sync;
+
+ /**
+ * Precompiled SQL for state_sync()
+ */
+ sqlite3_stmt *delete_state;
+
+ /**
+ * Precompiled SQL for state_sync()
+ */
+ sqlite3_stmt *insert_state_from_sync;
+
+ /**
+ * Precompiled SQL for state_sync()
+ */
+ sqlite3_stmt *delete_state_sync;
+
+ /**
+ * Precompiled SQL for state_get()
+ */
+ sqlite3_stmt *select_state_one;
+
+ /**
+ * Precompiled SQL for state_get_all()
+ */
+ sqlite3_stmt *select_state_prefix;
+
+};
+
+
+/**
+ * @brief Prepare a SQL statement
+ *
+ * @param dbh handle to the database
+ * @param sql SQL statement, UTF-8 encoded
+ * @param stmt set to the prepared statement
+ * @return 0 on success
+ */
+static int
+sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt)
+{
+ char *tail;
+ int result;
+
+ 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)
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Error preparing SQL query: %s\n %s\n"),
+ sqlite3_errmsg (dbh), sql);
+ return result;
+}
+
+
+/**
+ * @brief Prepare a SQL statement
+ *
+ * @param dbh handle to the database
+ * @param zSql SQL statement, UTF-8 encoded
+ * @param ppStmt set to the prepared statement
+ * @return 0 on success
+ */
+static int
+sql_exec (sqlite3 *dbh, const char *sql)
+{
+ int result;
+
+ result = sqlite3_exec (dbh, sql, NULL, NULL, NULL);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Executed `%s' / %d\n", sql, result);
+ if (result != SQLITE_OK)
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Error executing 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
+ */
+static int
+database_setup (struct Plugin *plugin)
+{
+ char *filename;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "psycstore-sqlite",
+ "FILENAME", &filename))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "psycstore-sqlite", "FILENAME");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK != GNUNET_DISK_file_test (filename))
+ {
+ if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (filename))
+ {
+ GNUNET_break (0);
+ GNUNET_free (filename);
+ return GNUNET_SYSERR;
+ }
+ }
+ /* filename should be UTF-8-encoded. If it isn't, it's a bug */
+ plugin->fn = filename;
+
+ /* Open database and precompile statements */
+ if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("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 locking_mode=EXCLUSIVE");
+ sql_exec (plugin->dbh, "PRAGMA count_changes=OFF");
+ 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 channels ("
+ " id INTEGER PRIMARY KEY,"
+ " pub_key BLOB UNIQUE"
+ ");");
+
+ sql_exec (plugin->dbh,
+ "CREATE TABLE IF NOT EXISTS slaves ("
+ " id INTEGER PRIMARY KEY,"
+ " pub_key BLOB UNIQUE"
+ ");");
+
+ sql_exec (plugin->dbh,
+ "CREATE TABLE IF NOT EXISTS membership ("
+ " channel_id INTEGER NOT NULL REFERENCES channels(id),"
+ " slave_id INTEGER NOT NULL REFERENCES slaves(id),"
+ " did_join INTEGER NOT NULL,"
+ " announced_at INTEGER NOT NULL,"
+ " effective_since INTEGER NOT NULL,"
+ " group_generation INTEGER NOT NULL"
+ ");");
+ sql_exec (plugin->dbh,
+ "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id "
+ "ON membership (channel_id, slave_id);");
+
+ sql_exec (plugin->dbh,
+ "CREATE TABLE IF NOT EXISTS messages ("
+ " channel_id INTEGER NOT NULL,"
+ " hop_counter INTEGER NOT NULL,"
+ " signature BLOB,"
+ " purpose BLOB,"
+ " fragment_id INTEGER NOT NULL,"
+ " fragment_offset INTEGER NOT NULL,"
+ " message_id INTEGER NOT NULL,"
+ " group_generation INTEGER NOT NULL,"
+ " multicast_flags INTEGER NOT NULL,"
+ " psyc_flags INTEGER NOT NULL,"
+ " data BLOB,"
+ " PRIMARY KEY (channel_id, fragment_id),"
+ " UNIQUE (channel_id, message_id, fragment_offset)"
+ ");");
+
+ sql_exec (plugin->dbh,
+ "CREATE TABLE IF NOT EXISTS state ("
+ " channel_id INTEGER NOT NULL,"
+ " name TEXT NOT NULL,"
+ " value_current BLOB, "
+ " value_signed BLOB, "
+ " PRIMARY KEY (channel_id, name)"
+ ");");
+
+ sql_exec (plugin->dbh,
+ "CREATE TABLE IF NOT EXISTS state_sync ("
+ " channel_id INTEGER NOT NULL,"
+ " name TEXT NOT NULL,"
+ " value BLOB, "
+ " PRIMARY KEY (channel_id, name)"
+ ");");
+
+ /* Prepare statements */
+
+ sql_prepare (plugin->dbh,
+ "INSERT OR IGNORE INTO channels (pub_key) VALUES (?);",
+ &plugin->insert_channel_key);
+
+ sql_prepare (plugin->dbh,
+ "INSERT OR IGNORE INTO slaves (pub_key) VALUES (?);",
+ &plugin->insert_slave_key);
+
+ sql_prepare (plugin->dbh,
+ "INSERT INTO membership "
+ " (channel_id, slave_id, did_join, announced_at, "
+ " effective_since, group_generation) "
+ "VALUES ((SELECT id FROM channels WHERE pub_key = ?), "
+ " (SELECT id FROM slaves WHERE pub_key = ?), "
+ " ?, ?, ?, ?);",
+ &plugin->insert_membership);
+
+ sql_prepare (plugin->dbh,
+ "SELECT did_join FROM membership "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND slave_id = ? AND effective_since <= ? "
+ "ORDER BY announced_at DESC LIMIT 1;",
+ &plugin->select_membership);
+
+ sql_prepare (plugin->dbh,
+ "INSERT INTO messages "
+ " (channel_id, hop_counter, signature, purpose, "
+ " fragment_id, fragment_offset, message_id, "
+ " group_generation, multicast_flags, psyc_flags, data) "
+ "VALUES ((SELECT id FROM channels WHERE pub_key = ?), "
+ " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
+ &plugin->insert_fragment);
+
+ sql_prepare (plugin->dbh,
+ "UPDATE messages "
+ "SET multicast_flags = multicast_flags | ?, "
+ " psyc_flags = psyc_flags | ? "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND message_id = ?;",
+ &plugin->update_fragment_flags);
+
+ sql_prepare (plugin->dbh,
+ "SELECT hop_counter, signature, purpose, "
+ " fragment_offset, message_id, group_generation, "
+ " multicast_flags, psyc_flags, data "
+ "FROM messages "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND fragment_id = ?;",
+ &plugin->select_fragment);
+
+ sql_prepare (plugin->dbh,
+ "SELECT hop_counter, signature, purpose, "
+ " fragment_id, fragment_offset, group_generation, "
+ " multicast_flags, psyc_flags, data "
+ "FROM messages "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND message_id = ?;",
+ &plugin->select_message);
+
+ sql_prepare (plugin->dbh,
+ "SELECT hop_counter, signature, purpose, "
+ " fragment_id, message_id, group_generation, "
+ " multicast_flags, psyc_flags, data "
+ "FROM messages "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND message_id = ? AND fragment_offset = ?;",
+ &plugin->select_message_fragment);
+
+ sql_prepare (plugin->dbh,
+ "SELECT max(fragment_id), max(message_id),
max(group_generation) "
+ "FROM messages "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key =
?);",
+ &plugin->select_master_counters);
+
+ sql_prepare (plugin->dbh,
+ "SELECT max(message_id) "
+ "FROM messages "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND psyc_flags & ?;",
+ &plugin->select_slave_counters);
+
+ sql_prepare (plugin->dbh,
+ "INSERT OR REPLACE INTO state (channel_id, name, value_current)
"
+ "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
+ &plugin->insert_state_current);
+
+ sql_prepare (plugin->dbh,
+ "UPDATE state "
+ "SET value_current = ? "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND name = ?;",
+ &plugin->update_state_current);
+
+ sql_prepare (plugin->dbh,
+ "UPDATE state "
+ "SET value_signed = value_current "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
",
+ &plugin->update_state_signed);
+
+ sql_prepare (plugin->dbh,
+ "INSERT INTO state_sync (channel_id, name, value) "
+ "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);",
+ &plugin->insert_state_sync);
+
+ sql_prepare (plugin->dbh,
+ "DELETE FROM state "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key =
?);",
+ &plugin->delete_state);
+
+ sql_prepare (plugin->dbh,
+ "INSERT INTO state "
+ " (channel_id, name, value_current, value_signed) "
+ "SELECT channel_id, name, value, value "
+ "FROM state_sync "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key =
?);",
+ &plugin->insert_state_from_sync);
+
+ sql_prepare (plugin->dbh,
+ "DELETE FROM state_sync "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key =
?);",
+ &plugin->delete_state_sync);
+
+ sql_prepare (plugin->dbh,
+ "SELECT value_current "
+ "FROM state "
+ "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)
"
+ " AND name = ?;",
+ &plugin->select_state_one);
+
+ sql_prepare (plugin->dbh,
+ "SELECT value_current "
+ "FROM state "
+ "WHERE name LIKE ? OR name LIKE ?;",
+ &plugin->select_state_prefix);
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown database connection and associate data
+ * structures.
+ * @param plugin the plugin context (state for this module)
+ */
+static void
+database_shutdown (struct Plugin *plugin)
+{
+ int result;
+ sqlite3_stmt *stmt;
+
+ if (NULL != plugin->insert_channel_key)
+ sqlite3_finalize (plugin->insert_channel_key);
+
+ if (NULL != plugin->insert_slave_key)
+ sqlite3_finalize (plugin->insert_slave_key);
+
+ if (NULL != plugin->insert_membership)
+ sqlite3_finalize (plugin->insert_membership);
+
+ if (NULL != plugin->select_membership)
+ sqlite3_finalize (plugin->select_membership);
+
+ if (NULL != plugin->insert_fragment)
+ sqlite3_finalize (plugin->insert_fragment);
+
+ if (NULL != plugin->update_fragment_flags)
+ sqlite3_finalize (plugin->update_fragment_flags);
+
+ if (NULL != plugin->select_fragment)
+ sqlite3_finalize (plugin->select_fragment);
+
+ if (NULL != plugin->select_message)
+ sqlite3_finalize (plugin->select_message);
+
+ if (NULL != plugin->select_message_fragment)
+ sqlite3_finalize (plugin->select_message_fragment);
+
+ if (NULL != plugin->select_master_counters)
+ sqlite3_finalize (plugin->select_master_counters);
+
+ if (NULL != plugin->select_slave_counters)
+ sqlite3_finalize (plugin->select_slave_counters);
+
+ if (NULL != plugin->insert_state_current)
+ sqlite3_finalize (plugin->insert_state_current);
+
+ if (NULL != plugin->update_state_current)
+ sqlite3_finalize (plugin->update_state_current);
+
+ if (NULL != plugin->update_state_signed)
+ sqlite3_finalize (plugin->update_state_signed);
+
+ if (NULL != plugin->insert_state_sync)
+ sqlite3_finalize (plugin->insert_state_sync);
+
+ if (NULL != plugin->delete_state)
+ sqlite3_finalize (plugin->delete_state);
+
+ if (NULL != plugin->insert_state_from_sync)
+ sqlite3_finalize (plugin->insert_state_from_sync);
+
+ if (NULL != plugin->delete_state_sync)
+ sqlite3_finalize (plugin->delete_state_sync);
+
+ if (NULL != plugin->select_state_one)
+ sqlite3_finalize (plugin->select_state_one);
+
+ if (NULL != plugin->select_state_prefix)
+ sqlite3_finalize (plugin->select_state_prefix);
+
+ result = sqlite3_close (plugin->dbh);
+ if (result == SQLITE_BUSY)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("Tried to close sqlite without finalizing all prepared
statements.\n"));
+ stmt = sqlite3_next_stmt (plugin->dbh, NULL);
+ while (stmt != NULL)
+ {
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite",
+ "Closing statement %p\n", stmt);
+ result = sqlite3_finalize (stmt);
+ if (result != SQLITE_OK)
+ GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite",
+ "Failed to close statement %p: %d\n", stmt, result);
+ stmt = sqlite3_next_stmt (plugin->dbh, NULL);
+ }
+ result = sqlite3_close (plugin->dbh);
+ }
+ if (SQLITE_OK != result)
+ LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
+
+ GNUNET_free_non_null (plugin->fn);
+}
+
+
+/**
+ * Store join/leave events for a PSYC channel in order to be able to answer
+ * membership test queries later.
+ *
+ * @see GNUNET_PSYCSTORE_membership_store()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_membership_store
+ (void *cls,
+ const struct GNUNET_HashCode *channel_key,
+ const struct GNUNET_HashCode *slave_key,
+ int did_join,
+ uint64_t announced_at,
+ uint64_t effective_since,
+ uint64_t group_generation) {
+
+
+}
+
+/**
+ * Test if a member was admitted to the channel at the given message ID.
+ *
+ * @see GNUNET_PSYCSTORE_membership_test()
+ *
+ * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not,
+ * #GNUNET_SYSERR if there was en error.
+ */
+int
+libgnunet_plugin_psycstore_sqlite_membership_test
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const struct GNUNET_CRYPTO_EccPublicKey *slave_key,
+ uint64_t message_id,
+ uint64_t group_generation) {
+
+}
+
+/**
+ * Store a message fragment sent to a channel.
+ *
+ * @see GNUNET_PSYCSTORE_fragment_store()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_fragment_store
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const struct GNUNET_MULTICAST_MessageHeader *message) {
+
+}
+
+/**
+ * Set additional flags for a given message.
+ *
+ * @param message_id ID of the message.
+ * @param flags Flags to add.
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_fragment_add_flags
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t message_id,
+ uint64_t multicast_flags,
+ uint64_t psyc_flags) {
+
+}
+
+/**
+ * Retrieve a message fragment by fragment ID.
+ *
+ * @see GNUNET_PSYCSTORE_fragment_get()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_fragment_get
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t fragment_id,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls) {
+
+}
+
+/**
+ * Retrieve all fragments of a message.
+ *
+ * @see GNUNET_PSYCSTORE_message_get()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_message_get
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t message_id,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls) {
+
+}
+
+/**
+ * Retrieve a fragment of message specified by its message ID and fragment
+ * offset.
+ *
+ * @see GNUNET_PSYCSTORE_message_get_fragment()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_message_get_fragment
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t message_id,
+ uint64_t fragment_offset,
+ GNUNET_PSYCSTORE_FragmentCallback cb,
+ void *cb_cls)
+{
+
+}
+
+/**
+ * Retrieve latest values of counters for a channel master.
+ *
+ * @see GNUNET_PSYCSTORE_counters_get_master()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_counters_get_master
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t *fragment_id,
+ uint64_t *message_id,
+ uint64_t *group_generation)
+{
+
+}
+
+/**
+ * Retrieve latest values of counters for a channel slave.
+ *
+ * @see GNUNET_PSYCSTORE_counters_get_slave()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_counters_get_slave
+ (void *cls,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ uint64_t *max_state_msg_id) {
+
+}
+
+/**
+ * Set a state variable to the given value.
+ *
+ * @see GNUNET_PSYCSTORE_state_modify()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_state_set
+ (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const char *name,
+ size_t value_size,
+ const void *value) {
+
+}
+
+/**
+ * Retrieve a state variable by name.
+ *
+ * @param name Name of the variable to retrieve.
+ * @param[out] value_size Size of value.
+ * @param[out] value Returned value.
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_state_get
+ (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const char *name,
+ GNUNET_PSYCSTORE_StateCallback cb,
+ void *cb_cls) {
+
+}
+
+/**
+ * Retrieve all state variables for a channel with the given prefix.
+ *
+ * @see GNUNET_PSYCSTORE_state_get_all()
+ *
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+int
+libgnunet_plugin_psycstore_sqlite_state_get_all
+ (struct GNUNET_PSYCSTORE_Handle *h,
+ const struct GNUNET_CRYPTO_EccPublicKey *channel_key,
+ const char *name,
+ GNUNET_PSYCSTORE_StateCallback cb,
+ void *cb_cls) {
+
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_PSYCSTORE_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_psycstore_sqlite_init (void *cls)
+{
+ static struct Plugin plugin;
+ const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct GNUNET_PSYCSTORE_PluginFunctions *api;
+
+ if (NULL != plugin.cfg)
+ return NULL; /* can only initialize once! */
+ memset (&plugin, 0, sizeof (struct Plugin));
+ plugin.cfg = cfg;
+ if (GNUNET_OK != database_setup (&plugin))
+ {
+ database_shutdown (&plugin);
+ return NULL;
+ }
+ api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions);
+ api->cls = &plugin;
+ api->membership_store = &libgnunet_plugin_psycstore_sqlite_membership_store;
+ api->membership_test = &libgnunet_plugin_psycstore_sqlite_membership_test;
+ api->fragment_store = &libgnunet_plugin_psycstore_sqlite_fragment_store;
+ api->fragment_add_flags =
&libgnunet_plugin_psycstore_sqlite_fragment_add_flags;
+ api->fragment_get = &libgnunet_plugin_psycstore_sqlite_fragment_get;
+ api->message_get = &libgnunet_plugin_psycstore_sqlite_message_get;
+ api->message_get_fragment =
&libgnunet_plugin_psycstore_sqlite_message_get_fragment;
+ api->counters_get_master =
&libgnunet_plugin_psycstore_sqlite_counters_get_master;
+ api->counters_get_slave =
&libgnunet_plugin_psycstore_sqlite_counters_get_slave;
+ api->state_set = &libgnunet_plugin_psycstore_sqlite_state_set;
+ api->state_get = &libgnunet_plugin_psycstore_sqlite_state_get;
+ api->state_get_all = &libgnunet_plugin_psycstore_sqlite_state_get_all;
+
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ _("Sqlite database running\n"));
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_psycstore_sqlite_done (void *cls)
+{
+ struct GNUNET_PSYCSTORE_PluginFunctions *api = cls;
+ struct Plugin *plugin = api->cls;
+
+ database_shutdown (plugin);
+ plugin->cfg = NULL;
+ GNUNET_free (api);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "sqlite plugin is finished\n");
+ return NULL;
+}
+
+/* end of plugin_psycstore_sqlite.c */
Modified: gnunet/src/psycstore/psycstore.conf
===================================================================
--- gnunet/src/psycstore/psycstore.conf 2013-08-29 10:01:15 UTC (rev 28895)
+++ gnunet/src/psycstore/psycstore.conf 2013-08-29 15:14:17 UTC (rev 28896)
@@ -5,6 +5,7 @@
UNIXPATH = /tmp/gnunet-service-psycstore.unix
UNIX_MATCH_UID = NO
UNIX_MATCH_GID = YES
+DATABASE = sqlite
-# Path to the SQLite database
-DB_FILE = $SERVICEHOME/psycstore.sqlite
+[psycstore-sqlite]
+FILENAME = $SERVICEHOME/psycstore/sqlite.db
Modified: gnunet/src/psycstore/psycstore_api.c
===================================================================
--- gnunet/src/psycstore/psycstore_api.c 2013-08-29 10:01:15 UTC (rev
28895)
+++ gnunet/src/psycstore/psycstore_api.c 2013-08-29 15:14:17 UTC (rev
28896)
@@ -340,22 +340,8 @@
GNUNET_assert (NULL == h->client);
h->client = GNUNET_CLIENT_connect ("psycstore", h->cfg);
GNUNET_assert (NULL != h->client);
-/*
- struct GNUNET_PSYCSTORE_OperationHandle *op;
- struct GNUNET_MessageHeader msg;
- op = GNUNET_malloc (sizeof (struct GNUNET_PSYCSTORE_OperationHandle) +
- sizeof (struct GNUNET_MessageHeader));
- op->h = h;
- op->msg = (const struct GNUNET_MessageHeader *) &op[1];
- msg.size = htons (sizeof (msg));
- msg.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_START);
- memcpy (&op[1], &msg, sizeof (msg));
- GNUNET_CONTAINER_DLL_insert (h->op_head,
- h->op_tail,
- op);
transmit_next (h);
GNUNET_assert (NULL != h->th);
-*/
}
@@ -379,6 +365,35 @@
/**
+ * Disconnect from PSYCstore service
+ *
+ * @param h handle to destroy
+ */
+void
+GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h)
+{
+ GNUNET_assert (NULL != h);
+ GNUNET_assert (h->op_head == h->op_tail);
+ if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (h->reconnect_task);
+ h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != h->th)
+ {
+ GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+ h->th = NULL;
+ }
+ if (NULL != h->client)
+ {
+ GNUNET_CLIENT_disconnect (h->client);
+ h->client = NULL;
+ }
+ GNUNET_free (h);
+}
+
+
+/**
* Cancel a PSYCstore operation. Note that the operation MAY still
* be executed; this merely cancels the continuation; if the request
* was already transmitted, the service may still choose to complete
@@ -420,32 +435,4 @@
}
-/**
- * Disconnect from PSYCstore service
- *
- * @param h handle to destroy
- */
-void
-GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h)
-{
- GNUNET_assert (NULL != h);
- GNUNET_assert (h->op_head == h->op_tail);
- if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (h->reconnect_task);
- h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (NULL != h->th)
- {
- GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
- h->th = NULL;
- }
- if (NULL != h->client)
- {
- GNUNET_CLIENT_disconnect (h->client);
- h->client = NULL;
- }
- GNUNET_free (h);
-}
-
/* end of psycstore_api.c */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r28896 - in gnunet/src: include psycstore,
gnunet <=