gnunet-svn
[Top][All Lists]
Advanced

[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,
+                                            &quota);
+  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,
-                                            &quota);
-  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,
+                                            &quota);
+  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 */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]