- fix
[oweals/gnunet.git] / src / regex / regex_dht.c
index ce9d4e2a1637d3130459ea4a5ad4026b69fa85df..f9e25c274d72d6aef8a8700137db874f7bcf0adc 100644 (file)
 #include "gnunet_dht_service.h"
 #include "gnunet_statistics_service.h"
 
+#define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__)
+
+/* FIXME: OPTION (API, CONFIG) */
 #define DHT_REPLICATION 5
 #define DHT_TTL         GNUNET_TIME_UNIT_HOURS
+#define DEBUG_DHT       GNUNET_YES
+
+#if DEBUG_DHT
+#define DHT_OPT         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | GNUNET_DHT_RO_RECORD_ROUTE
+#else
+#define DHT_OPT         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
+#endif
 
 struct GNUNET_REGEX_announce_handle
 {
@@ -82,31 +92,25 @@ regex_iterator (void *cls,
   struct GNUNET_REGEX_announce_handle *h = cls;
   struct RegexBlock *block;
   struct RegexEdge *block_edge;
-  enum GNUNET_DHT_RouteOption opt;
   size_t size;
   size_t len;
   unsigned int i;
   unsigned int offset;
   char *aux;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  regex dht put for state %s\n",
-              GNUNET_h2s (key));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "   proof: %s\n",
-              proof);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "   num edges: %u\n",
-              num_edges);
-
-  opt = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "  regex dht put for state %s\n",
+       GNUNET_h2s (key));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "   proof: %s\n", proof);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "   num edges: %u\n", num_edges);
+
   if (GNUNET_YES == accepting)
   {
     struct RegexAccept block;
 
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "   state %s is accepting, putting own id\n",
-                GNUNET_h2s(key));
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "   state %s is accepting, putting own id\n",
+         GNUNET_h2s(key));
     size = sizeof (block);
     block.key = *key;
     block.id = *(h->id);
@@ -116,13 +120,13 @@ regex_iterator (void *cls,
                               sizeof (block), GNUNET_NO);
     (void)
     GNUNET_DHT_put (h->dht, key,
-                    2, /* FIXME option */
-                    opt /* | GNUNET_DHT_RO_RECORD_ROUTE*/,
+                    DHT_REPLICATION,
+                    DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE,
                     GNUNET_BLOCK_TYPE_REGEX_ACCEPT,
                     size,
                     (char *) &block,
-                    GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: expiration time should be option */
-                    GNUNET_TIME_UNIT_HOURS, /* FIXME option */
+                    GNUNET_TIME_relative_to_absolute (DHT_TTL),
+                    DHT_TTL,
                     NULL, NULL);
   }
   len = strlen(proof);
@@ -144,10 +148,8 @@ regex_iterator (void *cls,
    */
   for (i = 0; i < num_edges; i++)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "    edge %s towards %s\n",
-                edges[i].label,
-                GNUNET_h2s(&edges[i].destination));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "    edge %s towards %s\n",
+         edges[i].label, GNUNET_h2s(&edges[i].destination));
 
     /* aux points at the end of the last block */
     len = strlen (edges[i].label);
@@ -164,14 +166,14 @@ regex_iterator (void *cls,
     aux = &aux[len];
   }
   (void)
