gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: major modification to datacache to store


From: gnunet
Subject: [gnunet] branch master updated: major modification to datacache to store route options (and clean up the API)
Date: Thu, 07 Jul 2022 13:42:55 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 2906241b6 major modification to datacache to store route options (and 
clean up the API)
2906241b6 is described below

commit 2906241b6a21d6009a0d195199f3a08e8f4d4e2a
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Thu Jul 7 13:42:52 2022 +0200

    major modification to datacache to store route options (and clean up the 
API)
---
 src/datacache/datacache.c                 |  32 +-
 src/datacache/plugin_datacache_heap.c     | 220 ++++------
 src/datacache/plugin_datacache_postgres.c | 205 +++++----
 src/datacache/plugin_datacache_sqlite.c   | 671 ++++++++++++++++++++++--------
 src/datacache/plugin_datacache_template.c |  20 +-
 src/datacache/test_datacache.c            |  74 ++--
 src/datacache/test_datacache_quota.c      |  66 ++-
 src/dht/gnunet-service-dht.h              |   8 +-
 src/dht/gnunet-service-dht_clients.c      |  36 +-
 src/dht/gnunet-service-dht_datacache.c    |  53 +--
 src/dht/gnunet-service-dht_datacache.h    |  47 +--
 src/dht/gnunet-service-dht_neighbours.c   |  50 +--
 src/dht/gnunet-service-dht_neighbours.h   |   6 +-
 src/dht/gnunet-service-dht_routing.c      |   6 +-
 src/dht/gnunet-service-dht_routing.h      |   2 +-
 src/gnsrecord/gnunet-gnsrecord-tvg.c      |   4 +-
 src/include/gnunet_datacache_lib.h        |  83 ++--
 src/include/gnunet_datacache_plugin.h     |  16 +-
 src/include/gnunet_dht_service.h          |   7 +-
 src/include/gnunet_sq_lib.h               |   8 +-
 20 files changed, 899 insertions(+), 715 deletions(-)

diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 761ab801f..c93ed58d6 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2015 GNUnet e.V.
+     Copyright (C) 2004-2010, 2015, 2022 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
@@ -259,26 +259,14 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle 
*h)
 
 enum GNUNET_GenericReturnValue
 GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
-                      const struct GNUNET_HashCode *key,
                       uint32_t xor_distance,
-                      size_t data_size,
-                      const char *data,
-                      enum GNUNET_BLOCK_Type type,
-                      struct GNUNET_TIME_Absolute discard_time,
-                      unsigned int path_info_len,
-                      const struct GNUNET_DHT_PathElement *path_info)
+                      const struct GNUNET_DATACACHE_Block *block)
 {
   ssize_t used;
 
   used = h->api->put (h->api->cls,
-                      key,
                       xor_distance,
-                      data_size,
-                      data,
-                      type,
-                      discard_time,
-                      path_info_len,
-                      path_info);
+                      block);
   if (-1 == used)
   {
     GNUNET_break (0);
@@ -291,10 +279,10 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Stored data under key `%s' in cache\n",
-       GNUNET_h2s (key));
+       GNUNET_h2s (&block->key));
   if (NULL != h->filter)
     GNUNET_CONTAINER_bloomfilter_add (h->filter,
-                                      key);
+                                      &block->key);
   GNUNET_STATISTICS_update (h->stats,
                             "# bytes stored",
                             used,
@@ -325,9 +313,10 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Processing request for key `%s'\n",
        GNUNET_h2s (key));
-  if ((NULL != h->filter) &&
-      (GNUNET_OK !=
-       GNUNET_CONTAINER_bloomfilter_test (h->filter, key)))
+  if ( (NULL != h->filter) &&
+       (GNUNET_OK !=
+        GNUNET_CONTAINER_bloomfilter_test (h->filter,
+                                           key)) )
   {
     GNUNET_STATISTICS_update (h->stats,
                               "# requests filtered by bloom filter",
@@ -364,7 +353,8 @@ GNUNET_DATACACHE_get_closest (struct 
GNUNET_DATACACHE_Handle *h,
                               key,
                               type,
                               num_results,
-                              iter, iter_cls);
+                              iter,
+                              iter_cls);
 }
 
 
diff --git a/src/datacache/plugin_datacache_heap.c 
b/src/datacache/plugin_datacache_heap.c
index 5b50468a5..a2b60c8da 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2012, 2015 GNUnet e.V.
+     Copyright (C) 2012, 2015, 2022 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
@@ -63,14 +63,9 @@ struct Plugin
 struct Value
 {
   /**
-   * Key for the entry.
+   * Block data.
    */
-  struct GNUNET_HashCode key;
-
-  /**
-   * Expiration time.
-   */
-  struct GNUNET_TIME_Absolute discard_time;
+  struct GNUNET_DATACACHE_Block block;
 
   /**
    * Corresponding node in the heap.
@@ -78,29 +73,15 @@ struct Value
   struct GNUNET_CONTAINER_HeapNode *hn;
 
   /**
-   * Path information.
-   */
-  struct GNUNET_DHT_PathElement *path_info;
-
-  /**
-   * Payload (actual payload follows this struct)
-   */
-  size_t size;
-
-  /**
-   * Number of entries in @e path_info.
+   * Put path as a non-const pointer.
    */
-  unsigned int path_info_len;
+  struct GNUNET_DHT_PathElement *put_path;
 
   /**
    * How close is the hash to us? Determines which heap we are in!
    */
   uint32_t distance;
 
-  /**
-   * Type of the block.
-   */
-  enum GNUNET_BLOCK_Type type;
 };
 
 
@@ -113,39 +94,14 @@ struct Value
 struct PutContext
 {
   /**
-   * Expiration time for the new value.
-   */
-  struct GNUNET_TIME_Absolute discard_time;
-
-  /**
-   * Data for the new value.
-   */
-  const char *data;
-
-  /**
-   * Path information.
+   * Block data.
    */
-  const struct GNUNET_DHT_PathElement *path_info;
+  const struct GNUNET_DATACACHE_Block *block;
 
   /**
-   * Number of bytes in @e data.
+   * Value to set to true if an equivalent block was found.
    */
-  size_t size;
-
-  /**
-   * Type of the node.
-   */
-  enum GNUNET_BLOCK_Type type;
-
-  /**
-   * Number of entries in @e path_info.
-   */
-  unsigned int path_info_len;
-
-  /**
-   * Value to set to #GNUNET_YES if an equivalent block was found.
-   */
-  int found;
+  bool found;
 };
 
 
@@ -166,31 +122,31 @@ put_cb (void *cls,
   struct PutContext *put_ctx = cls;
   struct Value *val = value;
 
-  if ((val->size == put_ctx->size) &&
-      (val->type == put_ctx->type) &&
-      (0 == memcmp (&val[1],
-                    put_ctx->data,
-                    put_ctx->size)))
+  if ((val->block.data_size == put_ctx->block->data_size) &&
+      (val->block.type == put_ctx->block->type) &&
+      (0 == memcmp (val->block.data,
+                    put_ctx->block->data,
+                    put_ctx->block->data_size)))
   {
-    put_ctx->found = GNUNET_YES;
-    val->discard_time = GNUNET_TIME_absolute_max (val->discard_time,
-                                                  put_ctx->discard_time);
+    put_ctx->found = true;
+    val->block.expiration_time
+      = GNUNET_TIME_absolute_max (val->block.expiration_time,
+                                  put_ctx->block->expiration_time);
     /* replace old path with new path */
-    GNUNET_array_grow (val->path_info,
-                       val->path_info_len,
-                       put_ctx->path_info_len);
-    GNUNET_memcpy (val->path_info,
-                   put_ctx->path_info,
-                   put_ctx->path_info_len * sizeof(struct
-                                                   GNUNET_DHT_PathElement));
+    GNUNET_free (val->put_path);
+    val->put_path = GNUNET_memdup (put_ctx->block->put_path,
+                                   put_ctx->block->put_path_length
+                                   * sizeof (struct GNUNET_DHT_PathElement));
+    val->block.put_path = val->put_path;
+    val->block.put_path_length = put_ctx->block->put_path_length;
     GNUNET_CONTAINER_heap_update_cost (val->hn,
-                                       val->discard_time.abs_value_us);
+                                       
val->block.expiration_time.abs_value_us);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Got same value for key %s and type %d (size %u vs %u)\n",
+                "Got same value for key %s and type %u (size %u vs %u)\n",
                 GNUNET_h2s (key),
-                val->type,
-                (unsigned int) val->size,
-                (unsigned int) put_ctx->size);
+                (unsigned int) val->block.type,
+                (unsigned int) val->block.data_size,
+                (unsigned int) put_ctx->block->data_size);
     return GNUNET_NO;
   }
   return GNUNET_YES;
@@ -201,75 +157,58 @@ put_cb (void *cls,
  * Store an item in the datastore.
  *
  * @param cls closure (our `struct Plugin`)
- * @param key key to store data under
  * @param xor_distance how close is @a key to our PID?
- * @param size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block data to store
  * @return 0 if duplicate, -1 on error, number of bytes used otherwise
  */
 static ssize_t
 heap_plugin_put (void *cls,
-                 const struct GNUNET_HashCode *key,
                  uint32_t xor_distance,
-                 size_t size,
-                 const char *data,
-                 enum GNUNET_BLOCK_Type type,
-                 struct GNUNET_TIME_Absolute discard_time,
-                 unsigned int path_info_len,
-                 const struct GNUNET_DHT_PathElement *path_info)
+                 const struct GNUNET_DATACACHE_Block *block)
 {
   struct Plugin *plugin = cls;
   struct Value *val;
   struct PutContext put_ctx = {
-    .data = data,
-    .size = size,
-    .path_info = path_info,
-    .path_info_len = path_info_len,
-    .discard_time = discard_time,
-    .type = type
+    .block = block,
+    .found = false
   };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Storing %u bytes under key %s with path length %u\n",
-              (unsigned int) size,
-              GNUNET_h2s (key),
-              path_info_len);
+              (unsigned int) block->data_size,
+              GNUNET_h2s (&block->key),
+              block->put_path_length);
   GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map,
-                                              key,
+                                              &block->key,
                                               &put_cb,
                                               &put_ctx);
   if (GNUNET_YES == put_ctx.found)
     return 0;
-  val = GNUNET_malloc (sizeof(struct Value) + size);
+  val = GNUNET_malloc (sizeof(struct Value)
+                       + block->data_size);
   GNUNET_memcpy (&val[1],
-                 data,
-                 size);
-  val->key = *key;
-  val->type = type;
-  val->discard_time = discard_time;
-  val->size = size;
+                 block->data,
+                 block->data_size);
+  val->block = *block;
+  val->block.data = &val[1];
   if (xor_distance >= NUM_HEAPS)
     val->distance = NUM_HEAPS - 1;
   else
     val->distance = xor_distance;
-  GNUNET_array_grow (val->path_info,
-                     val->path_info_len,
-                     path_info_len);
-  GNUNET_memcpy (val->path_info,
-                 path_info,
-                 path_info_len * sizeof(struct GNUNET_DHT_PathElement));
+  if (0 != block->put_path_length)
+    val->block.put_path
+      = GNUNET_memdup (block->put_path,
+                       block->put_path_length
+                       * sizeof (struct GNUNET_DHT_PathElement));
   (void) GNUNET_CONTAINER_multihashmap_put (plugin->map,
-                                            &val->key,
+                                            &val->block.key,
                                             val,
                                             
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-  val->hn = GNUNET_CONTAINER_heap_insert (plugin->heaps[val->distance],
-                                          val,
-                                          val->discard_time.abs_value_us);
-  return size + OVERHEAD;
+  val->hn = GNUNET_CONTAINER_heap_insert (
+    plugin->heaps[val->distance],
+    val,
+    val->block.expiration_time.abs_value_us);
+  return val->block.data_size + OVERHEAD;
 }
 
 
@@ -309,16 +248,16 @@ struct GetContext
  * @param value an existing value
  * @return #GNUNET_YES to continue to iterate
  */
