first half of new BLOCK API to generalize duplicate detection beyond BFs
authorChristian Grothoff <christian@grothoff.org>
Mon, 20 Feb 2017 14:09:00 +0000 (15:09 +0100)
committerChristian Grothoff <christian@grothoff.org>
Mon, 20 Feb 2017 14:09:19 +0000 (15:09 +0100)
15 files changed:
src/block/Makefile.am
src/block/bg_bf.c [new file with mode: 0644]
src/block/block.c
src/dht/Makefile.am
src/dht/plugin_block_dht.c
src/dns/plugin_block_dns.c
src/fs/Makefile.am
src/fs/plugin_block_fs.c
src/gns/Makefile.am
src/gns/plugin_block_gns.c
src/include/gnunet_block_group_lib.h [new file with mode: 0644]
src/include/gnunet_block_lib.h
src/include/gnunet_block_plugin.h
src/regex/Makefile.am
src/regex/plugin_block_regex.c

index c54a4c246fbae678e0e16d724182e8b32562c794..4a6d8e71e4fc89adb27f61d75050e376de85890f 100644 (file)
@@ -11,7 +11,9 @@ if USE_COVERAGE
   AM_CFLAGS = --coverage
 endif
 
-lib_LTLIBRARIES = libgnunetblock.la
+lib_LTLIBRARIES = \
+  libgnunetblock.la \
+  libgnunetblockgroup.la
 
 plugin_LTLIBRARIES = \
   libgnunet_plugin_block_test.la
@@ -49,3 +51,14 @@ libgnunetblock_la_DEPENDENCIES = \
 libgnunetblock_la_LDFLAGS = \
   $(GN_LIB_LDFLAGS) \
   -version-info 0:0:0
