guix-env: some update.
[oweals/gnunet.git] / src / set / gnunet-service-set_union_strata_estimator.c
index 2288e25f580e4678ce3035b7302a4b36e9769353..e3d6bfaec702369ea089f3b6391d4ef83f51506d 100644 (file)
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      (C) 2012 Christian Grothoff (and other contributing authors)
+      Copyright (C) 2012 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
 
       You should have received a copy of the GNU General Public License
       along with GNUnet; see the file COPYING.  If not, write to the
-      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-      Boston, MA 02111-1307, USA.
+      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+      Boston, MA 02110-1301, USA.
 */
 /**
  * @file set/gnunet-service-set_union_strata_estimator.c
  * @brief invertible bloom filter
  * @author Florian Dold
+ * @author Christian Grothoff
  */
-
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "ibf.h"
 #include "gnunet-service-set_union_strata_estimator.h"
 
 
+/**
+ * Should we try compressing the strata estimator? This will
+ * break compatibility with the 0.10.1-network.
+ */
+#define FAIL_10_1_COMPATIBILTIY 1
+
+
 /**
  * Write the given strata estimator to the buffer.
  *
  * @param se strata estimator to serialize
- * @param buf buffer to write to, must be of appropriate size
+ * @param[out] buf buffer to write to, must be of appropriate size
+ * @return number of bytes written to @a buf
  */
-void
-strata_estimator_write (const struct StrataEstimator *se, void *buf)
+size_t
+strata_estimator_write (const struct StrataEstimator *se,
+                        void *buf)
 {
-  int i;
+  char *sbuf = buf;
+  unsigned int i;
+  size_t osize;
 
   GNUNET_assert (NULL != se);
   for (i = 0; i < se->strata_count; i++)
   {
-    ibf_write_slice (se->strata[i], 0, se->ibf_size, buf);
-    buf += se->ibf_size * IBF_BUCKET_SIZE;
+    ibf_write_slice (se->strata[i],
+                     0,
+                     se->ibf_size,
+                     &sbuf[se->ibf_size * IBF_BUCKET_SIZE * i]);
   }
+  osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
+#if FAIL_10_1_COMPATIBILTIY
+  {
+    char *cbuf;
+    size_t nsize;
+
+    if (GNUNET_YES ==
+        GNUNET_try_compression (buf,
+                                osize,
+                                &cbuf,
+                                &nsize))
+    {
+      GNUNET_memcpy (buf, cbuf, nsize);
+      osize = nsize;
+      GNUNET_free (cbuf);
+    }
+  }
+#endif
+  return osize;
 }
 
 
@@ -54,17 +86,51 @@ strata_estimator_write (const struct StrataEstimator *se, void *buf)
  * estimator.  The strata estimator must already be allocated.
  *
  * @param buf buffer to read from
- * @param se strata estimator to write to
+ * @param buf_len number of bytes in @a buf
+ * @param is_compressed is the data compressed?
+ * @param[out] se strata estimator to write to
+ * @return #GNUNET_OK on success
  */
-void
-strata_estimator_read (const void *buf, struct StrataEstimator *se)
+int
+strata_estimator_read (const void *buf,
+                       size_t buf_len,
+                       int is_compressed,
+                       struct StrataEstimator *se)
 {
-  int i;
+  unsigned int i;
+  size_t osize;
+  char *dbuf;
+
+  dbuf = NULL;
+  if (GNUNET_YES == is_compressed)
+  {
+    osize = se->ibf_size * IBF_BUCKET_SIZE * se->strata_count;
+    dbuf = GNUNET_decompress (buf,
+                              buf_len,
+                              osize);
+    if (NULL == dbuf)
+    {
+      GNUNET_break_op (0); /* bad compressed input data */
+      return GNUNET_SYSERR;
+    }
+    buf = dbuf;
+    buf_len = osize;
+  }
+
+  if (buf_len != se->strata_count * se->ibf_size * IBF_BUCKET_SIZE)
+  {
+    GNUNET_break (0); /* very odd error */
+    GNUNET_free_non_null (dbuf);
+    return GNUNET_SYSERR;
+  }
+
   for (i = 0; i < se->strata_count; i++)
   {
     ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]);
     buf += se->ibf_size * IBF_BUCKET_SIZE;
   }
+  GNUNET_free_non_null (dbuf);
+  return GNUNET_OK;
 }
 
 
