NAMESTORE: rename flat plugin to heap
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Mon, 15 Oct 2018 10:05:11 +0000 (19:05 +0900)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Mon, 15 Oct 2018 10:05:11 +0000 (19:05 +0900)
src/namestore/Makefile.am
src/namestore/namestore.conf.in
src/namestore/perf_namestore_api_flat.conf [deleted file]
src/namestore/perf_namestore_api_heap.conf [new file with mode: 0644]
src/namestore/plugin_namestore_flat.c [deleted file]
src/namestore/plugin_namestore_heap.c [new file with mode: 0644]
src/namestore/test_namestore_api_flat.conf [deleted file]
src/namestore/test_namestore_api_heap.conf [new file with mode: 0644]
src/namestore/test_plugin_namestore_flat.conf [deleted file]
src/namestore/test_plugin_namestore_heap.conf [new file with mode: 0644]

index a349921d7f510f9995699a4f48d1daecc17a49f7..54357dd1e6a3cd9a449475629555008440f8cda9 100644 (file)
@@ -20,26 +20,26 @@ if USE_COVERAGE
   XLIBS = -lgcov
 endif
 
-FLAT_PLUGIN = libgnunet_plugin_namestore_flat.la
+HEAP_PLUGIN = libgnunet_plugin_namestore_heap.la
 if HAVE_TESTING
-FLAT_TESTS = test_plugin_namestore_flat \
- test_namestore_api_store_flat \
- test_namestore_api_store_update_flat \
- test_namestore_api_remove_flat \
- test_namestore_api_zone_iteration_flat \
- test_namestore_api_lookup_nick_flat \
- test_namestore_api_monitoring_flat \
- test_namestore_api_lookup_public_flat \
- test_namestore_api_lookup_private_flat \
- test_namestore_api_lookup_shadow_flat \
- test_namestore_api_lookup_shadow_filter_flat \
- test_namestore_api_remove_not_existing_record_flat \
- test_namestore_api_zone_iteration_nick_flat \
- test_namestore_api_zone_iteration_specific_zone_flat \
- test_namestore_api_zone_iteration_stop_flat \
- test_namestore_api_monitoring_existing_flat \
- test_namestore_api_zone_to_name_flat \
- perf_namestore_api_zone_iteration_flat
+HEAP_TESTS = test_plugin_namestore_heap \
+ test_namestore_api_store_heap \
+ test_namestore_api_store_update_heap \
+ test_namestore_api_remove_heap \
+ test_namestore_api_zone_iteration_heap \
+ test_namestore_api_lookup_nick_heap \
+ test_namestore_api_monitoring_heap \
+ test_namestore_api_lookup_public_heap \
+ test_namestore_api_lookup_private_heap \
+ test_namestore_api_lookup_shadow_heap \
+ test_namestore_api_lookup_shadow_filter_heap \
+ test_namestore_api_remove_not_existing_record_heap \
+ test_namestore_api_zone_iteration_nick_heap \
+ test_namestore_api_zone_iteration_specific_zone_heap \
+ test_namestore_api_zone_iteration_stop_heap \
+ test_namestore_api_monitoring_existing_heap \
+ test_namestore_api_zone_to_name_heap \
+ perf_namestore_api_zone_iteration_heap
 endif
 
 if HAVE_SQLITE
@@ -94,7 +94,7 @@ if HAVE_SQLITE
 check_PROGRAMS = \
  $(SQLITE_TESTS) \
  $(POSTGRES_TESTS) \
- $(FLAT_TESTS)
+ $(HEAP_TESTS)
 endif
 
 if ENABLE_TEST_RUN
@@ -180,18 +180,18 @@ gnunet_service_namestore_LDADD = \
 plugin_LTLIBRARIES = \
   $(SQLITE_PLUGIN) \
   $(POSTGRES_PLUGIN) \
-       $(FLAT_PLUGIN)
+       $(HEAP_PLUGIN)
 
 
 
-libgnunet_plugin_namestore_flat_la_SOURCES = \
-  plugin_namestore_flat.c
-libgnunet_plugin_namestore_flat_la_LIBADD = \
+libgnunet_plugin_namestore_heap_la_SOURCES = \
+  plugin_namestore_heap.c
+libgnunet_plugin_namestore_heap_la_LIBADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la  \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
   $(LTLIBINTL)
-libgnunet_plugin_namestore_flat_la_LDFLAGS = \
+libgnunet_plugin_namestore_heap_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
 
 
@@ -217,9 +217,9 @@ libgnunet_plugin_namestore_postgres_la_LIBADD = \
 libgnunet_plugin_namestore_postgres_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
 
-test_namestore_api_store_flat_SOURCES = \
+test_namestore_api_store_heap_SOURCES = \
  test_namestore_api_store.c
-test_namestore_api_store_flat_LDADD = \
+test_namestore_api_store_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -241,9 +241,9 @@ test_namestore_api_store_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_store_update_flat_SOURCES = \
+test_namestore_api_store_update_heap_SOURCES = \
  test_namestore_api_store_update.c
-test_namestore_api_store_update_flat_LDADD = \
+test_namestore_api_store_update_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -268,9 +268,9 @@ test_namestore_api_store_update_postgres_LDADD = \
   $(top_builddir)/src/namecache/libgnunetnamecache.la \
   libgnunetnamestore.la
 
-test_namestore_api_lookup_public_flat_SOURCES = \
+test_namestore_api_lookup_public_heap_SOURCES = \
  test_namestore_api_lookup_public.c
-test_namestore_api_lookup_public_flat_LDADD = \
+test_namestore_api_lookup_public_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -313,18 +313,18 @@ test_namestore_api_lookup_nick_postgres_LDADD = \
   $(top_builddir)/src/namecache/libgnunetnamecache.la \
   libgnunetnamestore.la
 
-test_namestore_api_lookup_nick_flat_SOURCES = \
+test_namestore_api_lookup_nick_heap_SOURCES = \
  test_namestore_api_lookup_nick.c
-test_namestore_api_lookup_nick_flat_LDADD = \
+test_namestore_api_lookup_nick_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   $(top_builddir)/src/namecache/libgnunetnamecache.la \
   libgnunetnamestore.la
 
-test_namestore_api_lookup_private_flat_SOURCES = \
+test_namestore_api_lookup_private_heap_SOURCES = \
  test_namestore_api_lookup_private.c
-test_namestore_api_lookup_private_flat_LDADD = \
+test_namestore_api_lookup_private_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -349,9 +349,9 @@ test_namestore_api_lookup_private_postgres_LDADD = \
   $(top_builddir)/src/namecache/libgnunetnamecache.la \
   libgnunetnamestore.la
 
-test_namestore_api_lookup_shadow_flat_SOURCES = \
+test_namestore_api_lookup_shadow_heap_SOURCES = \
  test_namestore_api_lookup_shadow.c