+
+
+libgnunetblockgroup_la_SOURCES = \
+  bg_bf.c
+libgnunetblockgroup_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+libgnunetblockgroup_la_DEPENDENCIES = \
+ $(top_builddir)/src/util/libgnunetutil.la
+libgnunetblockgroup_la_LDFLAGS = \
+  $(GN_LIB_LDFLAGS) \
+  -version-info 0:0:0
diff --git a/src/block/bg_bf.c b/src/block/bg_bf.c
new file mode 100644 (file)
index 0000000..f03ae52
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2017 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file block/bg_bf.c
+ * @brief implementation of a block group using a Bloom filter
+ *        to drop duplicate blocks
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_block_group_lib.h"
+#include "gnunet_block_plugin.h"
+
+
+/**
+ * Internal data structure for a block group.
+ */
+struct BfGroupInternals
+{
+  /**
+   * A Bloom filter to weed out duplicate replies probabilistically.
+   */
+  struct GNUNET_CONTAINER_BloomFilter *bf;
+
+  /**
+   * Set from the nonce to mingle the hashes before going into the @e bf.
+   */
+  uint32_t bf_mutator;
+
+  /**
+   * Size of @a bf.
+   */
+  uint32_t bf_size;
+
+};
+
+
+/**
+ * Serialize state of a block group.
+ *
+ * @param bg group to serialize
+ * @param[out] raw_data set to the serialized state
+ * @param[out] raw_data_size set to the number of bytes in @a raw_data
+ * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
+ *         supported, #GNUNET_SYSERR on error
+ */
+static int
+bf_group_serialize_cb (struct GNUNET_BLOCK_Group *bg,
+                       void **raw_data,
+                       size_t *raw_data_size)
+{
+  struct BfGroupInternals *gi = bg->internal_cls;
+  char *raw;
+
+  raw = GNUNET_malloc (gi->bf_size);
+  if (GNUNET_OK !=
+      GNUNET_CONTAINER_bloomfilter_get_raw_data (gi->bf,
+                                                 raw,
+                                                 gi->bf_size))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  *raw_data = raw;
+  *raw_data_size = gi->bf_size;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Destroy resources used by a block group.
+ *
+ * @param bg group to destroy, NULL is allowed
+ */
+static void
+bf_group_destroy_cb (struct GNUNET_BLOCK_Group *bg)
+{
+  struct BfGroupInternals *gi = bg->internal_cls;
+
+  GNUNET_CONTAINER_bloomfilter_free (gi->bf);
+  GNUNET_free (gi);
+  GNUNET_free (bg);
+}
+
+
+/**
+ * Create a new block group that filters duplicates using a Bloom filter.
+ *
+ * @param ctx block context in which the block group is created
+ * @param bf_size size of the Bloom filter
+ * @param bf_k K-value for the Bloom filter
+ * @param type block type
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+struct GNUNET_BLOCK_Group *
+GNUNET_BLOCK_GROUP_bf_create (void *cls,
+                              size_t bf_size,
+                              unsigned int bf_k,
+                              enum GNUNET_BLOCK_Type type,
+                              uint32_t nonce,
+                              const void *raw_data,
+                              size_t raw_data_size)
+{
+  struct BfGroupInternals *gi;
+  struct GNUNET_BLOCK_Group *bg;
+
+  gi = GNUNET_new (struct BfGroupInternals);
+  gi->bf = GNUNET_CONTAINER_bloomfilter_init ((bf_size != raw_data_size) ? NULL : raw_data,
+                                              bf_size,
+                                              bf_k);
+  gi->bf_mutator = nonce;
+  gi->bf_size = bf_size;
+  bg = GNUNET_new (struct GNUNET_BLOCK_Group);
+  bg->type = type;
+  bg->serialize_cb = &bf_group_serialize_cb;
+  bg->destroy_cb = &bf_group_destroy_cb;
+  bg->internal_cls = gi;
+  return bg;
+}
+
+
+/**
+ * Test if @a hc is contained in the Bloom filter of @a bg.  If so,
+ * return #GNUNET_YES.  If not, add @a hc to the Bloom filter and
+ * return #GNUNET_NO.
+ *
+ * @param bg block group to use for testing
+ * @param hc hash of element to evaluate
+ * @return #GNUNET_YES if @a hc is (likely) a duplicate
+ *         #GNUNET_NO if @a hc was definitively not in @bg (but now is)
+ */
+int
+GNUNET_BLOCK_GROUP_bf_test_and_set (struct GNUNET_BLOCK_Group *bg,
+                                    const struct GNUNET_HashCode *hc)
+{
+  struct BfGroupInternals *gi = bg->internal_cls;
+  struct GNUNET_HashCode mhash;
+
+  GNUNET_BLOCK_mingle_hash (hc,
+                            gi->bf_mutator,
+                            &mhash);
+  if (GNUNET_YES ==
+      GNUNET_CONTAINER_bloomfilter_test (gi->bf,
+                                         &mhash))
+    return GNUNET_YES;
+  GNUNET_CONTAINER_bloomfilter_add (gi->bf,
+                                    &mhash);
+  return GNUNET_NO;
+}
+
+
+/* end of bg_bf.c */
index c104f4bd158e2992ed6ba9d0a94b9114e2ea99be..d4f5462dd6e402d638227d5f1c2673a7be45da14 100644 (file)
@@ -158,6 +158,46 @@ GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
 }
 
 
+/**
+ * Serialize state of a block group.
+ *
+ * @param bg group to serialize
+ * @param[out] raw_data set to the serialized state
+ * @param[out] raw_data_size set to the number of bytes in @a raw_data
+ * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
+ *         supported, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
+                              void **raw_data,
+                              size_t *raw_data_size)
+{
+  *raw_data = NULL;
+  *raw_data_size = 0;
+  if (NULL == bg)
+    return GNUNET_NO;
+  if (NULL == bg->serialize_cb)
+    return GNUNET_NO;
+  return bg->serialize_cb (bg,
+                           raw_data,
+                           raw_data_size);
+}
+
+
+/**
+ * Destroy resources used by a block group.
+ *
+ * @param bg group to destroy, NULL is allowed
+ */
+void
+GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg)
+{
+  if (NULL == bg)
+    return;
+  bg->destroy_cb (bg);
+}
+
+
 /**
  * Find a plugin for the given type.
  *
@@ -188,6 +228,38 @@ find_plugin (struct GNUNET_BLOCK_Context *ctx,
 }
 
 
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+struct GNUNET_BLOCK_Group *
+GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
+                           enum GNUNET_BLOCK_Type type,
+                           uint32_t nonce,
+                           const void *raw_data,
+                           size_t raw_data_size)
+{
+  struct GNUNET_BLOCK_PluginFunctions *plugin;
+
+  plugin = find_plugin (ctx,
+                        type);
+  if (NULL == plugin->create_group)
+    return NULL;
+  return plugin->create_group (plugin->cls,
+                               type,
+                               nonce,
+                               raw_data,
+                               raw_data_size);
+}
+
+
 /**
  * Function called to validate a reply or a request.  For
  * request evaluation, simply pass "NULL" for the reply_block.
index 26beb300ba52644db702e1ae3ddd0f64c4a85acc..93dae9f6ef8891ab6ad30a6b679a3fcbe4ad67d4 100644 (file)
@@ -40,6 +40,7 @@ libgnunet_plugin_block_dht_la_SOURCES = \
 libgnunet_plugin_block_dht_la_LIBADD = \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/block/libgnunetblock.la \
+  $(top_builddir)/src/block/libgnunetblockgroup.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(LTLIBINTL)
 libgnunet_plugin_block_dht_la_LDFLAGS = \
index 4256a0fe64464bcd0bb0d7fb286d564558469527..4c5f122a4fd52959344e99f1220a7786660ebf6c 100644 (file)
  *        DHT (see fs block plugin)
  * @author Christian Grothoff
  */
