[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r5825 - in GNUnet/src/applications: . dstore_mysql dstore_s
From: |
gnunet |
Subject: |
[GNUnet-SVN] r5825 - in GNUnet/src/applications: . dstore_mysql dstore_sqlite |
Date: |
Sun, 9 Dec 2007 12:34:39 -0700 (MST) |
Author: grothoff
Date: 2007-12-09 12:34:38 -0700 (Sun, 09 Dec 2007)
New Revision: 5825
Added:
GNUnet/src/applications/dstore_mysql/
GNUnet/src/applications/dstore_mysql/Makefile.am
GNUnet/src/applications/dstore_mysql/check.conf
GNUnet/src/applications/dstore_mysql/dstore_mysql.c
GNUnet/src/applications/dstore_mysql/dstore_test.c
GNUnet/src/applications/dstore_sqlite/
GNUnet/src/applications/dstore_sqlite/Makefile.am
GNUnet/src/applications/dstore_sqlite/check.conf
GNUnet/src/applications/dstore_sqlite/dstore.c
GNUnet/src/applications/dstore_sqlite/dstore_test.c
Removed:
GNUnet/src/applications/dstore_sqlite/Makefile.am
GNUnet/src/applications/dstore_sqlite/check.conf
GNUnet/src/applications/dstore_sqlite/dstore.c
GNUnet/src/applications/dstore_sqlite/dstore_test.c
Log:
towards mysql dstore (incomplete)
Added: GNUnet/src/applications/dstore_mysql/Makefile.am
===================================================================
--- GNUnet/src/applications/dstore_mysql/Makefile.am
(rev 0)
+++ GNUnet/src/applications/dstore_mysql/Makefile.am 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,37 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/GNUnet
+
+LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+plugin_LTLIBRARIES = \
+ libgnunetmodule_dstore_mysql.la
+
+check_PROGRAMS = \
+ dstore_test
+
+TESTS = $(check_PROGRAMS)
+
+if HAVE_ZLIB
+ ZLIB_LNK = -lz
+endif
+
+AM_CPPFLAGS = $(CPPFLAGS) $(MYSQL_CPPFLAGS)
+
+libgnunetmodule_dstore_mysql_la_SOURCES = \
+ dstore_mysql.c
+libgnunetmodule_dstore_mysql_la_LDFLAGS = \
+ -export-dynamic -avoid-version -module \
+ $(MYSQL_LDFLAGS)
+libgnunetmodule_dstore_mysql_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ -lmysqlclient $(ZLIB_LNK)
+
+EXTRA_DIST = check.conf
+
+dstore_test_SOURCES = \
+ dstore_test.c
+dstore_test_LDADD = \
+ $(top_builddir)/src/server/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
Added: GNUnet/src/applications/dstore_mysql/check.conf
===================================================================
--- GNUnet/src/applications/dstore_mysql/check.conf
(rev 0)
+++ GNUnet/src/applications/dstore_mysql/check.conf 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,46 @@
+[PATHS]
+GNUNETD_HOME = /tmp/gnunet-sqlite-sqstore-test
+
+[GNUNETD]
+GNUNETD_HOME = /tmp/gnunet-sqlite-sqstore-test
+HELLOEXPIRES = 1440
+LOGLEVEL = "NOTHING"
+LOGFILE = $GNUNETD_HOME/logs
+KEEPLOG = "0"
+PIDFILE = $GNUNETD_HOME/gnunet.pid
+HOSTS = $GNUNETD_HOME/data/hosts/
+HTTP-PROXY = ""
+HTTP-PROXY-PORT = 1080
+APPLICATIONS = "fs getoption stats traffic"
+PROCESS-PRIORITY = "NORMAL"
+
+[KEYVALUE_DATABASE]
+DIR = $GNUNETD_HOME/data/kv/
+
+[MODULES]
+sqstore = "sqstore_mysql"
+topology = "topology_default"
+dstore = "dstore_mysql"
+
+[NETWORK]
+PORT = 12087
+INTERFACE = ""
+IP = ""
+HELLOEXCHANGE = YES
+TRUSTED = "127.0.0.0/8;"
+
+[LOAD]
+BASICLIMITING = YES
+INTERFACES = ""
+MAXNETDOWNBPSTOTAL = 50000
+MAXNETUPBPSTOTAL = 50000
+MAXCPULOAD = 50
+
+[FS]
+QUOTA = 1024
+ACTIVEMIGRATION = YES
+DIR = $GNUNETD_HOME/data/fs/
+INDEX-DIRECTORY = $GNUNETD_HOME/data/shared/
+INDEX-QUOTA = 8192
+POOL = 32
+
Added: GNUnet/src/applications/dstore_mysql/dstore_mysql.c
===================================================================
--- GNUnet/src/applications/dstore_mysql/dstore_mysql.c
(rev 0)
+++ GNUnet/src/applications/dstore_mysql/dstore_mysql.c 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,692 @@
+/*
+ This file is part of GNUnet.
+ (C) 2006, 2007 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_mysql/dstore.c
+ * @brief MySQL based implementation of the dstore service
+ * @author Christian Grothoff
+ * @todo Indexes, statistics
+ *
+ * Database: MySQL
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_dstore_service.h"
+#include "gnunet_stats_service.h"
+#include <mysql/mysql.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;
+
+static GNUNET_CoreAPIForPlugins *coreAPI;
+
+static struct GNUNET_Mutex *lock;
+
+/**
+ * Statistics service.
+ */
+static GNUNET_Stats_ServiceAPI *stats;
+
+static unsigned int stat_dstore_size;
+
+/**
+ * Estimate of the per-entry overhead (including indices).
+ */
+#define OVERHEAD ((4+4+8+8*2+sizeof(GNUNET_HashCode)*2+32))
+
+struct GNUNET_BloomFilter *bloom;
+
+static char *bloom_name;
+
+/**
+ * Path to MySQL configuration file.
+ */
+static char *cnffile;
+
+/**
+ * Handle for the MySQL database.
+ */
+static MYSQL *dbf;
+
+
+#define SELECT_VALUE_STMT "SELECT size, value FROM gn073dstore WHERE hash=?
AND type=? AND expire >= ?"
+static MYSQL_STMT *select_value;
+
+#define SELECT_OLD_VALUE_STMT "SELECT hash, type, expire, puttime, size, value
FROM gn073dstore ORDER BY puttime ASC LIMIT 1"
+static MYSQL_STMT *select_old_value;
+
+#define DELETE_VALUE_STMT "DELETE FROM gn073dstore WHERE hash = ? AND type = ?
AND "\
+ "expire = ? AND puttime = ? AND size = ? AND value =
?"
+static MYSQL_STMT *delete_value;
+
+#define INSERT_VALUE_STMT "INSERT INTO gn073dstore (hash, type, expire,
puttime, size, value) "\
+ "VALUES (?, ?, ?, ?, ?, ?)"
+static MYSQL_STMT *insert_value;
+
+#define UPDATE_VALUE_STMT "UPDATE gn073dstore SET puttime=?, expire=? "\
+ "WHERE hash=? AND type=? AND size=? AND value=?"
+static MYSQL_STMT *update_value;
+
+/**
+ * Die with an error message that indicates
+ * a failure of the command 'cmd' with the message given
+ * by strerror(errno).
+ */
+#define DIE_MYSQL(cmd, dbh) do { GNUNET_GE_LOG(coreAPI->ectx, GNUNET_GE_FATAL
| GNUNET_GE_ADMIN | GNUNET_GE_IMMEDIATE, _("`%s' failed at %s:%d with error:
%s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)); abort(); } 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_MYSQL(level, cmd, dbh) do { GNUNET_GE_LOG(coreAPI->ectx, level,
_("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__,
mysql_error((dbh))); } while(0);
+
+
+/**
+ * Close the database connection.
+ */
+static int
+iclose ()
+{
+#define PEND(h) if (h != NULL) { mysql_stmt_close(h); h = NULL; } else {}
+ if (dbf == NULL)
+ return GNUNET_SYSERR;
+ PEND (select_value);
+ PEND (select_old_value);
+ PEND (delete_value);
+ PEND (insert_value);
+ PEND (update_value);
+ mysql_close (dbf);
+ dbf = NULL;
+ return GNUNET_OK;
+}
+
+/**
+ * Initiate the database connection.
+ *
+ * @return GNUNET_OK on success
+ */
+static int
+iopen ()
+{
+ char *dbname;
+ my_bool reconnect = 0;
+ unsigned int timeout = 60; /* in seconds */
+
+ if (dbf != NULL)
+ return GNUNET_OK;
+ if (cnffile == NULL) {
+ GNUNET_GE_BREAK(NULL, 0);
+ return GNUNET_SYSERR;
+ }
+ dbf = mysql_init (NULL);
+ if (dbf == NULL) {
+ GNUNET_GE_BREAK(NULL, 0);
+ return GNUNET_SYSERR;
+ }
+ mysql_options (dbf, MYSQL_READ_DEFAULT_FILE, cnffile);
+ mysql_options (dbf, MYSQL_READ_DEFAULT_GROUP, "client");
+ mysql_options (dbf, MYSQL_OPT_RECONNECT, &reconnect);
+ mysql_options (dbf, MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout);
+ mysql_options (dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout);
+ mysql_options (dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout);
+
+ dbname = NULL;
+ GNUNET_GC_get_configuration_value_string (coreAPI->cfg,
+ "MYSQL", "DATABASE", "gnunet",
+ &dbname);
+ mysql_real_connect (dbf, NULL, NULL, NULL, dbname, 0, NULL, 0);
+ GNUNET_free (dbname);
+ if (mysql_error (dbf)[0])
+ {
+ LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ "mysql_real_connect", dbf);
+ iclose ();
+ return GNUNET_SYSERR;
+ }
+ mysql_query (dbf,
+ "SET SESSION net_read_timeout=60, SESSION
net_write_timeout=60");
+ if (mysql_error (dbf)[0])
+ {
+ LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ "mysql_query", dbf);
+ iclose ();
+ return GNUNET_SYSERR;
+ }
+
+ mysql_query (dbf, "DROP TABLE gn073dstore");
+ mysql_query (dbf,
+ "CREATE TEMPORARY TABLE gn073dstore ("
+ " size INT(11) UNSIGNED NOT NULL DEFAULT 0,"
+ " type INT(11) UNSIGNED NOT NULL DEFAULT 0,"
+ " puttime BIGINT UNSIGNED NOT NULL DEFAULT 0,"
+ " expire BIGINT UNSIGNED NOT NULL DEFAULT 0,"
+ " hash BINARY(64) NOT NULL DEFAULT '',"
+ " value BLOB NOT NULL DEFAULT '',"
+ " INDEX hashidx (hash(64),type,expire),"
+ " INDEX expireidx (puttime)"
+ ") ENGINE=InnoDB");
+ if (mysql_error (dbf)[0])
+ {
+ LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ "mysql_query", dbf);
+ iclose ();
+ return GNUNET_SYSERR;
+ }
+ mysql_query (dbf, "SET AUTOCOMMIT = 1");
+ if (mysql_error (dbf)[0])
+ {
+ LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK,
+ "mysql_query", dbf);
+ iclose ();
+ return GNUNET_SYSERR;
+ }
+#define PINIT(a,b) a = mysql_stmt_init(dbf); if (a == NULL) { iclose(); return
GNUNET_SYSERR; } else { \
+ if (mysql_stmt_prepare (a, b, strlen(b))) { \
+ GNUNET_GE_LOG (coreAPI->ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK |
GNUNET_GE_USER, \
+ _("`%s' failed at %s:%d with error: %s"), "mysql_stmt_prepare",
__FILE__, __LINE__, \
+ mysql_stmt_error (a)); iclose(); return GNUNET_SYSERR; } }
+ PINIT (select_value, SELECT_VALUE_STMT);
+ PINIT (select_old_value, SELECT_OLD_VALUE_STMT);
+ PINIT (delete_value, DELETE_VALUE_STMT);
+ PINIT (insert_value, INSERT_VALUE_STMT);
+ PINIT (update_value, UPDATE_VALUE_STMT);
+ return GNUNET_OK;
+}
+
+/**
+ * Check that we are within quota.
+ * @return GNUNET_OK if we are, GNUNET_NO if not, GNUNET_SYSERR if
+ * there was an internal error
+ */
+static int
+checkQuota ()
+{
+ MYSQL_BIND rbind[6];
+ unsigned int v_size;
+ unsigned int v_type;
+ GNUNET_CronTime v_puttime;
+ GNUNET_CronTime v_expire;
+ GNUNET_HashCode v_key;
+ unsigned long h_length;
+ unsigned long v_length;
+
+ 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
+ h_length = sizeof(GNUNET_HashCode);
+ v_length = GNUNET_MAX_BUFFER_SIZE;
+
+ memset (rbind, 0, sizeof (rbind));
+ rbind[0].buffer_type = MYSQL_TYPE_BLOB;
+ rbind[0].buffer_length = sizeof(GNUNET_HashCode);
+ rbind[0].length = &h_length;
+ rbind[0].buffer = &v_key;
+ rbind[1].buffer_type = MYSQL_TYPE_LONG;
+ rbind[1].is_unsigned = 1;
+ rbind[1].buffer = &v_type;
+ rbind[2].buffer_type = MYSQL_TYPE_LONGLONG;
+ rbind[2].is_unsigned = 1;
+ rbind[2].buffer = &v_expire;
+ rbind[3].buffer_type = MYSQL_TYPE_LONGLONG;
+ rbind[3].is_unsigned = 1;
+ rbind[3].buffer = &v_puttime;
+ rbind[4].buffer_type = MYSQL_TYPE_LONG;
+ rbind[4].is_unsigned = 1;
+ rbind[4].buffer = &v_size;
+ rbind[5].buffer_type = MYSQL_TYPE_BLOB;
+ rbind[5].buffer_length = GNUNET_MAX_BUFFER_SIZE;
+ rbind[5].length = &v_length;
+ rbind[5].buffer = GNUNET_malloc(GNUNET_MAX_BUFFER_SIZE);
+
+ GNUNET_mutex_lock (lock);
+ mysql_thread_init ();
+ if (mysql_stmt_execute (select_old_value))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_execute",
+ __FILE__, __LINE__,
+ mysql_stmt_error (select_old_value));
+ GNUNET_free(rbind[5].buffer);
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_GE_ASSERT (coreAPI->ectx, mysql_stmt_field_count (select_old_value)
== 6);
+ if (mysql_stmt_bind_result (select_old_value, rbind))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_result",
+ __FILE__, __LINE__,
+ mysql_stmt_error (select_old_value));
+ GNUNET_free(rbind[5].buffer);
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if ( (0 != mysql_stmt_fetch (select_old_value)) ||
+ (h_length != sizeof(GNUNET_HashCode)) )
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_result",
+ __FILE__, __LINE__,
+ mysql_stmt_error (select_old_value));
+ GNUNET_free(rbind[5].buffer);
+ mysql_stmt_reset (select_old_value);
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ mysql_stmt_reset (select_old_value);
+ if (mysql_stmt_bind_param (delete_value, rbind))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_param",
+ __FILE__, __LINE__, mysql_stmt_error (delete_value));
+ GNUNET_free(rbind[5].buffer);
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (mysql_stmt_execute (delete_value))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_execute",
+ __FILE__, __LINE__, mysql_stmt_error (delete_value));
+ GNUNET_free(rbind[5].buffer);
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free(rbind[5].buffer);
+ payload -= v_length + OVERHEAD;
+ mysql_stmt_reset (delete_value);
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ if (payload * 10 > quota * 9)
+ return GNUNET_NO;
+ 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)
+{
+ MYSQL_BIND rbind[6];
+ GNUNET_CronTime now;
+ unsigned long h_length;
+ unsigned long v_length;
+
+ if (size > MAX_CONTENT_SIZE)
+ return GNUNET_SYSERR;
+ GNUNET_mutex_lock (lock);
+ mysql_thread_init ();
+ iopen();
+ now = GNUNET_get_time();
+
+ /* first try UPDATE */
+ h_length = sizeof(GNUNET_HashCode);
+ v_length = size;
+ memset (rbind, 0, sizeof (rbind));
+ rbind[0].buffer_type = MYSQL_TYPE_LONGLONG;
+ rbind[0].is_unsigned = 1;
+ rbind[0].buffer = &now;
+ rbind[1].buffer_type = MYSQL_TYPE_LONGLONG;
+ rbind[1].is_unsigned = 1;
+ rbind[1].buffer = &discard_time;
+ rbind[2].buffer_type = MYSQL_TYPE_BLOB;
+ rbind[2].buffer_length = sizeof(GNUNET_HashCode);
+ rbind[2].length = &h_length;
+ rbind[2].buffer = (void*) key;
+ rbind[3].buffer_type = MYSQL_TYPE_LONG;
+ rbind[3].is_unsigned = 1;
+ rbind[3].buffer = &type;
+ rbind[4].buffer_type = MYSQL_TYPE_LONG;
+ rbind[4].is_unsigned = 1;
+ rbind[4].buffer = &size;
+ rbind[5].buffer_type = MYSQL_TYPE_BLOB;
+ rbind[5].buffer_length = size;
+ rbind[5].length = &v_length;
+ rbind[5].buffer = (void*) data;
+
+ if (mysql_stmt_bind_param (update_value, rbind))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_param",
+ __FILE__, __LINE__, mysql_stmt_error (update_value));
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (mysql_stmt_execute (update_value))
+ {
+ mysql_stmt_reset (update_value);
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_OK;
+ }
+ mysql_stmt_reset (update_value);
+ /* now try INSERT */
+
+ if (mysql_stmt_bind_param (insert_value, rbind))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_param",
+ __FILE__, __LINE__, mysql_stmt_error (insert_value));
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (mysql_stmt_execute (insert_value)) {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_param",
+ __FILE__, __LINE__, mysql_stmt_error (insert_value));
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ mysql_stmt_reset (insert_value);
+ mysql_thread_end ();
+ if (bloom != NULL)
+ GNUNET_bloomfilter_add (bloom, key);
+ payload += size + OVERHEAD;
+ checkQuota ();
+ 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)
+{
+ MYSQL_BIND qbind[3];
+ MYSQL_BIND rbind[2];
+ unsigned int v_size;
+ unsigned long h_length;
+ unsigned long v_length;
+ GNUNET_CronTime now;
+ unsigned int cnt;
+
+ GNUNET_mutex_lock (lock);
+ if ((bloom != NULL) && (GNUNET_NO == GNUNET_bloomfilter_test (bloom, key)))
+ {
+ GNUNET_mutex_unlock (lock);
+ return 0;
+ }
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "dstore processes get\n");
+#endif
+ now = GNUNET_get_time ();
+
+ h_length = sizeof(GNUNET_HashCode);
+ v_length = GNUNET_MAX_BUFFER_SIZE;
+ memset (qbind, 0, sizeof (qbind));
+ qbind[0].buffer_type = MYSQL_TYPE_BLOB;
+ qbind[0].buffer_length = sizeof(GNUNET_HashCode);
+ qbind[0].length = &h_length;
+ qbind[0].buffer = (void*) key;
+ qbind[1].buffer_type = MYSQL_TYPE_LONG;
+ qbind[1].is_unsigned = 1;
+ qbind[1].buffer = &type;
+ qbind[2].buffer_type = MYSQL_TYPE_LONGLONG;
+ qbind[2].is_unsigned = 1;
+ qbind[2].buffer = &now;
+
+ mysql_thread_init ();
+ iopen();
+ if (mysql_stmt_bind_param (select_value, qbind))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_param",
+ __FILE__, __LINE__, mysql_stmt_error (select_value));
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (mysql_stmt_execute (select_value))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_execute",
+ __FILE__, __LINE__, mysql_stmt_error (select_value));
+ iclose ();
+ GNUNET_mutex_unlock (lock);
+ mysql_thread_end ();
+ return GNUNET_SYSERR;
+ }
+
+ memset (rbind, 0, sizeof (rbind));
+ rbind[0].buffer_type = MYSQL_TYPE_LONG;
+ rbind[0].is_unsigned = 1;
+ rbind[0].buffer = &v_size;
+ rbind[1].buffer_type = MYSQL_TYPE_BLOB;
+ rbind[1].buffer_length = GNUNET_MAX_BUFFER_SIZE;
+ rbind[1].length = &v_length;
+ rbind[1].buffer = GNUNET_malloc(GNUNET_MAX_BUFFER_SIZE);
+ if (mysql_stmt_bind_result (select_value, rbind))
+ {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+ _("`%s' failed at %s:%d with error: %s\n"),
+ "mysql_stmt_bind_result",
+ __FILE__, __LINE__, mysql_stmt_error (select_value));
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ GNUNET_free(rbind[1].buffer);
+ return GNUNET_SYSERR;
+ }
+ cnt = 0;
+ while (0 == mysql_stmt_fetch (select_value))
+ {
+ if (v_length != v_size) {
+ GNUNET_GE_BREAK(NULL, 0);
+ iclose ();
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ GNUNET_free(rbind[1].buffer);
+ return cnt;
+ }
+ handler (key, type, v_size, rbind[1].buffer, closure);
+ cnt++;
+ }
+ mysql_stmt_reset (select_value);
+ mysql_thread_end ();
+ GNUNET_mutex_unlock (lock);
+ GNUNET_free(rbind[1].buffer);
+ return cnt;
+}
+
+GNUNET_Dstore_ServiceAPI *
+provide_module_dstore_mysql (GNUNET_CoreAPIForPlugins * capi)
+{
+ static GNUNET_Dstore_ServiceAPI api;
+ int fd;
+#ifndef WINDOWS
+ struct passwd *pw;
+#endif
+ size_t nX;
+ char *home_dir;
+
+ coreAPI = capi;
+#if DEBUG_SQLITE
+ GNUNET_GE_LOG (capi->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "MySQL Dstore: initializing database\n");
+#endif
+
+ /* verify that .my.cnf can be found */
+#ifndef WINDOWS
+ pw = getpwuid (getuid ());
+ if (!pw)
+ GNUNET_GE_DIE_STRERROR (coreAPI->ectx,
+ GNUNET_GE_FATAL | GNUNET_GE_ADMIN |
+ GNUNET_GE_IMMEDIATE, "getpwuid");
+ home_dir = GNUNET_strdup (pw->pw_dir);
+#else
+ home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1);
+ plibc_conv_to_win_path ("~/", home_dir);
+#endif
+ nX = strlen (home_dir) + 10;
+ cnffile = GNUNET_malloc (nX);
+ GNUNET_snprintf (cnffile, nX, "%s/.my.cnf", home_dir);
+ GNUNET_free (home_dir);
+ GNUNET_GC_get_configuration_value_filename (capi->cfg,
+ "MYSQL", "CONFIG", cnffile,
+ &home_dir);
+ GNUNET_free (cnffile);
+ cnffile = home_dir;
+ GNUNET_GE_ASSERT(NULL, cnffile != NULL);
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ _("Trying to use file `%s' for MySQL configuration.\n"),
+ cnffile);
+
+
+ if (iopen() != GNUNET_OK) {
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_ERROR | GNUNET_GE_IMMEDIATE | GNUNET_GE_USER,
+ _("Failed to initialize MySQL database connection for
dstore.\n"),
+ cnffile);
+ GNUNET_free(cnffile);
+ 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->requestService ("stats");
+ if (stats != NULL)
+ stat_dstore_size = stats->create (gettext_noop ("# bytes in dstore"));
+ return &api;
+}
+
+/**
+ * Shutdown the module.
+ */
+void
+release_module_dstore_mysql ()
+{
+ if (bloom != NULL)
+ {
+ GNUNET_bloomfilter_free (bloom);
+ bloom = NULL;
+ }
+ UNLINK (bloom_name);
+ GNUNET_free (bloom_name);
+ bloom_name = NULL;
+ if (stats != NULL)
+ {
+ coreAPI->releaseService (stats);
+ stats = NULL;
+ }
+#if DEBUG_SQLITE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
+ "MySQL Dstore: database shutdown\n");
+#endif
+ GNUNET_mutex_destroy (lock);
+ coreAPI = NULL;
+ GNUNET_free(cnffile);
+ cnffile = NULL;
+}
+
+/* end of dstore_mysql.c */
Property changes on: GNUnet/src/applications/dstore_mysql/dstore_mysql.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: GNUnet/src/applications/dstore_mysql/dstore_test.c
===================================================================
--- GNUnet/src/applications/dstore_mysql/dstore_test.c
(rev 0)
+++ GNUnet/src/applications/dstore_mysql/dstore_test.c 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,116 @@
+/*
+ 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 void
+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;
+ }
+}
+
+/**
+ * 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;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GNUNET_Dstore_ServiceAPI *api;
+ int ok;
+ struct GNUNET_GC_Configuration *cfg;
+ struct GNUNET_CronManager *cron;
+
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+ cron = cron_create (NULL);
+ initCore (NULL, cfg, cron, NULL);
+ api = requestService ("dstore");
+ if (api != NULL)
+ {
+ ok = test (api);
+ releaseService (api);
+ }
+ else
+ ok = GNUNET_SYSERR;
+ doneCore ();
+ if (ok == GNUNET_SYSERR)
+ return 1;
+ return error;
+}
+
+/* end of dstore_test.c */
Property changes on: GNUnet/src/applications/dstore_mysql/dstore_test.c
___________________________________________________________________
Name: svn:eol-style
+ native
Copied: GNUnet/src/applications/dstore_sqlite (from rev 5801,
GNUnet/src/applications/dstore)
Deleted: GNUnet/src/applications/dstore_sqlite/Makefile.am
===================================================================
--- GNUnet/src/applications/dstore/Makefile.am 2007-12-05 22:52:59 UTC (rev
5801)
+++ GNUnet/src/applications/dstore_sqlite/Makefile.am 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -1,33 +0,0 @@
-INCLUDES = -I$(top_srcdir)/src/include
-
-plugindir = $(libdir)/GNUnet
-
-LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-plugin_LTLIBRARIES = \
- libgnunetmodule_dstore.la
-
-check_PROGRAMS = \
- dstore_test
-
-TESTS = $(check_PROGRAMS)
-
-AM_CPPFLAGS = $(CPPFLAGS) $(SQLITE_CPPFLAGS)
-
-libgnunetmodule_dstore_la_SOURCES = \
- dstore.c
-libgnunetmodule_dstore_la_LDFLAGS = \
- -export-dynamic -avoid-version -module \
- $(SQLITE_LDFLAGS)
-libgnunetmodule_dstore_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- -lsqlite3
-
-EXTRA_DIST = check.conf
-
-dstore_test_SOURCES = \
- dstore_test.c
-dstore_test_LDADD = \
- $(top_builddir)/src/server/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
Copied: GNUnet/src/applications/dstore_sqlite/Makefile.am (from rev 5824,
GNUnet/src/applications/dstore/Makefile.am)
===================================================================
--- GNUnet/src/applications/dstore_sqlite/Makefile.am
(rev 0)
+++ GNUnet/src/applications/dstore_sqlite/Makefile.am 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,33 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/GNUnet
+
+LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+plugin_LTLIBRARIES = \
+ libgnunetmodule_dstore_sqlite.la
+
+check_PROGRAMS = \
+ dstore_test
+
+TESTS = $(check_PROGRAMS)
+
+AM_CPPFLAGS = $(CPPFLAGS) $(SQLITE_CPPFLAGS)
+
+libgnunetmodule_dstore_sqlite_la_SOURCES = \
+ dstore.c
+libgnunetmodule_dstore_sqlite_la_LDFLAGS = \
+ -export-dynamic -avoid-version -module \
+ $(SQLITE_LDFLAGS)
+libgnunetmodule_dstore_sqlite_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ -lsqlite3
+
+EXTRA_DIST = check.conf
+
+dstore_test_SOURCES = \
+ dstore_test.c
+dstore_test_LDADD = \
+ $(top_builddir)/src/server/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
Deleted: GNUnet/src/applications/dstore_sqlite/check.conf
===================================================================
--- GNUnet/src/applications/dstore/check.conf 2007-12-05 22:52:59 UTC (rev
5801)
+++ GNUnet/src/applications/dstore_sqlite/check.conf 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -1,45 +0,0 @@
-[PATHS]
-GNUNETD_HOME = /tmp/gnunet-sqlite-sqstore-test
-
-[GNUNETD]
-GNUNETD_HOME = /tmp/gnunet-sqlite-sqstore-test
-HELLOEXPIRES = 1440
-LOGLEVEL = "NOTHING"
-LOGFILE = $GNUNETD_HOME/logs
-KEEPLOG = "0"
-PIDFILE = $GNUNETD_HOME/gnunet.pid
-HOSTS = $GNUNETD_HOME/data/hosts/
-HTTP-PROXY = ""
-HTTP-PROXY-PORT = 1080
-APPLICATIONS = "fs getoption stats traffic"
-PROCESS-PRIORITY = "NORMAL"
-
-[KEYVALUE_DATABASE]
-DIR = $GNUNETD_HOME/data/kv/
-
-[MODULES]
-sqstore = "sqstore_sqlite"
-topology = "topology_default"
-
-[NETWORK]
-PORT = 12087
-INTERFACE = ""
-IP = ""
-HELLOEXCHANGE = YES
-TRUSTED = "127.0.0.0/8;"
-
-[LOAD]
-BASICLIMITING = YES
-INTERFACES = ""
-MAXNETDOWNBPSTOTAL = 50000
-MAXNETUPBPSTOTAL = 50000
-MAXCPULOAD = 50
-
-[FS]
-QUOTA = 1024
-ACTIVEMIGRATION = YES
-DIR = $GNUNETD_HOME/data/fs/
-INDEX-DIRECTORY = $GNUNETD_HOME/data/shared/
-INDEX-QUOTA = 8192
-POOL = 32
-
Copied: GNUnet/src/applications/dstore_sqlite/check.conf (from rev 5824,
GNUnet/src/applications/dstore/check.conf)
===================================================================
--- GNUnet/src/applications/dstore_sqlite/check.conf
(rev 0)
+++ GNUnet/src/applications/dstore_sqlite/check.conf 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,46 @@
+[PATHS]
+GNUNETD_HOME = /tmp/gnunet-sqlite-sqstore-test
+
+[GNUNETD]
+GNUNETD_HOME = /tmp/gnunet-sqlite-sqstore-test
+HELLOEXPIRES = 1440
+LOGLEVEL = "NOTHING"
+LOGFILE = $GNUNETD_HOME/logs
+KEEPLOG = "0"
+PIDFILE = $GNUNETD_HOME/gnunet.pid
+HOSTS = $GNUNETD_HOME/data/hosts/
+HTTP-PROXY = ""
+HTTP-PROXY-PORT = 1080
+APPLICATIONS = "fs getoption stats traffic"
+PROCESS-PRIORITY = "NORMAL"
+
+[KEYVALUE_DATABASE]
+DIR = $GNUNETD_HOME/data/kv/
+
+[MODULES]
+sqstore = "sqstore_sqlite"
+topology = "topology_default"
+dstore = "dstore_sqlite"
+
+[NETWORK]
+PORT = 12087
+INTERFACE = ""
+IP = ""
+HELLOEXCHANGE = YES
+TRUSTED = "127.0.0.0/8;"
+
+[LOAD]
+BASICLIMITING = YES
+INTERFACES = ""
+MAXNETDOWNBPSTOTAL = 50000
+MAXNETUPBPSTOTAL = 50000
+MAXCPULOAD = 50
+
+[FS]
+QUOTA = 1024
+ACTIVEMIGRATION = YES
+DIR = $GNUNETD_HOME/data/fs/
+INDEX-DIRECTORY = $GNUNETD_HOME/data/shared/
+INDEX-QUOTA = 8192
+POOL = 32
+
Deleted: GNUnet/src/applications/dstore_sqlite/dstore.c
===================================================================
--- GNUnet/src/applications/dstore/dstore.c 2007-12-05 22:52:59 UTC (rev
5801)
+++ GNUnet/src/applications/dstore_sqlite/dstore.c 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -1,571 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2006, 2007 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.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_util_containers.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 GNUNET_CoreAPIForPlugins *coreAPI;
-
-static struct GNUNET_Mutex *lock;
-
-/**
- * Statistics service.
- */
-static GNUNET_Stats_ServiceAPI *stats;
-
-static unsigned int stat_dstore_size;
-
-/**
- * Estimate of the per-entry overhead (including indices).
- */
-#define OVERHEAD ((4+4+8+8*2+sizeof(GNUNET_HashCode)*2+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 { 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 ds071 ("
- " 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 TEXT NOT NULL DEFAULT '',"
- " value BLOB NOT NULL DEFAULT '')");
- SQLITE3_EXEC (dbh, "CREATE INDEX idx_key ON ds071 (key)");
- SQLITE3_EXEC (dbh, "CREATE INDEX idx_puttime ON ds071 (puttime)");
-}
-
-static int
-db_reset ()
-{
- int fd;
- sqlite3 *dbh;
- char *tmpl;
-
- if (fn != NULL)
- {
- UNLINK (fn);
- GNUNET_free (fn);
- }
- tmpl = "/tmp/dstoreXXXXXX";
-
-#ifdef MINGW
- fn = (char *) GNUNET_malloc (MAX_PATH + 1);
- plibc_conv_to_win_path (tmpl, fn);
-#else
- fn = GNUNET_strdup (tmpl);
-#endif
- fd = mkstemp (fn);
- if (fd == -1)
- {
- GNUNET_GE_BREAK (NULL, 0);
- GNUNET_free (fn);
- fn = NULL;
- return GNUNET_SYSERR;
- }
- CLOSE (fd);
- if (SQLITE_OK != sqlite3_open (fn, &dbh))
- 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;
- unsigned int dsize;
- unsigned int dtype;
- GNUNET_CronTime dputtime;
- GNUNET_CronTime dexpire;
- char *dcontent;
- 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, puttime, expire, key, value FROM ds071
ORDER BY puttime ASC",
- &stmt) != SQLITE_OK) ||
- (sq_prepare (dbh,
- "DELETE FROM ds071 "
- "WHERE size = ? AND type = ? AND puttime = ? AND expire = ?
AND key = ? AND value = ?",
- &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;
- }
- dcontent = GNUNET_malloc (MAX_CONTENT_SIZE);
- 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);
- dputtime = sqlite3_column_int64 (stmt, 2);
- dexpire = sqlite3_column_int64 (stmt, 3);
- GNUNET_GE_BREAK (NULL,
- sqlite3_column_bytes (stmt,
- 4) == sizeof (GNUNET_HashCode));
- GNUNET_GE_BREAK (NULL, dsize == sqlite3_column_bytes (stmt, 5));
- memcpy (&dkey, sqlite3_column_blob (stmt, 4), sizeof (GNUNET_HashCode));
- if (dsize >= MAX_CONTENT_SIZE)
- {
- GNUNET_GE_BREAK (NULL, 0);
- dsize = MAX_CONTENT_SIZE;
- }
- memcpy (dcontent, sqlite3_column_blob (stmt, 5), dsize);
- sqlite3_reset (stmt);
- sqlite3_bind_int (dstmt, 1, dsize);
- sqlite3_bind_int (dstmt, 2, dtype);
- sqlite3_bind_int64 (dstmt, 3, dputtime);
- sqlite3_bind_int64 (dstmt, 4, dexpire);
- sqlite3_bind_blob (dstmt,
- 5, &dkey, sizeof (GNUNET_HashCode),
- SQLITE_TRANSIENT);
- sqlite3_bind_blob (dstmt, 6, dcontent, dsize, SQLITE_TRANSIENT);
- 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;
- }
- 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));
- }
- GNUNET_free (dcontent);
- 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)
-{
- sqlite3 *dbh;
- sqlite3_stmt *stmt;
- int ret;
-
- if (size > MAX_CONTENT_SIZE)
- return GNUNET_SYSERR;
- GNUNET_mutex_lock (lock);
- if ((fn == NULL) || (SQLITE_OK != sqlite3_open (fn, &dbh)))
- {
- db_reset (dbh);
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
-#if DEBUG_DSTORE
- GNUNET_GE_LOG (coreAPI->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
- "dstore processes put `%.*s\n", size, data);
-#endif
-
- /* first try UPDATE */
- if (sq_prepare (dbh,
- "UPDATE ds071 SET puttime=?, expire=? "
- "WHERE key=? AND type=? AND size=? AND value=?",
- &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, GNUNET_get_time ())) ||
- (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_int (stmt, 4, type))
- || (SQLITE_OK != sqlite3_bind_int (stmt, 5, size))
- || (SQLITE_OK !=
- sqlite3_bind_blob (stmt, 6, data, size, SQLITE_TRANSIENT)))
- {
- 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 (bloom != NULL)
- GNUNET_bloomfilter_add (bloom, key);
-
- if (GNUNET_OK != checkQuota (dbh))
- {
- sqlite3_close (dbh);
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- if (sq_prepare (dbh,
- "INSERT INTO ds071 "
- "(size, type, puttime, expire, key, 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, GNUNET_get_time ())) &&
- (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, 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 (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;
-
- 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, &dbh)))
- {
- db_reset (dbh);
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
-#if DEBUG_DSTORE
- GNUNET_GE_LOG (coreAPI->ectx,
- GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
- "dstore processes get\n");
-#endif
- now = GNUNET_get_time ();
- if (sq_prepare (dbh,
- "SELECT size, value FROM ds071 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);
- 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_int (stmt, 3, now);
- cnt = 0;
- while (sqlite3_step (stmt) == SQLITE_ROW)
- {
- size = sqlite3_column_int (stmt, 0);
- if (size != sqlite3_column_bytes (stmt, 1))
- {
- GNUNET_GE_BREAK (NULL, 0);
- continue;
- }
- dat = sqlite3_column_blob (stmt, 1);
- handler (key, type, size, dat, closure);
- cnt++;
- }
- sqlite3_finalize (stmt);
- sqlite3_close (dbh);
- GNUNET_mutex_unlock (lock);
- return cnt;
-}
-
-GNUNET_Dstore_ServiceAPI *
-provide_module_dstore (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
- if (GNUNET_OK != db_reset ())
- {
- GNUNET_GE_BREAK (capi->ectx, 0);
- return NULL;
- }
- lock = GNUNET_mutex_create (GNUNET_NO);
-
-
- coreAPI = capi;
- 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->requestService ("stats");
- if (stats != NULL)
- stat_dstore_size = stats->create (gettext_noop ("# bytes in dstore"));
- return &api;
-}
-
-/**
- * Shutdown the module.
- */
-void
-release_module_dstore ()
-{
- UNLINK (fn);
- GNUNET_free (fn);
- 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->releaseService (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 */
Copied: GNUnet/src/applications/dstore_sqlite/dstore.c (from rev 5824,
GNUnet/src/applications/dstore/dstore.c)
===================================================================
--- GNUnet/src/applications/dstore_sqlite/dstore.c
(rev 0)
+++ GNUnet/src/applications/dstore_sqlite/dstore.c 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,570 @@
+/*
+ This file is part of GNUnet.
+ (C) 2006, 2007 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.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 GNUNET_CoreAPIForPlugins *coreAPI;
+
+static struct GNUNET_Mutex *lock;
+
+/**
+ * Statistics service.
+ */
+static GNUNET_Stats_ServiceAPI *stats;
+
+static unsigned int stat_dstore_size;
+
+/**
+ * Estimate of the per-entry overhead (including indices).
+ */
+#define OVERHEAD ((4+4+8+8*2+sizeof(GNUNET_HashCode)*2+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 { 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 ds071 ("
+ " 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 TEXT NOT NULL DEFAULT '',"
+ " value BLOB NOT NULL DEFAULT '')");
+ SQLITE3_EXEC (dbh, "CREATE INDEX idx_key ON ds071 (key)");
+ SQLITE3_EXEC (dbh, "CREATE INDEX idx_puttime ON ds071 (puttime)");
+}
+
+static int
+db_reset ()
+{
+ int fd;
+ sqlite3 *dbh;
+ char *tmpl;
+
+ if (fn != NULL)
+ {
+ UNLINK (fn);
+ GNUNET_free (fn);
+ }
+ tmpl = "/tmp/dstoreXXXXXX";
+
+#ifdef MINGW
+ fn = (char *) GNUNET_malloc (MAX_PATH + 1);
+ plibc_conv_to_win_path (tmpl, fn);
+#else
+ fn = GNUNET_strdup (tmpl);
+#endif
+ fd = mkstemp (fn);
+ if (fd == -1)
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ GNUNET_free (fn);
+ fn = NULL;
+ return GNUNET_SYSERR;
+ }
+ CLOSE (fd);
+ if (SQLITE_OK != sqlite3_open (fn, &dbh))
+ 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;
+ unsigned int dsize;
+ unsigned int dtype;
+ GNUNET_CronTime dputtime;
+ GNUNET_CronTime dexpire;
+ char *dcontent;
+ 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, puttime, expire, key, value FROM ds071
ORDER BY puttime ASC",
+ &stmt) != SQLITE_OK) ||
+ (sq_prepare (dbh,
+ "DELETE FROM ds071 "
+ "WHERE size = ? AND type = ? AND puttime = ? AND expire = ?
AND key = ? AND value = ?",
+ &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;
+ }
+ dcontent = GNUNET_malloc (MAX_CONTENT_SIZE);
+ 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);
+ dputtime = sqlite3_column_int64 (stmt, 2);
+ dexpire = sqlite3_column_int64 (stmt, 3);
+ GNUNET_GE_BREAK (NULL,
+ sqlite3_column_bytes (stmt,
+ 4) == sizeof (GNUNET_HashCode));
+ GNUNET_GE_BREAK (NULL, dsize == sqlite3_column_bytes (stmt, 5));
+ memcpy (&dkey, sqlite3_column_blob (stmt, 4), sizeof (GNUNET_HashCode));
+ if (dsize >= MAX_CONTENT_SIZE)
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ dsize = MAX_CONTENT_SIZE;
+ }
+ memcpy (dcontent, sqlite3_column_blob (stmt, 5), dsize);
+ sqlite3_reset (stmt);
+ sqlite3_bind_int (dstmt, 1, dsize);
+ sqlite3_bind_int (dstmt, 2, dtype);
+ sqlite3_bind_int64 (dstmt, 3, dputtime);
+ sqlite3_bind_int64 (dstmt, 4, dexpire);
+ sqlite3_bind_blob (dstmt,
+ 5, &dkey, sizeof (GNUNET_HashCode),
+ SQLITE_TRANSIENT);
+ sqlite3_bind_blob (dstmt, 6, dcontent, dsize, SQLITE_TRANSIENT);
+ 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;
+ }
+ 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));
+ }
+ GNUNET_free (dcontent);
+ 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)
+{
+ sqlite3 *dbh;
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (size > MAX_CONTENT_SIZE)
+ return GNUNET_SYSERR;
+ GNUNET_mutex_lock (lock);
+ if ((fn == NULL) || (SQLITE_OK != sqlite3_open (fn, &dbh)))
+ {
+ db_reset (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "dstore processes put `%.*s\n", size, data);
+#endif
+
+ /* first try UPDATE */
+ if (sq_prepare (dbh,
+ "UPDATE ds071 SET puttime=?, expire=? "
+ "WHERE key=? AND type=? AND size=? AND value=?",
+ &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, GNUNET_get_time ())) ||
+ (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_int (stmt, 4, type))
+ || (SQLITE_OK != sqlite3_bind_int (stmt, 5, size))
+ || (SQLITE_OK !=
+ sqlite3_bind_blob (stmt, 6, data, size, SQLITE_TRANSIENT)))
+ {
+ 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 (bloom != NULL)
+ GNUNET_bloomfilter_add (bloom, key);
+
+ if (GNUNET_OK != checkQuota (dbh))
+ {
+ sqlite3_close (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+ if (sq_prepare (dbh,
+ "INSERT INTO ds071 "
+ "(size, type, puttime, expire, key, 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, GNUNET_get_time ())) &&
+ (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, 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 (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;
+
+ 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, &dbh)))
+ {
+ db_reset (dbh);
+ GNUNET_mutex_unlock (lock);
+ return GNUNET_SYSERR;
+ }
+#if DEBUG_DSTORE
+ GNUNET_GE_LOG (coreAPI->ectx,
+ GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,
+ "dstore processes get\n");
+#endif
+ now = GNUNET_get_time ();
+ if (sq_prepare (dbh,
+ "SELECT size, value FROM ds071 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);
+ 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_int (stmt, 3, now);
+ cnt = 0;
+ while (sqlite3_step (stmt) == SQLITE_ROW)
+ {
+ size = sqlite3_column_int (stmt, 0);
+ if (size != sqlite3_column_bytes (stmt, 1))
+ {
+ GNUNET_GE_BREAK (NULL, 0);
+ continue;
+ }
+ dat = sqlite3_column_blob (stmt, 1);
+ handler (key, type, size, dat, closure);
+ cnt++;
+ }
+ 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
+ if (GNUNET_OK != db_reset ())
+ {
+ GNUNET_GE_BREAK (capi->ectx, 0);
+ return NULL;
+ }
+ lock = GNUNET_mutex_create (GNUNET_NO);
+
+
+ coreAPI = capi;
+ 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->requestService ("stats");
+ if (stats != NULL)
+ stat_dstore_size = stats->create (gettext_noop ("# bytes in dstore"));
+ return &api;
+}
+
+/**
+ * Shutdown the module.
+ */
+void
+release_module_dstore_sqlite ()
+{
+ UNLINK (fn);
+ GNUNET_free (fn);
+ 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->releaseService (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 */
Deleted: GNUnet/src/applications/dstore_sqlite/dstore_test.c
===================================================================
--- GNUnet/src/applications/dstore/dstore_test.c 2007-12-05 22:52:59 UTC
(rev 5801)
+++ GNUnet/src/applications/dstore_sqlite/dstore_test.c 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -1,120 +0,0 @@
-/*
- 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_util_cron.h"
-#include "gnunet_util_config_impl.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 void
-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;
- }
-}
-
-/**
- * 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;
-
- cfg = GNUNET_GC_create ();
- if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
- {
- GNUNET_GC_free (cfg);
- return -1;
- }
- cron = cron_create (NULL);
- initCore (NULL, cfg, cron, NULL);
- api = requestService ("dstore");
- if (api != NULL)
- {
- ok = test (api);
- releaseService (api);
- }
- else
- ok = GNUNET_SYSERR;
- doneCore ();
- if (ok == GNUNET_SYSERR)
- return 1;
- return error;
-}
-
-/* end of dstore_test.c */
Copied: GNUnet/src/applications/dstore_sqlite/dstore_test.c (from rev 5824,
GNUnet/src/applications/dstore/dstore_test.c)
===================================================================
--- GNUnet/src/applications/dstore_sqlite/dstore_test.c
(rev 0)
+++ GNUnet/src/applications/dstore_sqlite/dstore_test.c 2007-12-09 19:34:38 UTC
(rev 5825)
@@ -0,0 +1,118 @@
+/*
+ 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 void
+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;
+ }
+}
+
+/**
+ * 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;
+
+ cfg = GNUNET_GC_create ();
+ if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
+ {
+ GNUNET_GC_free (cfg);
+ return -1;
+ }
+ cron = cron_create (NULL);
+ initCore (NULL, cfg, cron, NULL);
+ api = requestService ("dstore");
+ if (api != NULL)
+ {
+ ok = test (api);
+ releaseService (api);
+ }
+ else
+ ok = GNUNET_SYSERR;
+ doneCore ();
+ if (ok == GNUNET_SYSERR)
+ return 1;
+ return error;
+}
+
+/* end of dstore_test.c */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r5825 - in GNUnet/src/applications: . dstore_mysql dstore_sqlite,
gnunet <=