fixing shutdown
[oweals/gnunet.git] / src / ats / gnunet-service-ats-solver_ril.c
index 3c7bc9be0b50097ea6777f121ed5bad3493c6224..9aecd1747a5b4ee0bae845646c99f272c56ec615 100755 (executable)
 
 enum RIL_Action_Type
 {
-  RIL_ACTION_BW_IN_DBL = 0,
-  RIL_ACTION_BW_OUT_DBL = 1,
+  RIL_ACTION_NOTHING = 0,
+  RIL_ACTION_BW_IN_DBL = 1,
   RIL_ACTION_BW_IN_HLV = 2,
-  RIL_ACTION_BW_OUT_HLV = 3,
-  RIL_ACTION_TYPE_NUM = 4
+  RIL_ACTION_BW_IN_INC = 3,
+  RIL_ACTION_BW_IN_DEC = 4,
+  RIL_ACTION_BW_OUT_DBL = 5,
+  RIL_ACTION_BW_OUT_HLV = 6,
+  RIL_ACTION_BW_OUT_INC = 7,
+  RIL_ACTION_BW_OUT_DEC = 8,
+  RIL_ACTION_TYPE_NUM = 9
 };
 //TODO! add the rest of the actions
 
 enum RIL_Algorithm
 {
-  RIL_ALGO_SARSA = 0,
-  RIL_ALGO_Q = 1
+  RIL_ALGO_SARSA = 0, RIL_ALGO_Q = 1
 };
 
 enum RIL_E_Modification
@@ -400,7 +404,6 @@ agent_update_weights (struct RIL_Peer_Agent *agent,
   double delta;
   double *theta = agent->W[agent->a_old];
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "agent_update_weights() MUH a_old = %d\n", agent->a_old);
   delta = reward + agent_estimate_q (agent, s_next, a_prime)
       - agent_estimate_q (agent, agent->s_old, agent->a_old);
   for (i = 0; i < agent->m; i++)
@@ -447,6 +450,44 @@ agent_modify_eligibility (struct RIL_Peer_Agent *agent,
   }
 }
 
+static void
+envi_change_active_address (struct GAS_RIL_Handle *solver,
+    struct RIL_Peer_Agent *agent,
+    struct ATS_Address *new_address,
+    unsigned long long new_bw_in,
+    unsigned long long new_bw_out)
+{
+  int notify = GNUNET_NO;
+
+  if (agent->address != new_address)
+  {
+    agent->address->active = GNUNET_NO;
+    agent->address = new_address;
+    agent->address->active = GNUNET_YES;
+    agent->address->assigned_bw_in.value__ = htonl (agent->bw_in);
+    agent->address->assigned_bw_out.value__ = htonl (agent->bw_out);
+    notify |= GNUNET_YES;
+  }
+  if (agent->bw_in != new_bw_in)
+  {
+    agent->bw_in = new_bw_in;
+    agent->address->assigned_bw_in.value__ = htonl (new_bw_out);
+    notify |= GNUNET_YES;
+  }
+  if (agent->bw_out != new_bw_out)
+  {
+    agent->bw_out = new_bw_out;
+    agent->address->assigned_bw_out.value__ = htonl (new_bw_out);
+    notify |= GNUNET_YES;
+  }
+
+  if (notify)
+  {
+    solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls,
+        agent->address);
+  }
+}
+
 /**
  * Allocates a state vector and fills it with the features present
  * @param solver the solver handle
@@ -462,10 +503,10 @@ envi_get_state (struct GAS_RIL_Handle *solver)
   for (i = 0; i < solver->networks_count; i++)
   {
     net = &solver->network_entries[i];
-    state[i*4 + 0] = (double) net->bw_in_assigned;
-    state[i*4 + 1] = (double) net->bw_in_available;
-    state[i*4 + 2] = (double) net->bw_out_assigned;
-    state[i*4 + 3] = (double) net->bw_out_available;
+    state[i * 4 + 0] = (double) net->bw_in_assigned;
+    state[i * 4 + 1] = (double) net->bw_in_available;
+    state[i * 4 + 2] = (double) net->bw_out_assigned;
+    state[i * 4 + 3] = (double) net->bw_out_available;
   }
 
   return state;
@@ -492,17 +533,13 @@ envi_action_bw_double (struct GAS_RIL_Handle *solver,
 {
   if (direction_in)
   {
-    agent->bw_in *= 2;
-    agent->address->assigned_bw_in.value__ = htonl (agent->bw_in);
-    solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls,
-        agent->address);
+    envi_change_active_address (solver, agent, agent->address, agent->bw_in * 2,
+        agent->bw_out);
   }
   else
   {
-    agent->bw_out *= 2;
-    agent->address->assigned_bw_out.value__ = htonl (agent->bw_out);
-    solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls,
-        agent->address);
+    envi_change_active_address (solver, agent, agent->address, agent->bw_in,
+        agent->bw_out * 2);
   }
 }
 
@@ -511,24 +548,69 @@ envi_action_bw_halven (struct GAS_RIL_Handle *solver,
     struct RIL_Peer_Agent *agent,
     int direction_in)
 {
-  if ((direction_in && 1 == agent->bw_in)
-      || (!direction_in && 1 == agent->bw_out))
+  uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+  unsigned long long new_bw;
+
+  if (direction_in)
   {
-    return;
+    new_bw = agent->bw_in / 2;
+    if (new_bw < min_bw)
+      new_bw = min_bw;
+    envi_change_active_address (solver, agent, agent->address, new_bw,
+        agent->bw_out);
+  }
+  else
+  {
+    new_bw = agent->bw_out / 2;
+    if (new_bw < min_bw)
+      new_bw = min_bw;
+    envi_change_active_address (solver, agent, agent->address, agent->bw_in,
+        new_bw);
   }
+}
+
+static void
+envi_action_bw_inc (struct GAS_RIL_Handle *solver,
+    struct RIL_Peer_Agent *agent,
+    int direction_in)
+{
+  uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+
   if (direction_in)
   {
-    agent->bw_in /= 2;
-    agent->address->assigned_bw_in.value__ = htonl (agent->bw_in);
-    solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls,
-        agent->address);
+    envi_change_active_address (solver, agent, agent->address,
+        agent->bw_in + (5 * min_bw), agent->bw_out);
   }
   else
   {
-    agent->bw_out /= 2;
-    agent->address->assigned_bw_out.value__ = htonl (agent->bw_out);
-    solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls,
-        agent->address);
+    envi_change_active_address (solver, agent, agent->address, agent->bw_in,
+        agent->bw_out + (5 * min_bw));
+  }
+}
+
+static void
+envi_action_bw_dec (struct GAS_RIL_Handle *solver,
+    struct RIL_Peer_Agent *agent,
+    int direction_in)
+{
+  uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+  unsigned long long new_bw;
+
+  if (direction_in)
+  {
+    new_bw = agent->bw_in - (5 * min_bw);
+    if (new_bw < min_bw)
+      new_bw = min_bw;
+    envi_change_active_address (solver, agent, agent->address, new_bw,
+        agent->bw_out);
+  }
+  else
+  {
+    new_bw = agent->bw_out - (5 * min_bw);
+    if (new_bw < min_bw)
+      new_bw = min_bw;
+    envi_change_active_address (solver, agent, agent->address, agent->bw_in,
+        new_bw);
   }
 }
 
@@ -544,18 +626,35 @@ envi_do_action (struct GAS_RIL_Handle *solver,
 {
   switch (action)
   {
+  case RIL_ACTION_NOTHING:
+    break;
   case RIL_ACTION_BW_IN_DBL:
     envi_action_bw_double (solver, agent, GNUNET_YES);
     break;
   case RIL_ACTION_BW_IN_HLV:
     envi_action_bw_halven (solver, agent, GNUNET_YES);
     break;
+  case RIL_ACTION_BW_IN_INC:
+    envi_action_bw_inc (solver, agent, GNUNET_YES);
+    break;
+  case RIL_ACTION_BW_IN_DEC:
+    envi_action_bw_dec (solver, agent, GNUNET_YES);
+    break;
   case RIL_ACTION_BW_OUT_DBL:
     envi_action_bw_double (solver, agent, GNUNET_NO);
     break;
   case RIL_ACTION_BW_OUT_HLV:
     envi_action_bw_halven (solver, agent, GNUNET_NO);
     break;
+  case RIL_ACTION_BW_OUT_INC:
+    envi_action_bw_inc (solver, agent, GNUNET_NO);
+    break;
+  case RIL_ACTION_BW_OUT_DEC:
+    envi_action_bw_dec (solver, agent, GNUNET_NO);
+    break;
+  default:
+    // error - action does not exist
+    GNUNET_assert(GNUNET_NO);
   }
 }
 
@@ -576,7 +675,7 @@ agent_step (struct RIL_Peer_Agent *agent)
   s_next = envi_get_state (agent->envi);
   reward = envi_get_reward (agent->envi, agent);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "agent_step() with algorithm %s\n",
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "agent_step() with algorithm %s\n",
       agent->envi->parameters.algorithm ? "Q" : "SARSA");
 
   switch (agent->envi->parameters.algorithm)
@@ -720,8 +819,10 @@ ril_remove_agent (struct GAS_RIL_Handle *s, struct RIL_Peer_Agent *agent)
     next_agent = cur_agent->next;
 
     if (agent == cur_agent)
+    {
       GNUNET_CONTAINER_DLL_remove(s->agents_head, s->agents_tail, cur_agent);
       agent_die (s, cur_agent);
+    }
 
     cur_agent = next_agent;
   }
@@ -733,22 +834,22 @@ ril_remove_agent (struct GAS_RIL_Handle *s, struct RIL_Peer_Agent *agent)
  * @param active_only whether only active agents should be counted
  * @return number of agents
  */
