added simulation
[oweals/gnunet.git] / src / ats / libgnunet_plugin_ats_mlp.c
index 02bf1828761ad274b8f399e1b73131d2e7de1e4e..07f77161fcfa137608d47a84a4650a709c10fd99 100644 (file)
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file ats/gnunet-service-ats-solver_mlp.c
+ * @file ats/libgnunet_plugin_ats_mlp.c
  * @brief ats mlp problem solver
  * @author Matthias Wachs
  * @author Christian Grothoff
@@ -255,10 +255,14 @@ mlp_ats_to_string (int ats_index)
   switch (ats_index) {
     case GNUNET_ATS_ARRAY_TERMINATOR:
       return "GNUNET_ATS_ARRAY_TERMINATOR";
-    case GNUNET_ATS_UTILIZATION_UP:
-      return "GNUNET_ATS_UTILIZATION_UP";
-    case GNUNET_ATS_UTILIZATION_DOWN:
-      return "GNUNET_ATS_UTILIZATION_DOWN";
+    case GNUNET_ATS_UTILIZATION_OUT:
+      return "GNUNET_ATS_UTILIZATION_OUT";
+    case GNUNET_ATS_UTILIZATION_IN:
+      return "GNUNET_ATS_UTILIZATION_IN";
+    case GNUNET_ATS_UTILIZATION_PAYLOAD_OUT:
+      return "GNUNET_ATS_UTILIZATION_PAYLOAD_OUT";
+    case GNUNET_ATS_UTILIZATION_PAYLOAD_IN:
+      return "GNUNET_ATS_UTILIZATION_PAYLOAD_IN";
     case GNUNET_ATS_COST_LAN:
       return "GNUNET_ATS_COST_LAN";
     case GNUNET_ATS_COST_WAN:
@@ -1073,6 +1077,14 @@ mlp_propagate_results (void *cls,
   return GNUNET_OK;
 }
 
+static void notify (struct GAS_MLP_Handle *mlp,
+    enum GAS_Solver_Operation op,
+    enum GAS_Solver_Status stat,
+    enum GAS_Solver_Additional_Information add)
+{
+  if (NULL != mlp->env->info_cb)
+    mlp->env->info_cb (mlp->env->info_cb_cls, op, stat, add);
+}
 /**
  * Solves the MLP problem
  *
@@ -1086,107 +1098,144 @@ GAS_mlp_solve_problem (void *solver)
   char *filename;
   int res_lp = 0;
   int res_mip = 0;
-  struct GNUNET_TIME_Absolute start_build;
-  struct GNUNET_TIME_Relative duration_build;
-  struct GNUNET_TIME_Absolute start_lp;
-  struct GNUNET_TIME_Relative duration_lp;
-  struct GNUNET_TIME_Absolute start_mlp;
-  struct GNUNET_TIME_Relative duration_mlp;
-  GNUNET_assert (NULL != solver);
+
+  struct GNUNET_TIME_Absolute start;
+  struct GNUNET_TIME_Relative dur_total;
+  struct GNUNET_TIME_Relative dur_setup;
+  struct GNUNET_TIME_Relative dur_lp;
+  struct GNUNET_TIME_Relative dur_mlp;
+
+  GNUNET_assert(NULL != solver);
 
   if (GNUNET_YES == mlp->bulk_lock)
-  {
-    mlp->bulk_request ++;
-    return GNUNET_NO;
-  }
+    {
+      mlp->bulk_request++;
+      return GNUNET_NO;
+    }
+  notify(mlp, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS,
+      (GNUNET_YES == mlp->mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED);
+  start = GNUNET_TIME_absolute_get();
 
-  if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->requested_peers))
-    return GNUNET_OK; /* No pending requests */
-  if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->addresses))
-    return GNUNET_OK; /* No addresses available */
+  if (0 == GNUNET_CONTAINER_multipeermap_size(mlp->requested_peers))
+    {
+      notify(mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE);
+      return GNUNET_OK; /* No pending requests */
+    }
+  if (0 == GNUNET_CONTAINER_multipeermap_size(mlp->addresses))
+    {
+      notify(mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE);
+      return GNUNET_OK; /* No addresses available */
+    }
 