-  GNUNET_DHT_put(h->dht, key,
-                 DHT_REPLICATION, /* FIXME OPTION */
-                 opt,
-                 GNUNET_BLOCK_TYPE_REGEX, size,
-                 (char *) block,
-                 GNUNET_TIME_relative_to_absolute (DHT_TTL), /* FIXME: this should be an option */
-                 DHT_TTL,
-                 NULL, NULL);
+  GNUNET_DHT_put (h->dht, key,
+                  DHT_REPLICATION,
+                  DHT_OPT,
+                  GNUNET_BLOCK_TYPE_REGEX, size,
+                  (char *) block,
+                  GNUNET_TIME_relative_to_absolute (DHT_TTL),
+                  DHT_TTL,
+                  NULL, NULL);
   GNUNET_STATISTICS_update (h->stats, "# regex blocks stored",
                             1, GNUNET_NO);
   GNUNET_STATISTICS_update (h->stats, "# regex block bytes stored",
@@ -190,7 +192,7 @@ GNUNET_REGEX_announce (struct GNUNET_DHT_Handle *dht,
 {
   struct GNUNET_REGEX_announce_handle *h;
 
-  GNUNET_assert (NULL == dht);
+  GNUNET_assert (NULL != dht);
   h = GNUNET_malloc (sizeof (struct GNUNET_REGEX_announce_handle));
   h->regex = regex;
   h->dht = dht;
@@ -206,6 +208,7 @@ GNUNET_REGEX_announce (struct GNUNET_DHT_Handle *dht,
 void
 GNUNET_REGEX_reannounce (struct GNUNET_REGEX_announce_handle *h)
 {
+  LOG (GNUNET_ERROR_TYPE_INFO, "GNUNET_REGEX_reannounce: %s\n", h->regex);
   GNUNET_REGEX_iterate_all_edges (h->dfa, &regex_iterator, h);
 }
 
@@ -348,8 +351,9 @@ dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp,
   struct RegexSearchContext *ctx = cls;
   struct GNUNET_REGEX_search_handle *info = ctx->info;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for %s\n", info->description);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n");
+  LOG (GNUNET_ERROR_TYPE_INFO, "   accept for %s (key %s)\n",
+       info->description, GNUNET_h2s(key));
 
   GNUNET_STATISTICS_update (info->stats, "# regex accepting blocks found",
                             1, GNUNET_NO);
@@ -377,13 +381,13 @@ regex_find_path (const struct GNUNET_HashCode *key,
 {
   struct GNUNET_DHT_GetHandle *get_h;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n");
+  LOG (GNUNET_ERROR_TYPE_INFO, "   find accept for %s\n", GNUNET_h2s (key));
   get_h = GNUNET_DHT_get_start (ctx->info->dht,    /* handle */
                                 GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */
                                 key,     /* key to search */
                                 DHT_REPLICATION, /* replication level */
-                                GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE |
-                                GNUNET_DHT_RO_RECORD_ROUTE,
+                                DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE,
                                 NULL,       /* xquery */ // FIXME BLOOMFILTER
                                 0,     /* xquery bits */ // FIXME BLOOMFILTER SIZE
                                 &dht_get_string_accept_handler, ctx);
@@ -427,17 +431,33 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp,
   struct GNUNET_REGEX_search_handle *info = ctx->info;
   void *copy;
   size_t len;
+  char *datastore;
+
+#if DEBUG_DHT
+  if (NULL != put_path && 0 != put_path_length)
+  {
+    datastore = GNUNET_strdup (GNUNET_i2s (&put_path[put_path_length - 1]));
+  }
+  else
+  {
+    GNUNET_asprintf (&datastore, "?? %u/%u", put_path_length, get_path_length);
+  }
+#else
+  datastore = GNUNET_strdup ("N/A");
+#endif
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "DHT GET STRING RETURNED RESULTS\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "  key: %s\n", GNUNET_h2s (key));
+  LOG (GNUNET_ERROR_TYPE_INFO, " DHT GET result for %s (%s) at %s\n",
+       GNUNET_h2s (key), ctx->info->description, datastore);
+  GNUNET_free (datastore);
 
   copy = GNUNET_malloc (size);
   memcpy (copy, data, size);
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONTAINER_multihashmap_put(info->dht_get_results, key, copy,
-                                                  GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
+  GNUNET_break (
+    GNUNET_OK ==
+    GNUNET_CONTAINER_multihashmap_put (info->dht_get_results,
+                                       &((struct RegexBlock *)copy)->key, copy,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)
+               );
   len = ntohl (block->n_proof);
   {
     char proof[len + 1];
@@ -455,11 +475,11 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp,
   {
     if (GNUNET_YES == ntohl (block->accepting))
     {
-      regex_find_path(key, ctx);
+      regex_find_path (key, ctx);
     }
     else
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  block not accepting!\n");
+      LOG (GNUNET_ERROR_TYPE_INFO, "  block not accepting!\n");
       // FIXME REGEX this block not successful, wait for more? start timeout?
     }
     return;
@@ -474,11 +494,10 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp,
 /**
  * Iterator over found existing mesh regex blocks that match an ongoing search.
  *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to iterate,
- *         GNUNET_NO if not.
+ * @param cls Closure (current context)-
+ * @param key Current key code (key for cached block).
+ * @param value Value in the hash map (cached RegexBlock).
+ * @return GNUNET_YES: we should always continue to iterate.
  */
 static int
 regex_result_iterator (void *cls,
@@ -491,18 +510,15 @@ regex_result_iterator (void *cls,
   if (GNUNET_YES == ntohl(block->accepting) &&
       ctx->position == strlen (ctx->info->description))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Found accepting known block\n");
+    LOG (GNUNET_ERROR_TYPE_INFO, " * Found accepting known block\n");
     regex_find_path (key, ctx);
     return GNUNET_YES; // We found an accept state!
   }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n",
-                ctx->position, strlen(ctx->info->description),
-                ntohl(block->accepting));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n",
+       ctx->position, strlen(ctx->info->description),
+       ntohl(block->accepting));
 
-  }
-  regex_next_edge(block, SIZE_MAX, ctx);
+  regex_next_edge (block, SIZE_MAX, ctx);
 
   GNUNET_STATISTICS_update (ctx->info->stats, "# regex mesh blocks iterated",
                             1, GNUNET_NO);
@@ -535,39 +551,39 @@ regex_edge_iterator (void *cls,
   GNUNET_STATISTICS_update (info->stats, "# regex edges iterated",
                             1, GNUNET_NO);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*    Start of regex edge iterator\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     descr : %s\n", info->description);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     posit : %u\n", ctx->position);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*    Start of regex edge iterator\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     descr : %s\n", info->description);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     posit : %u\n", ctx->position);
   current = &info->description[ctx->position];
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     currt : %s\n", current);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     currt : %s\n", current);
   current_len = strlen (info->description) - ctx->position;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     ctlen : %u\n", current_len);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     tklen : %u\n", len);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     token : %.*s\n", len, token);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     nextk : %s\n", GNUNET_h2s(key));
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     ctlen : %u\n", current_len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     tklen : %u\n", len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     token : %.*s\n", len, token);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*     nextk : %s\n", GNUNET_h2s(key));
   if (len > current_len)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     Token too long, END\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*     Token too long, END\n");
     return GNUNET_YES; // Token too long, wont match
   }
   if (0 != strncmp (current, token, len))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     Token doesn't match, END\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*     Token doesn't match, END\n");
     return GNUNET_YES; // Token doesn't match
   }
 
   if (len > ctx->longest_match)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     Token is longer, KEEP\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*     Token is longer, KEEP\n");
     ctx->longest_match = len;
     ctx->hash = *key;
   }
   else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     Token is not longer, IGNORE\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*     Token is not longer, IGNORE\n");
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*    End of regex edge iterator\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "*    End of regex edge iterator\n");
   return GNUNET_YES;
 }
 
