added simulation
[oweals/gnunet.git] / src / ats / libgnunet_plugin_ats_proportional.c
index 0c855a66fde219266c5c62bf2f7bdd6ab390ca73..638a352562f9001496364c1662c315e81652044c 100644 (file)
@@ -345,6 +345,28 @@ struct Network
   struct AddressWrapper *tail;
 };
 
+/**
+ * Address information stored in the solver
+ */
+struct AddressSolverInformation
+{
+  struct Network *network;
+
+  /**
+   * Inbound quota
+   *
+   */
+  unsigned long long calculated_quota_in_NBO;
+
+  /**
+   * Outbound quota
+   *
+   */
+  unsigned long long calculated_quota_out_NBO;
+
+
+};
+
 /**
  * Wrapper for addresses to store them in network's linked list
  */
@@ -457,7 +479,7 @@ libgnunet_plugin_ats_proportional_done (void *cls)
 
     if (s->network_entries[c].active_addresses > 0)
     {
-      LOG(GNUNET_ERROR_TYPE_ERROR,
+      LOG(GNUNET_ERROR_TYPE_DEBUG,
           "Had %u active addresses for network `%s' not deleted during shutdown\n",
           s->network_entries[c].active_addresses, s->network_entries[c].desc);
       GNUNET_break(0);
@@ -469,6 +491,7 @@ libgnunet_plugin_ats_proportional_done (void *cls)
       next = cur->next;
       GNUNET_CONTAINER_DLL_remove(s->network_entries[c].head,
           s->network_entries[c].tail, cur);
+      GNUNET_free_non_null (cur->addr->solver_information);
       GNUNET_free(cur);
     }
     GNUNET_free(s->network_entries[c].stat_total);
@@ -476,13 +499,13 @@ libgnunet_plugin_ats_proportional_done (void *cls)
   }
   if (s->total_addresses > 0)
   {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
+    LOG(GNUNET_ERROR_TYPE_DEBUG,
         "Had %u addresses not deleted during shutdown\n", s->total_addresses);
     GNUNET_break(0);
   }
   if (s->active_addresses > 0)
   {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
+    LOG(GNUNET_ERROR_TYPE_DEBUG,
         "Had %u active addresses not deleted during shutdown\n",
         s->active_addresses);
     GNUNET_break (0);
@@ -530,12 +553,14 @@ is_bandwidth_available_in_network (struct Network *net)
  * this address
  */
 static void
-distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
+distribute_bandwidth (struct GAS_PROPORTIONAL_Handle *s,
     struct Network *net, struct ATS_Address *address_except)
 {
+  struct AddressSolverInformation *asi;
+  struct AddressWrapper *cur;
+
   unsigned long long remaining_quota_in = 0;
   unsigned long long quota_out_used = 0;
-
   unsigned long long remaining_quota_out = 0;
   unsigned long long quota_in_used = 0;
   uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
@@ -544,16 +569,9 @@ distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
   double cur_pref; /* Important: has to be double not float due to precision */
   const double *t = NULL; /* Important: has to be double not float due to precision */
   int c;
-
   unsigned long long assigned_quota_in = 0;
   unsigned long long assigned_quota_out = 0;
-  struct AddressWrapper *cur;
 
-  if (GNUNET_YES == s->bulk_lock)
-  {
-    s->bulk_requests++;
-    return;
-  }
 
   LOG(GNUNET_ERROR_TYPE_DEBUG,
       "Recalculate quota for network type `%s' for %u addresses (in/out): %llu/%llu \n",
@@ -643,16 +661,9 @@ distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
       assigned_quota_out = UINT32_MAX;
 
     /* Compare to current bandwidth assigned */
-    if ((assigned_quota_in != ntohl (cur->addr->assigned_bw_in.value__))
-        || (assigned_quota_out != ntohl (cur->addr->assigned_bw_out.value__)))
-    {
-      cur->addr->assigned_bw_in.value__ = htonl (assigned_quota_in);
-      cur->addr->assigned_bw_out.value__ = htonl (assigned_quota_out);
-      /* Notify on change */
-      if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except))
-        s->bw_changed (s->bw_changed_cls, cur->addr);
-    }
-
+    asi = cur->addr->solver_information;
+    asi->calculated_quota_in_NBO = htonl (assigned_quota_in);
+    asi->calculated_quota_out_NBO = htonl (assigned_quota_out);
   }
   LOG(GNUNET_ERROR_TYPE_DEBUG,
       "Total bandwidth assigned is (in/out): %llu /%llu\n", quota_in_used,
@@ -706,11 +717,12 @@ find_best_address_it (void *cls,
   struct FindBestAddressCtx *fba_ctx = (struct FindBestAddressCtx *) cls;
   struct ATS_Address *current = (struct ATS_Address *) value;
   struct GNUNET_TIME_Absolute now;
-  struct Network *net = (struct Network *) current->solver_information;
+  struct AddressSolverInformation *asi;
   const double *norm_prop_cur;
   const double *norm_prop_prev;
   int index;
 
+  asi = current->solver_information;
   now = GNUNET_TIME_absolute_get ();
 
   if (current->blocked_until.abs_value_us
@@ -722,7 +734,7 @@ find_best_address_it (void *cls,
         GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (now, current->blocked_until), GNUNET_YES));
     return GNUNET_OK;
   }
-  if (GNUNET_NO == is_bandwidth_available_in_network (net))
+  if (GNUNET_NO == is_bandwidth_available_in_network (asi->network))
     return GNUNET_OK; /* There's no bandwidth available in this network */
   if (NULL != fba_ctx->best)
   {
@@ -801,18 +813,83 @@ find_best_address_it (void *cls,
  *  Helper functions
  *  ---------------------------
  */
+static void
+propagate_bandwidth (struct GAS_PROPORTIONAL_Handle *s,
+    struct Network *net, struct ATS_Address *address_except)
+{
+  struct AddressWrapper *cur;
+  struct AddressSolverInformation *asi;
+  for (cur = net->head; NULL != cur; cur = cur->next)
+  {
+      asi = cur->addr->solver_information;
+      if ( (cur->addr->assigned_bw_in.value__ != asi->calculated_quota_in_NBO) ||
+           (cur->addr->assigned_bw_out.value__ != asi->calculated_quota_out_NBO) )
+      {
+        cur->addr->assigned_bw_in.value__ = asi->calculated_quota_in_NBO;
+        cur->addr->assigned_bw_out.value__ = asi->calculated_quota_in_NBO;
+        /* Notify on change */
+        if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except))
+          s->bw_changed (s->bw_changed_cls, cur->addr);
+      }
+  }
+}
 
 /**
- * Update bandwidth assignment for all networks
+ * Distribibute bandwidth
  *
  * @param s the solver handle
+ * @param n the network, can be NULL for all network
+ * @param address_except do not notify for this address
  */
 static void
-distribute_bandwidth_in_all_networks (struct GAS_PROPORTIONAL_Handle *s)
+distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
+    struct Network *n, struct ATS_Address *address_except)
 {
-  int i;
-  for (i = 0; i < s->network_count; i++)
-    distribute_bandwidth_in_network (s, &s->network_entries[i], NULL );
+  if (GNUNET_YES == s->bulk_lock)
+  {
+    s->bulk_requests++;
+    return;
+  }
+
+  if (NULL != n)
+  {
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_START,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE);
+    distribute_bandwidth(s, n, address_except);
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_STOP,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE);
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE);
+    propagate_bandwidth(s, n, address_except);
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE);
+  }
+  else
+  {
+    int i;
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_START,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL);
+    for (i = 0; i < s->network_count; i++)
+      distribute_bandwidth(s, &s->network_entries[i], NULL);
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_STOP,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL);
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL);
+    for (i = 0; i < s->network_count; i++)
+    {
+      propagate_bandwidth(s, &s->network_entries[i], address_except);
+    }
+    if (NULL != s->env->info_cb)
+      s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP,
+          GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL);
+  }
 }
 
 /**
@@ -990,7 +1067,7 @@ GAS_proportional_address_change_preference (void *solver,
   GNUNET_assert(NULL != solver);
   GNUNET_assert(NULL != peer);
 
-  distribute_bandwidth_in_all_networks (s);
+  distribute_bandwidth_in_network (s, NULL, NULL);
 }
 
 
@@ -1033,6 +1110,8 @@ GAS_proportional_get_preferred_address (void *solver,
   struct Network *net_cur;
   struct ATS_Address *prev;
   struct FindBestAddressCtx fba_ctx;
+  struct AddressSolverInformation *asi;
+  struct AddressSolverInformation *asi_prev;
 
   GNUNET_assert(s != NULL);
   GNUNET_assert(peer != NULL);
@@ -1063,7 +1142,8 @@ GAS_proportional_get_preferred_address (void *solver,
   LOG(GNUNET_ERROR_TYPE_INFO, "Suggesting %s address %p for peer `%s'\n",
       (GNUNET_NO == fba_ctx.best->active) ? "inactive" : "active", fba_ctx.best,
       GNUNET_i2s (peer));
-  net_cur = (struct Network *) fba_ctx.best->solver_information;
+  asi = fba_ctx.best->solver_information;
+  net_cur = asi->network ;
   if (NULL == fba_ctx.best)
   {
     LOG(GNUNET_ERROR_TYPE_ERROR,
@@ -1083,20 +1163,20 @@ GAS_proportional_get_preferred_address (void *solver,
    * - update quota for previous address network
    * - update quota for this address network
    */