-static int
+static enum GNUNET_GenericReturnValue
 get_cb (void *cls,
         const struct GNUNET_HashCode *key,
         void *value)
 {
   struct GetContext *get_ctx = cls;
   struct Value *val = value;
-  int ret;
+  enum GNUNET_GenericReturnValue ret;
 
-  if ( (get_ctx->type != val->type) &&
+  if ( (get_ctx->type != val->block.type) &&
        (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -327,7 +266,7 @@ get_cb (void *cls,
                 get_ctx->type);
     return GNUNET_OK;
   }
-  if (GNUNET_TIME_absolute_is_past (val->discard_time))
+  if (GNUNET_TIME_absolute_is_past (val->block.expiration_time))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Result for key %s is expired\n",
@@ -339,13 +278,7 @@ get_cb (void *cls,
               GNUNET_h2s (key));
   if (NULL != get_ctx->iter)
     ret = get_ctx->iter (get_ctx->iter_cls,
-                         key,
-                         val->size,
-                         (const char *) &val[1],
-                         val->type,
-                         val->discard_time,
-                         val->path_info_len,
-                         val->path_info);
+                         &val->block);
   else
     ret = GNUNET_YES;
   get_ctx->cnt++;
@@ -393,7 +326,7 @@ heap_plugin_get (void *cls,
  * @param cls closure (our `struct Plugin`)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static int
+static enum GNUNET_GenericReturnValue
 heap_plugin_del (void *cls)
 {
   struct Plugin *plugin = cls;
@@ -409,12 +342,12 @@ heap_plugin_del (void *cls)
     return GNUNET_SYSERR;
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multihashmap_remove (plugin->map,
-                                                       &val->key,
+                                                       &val->block.key,
                                                        val));
   plugin->env->delete_notify (plugin->env->cls,
-                              &val->key,
-                              val->size + OVERHEAD);
-  GNUNET_free (val->path_info);
+                              &val->block.key,
+                              val->block.data_size + OVERHEAD);
+  GNUNET_free (val->put_path);
   GNUNET_free (val);
   return GNUNET_OK;
 }
@@ -448,7 +381,7 @@ find_closest (void *cls,
   if (1 != GNUNET_CRYPTO_hash_cmp (key,
                                    gcc->key))
     return GNUNET_OK; /* useless */
-  if ( (val->type != gcc->type) &&
+  if ( (val->block.type != gcc->type) &&
        (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
     return GNUNET_OK; /* useless */
   j = gcc->num_results;
@@ -460,7 +393,7 @@ find_closest (void *cls,
       break;
     }
     if (1 ==
-        GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key,
+        GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->block.key,
                                 key))
     {
       j = i;
@@ -512,14 +445,15 @@ heap_plugin_get_closest (void *cls,
   {
     if (NULL == values[i])
       return i;
-    iter (iter_cls,
-          &values[i]->key,
-          values[i]->size,
-          (void *) &values[i][1],
-          values[i]->type,
-          values[i]->discard_time,
-          values[i]->path_info_len,
-          values[i]->path_info);
+    if ( (NULL != iter) &&
+         (GNUNET_SYSERR ==
+          iter (iter_cls,
+                &values[i]->block)) )
+    {
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Ending iteration (client error)\n");
+      return i;
+    }
   }
   return num_results * 2;
 }
@@ -576,9 +510,9 @@ libgnunet_plugin_datacache_heap_done (void *cls)
     {
       GNUNET_assert (GNUNET_YES ==
                      GNUNET_CONTAINER_multihashmap_remove (plugin->map,
-                                                           &val->key,
+                                                           &val->block.key,
                                                            val));
-      GNUNET_free (val->path_info);
+      GNUNET_free (val->put_path);
       GNUNET_free (val);
     }
     GNUNET_CONTAINER_heap_destroy (plugin->heaps[i]);
diff --git a/src/datacache/plugin_datacache_postgres.c 
b/src/datacache/plugin_datacache_postgres.c
index 1a83cda86..d9e25992b 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -63,73 +63,75 @@ struct Plugin
  * @param plugin global context
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static int
+static enum GNUNET_GenericReturnValue
 init_connection (struct Plugin *plugin)
 {
   struct GNUNET_PQ_ExecuteStatement es[] = {
     GNUNET_PQ_make_try_execute (
-      "CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn011dc_oid_seq"),
-    GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn011dc ("
-                            "  oid OID NOT NULL DEFAULT 
nextval('gn011dc_oid_seq'),"
+      "CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn180dc_oid_seq"),
+    GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn180dc ("
+                            "  oid OID NOT NULL DEFAULT 
nextval('gn180dc_oid_seq'),"
                             "  type INTEGER NOT NULL,"
+                            "  ro INTEGER NOT NULL,"
                             "  prox INTEGER NOT NULL,"
-                            "  discard_time BIGINT NOT NULL,"
+                            "  expiration_time BIGINT NOT NULL,"
                             "  key BYTEA NOT NULL,"
                             "  value BYTEA NOT NULL,"
                             "  path BYTEA DEFAULT NULL)"),
     GNUNET_PQ_make_try_execute (
-      "ALTER SEQUENCE gnu011dc_oid_seq OWNED BY gn011dc.oid"),
+      "ALTER SEQUENCE gnu011dc_oid_seq OWNED BY gn180dc.oid"),
     GNUNET_PQ_make_try_execute (
-      "CREATE INDEX IF NOT EXISTS idx_oid ON gn011dc (oid)"),
+      "CREATE INDEX IF NOT EXISTS idx_oid ON gn180dc (oid)"),
     GNUNET_PQ_make_try_execute (
-      "CREATE INDEX IF NOT EXISTS idx_key ON gn011dc (key)"),
+      "CREATE INDEX IF NOT EXISTS idx_key ON gn180dc (key)"),
     GNUNET_PQ_make_try_execute (
-      "CREATE INDEX IF NOT EXISTS idx_dt ON gn011dc (discard_time)"),
+      "CREATE INDEX IF NOT EXISTS idx_dt ON gn180dc (expiration_time)"),
     GNUNET_PQ_make_execute (
-      "ALTER TABLE gn011dc ALTER value SET STORAGE EXTERNAL"),
-    GNUNET_PQ_make_execute ("ALTER TABLE gn011dc ALTER key SET STORAGE PLAIN"),
+      "ALTER TABLE gn180dc ALTER value SET STORAGE EXTERNAL"),
+    GNUNET_PQ_make_execute ("ALTER TABLE gn180dc ALTER key SET STORAGE PLAIN"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
   };
   struct GNUNET_PQ_PreparedStatement ps[] = {
     GNUNET_PQ_make_prepare ("getkt",
-                            "SELECT discard_time,type,value,path FROM gn011dc "
-                            "WHERE key=$1 AND type=$2 AND discard_time >= $3",
+                            "SELECT expiration_time,type,ro,value,path FROM 
gn180dc "
+                            "WHERE key=$1 AND type=$2 AND expiration_time >= 
$3",
                             3),
     GNUNET_PQ_make_prepare ("getk",
-                            "SELECT discard_time,type,value,path FROM gn011dc "
-                            "WHERE key=$1 AND discard_time >= $2",
+                            "SELECT expiration_time,type,ro,value,path FROM 
gn180dc "
+                            "WHERE key=$1 AND expiration_time >= $2",
                             2),
     GNUNET_PQ_make_prepare ("getex",
-                            "SELECT length(value) AS len,oid,key FROM gn011dc"
-                            " WHERE discard_time < $1"
-                            " ORDER BY discard_time ASC LIMIT 1",
+                            "SELECT LENGTH(value) AS len,oid,key FROM gn180dc"
+                            " WHERE expiration_time < $1"
+                            " ORDER BY expiration_time ASC LIMIT 1",
                             1),
     GNUNET_PQ_make_prepare ("getm",
-                            "SELECT length(value) AS len,oid,key FROM gn011dc"
-                            " ORDER BY prox ASC, discard_time ASC LIMIT 1",
+                            "SELECT LENGTH(value) AS len,oid,key FROM gn180dc"
+                            " ORDER BY prox ASC, expiration_time ASC LIMIT 1",
                             0),
     GNUNET_PQ_make_prepare ("get_closest",
-                            "(SELECT discard_time,type,value,path,key FROM 
gn011dc"
+                            "(SELECT expiration_time,type,ro,value,path,key 
FROM gn180dc"
                             " WHERE key >= $1"
-                            "   AND discard_time >= $2"
+                            "   AND expiration_time >= $2"
                             "   AND ( (type = $3) OR ( 0 = $3) )"
                             " ORDER BY key ASC"
                             " LIMIT $4)"
                             " UNION "
-                            "(SELECT discard_time,type,value,path,key FROM 
gn011dc"
+                            "(SELECT expiration_time,type,ro,value,path,key 
FROM gn180dc"
                             " WHERE key <= $1"
-                            "   AND discard_time >= $2"
+                            "   AND expiration_time >= $2"
                             "   AND ( (type = $3) OR ( 0 = $3) )"
                             " ORDER BY key DESC"
                             " LIMIT $4)",
                             4),
     GNUNET_PQ_make_prepare ("delrow",
-                            "DELETE FROM gn011dc WHERE oid=$1",
+                            "DELETE FROM gn180dc WHERE oid=$1",
                             1),
     GNUNET_PQ_make_prepare ("put",
-                            "INSERT INTO gn011dc (type, prox, discard_time, 
key, value, path) "
-                            "VALUES ($1, $2, $3, $4, $5, $6)",
-                            6),
+                            "INSERT INTO gn180dc"
+                            " (type, ro, prox, expiration_time, key, value, 
path) "
+                            "VALUES ($1, $2, $3, $4, $5, $6, $7)",
+                            7),
     GNUNET_PQ_PREPARED_STATEMENT_END
   };
 
@@ -148,38 +150,29 @@ init_connection (struct Plugin *plugin)
  * Store an item in the datastore.
  *
  * @param cls closure (our `struct Plugin`)
- * @param key key to store @a data under
  * @param prox proximity of @a key to my PID
- * @param data_size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block data to store
  * @return 0 if duplicate, -1 on error, number of bytes used otherwise
  */
 static ssize_t
 postgres_plugin_put (void *cls,
-                     const struct GNUNET_HashCode *key,
                      uint32_t prox,
-                     size_t data_size,
-                     const char *data,
-                     enum GNUNET_BLOCK_Type type,
-                     struct GNUNET_TIME_Absolute discard_time,
-                     unsigned int path_info_len,
-                     const struct GNUNET_DHT_PathElement *path_info)
+                     const struct GNUNET_DATACACHE_Block *block)
 {
   struct Plugin *plugin = cls;
-  uint32_t type32 = (uint32_t) type;
+  uint32_t type32 = (uint32_t) block->type;
+  uint32_t ro32 = (uint32_t) block->type;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint32 (&type32),
+    GNUNET_PQ_query_param_uint32 (&ro32),
     GNUNET_PQ_query_param_uint32 (&prox),
-    GNUNET_PQ_query_param_absolute_time (&discard_time),
-    GNUNET_PQ_query_param_auto_from_type (key),
-    GNUNET_PQ_query_param_fixed_size (data, data_size),
-    GNUNET_PQ_query_param_fixed_size (path_info,
-                                      path_info_len * sizeof(struct
-                                                             
GNUNET_DHT_PathElement)),
+    GNUNET_PQ_query_param_absolute_time (&block->expiration_time),
+    GNUNET_PQ_query_param_auto_from_type (&block->key),
+    GNUNET_PQ_query_param_fixed_size (block->data,
+                                      block->data_size),
+    GNUNET_PQ_query_param_fixed_size (block->put_path,
+                                      block->put_path_length
+                                      * sizeof(struct GNUNET_DHT_PathElement)),
     GNUNET_PQ_query_param_end
   };
   enum GNUNET_DB_QueryStatus ret;
@@ -190,7 +183,7 @@ postgres_plugin_put (void *cls,
   if (0 > ret)
     return -1;
   plugin->num_items++;
-  return data_size + OVERHEAD;
+  return block->data_size + OVERHEAD;
 }
 
 
@@ -234,23 +227,25 @@ handle_results (void *cls,
 
   for (unsigned int i = 0; i < num_results; i++)
   {
-    struct GNUNET_TIME_Absolute expiration_time;
-    uint32_t type;
+    uint32_t type32;
+    uint32_t bro32;
     void *data;
-    size_t data_size;
-    struct GNUNET_DHT_PathElement *path;
-    size_t path_len;
+    struct GNUNET_DATACACHE_Block block;
+    void *path;
+    size_t path_size;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_absolute_time ("discard_time",
-                                           &expiration_time),
+      GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+                                           &block.expiration_time),
       GNUNET_PQ_result_spec_uint32 ("type",
-                                    &type),
+                                    &type32),
+      GNUNET_PQ_result_spec_uint32 ("ro",
+                                    &bro32),
       GNUNET_PQ_result_spec_variable_size ("value",
                                            &data,
-                                           &data_size),
+                                           &block.data_size),
       GNUNET_PQ_result_spec_variable_size ("path",
-                                           (void **) &path,
-                                           &path_len),
+                                           &path,
+                                           &path_size),
       GNUNET_PQ_result_spec_end
     };
 
@@ -262,26 +257,27 @@ handle_results (void *cls,
       GNUNET_break (0);
       return;
     }
-    if (0 != (path_len % sizeof(struct GNUNET_DHT_PathElement)))
+    if (0 != (path_size % sizeof(struct GNUNET_DHT_PathElement)))
     {
       GNUNET_break (0);
-      path_len = 0;
+      path_size = 0;
+      path = NULL;
     }
-    path_len %= sizeof(struct GNUNET_DHT_PathElement);
+    block.data = data;
+    block.put_path = path;
+    block.put_path_length
+      = path_size / sizeof (struct GNUNET_DHT_PathElement);
+    block.type = (enum GNUNET_BLOCK_Type) type32;
+    block.ro = (enum GNUNET_DHT_RouteOption) bro32;
+    block.key = *hrc->key;
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Found result of size %u bytes and type %u in database\n",
-         (unsigned int) data_size,
-         (unsigned int) type);
-    if ((NULL != hrc->iter) &&
-        (GNUNET_SYSERR ==
-         hrc->iter (hrc->iter_cls,
-                    hrc->key,
-                    data_size,
-                    data,
-                    (enum GNUNET_BLOCK_Type) type,
-                    expiration_time,
-                    path_len,
-                    path)))
+         (unsigned int) block.data_size,
+         (unsigned int) block.type);
+    if ( (NULL != hrc->iter) &&
+         (GNUNET_SYSERR ==
+          hrc->iter (hrc->iter_cls,
+                     &block)) )
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG,
            "Ending iteration (client error)\n");