@@ -589,6 +605,7 @@ regex_next_edge (const struct RegexBlock *block,
   struct RegexSearchContext *new_ctx;
   struct GNUNET_REGEX_search_handle *info = ctx->info;
   struct GNUNET_DHT_GetHandle *get_h;
+  struct GNUNET_HashCode *hash;
   const char *rest;
   int result;
 
@@ -601,8 +618,12 @@ regex_next_edge (const struct RegexBlock *block,
 
   /* Did anything match? */
   if (0 == ctx->longest_match)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  no match in block\n");
     return;
+  }
 
+  hash = &ctx->hash;
   new_ctx = GNUNET_malloc (sizeof (struct RegexSearchContext));
   new_ctx->info = info;
   new_ctx->position = ctx->position + ctx->longest_match;
@@ -610,28 +631,29 @@ regex_next_edge (const struct RegexBlock *block,
 
   /* Check whether we already have a DHT GET running for it */
   if (GNUNET_YES ==
-      GNUNET_CONTAINER_multihashmap_contains(info->dht_get_handles, &ctx->hash))
+      GNUNET_CONTAINER_multihashmap_contains (info->dht_get_handles, hash))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     GET running, END\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "*     GET for %s running, END\n",
+         GNUNET_h2s (hash));
     GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results,
-                                                &ctx->hash,
+                                                hash,
                                                 &regex_result_iterator,
                                                 new_ctx);
-    // FIXME: "leaks" new_ctx? avoid keeping it around?
-    return; // We are already looking for it
+    return; /* We are already looking for it */
   }
 
   GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed",
                             1, GNUNET_NO);
 
   /* Start search in DHT */
+  LOG (GNUNET_ERROR_TYPE_INFO, "   looking for %s\n", GNUNET_h2s (hash));
   rest = &new_ctx->info->description[new_ctx->position];
   get_h = 
       GNUNET_DHT_get_start (info->dht,    /* handle */
                             GNUNET_BLOCK_TYPE_REGEX, /* type */
-                            &ctx->hash,     /* key to search */
+                            hash,     /* key to search */
                             DHT_REPLICATION, /* replication level */
-                            GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
+                            DHT_OPT,
                             rest, /* xquery */
                             // FIXME add BLOOMFILTER to exclude filtered peers
                             strlen(rest) + 1,     /* xquery bits */
@@ -639,7 +661,7 @@ regex_next_edge (const struct RegexBlock *block,
                             &dht_get_string_handler, new_ctx);
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles,
-                                        &ctx->hash,
+                                        hash,
                                         get_h,
                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
   {
@@ -657,17 +679,54 @@ GNUNET_REGEX_search (struct GNUNET_DHT_Handle *dht,
                      struct GNUNET_STATISTICS_Handle *stats)
 {
   struct GNUNET_REGEX_search_handle *h;
+  struct GNUNET_DHT_GetHandle *get_h;
+  struct RegexSearchContext *ctx;
+  struct GNUNET_HashCode key;
+  size_t size;
+  size_t len;
 
-  GNUNET_assert (NULL == dht);
+  /* Initialize handle */
+  LOG (GNUNET_ERROR_TYPE_INFO, "GNUNET_REGEX_search: %s\n", string);
+  GNUNET_assert (NULL != dht);
+  GNUNET_assert (NULL != callback);
   h = GNUNET_malloc (sizeof (struct GNUNET_REGEX_search_handle));
   h->dht = dht;
   h->description = GNUNET_strdup (string);
   h->callback = callback;
   h->callback_cls = callback_cls;
   h->stats = stats;
-  
-  h->dht_get_handles = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
+  h->dht_get_handles = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
   h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
+
+  /* Initialize context */
+  len = strlen (string);
+  size = GNUNET_REGEX_get_first_key (string, len, &key);
+  ctx = GNUNET_malloc (sizeof (struct RegexSearchContext));
+  ctx->position = size;
+  ctx->info = h;
+  GNUNET_array_append (h->contexts, h->n_contexts, ctx);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "  consumed %u bits out of %u\n", size, len);
+  LOG (GNUNET_ERROR_TYPE_INFO, "   looking for %s\n", GNUNET_h2s (&key));
+
+  /* Start search in DHT */
+  get_h = GNUNET_DHT_get_start (h->dht,    /* handle */
+                                GNUNET_BLOCK_TYPE_REGEX, /* type */
+                                &key,     /* key to search */
+                                DHT_REPLICATION, /* replication level */
+                                DHT_OPT,
+                                &h->description[size],           /* xquery */
+                                // FIXME add BLOOMFILTER to exclude filtered peers
+                                len + 1 - size,                /* xquery bits */
+                                // FIXME add BLOOMFILTER SIZE
+                                &dht_get_string_handler, ctx);
+  GNUNET_break (
+    GNUNET_OK ==
+    GNUNET_CONTAINER_multihashmap_put (h->dht_get_handles,
+                                       &key,
+                                       get_h,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)
+               );
+
   return h;
 }
 
@@ -751,4 +810,4 @@ GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_search_handle *h)
 
 
 
-/* end of regex_dht.c */
\ No newline at end of file
+/* end of regex_dht.c */