-  prev = get_active_address (s,
-                            s->addresses, peer);
+  prev = get_active_address (s, s->addresses, peer);
   if (NULL != prev)
   {
-    net_prev = (struct Network *) prev->solver_information;
+    asi_prev = prev->solver_information;
+    net_prev = (struct Network *) asi_prev->network;
     prev->active = GNUNET_NO; /* No active any longer */
     prev->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
     prev->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
     if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES))
       GNUNET_break(0);
-    distribute_bandwidth_in_network (s, net_prev, NULL );
+    distribute_bandwidth_in_network (s, net_prev, NULL);
   }
 
-  if (GNUNET_NO == (is_bandwidth_available_in_network (fba_ctx.best->solver_information)))
+  if (GNUNET_NO == (is_bandwidth_available_in_network (net_cur)))
   {
     GNUNET_break(0); /* This should never happen*/
     return NULL ;
@@ -1104,7 +1184,7 @@ GAS_proportional_get_preferred_address (void *solver,
 
   fba_ctx.best->active = GNUNET_YES;
   addresse_increment (s, net_cur, GNUNET_NO, GNUNET_YES);
-  distribute_bandwidth_in_network (s, net_cur, fba_ctx.best );
+  distribute_bandwidth_in_network (s, net_cur, fba_ctx.best);
   return fba_ctx.best;
 }
 
@@ -1120,6 +1200,7 @@ GAS_proportional_stop_get_preferred_address (void *solver,
 {
   struct GAS_PROPORTIONAL_Handle *s = solver;
   struct ATS_Address *cur;
+  struct AddressSolverInformation *asi;
   struct Network *cur_net;
 
   if (GNUNET_YES
@@ -1133,7 +1214,8 @@ GAS_proportional_stop_get_preferred_address (void *solver,
   if (NULL != cur)
   {
     /* Disabling current address */
-    cur_net = (struct Network *) cur->solver_information;
+    asi = cur->solver_information;
+    cur_net = asi->network ;
     cur->active = GNUNET_NO; /* No active any longer */
     cur->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
     cur->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
@@ -1158,6 +1240,7 @@ GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
   struct GAS_PROPORTIONAL_Handle *s = solver;
   struct Network *net;
   struct AddressWrapper *aw;
+  struct AddressSolverInformation *asi;
   const struct ATS_Address *new_address;
 
 
@@ -1168,8 +1251,15 @@ GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
    *   - decrease number of active addreses
    *   - update quotas
    */
+  asi = address->solver_information;
 
-  net = (struct Network *) address->solver_information;
+  if (NULL == asi)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  net = asi->network;
 
   if (GNUNET_NO == session_only)
   {
@@ -1192,6 +1282,7 @@ GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
       return;
     }
     GNUNET_CONTAINER_DLL_remove(net->head, net->tail, aw);
+    GNUNET_free_non_null (aw->addr->solver_information);
     GNUNET_free(aw);
   }
   else
@@ -1213,7 +1304,7 @@ GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
 
     if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES))
       GNUNET_break(0);
-    distribute_bandwidth_in_network (s, net, NULL );
+    distribute_bandwidth_in_network (s, net, NULL);
     if (NULL == (new_address = GAS_proportional_get_preferred_address (s, &address->peer)))
     {
       /* No alternative address found, disconnect peer */
@@ -1266,7 +1357,7 @@ GAS_proportional_bulk_stop (void *solver)
   if ((0 == s->bulk_lock) && (0 < s->bulk_requests))
   {
     LOG(GNUNET_ERROR_TYPE_DEBUG, "No lock pending, recalculating\n");
-    distribute_bandwidth_in_all_networks (s);
+    distribute_bandwidth_in_network (s, NULL, NULL);
     s->bulk_requests = 0;
   }
 }
@@ -1299,12 +1390,14 @@ GAS_proportional_address_property_changed (void *solver,
 {
   struct GAS_PROPORTIONAL_Handle *s;
   struct Network *n;
+  struct AddressSolverInformation *asi;
 
   GNUNET_assert(NULL != solver);
   GNUNET_assert(NULL != address);
 
   s = (struct GAS_PROPORTIONAL_Handle *) solver;
-  n = (struct Network *) address->solver_information;
+  asi = address->solver_information;
+  n = asi->network;
 
   if (NULL == n)
   {
@@ -1327,7 +1420,7 @@ GAS_proportional_address_property_changed (void *solver,
   case GNUNET_ATS_COST_WAN:
   case GNUNET_ATS_COST_LAN:
   case GNUNET_ATS_COST_WLAN:
-    distribute_bandwidth_in_network (s, n, GNUNET_NO);
+    distribute_bandwidth_in_network (s, n, NULL);
     break;
   }
 }
@@ -1385,7 +1478,9 @@ GAS_proportional_address_change_network (void *solver,
     struct ATS_Address *address, uint32_t current_network, uint32_t new_network)
 {
   struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver;
+  struct AddressSolverInformation *asi;
   int save_active = GNUNET_NO;
+
   struct Network *new_net = NULL;
 
   if (current_network == new_network)
@@ -1429,7 +1524,8 @@ GAS_proportional_address_change_network (void *solver,
   }
 
   /* Add to new network and update*/
-  address->solver_information = new_net;
+  asi = address->solver_information;
+  asi->network = new_net;
   GAS_proportional_address_add (solver, address, new_network);
   if (GNUNET_YES == save_active)
   {
@@ -1439,7 +1535,7 @@ GAS_proportional_address_change_network (void *solver,
       /* Assign bandwidth to updated address */
       address->active = GNUNET_YES;
       addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES);
-      distribute_bandwidth_in_network (solver, new_net, NULL );
+      distribute_bandwidth_in_network (solver, new_net, NULL);
     }
     else
     {
@@ -1469,9 +1565,9 @@ GAS_proportional_address_add (void *solver, struct ATS_Address *address,
   struct GAS_PROPORTIONAL_Handle *s = solver;
   struct Network *net = NULL;
   struct AddressWrapper *aw = NULL;
+  struct AddressSolverInformation *asi;
 
   GNUNET_assert(NULL != s);
-
   net = get_network (s, network);
   if (NULL == net)
   {
@@ -1483,7 +1579,12 @@ GAS_proportional_address_add (void *solver, struct ATS_Address *address,
   aw->addr = address;
   GNUNET_CONTAINER_DLL_insert(net->head, net->tail, aw);
   addresse_increment (s, net, GNUNET_YES, GNUNET_NO);
-  aw->addr->solver_information = net;
+
+  asi = GNUNET_malloc (sizeof (struct AddressSolverInformation));
+  asi->network = net;
+  asi->calculated_quota_in_NBO = 0;
+  asi->calculated_quota_out_NBO = 0;
+  aw->addr->solver_information = asi;
 
   if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (s->requests, &address->peer))
   {