@@ -350,7 +346,7 @@ postgres_plugin_get (void *cls,
  * @param cls closure (our `struct Plugin`)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_plugin_del (void *cls)
 {
   struct Plugin *plugin = cls;
@@ -453,26 +449,27 @@ extract_result_cb (void *cls,
     return;
   for (unsigned int i = 0; i < num_results; i++)
   {
-    struct GNUNET_TIME_Absolute expiration_time;
-    uint32_t type;
+    uint32_t type32;
+    uint32_t bro32;
+    struct GNUNET_DATACACHE_Block block;
     void *data;
-    size_t data_size;
-    struct GNUNET_DHT_PathElement *path;
-    size_t path_len;
-    struct GNUNET_HashCode key;
+    void *path;
+    size_t path_size;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_absolute_time ("",
-                                           &expiration_time),
+      GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+                                           &block.expiration_time),
       GNUNET_PQ_result_spec_uint32 ("type",
-                                    &type),
+                                    &type32),
+      GNUNET_PQ_result_spec_uint32 ("ro",
+                                    &bro32),
       GNUNET_PQ_result_spec_variable_size ("value",
                                            &data,
-                                           &data_size),
+                                           &block.data_size),
       GNUNET_PQ_result_spec_variable_size ("path",
-                                           (void **) &path,
-                                           &path_len),
+                                           &path,
+                                           &path_size),
       GNUNET_PQ_result_spec_auto_from_type ("key",
-                                            &key),
+                                            &block.key),
       GNUNET_PQ_result_spec_end
     };
 
@@ -484,25 +481,25 @@ extract_result_cb (void *cls,
       GNUNET_break (0);
       return;
     }
-    if (0 != (path_len % sizeof(struct GNUNET_DHT_PathElement)))
+    if (0 != (path_size % sizeof(struct GNUNET_DHT_PathElement)))
     {
       GNUNET_break (0);
-      path_len = 0;
+      path_size = 0;
+      path = NULL;
     }
-    path_len %= sizeof(struct GNUNET_DHT_PathElement);
+    block.type = (enum GNUNET_BLOCK_Type) type32;
+    block.ro = (enum GNUNET_DHT_RouteOption) bro32;
+    block.data = data;
+    block.put_path = path;
+    block.put_path_length = path_size / sizeof (struct GNUNET_DHT_PathElement);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Found result of size %u bytes and type %u in database\n",
-         (unsigned int) data_size,
-         (unsigned int) type);
-    if (GNUNET_SYSERR ==
-        erc->iter (erc->iter_cls,
-                   &key,
-                   data_size,
-                   data,
-                   (enum GNUNET_BLOCK_Type) type,
-                   expiration_time,
-                   path_len,
-                   path))
+         (unsigned int) block.data_size,
+         (unsigned int) block.type);
+    if ( (NULL != erc->iter) &&
+         (GNUNET_SYSERR ==
+          erc->iter (erc->iter_cls,
+                     &block)) )
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG,
            "Ending iteration (client error)\n");
diff --git a/src/datacache/plugin_datacache_sqlite.c 
b/src/datacache/plugin_datacache_sqlite.c
index 6f2165433..22ae5c0f5 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2006, 2009, 2015 GNUnet e.V.
+     Copyright (C) 2006, 2009, 2015, 2022 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
@@ -71,11 +71,21 @@ struct Plugin
    */
   sqlite3_stmt *get_count_stmt;
 
+  /**
+   * Prepared statement for #sqlite_plugin_get.
+   */
+  sqlite3_stmt *get_count_any_stmt;
+
   /**
    * Prepared statement for #sqlite_plugin_get.
    */
   sqlite3_stmt *get_stmt;
 
+  /**
+   * Prepared statement for #sqlite_plugin_get.
+   */
+  sqlite3_stmt *get_any_stmt;
+
   /**
    * Prepared statement for #sqlite_plugin_del.
    */
@@ -133,9 +143,10 @@ struct Plugin
   do                                                            \
   {                                                             \
     emsg = NULL;                                                \
-    if (SQLITE_OK != sqlite3_exec (db, cmd, NULL, NULL, &emsg)) \
+    if (SQLITE_OK !=                                            \
+        sqlite3_exec (db, cmd, NULL, NULL, &emsg))              \
     {                                                           \
-      LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,    \
+      LOG (GNUNET_ERROR_TYPE_ERROR,                             \
            _ ("`%s' failed at %s:%d with error: %s\n"),         \
            "sqlite3_exec",                                      \
            __FILE__,                                            \
@@ -173,67 +184,222 @@ sq_prepare (sqlite3 *dbh,
  * Store an item in the datastore.
  *
  * @param cls closure (our `struct Plugin`)
- * @param key key to store @a data under
  * @param xor_distance how close is @a key to our PID?
- * @param size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info array of peers that have processed the request
+ * @param block data to store
  * @return 0 if duplicate, -1 on error, number of bytes used otherwise
  */
 static ssize_t
 sqlite_plugin_put (void *cls,
-                   const struct GNUNET_HashCode *key,
                    uint32_t xor_distance,
-                   size_t size,
-                   const char *data,
-                   enum GNUNET_BLOCK_Type type,
-                   struct GNUNET_TIME_Absolute discard_time,
-                   unsigned int path_info_len,
-                   const struct GNUNET_DHT_PathElement *path_info)
+                   const struct GNUNET_DATACACHE_Block *block)
 {
   struct Plugin *plugin = cls;
-  uint32_t type32 = type;
-  struct GNUNET_SQ_QueryParam params[] =
-  { GNUNET_SQ_query_param_uint32 (&type32),
-    GNUNET_SQ_query_param_absolute_time (&discard_time),
-    GNUNET_SQ_query_param_auto_from_type (key),
+  uint32_t type32 = (uint32_t) block->type;
+  uint32_t ro32 = (uint32_t) block->ro;
+  struct GNUNET_SQ_QueryParam params[] = {
+    GNUNET_SQ_query_param_uint32 (&type32),
+    GNUNET_SQ_query_param_uint32 (&ro32),
+    GNUNET_SQ_query_param_absolute_time (&block->expiration_time),
+    GNUNET_SQ_query_param_auto_from_type (&block->key),
     GNUNET_SQ_query_param_uint32 (&xor_distance),
-    GNUNET_SQ_query_param_fixed_size (data, size),
-    GNUNET_SQ_query_param_fixed_size (path_info,
-                                      path_info_len
+    GNUNET_SQ_query_param_fixed_size (block->data,
+                                      block->data_size),
+    GNUNET_SQ_query_param_fixed_size (block->put_path,
+                                      block->put_path_length
                                       * sizeof(struct GNUNET_DHT_PathElement)),
-    GNUNET_SQ_query_param_end };
+    GNUNET_SQ_query_param_end
+  };
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Processing PUT of %u bytes with key `%s' and expiration %s\n",
-       (unsigned int) size,
-       GNUNET_h2s (key),
+       (unsigned int) block->data_size,
+       GNUNET_h2s (&block->key),
        GNUNET_STRINGS_relative_time_to_string (
          GNUNET_TIME_absolute_get_remaining (
-           discard_time),
+           block->expiration_time),
          GNUNET_YES));
-  if (GNUNET_OK != GNUNET_SQ_bind (plugin->insert_stmt, params))
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->insert_stmt,
+                      params))
   {
     LOG_SQLITE (plugin->dbh,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                GNUNET_ERROR_TYPE_ERROR,
                 "sqlite3_bind_xxx");
-    GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->insert_stmt);
     return -1;
   }
-  if (SQLITE_DONE != sqlite3_step (plugin->insert_stmt))
+  if (SQLITE_DONE !=
+      sqlite3_step (plugin->insert_stmt))
   {
     LOG_SQLITE (plugin->dbh,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                GNUNET_ERROR_TYPE_ERROR,
                 "sqlite3_step");
-    GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->insert_stmt);
     return -1;
   }
   plugin->num_items++;
-  GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt);
-  return size + OVERHEAD;
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->insert_stmt);
+  return block->data_size + OVERHEAD;
+}
+
+
+/**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param cls closure (our `struct Plugin`)
+ * @param key
+ * @param iter maybe NULL (to just count)
+ * @param iter_cls closure for @a iter
+ * @return the number of results found
+ */
+static unsigned int
+get_any (void *cls,
+         const struct GNUNET_HashCode *key,
+         GNUNET_DATACACHE_Iterator iter,
+         void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_TIME_Absolute now;
+  unsigned int cnt;
+  uint32_t off;
+  uint32_t btype32;
+  uint32_t bro32;
+  unsigned int total;
+  struct GNUNET_DATACACHE_Block block;
+  void *path;
+  void *data;
+  size_t path_size;
+  struct GNUNET_SQ_QueryParam params_count[] = {
+    GNUNET_SQ_query_param_auto_from_type (key),
+    GNUNET_SQ_query_param_absolute_time (&now),
+    GNUNET_SQ_query_param_end
+  };
+  struct GNUNET_SQ_QueryParam params_select[] = {
+    GNUNET_SQ_query_param_auto_from_type (key),
+    GNUNET_SQ_query_param_absolute_time (&now),
+    GNUNET_SQ_query_param_uint32 (&off),
+    GNUNET_SQ_query_param_end
+  };
+  struct GNUNET_SQ_ResultSpec rs[] = {
+    GNUNET_SQ_result_spec_variable_size (&data,
+                                         &block.data_size),
+    GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
+    GNUNET_SQ_result_spec_variable_size (&path,
+                                         &path_size),
+    GNUNET_SQ_result_spec_uint32 (&btype32),
+    GNUNET_SQ_result_spec_uint32 (&bro32),
+    GNUNET_SQ_result_spec_end
+  };
+
+  now = GNUNET_TIME_absolute_get ();
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing GET for key `%s'\n",
+       GNUNET_h2s (key));
+
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->get_count_any_stmt,
+                      params_count))
+  {
+    LOG_SQLITE (plugin->dbh,
+                GNUNET_ERROR_TYPE_ERROR,
+                "sqlite3_bind_xxx");
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_count_any_stmt);
+    return 0;
+  }
+  if (SQLITE_ROW !=
+      sqlite3_step (plugin->get_count_any_stmt))
+  {
+    LOG_SQLITE (plugin->dbh,
+                GNUNET_ERROR_TYPE_ERROR,
+                "sqlite_step");
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_count_any_stmt);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "No content found when processing GET for key `%s'\n",
+         GNUNET_h2s (key));
+    return 0;
+  }
+  total = sqlite3_column_int (plugin->get_count_any_stmt,
+                              0);
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->get_count_any_stmt);
+  if ( (0 == total) ||
+       (NULL == iter) )
+  {
+    if (0 == total)
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "No content found when processing GET for key `%s'\n",
+           GNUNET_h2s (key));
+    return total;
+  }
+
+  cnt = 0;
+  block.key = *key;
+  off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  total);
+  while (cnt < total)
+  {
+    off = (off + 1) % total;
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->get_any_stmt,
+                        params_select))
+    {
+      LOG_SQLITE (plugin->dbh,
+                  GNUNET_ERROR_TYPE_ERROR,
+                  "sqlite3_bind_xxx");
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->get_any_stmt);
+      return cnt;
+    }
+    if (SQLITE_ROW !=
+        sqlite3_step (plugin->get_any_stmt))
+      break;
+    if (GNUNET_OK !=
+        GNUNET_SQ_extract_result (plugin->get_any_stmt,
+                                  rs))
+    {
+      GNUNET_break (0);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->get_any_stmt);
+      break;
+    }
+    if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
+    {
+      GNUNET_break (0);
+      path_size = 0;
+      path = NULL;
+    }
+    block.data = data;
+    block.put_path = path;
+    block.put_path_length = path_size / sizeof(struct GNUNET_DHT_PathElement);
+    block.type = (enum GNUNET_BLOCK_Type) btype32;
+    block.ro = (enum GNUNET_DHT_RouteOption) bro32;
+    cnt++;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Found %u-byte result when processing GET for key `%s'\n",
+         (unsigned int) block.data_size,
+         GNUNET_h2s (&block.key));
+    if (GNUNET_OK !=
+        iter (iter_cls,
+              &block))
+    {
+      GNUNET_SQ_cleanup_result (rs);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->get_any_stmt);
+      break;
+    }
+    GNUNET_SQ_cleanup_result (rs);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_any_stmt);
+  }
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->get_any_stmt);
+  return cnt;
 }
 
 
@@ -249,67 +415,81 @@ sqlite_plugin_put (void *cls,
  * @return the number of results found
  */
 static unsigned int
-sqlite_plugin_get (void *cls,
-                   const struct GNUNET_HashCode *key,
-                   enum GNUNET_BLOCK_Type type,
-                   GNUNET_DATACACHE_Iterator iter,
-                   void *iter_cls)
+get_typed (void *cls,
+           const struct GNUNET_HashCode *key,
+           enum GNUNET_BLOCK_Type type,
+           GNUNET_DATACACHE_Iterator iter,
+           void *iter_cls)
 {
   struct Plugin *plugin = cls;
   uint32_t type32 = type;
   struct GNUNET_TIME_Absolute now;
-  struct GNUNET_TIME_Absolute exp;
-  size_t size;
-  void *dat;
   unsigned int cnt;
   uint32_t off;
+  uint32_t bro32;
   unsigned int total;
-  size_t psize;
-  struct GNUNET_DHT_PathElement *path;
-  struct GNUNET_SQ_QueryParam params_count[] =
-  { GNUNET_SQ_query_param_auto_from_type (key),
+  struct GNUNET_DATACACHE_Block block;
+  void *path;
+  void *data;
+  size_t path_size;
+  struct GNUNET_SQ_QueryParam params_count[] = {
+    GNUNET_SQ_query_param_auto_from_type (key),
     GNUNET_SQ_query_param_uint32 (&type32),
     GNUNET_SQ_query_param_absolute_time (&now),
-    GNUNET_SQ_query_param_end };
-  struct GNUNET_SQ_QueryParam params_select[] =
-  { GNUNET_SQ_query_param_auto_from_type (key),
+    GNUNET_SQ_query_param_end
+  };
+  struct GNUNET_SQ_QueryParam params_select[] = {
+    GNUNET_SQ_query_param_auto_from_type (key),
     GNUNET_SQ_query_param_uint32 (&type32),
     GNUNET_SQ_query_param_absolute_time (&now),
     GNUNET_SQ_query_param_uint32 (&off),
-    GNUNET_SQ_query_param_end };
-  struct GNUNET_SQ_ResultSpec rs[] =
-  { GNUNET_SQ_result_spec_variable_size (&dat, &size),
-    GNUNET_SQ_result_spec_absolute_time (&exp),
-    GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
-    GNUNET_SQ_result_spec_end };
+    GNUNET_SQ_query_param_end
+  };
+  struct GNUNET_SQ_ResultSpec rs[] = {
+    GNUNET_SQ_result_spec_variable_size (&data,
+                                         &block.data_size),
+    GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
+    GNUNET_SQ_result_spec_variable_size (&path,
+                                         &path_size),
+    GNUNET_SQ_result_spec_uint32 (&bro32),
+    GNUNET_SQ_result_spec_end
+  };
 
   now = GNUNET_TIME_absolute_get ();
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Processing GET for key `%s'\n",
        GNUNET_h2s (key));
 