-
 #include "platform.h"
 #include "gnunet_constants.h"
 #include "gnunet_hello_lib.h"
 #include "gnunet_block_plugin.h"
+#include "gnunet_block_group_lib.h"
 
 #define DEBUG_DHT GNUNET_EXTRA_LOGGING
 
+/**
+ * How big is the BF we use for DHT blocks?
+ */
+#define DHT_BF_SIZE 8
+
+
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+static struct GNUNET_BLOCK_Group *
+block_plugin_dht_create_group (void *cls,
+                               enum GNUNET_BLOCK_Type type,
+                               uint32_t nonce,
+                               const void *raw_data,
+                               size_t raw_data_size)
+{
+  return GNUNET_BLOCK_GROUP_bf_create (cls,
+                                       DHT_BF_SIZE,
+                                       GNUNET_CONSTANTS_BLOOMFILTER_K,
+                                       type,
+                                       nonce,
+                                       raw_data,
+                                       raw_data_size);
+}
+
 
 /**
  * Function called to validate a reply or a request.  For
@@ -182,6 +215,7 @@ libgnunet_plugin_block_dht_init (void *cls)
   api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
   api->evaluate = &block_plugin_dht_evaluate;
   api->get_key = &block_plugin_dht_get_key;
+  api->create_group = &block_plugin_dht_create_group;
   api->types = types;
   return api;
 }
index 8c6ec93ee2b76e9c0a51411faa97129935913525..e4bc9209cb24129c9ecc199e08733cc3ca5ea081 100644 (file)
@@ -96,9 +96,9 @@ block_plugin_dns_evaluate (void *cls,
     }
     if (GNUNET_OK !=
         GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD,
-                                 &ad->purpose,
-                                 &ad->signature,
-                                 &ad->peer.public_key))
+                                    &ad->purpose,
+                                    &ad->signature,
+                                    &ad->peer.public_key))
     {
       GNUNET_break_op (0);
       return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
index 75451c7f6444cbc7e162df89ca7ff5f0437b95e0..4374d45eabafb796b34ddc76fc4b88cdd69c0479 100644 (file)
@@ -219,6 +219,7 @@ gnunet_unindex_LDADD = \
 libgnunet_plugin_block_fs_la_SOURCES = \
   plugin_block_fs.c
 libgnunet_plugin_block_fs_la_LIBADD = \
+  $(top_builddir)/src/block/libgnunetblockgroup.la \
   $(top_builddir)/src/block/libgnunetblock.la \
   libgnunetfs.la \
   $(top_builddir)/src/util/libgnunetutil.la \
index 415a2e3eded20ddd76fc1ef1e3b13f350f0bd220..0387340821fb45c68c650d911bf9ffefc2c20379 100644 (file)
  * @brief blocks used for file-sharing
  * @author Christian Grothoff
  */
-
 #include "platform.h"
 #include "gnunet_block_plugin.h"
 #include "gnunet_fs_service.h"
 #include "block_fs.h"
 #include "gnunet_signatures.h"
