[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r8782 - in gnunet: . src src/datacache src/datastore src/in
From: |
gnunet |
Subject: |
[GNUnet-SVN] r8782 - in gnunet: . src src/datacache src/datastore src/include |
Date: |
Sat, 25 Jul 2009 16:24:42 -0600 |
Author: grothoff
Date: 2009-07-25 16:24:42 -0600 (Sat, 25 Jul 2009)
New Revision: 8782
Added:
gnunet/src/datacache/
gnunet/src/datacache/Makefile.am
gnunet/src/datacache/datacache_api.c
gnunet/src/datacache/plugin_datacache.h
gnunet/src/datacache/plugin_datacache_sqlite.c
gnunet/src/datacache/plugin_datacache_template.c
gnunet/src/datacache/test_datacache_api.c
Modified:
gnunet/TODO
gnunet/configure.ac
gnunet/src/Makefile.am
gnunet/src/datastore/Makefile.am
gnunet/src/datastore/plugin_datastore_template.c
gnunet/src/include/gnunet_datacache_lib.h
Log:
towards datacache implementation
Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2009-07-25 21:32:23 UTC (rev 8781)
+++ gnunet/TODO 2009-07-25 22:24:42 UTC (rev 8782)
@@ -58,7 +58,7 @@
Module features to implement:
-* Dstore (needed for DHT)
+* datacache (needed for DHT)
- design plugin API
- implement sqlite-based dstore plugin
- implement dstore API
Modified: gnunet/configure.ac
===================================================================
--- gnunet/configure.ac 2009-07-25 21:32:23 UTC (rev 8781)
+++ gnunet/configure.ac 2009-07-25 22:24:42 UTC (rev 8782)
@@ -745,6 +745,7 @@
src/Makefile
src/arm/Makefile
src/core/Makefile
+src/datacache/Makefile
src/datastore/Makefile
src/fragmentation/Makefile
src/hello/Makefile
Modified: gnunet/src/Makefile.am
===================================================================
--- gnunet/src/Makefile.am 2009-07-25 21:32:23 UTC (rev 8781)
+++ gnunet/src/Makefile.am 2009-07-25 22:24:42 UTC (rev 8782)
@@ -11,6 +11,8 @@
include $(INTLEMU_SUBDIRS) \
util \
arm \
+ datacache \
+ datastore \
fragmentation \
hello \
peerinfo \
@@ -19,7 +21,6 @@
template \
transport \
core \
- datastore \
$(HOSTLIST_DIR) \
topology
Added: gnunet/src/datacache/Makefile.am
===================================================================
--- gnunet/src/datacache/Makefile.am (rev 0)
+++ gnunet/src/datacache/Makefile.am 2009-07-25 22:24:42 UTC (rev 8782)
@@ -0,0 +1,76 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+if MINGW
+ WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIBS = -lgcov
+endif
+
+
+lib_LTLIBRARIES = \
+ libgnunetdatacache.la
+
+libgnunetdatacache_la_SOURCES = \
+ datacache_api.c plugin_datacache.h
+libgnunetdatacache_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+libgnunetdatacache_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+ -version-info 0:0:0
+
+
+plugin_LTLIBRARIES = \
+ libgnunet_plugin_datacache_sqlite.la \
+ libgnunet_plugin_datacache_template.la
+
+
+libgnunet_plugin_datacache_sqlite_la_SOURCES = \
+ plugin_datacache_sqlite.c
+libgnunet_plugin_datacache_sqlite_la_LIBADD = \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3
+libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_datacache_template_la_SOURCES = \
+ plugin_datacache_template.c
+libgnunet_plugin_datacache_template_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS)
+libgnunet_plugin_datacache_template_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+#check_PROGRAMS = \
+# test_datacache_api \
+# perf_datacache_api \
+# perf_plugin_datacache
+#
+#TESTS = $(check_PROGRAMS)
+#
+#test_datacache_api_SOURCES = \
+# test_datacache_api.c
+#test_datacache_api_LDADD = \
+# $(top_builddir)/src/datacache/libgnunetdatacache.la \
+# $(top_builddir)/src/util/libgnunetutil.la
+#
+#perf_datacache_api_SOURCES = \
+# perf_datacache_api.c
+#perf_datacache_api_LDADD = \
+# $(top_builddir)/src/datacache/libgnunetdatacache.la \
+# $(top_builddir)/src/util/libgnunetutil.la
+#
+#perf_plugin_datacache_SOURCES = \
+# perf_plugin_datacache.c
+#perf_plugin_datacache_LDADD = \
+# $(top_builddir)/src/util/libgnunetutil.la
+#
+#
+#EXTRA_DIST = \
+# test_datacache_api_data.conf \
+# perf_plugin_datacache_data.conf
Added: gnunet/src/datacache/datacache_api.c
===================================================================
--- gnunet/src/datacache/datacache_api.c (rev 0)
+++ gnunet/src/datacache/datacache_api.c 2009-07-25 22:24:42 UTC (rev
8782)
@@ -0,0 +1,261 @@
+/*
+ This file is part of GNUnet
+ (C) 2004, 2005, 2006, 2007, 2009 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 2, 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 datacache/datacache_api.c
+ * @brief datacache API implementation
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_datacache_lib.h"
+#include "plugin_datacache.h"
+
+/**
+ * Internal state of the datacache library.
+ */
+struct GNUNET_DATACACHE_Handle
+{
+
+ /**
+ * Our datastore plugin (NULL if not available).
+ */
+ struct DatastorePlugin *plugin;
+
+ /**
+ * Bloomfilter to quickly tell if we don't have the content.
+ */
+ struct GNUNET_CONTAINER_BloomFilter *filter;
+
+ /**
+ * Our configuration.
+ */
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Configuration section to use.
+ */
+ char *section;
+
+ /**
+ * API of the transport as returned by the plugin's
+ * initialization function.
+ */
+ struct GNUNET_DATACACHE_PluginFunctions *api;
+
+ /**
+ * Short name for the plugin (i.e. "sqlite").
+ */
+ char *short_name;
+
+ /**
+ * Name of the library (i.e. "gnunet_plugin_datacache_sqlite").
+ */
+ char *lib_name;
+
+ /**
+ * Environment provided to our plugin.
+ */
+ struct GNUNET_DATASTORE_PluginEnvironment env;
+
+ /**
+ * How much space is in use right now?
+ */
+ unsigned long long utilization;
+
+};
+
+
+/**
+ * Function called by plugins to notify the datacache
+ * about content deletions.
+ *
+ * @param cls closure
+ * @param key key of the content that was deleted
+ * @param size number of bytes that were made available
+ */
+static void
+env_delete_notify (void *cls,
+ const GNUNET_HashCode *key,
+ uint32_t size)
+{
+ struct GNUNET_DATACACHE_Handle * h = cls;
+ GNUNET_assert (h->utilization >= size);
+ h->utilization -= size;
+ GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
+}
+
+
+/**
+ * Create a data cache.
+ *
+ * @param sched scheduler to use
+ * @param cfg configuration to use
+ * @param section section in the configuration that contains our options
+ * @return handle to use to access the service
+ */
+struct GNUNET_DATACACHE_Handle *
+GNUNET_DATACACHE_create (struct GNUNET_SCHEDULER_Handle *sched,
+ struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section)
+{
+ unsigned int bf_size;
+ struct GNUNET_DATACACHE_Handle *ret;
+ struct DatacachePlugin *ret;
+ char *libname;
+ char *name;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (c,
+ section, "QUOTA", "a))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("No `%s' specified for `%s' in configuration!\n"),
+ "QUOTA",
+ section);
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "DATABASE", &name))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("No `%s' specified for `%s' in configuration!\n"),
+ "DATABASE",
+ section);
+ return NULL;
+ }
+ bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
+
+ ret = GNUNET_malloc (sizeof(struct GNUNET_DATACACHE_Handle));
+ /* FIXME: create a temporary file for the bloomfilter to better
+ support deletions! */
+ ret->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, bf_size, 5); /*
approx. 3% false positives at max use */
+ ret->section = GNUNET_strdup (section);
+ ret->env.sched = s;
+ ret->env.cfg = cfg;
+ ret->env.delete_notify = &env_delete_notify;
+ ret->env.section = ret->section;
+ ret->env.cls = ret;
+ ret->env.delete_notify = &delete_notify;
+ ret->env.quota = quota;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Loading `%s' datacache plugin\n"), name);
+ GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name);
+ ret->short_name = name;
+ ret->lib_name = libname;
+ ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
+ if (ret->api == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to load datacache plugin for `%s'\n"), name);
+ GNUNET_DATACACHE_destroy (ret);
+ return NULL;
+ }
+ return ret;
+}
+
+
+/**
+ * Destroy a data cache (and free associated resources).
+ *
+ * @param h handle to the datastore
+ */
+void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
+{
+ GNUNET_CONTAINER_bloomfilter_free (h->filter);
+ if (h->api != NULL)
+ GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api));
+ GNUNET_free (h->lib_name);
+ GNUNET_free (h->short_name);
+ GNUNET_free (h->section);
+ GNUNET_free (h);
+}
+
+
+/**
+ * Store an item in the datastore.
+ *
+ * @param h handle to the datacache
+ * @param key key to store data under
+ * @param size number of bytes in data
+ * @param data data to store
+ * @param type type of the value
+ * @param discard_time when to discard the value in any case
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.)
+ */
+int
+GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
+ const GNUNET_HashCode * key,
+ uint32_t size,
+ const char *data,
+ unsigned int type,
+ struct GNUNET_TIME_Absolute discard_time)
+{
+ uint32_t used;
+
+ used = h->api->put (h->api->cls,
+ key,
+ size,
+ data,
+ type,
+ discard_time);
+ if (used == 0)
+ return GNUNET_SYSERR;
+ GNUNET_CONTAINER_bloomfilter_add (h->filter, key);
+ while (h->utilization + used > h->api.quota)
+ GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls));
+ h->utilization += used;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Iterate over the results for a particular key
+ * in the datacache.
+ *
+ * @param h handle to the datacache
+ * @param key what to look up
+ * @param type entries of which type are relevant?
+ * @param iter maybe NULL (to just count)
+ * @param iter_cls closure for iter
+ * @return the number of results found
+ */
+unsigned int
+GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
+ const GNUNET_HashCode * key,
+ unsigned int type,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls)
+{
+ if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter,
+ key))
+ return 0; /* can not be present */
+ return h->api->get (h->api->cls,
+ key,
+ type,
+ iter,
+ iter_cls);
+}
+
+
+
+/* end of datacache_api.c */
Added: gnunet/src/datacache/plugin_datacache.h
===================================================================
--- gnunet/src/datacache/plugin_datacache.h (rev 0)
+++ gnunet/src/datacache/plugin_datacache.h 2009-07-25 22:24:42 UTC (rev
8782)
@@ -0,0 +1,159 @@
+/*
+ This file is part of GNUnet
+ (C) 2006, 2009 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 2, 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 datacache/plugin_datacache.h
+ * @brief API for database backends for the datacache
+ * @author Christian Grothoff
+ */
+#ifndef PLUGIN_DATACACHE_H
+#define PLUGIN_DATACACHE_H
+
+#include "gnunet_datacache_lib.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * Function called by plugins to notify the datacache
+ * about content deletions.
+ *
+ * @param cls closure
+ * @param key key of the content that was deleted
+ * @param size number of bytes that were made available
+ */
+typedef void (*GNUNET_DATACACHE_DeleteNotifyCallback)(void *cls,
+ const GNUNET_HashCode
*key,
+ uint32_t size);
+
+
+/**
+ * The datastore service will pass a pointer to a struct
+ * of this type as the first and only argument to the
+ * entry point of each datastore plugin.
+ */
+struct GNUNET_DATACACHE_PluginEnvironment
+{
+
+ /**
+ * Scheduler to use.
+ */
+ struct GNUNET_SCHEDULER_Handle *sched;
+
+ /**
+ * Configuration to use.
+ */
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Configuration section to use.
+ */
+ const char *section;
+
+ /**
+ * Closure to use for callbacks.
+ */
+ void *cls;
+
+ /**
+ * Function to call whenever the plugin needs to
+ * discard content that it was asked to store.
+ */
+ GNUNET_DATACACHE_DeleteNotifyCallback delete_notify;
+
+ /**
+ * How much space are we allowed to use?
+ */
+ unsigned long long quota;
+
+};
+
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct GNUNET_DATACACHE_PluginFunctions {
+
+ /**
+ * Closure to pass to all plugin functions.
+ */
+ void *cls;
+
+ /**
+ * Store an item in the datastore.
+ *
+ * @param key key to store data under
+ * @param size number of bytes in data
+ * @param data data to store
+ * @param type type of the value
+ * @param discard_time when to discard the value in any case
+ * @return 0 on error, number of bytes used otherwise
+ */
+ uint32_t (*put) (void *cls,
+ const GNUNET_HashCode * key,
+ uint32_t size,
+ const char *data,
+ uint32_t type,
+ struct GNUNET_TIME_Absolute discard_time);
+
+
+ /**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param key
+ * @param type entries of which type are relevant?
+ * @param iter maybe NULL (to just count)
+ * @return the number of results found
+ */
+ unsigned int (*get) (void *cls,
+ const GNUNET_HashCode * key,
+ uint32_t type,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls);
+
+
+ /**
+ * Delete the entry with the lowest expiration value
+ * from the datacache right now.
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+ int (*del) (void *cls);
+
+
+};
+
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* end of plugin_datacache.h */
+#endif
Added: gnunet/src/datacache/plugin_datacache_sqlite.c
===================================================================
--- gnunet/src/datacache/plugin_datacache_sqlite.c
(rev 0)
+++ gnunet/src/datacache/plugin_datacache_sqlite.c 2009-07-25 22:24:42 UTC
(rev 8782)
@@ -0,0 +1,676 @@
+/*
+ This file is part of GNUnet.
+ (C) 2006, 2007, 2008 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 2, 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 applications/dstore_sqlite/dstore.c
+ * @brief SQLite based implementation of the dstore service
+ * @author Christian Grothoff
+ * @todo Indexes, statistics
+ *
+ * Database: SQLite
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_dstore_service.h"
+#include "gnunet_stats_service.h"
+#include <sqlite3.h>
+
+#define DEBUG_DSTORE GNUNET_NO
+
+/**
+ * Maximum size for an individual item.
+ */
+#define MAX_CONTENT_SIZE 65536
+
+/**
+ * Bytes used
+ */
+static unsigned long long payload;
+
+/**
+ * Maximum bytes available
+ */
+static unsigned long long quota;
+
+/**
+ * Filename of this database
+ */
+static char *fn;
+static char *fn_utf8;
+
+static GNUNET_CoreAPIForPlugins *coreAPI;
+
+static struct GNUNET_Mutex *lock;
+
+/**
+ * Statistics service.
+ */
+static GNUNET_Stats_ServiceAPI *stats;
+
+static unsigned int stat_dstore_size;
+
+static unsigned int stat_dstore_quota;
+
+/**
+ * Estimate of the per-entry overhead (including indices).
+ */
+#define OVERHEAD ((4*2+4*2+8*2+8*2+sizeof(GNUNET_HashCode)*5+32))
+
+struct GNUNET_BloomFilter *bloom;
+
+static char *bloom_name;
+
+/**
+ * @brief Prepare a SQL statement
+ */
+static int
+sq_prepare (sqlite3 * dbh, const char *zSql, /* SQL statement, UTF-8
encoded */
+ sqlite3_stmt ** ppStmt)
+{ /* OUT: Statement handle */
+ char *dummy;
+ return sqlite3_prepare (dbh,
+ zSql,
+ strlen (zSql), ppStmt, (const char **) &dummy);
+}
+
+#define SQLITE3_EXEC(db, cmd) do { emsg = NULL; if (SQLITE_OK !=
sqlite3_exec(db, cmd, NULL, NULL, &emsg)) { GNUNET_GE_LOG(coreAPI->ectx,
GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, _("`%s' failed at %s:%d
with error: %s\n"), "sqlite3_exec", __FILE__, __LINE__, emsg);
sqlite3_free(emsg); } } while(0)
+
+/**
+ * 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_GE_LOG(coreAPI->ectx, level,
_("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__,
sqlite3_errmsg(db)); } while(0)
+
+static void
+db_init (sqlite3 * dbh)
+{
+ char *emsg;
+
+ SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY");
+ SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
+ SQLITE3_EXEC (dbh, "PRAGMA count_changes=OFF");
+ SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
+ SQLITE3_EXEC (dbh,
+ "CREATE TABLE ds080 ("
+ " size INTEGER NOT NULL DEFAULT 0,"
+ " type INTEGER NOT NULL DEFAULT 0,"
+ " puttime INTEGER NOT NULL DEFAULT 0,"
+ " expire INTEGER NOT NULL DEFAULT 0,"
+ " key BLOB NOT NULL DEFAULT '',"
+ " vhash BLOB NOT NULL DEFAULT '',"
+ " value BLOB NOT NULL DEFAULT '')");
+ SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds080 (key,type,expire)");
+ SQLITE3_EXEC (dbh,
+ "CREATE INDEX idx_allidx ON ds080 (key,vhash,type,size)");
+ SQLITE3_EXEC (dbh, "CREATE INDEX idx_puttime ON ds080 (puttime)");
+}
+
+static int
+db_reset ()
+{
+ int fd;
+ sqlite3 *dbh;
+ char *tmpl;
+ const char *tmpdir;
+
+ if (fn != NULL)
+ {
+ UNLINK (fn);
+ GNUNET_free (fn);
+ GNUNET_free (fn_utf8);
+ }
+ payload = 0;
+
+ tmpdir = getenv ("TMPDIR");
+ tmpdir = tmpdir ? tmpdir : "/tmp";
+
+#define TEMPLATE "/gnunet-dstoreXXXXXX"
+ tmpl = GNUNET_malloc (strlen (tmpdir) + sizeof (TEMPLATE) + 1);
+ strcpy (tmpl, tmpdir);
+ strcat (tmpl, TEMPLATE);
+#undef TEMPLATE
+
+#ifdef MINGW
+ fn = (char *) GNUNET_malloc (MAX_PATH + 1);
+ plibc_conv_to_win_path (tmpl, fn);
+ GNUNET_free (tmpl);
+#else
+ fn = tmpl;
+#endif
+ fd = mkstemp (fn);
+ if (fd == -1)
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ GNUNET_free (fn);
+ fn = NULL;
+ return GNUNET_SYSERR;
+ }
+ CLOSE (fd);
+ fn_utf8 = GNUNET_convert_string_to_utf8 (coreAPI->ectx, fn, strlen (fn),
+#ifdef ENABLE_NLS
+ nl_langinfo (CODESET)
+#else
+ "UTF-8" /* good luck */
+#endif
+ );
+ if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))
+ {
+ GNUNET_free (fn);
+ GNUNET_free (fn_utf8);
+ fn = NULL;
+ return GNUNET_SYSERR;
+ }
+ db_init (dbh);
+ sqlite3_close (dbh);
+ return GNUNET_OK;
+}
+
+/**
+ * Check that we are within quota.
+ * @return GNUNET_OK if we are.
+ */
+static int
+checkQuota (sqlite3 * dbh)
+{
+ GNUNET_HashCode dkey;
+ GNUNET_HashCode vhash;
+ unsigned int dsize;
+ unsigned int dtype;
+ sqlite3_stmt *stmt;
+ sqlite3_stmt *dstmt;
+ int err;
+
+ if (payload * 10 <= quota * 9)
+ return GNUNET_OK; /* we seem to be about 10% off */
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "DStore above qutoa (have %llu, allowed %llu), will delete
some data.\n",
+ payload, quota);
+#endif
+ stmt = NULL;
+ dstmt = NULL;
+ if ((sq_prepare (dbh,
+ "SELECT size, type, key, vhash FROM ds080 ORDER BY puttime
ASC LIMIT 1",
+ &stmt) != SQLITE_OK) ||
+ (sq_prepare (dbh,
+ "DELETE FROM ds080 "
+ "WHERE key=? AND vhash=? AND type=? AND size=?",
+ &dstmt) != SQLITE_OK))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh));
+ GNUNET_GE_BREAK (NULL, 0);
+ if (dstmt != NULL)
+ sqlite3_finalize (dstmt);
+ if (stmt != NULL)
+ sqlite3_finalize (stmt);
+ return GNUNET_SYSERR;
+ }
+ err = SQLITE_DONE;
+ while ((payload * 10 > quota * 9) && /* we seem to be about 10% off */
+ ((err = sqlite3_step (stmt)) == SQLITE_ROW))
+ {
+ dsize = sqlite3_column_int (stmt, 0);
+ dtype = sqlite3_column_int (stmt, 1);
+ GNUNET_GE_BREAK (NULL,
+ sqlite3_column_bytes (stmt,
+ 2) == sizeof (GNUNET_HashCode));
+ GNUNET_GE_BREAK (NULL,
+ sqlite3_column_bytes (stmt,
+ 3) == sizeof (GNUNET_HashCode));
+ memcpy (&dkey, sqlite3_column_blob (stmt, 2), sizeof (GNUNET_HashCode));
+ memcpy (&vhash, sqlite3_column_blob (stmt, 3),
+ sizeof (GNUNET_HashCode));
+ sqlite3_reset (stmt);
+ sqlite3_bind_blob (dstmt,
+ 1, &dkey, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_blob (dstmt,
+ 2, &vhash, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_int (dstmt, 3, dtype);
+ sqlite3_bind_int (dstmt, 4, dsize);
+ if ((err = sqlite3_step (dstmt)) != SQLITE_DONE)
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sqlite3_step", __FILE__, __LINE__,
+ sqlite3_errmsg (dbh));
+ sqlite3_reset (dstmt);
+ GNUNET_GE_BREAK (NULL, 0); /* should delete but cannot!? */
+ break;
+ }
+ if (sqlite3_total_changes (dbh) > 0)
+ {
+ if (bloom != NULL)
+ GNUNET_bloomfilter_remove (bloom, &dkey);
+ payload -= (dsize + OVERHEAD);
+ }
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
+ GNUNET_GE_DEVELOPER,
+ "Deleting %u bytes decreases DStore payload to %llu out
of %llu\n",
+ dsize, payload, quota);
+#endif
+ sqlite3_reset (dstmt);
+ }
+ if (err != SQLITE_DONE)
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sqlite3_step", __FILE__, __LINE__,
+ sqlite3_errmsg (dbh));
+ }
+ sqlite3_finalize (dstmt);
+ sqlite3_finalize (stmt);
+ if (payload * 10 > quota * 9)
+ {
+ /* we seem to be about 10% off */
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_DEVELOPER,
+ "Failed to delete content to drop below quota (bug?).\n",
+ payload, quota);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+/**
+ * Store an item in the datastore.
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+static int
+d_put (const GNUNET_HashCode * key,
+ unsigned int type,
+ GNUNET_CronTime discard_time, unsigned int size, const char *data)
+{
+ GNUNET_HashCode vhash;
+ sqlite3 *dbh;
+ sqlite3_stmt *stmt;
+ int ret;
+ GNUNET_CronTime now;
+
+ if (size > MAX_CONTENT_SIZE)
+ return GNUNET_SYSERR;
+ GNUNET_hash (data, size, &vhash);
+ GNUNET_mutex_lock (lock);
+ if ((fn == NULL) || (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)))
+ {
+ db_reset (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ now = GNUNET_get_time ();
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "dstore processes put `%.*s' with expiration %llu\n",
+ size, data, discard_time);
+#endif
+
+ /* first try UPDATE */
+ if (sq_prepare (dbh,
+ "UPDATE ds080 SET puttime=?, expire=? "
+ "WHERE key=? AND vhash=? AND type=? AND size=?",
+ &stmt) != SQLITE_OK)
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh));
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if ((SQLITE_OK !=
+ sqlite3_bind_int64 (stmt, 1, now)) ||
+ (SQLITE_OK !=
+ sqlite3_bind_int64 (stmt, 2, discard_time)) ||
+ (SQLITE_OK !=
+ sqlite3_bind_blob (stmt, 3, key, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT)) ||
+ (SQLITE_OK !=
+ sqlite3_bind_blob (stmt, 4, &vhash, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT)) ||
+ (SQLITE_OK != sqlite3_bind_int (stmt, 5, type)) ||
+ (SQLITE_OK != sqlite3_bind_int (stmt, 6, size)))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sqlite3_bind_xxx", __FILE__, __LINE__,
+ sqlite3_errmsg (dbh));
+ sqlite3_finalize (stmt);
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (SQLITE_DONE != sqlite3_step (stmt))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sqlite3_step", __FILE__, __LINE__,
+ sqlite3_errmsg (dbh));
+ sqlite3_finalize (stmt);
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ ret = sqlite3_changes (dbh);
+ sqlite3_finalize (stmt);
+ if (ret > 0)
+ {
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_OK;
+ }
+ if (GNUNET_OK != checkQuota (dbh))
+ {
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (sq_prepare (dbh,
+ "INSERT INTO ds080 "
+ "(size, type, puttime, expire, key, vhash, value) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)", &stmt) != SQLITE_OK)
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh));
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if ((SQLITE_OK == sqlite3_bind_int (stmt, 1, size)) &&
+ (SQLITE_OK == sqlite3_bind_int (stmt, 2, type)) &&
+ (SQLITE_OK == sqlite3_bind_int64 (stmt, 3, now)) &&
+ (SQLITE_OK == sqlite3_bind_int64 (stmt, 4, discard_time)) &&
+ (SQLITE_OK ==
+ sqlite3_bind_blob (stmt, 5, key, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT)) &&
+ (SQLITE_OK ==
+ sqlite3_bind_blob (stmt, 6, &vhash, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT))
+ && (SQLITE_OK ==
+ sqlite3_bind_blob (stmt, 7, data, size, SQLITE_TRANSIENT)))
+ {
+ if (SQLITE_DONE != sqlite3_step (stmt))
+ {
+ LOG_SQLITE (dbh,
+ GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN
+ | GNUNET_GE_BULK, "sqlite3_step");
+ }
+ else
+ {
+ payload += size + OVERHEAD;
+ if (bloom != NULL)
+ GNUNET_bloomfilter_add (bloom, key);
+ }
+ if (SQLITE_OK != sqlite3_finalize (stmt))
+ LOG_SQLITE (dbh,
+ GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN |
+ GNUNET_GE_BULK, "sqlite3_finalize");
+ }
+ else
+ {
+ LOG_SQLITE (dbh,
+ GNUNET_GE_ERROR | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN |
+ GNUNET_GE_BULK, "sqlite3_bind_xxx");
+ }
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "Storing %u bytes increases DStore payload to %llu out of
%llu\n",
+ size, payload, quota);
+#endif
+ checkQuota (dbh);
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ if (stats != NULL)
+ stats->set (stat_dstore_size, payload);
+ return GNUNET_OK;
+}
+
+/**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param key
+ * @param type entries of which type are relevant?
+ * @param iter maybe NULL (to just count)
+ * @return the number of results, GNUNET_SYSERR if the
+ * iter is non-NULL and aborted the iteration
+ */
+static int
+d_get (const GNUNET_HashCode * key,
+ unsigned int type, GNUNET_ResultProcessor handler, void *closure)
+{
+ sqlite3 *dbh;
+ sqlite3_stmt *stmt;
+ GNUNET_CronTime now;
+ unsigned int size;
+ const char *dat;
+ unsigned int cnt;
+ unsigned int off;
+ unsigned int total;
+ char scratch[256];
+
+ GNUNET_mutex_lock (lock);
+ if ((bloom != NULL) && (GNUNET_NO == GNUNET_bloomfilter_test (bloom, key)))
+ {
+ GNUNET_mutex_unlock (lock);
+ return 0;
+ }
+ if ((fn == NULL) || (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)))
+ {
+ db_reset (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ now = GNUNET_get_time ();
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "dstore processes get at `%llu'\n", now);
+#endif
+ if (sq_prepare (dbh,
+ "SELECT count(*) FROM ds080 WHERE key=? AND type=? AND
expire >= ?",
+ &stmt) != SQLITE_OK)
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (dbh));
+ sqlite3_close (dbh);
+ db_reset (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_int (stmt, 2, type);
+ sqlite3_bind_int64 (stmt, 3, now);
+ if (SQLITE_ROW != sqlite3_step (stmt))
+ {
+ LOG_SQLITE (dbh,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
+ GNUNET_GE_BULK, "sqlite_step");
+ sqlite3_reset (stmt);
+ sqlite3_finalize (stmt);
+ db_reset (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ total = sqlite3_column_int (stmt, 0);
+ sqlite3_reset (stmt);
+ sqlite3_finalize (stmt);
+ if ((total == 0) || (handler == NULL))
+ {
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return total;
+ }
+
+ cnt = 0;
+ off = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, total);
+ while (cnt < total)
+ {
+ off = (off + 1) % total;
+ GNUNET_snprintf (scratch, 256,
+ "SELECT size, value FROM ds080 WHERE key=? AND type=?
AND expire >= ? LIMIT 1 OFFSET %u",
+ off);
+ if (sq_prepare (dbh, scratch, &stmt) != SQLITE_OK)
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "sq_prepare", __FILE__, __LINE__,
+ sqlite3_errmsg (dbh));
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_int (stmt, 2, type);
+ sqlite3_bind_int64 (stmt, 3, now);
+ if (sqlite3_step (stmt) != SQLITE_ROW)
+ break;
+ size = sqlite3_column_int (stmt, 0);
+ if (size != sqlite3_column_bytes (stmt, 1))
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ sqlite3_finalize (stmt);
+ continue;
+ }
+ dat = sqlite3_column_blob (stmt, 1);
+ cnt++;
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
+ GNUNET_GE_DEVELOPER,
+ "dstore found result for get: `%.*s'\n", size, dat);
+#endif
+ if ((handler != NULL) &&
+ (GNUNET_OK != handler (key, type, size, dat, closure)))
+ {
+ sqlite3_finalize (stmt);
+ break;
+ }
+ sqlite3_finalize (stmt);
+ }
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return cnt;
+}
+
+GNUNET_Dstore_ServiceAPI *
+provide_module_dstore_sqlite (GNUNET_CoreAPIForPlugins * capi)
+{
+ static GNUNET_Dstore_ServiceAPI api;
+ int fd;
+
+#if DEBUG_SQLITE
+ GNUNET_GE_LOG (capi->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "SQLite Dstore: initializing database\n");
+#endif
+ coreAPI = capi;
+ if (GNUNET_OK != db_reset ())
+ {
+ GNUNET_GE_BREAK (capi->ectx, 0);
+ return NULL;
+ }
+ lock = GNUNET_mutex_create (GNUNET_NO);
+
+
+ api.get = &d_get;
+ api.put = &d_put;
+ GNUNET_GC_get_configuration_value_number (coreAPI->cfg,
+ "DSTORE", "QUOTA", 1, 1024, 1,
+ "a);
+ if (quota == 0) /* error */
+ quota = 1;
+ quota *= 1024 * 1024;
+
+ bloom_name = GNUNET_strdup ("/tmp/dbloomXXXXXX");
+ fd = mkstemp (bloom_name);
+ if (fd != -1)
+ {
+ bloom = GNUNET_bloomfilter_load (coreAPI->ectx, bloom_name, quota /
(OVERHEAD + 1024), /* 8 bit per entry in DB, expect 1k entries */
+ 5);
+ CLOSE (fd);
+ }
+ stats = capi->service_request ("stats");
+ if (stats != NULL)
+ {
+ stat_dstore_size = stats->create (gettext_noop ("# bytes in dstore"));
+ stat_dstore_quota =
+ stats->create (gettext_noop ("# max bytes allowed in dstore"));
+ stats->set (stat_dstore_quota, quota);
+ }
+ return &api;
+}
+
+/**
+ * Shutdown the module.
+ */
+void
+release_module_dstore_sqlite ()
+{
+ UNLINK (fn);
+ GNUNET_free (fn);
+ GNUNET_free (fn_utf8);
+ fn = NULL;
+ if (bloom != NULL)
+ {
+ GNUNET_bloomfilter_free (bloom);
+ bloom = NULL;
+ }
+ UNLINK (bloom_name);
+ GNUNET_free (bloom_name);
+ bloom_name = NULL;
+ if (stats != NULL)
+ {
+ coreAPI->service_release (stats);
+ stats = NULL;
+ }
+#if DEBUG_SQLITE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "SQLite Dstore: database shutdown\n");
+#endif
+ GNUNET_mutex_destroy (lock);
+ coreAPI = NULL;
+}
+
+/* end of dstore.c */
Added: gnunet/src/datacache/plugin_datacache_template.c
===================================================================
--- gnunet/src/datacache/plugin_datacache_template.c
(rev 0)
+++ gnunet/src/datacache/plugin_datacache_template.c 2009-07-25 22:24:42 UTC
(rev 8782)
@@ -0,0 +1,151 @@
+/*
+ This file is part of GNUnet
+ (C) 2006, 2009 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 2, 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 datacache/plugin_datacache_template.c
+ * @brief template for an implementation of a database backend for the
datacache
+ * @author Christian Grothoff
+ */
+#ifndef PLUGIN_DATACACHE_H
+#define PLUGIN_DATACACHE_H
+
+#include "plugin_datacache.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0 /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+
+/**
+ * Context for all functions in this plugin.
+ */
+struct Plugin
+{
+ /**
+ * Our execution environment.
+ */
+ struct GNUNET_DATASTORE_PluginEnvironment *env;
+};
+
+
+/**
+ * Store an item in the datastore.
+ *
+ * @param key key to store data under
+ * @param size number of bytes in data
+ * @param data data to store
+ * @param type type of the value
+ * @param discard_time when to discard the value in any case
+ * @return 0 on error, number of bytes used otherwise
+ */
+static uint32_t
+template_plugin_put (void *cls,
+ const GNUNET_HashCode * key,
+ uint32_t size,
+ const char *data,
+ uint32_t type,
+ struct GNUNET_TIME_Absolute discard_time)
+{
+ GNUNET_break (0);
+ return 0;
+}
+
+
+/**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param key
+ * @param type entries of which type are relevant?
+ * @param iter maybe NULL (to just count)
+ * @return the number of results found
+ */
+static unsigned int
+template_plugin_get (void *cls,
+ const GNUNET_HashCode * key,
+ uint32_t type,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls)
+{
+ GNUNET_break (0);
+ return 0;
+}
+
+
+/**
+ * Delete the entry with the lowest expiration value
+ * from the datacache right now.
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+static int
+template_plugin_del (void *cls)
+{
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * Entry point for the plugin.
+ */
+void *
+libgnunet_plugin_datacache_template_init (void *cls)
+{
+ struct GNUNET_DATACACHE_PluginEnvironment *env = cls;
+ struct GNUNET_DATACACHE_PluginFunctions *api;
+ struct Plugin *plugin;
+
+ plugin = GNUNET_malloc (sizeof (struct Plugin));
+ plugin->env = env;
+ api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions));
+ api->cls = plugin;
+ api->get = &template_plugin_get;
+ api->put = &template_plugin_put;
+ api->del = &template_plugin_del;
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
+ "template", _("Template datacache running\n"));
+ return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ */
+void *
+libgnunet_plugin_datacache_template_done (void *cls)
+{
+ struct GNUNET_DATACACHE_PluginFunctions *api = cls;
+ struct Plugin *plugin = api->cls;
+
+ GNUNET_free (plugin);
+ GNUNET_free (api);
+ return NULL;
+}
+
+
+
+/* end of plugin_datacache_template.c */
+
Added: gnunet/src/datacache/test_datacache_api.c
===================================================================
--- gnunet/src/datacache/test_datacache_api.c (rev 0)
+++ gnunet/src/datacache/test_datacache_api.c 2009-07-25 22:24:42 UTC (rev
8782)
@@ -0,0 +1,120 @@
+/*
+ This file is part of GNUnet.
+ (C) 2006 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 2, 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 applications/dstore/dstore_test.c
+ * @brief Test for the dstore implementations.
+ * @author Nils Durner
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_protocols.h"
+#include "gnunet_dstore_service.h"
+#include "core.h"
+
+#define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__,
__LINE__); goto FAILURE;} } while (0)
+
+static int error;
+
+static int
+checkIt (const GNUNET_HashCode * key,
+ unsigned int type, unsigned int size, const char *data, void *cls)
+{
+ if (size != sizeof (GNUNET_HashCode))
+ {
+ printf ("ERROR: Invalid size\n");
+ error = 2;
+ }
+ if (0 != memcmp (data, cls, size))
+ {
+ printf ("ERROR: Invalid data\n");
+ error = 3;
+ }
+ return GNUNET_OK;
+}
+
+/**
+ * Add testcode here!
+ */
+static int
+test (GNUNET_Dstore_ServiceAPI * api)
+{
+ GNUNET_HashCode k;
+ GNUNET_HashCode n;
+ GNUNET_CronTime exp;
+ unsigned int i;
+
+ exp = GNUNET_get_time () + 5 * GNUNET_CRON_MINUTES;
+ memset (&k, 0, sizeof (GNUNET_HashCode));
+ for (i = 0; i < 100; i++)
+ {
+ GNUNET_hash (&k, sizeof (GNUNET_HashCode), &n);
+ ASSERT (GNUNET_OK == api->put (&k,
+ i % 2,
+ exp, sizeof (GNUNET_HashCode),
+ (const char *) &n));
+ k = n;
+ }
+ memset (&k, 0, sizeof (GNUNET_HashCode));
+ for (i = 0; i < 100; i++)
+ {
+ GNUNET_hash (&k, sizeof (GNUNET_HashCode), &n);
+ ASSERT (1 == api->get (&k, i % 2, &checkIt, &n));
+ k = n;
+ }
+ return GNUNET_OK;
+FAILURE:
+ return GNUNET_SYSERR;
+}
+
+#define TEST_DB "/tmp/GNUnet_dstore_test/"
+
+int
+main (int argc, char *argv[])
+{
+ GNUNET_Dstore_ServiceAPI *api;
+ int ok;
+ struct GNUNET_GC_Configuration *cfg;
+ struct GNUNET_CronManager *cron;
+
+ GNUNET_disable_entropy_gathering ();
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+ cron = GNUNET_cron_create (NULL);
+ GNUNET_CORE_init (NULL, cfg, cron, NULL);
+ api = GNUNET_CORE_request_service ("dstore");
+ if (api != NULL)
+ {
+ ok = test (api);
+ GNUNET_CORE_release_service (api);
+ }
+ else
+ ok = GNUNET_SYSERR;
+ GNUNET_CORE_done ();
+ if (ok == GNUNET_SYSERR)
+ return 1;
+ return error;
+}
+
+/* end of dstore_test.c */
Modified: gnunet/src/datastore/Makefile.am
===================================================================
--- gnunet/src/datastore/Makefile.am 2009-07-25 21:32:23 UTC (rev 8781)
+++ gnunet/src/datastore/Makefile.am 2009-07-25 22:24:42 UTC (rev 8782)
@@ -16,7 +16,7 @@
libgnunetdatastore.la
libgnunetdatastore_la_SOURCES = \
- datastore_api.c datastore.h
+ datastore_api.c datastore.h plugin_datastore.h
libgnunetdatastore_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL)
Modified: gnunet/src/datastore/plugin_datastore_template.c
===================================================================
--- gnunet/src/datastore/plugin_datastore_template.c 2009-07-25 21:32:23 UTC
(rev 8781)
+++ gnunet/src/datastore/plugin_datastore_template.c 2009-07-25 22:24:42 UTC
(rev 8782)
@@ -47,6 +47,7 @@
*/
static unsigned long long template_plugin_get_size (void *cls)
{
+ GNUNET_break (0);
return 0;
}
@@ -76,6 +77,7 @@
struct GNUNET_TIME_Absolute expiration,
char **msg)
{
+ GNUNET_break (0);
*msg = GNUNET_strdup ("not implemented");
return GNUNET_SYSERR;
}
@@ -94,9 +96,10 @@
* to signal the end of the iteration).
*/
static void
-template_next_request (void *next_cls,
+template_plugin_next_request (void *next_cls,
int end_it)
{
+ GNUNET_break (0);
}
@@ -124,6 +127,7 @@
uint32_t type,
PluginIterator iter, void *iter_cls)
{
+ GNUNET_break (0);
}
@@ -155,6 +159,7 @@
int delta, struct GNUNET_TIME_Absolute expire,
char **msg)
{
+ GNUNET_break (0);
*msg = GNUNET_strdup ("not implemented");
return GNUNET_SYSERR;
}
@@ -176,6 +181,7 @@
PluginIterator iter,
void *iter_cls)
{
+ GNUNET_break (0);
}
@@ -196,6 +202,7 @@
PluginIterator iter,
void *iter_cls)
{
+ GNUNET_break (0);
}
@@ -216,6 +223,7 @@
PluginIterator iter,
void *iter_cls)
{
+ GNUNET_break (0);
}
@@ -236,6 +244,7 @@
PluginIterator iter,
void *iter_cls)
{
+ GNUNET_break (0);
}
@@ -256,6 +265,7 @@
PluginIterator iter,
void *iter_cls)
{
+ GNUNET_break (0);
}
@@ -265,6 +275,7 @@
static void
template_plugin_drop (void *cls)
{
+ GNUNET_break (0);
}
@@ -284,7 +295,7 @@
api->cls = plugin;
api->get_size = &template_plugin_get_size;
api->put = &template_plugin_put;
- api->next_request = &template_next_request;
+ api->next_request = &template_plugin_next_request;
api->get = &template_plugin_get;
api->update = &template_plugin_update;
api->iter_low_priority = &template_plugin_iter_low_priority;
Modified: gnunet/src/include/gnunet_datacache_lib.h
===================================================================
--- gnunet/src/include/gnunet_datacache_lib.h 2009-07-25 21:32:23 UTC (rev
8781)
+++ gnunet/src/include/gnunet_datacache_lib.h 2009-07-25 22:24:42 UTC (rev
8782)
@@ -51,12 +51,14 @@
/**
* Create a data cache.
*
+ * @param sched scheduler to use
* @param cfg configuration to use
* @param section section in the configuration that contains our options
* @return handle to use to access the service
*/
struct GNUNET_DATACACHE_Handle *
-GNUNET_DATACACHE_create (struct GNUNET_CONFIGURATION_Handle *cfg,
+GNUNET_DATACACHE_create (struct GNUNET_SCHEDULER_Handle *sched,
+ struct GNUNET_CONFIGURATION_Handle *cfg,
const char *section);
@@ -85,8 +87,9 @@
/**
- * Store an item in the datastore.
+ * Store an item in the datacache.
*
+ * @param h handle to the datacache
* @param key key to store data under
* @param size number of bytes in data
* @param data data to store
@@ -95,7 +98,8 @@
* @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.)
*/
int
-GNUNET_DATACACHE_put (const GNUNET_HashCode * key,
+GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
+ const GNUNET_HashCode * key,
uint32_t size,
const char *data,
unsigned int type,
@@ -104,8 +108,9 @@
/**
* Iterate over the results for a particular key
- * in the datastore.
+ * in the datacache.
*
+ * @param h handle to the datacache
* @param key what to look up
* @param type entries of which type are relevant?
* @param iter maybe NULL (to just count)
@@ -113,7 +118,8 @@
* @return the number of results found
*/
unsigned int
-GNUNET_DATACACHE_get (const GNUNET_HashCode * key,
+GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
+ const GNUNET_HashCode * key,
unsigned int type,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r8782 - in gnunet: . src src/datacache src/datastore src/include,
gnunet <=