-  if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_count_stmt, params_count))
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->get_count_stmt,
+                      params_count))
   {
     LOG_SQLITE (plugin->dbh,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                GNUNET_ERROR_TYPE_ERROR,
                 "sqlite3_bind_xxx");
-    GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_count_stmt);
     return 0;
   }
-  if (SQLITE_ROW != sqlite3_step (plugin->get_count_stmt))
+  if (SQLITE_ROW !=
+      sqlite3_step (plugin->get_count_stmt))
   {
     LOG_SQLITE (plugin->dbh,
-                GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                GNUNET_ERROR_TYPE_ERROR,
                 "sqlite_step");
-    GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_count_stmt);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "No content found when processing GET for key `%s'\n",
          GNUNET_h2s (key));
     return 0;
   }
-  total = sqlite3_column_int (plugin->get_count_stmt, 0);
-  GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt);
-  if ((0 == total) || (NULL == iter))
+  total = sqlite3_column_int (plugin->get_count_stmt,
+                              0);
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->get_count_stmt);
+  if ( (0 == total) ||
+       (NULL == iter) )
   {
     if (0 == total)
       LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -319,52 +499,102 @@ sqlite_plugin_get (void *cls,
   }
 
   cnt = 0;
-  off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
+  block.key = *key;
+  off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  total);
   while (cnt < total)
   {
     off = (off + 1) % total;
-    if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_stmt, params_select))
+    if (GNUNET_OK !=
+        GNUNET_SQ_bind (plugin->get_stmt,
+                        params_select))
     {
       LOG_SQLITE (plugin->dbh,
-                  GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                  GNUNET_ERROR_TYPE_ERROR,
                   "sqlite3_bind_xxx");
-      GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->get_stmt);
       return cnt;
     }
-    if (SQLITE_ROW != sqlite3_step (plugin->get_stmt))
+    if (SQLITE_ROW !=
+        sqlite3_step (plugin->get_stmt))
       break;
-    if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_stmt, rs))
+    if (GNUNET_OK !=
+        GNUNET_SQ_extract_result (plugin->get_stmt,
+                                  rs))
     {
       GNUNET_break (0);
-      GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->get_stmt);
       break;
     }
-    if (0 != psize % sizeof(struct GNUNET_DHT_PathElement))
+    if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
     {
       GNUNET_break (0);
-      psize = 0;
+      path_size = 0;
       path = NULL;
     }