-test_namestore_api_lookup_shadow_flat_LDADD = \
+test_namestore_api_lookup_shadow_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -376,9 +376,9 @@ test_namestore_api_lookup_shadow_postgres_LDADD = \
   $(top_builddir)/src/namecache/libgnunetnamecache.la \
   libgnunetnamestore.la
 
-test_namestore_api_lookup_shadow_filter_flat_SOURCES = \
+test_namestore_api_lookup_shadow_filter_heap_SOURCES = \
  test_namestore_api_lookup_shadow_filter.c
-test_namestore_api_lookup_shadow_filter_flat_LDADD = \
+test_namestore_api_lookup_shadow_filter_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -418,17 +418,17 @@ test_namestore_api_remove_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_remove_flat_SOURCES = \
+test_namestore_api_remove_heap_SOURCES = \
  test_namestore_api_remove.c
-test_namestore_api_remove_flat_LDADD = \
+test_namestore_api_remove_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_remove_not_existing_record_flat_SOURCES = \
+test_namestore_api_remove_not_existing_record_heap_SOURCES = \
  test_namestore_api_remove_not_existing_record.c
-test_namestore_api_remove_not_existing_record_flat_LDADD = \
+test_namestore_api_remove_not_existing_record_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -450,9 +450,9 @@ test_namestore_api_remove_not_existing_record_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_zone_to_name_flat_SOURCES = \
+test_namestore_api_zone_to_name_heap_SOURCES = \
  test_namestore_api_zone_to_name.c
-test_namestore_api_zone_to_name_flat_LDADD = \
+test_namestore_api_zone_to_name_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   libgnunetnamestore.la
@@ -471,9 +471,9 @@ test_namestore_api_zone_to_name_postgres_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   libgnunetnamestore.la
 
-test_namestore_api_monitoring_flat_SOURCES = \
+test_namestore_api_monitoring_heap_SOURCES = \
  test_namestore_api_monitoring.c
-test_namestore_api_monitoring_flat_LDADD = \
+test_namestore_api_monitoring_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   libgnunetnamestore.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -495,9 +495,9 @@ test_namestore_api_monitoring_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   $(top_builddir)/src/util/libgnunetutil.la
 
-test_namestore_api_monitoring_existing_flat_SOURCES = \
+test_namestore_api_monitoring_existing_heap_SOURCES = \
  test_namestore_api_monitoring_existing.c
-test_namestore_api_monitoring_existing_flat_LDADD = \
+test_namestore_api_monitoring_existing_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   libgnunetnamestore.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -519,9 +519,9 @@ test_namestore_api_monitoring_existing_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   $(top_builddir)/src/util/libgnunetutil.la
 
-test_namestore_api_zone_iteration_flat_SOURCES = \
+test_namestore_api_zone_iteration_heap_SOURCES = \
  test_namestore_api_zone_iteration.c
-test_namestore_api_zone_iteration_flat_LDADD = \
+test_namestore_api_zone_iteration_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -559,17 +559,17 @@ perf_namestore_api_zone_iteration_sqlite_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-perf_namestore_api_zone_iteration_flat_SOURCES = \
+perf_namestore_api_zone_iteration_heap_SOURCES = \
  perf_namestore_api_zone_iteration.c
-perf_namestore_api_zone_iteration_flat_LDADD = \
+perf_namestore_api_zone_iteration_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_zone_iteration_nick_flat_SOURCES = \
+test_namestore_api_zone_iteration_nick_heap_SOURCES = \
  test_namestore_api_zone_iteration_nick.c
-test_namestore_api_zone_iteration_nick_flat_LDADD = \
+test_namestore_api_zone_iteration_nick_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -591,9 +591,9 @@ test_namestore_api_zone_iteration_nick_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_zone_iteration_specific_zone_flat_SOURCES = \
+test_namestore_api_zone_iteration_specific_zone_heap_SOURCES = \
  test_namestore_api_zone_iteration_specific_zone.c
-test_namestore_api_zone_iteration_specific_zone_flat_LDADD = \
+test_namestore_api_zone_iteration_specific_zone_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -615,9 +615,9 @@ test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_namestore_api_zone_iteration_stop_flat_SOURCES = \
+test_namestore_api_zone_iteration_stop_heap_SOURCES = \
  test_namestore_api_zone_iteration_stop.c
-test_namestore_api_zone_iteration_stop_flat_LDADD = \
+test_namestore_api_zone_iteration_stop_heap_LDADD = \
   $(top_builddir)/src/testing/libgnunettesting.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
@@ -639,9 +639,9 @@ test_namestore_api_zone_iteration_stop_postgres_LDADD = \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
   libgnunetnamestore.la
 
-test_plugin_namestore_flat_SOURCES = \
+test_plugin_namestore_heap_SOURCES = \
  test_plugin_namestore.c
-test_plugin_namestore_flat_LDADD = \
+test_plugin_namestore_heap_LDADD = \
  $(top_builddir)/src/testing/libgnunettesting.la \
  $(top_builddir)/src/util/libgnunetutil.la
 
@@ -666,13 +666,13 @@ EXTRA_DIST = \
   test_namestore_api.conf \
   test_namestore_api_postgres.conf \
   test_namestore_api_sqlite.conf \
-  test_namestore_api_flat.conf \
+  test_namestore_api_heap.conf \
   perf_namestore_api_postgres.conf \
   perf_namestore_api_sqlite.conf \
-  perf_namestore_api_flat.conf \
+  perf_namestore_api_heap.conf \
   test_plugin_namestore_sqlite.conf \
   test_plugin_namestore_postgres.conf \
-  test_plugin_namestore_flat.conf \
+  test_plugin_namestore_heap.conf \
   test_hostkey \
   zonefiles/S5I9DSGQVAB5FVV16T3B3CC5H1B2JGL3Q412JBKURME8EKU0600G.zkey \
   zonefiles/AQ835GVL939H4O8QJQ7GBLPTQC0QAAO91BN7QK01BA63MDSK6I4G.zkey \
index eb95f95bebf6f59bb6ac0a920210d3b436869347..b5fb45abc0f76c0d7d216c2737a6ef02bcea2d5d 100644 (file)
@@ -23,8 +23,8 @@ CACHE_KEYS = YES
 [namestore-sqlite]
 FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db
 
-[namestore-flat]
-FILENAME = $GNUNET_DATA_HOME/namestore/flat.db
+[namestore-heap]
+FILENAME = $GNUNET_DATA_HOME/namestore/heap.db
 
 
 [namestore-postgres]