-static int
-ril_count_agents (struct GAS_RIL_Handle *solver, int active_only)
-{
-  int c;
-  struct RIL_Peer_Agent *cur;
-
-  c = 0;
-  for (cur = solver->agents_head; NULL != cur; cur = cur->next)
-  {
-    if ((!active_only) || (active_only && cur->active))
-    {
-      c += 1;
-    }
-  }
-  return c;
-}
+//static int
+//ril_count_agents (struct GAS_RIL_Handle *solver, int active_only)
+//{
+//  int c;
+//  struct RIL_Peer_Agent *cur;
+//
+//  c = 0;
+//  for (cur = solver->agents_head; NULL != cur; cur = cur->next)
+//  {
+//    if ((!active_only) || (active_only && cur->active))
+//    {
+//      c += 1;
+//    }
+//  }
+//  return c;
+//}
 
 /**
  * Returns the agent for a peer
@@ -774,7 +875,7 @@ ril_get_agent (struct GAS_RIL_Handle *solver,
 
   if (create)
     return agent_init (solver, peer);
-  return NULL;
+  return NULL ;
 }
 
 static int
@@ -803,7 +904,7 @@ ril_init_agents_it (void *cls, const struct GNUNET_HashCode *key, void *value)
   struct RIL_Peer_Agent *agent = NULL;
   uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
 
-  if (ril_network_is_active(address->solver_information))
+  if (ril_network_is_active (address->solver_information))
   {
     agent = ril_get_agent (solver, &address->peer, GNUNET_YES);
 
@@ -822,6 +923,28 @@ ril_init_agents_it (void *cls, const struct GNUNET_HashCode *key, void *value)
   return GNUNET_YES;
 }
 
+static void
+ril_get_new_address_or_delete (struct GAS_RIL_Handle *solver,
+    struct RIL_Peer_Agent *agent)
+{
+  uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+  //get new address for agent or delete agent
+
+  agent->address = NULL; //forget current address
+  GNUNET_CONTAINER_multihashmap_iterate (solver->addresses, &ril_init_agents_it,
+      solver); //put another address
+
+  if (NULL == agent->address) //no other address available
+  {
+    agent->active = GNUNET_NO;
+    ril_remove_agent (solver, agent);
+  }
+  else
+  {
+    envi_change_active_address (solver, agent, agent->address, min_bw, min_bw);
+  }
+}
+
 /**
  * Lookup network struct by type
  *
@@ -836,11 +959,12 @@ ril_get_network (struct GAS_RIL_Handle *s, uint32_t type)
 
   for (i = 0; i < s->networks_count; i++)
   {
-    if (s->network_entries[i].type == type) {
+    if (s->network_entries[i].type == type)
+    {
       return &s->network_entries[i];
     }
   }
-  return NULL;
+  return NULL ;
 }
 
 /**
@@ -863,7 +987,7 @@ GAS_ril_address_change_preference (void *s,
     double pref_rel)
 {
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "API_address_change_preference() Preference `%s' for peer `%s' changed to %.2f \n",
+      "API_address_change_preference() Preference '%s' for peer '%s' changed to %.2f \n",
       GNUNET_ATS_print_preference_type (kind), GNUNET_i2s (peer), pref_rel);
   /*
    * Nothing to do here. Preferences are considered during reward calculation.
@@ -1060,7 +1184,7 @@ GAS_ril_address_add (void *solver,
    * and action vector
    */
 