@@ -75,10 +141,12 @@ strata_estimator_read (const void *buf, struct StrataEstimator *se)
  * @param key key to add
  */
 void
-strata_estimator_insert (struct StrataEstimator *se, struct IBF_Key key)
+strata_estimator_insert (struct StrataEstimator *se,
+                         struct IBF_Key key)
 {
   uint64_t v;
-  int i;
+  unsigned int i;
+
   v = key.key_val;
   /* count trailing '1'-bits of v */
   for (i = 0; v & 1; v>>=1, i++)
@@ -94,10 +162,12 @@ strata_estimator_insert (struct StrataEstimator *se, struct IBF_Key key)
  * @param key key to remove
  */
 void
-strata_estimator_remove (struct StrataEstimator *se, struct IBF_Key key)
+strata_estimator_remove (struct StrataEstimator *se,
+                         struct IBF_Key key)
 {
   uint64_t v;
-  int i;
+  unsigned int i;
+
   v = key.key_val;
   /* count trailing '1'-bits of v */
   for (i = 0; v & 1; v>>=1, i++)
@@ -112,22 +182,35 @@ strata_estimator_remove (struct StrataEstimator *se, struct IBF_Key key)
  * @param strata_count number of stratas, that is, number of ibfs in the estimator
  * @param ibf_size size of each ibf stratum
  * @param ibf_hashnum hashnum parameter of each ibf
- * @return a freshly allocated, empty strata estimator
+ * @return a freshly allocated, empty strata estimator, NULL on error
  */
 struct StrataEstimator *
-strata_estimator_create (unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum)
+strata_estimator_create (unsigned int strata_count,
+                         uint32_t ibf_size,
+                         uint8_t ibf_hashnum)
 {
   struct StrataEstimator *se;
-  int i;
-
-  /* fixme: allocate everything in one chunk */
+  unsigned int i;
+  unsigned int j;
 
   se = GNUNET_new (struct StrataEstimator);
   se->strata_count = strata_count;
   se->ibf_size = ibf_size;
-  se->strata = GNUNET_malloc (sizeof (struct InvertibleBloomFilter *) * strata_count);
+  se->strata = GNUNET_new_array (strata_count,
+                                 struct InvertibleBloomFilter *);
   for (i = 0; i < strata_count; i++)
+  {
     se->strata[i] = ibf_create (ibf_size, ibf_hashnum);
+    if (NULL == se->strata[i])
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to allocate memory for strata estimator\n");
+      for (j = 0; j < i; j++)
+        ibf_destroy (se->strata[i]);
+      GNUNET_free (se);
+      return NULL;
+    }
+  }
   return se;
 }
 
@@ -146,7 +229,7 @@ strata_estimator_difference (const struct StrataEstimator *se1,
                              const struct StrataEstimator *se2)
 {
   int i;
-  int count;
+  unsigned int count;
 
   GNUNET_assert (se1->strata_count == se2->strata_count);
   count = 0;
@@ -155,6 +238,7 @@ strata_estimator_difference (const struct StrataEstimator *se1,
     struct InvertibleBloomFilter *diff;
     /* number of keys decoded from the ibf */
     int ibf_count;
+
     /* FIXME: implement this without always allocating new IBFs */
     diff = ibf_dup (se1->strata[i]);
     ibf_subtract (diff, se2->strata[i]);
@@ -191,12 +275,13 @@ struct StrataEstimator *
 strata_estimator_dup (struct StrataEstimator *se)
 {
   struct StrataEstimator *c;
-  int i;
+  unsigned int i;
 
   c = GNUNET_new (struct StrataEstimator);
   c->strata_count = se->strata_count;
   c->ibf_size = se->ibf_size;
-  c->strata = GNUNET_malloc (sizeof (struct InvertibleBloomFilter *) * se->strata_count);
+  c->strata = GNUNET_new_array (se->strata_count,
+                                struct InvertibleBloomFilter *);
   for (i = 0; i < se->strata_count; i++)
     c->strata[i] = ibf_dup (se->strata[i]);
   return c;
@@ -211,11 +296,10 @@ strata_estimator_dup (struct StrataEstimator *se)
 void
 strata_estimator_destroy (struct StrataEstimator *se)
 {
-  int i;
+  unsigned int i;
 
   for (i = 0; i < se->strata_count; i++)
     ibf_destroy (se->strata[i]);
   GNUNET_free (se->strata);
   GNUNET_free (se);
 }
-