+#include "gnunet_block_group_lib.h"
 
 
 /**
  */
 #define BLOOMFILTER_K 16
 
+/**
+ * How big is the BF we use for FS blocks?
+ */
+#define FS_BF_SIZE 8
+
+
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+static struct GNUNET_BLOCK_Group *
+block_plugin_fs_create_group (void *cls,
+                               enum GNUNET_BLOCK_Type type,
+                               uint32_t nonce,
+                               const void *raw_data,
+                               size_t raw_data_size)
+{
+  switch (type)
+  {
+  case GNUNET_BLOCK_TYPE_FS_DBLOCK:
+    return NULL;
+  case GNUNET_BLOCK_TYPE_FS_IBLOCK:
+    return NULL;
+  case GNUNET_BLOCK_TYPE_FS_UBLOCK:
+    return GNUNET_BLOCK_GROUP_bf_create (cls,
+                                         FS_BF_SIZE,
+                                         BLOOMFILTER_K,
+                                         type,
+                                         nonce,
+                                         raw_data,
+                                         raw_data_size);
+  default:
+    GNUNET_break (0);
+    return NULL;
+  }
+}
+
+
 /**
  * Function called to validate a reply or a request.  For
  * request evaluation, simply pass "NULL" for the reply_block.
@@ -214,6 +259,7 @@ libgnunet_plugin_block_fs_init (void *cls)
   api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
   api->evaluate = &block_plugin_fs_evaluate;
   api->get_key = &block_plugin_fs_get_key;
+  api->create_group = &block_plugin_fs_create_group;
   api->types = types;
   return api;
 }
index 8f27890d707fe7478de9bcf7b5b190724d16e413..d59908c0a657b0eb13e303ae111c4516d5dafb76 100644 (file)
@@ -227,6 +227,7 @@ libgnunet_plugin_block_gns_la_SOURCES = \
 libgnunet_plugin_block_gns_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/block/libgnunetblock.la \
+  $(top_builddir)/src/block/libgnunetblockgroup.la \
   $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la
 libgnunet_plugin_block_gns_la_LDFLAGS = \
   $(GN_PLUGIN_LDFLAGS)
index f0e34a04bbf85ddc69d16a90d125debc2d07c675..8d3e84042a4e7374f93078cf9c35a06eb46203b7 100644 (file)
  * @file gns/plugin_block_gns.c
  * @brief blocks used for GNS records
  * @author Martin Schanzenbach
+ * @author Christian Grothoff
  */
 
 #include "platform.h"
+#include "gnunet_block_group_lib.h"
 #include "gnunet_block_plugin.h"
 #include "gnunet_namestore_service.h"
 #include "gnunet_signatures.h"
  */
 #define BLOOMFILTER_K 16
 
+/**
+ * How big is the BF we use for GNS blocks?
+ */
+#define GNS_BF_SIZE 8
+
+
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+static struct GNUNET_BLOCK_Group *
+block_plugin_gns_create_group (void *cls,
+                               enum GNUNET_BLOCK_Type type,
+                               uint32_t nonce,
+                               const void *raw_data,
+                               size_t raw_data_size)
+{
+  return GNUNET_BLOCK_GROUP_bf_create (cls,
+                                       GNS_BF_SIZE,
+                                       BLOOMFILTER_K,
+                                       type,
+                                       nonce,
+                                       raw_data,
+                                       raw_data_size);
+}
+
+
 /**
  * Function called to validate a reply or a request.  For
  * request evaluation, simply pass "NULL" for the reply_block.
@@ -141,9 +177,11 @@ block_plugin_gns_evaluate (void *cls,
  *         (or if extracting a key from a block of this type does not work)
  */
 static int
-block_plugin_gns_get_key (void *cls, enum GNUNET_BLOCK_Type type,
-                         const void *reply_block, size_t reply_block_size,
-                         struct GNUNET_HashCode *key)
+block_plugin_gns_get_key (void *cls,
+                          enum GNUNET_BLOCK_Type type,
+                          const void *reply_block,
+                          size_t reply_block_size,
+                          struct GNUNET_HashCode *key)
 {
   const struct GNUNET_GNSRECORD_Block *block;
 
@@ -178,6 +216,7 @@ libgnunet_plugin_block_gns_init (void *cls)
   api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
   api->evaluate = &block_plugin_gns_evaluate;
   api->get_key = &block_plugin_gns_get_key;
+  api->create_group = &block_plugin_gns_create_group;
   api->types = types;
   return api;
 }