-  address->solver_information = ril_get_network(s, network);
+  address->solver_information = ril_get_network (s, network);
 
   /*
    * reiterate all addresses, create new agent if necessary and give the agent the address
@@ -1099,24 +1223,24 @@ GAS_ril_address_delete (void *solver,
   struct GAS_RIL_Handle *s = solver;
   struct RIL_Peer_Agent *agent;
 
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+      "API_address_delete() deleting %s address %p for peer '%s'\n",
+      address->active ? "active" : "inactive", address,
+      GNUNET_i2s (&address->peer));
+
   agent = ril_get_agent (s, &address->peer, GNUNET_NO);
 
   if (NULL == agent)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_address_delete() deleting address for unallocated agent");
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+        "API_address_delete() deleting address for unallocated agent\n");
     return;
   }
 
-  if (0 == memcmp (agent->address->addr, address->addr, address->addr_len)) //if used address deleted
+  if (address == agent->address) //if used address deleted
   {
-    agent->address = NULL; //delete address
-    GNUNET_CONTAINER_multihashmap_iterate (s->addresses, &ril_init_agents_it,
-        solver); //put another address
-    if (NULL == agent->address) //no other address available
-    {
-      agent->active = GNUNET_NO;
-      ril_remove_agent (solver, agent);
-    }
+    address->active = GNUNET_NO;
+    ril_get_new_address_or_delete (s, agent);
   }
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -1142,7 +1266,7 @@ GAS_ril_address_property_changed (void *solver,
     double rel_value)
 {
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-      "API_address_property_changed() Property `%s' for peer `%s' address %p changed "
+      "API_address_property_changed() Property '%s' for peer '%s' address %p changed "
           "to %.2f \n", GNUNET_ATS_print_property_type (type),
       GNUNET_i2s (&address->peer), address, rel_value);
   /*
@@ -1219,25 +1343,26 @@ GAS_ril_address_change_network (void *solver,
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
       "API_address_change_network() Network type changed, moving "
-          "%s address of peer %s from `%s' to `%s'\n",
+          "%s address of peer %s from '%s' to '%s'\n",
       (GNUNET_YES == address->active) ? "active" : "inactive",
       GNUNET_i2s (&address->peer),
       GNUNET_ATS_print_network_type (current_network),
       GNUNET_ATS_print_network_type (new_network));
 
-  address->solver_information = ril_get_network(solver, new_network);
+  address->solver_information = ril_get_network (solver, new_network);
 
   if (address->active)
   {
-    agent = ril_get_agent(solver, &address->peer, GNUNET_NO);
+    agent = ril_get_agent (solver, &address->peer, GNUNET_NO);
 
     //remove from old network
     net = ril_get_network (s, current_network);
     net->bw_in_assigned -= agent->bw_in;
     net->bw_out_assigned -= agent->bw_out;
 
-    if (ril_network_is_active(ril_get_network(s, new_network)))
+    if (ril_network_is_active (ril_get_network (s, new_network)))
     {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New network is active\n");
       //add to new network
       net = ril_get_network (s, new_network);
       net->bw_in_assigned += agent->bw_in;
@@ -1249,15 +1374,18 @@ GAS_ril_address_change_network (void *solver,
     }
     else //new network for this address is not active => address must not be considered
     {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New network is not active\n");
+
+      net = agent->address->solver_information;
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Before: active address %p is %s\n",
+          agent->address, GNUNET_ATS_print_network_type (net->type));
+
       address->active = GNUNET_NO;
-      agent->address = NULL; //delete address
-          GNUNET_CONTAINER_multihashmap_iterate (s->addresses, &ril_init_agents_it,
-              solver); //put another address
-      if (NULL == agent->address) //no other address available
-      {
-        agent->active = GNUNET_NO;
-        ril_remove_agent(s, agent);
-      }
+      ril_get_new_address_or_delete (s, agent);
+
+      net = agent->address->solver_information;
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "After: active address %p is %s\n",
+          agent->address, GNUNET_ATS_print_network_type (net->type));
     }
   }
 }
@@ -1281,7 +1409,6 @@ GAS_ril_address_preference_feedback (void *solver,
     double score)
 {
   //TODO! collect reward until next reward calculation
-  //TODO! Find out application
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
       "API_address_preference_feedback() Peer '%s' got a feedback of %+.3f from application %s for "
           "preference %s for %d seconds\n", GNUNET_i2s (peer), "UNKNOWN",
@@ -1340,7 +1467,10 @@ GAS_ril_get_preferred_address (void *solver,
 
   if (NULL == agent)
   {
-    return NULL;
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+        "API_get_preferred_address() No agent for peer '%s' do not suggest address\n",
+        GNUNET_i2s (peer));
+    return NULL ;
   }
 
   agent->active = GNUNET_YES;