-  if ((GNUNET_NO == mlp->mlp_prob_changed) && (GNUNET_NO == mlp->mlp_prob_updated))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n");
-    return GNUNET_OK;
-  }
+  if ((GNUNET_NO == mlp->mlp_prob_changed)
+      && (GNUNET_NO == mlp->mlp_prob_updated))
+    {
+      LOG(GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n");
+      notify(mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE);
+      return GNUNET_OK;
+    }
   if (GNUNET_YES == mlp->mlp_prob_changed)
-  {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n");
-      mlp_delete_problem (mlp);
-      start_build = GNUNET_TIME_absolute_get();
-      if (GNUNET_SYSERR == mlp_create_problem (mlp))
-        return GNUNET_SYSERR;
-      duration_build = GNUNET_TIME_absolute_get_duration (start_build);
+    {
+      LOG(GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n");
+      notify(mlp, GAS_OP_SOLVE_SETUP_START, GAS_STAT_SUCCESS, GAS_INFO_FULL);
+      mlp_delete_problem(mlp);
+      if (GNUNET_SYSERR == mlp_create_problem(mlp))
+        {
+          notify(mlp, GAS_OP_SOLVE_SETUP_STOP, GAS_STAT_FAIL, GAS_INFO_FULL);
+          return GNUNET_SYSERR;
+        }
+      notify(mlp, GAS_OP_SOLVE_SETUP_STOP, GAS_STAT_SUCCESS, GAS_INFO_FULL);
       mlp->control_param_lp.presolve = GLP_YES;
       mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP solution */
-  }
+    }
   else
-  {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
-      duration_build.rel_value_us = 0;
-  }
+    {
+      LOG(GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
+    }
 
+  dur_setup = GNUNET_TIME_absolute_get_duration (start);
+  mlp->control_param_lp.presolve = GLP_YES;
   /* Run LP solver */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running LP solver %s\n",
+
+  notify(mlp, GAS_OP_SOLVE_MLP_LP_START, GAS_STAT_SUCCESS,
+      (GNUNET_YES == mlp->mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED);
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "Running LP solver %s\n",
       (GLP_YES == mlp->control_param_lp.presolve)? "with presolver": "without presolver");
-  start_lp = GNUNET_TIME_absolute_get();
-  res_lp = mlp_solve_lp_problem (mlp);
-  duration_lp = GNUNET_TIME_absolute_get_duration (start_lp);
+  res_lp = mlp_solve_lp_problem(mlp);
+  notify(mlp, GAS_OP_SOLVE_MLP_LP_STOP,
+      (GNUNET_OK == res_lp) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
+      (GNUNET_YES == mlp->mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED);
 
+  dur_lp = GNUNET_TIME_absolute_get_duration (start);
+  dur_lp = GNUNET_TIME_relative_subtract(dur_lp, dur_setup);
 
   /* Run MLP solver */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n");
-  start_mlp = GNUNET_TIME_absolute_get();
-  res_mip = mlp_solve_mlp_problem (mlp);
+  LOG(GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n");
+  notify(mlp, GAS_OP_SOLVE_MLP_MLP_START, GAS_STAT_SUCCESS,
+      (GNUNET_YES == mlp->mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED);
+  res_mip = mlp_solve_mlp_problem(mlp);
+  notify(mlp, GAS_OP_SOLVE_MLP_MLP_STOP,
+      (GNUNET_OK == res_lp) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
+      (GNUNET_YES == mlp->mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED);
+  notify(mlp, GAS_OP_SOLVE_STOP,
+      (GNUNET_OK == res_mip) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
+      (GNUNET_YES == mlp->mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED);
+
+  dur_mlp = GNUNET_TIME_absolute_get_duration (start);
+  dur_mlp = GNUNET_TIME_relative_subtract(dur_mlp, dur_setup);
+  dur_mlp = GNUNET_TIME_relative_subtract(dur_mlp, dur_lp);
+  dur_total = GNUNET_TIME_absolute_get_duration (start);
 
-  duration_mlp = GNUNET_TIME_absolute_get_duration (start_mlp);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+      "Execution time for %s solve: (total/setup/lp/mlp) : %llu %llu %llu %llu\n",
+      (GNUNET_YES == mlp->mlp_prob_changed) ? "full" : "updated",
+      (unsigned long long) dur_total.rel_value_us,
+      (unsigned long long) dur_setup.rel_value_us,
+      (unsigned long long) dur_lp.rel_value_us,
+      (unsigned long long) dur_mlp.rel_value_us);
 
   /* Save stats */
   mlp->ps.lp_res = res_lp;
   mlp->ps.mip_res = res_mip;
-  mlp->ps.build_dur = duration_build;
-  mlp->ps.lp_dur = duration_lp;
-  mlp->ps.mip_dur = duration_mlp;
   mlp->ps.lp_presolv = mlp->control_param_lp.presolve;
   mlp->ps.mip_presolv = mlp->control_param_mlp.presolve;
-  mlp->ps.p_cols = glp_get_num_cols (mlp->p.prob);
-  mlp->ps.p_rows = glp_get_num_rows (mlp->p.prob);
+  mlp->ps.p_cols = glp_get_num_cols(mlp->p.prob);
+  mlp->ps.p_rows = glp_get_num_rows(mlp->p.prob);
   mlp->ps.p_elements = mlp->p.num_elements;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Execution time: Build %s\n",
-       GNUNET_STRINGS_relative_time_to_string (duration_build, GNUNET_NO));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Execution time: LP %s\n",
-       GNUNET_STRINGS_relative_time_to_string (duration_lp, GNUNET_NO));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Execution time: MLP %s\n",
-       GNUNET_STRINGS_relative_time_to_string (duration_mlp, GNUNET_NO));
-
   /* Propagate result*/
+  notify(mlp, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START,
+      (GNUNET_OK == res_lp) && (GNUNET_OK == res_mip) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
+      GAS_INFO_NONE);
   if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip))
-  {
-    GNUNET_CONTAINER_multipeermap_iterate (mlp->addresses, &mlp_propagate_results, mlp);
-  }
+    {
+      GNUNET_CONTAINER_multipeermap_iterate(mlp->addresses,
+          &mlp_propagate_results, mlp);
+    }
+  notify(mlp, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP,
+      (GNUNET_OK == res_lp) && (GNUNET_OK == res_mip) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
+      GAS_INFO_NONE);
 
   struct GNUNET_TIME_Absolute time = GNUNET_TIME_absolute_get();
   if (GNUNET_YES == mlp->write_mip_mps)
-  {
-    /* Write problem to disk */
-    GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers, mlp->p.num_addresses, time.abs_value_us);
-    LOG (GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
-    glp_write_lp(mlp->p.prob, NULL, filename);
-    GNUNET_free (filename);
-  }
+    {
+      /* Write problem to disk */
+      GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers,
+          mlp->p.num_addresses, time.abs_value_us);
+      LOG(GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
+      glp_write_lp(mlp->p.prob, NULL, filename);
+      GNUNET_free(filename);
+    }
   if (GNUNET_YES == mlp->write_mip_sol)
-  {
-    /* Write solution to disk */
-    GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers, mlp->p.num_addresses, time.abs_value_us);
-    glp_print_mip (mlp->p.prob, filename );
-    LOG (GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
-    GNUNET_free (filename);
-  }
+    {
+      /* Write solution to disk */
+      GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers,
+          mlp->p.num_addresses, time.abs_value_us);
+      glp_print_mip(mlp->p.prob, filename);
+      LOG(GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
+      GNUNET_free(filename);
+    }
 
   /* Reset change and update marker */
   mlp->control_param_lp.presolve = GLP_NO;
@@ -1217,6 +1266,12 @@ GAS_mlp_address_add (void *solver,
   GNUNET_assert (NULL != solver);
   GNUNET_assert (NULL != address);
 
+  if (GNUNET_ATS_NetworkTypeCount <= network)
+  {
+   GNUNET_break (0);
+   return;
+  }
+
   if (NULL == address->solver_information)
   {
       address->solver_information = GNUNET_new (struct MLP_information);
@@ -1380,6 +1435,12 @@ GAS_mlp_address_change_network (void *solver,
   GNUNET_assert (NULL != solver);
   GNUNET_assert (NULL != address);
 
+  if (GNUNET_ATS_NetworkTypeCount <= new_network)
+  {
+   GNUNET_break (0);
+   return;
+  }
+
   if (NULL == mlpi)
   {
     GNUNET_break (0);
@@ -1739,8 +1800,9 @@ GAS_mlp_address_change_preference (void *solver,
     return;
   }
   p->f = get_peer_pref_value (mlp, peer);
+  /*
   LOG (GNUNET_ERROR_TYPE_ERROR, "PEER PREF: %s %.2f\n",
-      GNUNET_i2s(peer), p->f);
+      GNUNET_i2s(peer), p->f);*/
   mlp_create_problem_update_value (&mlp->p, p->r_c9, mlp->p.c_r, -p->f, __LINE__);
 
   /* Problem size changed: new address for peer with pending request */
@@ -1794,7 +1856,8 @@ mlp_free_peers (void *cls,
 /**
  * Shutdown the MLP problem solving component
  *
- * @param solver the solver handle
+ * @param cls the solver handle
+ * @return NULL
  */
 void *
 libgnunet_plugin_ats_mlp_done (void *cls)
@@ -1843,8 +1906,8 @@ libgnunet_plugin_ats_mlp_init (void *cls)
   GNUNET_assert (NULL != env->stats);
   GNUNET_assert (NULL != env->addresses);
   GNUNET_assert (NULL != env->bandwidth_changed_cb);
-  GNUNET_assert (NULL != env->get_preferences_cb);
-  GNUNET_assert (NULL != env->get_property_cb);
+  GNUNET_assert (NULL != env->get_preferences);
+  GNUNET_assert (NULL != env->get_property);
 
   /* Init GLPK environment */
   int res = glp_init_env();
@@ -2056,9 +2119,9 @@ libgnunet_plugin_ats_mlp_init (void *cls)
   mlp->addresses = env->addresses;
   mlp->bw_changed_cb = env->bandwidth_changed_cb;
   mlp->bw_changed_cb_cls = env->bw_changed_cb_cls;
-  mlp->get_preferences =  env->get_preferences_cb;
+  mlp->get_preferences =  env->get_preferences;
   mlp->get_preferences_cls = env->get_preference_cls;
-  mlp->get_properties = env->get_property_cb;
+  mlp->get_properties = env->get_property;
   mlp->get_properties_cls = env->get_property_cls;
   /* Setting MLP Input variables */