diff --git a/src/include/gnunet_block_group_lib.h b/src/include/gnunet_block_group_lib.h
new file mode 100644 (file)
index 0000000..5fa14ce
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2010 GNUnet e.V.
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @author Christian Grothoff
+ *
+ * @file
+ * Library for creating block groups (to be used by block plugins)
+ *
+ * @defgroup block  Block group library
+ * Library for data group management
+ * @{
+ */
+#ifndef GNUNET_BLOCK_GROUP_LIB_H
+#define GNUNET_BLOCK_GROUP_LIB_H
+
+#include "gnunet_util_lib.h"
+#include "gnunet_block_lib.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+
+/**
+ * Create a new block group that filters duplicates using a Bloom filter.
+ *
+ * @param ctx block context in which the block group is created
+ * @param bf_size size of the Bloom filter
+ * @param bf_k K-value for the Bloom filter
+ * @param type block type
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+struct GNUNET_BLOCK_Group *
+GNUNET_BLOCK_GROUP_bf_create (void *cls,
+                              size_t bf_size,
+                              unsigned int bf_k,
+                              enum GNUNET_BLOCK_Type type,
+                              uint32_t nonce,
+                              const void *raw_data,
+                              size_t raw_data_size);
+
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* ifndef GNUNET_BLOCK_GROUP_LIB_H */
+#endif
+
+/** @} */  /* end of group */
+
+/* end of gnunet_block_group_lib.h */
index b21b3496b608ba4f28a734304f1a83badc04cf3c..0f0fee499779f014c6b597e5ac9b0ac1dbe0bc73 100644 (file)
@@ -229,6 +229,57 @@ void
 GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx);
 
 
+/**
+ * Handle for a group of elements that will be evaluated together.
+ * They must all be of the same type.  A block group allows the
+ * plugin to keep some state across individual evaluations.
+ */
+struct GNUNET_BLOCK_Group;
+
+
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+struct GNUNET_BLOCK_Group *
+GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx,
+                           enum GNUNET_BLOCK_Type type,
+                           uint32_t nonce,
+                           const void *raw_data,
+                           size_t raw_data_size);
+
+
+/**
+ * Serialize state of a block group.
+ *
+ * @param bg group to serialize
+ * @param[out] raw_data set to the serialized state
+ * @param[out] raw_data_size set to the number of bytes in @a raw_data
+ * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
+ *         supported, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg,
+                              void **raw_data,
+                              size_t *raw_data_size);
+
+
+/**
+ * Destroy resources used by a block group.
+ *
+ * @param bg group to destroy, NULL is allowed
+ */
+void
+GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg);
+
+
 /**
  * Function called to validate a reply or a request.  For
  * request evaluation, simply pass "NULL" for the @a reply_block.
index 5c320457eb8445bacd532f277340e2a55f9a9dd6..d7454b5d586c2371ed7bf3d8abc8f883ca5082ef 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2010,2013 GNUnet e.V.
+     Copyright (C) 2010,2013,2017 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 #include "gnunet_block_lib.h"
 
 
+/**
+ * Serialize state of a block group.
+ *
+ * @param bg group to serialize
+ * @param[out] raw_data set to the serialized state
+ * @param[out] raw_data_size set to the number of bytes in @a raw_data
+ * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not
+ *         supported, #GNUNET_SYSERR on error
+ */
+typedef int
+(*GNUNET_BLOCK_GroupSerializeFunction)(struct GNUNET_BLOCK_Group *bg,
+                                       void **raw_data,
+                                       size_t *raw_data_size);
+
+
+/**
+ * Destroy resources used by a block group.
+ *
+ * @param bg group to destroy, NULL is allowed
+ */
+typedef void
+(*GNUNET_BLOCK_GroupDestroyFunction)(struct GNUNET_BLOCK_Group *bg);
+
+
+/**
+ * Block group data.  The plugin must initialize the callbacks
+ * and can use the @e internal_cls as it likes.
+ */
+struct GNUNET_BLOCK_Group
+{
+
+  /**
+   * Context owning the block group. Set by the main block library.
+   */
+  struct GNUENT_BLOCK_Context *ctx;
+
+  /**
+   * Type for the block group.  Set by the main block library.
+   */
+  enum GNUNET_BLOCK_Type type;
+
+  /**
+   * Serialize the block group data, can be NULL if
+   * not supported.
+   */
+  GNUNET_BLOCK_GroupSerializeFunction serialize_cb;
+
+  /**
+   * Function to call to destroy the block group.
+   * Must not be NULL.
+   */
+  GNUNET_BLOCK_GroupDestroyFunction destroy_cb;
+
+  /**
+   * Internal data structure of the plugin.
+   */
+  void *internal_cls;
+
+};
+
+
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+typedef struct GNUNET_BLOCK_Group *
+(*GNUNET_BLOCK_GroupCreateFunction)(void *cls,
+                                    enum GNUNET_BLOCK_Type type,
+                                    uint32_t nonce,
+                                    const void *raw_data,
+                                    size_t raw_data_size);
+
+
 /**
  * Function called to validate a reply or a request.  For
  * request evaluation, simply pass "NULL" for the @a reply_block.
@@ -121,6 +201,11 @@ struct GNUNET_BLOCK_PluginFunctions
    */
   GNUNET_BLOCK_GetKeyFunction get_key;
 
