-remove trailing whitespace
[oweals/gnunet.git] / src / dht / gnunet-service-dht_routing.c
index c1dca4e2155533e717e027de7388778363936008..e2995bd49aaad7cd3e6d0d37c6fa2e433f2d3bc6 100644 (file)
@@ -153,11 +153,11 @@ struct ProcessContext
 /**
  * Forward the result to the given peer if it matches the request.
  *
- * @param cls the 'struct ProcessContext' with the result
+ * @param cls the `struct ProcessContext` with the result
  * @param key the query
- * @param value the 'struct RecentRequest' with the request
- * @return GNUNET_OK (continue to iterate),
- *         GNUNET_SYSERR if the result is malformed or type unsupported
+ * @param value the `struct RecentRequest` with the request
+ * @return #GNUNET_OK (continue to iterate),
+ *         #GNUNET_SYSERR if the result is malformed or type unsupported
  */
 static int
 process (void *cls, const struct GNUNET_HashCode * key, void *value)
@@ -226,6 +226,12 @@ process (void *cls, const struct GNUNET_HashCode * key, void *value)
                               ("# Invalid REPLIES matched against routing table"),
                               1, GNUNET_NO);
     return GNUNET_SYSERR;
+  case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
+    GNUNET_STATISTICS_update (GDS_stats,
+                              gettext_noop
+                              ("# Irrelevant REPLIES matched against routing table"),
+                              1, GNUNET_NO);
+    return GNUNET_OK;
   case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
     GNUNET_break (0);
     return GNUNET_OK;
@@ -258,7 +264,7 @@ process (void *cls, const struct GNUNET_HashCode * key, void *value)
  * @param key key for the content
  * @param put_path_length number of entries in put_path
  * @param put_path peers the original PUT traversed (if tracked)
- * @param get_path_length number of entries in put_path
+ * @param get_path_length number of entries in get_path
  * @param get_path peers this reply has traversed so far (if tracked)
  * @param data payload of the reply
  * @param data_size number of bytes in data
@@ -289,7 +295,7 @@ GDS_ROUTING_process (enum GNUNET_BLOCK_Type type,
        reply as request-validation (but we need response-validation).
        So we set 'data' to a 0-byte non-NULL value just to be sure */
     GNUNET_break (0 == data_size);
-    data_size = 0;
+    pc.data_size = 0;
     pc.data = ""; /* something not null */
   }
   GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &process, &pc);
@@ -315,13 +321,54 @@ expire_oldest_entry ()
   GNUNET_CONTAINER_heap_remove_node (recent_req->heap_node);
   GNUNET_CONTAINER_bloomfilter_free (recent_req->reply_bf);
   GNUNET_assert (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (recent_map, 
-                                                      &recent_req->key, 
+                GNUNET_CONTAINER_multihashmap_remove (recent_map,
+                                                      &recent_req->key,
                                                       recent_req));
   GNUNET_free (recent_req);
 }
 
 
+/**
+ * Try to combine multiple recent requests for the same value
+ * (if they come from the same peer).
+ *
+ * @param cls the new 'struct RecentRequest' (to discard upon successful combination)
+ * @param key the query
+ * @param value the existing 'struct RecentRequest' (to update upon successful combination)
+ * @return GNUNET_OK (continue to iterate),
+ *         GNUNET_SYSERR if the request was successfully combined
+ */
+static int
+try_combine_recent (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+  struct RecentRequest *in = cls;
+  struct RecentRequest *rr = value;
+
+  if ( (0 != memcmp (&in->peer,
+                    &rr->peer,
+                    sizeof (struct GNUNET_PeerIdentity))) ||
+       (in->type != rr->type) ||
+       (in->xquery_size != rr->xquery_size) ||
+       (0 != memcmp (in->xquery,
+                    rr->xquery,
+                    in->xquery_size)) )
+    return GNUNET_OK;
+  if (in->reply_bf_mutator != rr->reply_bf_mutator)
+  {
+    rr->reply_bf_mutator = in->reply_bf_mutator;
+    GNUNET_CONTAINER_bloomfilter_free (rr->reply_bf);
+    rr->reply_bf = in->reply_bf;
+  }
+  else
+  {
+    GNUNET_CONTAINER_bloomfilter_or2 (rr->reply_bf,
+                                     in->reply_bf);
+    GNUNET_CONTAINER_bloomfilter_free (in->reply_bf);
+  }
+  GNUNET_free (in);
+  return GNUNET_SYSERR;
+}
+
 
 /**
  * Add a new entry to our routing table.
@@ -331,10 +378,10 @@ expire_oldest_entry ()
  * @param options options for processing
  * @param key key for the content
  * @param xquery extended query
- * @param xquery_size number of bytes in xquery
+ * @param xquery_size number of bytes in @a xquery
  * @param reply_bf bloomfilter to filter duplicates
- * @param reply_bf_mutator mutator for reply_bf
-*/
+ * @param reply_bf_mutator mutator for @a reply_bf
+ */
 void
 GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
                  enum GNUNET_BLOCK_Type type,
@@ -354,15 +401,26 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
   recent_req = GNUNET_malloc (sizeof (struct RecentRequest) + xquery_size);
   recent_req->peer = *sender;
   recent_req->key = *key;
-  recent_req->heap_node =
-      GNUNET_CONTAINER_heap_insert (recent_heap, recent_req,
-                                    GNUNET_TIME_absolute_get ().abs_value);
   recent_req->reply_bf = GNUNET_CONTAINER_bloomfilter_copy (reply_bf);
   recent_req->type = type;
   recent_req->options = options;
   recent_req->xquery = &recent_req[1];
+  memcpy (&recent_req[1], xquery, xquery_size);
   recent_req->xquery_size = xquery_size;
   recent_req->reply_bf_mutator = reply_bf_mutator;
+  if (GNUNET_SYSERR ==
+      GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key,
+                                                 &try_combine_recent, recent_req))
+  {
+    GNUNET_STATISTICS_update (GDS_stats,
+                              gettext_noop
+                              ("# DHT requests combined"),
+                              1, GNUNET_NO);
+    return;
+  }
+  recent_req->heap_node =
+      GNUNET_CONTAINER_heap_insert (recent_heap, recent_req,
+                                    GNUNET_TIME_absolute_get ().abs_value_us);
   GNUNET_CONTAINER_multihashmap_put (recent_map, key, recent_req,
                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
 
@@ -377,7 +435,7 @@ void
 GDS_ROUTING_init ()
 {
   recent_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
-  recent_map = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT * 4 / 3);
+  recent_map = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT * 4 / 3, GNUNET_NO);
 }