diff --git a/src/namestore/perf_namestore_api_flat.conf b/src/namestore/perf_namestore_api_flat.conf
deleted file mode 100644 (file)
index f356e90..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@INLINE@ test_namestore_api.conf
-
-[namestore]
-DATABASE = flat
-
-[namecache]
-DISABLE = YES
-
-[namestore-flat]
-FILENAME = $GNUNET_TEST_HOME/namestore/flat.db
diff --git a/src/namestore/perf_namestore_api_heap.conf b/src/namestore/perf_namestore_api_heap.conf
new file mode 100644 (file)
index 0000000..a12761a
--- /dev/null
@@ -0,0 +1,10 @@
+@INLINE@ test_namestore_api.conf
+
+[namestore]
+DATABASE = heap
+
+[namecache]
+DISABLE = YES
+
+[namestore-heap]
+FILENAME = $GNUNET_TEST_HOME/namestore/heap.db
diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c
deleted file mode 100644 (file)
index 4873f6e..0000000
+++ /dev/null
@@ -1,801 +0,0 @@
- /*
-  * This file is part of GNUnet
-  * Copyright (C) 2009-2015, 2018 GNUnet e.V.
-  *
-  * GNUnet is free software: you can redistribute it and/or modify it
-  * under the terms of the GNU Affero General Public License as published
-  * by the Free Software Foundation, either version 3 of the License,
-  * or (at your option) any later version.
-  *
-  * GNUnet is distributed in the hope that it will be useful, but
-  * WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  * Affero General Public License for more details.
-  *
-  * You should have received a copy of the GNU Affero General Public License
-  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  */
-
-/**
- * @file namestore/plugin_namestore_flat.c
- * @brief file-based namestore backend
- * @author Martin Schanzenbach
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "gnunet_namestore_plugin.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "namestore.h"
-
-/**
- * Context for all functions in this plugin.
- */
-struct Plugin
-{
-
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Database filename.
-   */
-  char *fn;
-
-  /**
-   * HashMap
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *hm;
-
-};
-
-
-struct FlatFileEntry
-{
-  /**
-   * Entry zone
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey private_key;
-
-  /**
-   * Record cound
-   */
-  uint32_t record_count;
-
-  /**
-   * Rvalue
-   */
-  uint64_t rvalue;
-
-  /**
-   * Record data
-   */
-  struct GNUNET_GNSRECORD_Data *record_data;
-
-  /**
-   * Label
-   */
-  char *label;
-
-
-};
-
-
-/**
- * Initialize the database connections and associated
- * data structures (create tables and indices
- * as needed as well).
- *
- * @param plugin the plugin context (state for this module)
- * @return #GNUNET_OK on success
- */
-static int
-database_setup (struct Plugin *plugin)
-{
-  char *afsdir;
-  char *record_data;
-  char *zone_private_key;
-  char *record_data_b64;
-  char *buffer;
-  char *line;
-  char *label;
-  char *rvalue;
-  char *record_count;
-  size_t record_data_size;
-  uint64_t size;
-  struct GNUNET_HashCode hkey;
-  struct GNUNET_DISK_FileHandle *fh;
-  struct FlatFileEntry *entry;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
-                                               "namestore-flat",
-                                               "FILENAME",
-                                              &afsdir))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               "namestore-flat",
-                              "FILENAME");
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_DISK_file_test (afsdir))
-  {
-    if (GNUNET_OK !=
-       GNUNET_DISK_directory_create_for_file (afsdir))
-    {
-      GNUNET_break (0);
-      GNUNET_free (afsdir);
-      return GNUNET_SYSERR;
-    }
-  }
-  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
-  plugin->fn = afsdir;
-
-  /* Load data from file into hashmap */
-  plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
-                                                     GNUNET_NO);
-  fh = GNUNET_DISK_file_open (afsdir,
-                              GNUNET_DISK_OPEN_CREATE |
-                              GNUNET_DISK_OPEN_READWRITE,
-                              GNUNET_DISK_PERM_USER_WRITE |
-                              GNUNET_DISK_PERM_USER_READ);
-  if (NULL == fh)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-         _("Unable to initialize file: %s.\n"),
-         afsdir);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_SYSERR ==
-      GNUNET_DISK_file_size (afsdir,
-                             &size,
-                             GNUNET_YES,
-                             GNUNET_YES))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-         _("Unable to get filesize: %s.\n"),
-         afsdir);
-    GNUNET_DISK_file_close (fh);
-    return GNUNET_SYSERR;
-  }
-
-  buffer = GNUNET_malloc (size + 1);
-  if (GNUNET_SYSERR ==
-      GNUNET_DISK_file_read (fh,
-                             buffer,
-                             size))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-         _("Unable to read file: %s.\n"),
-         afsdir);
-    GNUNET_free (buffer);
-    GNUNET_DISK_file_close (fh);
-    return GNUNET_SYSERR;
-  }
-  buffer[size] = '\0';
-  GNUNET_DISK_file_close (fh);
-
-  if (0 < size)
-  {
-    line = strtok (buffer, "\n");
-    while (line != NULL)
-    {
-      zone_private_key = strtok (line, ",");
-      if (NULL == zone_private_key)
-        break;
-      rvalue = strtok (NULL, ",");
-      if (NULL == rvalue)
-        break;
-      record_count = strtok (NULL, ",");
-      if (NULL == record_count)
-        break;
-      record_data_b64 = strtok (NULL, ",");
-      if (NULL == record_data_b64)
-        break;
-      label = strtok (NULL, ",");
-      if (NULL == label)
-        break;
-      line = strtok (NULL, "\n");
-      entry = GNUNET_new (struct FlatFileEntry);
-      {
-        unsigned long long ll;
-
-        if (1 != sscanf (rvalue,
-                         "%llu",
-                         &ll))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Error parsing entry\n");
-          GNUNET_free (entry);
-          break;
-        }
-        entry->rvalue = (uint64_t) ll;
-      }
-      {
-        unsigned int ui;
-
-        if (1 != sscanf (record_count,
-                         "%u",
-                         &ui))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Error parsing entry\n");
-          GNUNET_free (entry);
-          break;
-        }
-        entry->record_count = (uint32_t) ui;
-      }
-      entry->label = GNUNET_strdup (label);
-      record_data_size
-       = GNUNET_STRINGS_base64_decode (record_data_b64,
-                                       strlen (record_data_b64),
-                                       (void **) &record_data);
-      entry->record_data =
-        GNUNET_new_array (entry->record_count,
-                         struct GNUNET_GNSRECORD_Data);
-      if (GNUNET_OK !=
-         GNUNET_GNSRECORD_records_deserialize (record_data_size,
-                                               record_data,
-                                               entry->record_count,
-                                               entry->record_data))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Unable to deserialize record %s\n",
-                   label);
-        GNUNET_free (entry->label);
-        GNUNET_free (entry);
-        GNUNET_free (record_data);
-        break;
-      }
-      GNUNET_free (record_data);
-
-      {
-        struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key;
-
-        GNUNET_STRINGS_base64_decode (zone_private_key,
-                                      strlen (zone_private_key),
-                                      (void**)&private_key);
-        entry->private_key = *private_key;
-        GNUNET_free (private_key);
-      }
-
-      {
-        char *key;
-        size_t key_len;
-
-        key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
-        key = GNUNET_malloc (strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
-        GNUNET_memcpy (key,
-                       label,
-                       strlen (label));
-        GNUNET_memcpy (key+strlen(label),
-                       &entry->private_key,
-                       sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
-        GNUNET_CRYPTO_hash (key,
-                            key_len,
-                            &hkey);
-        GNUNET_free (key);
-      }
-      if (GNUNET_OK !=
-          GNUNET_CONTAINER_multihashmap_put (plugin->hm,
-                                             &hkey,
-                                             entry,
-                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
-      {
-        GNUNET_free (entry);
-        GNUNET_break (0);
-      }
-    }
-  }
-  GNUNET_free (buffer);
-  return GNUNET_OK;
-}
-
-
-/**
- * Store values in hashmap in file and free data
- *
- * @param plugin the plugin context
- * @param key key in the map
- * @param value a `struct FlatFileEntry`
- */
-static int
-store_and_free_entries (void *cls,
-                        const struct GNUNET_HashCode *key,
-                        void *value)
-{
-  struct GNUNET_DISK_FileHandle *fh = cls;
-  struct FlatFileEntry *entry = value;
-  char *line;
-  char *zone_private_key;
-  char *record_data_b64;
-  ssize_t data_size;
-
-  (void) key;
-  GNUNET_STRINGS_base64_encode (&entry->private_key,
-                                sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
-                                &zone_private_key);
-  data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
-                                                 entry->record_data);
-  if (data_size < 0)
-  {
-    GNUNET_break (0);
-    GNUNET_free (zone_private_key);
-    return GNUNET_SYSERR;
-  }
-  if (data_size >= UINT16_MAX)
-  {
-    GNUNET_break (0);
-    GNUNET_free (zone_private_key);
-    return GNUNET_SYSERR;
-  }
-  {
-    char data[data_size];
-    ssize_t ret;
-
-    ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
-                                             entry->record_data,
-                                             data_size,
-                                             data);
-    if ( (ret < 0) ||
-        (data_size != ret) )
-    {
-      GNUNET_break (0);
-      GNUNET_free (zone_private_key);
-      return GNUNET_SYSERR;
-    }
-    GNUNET_STRINGS_base64_encode (data,
-                                  data_size,
-                                  &record_data_b64);
-  }
-  GNUNET_asprintf (&line,
-                   "%s,%llu,%u,%s,%s\n",
-                   zone_private_key,
-                   (unsigned long long) entry->rvalue,
-                   (unsigned int) entry->record_count,
-                   record_data_b64,
-                   entry->label);
-  GNUNET_free (record_data_b64);
-  GNUNET_free (zone_private_key);
-
-  GNUNET_DISK_file_write (fh,
-                          line,
-                          strlen (line));
-
-  GNUNET_free (line);
-  GNUNET_free (entry->label);
-  GNUNET_free (entry->record_data);
-  GNUNET_free (entry);
-  return GNUNET_YES;
-}
-
-
-/**
- * Shutdown database connection and associate data
- * structures.
- * @param plugin the plugin context (state for this module)
- */
-static void
-database_shutdown (struct Plugin *plugin)
-{
-  struct GNUNET_DISK_FileHandle *fh;
-
-  fh = GNUNET_DISK_file_open (plugin->fn,
-                              GNUNET_DISK_OPEN_CREATE |
-                              GNUNET_DISK_OPEN_TRUNCATE |
-                              GNUNET_DISK_OPEN_READWRITE,
-                              GNUNET_DISK_PERM_USER_WRITE |
-                              GNUNET_DISK_PERM_USER_READ);
-  if (NULL == fh)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Unable to initialize file: %s.\n"),
-                plugin->fn);
-    return;
-  }
-
-  GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
-                                         &store_and_free_entries,
-                                         fh);
-  GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
-  GNUNET_DISK_file_close (fh);
-}
-
-
-/**
- * Store a record in the datastore.  Removes any existing record in the
- * same zone with the same name.
- *
- * @param cls closure (internal context for the plugin)
- * @param zone_key private key of the zone
- * @param label name that is being mapped (at most 255 characters long)
- * @param rd_count number of entries in @a rd array
- * @param rd array of records with data to store
- * @return #GNUNET_OK on success, else #GNUNET_SYSERR
- */
-static int
-namestore_flat_store_records (void *cls,
-                              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
-                              const char *label,
-                              unsigned int rd_count,
-                              const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct Plugin *plugin = cls;
-  uint64_t rvalue;
-  size_t key_len;
-  char *key;
-  struct GNUNET_HashCode hkey;
-  struct FlatFileEntry *entry;
-
-  rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                    UINT64_MAX);
-  key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
-  key = GNUNET_malloc (key_len);
-  GNUNET_memcpy (key,
-                 label,
-                 strlen (label));
-  GNUNET_memcpy (key + strlen(label),
-                 zone_key,
-                 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
-  GNUNET_CRYPTO_hash (key,
-                      key_len,
-                      &hkey);
-  GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
-                                            &hkey);
-  if (0 == rd_count)
-  {
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
-                     "sqlite",
-                     "Record deleted\n");
-    return GNUNET_OK;
-  }
-  entry = GNUNET_new (struct FlatFileEntry);
-  GNUNET_asprintf (&entry->label,
-                   label,
-                   strlen (label));
-  GNUNET_memcpy (&entry->private_key,
-                 zone_key,
-                 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
-  entry->rvalue = rvalue;
-  entry->record_count = rd_count;
-  entry->record_data = GNUNET_new_array (rd_count,
-                                         struct GNUNET_GNSRECORD_Data);
-  for (unsigned int i = 0; i < rd_count; i++)
-  {
-    entry->record_data[i].expiration_time = rd[i].expiration_time;
-    entry->record_data[i].record_type = rd[i].record_type;
-    entry->record_data[i].flags = rd[i].flags;
-    entry->record_data[i].data_size = rd[i].data_size;
-    entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
-    GNUNET_memcpy ((char*)entry->record_data[i].data,
-                   rd[i].data,
-                   rd[i].data_size);
-  }
-  return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
-                                            &hkey,
-                                            entry,
-                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-}
-
-
-/**
- * Lookup records in the datastore for which we are the authority.
- *
- * @param cls closure (internal context for the plugin)
- * @param zone private key of the zone
- * @param label name of the record in the zone
- * @param iter function to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
- */
-static int
-namestore_flat_lookup_records (void *cls,
-                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                               const char *label,
-                               GNUNET_NAMESTORE_RecordIterator iter,
-                               void *iter_cls)
-{
-  struct Plugin *plugin = cls;
-  struct FlatFileEntry *entry;
-  struct GNUNET_HashCode hkey;
-  char *key;
-  size_t key_len;
-
-  if (NULL == zone)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
-  key = GNUNET_malloc (key_len);
-  GNUNET_memcpy (key,
-                label,
-                strlen (label));
-  GNUNET_memcpy (key+strlen(label),
-                zone,
-                sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
-  GNUNET_CRYPTO_hash (key,
-                      key_len,
-                      &hkey);
-  GNUNET_free (key);
-
-  entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
-                                            &hkey);
-
-  if (NULL == entry)
-    return GNUNET_NO;
-  if (NULL != iter)
-    iter (iter_cls,
-         0,
-         &entry->private_key,
-         entry->label,
-         entry->record_count,
-         entry->record_data);
-  return GNUNET_YES;
-}
-
-
-/**
- * Closure for #iterate_zones.
- */
-struct IterateContext
-{
-  /**
-   * How many more records should we skip before returning results?
-   */
-  uint64_t offset;
-
-  /**
-   * How many more records should we return?
-   */
-  uint64_t limit;
-
-  /**
-   * What is the position of the current entry, counting
-   * starts from 1.
-   */
-  uint64_t pos;
-
-  /**
-   * Target zone.
-   */
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone;
-
-  /**
-   * Function to call on each record.
-   */
-  GNUNET_NAMESTORE_RecordIterator iter;
-
-  /**
-   * Closure for @e iter.
-   */
-  void *iter_cls;
-
-};
-
-
-/**
- * Helper function for #namestore_flat_iterate_records().
- *
- * @param cls a `struct IterateContext`
- * @param key unused
- * @param value a `struct FlatFileEntry`
- * @return #GNUNET_YES to continue the iteration
- */
-static int
-iterate_zones (void *cls,
-               const struct GNUNET_HashCode *key,
-               void *value)
-{
-  struct IterateContext *ic = cls;
-  struct FlatFileEntry *entry = value;
-
-  (void) key;
-  if (0 == ic->limit)
-    return GNUNET_NO;
-  if ( (NULL != ic->zone) &&
-       (0 != memcmp (&entry->private_key,
-                     ic->zone,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
-    return GNUNET_YES;
-  ic->pos++;
-  if (ic->offset > 0)
-  {
-    ic->offset--;
-    return GNUNET_YES;
-  }
-  ic->iter (ic->iter_cls,
-           ic->pos,
-            (NULL == ic->zone) 
-           ? &entry->private_key
-           : ic->zone,
-            entry->label,
-            entry->record_count,
-            entry->record_data);
-  ic->limit--;
-  if (0 == ic->limit)
-    return GNUNET_NO;
-  return GNUNET_YES;
-}
-
-
-/**
- * Iterate over the results for a particular key and zone in the
- * datastore.  Will return at most one result to the iterator.
- *
- * @param cls closure (internal context for the plugin)
- * @param zone hash of public key of the zone, NULL to iterate over all zones
- * @param serial serial number to exclude in the list of all matching records
- * @param limit maximum number of results to return to @a iter
- * @param iter function to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
- */
-static int
-namestore_flat_iterate_records (void *cls,
-                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                                uint64_t serial,
-                                uint64_t limit,
-                                GNUNET_NAMESTORE_RecordIterator iter,
-                                void *iter_cls)
-{
-  struct Plugin *plugin = cls;
-  struct IterateContext ic;
-
-  ic.offset = serial;
-  ic.pos = 0;
-  ic.limit = limit;
-  ic.iter = iter;
-  ic.iter_cls = iter_cls;
-  ic.zone = zone;
-  GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
-                                         &iterate_zones,
-                                         &ic);
-  return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
-}
-
-
-/**
- * Closure for #zone_to_name.
- */
-struct ZoneToNameContext
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone;
-  const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone;
-  GNUNET_NAMESTORE_RecordIterator iter;
-  void *iter_cls;
-
-  int result_found;
-};
-
-
-static int
-zone_to_name (void *cls,
-              const struct GNUNET_HashCode *key,
-              void *value)
-{
-  struct ZoneToNameContext *ztn = cls;
-  struct FlatFileEntry *entry = value;
-
-  (void) key;
-  if (0 != memcmp (&entry->private_key,
-                   ztn->zone,
-                   sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
-    return GNUNET_YES;
-
-  for (unsigned int i = 0; i < entry->record_count; i++)
-  {
-    if (GNUNET_GNSRECORD_TYPE_PKEY != entry->record_data[i].record_type)
-      continue;
-    if (0 == memcmp (ztn->value_zone,
-                     entry->record_data[i].data,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-    {
-      ztn->iter (ztn->iter_cls,
-                 0,
-                 &entry->private_key,
-                 entry->label,
-                 entry->record_count,
-                 entry->record_data);
-      ztn->result_found = GNUNET_YES;
-    }
-  }
-  return GNUNET_YES;
-}
-
-
-/**
- * Look for an existing PKEY delegation record for a given public key.
- * Returns at most one result to the iterator.
- *
- * @param cls closure (internal context for the plugin)
- * @param zone private key of the zone to look up in, never NULL
- * @param value_zone public key of the target zone (value), never NULL
- * @param iter function to call with the result
- * @param iter_cls closure for @a iter
- * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
- */
-static int
-namestore_flat_zone_to_name (void *cls,
-                             const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                             const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
-                             GNUNET_NAMESTORE_RecordIterator iter,
-                             void *iter_cls)
-{
-  struct Plugin *plugin = cls;
-  struct ZoneToNameContext ztn = {
-    .iter = iter,
-    .iter_cls = iter_cls,
-    .zone = zone,
-    .value_zone = value_zone,
-    .result_found = GNUNET_NO
-  };
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Performing reverse lookup for `%s'\n",
-              GNUNET_GNSRECORD_z2s (value_zone));
-  GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
-                                         &zone_to_name,
-                                         &ztn);
-  return ztn.result_found;
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_namestore_flat_init (void *cls)
-{
-  static struct Plugin plugin;
-  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct GNUNET_NAMESTORE_PluginFunctions *api;
-
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin,
-         0,
-         sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  if (GNUNET_OK != database_setup (&plugin))
-  {
-    database_shutdown (&plugin);
-    return NULL;
-  }
-  api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
-  api->cls = &plugin;
-  api->store_records = &namestore_flat_store_records;
-  api->iterate_records = &namestore_flat_iterate_records;
-  api->zone_to_name = &namestore_flat_zone_to_name;
-  api->lookup_records = &namestore_flat_lookup_records;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              _("flat file database running\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_namestore_flat_done (void *cls)
-{
-  struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
-  struct Plugin *plugin = api->cls;
-
-  database_shutdown (plugin);
-  plugin->cfg = NULL;
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "flat file plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_namestore_flat.c */
diff --git a/src/namestore/plugin_namestore_heap.c b/src/namestore/plugin_namestore_heap.c
new file mode 100644 (file)
index 0000000..8442294
--- /dev/null
@@ -0,0 +1,801 @@
+ /*
+  * This file is part of GNUnet
+  * Copyright (C) 2009-2015, 2018 GNUnet e.V.
+  *
+  * GNUnet is free software: you can redistribute it and/or modify it
+  * under the terms of the GNU Affero General Public License as published
+  * by the Free Software Foundation, either version 3 of the License,
+  * or (at your option) any later version.
+  *
+  * GNUnet is distributed in the hope that it will be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Affero General Public License for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+
+/**
+ * @file namestore/plugin_namestore_heap.c
+ * @brief file-based namestore backend
+ * @author Martin Schanzenbach
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_namestore_plugin.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "namestore.h"
+
+/**
+ * Context for all functions in this plugin.
+ */
+struct Plugin
+{
+
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Database filename.
+   */
+  char *fn;
+
+  /**
+   * HashMap
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *hm;
+
+};
+
+
+struct FlatFileEntry
+{
+  /**
+   * Entry zone
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey private_key;
+
+  /**
+   * Record cound
+   */
+  uint32_t record_count;
+
+  /**
+   * Rvalue
+   */
+  uint64_t rvalue;
+
+  /**
+   * Record data
+   */
+  struct GNUNET_GNSRECORD_Data *record_data;
+
+  /**
+   * Label
+   */
+  char *label;
+
+
+};
+
+
+/**
+ * Initialize the database connections and associated
+ * data structures (create tables and indices
+ * as needed as well).
+ *
+ * @param plugin the plugin context (state for this module)
+ * @return #GNUNET_OK on success
+ */
+static int
+database_setup (struct Plugin *plugin)
+{
+  char *afsdir;
+  char *record_data;
+  char *zone_private_key;
+  char *record_data_b64;
+  char *buffer;
+  char *line;
+  char *label;
+  char *rvalue;
+  char *record_count;
+  size_t record_data_size;
+  uint64_t size;
+  struct GNUNET_HashCode hkey;
+  struct GNUNET_DISK_FileHandle *fh;
+  struct FlatFileEntry *entry;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
+                                               "namestore-heap",
+                                               "FILENAME",
+                                              &afsdir))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "namestore-heap",
+                              "FILENAME");
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_DISK_file_test (afsdir))
+  {
+    if (GNUNET_OK !=
+       GNUNET_DISK_directory_create_for_file (afsdir))
+    {
+      GNUNET_break (0);
+      GNUNET_free (afsdir);
+      return GNUNET_SYSERR;
+    }
+  }
+  /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
+  plugin->fn = afsdir;
+
+  /* Load data from file into hashmap */
+  plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
+                                                     GNUNET_NO);
+  fh = GNUNET_DISK_file_open (afsdir,
+                              GNUNET_DISK_OPEN_CREATE |
+                              GNUNET_DISK_OPEN_READWRITE,
+                              GNUNET_DISK_PERM_USER_WRITE |
+                              GNUNET_DISK_PERM_USER_READ);
+  if (NULL == fh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+         _("Unable to initialize file: %s.\n"),
+         afsdir);
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_SYSERR ==
+      GNUNET_DISK_file_size (afsdir,
+                             &size,
+                             GNUNET_YES,
+                             GNUNET_YES))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+         _("Unable to get filesize: %s.\n"),
+         afsdir);
+    GNUNET_DISK_file_close (fh);
+    return GNUNET_SYSERR;
+  }
+
+  buffer = GNUNET_malloc (size + 1);
+  if (GNUNET_SYSERR ==
+      GNUNET_DISK_file_read (fh,
+                             buffer,
+                             size))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+         _("Unable to read file: %s.\n"),
+         afsdir);
+    GNUNET_free (buffer);
+    GNUNET_DISK_file_close (fh);
+    return GNUNET_SYSERR;
+  }
+  buffer[size] = '\0';
+  GNUNET_DISK_file_close (fh);
+
+  if (0 < size)
+  {
+    line = strtok (buffer, "\n");
+    while (line != NULL)
+    {
+      zone_private_key = strtok (line, ",");
+      if (NULL == zone_private_key)
+        break;
+      rvalue = strtok (NULL, ",");
+      if (NULL == rvalue)
+        break;
+      record_count = strtok (NULL, ",");
+      if (NULL == record_count)
+        break;
+      record_data_b64 = strtok (NULL, ",");
+      if (NULL == record_data_b64)
+        break;
+      label = strtok (NULL, ",");
+      if (NULL == label)
+        break;
+      line = strtok (NULL, "\n");
+      entry = GNUNET_new (struct FlatFileEntry);
+      {
+        unsigned long long ll;
+
+        if (1 != sscanf (rvalue,
+                         "%llu",
+                         &ll))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Error parsing entry\n");
+          GNUNET_free (entry);
+          break;
+        }
+        entry->rvalue = (uint64_t) ll;
+      }
+      {
+        unsigned int ui;
+
+        if (1 != sscanf (record_count,
+                         "%u",
+                         &ui))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Error parsing entry\n");
+          GNUNET_free (entry);
+          break;
+        }
+        entry->record_count = (uint32_t) ui;
+      }
+      entry->label = GNUNET_strdup (label);
+      record_data_size
+       = GNUNET_STRINGS_base64_decode (record_data_b64,
+                                       strlen (record_data_b64),
+                                       (void **) &record_data);
+      entry->record_data =
+        GNUNET_new_array (entry->record_count,
+                         struct GNUNET_GNSRECORD_Data);
+      if (GNUNET_OK !=
+         GNUNET_GNSRECORD_records_deserialize (record_data_size,
+                                               record_data,
+                                               entry->record_count,
+                                               entry->record_data))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Unable to deserialize record %s\n",
+                   label);
+        GNUNET_free (entry->label);
+        GNUNET_free (entry);
+        GNUNET_free (record_data);
+        break;
+      }
+      GNUNET_free (record_data);
+
+      {
+        struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key;
+
+        GNUNET_STRINGS_base64_decode (zone_private_key,
+                                      strlen (zone_private_key),
+                                      (void**)&private_key);
+        entry->private_key = *private_key;
+        GNUNET_free (private_key);
+      }
+
+      {
+        char *key;
+        size_t key_len;
+
+        key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
+        key = GNUNET_malloc (strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
+        GNUNET_memcpy (key,
+                       label,
+                       strlen (label));
+        GNUNET_memcpy (key+strlen(label),
+                       &entry->private_key,
+                       sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
+        GNUNET_CRYPTO_hash (key,
+                            key_len,
+                            &hkey);
+        GNUNET_free (key);
+      }
+      if (GNUNET_OK !=
+          GNUNET_CONTAINER_multihashmap_put (plugin->hm,
+                                             &hkey,
+                                             entry,
+                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+      {
+        GNUNET_free (entry);
+        GNUNET_break (0);
+      }
+    }
+  }
+  GNUNET_free (buffer);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Store values in hashmap in file and free data
+ *
+ * @param plugin the plugin context
+ * @param key key in the map
+ * @param value a `struct FlatFileEntry`
+ */
+static int
+store_and_free_entries (void *cls,
+                        const struct GNUNET_HashCode *key,
+                        void *value)
+{
+  struct GNUNET_DISK_FileHandle *fh = cls;
+  struct FlatFileEntry *entry = value;
+  char *line;
+  char *zone_private_key;
+  char *record_data_b64;
+  ssize_t data_size;
+
+  (void) key;
+  GNUNET_STRINGS_base64_encode (&entry->private_key,
+                                sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
+                                &zone_private_key);
+  data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
+                                                 entry->record_data);
+  if (data_size < 0)
+  {
+    GNUNET_break (0);
+    GNUNET_free (zone_private_key);
+    return GNUNET_SYSERR;
+  }
+  if (data_size >= UINT16_MAX)
+  {
+    GNUNET_break (0);
+    GNUNET_free (zone_private_key);
+    return GNUNET_SYSERR;
+  }
+  {
+    char data[data_size];
+    ssize_t ret;
+
+    ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
+                                             entry->record_data,
+                                             data_size,
+                                             data);
+    if ( (ret < 0) ||
+        (data_size != ret) )
+    {
+      GNUNET_break (0);
+      GNUNET_free (zone_private_key);
+      return GNUNET_SYSERR;
+    }
+    GNUNET_STRINGS_base64_encode (data,
+                                  data_size,
+                                  &record_data_b64);
+  }
+  GNUNET_asprintf (&line,
+                   "%s,%llu,%u,%s,%s\n",
+                   zone_private_key,
+                   (unsigned long long) entry->rvalue,
+                   (unsigned int) entry->record_count,
+                   record_data_b64,
+                   entry->label);
+  GNUNET_free (record_data_b64);
+  GNUNET_free (zone_private_key);
+
+  GNUNET_DISK_file_write (fh,
+                          line,
+                          strlen (line));
+
+  GNUNET_free (line);
+  GNUNET_free (entry->label);
+  GNUNET_free (entry->record_data);
+  GNUNET_free (entry);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Shutdown database connection and associate data
+ * structures.
+ * @param plugin the plugin context (state for this module)
+ */
+static void
+database_shutdown (struct Plugin *plugin)
+{
+  struct GNUNET_DISK_FileHandle *fh;
+
+  fh = GNUNET_DISK_file_open (plugin->fn,
+                              GNUNET_DISK_OPEN_CREATE |
+                              GNUNET_DISK_OPEN_TRUNCATE |
+                              GNUNET_DISK_OPEN_READWRITE,
+                              GNUNET_DISK_PERM_USER_WRITE |
+                              GNUNET_DISK_PERM_USER_READ);
+  if (NULL == fh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Unable to initialize file: %s.\n"),
+                plugin->fn);
+    return;
+  }
+
+  GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
+                                         &store_and_free_entries,
+                                         fh);
+  GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
+  GNUNET_DISK_file_close (fh);
+}
+
+
+/**
+ * Store a record in the datastore.  Removes any existing record in the
+ * same zone with the same name.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param zone_key private key of the zone
+ * @param label name that is being mapped (at most 255 characters long)
+ * @param rd_count number of entries in @a rd array
+ * @param rd array of records with data to store
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+namestore_heap_store_records (void *cls,
+                              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
+                              const char *label,
+                              unsigned int rd_count,
+                              const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct Plugin *plugin = cls;
+  uint64_t rvalue;
+  size_t key_len;
+  char *key;
+  struct GNUNET_HashCode hkey;
+  struct FlatFileEntry *entry;
+
+  rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                    UINT64_MAX);
+  key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
+  key = GNUNET_malloc (key_len);
+  GNUNET_memcpy (key,
+                 label,
+                 strlen (label));
+  GNUNET_memcpy (key + strlen(label),
+                 zone_key,
+                 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
+  GNUNET_CRYPTO_hash (key,
+                      key_len,
+                      &hkey);
+  GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
+                                            &hkey);
+  if (0 == rd_count)
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                     "sqlite",
+                     "Record deleted\n");
+    return GNUNET_OK;
+  }
+  entry = GNUNET_new (struct FlatFileEntry);
+  GNUNET_asprintf (&entry->label,
+                   label,
+                   strlen (label));
+  GNUNET_memcpy (&entry->private_key,
+                 zone_key,
+                 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
+  entry->rvalue = rvalue;
+  entry->record_count = rd_count;
+  entry->record_data = GNUNET_new_array (rd_count,
+                                         struct GNUNET_GNSRECORD_Data);
+  for (unsigned int i = 0; i < rd_count; i++)
+  {
+    entry->record_data[i].expiration_time = rd[i].expiration_time;
+    entry->record_data[i].record_type = rd[i].record_type;
+    entry->record_data[i].flags = rd[i].flags;
+    entry->record_data[i].data_size = rd[i].data_size;
+    entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
+    GNUNET_memcpy ((char*)entry->record_data[i].data,
+                   rd[i].data,
+                   rd[i].data_size);
+  }
+  return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
+                                            &hkey,
+                                            entry,
+                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+}
+
+
+/**
+ * Lookup records in the datastore for which we are the authority.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param zone private key of the zone
+ * @param label name of the record in the zone
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
+ */
+static int
+namestore_heap_lookup_records (void *cls,
+                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                               const char *label,
+                               GNUNET_NAMESTORE_RecordIterator iter,
+                               void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  struct FlatFileEntry *entry;
+  struct GNUNET_HashCode hkey;
+  char *key;
+  size_t key_len;
+
+  if (NULL == zone)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  key_len = strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
+  key = GNUNET_malloc (key_len);
+  GNUNET_memcpy (key,
+                label,
+                strlen (label));
+  GNUNET_memcpy (key+strlen(label),
+                zone,
+                sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
+  GNUNET_CRYPTO_hash (key,
+                      key_len,
+                      &hkey);
+  GNUNET_free (key);
+
+  entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
+                                            &hkey);
+
+  if (NULL == entry)
+    return GNUNET_NO;
+  if (NULL != iter)
+    iter (iter_cls,
+         0,
+         &entry->private_key,
+         entry->label,
+         entry->record_count,
+         entry->record_data);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Closure for #iterate_zones.
+ */
+struct IterateContext
+{
+  /**
+   * How many more records should we skip before returning results?
+   */
+  uint64_t offset;
+
+  /**
+   * How many more records should we return?
+   */
+  uint64_t limit;
+
+  /**
+   * What is the position of the current entry, counting
+   * starts from 1.
+   */
+  uint64_t pos;
+
+  /**
+   * Target zone.
+   */
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone;
+
+  /**
+   * Function to call on each record.
+   */
+  GNUNET_NAMESTORE_RecordIterator iter;
+
+  /**
+   * Closure for @e iter.
+   */
+  void *iter_cls;
+
+};
+
+
+/**
+ * Helper function for #namestore_heap_iterate_records().
+ *
+ * @param cls a `struct IterateContext`
+ * @param key unused
+ * @param value a `struct FlatFileEntry`
+ * @return #GNUNET_YES to continue the iteration
+ */
+static int
+iterate_zones (void *cls,
+               const struct GNUNET_HashCode *key,
+               void *value)
+{
+  struct IterateContext *ic = cls;
+  struct FlatFileEntry *entry = value;
+
+  (void) key;
+  if (0 == ic->limit)
+    return GNUNET_NO;
+  if ( (NULL != ic->zone) &&
+       (0 != memcmp (&entry->private_key,
+                     ic->zone,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
+    return GNUNET_YES;
+  ic->pos++;
+  if (ic->offset > 0)
+  {
+    ic->offset--;
+    return GNUNET_YES;
+  }
+  ic->iter (ic->iter_cls,
+           ic->pos,
+            (NULL == ic->zone) 
+           ? &entry->private_key
+           : ic->zone,
+            entry->label,
+            entry->record_count,
+            entry->record_data);
+  ic->limit--;
+  if (0 == ic->limit)
+    return GNUNET_NO;
+  return GNUNET_YES;
+}
+
+
+/**
+ * Iterate over the results for a particular key and zone in the
+ * datastore.  Will return at most one result to the iterator.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param zone hash of public key of the zone, NULL to iterate over all zones
+ * @param serial serial number to exclude in the list of all matching records
+ * @param limit maximum number of results to return to @a iter
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
+ */
+static int
+namestore_heap_iterate_records (void *cls,
+                                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                                uint64_t serial,
+                                uint64_t limit,
+                                GNUNET_NAMESTORE_RecordIterator iter,
+                                void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  struct IterateContext ic;
+
+  ic.offset = serial;
+  ic.pos = 0;
+  ic.limit = limit;
+  ic.iter = iter;
+  ic.iter_cls = iter_cls;
+  ic.zone = zone;
+  GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
+                                         &iterate_zones,
+                                         &ic);
+  return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
+}
+
+
+/**
+ * Closure for #zone_to_name.
+ */
+struct ZoneToNameContext
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone;
+  const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone;
+  GNUNET_NAMESTORE_RecordIterator iter;
+  void *iter_cls;
+
+  int result_found;
+};
+
+
+static int
+zone_to_name (void *cls,
+              const struct GNUNET_HashCode *key,
+              void *value)
+{
+  struct ZoneToNameContext *ztn = cls;
+  struct FlatFileEntry *entry = value;
+
+  (void) key;
+  if (0 != memcmp (&entry->private_key,
+                   ztn->zone,
+                   sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
+    return GNUNET_YES;
+
+  for (unsigned int i = 0; i < entry->record_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_PKEY != entry->record_data[i].record_type)
+      continue;
+    if (0 == memcmp (ztn->value_zone,
+                     entry->record_data[i].data,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+    {
+      ztn->iter (ztn->iter_cls,
+                 0,
+                 &entry->private_key,
+                 entry->label,
+                 entry->record_count,
+                 entry->record_data);
+      ztn->result_found = GNUNET_YES;
+    }
+  }
+  return GNUNET_YES;
+}
+
+
+/**
+ * Look for an existing PKEY delegation record for a given public key.
+ * Returns at most one result to the iterator.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param zone private key of the zone to look up in, never NULL
+ * @param value_zone public key of the target zone (value), never NULL
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
+ */
+static int
+namestore_heap_zone_to_name (void *cls,
+                             const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                             const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone,
+                             GNUNET_NAMESTORE_RecordIterator iter,
+                             void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  struct ZoneToNameContext ztn = {
+    .iter = iter,
+    .iter_cls = iter_cls,
+    .zone = zone,
+    .value_zone = value_zone,
+    .result_found = GNUNET_NO
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Performing reverse lookup for `%s'\n",
+              GNUNET_GNSRECORD_z2s (value_zone));
+  GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
+                                         &zone_to_name,
+                                         &ztn);
+  return ztn.result_found;
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_namestore_heap_init (void *cls)
+{
+  static struct Plugin plugin;
+  const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct GNUNET_NAMESTORE_PluginFunctions *api;
+
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin,
+         0,
+         sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  if (GNUNET_OK != database_setup (&plugin))
+  {
+    database_shutdown (&plugin);
+    return NULL;
+  }
+  api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
+  api->cls = &plugin;
+  api->store_records = &namestore_heap_store_records;
+  api->iterate_records = &namestore_heap_iterate_records;
+  api->zone_to_name = &namestore_heap_zone_to_name;
+  api->lookup_records = &namestore_heap_lookup_records;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _("heap file database running\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_namestore_heap_done (void *cls)
+{
+  struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
+  struct Plugin *plugin = api->cls;
+
+  database_shutdown (plugin);
+  plugin->cfg = NULL;
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "heap file plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_namestore_heap.c */
diff --git a/src/namestore/test_namestore_api_flat.conf b/src/namestore/test_namestore_api_flat.conf
deleted file mode 100644 (file)
index 6a28306..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_namestore_api.conf
-
-[namestore]
-DATABASE = flat
-
-[namestore-flat]
-FILENAME = $GNUNET_TEST_HOME/namestore/flat.db
diff --git a/src/namestore/test_namestore_api_heap.conf b/src/namestore/test_namestore_api_heap.conf
new file mode 100644 (file)
index 0000000..1d6173e
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_namestore_api.conf
+
+[namestore]
+DATABASE = heap
+
+[namestore-heap]
+FILENAME = $GNUNET_TEST_HOME/namestore/flat.db
diff --git a/src/namestore/test_plugin_namestore_flat.conf b/src/namestore/test_plugin_namestore_flat.conf
deleted file mode 100644 (file)
index 5c632f0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[namestore-flat]
-FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb
diff --git a/src/namestore/test_plugin_namestore_heap.conf b/src/namestore/test_plugin_namestore_heap.conf
new file mode 100644 (file)
index 0000000..94f79b9
--- /dev/null
@@ -0,0 +1,2 @@
+[namestore-heap]
+FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb