-more datacache integration work
[oweals/gnunet.git] / src / testbed / gnunet-daemon-latency-logger.c
index e4faa8c98e09932f9dd86185392b8ccc307cb140..2dca73768d351fdf4e0ae39bc2bece1506c3ebc1 100644 (file)
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      (C) 2008--2014 Christian Grothoff (and other contributing authors)
+      Copyright (C) 2008--2014 Christian Grothoff (and other contributing authors)
 
       GNUnet is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
@@ -21,7 +21,7 @@
 /**
  * @file testbed/gnunet-daemon-latency-logger.c
  * @brief log latency values from neighbour connections into an SQLite database
- * @author Sree Harsha Totakura <sreeharsha@totakura.in> 
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  */
 
 #include "platform.h"
   } while(0)
 
 
+/**
+ * Entry type to be used in the map to store old latency values
+ */
+struct Entry
+{
+  /**
+   *  The peer's identity
+   */
+  struct GNUNET_PeerIdentity id;
+
+  /**
+   * The last known value for latency.
+   * FIXME: type!
+   */
+  unsigned int latency;
+
+};
+
+
+/**
+ * Handle to the map used to store old latency values for peers
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *map;
+
 /**
  * The SQLite database handle
  */
@@ -75,7 +99,32 @@ struct sqlite3_stmt *stmt_insert;
 /**
  * Shutdown task identifier
  */
-GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
+struct GNUNET_SCHEDULER_Task * shutdown_task;
+
+
+/**
+ * @ingroup hashmap
+ * Iterator over hash map entries.
+ *
+ * @param cls closure
+ * @param key current public key
+ * @param value value in the hash map
+ * @return #GNUNET_YES if we should continue to
+ *         iterate,
+ *         #GNUNET_NO if not.
+ */
+static int
+free_iterator (void *cls,
+               const struct GNUNET_PeerIdentity *key,
+               void *value)
+{
+  struct Entry *e = cls;
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multipeermap_remove (map, key, e));
+  GNUNET_free (e);
+  return GNUNET_YES;
+}
 
 
 /**
@@ -83,12 +132,12 @@ GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
  *
  * @param cls NULL
  * @param tc task context from scheduler
- * @return 
+ * @return
  */
 static void
 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  shutdown_task = GNUNET_SCHEDULER_NO_TASK;
+  shutdown_task = NULL;
   GNUNET_ATS_performance_done (ats);
   ats = NULL;
   if (NULL != stmt_insert)
@@ -98,6 +147,13 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   }
   GNUNET_break (SQLITE_OK == sqlite3_close (db));
   db = NULL;
+  if (NULL != map)
+  {
+    GNUNET_assert (GNUNET_SYSERR !=
+                   GNUNET_CONTAINER_multipeermap_iterate (map, free_iterator, NULL));
+    GNUNET_CONTAINER_multipeermap_destroy (map);
+    map = NULL;
+  }
 }
 
 /**
@@ -105,12 +161,13 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  *
  * @param cls closure
  * @param address the address
- * @param address_active is this address actively used to maintain a connection
- *                             to a peer
+ * @param address_active #GNUNET_YES if this address is actively used
+ *        to maintain a connection to a peer;
+ *        #GNUNET_NO if the address is not actively used;
+ *        #GNUNET_SYSERR if this address is no longer available for ATS
  * @param bandwidth_out assigned outbound bandwidth for the connection
  * @param bandwidth_in assigned inbound bandwidth for the connection
- * @param ats performance data for the address (as far as known)
- * @param ats_count number of performance records in 'ats'
+ * @param prop performance data for the address (as far as known)
  */
 static void
 addr_info_cb (void *cls,
@@ -118,8 +175,7 @@ addr_info_cb (void *cls,
               int address_active,
               struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
               struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
-              const struct GNUNET_ATS_Information *ats,
-              uint32_t ats_count)
+              const struct GNUNET_ATS_Properties *prop)
 {
   static const char *query_insert =
       "INSERT INTO ats_info("
@@ -131,21 +187,28 @@ addr_info_cb (void *cls,
       " ?2,"
       " datetime('now')"
       ");";
-  int latency;
-  unsigned int cnt;
+  struct Entry *entry;
+  int latency; /* FIXME: type!? */
+
+  if (NULL == address)
+  {
+    /* ATS service temporarily disconnected */
+    return;
+  }
 
   GNUNET_assert (NULL != db);
-  if (GNUNET_NO == address_active)
+  if (GNUNET_YES != address_active)
     return;
-  for (cnt = 0; cnt < ats_count; cnt++)
+  latency = (int) prop->delay.rel_value_us;
+  entry = NULL;
+  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map,
+                                                            &address->peer))
   {
-    if (GNUNET_ATS_QUALITY_NET_DELAY == ntohl (ats[cnt].type))
-      goto insert;
+    entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer);
+    GNUNET_assert (NULL != entry);
+    if (latency == entry->latency)
+      return;
   }
-  return;
-
- insert:
-  latency = (int) ntohl (ats[cnt].value);
   if (NULL == stmt_insert)
   {
     if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert,
@@ -173,8 +236,17 @@ addr_info_cb (void *cls,
     LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert");
     goto err_shutdown;
   }
+  if (NULL == entry)
+  {
+    entry = GNUNET_new (struct Entry);
+    entry->id = address->peer;
+    GNUNET_CONTAINER_multipeermap_put (map,
+                                       &entry->id, entry,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+  }
+  entry->latency = latency;
   return;
-  
+
  err_shutdown:
       GNUNET_SCHEDULER_shutdown ();
 }
@@ -192,7 +264,7 @@ static void
 run (void *cls, char *const *args, const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  const char *query_create = 
+  const char *query_create =
       "CREATE TABLE ats_info ("
       "id TEXT,"
       "val INTEGER,"
@@ -212,7 +284,7 @@ run (void *cls, char *const *args, const char *cfgfile,
     if (NULL != db)
     {
       LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2");
-      sqlite3_close (db);
+      GNUNET_break (SQLITE_OK == sqlite3_close (db));
     }
     else
       LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile);
@@ -223,9 +295,10 @@ run (void *cls, char *const *args, const char *cfgfile,
     DEBUG ("SQLite Error: %d.  Perhaps the database `%s' already exits.\n",
            sqlite3_errcode (db), dbfile);
   DEBUG ("Opened database %s\n", dbfile);
-  GNUNET_free (dbfile);  
+  GNUNET_free (dbfile);
   dbfile = NULL;
-  ats = GNUNET_ATS_performance_init (c, addr_info_cb, NULL);
+  ats = GNUNET_ATS_performance_init (c, &addr_info_cb, NULL);
+  map = GNUNET_CONTAINER_multipeermap_create (30, GNUNET_YES);
   shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                                 &do_shutdown, NULL);
 }