-    psize /= sizeof(struct GNUNET_DHT_PathElement);
+    block.data = data;
+    block.put_path = path;
+    block.put_path_length = path_size / sizeof(struct GNUNET_DHT_PathElement);
+    block.type = type;
+    block.ro = (enum GNUNET_DHT_RouteOption) bro32;
     cnt++;
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Found %u-byte result when processing GET for key `%s'\n",
-         (unsigned int) size,
-         GNUNET_h2s (key));
-    if (GNUNET_OK != iter (iter_cls, key, size, dat, type, exp, psize, path))
+         (unsigned int) block.data_size,
+         GNUNET_h2s (&block.key));
+    if ( (NULL != iter) &&
+         (GNUNET_OK !=
+          iter (iter_cls,
+                &block)) )
     {
       GNUNET_SQ_cleanup_result (rs);
-      GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->get_stmt);
       break;
     }
     GNUNET_SQ_cleanup_result (rs);
-    GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_stmt);
   }
-  GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt);
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->get_stmt);
   return cnt;
 }
 
 
+/**
+ * Iterate over the results for a particular key
+ * in the datastore.
+ *
+ * @param cls closure (our `struct Plugin`)
+ * @param key
+ * @param type entries of which type are relevant?
+ * @param iter maybe NULL (to just count)
+ * @param iter_cls closure for @a iter
+ * @return the number of results found
+ */
+static unsigned int
+sqlite_plugin_get (void *cls,
+                   const struct GNUNET_HashCode *key,
+                   enum GNUNET_BLOCK_Type type,
+                   GNUNET_DATACACHE_Iterator iter,
+                   void *iter_cls)
+{
+  if (GNUNET_BLOCK_TYPE_ANY == type)
+    return get_any (cls,
+                    key,
+                    iter,
+                    iter_cls);
+  return get_typed (cls,
+                    key,
+                    type,
+                    iter,
+                    iter_cls);
+}
+
+
 /**
  * Delete the entry with the lowest expiration value
  * from the datacache right now.
@@ -372,76 +602,103 @@ sqlite_plugin_get (void *cls,
  * @param cls closure (our `struct Plugin`)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static int
+static enum GNUNET_GenericReturnValue
 sqlite_plugin_del (void *cls)
 {
   struct Plugin *plugin = cls;
   uint64_t rowid;
   void *data;
-  size_t dsize;
+  size_t data_size;
   struct GNUNET_HashCode hc;
   struct GNUNET_TIME_Absolute now;
-  struct GNUNET_SQ_ResultSpec rs[] =
-  { GNUNET_SQ_result_spec_uint64 (&rowid),
+  struct GNUNET_SQ_ResultSpec rs[] = {
+    GNUNET_SQ_result_spec_uint64 (&rowid),
     GNUNET_SQ_result_spec_auto_from_type (&hc),
-    GNUNET_SQ_result_spec_variable_size ((void **) &data, &dsize),
-    GNUNET_SQ_result_spec_end };
-  struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint64 (
-                                             &rowid),
-                                           GNUNET_SQ_query_param_end };
-  struct GNUNET_SQ_QueryParam time_params[] =
-  { GNUNET_SQ_query_param_absolute_time (&now), GNUNET_SQ_query_param_end };
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing DEL\n");
+    GNUNET_SQ_result_spec_variable_size (&data,
+                                         &data_size),
+    GNUNET_SQ_result_spec_end
+  };
+  struct GNUNET_SQ_QueryParam params[] = {
+    GNUNET_SQ_query_param_uint64 (&rowid),
+    GNUNET_SQ_query_param_end
+  };
+  struct GNUNET_SQ_QueryParam time_params[] = {
+    GNUNET_SQ_query_param_absolute_time (&now),
+    GNUNET_SQ_query_param_end
+  };
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Processing DEL\n");
   now = GNUNET_TIME_absolute_get ();
-  if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_expired_stmt, time_params))
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->del_expired_stmt,
+                      time_params))
   {
     LOG_SQLITE (plugin->dbh,
                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                 "sqlite3_bind");
-    GNUNET_SQ_reset (plugin->dbh, plugin->del_expired_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->del_expired_stmt);
     return GNUNET_SYSERR;
   }
-  if ((SQLITE_ROW != sqlite3_step (plugin->del_expired_stmt)) ||
-      (GNUNET_OK != GNUNET_SQ_extract_result (plugin->del_expired_stmt, rs)))
+  if ( (SQLITE_ROW !=
+        sqlite3_step (plugin->del_expired_stmt)) ||
+       (GNUNET_OK !=
+        GNUNET_SQ_extract_result (plugin->del_expired_stmt,
+                                  rs)))
   {
-    GNUNET_SQ_reset (plugin->dbh, plugin->del_expired_stmt);
-    if (SQLITE_ROW != sqlite3_step (plugin->del_select_stmt))
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->del_expired_stmt);
+    if (SQLITE_ROW !=
+        sqlite3_step (plugin->del_select_stmt))
     {
       LOG_SQLITE (plugin->dbh,
                   GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                   "sqlite3_step");
-      GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->del_select_stmt);
       return GNUNET_SYSERR;
     }
-    if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->del_select_stmt, rs))
+    if (GNUNET_OK !=
+        GNUNET_SQ_extract_result (plugin->del_select_stmt,
+                                  rs))
     {
-      GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt);
+      GNUNET_SQ_reset (plugin->dbh,
+                       plugin->del_select_stmt);
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
   }
   GNUNET_SQ_cleanup_result (rs);
-  GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt);
-  if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_stmt, params))
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->del_select_stmt);
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->del_stmt,
+                      params))
   {
     LOG_SQLITE (plugin->dbh,
                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                 "sqlite3_bind");
-    GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->del_stmt);
     return GNUNET_SYSERR;
   }
-  if (SQLITE_DONE != sqlite3_step (plugin->del_stmt))
+  if (SQLITE_DONE !=
+      sqlite3_step (plugin->del_stmt))
   {
     LOG_SQLITE (plugin->dbh,
                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                 "sqlite3_step");
-    GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt);
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->del_stmt);
     return GNUNET_SYSERR;
   }
   plugin->num_items--;
-  plugin->env->delete_notify (plugin->env->cls, &hc, dsize + OVERHEAD);
-  GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt);
+  plugin->env->delete_notify (plugin->env->cls,
+                              &hc,
+                              data_size + OVERHEAD);
+  GNUNET_SQ_reset (plugin->dbh,
+                   plugin->del_stmt);
   return GNUNET_OK;
 }
 
@@ -472,14 +729,13 @@ sqlite_plugin_get_closest (void *cls,
   uint32_t type32 = type;
   uint32_t num_results32 = num_results;
   struct GNUNET_TIME_Absolute now;
-  struct GNUNET_TIME_Absolute exp;
-  size_t size;
-  void *dat;
+  void *data;
+  void *path;
+  size_t path_size;
   unsigned int cnt;
-  size_t psize;
-  uint32_t rtype;
-  struct GNUNET_HashCode hc;
-  struct GNUNET_DHT_PathElement *path;
+  uint32_t bro32;
+  struct GNUNET_DATACACHE_Block block;
+  uint32_t rtype32;
   struct GNUNET_SQ_QueryParam params[] = {
     GNUNET_SQ_query_param_auto_from_type (key),
     GNUNET_SQ_query_param_absolute_time (&now),
@@ -488,11 +744,14 @@ sqlite_plugin_get_closest (void *cls,
     GNUNET_SQ_query_param_end
   };
   struct GNUNET_SQ_ResultSpec rs[] = {
-    GNUNET_SQ_result_spec_variable_size (&dat, &size),
-    GNUNET_SQ_result_spec_absolute_time (&exp),
-    GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
-    GNUNET_SQ_result_spec_uint32 (&rtype),
-    GNUNET_SQ_result_spec_auto_from_type (&hc),
+    GNUNET_SQ_result_spec_variable_size (&data,
+                                         &block.data_size),
+    GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
+    GNUNET_SQ_result_spec_variable_size (&path,
+                                         &path_size),
+    GNUNET_SQ_result_spec_uint32 (&rtype32),
+    GNUNET_SQ_result_spec_uint32 (&bro32),
+    GNUNET_SQ_result_spec_auto_from_type (&block.key),
     GNUNET_SQ_result_spec_end
   };
 
@@ -512,7 +771,8 @@ sqlite_plugin_get_closest (void *cls,
     return 0;
   }
   cnt = 0;
-  while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt))
+  while (SQLITE_ROW ==
+         sqlite3_step (plugin->get_closest_stmt))
   {
     if (GNUNET_OK !=
         GNUNET_SQ_extract_result (plugin->get_closest_stmt,
@@ -521,26 +781,27 @@ sqlite_plugin_get_closest (void *cls,
       GNUNET_break (0);
       break;
     }
-    if (0 != psize % sizeof(struct GNUNET_DHT_PathElement))
+    if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
     {
       GNUNET_break (0);
-      psize = 0;
+      path_size = 0;
       path = NULL;
     }
-    psize /= sizeof(struct GNUNET_DHT_PathElement);
+    block.put_path_length
+      = path_size / sizeof(struct GNUNET_DHT_PathElement);
+    block.put_path = path;
+    block.data = data;
+    block.type = (enum GNUNET_BLOCK_Type) rtype32;
+    block.ro = (enum GNUNET_DHT_RouteOption) bro32;
     cnt++;
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Found %u-byte result at %s when processing GET_CLOSE\n",
-         (unsigned int) size,
-         GNUNET_h2s (&hc));
-    if (GNUNET_OK != iter (iter_cls,
-                           &hc,
-                           size,
-                           dat,
-                           rtype,
-                           exp,
-                           psize,
-                           path))
+         (unsigned int) block.data_size,
+         GNUNET_h2s (&block.key));
+
+    if (GNUNET_OK !=
+        iter (iter_cls,
+              &block))
     {
       GNUNET_SQ_cleanup_result (rs);
       break;
@@ -570,25 +831,30 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
   sqlite3 *dbh;
   char *emsg;
 
-  if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
-                                                          "datacache-sqlite",
-                                                          "IN_MEMORY"))
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
+                                            "datacache-sqlite",
+                                            "IN_MEMORY"))
   {
-    if (SQLITE_OK != sqlite3_open (":memory:", &dbh))
+    if (SQLITE_OK !=
+        sqlite3_open (":memory:",
+                      &dbh))
       return NULL;
     fn_utf8 = NULL;
   }
   else
   {
     fn = GNUNET_DISK_mktemp ("gnunet-datacache");
-    if (fn == NULL)
+    if (NULL == fn)
     {
       GNUNET_break (0);
       return NULL;
     }
     /* fn should be UTF-8-encoded. If it isn't, it's a bug. */
     fn_utf8 = GNUNET_strdup (fn);
-    if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh))
+    if (SQLITE_OK !=
+        sqlite3_open (fn_utf8,
+                      &dbh))
     {
       GNUNET_free (fn);
       GNUNET_free (fn_utf8);
@@ -602,22 +868,30 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
   SQLITE3_EXEC (dbh, "PRAGMA journal_mode=OFF");
   SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
   SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
-  if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
-                                                          "datacache-sqlite",
-                                                          "IN_MEMORY"))
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
+                                            "datacache-sqlite",
+                                            "IN_MEMORY"))
     SQLITE3_EXEC (dbh, "PRAGMA sqlite_temp_store=3");
 
   SQLITE3_EXEC (dbh,
-                "CREATE TABLE ds091 ("
+                "CREATE TABLE ds180 ("
                 "  type INTEGER NOT NULL DEFAULT 0,"
+                "  ro INTEGER NOT NULL DEFAULT 0,"
                 "  expire INTEGER NOT NULL,"
                 "  key BLOB NOT NULL DEFAULT '',"
                 "  prox INTEGER NOT NULL,"
                 "  value BLOB NOT NULL,"
                 "  path BLOB DEFAULT '')");
-  SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds091 (key,type,expire)");
-  SQLITE3_EXEC (dbh, "CREATE INDEX idx_prox_expire ON ds091 (prox,expire)");
-  SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire_only ON ds091 (expire)");
+  SQLITE3_EXEC (dbh,
+                "CREATE INDEX idx_hashidx"
+                " ON ds180 (key,type,expire)");
+  SQLITE3_EXEC (dbh,
+                "CREATE INDEX idx_prox_expire"
+                " ON ds180 (prox,expire)");
+  SQLITE3_EXEC (dbh,
+                "CREATE INDEX idx_expire_only"
+                " ON ds180 (expire)");
   plugin = GNUNET_new (struct Plugin);
   plugin->env = env;
   plugin->dbh = dbh;
@@ -625,41 +899,67 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
 
   if ((SQLITE_OK !=
        sq_prepare (plugin->dbh,
-                   "INSERT INTO ds091 (type, expire, key, prox, value, path) "
-                   "VALUES (?, ?, ?, ?, ?, ?)",
+                   "INSERT INTO ds180"
+                   " (type, ro, expire, key, prox, value, path)"
+                   " VALUES (?, ?, ?, ?, ?, ?, ?)",
                    &plugin->insert_stmt)) ||
-      (SQLITE_OK != sq_prepare (plugin->dbh,
-                                "SELECT count(*) FROM ds091 "
-                                "WHERE key=? AND type=? AND expire >= ?",
-                                &plugin->get_count_stmt)) ||
       (SQLITE_OK !=
        sq_prepare (plugin->dbh,
-                   "SELECT value,expire,path FROM ds091"
-                   " WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?",
+                   "SELECT COUNT(*) FROM ds180 "
+                   "WHERE key=?"
+                   " AND type=?"
+                   " AND expire >= ?",
+                   &plugin->get_count_stmt)) ||
+      (SQLITE_OK !=
+       sq_prepare (plugin->dbh,
+                   "SELECT COUNT(*) FROM ds180 "
+                   "WHERE key=? AND expire >= ?",
+                   &plugin->get_count_any_stmt)) ||
+      (SQLITE_OK !=
+       sq_prepare (plugin->dbh,
+                   "SELECT value,expire,path,ro"
+                   " FROM ds180"
+                   " WHERE key=?"
+                   " AND type=?"
+                   " AND expire >= ?"
+                   " LIMIT 1 OFFSET ?",
                    &plugin->get_stmt)) ||
-      (SQLITE_OK != sq_prepare (plugin->dbh,
-                                "SELECT _ROWID_,key,value FROM ds091"
-                                " WHERE expire < ?1"
-                                " ORDER BY expire ASC LIMIT 1",
-                                &plugin->del_expired_stmt)) ||
-      (SQLITE_OK != sq_prepare (plugin->dbh,
-                                "SELECT _ROWID_,key,value FROM ds091"
-                                " ORDER BY prox ASC, expire ASC LIMIT 1",
-                                &plugin->del_select_stmt)) ||
-      (SQLITE_OK != sq_prepare (plugin->dbh,
-                                "DELETE FROM ds091 WHERE _ROWID_=?",
-                                &plugin->del_stmt)) ||
+      (SQLITE_OK !=
+       sq_prepare (plugin->dbh,
+                   "SELECT value,expire,path,type,ro"
+                   " FROM ds180"
+                   " WHERE key=?"
+                   " AND expire >= ?"
+                   " LIMIT 1 OFFSET ?",
+                   &plugin->get_any_stmt)) ||
+      (SQLITE_OK !=
+       sq_prepare (plugin->dbh,
+                   "SELECT _ROWID_,key,value FROM ds180"
+                   " WHERE expire < ?1"
+                   " ORDER BY expire ASC LIMIT 1",
+                   &plugin->del_expired_stmt)) ||
+      (SQLITE_OK !=
+       sq_prepare (plugin->dbh,
+                   "SELECT _ROWID_,key,value FROM ds180"
+                   " ORDER BY prox ASC, expire ASC LIMIT 1",
+                   &plugin->del_select_stmt)) ||
+      (SQLITE_OK !=
+       sq_prepare (plugin->dbh,
+                   "DELETE FROM ds180 WHERE _ROWID_=?",
+                   &plugin->del_stmt)) ||
       (SQLITE_OK !=
        sq_prepare (plugin->dbh,
                    "SELECT * FROM ("
-                   " SELECT value,expire,path,type,key FROM ds091 "
+                   " SELECT value,expire,path,type,ro,key"
+                   " FROM ds180 "
                    " WHERE key>=?1 "
                    "  AND expire >= ?2"
                    "  AND ( (type=?3) or (0 == ?3) )"
                    " ORDER BY KEY ASC LIMIT ?4)"
                    "UNION "
                    "SELECT * FROM ("
-                   " SELECT value,expire,path,type,key FROM ds091 "
+                   " SELECT value,expire,path,type,ro,key"
+                   " FROM ds180 "
                    " WHERE key<=?1 "
                    "  AND expire >= ?2"
                    "  AND ( (type=?3) or (0 == ?3) )"
@@ -669,7 +969,8 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
     LOG_SQLITE (plugin->dbh,
                 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                 "sq_prepare");
-    GNUNET_break (SQLITE_OK == sqlite3_close (plugin->dbh));
+    GNUNET_break (SQLITE_OK ==
+                  sqlite3_close (plugin->dbh));
     GNUNET_free (plugin);
     return NULL;
   }
@@ -680,7 +981,8 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
   api->put = &sqlite_plugin_put;
   api->del = &sqlite_plugin_del;
   api->get_closest = &sqlite_plugin_get_closest;
-  LOG (GNUNET_ERROR_TYPE_INFO, "Sqlite datacache running\n");
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Sqlite datacache running\n");
   return api;
 }
 
@@ -703,13 +1005,18 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
 #endif
 
 #if ! WINDOWS || defined(__CYGWIN__)
-  if ((NULL != plugin->fn) && (0 != unlink (plugin->fn)))
-    LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn);
+  if ( (NULL != plugin->fn) &&
+       (0 != unlink (plugin->fn)) )
+    LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
+                       "unlink",
+                       plugin->fn);
   GNUNET_free (plugin->fn);
 #endif
   sqlite3_finalize (plugin->insert_stmt);
   sqlite3_finalize (plugin->get_count_stmt);
+  sqlite3_finalize (plugin->get_count_any_stmt);
   sqlite3_finalize (plugin->get_stmt);
+  sqlite3_finalize (plugin->get_any_stmt);
   sqlite3_finalize (plugin->del_select_stmt);
   sqlite3_finalize (plugin->del_expired_stmt);
   sqlite3_finalize (plugin->del_stmt);
@@ -721,7 +1028,8 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _ (
            "Tried to close sqlite without finalizing all prepared 
statements.\n"));
-    stmt = sqlite3_next_stmt (plugin->dbh, NULL);
+    stmt = sqlite3_next_stmt (plugin->dbh,
+                              NULL);
     while (NULL != stmt)
     {
       result = sqlite3_finalize (stmt);
@@ -730,13 +1038,16 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
              "Failed to close statement %p: %d\n",
              stmt,
              result);
-      stmt = sqlite3_next_stmt (plugin->dbh, NULL);
+      stmt = sqlite3_next_stmt (plugin->dbh,
+                                NULL);
     }
     result = sqlite3_close (plugin->dbh);
   }
 #endif
   if (SQLITE_OK != result)
-    LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close");
+    LOG_SQLITE (plugin->dbh,
+                GNUNET_ERROR_TYPE_ERROR,
+                "sqlite3_close");
 
   GNUNET_free (plugin);
   GNUNET_free (api);
diff --git a/src/datacache/plugin_datacache_template.c 
b/src/datacache/plugin_datacache_template.c
index 2f7b41dbe..1bd712d39 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2006, 2009, 2015 GNUnet e.V.
+     Copyright (C) 2006, 2009, 2015, 2022 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
@@ -44,26 +44,14 @@ struct Plugin
  * Store an item in the datastore.
  *
  * @param cls closure (our `struct Plugin`)
- * @param key key to store @a data under
  * @param xor_distance distance of @a key to our PID
- * @param size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block data to store
  * @return 0 if duplicate, -1 on error, number of bytes used otherwise
  */
 static ssize_t
 template_plugin_put (void *cls,
-                     const struct GNUNET_HashCode *key,
                      uint32_t xor_distance,
-                     size_t size,
-                     const char *data,
-                     enum GNUNET_BLOCK_Type type,
-                     struct GNUNET_TIME_Absolute discard_time,
-                     unsigned int path_info_len,
-                     const struct GNUNET_DHT_PathElement *path_info)
+                     const struct GNUNET_DATACACHE_Block *block)
 {
   GNUNET_break (0);
   return -1;
@@ -100,7 +88,7 @@ template_plugin_get (void *cls,
  * @param cls closure (our `struct Plugin`)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static int
+static enum GNUNET_GenericReturnValue
 template_plugin_del (void *cls)
 {
   GNUNET_break (0);
diff --git a/src/datacache/test_datacache.c b/src/datacache/test_datacache.c
index 5740d2b7d..b5d978995 100644
--- a/src/datacache/test_datacache.c
+++ b/src/datacache/test_datacache.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2006, 2009, 2010 GNUnet e.V.
+     Copyright (C) 2006, 2009, 2010, 2022 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
@@ -39,26 +39,18 @@ static int ok;
 static const char *plugin_name;
 
 
-static int
+static enum GNUNET_GenericReturnValue
 checkIt (void *cls,
-         const struct GNUNET_HashCode *key,
-         size_t size, const char *data,
-         enum GNUNET_BLOCK_Type type,
-         struct GNUNET_TIME_Absolute exp,
-         unsigned int path_len,
-         const struct GNUNET_DHT_PathElement *path)
+         const struct GNUNET_DATACACHE_Block *block)
 {
-  (void) key;
-  (void) type;
-  (void) exp;
-  (void) path_len;
-  (void) path;
-  if (size != sizeof(struct GNUNET_HashCode))
+  if (block->data_size != sizeof(struct GNUNET_HashCode))
   {
     GNUNET_break (0);
     ok = 2;
   }
-  if (0 != memcmp (data, cls, size))
+  if (0 != memcmp (block->data,
+                   cls,
+                   block->data_size))
   {
     GNUNET_break (0);
     ok = 3;
@@ -74,9 +66,9 @@ run (void *cls,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
   struct GNUNET_DATACACHE_Handle *h;
+  struct GNUNET_DATACACHE_Block block;
   struct GNUNET_HashCode k;
   struct GNUNET_HashCode n;
-  struct GNUNET_TIME_Absolute exp;
 
   (void) cls;
   (void) args;
@@ -84,7 +76,7 @@ run (void *cls,
   ok = 0;
   h = GNUNET_DATACACHE_create (cfg,
                                "testcache");
-  if (h == NULL)
+  if (NULL == h)
   {
     fprintf (stderr,
              "%s",
@@ -92,19 +84,28 @@ run (void *cls,
     ok = 77;   /* mark test as skipped */
     return;
   }
-  exp = GNUNET_TIME_absolute_get ();
-  exp.abs_value_us += 5 * 60 * 1000 * 1000LL;
-  memset (&k, 0, sizeof(struct GNUNET_HashCode));
+  block.expiration_time = GNUNET_TIME_absolute_get ();
+  block.expiration_time.abs_value_us += 5 * 60 * 1000 * 1000LL;
+  memset (&k,
+          0,
+          sizeof(struct GNUNET_HashCode));
   for (unsigned int i = 0; i < 100; i++)
   {
-    GNUNET_CRYPTO_hash (&k, sizeof(struct GNUNET_HashCode), &n);
+    GNUNET_CRYPTO_hash (&k,
+                        sizeof(struct GNUNET_HashCode),
+                        &n);
+    block.key = k;
+    block.data = &n;
+    block.data_size = sizeof (n);
+    block.ro = 42;
+    block.type = (enum GNUNET_BLOCK_Type) (1 + i % 16);
+    block.put_path = NULL;
+    block.put_path_length = 0;
+    block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
     ASSERT (GNUNET_OK ==
             GNUNET_DATACACHE_put (h,
-                                  &k,
-                                  GNUNET_YES,
-                                  sizeof(struct GNUNET_HashCode),
-                                  (const char *) &n, 1 + i % 16, exp,
-                                  0, NULL));
+                                  42,
+                                  &block));
     k = n;
   }
   memset (&k,
@@ -117,7 +118,7 @@ run (void *cls,
                         &n);
     ASSERT (1 == GNUNET_DATACACHE_get (h,
                                        &k,
-                                       1 + i % 16,
+                                       (enum GNUNET_BLOCK_Type) (1 + i % 16),
                                        &checkIt,
                                        &n));
     k = n;
@@ -129,16 +130,19 @@ run (void *cls,
   GNUNET_CRYPTO_hash (&k,
                       sizeof(struct GNUNET_HashCode),
                       &n);
+  block.key = k;
+  block.data = &n;
+  block.data_size = sizeof (n);
+  block.ro = 42;
+  block.type = (enum GNUNET_BLOCK_Type) 792;
+  block.put_path = NULL;
+  block.put_path_length = 0;
+  block.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS;
+  block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
   ASSERT (GNUNET_OK ==
           GNUNET_DATACACHE_put (h,
-                                &k,
-                                GNUNET_YES,
-                                sizeof(struct GNUNET_HashCode),
-                                (const char *) &n,
-                                792,
-                                GNUNET_TIME_UNIT_FOREVER_ABS,
-                                0,
-                                NULL));
+                                42,
+                                &block));
   ASSERT (0 != GNUNET_DATACACHE_get (h,
                                      &k,
                                      792,
diff --git a/src/datacache/test_datacache_quota.c 
b/src/datacache/test_datacache_quota.c
index 92807fbe2..0b647ee99 100644
--- a/src/datacache/test_datacache_quota.c
+++ b/src/datacache/test_datacache_quota.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2006, 2009, 2010 GNUnet e.V.
+     Copyright (C) 2006, 2009, 2010, 2022 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
@@ -53,8 +53,8 @@ run (void *cls,
   struct GNUNET_DATACACHE_Handle *h;
   struct GNUNET_HashCode k;
   struct GNUNET_HashCode n;
+  struct GNUNET_DATACACHE_Block block;
   char buf[3200];
-  struct GNUNET_TIME_Absolute exp;
 
   (void) cls;
   (void) args;
@@ -70,9 +70,14 @@ run (void *cls,
              "Failed to initialize datacache.  Database likely not setup, 
skipping test.\n");
     return;
   }
-  exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS);
-  memset (buf, 1, sizeof(buf));
-  memset (&k, 0, sizeof(struct GNUNET_HashCode));
+  block.expiration_time = GNUNET_TIME_relative_to_absolute (
+    GNUNET_TIME_UNIT_HOURS);
+  memset (buf,
+          1,
+          sizeof(buf));
+  memset (&k,
+          0,
+          sizeof(struct GNUNET_HashCode));
   for (unsigned int i = 0; i < 10; i++)
   {
     fprintf (stderr,
@@ -83,35 +88,56 @@ run (void *cls,
                         &n);
     for (unsigned int j = i; j < sizeof(buf); j += 10)
     {
-      exp.abs_value_us++;
       buf[j] = i;
+      block.key = k;
+      block.data = buf;
+      block.data_size = j;
+      block.ro = 42;
+      block.type = (enum GNUNET_BLOCK_Type) (1 + i);
+      block.put_path = NULL;
+      block.put_path_length = 0;
+      block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
+      block.expiration_time.abs_value_us++;
       ASSERT (GNUNET_OK ==
               GNUNET_DATACACHE_put (h,
-                                    &k,
-                                    GNUNET_YES,
-                                    j,
-                                    buf,
-                                    1 + i,
-                                    exp,
-                                    0,
-                                    NULL));
-      ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
+                                    42,
+                                    &block));
+      ASSERT (0 < GNUNET_DATACACHE_get (h,
+                                        &k,
+                                        1 + i,
+                                        NULL,
+                                        NULL));
     }
     k = n;
   }
   fprintf (stderr, "%s", "\n");
-  memset (&k, 0, sizeof(struct GNUNET_HashCode));
+  memset (&k,
+          0,
+          sizeof(struct GNUNET_HashCode));
   for (unsigned int i = 0; i < 10; i++)
   {
     fprintf (stderr, "%s", ".");
-    GNUNET_CRYPTO_hash (&k, sizeof(struct GNUNET_HashCode), &n);
+    GNUNET_CRYPTO_hash (&k,
+                        sizeof(struct GNUNET_HashCode),
+                        &n);
     if (i < 2)
-      ASSERT (0 == GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
+      ASSERT (0 ==
+              GNUNET_DATACACHE_get (h,
+                                    &k,
+                                    1 + i,
+                                    NULL,
+                                    NULL));
     if (i == 9)
-      ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
+      ASSERT (0 < GNUNET_DATACACHE_get (h,
+                                        &k,
+                                        1 + i,
+                                        NULL,
+                                        NULL));
     k = n;
   }
-  fprintf (stderr, "%s", "\n");
+  fprintf (stderr,
+           "%s",
+           "\n");
   GNUNET_DATACACHE_destroy (h);
   return;
 FAILURE:
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index a1513fcce..5507dcea0 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -149,7 +149,7 @@ GDS_u_hold (struct GDS_Underlay *u,
  * @return true on success, false on failures
  */
 bool
-GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
+GDS_CLIENTS_handle_reply (const struct GNUNET_DATACACHE_Block *bd,
                           const struct GNUNET_HashCode *query_hash,
                           unsigned int get_path_length,
                           const struct GNUNET_DHT_PathElement *get_path);
@@ -186,7 +186,7 @@ GDS_CLIENTS_process_get (enum GNUNET_DHT_RouteOption 
options,
  * @param get_path_length number of entries in @a get_path.
  */
 void
-GDS_CLIENTS_process_get_resp (const struct GDS_DATACACHE_BlockData *bd,
+GDS_CLIENTS_process_get_resp (const struct GNUNET_DATACACHE_Block *bd,
                               const struct GNUNET_DHT_PathElement *get_path,
                               unsigned int get_path_length);
 
@@ -196,14 +196,12 @@ GDS_CLIENTS_process_get_resp (const struct 
GDS_DATACACHE_BlockData *bd,
  * them in that case. The @a path should include our own
  * peer ID (if recorded).
  *
- * @param options routing options to apply
  * @param bd details about the block
  * @param hop_count Hop count so far.
  * @param desired_replication_level Desired replication level.
  */
 void
-GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
-                         const struct GDS_DATACACHE_BlockData *bd,
+GDS_CLIENTS_process_put (const struct GNUNET_DATACACHE_Block *bd,
                          uint32_t hop_count,
                          uint32_t desired_replication_level);
 
diff --git a/src/dht/gnunet-service-dht_clients.c 
b/src/dht/gnunet-service-dht_clients.c
index fd65102b3..631c4f68b 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -490,16 +490,15 @@ handle_dht_local_put (void *cls,
 {
   struct ClientHandle *ch = cls;
   uint16_t size = ntohs (dht_msg->header.size);
-  enum GNUNET_DHT_RouteOption options
-    = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options);
   uint32_t replication_level
     = ntohl (dht_msg->desired_replication_level);
-  struct GDS_DATACACHE_BlockData bd = {
+  struct GNUNET_DATACACHE_Block bd = {
     .key = dht_msg->key,
     .expiration_time = GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
     .data = &dht_msg[1],
     .data_size = size - sizeof (*dht_msg),
-    .type = ntohl (dht_msg->type)
+    .type = ntohl (dht_msg->type),
+    .ro = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options)
   };
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -536,14 +535,13 @@ handle_dht_local_put (void *cls,
                                            DHT_BLOOM_SIZE,
                                            GNUNET_CONSTANTS_BLOOMFILTER_K);
     /* store locally */
-    if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+    if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
          (GDS_am_closest_peer (&dht_msg->key,
                                peer_bf)))
       GDS_DATACACHE_handle_put (&bd);
     /* route to other peers */
     if (GNUNET_OK !=
         GDS_NEIGHBOURS_handle_put (&bd,
-                                   options,
                                    replication_level,
                                    0 /* hop count */,
                                    peer_bf))
@@ -556,7 +554,6 @@ handle_dht_local_put (void *cls,
     GNUNET_CONTAINER_bloomfilter_free (peer_bf);
   }
   GDS_CLIENTS_process_put (
-    options,
     &bd,
     0,  /* hop count */
     replication_level);
@@ -572,7 +569,7 @@ handle_dht_local_put (void *cls,
  */
 static void
 handle_local_result (void *cls,
-                     const struct GDS_DATACACHE_BlockData *bd)
+                     const struct GNUNET_DATACACHE_Block *bd)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Datacache provided result for query key %s\n",
@@ -877,7 +874,7 @@ struct ForwardReplyContext
   /**
    * Block details.
    */
-  const struct GDS_DATACACHE_BlockData *bd;
+  const struct GNUNET_DATACACHE_Block *bd;
 
   /**
    * GET path taken.
@@ -1034,7 +1031,7 @@ forward_reply (void *cls,
 
 
 bool
-GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
+GDS_CLIENTS_handle_reply (const struct GNUNET_DATACACHE_Block *bd,
                           const struct GNUNET_HashCode *query_hash,
                           unsigned int get_path_length,
                           const struct GNUNET_DHT_PathElement *get_path)
@@ -1414,7 +1411,7 @@ GDS_CLIENTS_process_get (enum GNUNET_DHT_RouteOption 
options,
  */
 struct ResponseActionContext
 {
-  const struct GDS_DATACACHE_BlockData *bd;
+  const struct GNUNET_DATACACHE_Block *bd;
   const struct GNUNET_DHT_PathElement *get_path;
   unsigned int get_path_length;
 };
@@ -1432,7 +1429,7 @@ response_action (void *cls,
                  struct ClientMonitorRecord *m)
 {
   const struct ResponseActionContext *resp_ctx = cls;
-  const struct GDS_DATACACHE_BlockData *bd = resp_ctx->bd;
+  const struct GNUNET_DATACACHE_Block *bd = resp_ctx->bd;
 
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_DHT_MonitorGetRespMessage *mmsg;
@@ -1467,7 +1464,7 @@ response_action (void *cls,
 
 
 void
-GDS_CLIENTS_process_get_resp (const struct GDS_DATACACHE_BlockData *bd,
+GDS_CLIENTS_process_get_resp (const struct GNUNET_DATACACHE_Block *bd,
                               const struct GNUNET_DHT_PathElement *get_path,
                               unsigned int get_path_length)
 {
@@ -1489,8 +1486,7 @@ GDS_CLIENTS_process_get_resp (const struct 
GDS_DATACACHE_BlockData *bd,
  */
 struct PutActionContext
 {
-  const struct GDS_DATACACHE_BlockData *bd;
-  enum GNUNET_DHT_RouteOption options;
+  const struct GNUNET_DATACACHE_Block *bd;
   uint32_t hop_count;
   uint32_t desired_replication_level;
 };
@@ -1508,7 +1504,7 @@ put_action (void *cls,
             struct ClientMonitorRecord *m)
 {
   const struct PutActionContext *put_ctx = cls;
-  const struct GDS_DATACACHE_BlockData *bd = put_ctx->bd;
+  const struct GNUNET_DATACACHE_Block *bd = put_ctx->bd;
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_DHT_MonitorPutMessage *mmsg;
   struct GNUNET_DHT_PathElement *msg_path;
@@ -1520,7 +1516,7 @@ put_action (void *cls,
   env = GNUNET_MQ_msg_extra (mmsg,
                              msize,
                              GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
-  mmsg->options = htonl (put_ctx->options);
+  mmsg->options = htonl (bd->ro);
   mmsg->type = htonl (bd->type);
   mmsg->hop_count = htonl (put_ctx->hop_count);
   mmsg->desired_replication_level = htonl (put_ctx->desired_replication_level);
@@ -1540,16 +1536,14 @@ put_action (void *cls,
 
 
 void
-GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
-                         const struct GDS_DATACACHE_BlockData *bd,
+GDS_CLIENTS_process_put (const struct GNUNET_DATACACHE_Block *bd,
                          uint32_t hop_count,
                          uint32_t desired_replication_level)
 {
   struct PutActionContext put_ctx = {
     .bd = bd,
     .hop_count = hop_count,
-    .desired_replication_level = desired_replication_level,
-    .options = options
+    .desired_replication_level = desired_replication_level
   };
 
   for_matching_monitors (bd->type,
diff --git a/src/dht/gnunet-service-dht_datacache.c 
b/src/dht/gnunet-service-dht_datacache.c
index be0a6db81..dcb6308a9 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -46,7 +46,7 @@ static struct GNUNET_DATACACHE_Handle *datacache;
 
 
 void
-GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd)
+GDS_DATACACHE_handle_put (const struct GNUNET_DATACACHE_Block *bd)
 {
   struct GNUNET_HashCode xor;
   enum GNUNET_GenericReturnValue r;
@@ -71,14 +71,8 @@ GDS_DATACACHE_handle_put (const struct 
GDS_DATACACHE_BlockData *bd)
                           &GDS_my_identity_hash,
                           &xor);
   r = GNUNET_DATACACHE_put (datacache,
-                            &bd->key,
                             GNUNET_CRYPTO_hash_count_leading_zeros (&xor),
-                            bd->data_size,
-                            bd->data,
-                            bd->type,
-                            bd->expiration_time,
-                            bd->put_path_length,
-                            bd->put_path);
+                            bd);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n",
        GNUNET_h2s (&bd->key),
@@ -134,55 +128,34 @@ struct GetRequestContext
  * Iterator for local get request results,
  *
  * @param cls closure for iterator, a `struct GetRequestContext`
- * @param exp when does this value expire?
- * @param key the key this data is stored under
- * @param data_size the size of the data identified by key
- * @param data the actual data
- * @param type the type of the @a data
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
+ * @param bd block data
  * @return #GNUNET_OK to continue iteration, anything else
  * to stop iteration.
  */
 static enum GNUNET_GenericReturnValue
 datacache_get_iterator (void *cls,
-                        const struct GNUNET_HashCode *key,
-                        size_t data_size,
-                        const char *data,
-                        enum GNUNET_BLOCK_Type type,
-                        struct GNUNET_TIME_Absolute exp,
-                        unsigned int put_path_length,
-                        const struct GNUNET_DHT_PathElement *put_path)
+                        const struct GNUNET_DATACACHE_Block *bd)
 {
   struct GetRequestContext *ctx = cls;
   enum GNUNET_BLOCK_ReplyEvaluationResult eval;
-  struct GDS_DATACACHE_BlockData bd = {
-    .key = *key,
-    .expiration_time = exp,
-    .put_path = put_path,
-    .data = data,
-    .data_size = data_size,
-    .put_path_length = put_path_length,
-    .type = type
-  };
 
-  if (GNUNET_TIME_absolute_is_past (exp))
+  if (GNUNET_TIME_absolute_is_past (bd->expiration_time))
   {
     GNUNET_break (0);  /* why does datacache return expired values? */
     return GNUNET_OK;   /* skip expired record */
   }
   eval
     = GNUNET_BLOCK_check_reply (GDS_block_context,
-                                bd.type,
+                                bd->type,
                                 ctx->bg,
-                                &bd.key,
+                                &bd->key,
                                 ctx->xquery,
                                 ctx->xquery_size,
-                                bd.data,
-                                bd.data_size);
+                                bd->data,
+                                bd->data_size);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Evaluated reply for query %s in datacache, result is %d\n",
-       GNUNET_h2s (key),
+       GNUNET_h2s (&bd->key),
        (int) eval);
   ctx->eval = eval;
   switch (eval)
@@ -196,7 +169,7 @@ datacache_get_iterator (void *cls,
                               1,
                               GNUNET_NO);
     ctx->gc (ctx->gc_cls,
-             &bd);
+             bd);
     break;
   case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
     GNUNET_STATISTICS_update (GDS_stats,
@@ -225,7 +198,7 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
                           void *gc_cls)
 {
   struct GetRequestContext ctx = {
-                                  .eval = 
GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
+    .eval = GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
     .key = *key,
     .xquery = xquery,
     .xquery_size = xquery_size,
@@ -265,7 +238,7 @@ GDS_DATACACHE_get_closest (const struct GNUNET_HashCode 
*key,
                            void *cb_cls)
 {
   struct GetRequestContext ctx = {
-                                  .eval = 
GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
+    .eval = GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED,
     .key = *key,
     .xquery = xquery,
     .xquery_size = xquery_size,
diff --git a/src/dht/gnunet-service-dht_datacache.h 
b/src/dht/gnunet-service-dht_datacache.h
index d860139f5..b15e5378f 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -30,48 +30,7 @@
 #include "gnunet_util_lib.h"
 #include "gnunet_block_lib.h"
 #include "gnunet_dht_service.h"
-
-
-/**
- * Information about a block stored in the datacache.
- */
-struct GDS_DATACACHE_BlockData
-{
-  /**
-   * Key of the block.
-   */
-  struct GNUNET_HashCode key;
-
-  /**
-   * When does the block expire?
-   */
-  struct GNUNET_TIME_Absolute expiration_time;
-
-  /**
-   * PUT path taken by the block, array of peer identities.
-   */
-  const struct GNUNET_DHT_PathElement *put_path;
-
-  /**
-   * Actual block data.
-   */
-  const void *data;
-
-  /**
-   * Number of bytes in @a data.
-   */
-  size_t data_size;
-
-  /**
-   * Length of the @e put_path array.
-   */
-  unsigned int put_path_length;
-
-  /**
-   * Type of the block.
-   */
-  enum GNUNET_BLOCK_Type type;
-};
+#include "gnunet_datacache_lib.h"
 
 
 /**
@@ -81,7 +40,7 @@ struct GDS_DATACACHE_BlockData
  * @param bd block data to cache
  */
 void
-GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd);
+GDS_DATACACHE_handle_put (const struct GNUNET_DATACACHE_Block *bd);
 
 
 /**
@@ -92,7 +51,7 @@ GDS_DATACACHE_handle_put (const struct 
GDS_DATACACHE_BlockData *bd);
  */
 typedef void
 (*GDS_DATACACHE_GetCallback)(void *cls,
-                             const struct GDS_DATACACHE_BlockData *bd);
+                             const struct GNUNET_DATACACHE_Block *bd);
 
 
 /**
diff --git a/src/dht/gnunet-service-dht_neighbours.c 
b/src/dht/gnunet-service-dht_neighbours.c
index fde25936f..2a54f715a 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -1285,7 +1285,7 @@ get_target_peers (const struct GNUNET_HashCode *key,
  * @param bd block data we got
  */
 static void
-hello_check (const struct GDS_DATACACHE_BlockData *bd)
+hello_check (const struct GNUNET_DATACACHE_Block *bd)
 {
   struct GNUNET_PeerIdentity pid;
   struct GNUNET_HELLO_Builder *b;
@@ -1305,8 +1305,7 @@ hello_check (const struct GDS_DATACACHE_BlockData *bd)
 
 
 enum GNUNET_GenericReturnValue
-GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
-                           enum GNUNET_DHT_RouteOption options,
+GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
                            uint16_t desired_replication_level,
                            uint16_t hop_count,
                            struct GNUNET_CONTAINER_BloomFilter *bf)
@@ -1336,8 +1335,8 @@ GDS_NEIGHBOURS_handle_put (const struct 
GDS_DATACACHE_BlockData *bd,
               "Adding myself (%s) to PUT bloomfilter for %s with RO(%s/%s)\n",
               GNUNET_i2s (&GDS_my_identity),
               GNUNET_h2s (&bd->key),
-              (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
-              (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
+              (bd->ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
+              (bd->ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
 
   /* if we got a HELLO, consider it for our own routing table */
   hello_check (bd);
@@ -1394,7 +1393,7 @@ GDS_NEIGHBOURS_handle_put (const struct 
GDS_DATACACHE_BlockData *bd,
     ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
     ppm->header.size = htons (sizeof (buf));
     ppm->type = htonl (bd->type);
-    ppm->options = htons (options);
+    ppm->options = htons (bd->ro);
     ppm->hop_count = htons (hop_count + 1);
     ppm->desired_replication_level = htons (desired_replication_level);
     ppm->put_path_length = htons (put_path_length);
@@ -1565,7 +1564,7 @@ GDS_NEIGHBOURS_lookup_peer (const struct 
GNUNET_PeerIdentity *target)
 
 bool
 GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
-                             const struct GDS_DATACACHE_BlockData *bd,
+                             const struct GNUNET_DATACACHE_Block *bd,
                              const struct GNUNET_HashCode *query_hash,
                              unsigned int get_path_length,
                              const struct GNUNET_DHT_PathElement *get_path)
@@ -1748,16 +1747,15 @@ handle_dht_p2p_put (void *cls,
   struct Target *t = cls;
   struct PeerInfo *peer = t->pi;
   uint16_t msize = ntohs (put->header.size);
-  enum GNUNET_DHT_RouteOption options
-    = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
   const struct GNUNET_DHT_PathElement *put_path
     = (const struct GNUNET_DHT_PathElement *) &put[1];
   uint16_t putlen
     = ntohs (put->put_path_length);
-  struct GDS_DATACACHE_BlockData bd = {
+  struct GNUNET_DATACACHE_Block bd = {
     .key = put->key,
     .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
     .type = ntohl (put->type),
+    .ro = (enum GNUNET_DHT_RouteOption) ntohs (put->options),
     .data_size = msize - (sizeof(*put)
                           + putlen * sizeof(struct GNUNET_DHT_PathElement)),
     .data = &put_path[putlen]
@@ -1767,8 +1765,8 @@ handle_dht_p2p_put (void *cls,
               "PUT for `%s' from %s with RO (%s/%s)\n",
               GNUNET_h2s (&put->key),
               GNUNET_i2s (&peer->id),
