extending bandwidth tracker api to support notifications
[oweals/gnunet.git] / src / util / bandwidth.c
index 60cb50529f316d7a3dfcf085b286025cb6cb5fbb..f056c1aeeb42b792634379c6c3fb9e4aa02e2055 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2010 Christian Grothoff (and other contributing authors)
+     (C) 2010, 2013 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
 
      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 2, or (at your
+     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
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -83,9 +83,9 @@ GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO
   b = ntohl (bps.value__);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Bandwidth has %llu bytes available until deadline in %s\n",
   b = ntohl (bps.value__);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Bandwidth has %llu bytes available until deadline in %s\n",
-       (unsigned long long) ((b * deadline.rel_value + 500LL) / 1000LL),
+       (unsigned long long) ((b * deadline.rel_value_us + 500000LL) / 1000000LL),
        GNUNET_STRINGS_relative_time_to_string (deadline, GNUNET_YES));
        GNUNET_STRINGS_relative_time_to_string (deadline, GNUNET_YES));
-  return (b * deadline.rel_value + 500LL) / 1000LL;
+  return (b * deadline.rel_value_us + 500000LL) / 1000000LL;
 }
 
 
 }
 
 
@@ -105,20 +105,22 @@ GNUNET_BANDWIDTH_value_get_delay_for (struct GNUNET_BANDWIDTH_Value32NBO bps,
   struct GNUNET_TIME_Relative ret;
 
   b = ntohl (bps.value__);
   struct GNUNET_TIME_Relative ret;
 
   b = ntohl (bps.value__);
-  if (b == 0)
+  if (0 == b)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Bandwidth suggests delay of infinity (zero bandwidth)\n");
     return GNUNET_TIME_UNIT_FOREVER_REL;
   }
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Bandwidth suggests delay of infinity (zero bandwidth)\n");
     return GNUNET_TIME_UNIT_FOREVER_REL;
   }
-  ret.rel_value = size * 1000LL / b;
+  ret.rel_value_us = size * 1000LL * 1000LL / b;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Bandwidth suggests delay of %llu ms for %llu bytes of traffic\n",
-       (unsigned long long) ret.rel_value, (unsigned long long) size);
+       "Bandwidth suggests delay of %s for %llu bytes of traffic\n",
+       GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES),
+       (unsigned long long) size);
   return ret;
 }
 
 
   return ret;
 }
 
 
+
 /**
  * Initialize bandwidth tracker.  Note that in addition to the
  * 'max_carry_s' limit, we also always allow at least
 /**
  * Initialize bandwidth tracker.  Note that in addition to the
  * 'max_carry_s' limit, we also always allow at least
@@ -129,15 +131,21 @@ GNUNET_BANDWIDTH_value_get_delay_for (struct GNUNET_BANDWIDTH_Value32NBO bps,
  * bytes).
  *
  * @param av tracker to initialize
  * bytes).
  *
  * @param av tracker to initialize
+ * @param update_cb callback to notify a client about the tracker being updated
+ * @param update_cb_cls cls for the callback
  * @param bytes_per_second_limit initial limit to assume
  * @param max_carry_s maximum number of seconds unused bandwidth
  *        may accumulate before it expires
  */
 void
 GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av,
  * @param bytes_per_second_limit initial limit to assume
  * @param max_carry_s maximum number of seconds unused bandwidth
  *        may accumulate before it expires
  */
 void
 GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av,