+  /**
+   * Create a block group to process a bunch of blocks in a shared
+   * context (i.e. to detect duplicates).
+   */
+  GNUNET_BLOCK_GroupCreateFunction create_group;
 };
 
 #endif
index 70f612485a012566c1c9eec304708922cf693b91..80997db40faf3160ae1b874c07eecdd22e4786d6 100644 (file)
@@ -80,6 +80,7 @@ libgnunet_plugin_block_regex_la_SOURCES = \
 libgnunet_plugin_block_regex_la_LIBADD = \
  libgnunetregexblock.la \
  $(top_builddir)/src/block/libgnunetblock.la \
+ $(top_builddir)/src/block/libgnunetblockgroup.la \
  $(top_builddir)/src/util/libgnunetutil.la
 libgnunet_plugin_block_regex_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
index 36926c25d560b4c5e12b2fbca216ad09acd44a81..11511a71b3b5d1d7a509692b6ab6da2c89ad878c 100644 (file)
  * @brief blocks used for regex storage and search
  * @author Bartlomiej Polot
  */
-
 #include "platform.h"
 #include "gnunet_block_plugin.h"
+#include "gnunet_block_group_lib.h"
 #include "block_regex.h"
 #include "regex_block_lib.h"
 #include "gnunet_constants.h"
 #include "gnunet_signatures.h"
 
 
+/**
+ * How big is the BF we use for REGEX blocks?
+ */
+#define REGEX_BF_SIZE 8
+
+
+/**
+ * Create a new block group.
+ *
+ * @param ctx block context in which the block group is created
+ * @param type type of the block for which we are creating the group
+ * @param nonce random value used to seed the group creation
+ * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
+ * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
+ * @return block group handle, NULL if block groups are not supported
+ *         by this @a type of block (this is not an error)
+ */
+static struct GNUNET_BLOCK_Group *
+block_plugin_regex_create_group (void *cls,
+                                 enum GNUNET_BLOCK_Type type,
+                                 uint32_t nonce,
+                                 const void *raw_data,
+                                 size_t raw_data_size)
+{
+  return GNUNET_BLOCK_GROUP_bf_create (cls,
+                                       REGEX_BF_SIZE,
+                                       GNUNET_CONSTANTS_BLOOMFILTER_K,
+                                       type,
+                                       nonce,
+                                       raw_data,
+                                       raw_data_size);
+}
+
+
 /**
  * Function called to validate a reply or a request of type
  * #GNUNET_BLOCK_TYPE_REGEX.
@@ -346,6 +380,7 @@ libgnunet_plugin_block_regex_init (void *cls)
   api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
   api->evaluate = &block_plugin_regex_evaluate;
   api->get_key = &block_plugin_regex_get_key;
+  api->create_group = &block_plugin_regex_create_group;
   api->types = types;
   return api;
 }