-              (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
-              (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
+              (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
+              (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
   if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
   {
     GNUNET_STATISTICS_update (GDS_stats,
@@ -1786,7 +1784,7 @@ handle_dht_p2p_put (void *cls,
     GNUNET_break_op (0);
     return;
   }
-  if (0 == (options & GNUNET_DHT_RO_RECORD_ROUTE))
+  if (0 == (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE))
     putlen = 0;
   GNUNET_STATISTICS_update (GDS_stats,
                             "# P2P PUT requests received",
@@ -1837,7 +1835,7 @@ handle_dht_p2p_put (void *cls,
     /* extend 'put path' by sender */
     bd.put_path = (const struct GNUNET_DHT_PathElement *) pp;
     bd.put_path_length = putlen + 1;
-    if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
+    if (0 != (bd.ro & GNUNET_DHT_RO_RECORD_ROUTE))
     {
       unsigned int failure_offset;
 
@@ -1884,7 +1882,7 @@ handle_dht_p2p_put (void *cls,
                                             0, NULL /* get path */));
 
     /* store locally */
-    if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+    if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
          (GDS_am_closest_peer (&put->key,
                                bf)) )
       GDS_DATACACHE_handle_put (&bd);
@@ -1894,16 +1892,14 @@ handle_dht_p2p_put (void *cls,
       /* route to other peers */
       forwarded
         = GDS_NEIGHBOURS_handle_put (&bd,
-                                     options,
                                      ntohs (put->desired_replication_level),
                                      ntohs (put->hop_count),
                                      bf);
       /* notify monitoring clients */
-      GDS_CLIENTS_process_put (options
-                               | ((GNUNET_OK == forwarded)
-                                ? GNUNET_DHT_RO_LAST_HOP
-                                : 0),
-                               &bd,
+      bd.ro |= ((GNUNET_OK == forwarded)
+                ? GNUNET_DHT_RO_LAST_HOP
+                : 0);
+      GDS_CLIENTS_process_put (&bd,
                                ntohs (put->hop_count),
                                ntohs (put->desired_replication_level));
     }
@@ -1957,7 +1953,7 @@ handle_find_my_hello (struct PeerInfo *pi,
                                        block,
                                        block_size))
     {
-      struct GDS_DATACACHE_BlockData bd = {
+      struct GNUNET_DATACACHE_Block bd = {
         .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
         .expiration_time
           = GNUNET_TIME_relative_to_absolute (
@@ -2014,7 +2010,7 @@ handle_find_local_hello (struct PeerInfo *pi,
           peer->hello,
           peer->hello_size)) )
   {
-    struct GDS_DATACACHE_BlockData bd = {
+    struct GNUNET_DATACACHE_Block bd = {
       .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
       .expiration_time = peer->hello_expiration,
       .key = peer->phash,
@@ -2038,7 +2034,7 @@ handle_find_local_hello (struct PeerInfo *pi,
  */
 static void
 handle_local_result (void *cls,
-                     const struct GDS_DATACACHE_BlockData *bd)
+                     const struct GNUNET_DATACACHE_Block *bd)
 {
   struct PeerInfo *peer = cls;
 
@@ -2242,7 +2238,7 @@ handle_dht_p2p_get (void *cls,
  * @return true on success
  */
 static bool
-process_reply_with_path (const struct GDS_DATACACHE_BlockData *bd,
+process_reply_with_path (const struct GNUNET_DATACACHE_Block *bd,
                          const struct GNUNET_HashCode *query_hash,
                          unsigned int get_path_length,
                          const struct GNUNET_DHT_PathElement *get_path)
@@ -2265,7 +2261,7 @@ process_reply_with_path (const struct 
GDS_DATACACHE_BlockData *bd,
   {
     struct GNUNET_DHT_PathElement xput_path[GNUNET_NZL (get_path_length
                                                         + 
bd->put_path_length)];
-    struct GDS_DATACACHE_BlockData bdx = *bd;
+    struct GNUNET_DATACACHE_Block bdx = *bd;
 
     GNUNET_memcpy (xput_path,
                    bd->put_path,
@@ -2332,7 +2328,7 @@ handle_dht_p2p_result (void *cls,
   struct PeerInfo *peer = t->pi;
   uint16_t msize = ntohs (prm->header.size);
   uint16_t get_path_length = ntohs (prm->get_path_length);
-  struct GDS_DATACACHE_BlockData bd = {
+  struct GNUNET_DATACACHE_Block bd = {
     .expiration_time  = GNUNET_TIME_absolute_ntoh (prm->expiration_time),
     .put_path = (const struct GNUNET_DHT_PathElement *) &prm[1],
     .put_path_length = ntohs (prm->put_path_length),
diff --git a/src/dht/gnunet-service-dht_neighbours.h 
b/src/dht/gnunet-service-dht_neighbours.h
index 4f4172f71..96db21b9b 100644
--- a/src/dht/gnunet-service-dht_neighbours.h
+++ b/src/dht/gnunet-service-dht_neighbours.h
@@ -54,15 +54,13 @@ GDS_NEIGHBOURS_lookup_peer (const struct 
GNUNET_PeerIdentity *target);
  * network).
  *
  * @param bd data about the block
- * @param options routing options
  * @param desired_replication_level desired replication level
  * @param hop_count how many hops has this message traversed so far
  * @param bf Bloom filter of peers this PUT has already traversed
  * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
  */
 enum GNUNET_GenericReturnValue
-GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
-                           enum GNUNET_DHT_RouteOption options,
+GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd,
                            uint16_t desired_replication_level,
                            uint16_t hop_count,
                            struct GNUNET_CONTAINER_BloomFilter *bf);
@@ -112,7 +110,7 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
  */
 bool
 GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
-                             const struct GDS_DATACACHE_BlockData *bd,
+                             const struct GNUNET_DATACACHE_Block *bd,
                              const struct GNUNET_HashCode *query_hash,
                              unsigned int get_path_length,
                              const struct GNUNET_DHT_PathElement *get_path);
diff --git a/src/dht/gnunet-service-dht_routing.c 
b/src/dht/gnunet-service-dht_routing.c
index 6deb5fa16..8f87751bb 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -105,7 +105,7 @@ struct ProcessContext
   /**
    * Block data.
    */
-  const struct GDS_DATACACHE_BlockData *bd;
+  const struct GNUNET_DATACACHE_Block *bd;
 
   /**
    * Path of the reply.
@@ -137,7 +137,7 @@ process (void *cls,
   struct RecentRequest *rr = value;
   enum GNUNET_BLOCK_ReplyEvaluationResult eval;
   unsigned int get_path_length;
-  struct GDS_DATACACHE_BlockData bdx = *pc->bd;
+  struct GNUNET_DATACACHE_Block bdx = *pc->bd;
 
   if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) &&
        (rr->type != pc->bd->type) )
@@ -252,7 +252,7 @@ process (void *cls,
  * @param get_path peers this reply has traversed so far (if tracked)
  */
 void
-GDS_ROUTING_process (const struct GDS_DATACACHE_BlockData *bd,
+GDS_ROUTING_process (const struct GNUNET_DATACACHE_Block *bd,
                      const struct GNUNET_HashCode *query_hash,
                      unsigned int get_path_length,
                      const struct GNUNET_DHT_PathElement *get_path)
diff --git a/src/dht/gnunet-service-dht_routing.h 
b/src/dht/gnunet-service-dht_routing.h
index 1e35f3dc0..08c7de870 100644
--- a/src/dht/gnunet-service-dht_routing.h
+++ b/src/dht/gnunet-service-dht_routing.h
@@ -44,7 +44,7 @@
  * @param get_path peers this reply has traversed so far (if tracked)
  */
 void
-GDS_ROUTING_process (const struct GDS_DATACACHE_BlockData *bd,
+GDS_ROUTING_process (const struct GNUNET_DATACACHE_Block *bd,
                      const struct GNUNET_HashCode *query_hash,
                      unsigned int get_path_length,
                      const struct GNUNET_DHT_PathElement *get_path);
diff --git a/src/gnsrecord/gnunet-gnsrecord-tvg.c 
b/src/gnsrecord/gnunet-gnsrecord-tvg.c
index d45b3a5d8..4d5eb73b3 100644
--- a/src/gnsrecord/gnunet-gnsrecord-tvg.c
+++ b/src/gnsrecord/gnunet-gnsrecord-tvg.c
@@ -173,7 +173,7 @@ run_pkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, 
const char *label)
   printf ("Label:\n");
   print_bytes (conv_lbl, strlen (conv_lbl), 8);
   GNUNET_free (conv_lbl);
-  printf ("\Number of records (integer): %d\n\n", rd_count);
+  printf ("\nNumber of records (integer): %d\n\n", rd_count);
 
   for (int i = 0; i < rd_count; i++)
   {
@@ -300,7 +300,7 @@ run_edkey (struct GNUNET_GNSRECORD_Data *rd, int rd_count, 
const char*label)
   print_bytes (conv_lbl, strlen (conv_lbl), 8);
   GNUNET_free (conv_lbl);
   fprintf (stdout,
-           "\Number of records (integer): %d\n\n", rd_count);
+           "\nNumber of records (integer): %d\n\n", rd_count);
 
   for (int i = 0; i < rd_count; i++)
   {
diff --git a/src/include/gnunet_datacache_lib.h 
b/src/include/gnunet_datacache_lib.h
index 737a5c845..c4d74524a 100644
--- a/src/include/gnunet_datacache_lib.h
+++ b/src/include/gnunet_datacache_lib.h
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2006, 2009, 2015 GNUnet e.V.
+     Copyright (C) 2006, 2009, 2015, 2022 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
@@ -50,6 +50,53 @@ extern "C"
 #endif
 
 
+/**
+ * Information about a block stored in the datacache.
+ */
+struct GNUNET_DATACACHE_Block
+{
+  /**
+   * Key of the block.
+   */
+  struct GNUNET_HashCode key;
+
+  /**
+   * When does the block expire?
+   */
+  struct GNUNET_TIME_Absolute expiration_time;
+
+  /**
+   * PUT path taken by the block, array of peer identities.
+   */
+  const struct GNUNET_DHT_PathElement *put_path;
+
+  /**
+   * Actual block data.
+   */
+  const void *data;
+
+  /**
+   * Number of bytes in @a data.
+   */
+  size_t data_size;
+
+  /**
+   * Length of the @e put_path array.
+   */
+  unsigned int put_path_length;
+
+  /**
+   * Type of the block.
+   */
+  enum GNUNET_BLOCK_Type type;
+
+  /**
+   * Options for routing for the block.
+   */
+  enum GNUNET_DHT_RouteOption ro;
+};
+
+
 /**
  * Handle to the cache.
  */
@@ -81,50 +128,26 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle 
*h);
  * An iterator over a set of items stored in the datacache.
  *
  * @param cls closure
- * @param key key for the content
- * @param data_size number of bytes in @a data
- * @param data content stored
- * @param type type of the content
- * @param exp when will the content expire?
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param block a block from the datacache
  * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
  */
 typedef enum GNUNET_GenericReturnValue
 (*GNUNET_DATACACHE_Iterator)(void *cls,
-                             const struct GNUNET_HashCode *key,
-                             size_t data_size,
-                             const char *data,
-                             enum GNUNET_BLOCK_Type type,
-                             struct GNUNET_TIME_Absolute exp,
-                             unsigned int path_info_len,
-                             const struct GNUNET_DHT_PathElement *path_info);
+                             const struct GNUNET_DATACACHE_Block *block);
 
 
 /**
  * Store an item in the datacache.
  *
  * @param h handle to the datacache
- * @param key key to store data under
- * @param how close is @a key to our pid?
- * @param data_size number of bytes in @a data
- * @param data data to store
- * @param type type of the value
- * @param discard_time when to discard the value in any case
- * @param path_info_len number of entries in @a path_info
- * @param path_info a path through the network
+ * @param xor_distance how close is the block's key to our pid?
+ * @param block actual block data to store
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error, #GNUNET_NO if 
duplicate
  */
 enum GNUNET_GenericReturnValue
 GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
-                      const struct GNUNET_HashCode *key,
                       uint32_t xor_distance,
-                      size_t data_size,
-                      const char *data,
-                      enum GNUNET_BLOCK_Type type,
-                      struct GNUNET_TIME_Absolute discard_time,
-                      unsigned int path_info_len,
-                      const struct GNUNET_DHT_PathElement *path_info);
+                      const struct GNUNET_DATACACHE_Block *block);
 
 
 /**
diff --git a/src/include/gnunet_datacache_plugin.h 
b/src/include/gnunet_datacache_plugin.h
index 34bf5f277..7e63d87d9 100644
--- a/src/include/gnunet_datacache_plugin.h
+++ b/src/include/gnunet_datacache_plugin.h
@@ -105,26 +105,14 @@ struct GNUNET_DATACACHE_PluginFunctions
    * Store an item in the datastore.
    *
    * @param cls closure (internal context for the plugin)
-   * @param key key to store the value under
    * @param xor_distance how close is @a key to our PID?
-   * @param size number of bytes in @a data
-   * @param data data to store
-   * @param type type of the value
-   * @param discard_time when to discard the value in any case
-   * @param path_info_len number of entries in @a path_info
-   * @param path_info a path through the network
+   * @param block data to store
    * @return 0 if duplicate, -1 on error, number of bytes used otherwise
    */
   ssize_t
   (*put) (void *cls,
-          const struct GNUNET_HashCode *key,
           uint32_t xor_distance,
-          size_t size,
-          const char *data,
-          enum GNUNET_BLOCK_Type type,
-          struct GNUNET_TIME_Absolute discard_time,
-          unsigned int path_info_len,
-          const struct GNUNET_DHT_PathElement *path_info);
+          const struct GNUNET_DATACACHE_Block *block);
 
 
   /**
diff --git a/src/include/gnunet_dht_service.h b/src/include/gnunet_dht_service.h
index 22b659d66..d683ae0bf 100644
--- a/src/include/gnunet_dht_service.h
+++ b/src/include/gnunet_dht_service.h
@@ -105,11 +105,16 @@ enum GNUNET_DHT_RouteOption
    */
   GNUNET_DHT_RO_FIND_APPROXIMATE = 4,
 
+  /**
+   * Flag set if the path was truncated.
+   */
+  GNUNET_DHT_RO_TRUNCATED = 8,
+
   /**
    * Flag given to monitors if this was the last hop for a GET/PUT.
    * This is only used for internal processing.
    */
-  GNUNET_DHT_RO_LAST_HOP = 65535
+  GNUNET_DHT_RO_LAST_HOP = 32768
 };
 
 
diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h
index e89ded07e..51713e755 100644
--- a/src/include/gnunet_sq_lib.h
+++ b/src/include/gnunet_sq_lib.h
@@ -194,7 +194,7 @@ GNUNET_SQ_query_param_uint64 (const uint64_t *x);
  * @param params parameters to the statement
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_SQ_bind (sqlite3_stmt *stmt,
                 const struct GNUNET_SQ_QueryParam *params);
 
@@ -498,7 +498,7 @@ GNUNET_SQ_make_prepare (const char *sql,
  * @param ps array of statements to prepare
  * @return #GNUNET_OK on success
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_SQ_prepare (sqlite3 *dbh,
                    const struct GNUNET_SQ_PrepareStatement *ps);
 
@@ -520,7 +520,7 @@ struct GNUNET_SQ_ExecuteStatement
   /**
    * Should we ignore errors?
    */
-  int ignore_errors;
+  bool ignore_errors;
 };
 
 
@@ -560,7 +560,7 @@ GNUNET_SQ_make_try_execute (const char *sql);
  * @return #GNUNET_OK on success (modulo statements where errors can be 
ignored)
  *         #GNUNET_SYSERR on error
  */
-int
+enum GNUNET_GenericReturnValue
 GNUNET_SQ_exec_statements (sqlite3 *dbh,
                            const struct GNUNET_SQ_ExecuteStatement *es);
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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