+                               GNUNET_BANDWIDTH_tracker_update_cb update_cb,
+                               void *update_cb_cls,
                                struct GNUNET_BANDWIDTH_Value32NBO
                                bytes_per_second_limit, uint32_t max_carry_s)
 {
                                struct GNUNET_BANDWIDTH_Value32NBO
                                bytes_per_second_limit, uint32_t max_carry_s)
 {
+  av->update_cb = update_cb;
+  av->update_cb_cls = update_cb_cls;
   av->consumption_since_last_update__ = 0;
   av->last_update__ = GNUNET_TIME_absolute_get ();
   av->available_bytes_per_s__ = ntohl (bytes_per_second_limit.value__);
   av->consumption_since_last_update__ = 0;
   av->last_update__ = GNUNET_TIME_absolute_get ();
   av->available_bytes_per_s__ = ntohl (bytes_per_second_limit.value__);
@@ -158,16 +166,17 @@ static void
 update_tracker (struct GNUNET_BANDWIDTH_Tracker *av)
 {
   struct GNUNET_TIME_Absolute now;
 update_tracker (struct GNUNET_BANDWIDTH_Tracker *av)
 {
   struct GNUNET_TIME_Absolute now;
+  struct GNUNET_TIME_Relative delta;
   uint64_t delta_time;
   uint64_t delta_avail;
   uint64_t left_bytes;
   uint64_t max_carry;
 
   now = GNUNET_TIME_absolute_get ();
   uint64_t delta_time;
   uint64_t delta_avail;
   uint64_t left_bytes;
   uint64_t max_carry;
 
   now = GNUNET_TIME_absolute_get ();
-  delta_time = now.abs_value - av->last_update__.abs_value;
+  delta_time = now.abs_value_us - av->last_update__.abs_value_us;
   delta_avail =
       (delta_time * ((unsigned long long) av->available_bytes_per_s__) +
   delta_avail =
       (delta_time * ((unsigned long long) av->available_bytes_per_s__) +
-       500LL) / 1000LL;
+       500000LL) / 1000000LL;
   av->consumption_since_last_update__ -= delta_avail;
   av->last_update__ = now;
   if (av->consumption_since_last_update__ < 0)
   av->consumption_since_last_update__ -= delta_avail;
   av->last_update__ = now;
   if (av->consumption_since_last_update__ < 0)
@@ -181,10 +190,11 @@ update_tracker (struct GNUNET_BANDWIDTH_Tracker *av)
     else
       av->consumption_since_last_update__ = -max_carry;
   }
     else
       av->consumption_since_last_update__ = -max_carry;
   }
+  delta.rel_value_us = delta_time;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Tracker %p  updated, have %u Bps, last update was %llu ms ago\n", av,
+       "Tracker %p updated, have %u Bps, last update was %s ago\n", av,
        (unsigned int) av->available_bytes_per_s__,
        (unsigned int) av->available_bytes_per_s__,
-       (unsigned long long) delta_time);
+       GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES));
 }
 
 
 }
 
 
@@ -251,22 +261,26 @@ GNUNET_BANDWIDTH_tracker_get_delay (struct GNUNET_BANDWIDTH_Tracker *av,
 
   if (av->available_bytes_per_s__ == 0)
   {
 
   if (av->available_bytes_per_s__ == 0)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p delay is infinity\n", av);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Tracker %p delay is infinity\n", av);
     return GNUNET_TIME_UNIT_FOREVER_REL;
   }
   update_tracker (av);
   bytes_needed = size + av->consumption_since_last_update__;
   if (bytes_needed <= 0)
   {
     return GNUNET_TIME_UNIT_FOREVER_REL;
   }
   update_tracker (av);
   bytes_needed = size + av->consumption_since_last_update__;
   if (bytes_needed <= 0)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p delay for %u bytes is zero\n", av,
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Tracker %p delay for %u bytes is zero\n", av,
          (unsigned int) size);
     return GNUNET_TIME_UNIT_ZERO;
   }
          (unsigned int) size);
     return GNUNET_TIME_UNIT_ZERO;
   }
-  ret.rel_value =
-      (1000LL * bytes_needed) /
+  ret.rel_value_us =
+      (1000LL * 1000LL * bytes_needed) /
       (unsigned long long) av->available_bytes_per_s__;
       (unsigned long long) av->available_bytes_per_s__;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p delay for %u bytes is %llu ms\n",
-       av, (unsigned int) size, (unsigned long long) ret.rel_value);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Tracker %p delay for %u bytes is %s\n",
+       av, (unsigned int) size,
+       GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES));
   return ret;
 }
 
   return ret;
 }
 
@@ -293,7 +307,7 @@ GNUNET_BANDWIDTH_tracker_get_available (struct GNUNET_BANDWIDTH_Tracker * av)
                                                   (av->last_update__));
   used = av->consumption_since_last_update__;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
                                                   (av->last_update__));
   used = av->consumption_since_last_update__;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Tracker %p  available bandwidth is %lld bytes\n", av,
+       "Tracker %p available bandwidth is %lld bytes\n", av,
        (long long) (int64_t) (avail - used));
   return (int64_t) (avail - used);
 }
        (long long) (int64_t) (avail - used));
   return (int64_t) (avail - used);
 }
@@ -314,11 +328,14 @@ GNUNET_BANDWIDTH_tracker_update_quota (struct GNUNET_BANDWIDTH_Tracker *av,
   uint32_t new_limit;
 
   new_limit = ntohl (bytes_per_second_limit.value__);
   uint32_t new_limit;
 
   new_limit = ntohl (bytes_per_second_limit.value__);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p bandwidth changed to %u Bps\n", av,
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Tracker %p bandwidth changed to %u Bps\n", av,
        (unsigned int) new_limit);
   update_tracker (av);
   old_limit = av->available_bytes_per_s__;
   av->available_bytes_per_s__ = new_limit;
        (unsigned int) new_limit);
   update_tracker (av);
   old_limit = av->available_bytes_per_s__;
   av->available_bytes_per_s__ = new_limit;
+  if (NULL != av->update_cb)
+    av->update_cb (av->update_cb_cls);
   if (old_limit > new_limit)
     update_tracker (av);        /* maximum excess might be less now */
 }
   if (old_limit > new_limit)
     update_tracker (av);        /* maximum excess might be less now */
 }