[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r26169 - gnunet/src/ats
From: |
gnunet |
Subject: |
[GNUnet-SVN] r26169 - gnunet/src/ats |
Date: |
Wed, 20 Feb 2013 18:53:31 +0100 |
Author: wachs
Date: 2013-02-20 18:53:31 +0100 (Wed, 20 Feb 2013)
New Revision: 26169
Modified:
gnunet/src/ats/gnunet-service-ats_addresses_mlp.c
gnunet/src/ats/gnunet-service-ats_addresses_mlp.h
Log:
changes
Modified: gnunet/src/ats/gnunet-service-ats_addresses_mlp.c
===================================================================
--- gnunet/src/ats/gnunet-service-ats_addresses_mlp.c 2013-02-20 16:24:28 UTC
(rev 26168)
+++ gnunet/src/ats/gnunet-service-ats_addresses_mlp.c 2013-02-20 17:53:31 UTC
(rev 26169)
@@ -137,9 +137,8 @@
#define WRITE_MLP GNUNET_NO
#define DEBUG_ATS GNUNET_NO
-#define VERBOSE_GLPK GNUNET_YES
+#define VERBOSE_GLPK GNUNET_NO
-
/**
* Intercept GLPK terminal output
* @param info the mlp handle
@@ -150,10 +149,13 @@
mlp_term_hook (void *info, const char *s)
{
/* Not needed atm struct MLP_information *mlp = info; */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s", s);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%s", s);
return 1;
}
+
+
+
/**
* Delete the MLP problem and free the constrain matrix
*
@@ -193,6 +195,41 @@
}
+/**
+ * Translate ATS properties to text
+ * Just intended for debugging
+ *
+ * @param ats_index the ATS index
+ * @return string with result
+ */
+const char *
+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_COST_LAN:
+ return "GNUNET_ATS_COST_LAN";
+ case GNUNET_ATS_COST_WAN:
+ return "GNUNET_ATS_COST_LAN";
+ case GNUNET_ATS_COST_WLAN:
+ return "GNUNET_ATS_COST_WLAN";
+ case GNUNET_ATS_NETWORK_TYPE:
+ return "GNUNET_ATS_NETWORK_TYPE";
+ case GNUNET_ATS_QUALITY_NET_DELAY:
+ return "GNUNET_ATS_QUALITY_NET_DELAY";
+ case GNUNET_ATS_QUALITY_NET_DISTANCE:
+ return "GNUNET_ATS_QUALITY_NET_DISTANCE";
+ default:
+ GNUNET_break (0);
+ return "unknown";
+ }
+}
+
#if 0
/**
@@ -276,40 +313,6 @@
}
}
-/**
- * Translate ATS properties to text
- * Just intended for debugging
- *
- * @param ats_index the ATS index
- * @return string with result
- */
-const char *
-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_COST_LAN:
- return "GNUNET_ATS_COST_LAN";
- case GNUNET_ATS_COST_WAN:
- return "GNUNET_ATS_COST_LAN";
- case GNUNET_ATS_COST_WLAN:
- return "GNUNET_ATS_COST_WLAN";
- case GNUNET_ATS_NETWORK_TYPE:
- return "GNUNET_ATS_NETWORK_TYPE";
- case GNUNET_ATS_QUALITY_NET_DELAY:
- return "GNUNET_ATS_QUALITY_NET_DELAY";
- case GNUNET_ATS_QUALITY_NET_DISTANCE:
- return "GNUNET_ATS_QUALITY_NET_DISTANCE";
- default:
- GNUNET_break (0);
- return "unknown";
- }
-}
/**
* Find a peer in the DLL
@@ -332,7 +335,391 @@
}
+
+#if 0
/**
+ * Find the required ATS information for an address
+ *
+ * @param addr the address
+ * @param ats_index the desired ATS index
+ *
+ * @return the index on success, otherwise GNUNET_SYSERR
+ */
+static int
+mlp_lookup_ats (struct ATS_Address *addr, int ats_index)
+{
+ struct GNUNET_ATS_Information * ats = addr->ats;
+ int c = 0;
+ int found = GNUNET_NO;
+ for (c = 0; c < addr->ats_count; c++)
+ {
+ if (ats[c].type == ats_index)
+ {
+ found = GNUNET_YES;
+ break;
+ }
+ }
+ if (found == GNUNET_YES)
+ return c;
+ else
+ return GNUNET_SYSERR;
+}
+#endif
+
+/**
+ * Solves the LP problem
+ *
+ * @param mlp the MLP Handle
+ * @param s_ctx context to return results
+ * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
+ */
+static int
+mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp, struct
GAS_MLP_SolutionContext *s_ctx)
+{
+ int res;
+ struct GNUNET_TIME_Relative duration;
+ struct GNUNET_TIME_Absolute end;
+ struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get();
+
+ /* LP presolver?
+ * Presolver is required if the problem was modified and an existing
+ * valid basis is now invalid */
+ if (mlp->presolver_required == GNUNET_YES)
+ mlp->control_param_lp.presolve = GLP_ON;
+ else
+ mlp->control_param_lp.presolve = GLP_OFF;
+
+ /* Solve LP problem to have initial valid solution */
+lp_solv:
+ res = glp_simplex(mlp->prob, &mlp->control_param_lp);
+ if (res == 0)
+ {
+ /* The LP problem instance has been successfully solved. */
+ }
+ else if (res == GLP_EITLIM)
+ {
+ /* simplex iteration limit has been exceeded. */
+ // TODO Increase iteration limit?
+ }
+ else if (res == GLP_ETMLIM)
+ {
+ /* Time limit has been exceeded. */
+ // TODO Increase time limit?
+ }
+ else
+ {
+ /* Problem was ill-defined, retry with presolver */
+ if (mlp->presolver_required == GNUNET_NO)
+ {
+ mlp->presolver_required = GNUNET_YES;
+ goto lp_solv;
+ }
+ else
+ {
+ /* Problem was ill-defined, no way to handle that */
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "ats-mlp",
+ "Solving LP problem failed: %i %s\n", res, mlp_solve_to_string(res));
+ return GNUNET_SYSERR;
+ }
+ }
+
+ end = GNUNET_TIME_absolute_get ();
+ duration = GNUNET_TIME_absolute_get_difference (start, end);
+ mlp->lp_solved++;
+ mlp->lp_total_duration += duration.rel_value;
+ s_ctx->lp_duration = duration;
+
+ GNUNET_STATISTICS_update (mlp->stats,"# LP problem solved", 1, GNUNET_NO);
+ GNUNET_STATISTICS_set (mlp->stats,"# LP execution time (ms)",
duration.rel_value, GNUNET_NO);
+ GNUNET_STATISTICS_set (mlp->stats,"# LP execution time average (ms)",
+ mlp->lp_total_duration / mlp->lp_solved, GNUNET_NO);
+
+ /* Analyze problem status */
+ res = glp_get_status (mlp->prob);
+ switch (res) {
+ /* solution is optimal */
+ case GLP_OPT:
+ /* solution is feasible */
+ case GLP_FEAS:
+ break;
+
+ /* Problem was ill-defined, no way to handle that */
+ default:
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "ats-mlp",
+ "Solving LP problem failed, no solution: %s\n",
mlp_status_to_string(res));
+ return GNUNET_SYSERR;
+ break;
+ }
+
+ /* solved sucessfully, no presolver required next time */
+ mlp->presolver_required = GNUNET_NO;
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Solves the MLP problem
+ *
+ * @param mlp the MLP Handle
+ * @param s_ctx context to return results
+ * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
+ */
+int
+mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp, struct
GAS_MLP_SolutionContext *s_ctx)
+{
+ int res;
+ struct GNUNET_TIME_Relative duration;
+ struct GNUNET_TIME_Absolute end;
+ struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get();
+
+ /* solve MLP problem */
+ res = glp_intopt(mlp->prob, &mlp->control_param_mlp);
+
+ if (res == 0)
+ {
+ /* The MLP problem instance has been successfully solved. */
+ }
+ else if (res == GLP_EITLIM)
+ {
+ /* simplex iteration limit has been exceeded. */
+ // TODO Increase iteration limit?
+ }
+ else if (res == GLP_ETMLIM)
+ {
+ /* Time limit has been exceeded. */
+ // TODO Increase time limit?
+ }
+ else
+ {
+ /* Problem was ill-defined, no way to handle that */
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "ats-mlp",
+ "Solving MLP problem failed: %s\n", mlp_solve_to_string(res));
+ return GNUNET_SYSERR;
+ }
+
+ end = GNUNET_TIME_absolute_get ();
+ duration = GNUNET_TIME_absolute_get_difference (start, end);
+ mlp->mlp_solved++;
+ mlp->mlp_total_duration += duration.rel_value;
+ s_ctx->mlp_duration = duration;
+
+ GNUNET_STATISTICS_update (mlp->stats,"# MLP problem solved", 1, GNUNET_NO);
+ GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time (ms)",
duration.rel_value, GNUNET_NO);
+ GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time average (ms)",
+ mlp->mlp_total_duration / mlp->mlp_solved,
GNUNET_NO);
+
+ /* Analyze problem status */
+ res = glp_mip_status(mlp->prob);
+ switch (res) {
+ /* solution is optimal */
+ case GLP_OPT:
+ /* solution is feasible */
+ case GLP_FEAS:
+ break;
+
+ /* Problem was ill-defined, no way to handle that */
+ default:
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "ats-mlp",
+ "Solving MLP problem failed, %s\n\n", mlp_status_to_string(res));
+ return GNUNET_SYSERR;
+ break;
+ }
+
+ return GNUNET_OK;
+}
+
+int GAS_mlp_solve_problem (void *solver, struct GAS_MLP_SolutionContext *ctx);
+
+
+static void
+mlp_scheduler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GAS_MLP_Handle *mlp = cls;
+ struct GAS_MLP_SolutionContext ctx;
+
+ mlp->mlp_task = GNUNET_SCHEDULER_NO_TASK;
+
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduled problem solving\n");
+
+ if (mlp->addr_in_problem != 0)
+ GAS_mlp_solve_problem(mlp, &ctx);
+}
+
+
+
+
+static void
+update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating quality metrics for peer
`%s'\n",
+ GNUNET_i2s (&address->peer));
+
+ GNUNET_assert (NULL != address);
+ GNUNET_assert (NULL != address->solver_information);
+// GNUNET_assert (NULL != address->ats);
+
+ struct MLP_information *mlpi = address->solver_information;
+ //struct GNUNET_ATS_Information *ats = address->ats;
+ GNUNET_assert (mlpi != NULL);
+
+ int c;
+ for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
+ {
+
+ /* FIXME int index = mlp_lookup_ats(address, mlp->q[c]); */
+ int index = GNUNET_SYSERR;
+
+ if (index == GNUNET_SYSERR)
+ continue;
+ /* FIXME
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' value
`%s': %f\n",
+ GNUNET_i2s (&address->peer),
+ mlp_ats_to_string(mlp->q[c]),
+ (double) ats[index].value);
+
+ int i = mlpi->q_avg_i[c];*/
+ double * qp = mlpi->q[c];
+ /* FIXME
+ qp[i] = (double) ats[index].value;
+ */
+
+ int t;
+ for (t = 0; t < MLP_AVERAGING_QUEUE_LENGTH; t++)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': `%s' queue[%u]: %f\n",
+ GNUNET_i2s (&address->peer),
+ mlp_ats_to_string(mlp->q[c]),
+ t,
+ qp[t]);
+ }
+
+ if (mlpi->q_avg_i[c] + 1 < (MLP_AVERAGING_QUEUE_LENGTH))
+ mlpi->q_avg_i[c] ++;
+ else
+ mlpi->q_avg_i[c] = 0;
+
+
+ int c2;
+ int c3;
+ double avg = 0.0;
+ switch (mlp->q[c])
+ {
+ case GNUNET_ATS_QUALITY_NET_DELAY:
+ c3 = 0;
+ for (c2 = 0; c2 < MLP_AVERAGING_QUEUE_LENGTH; c2++)
+ {
+ if (mlpi->q[c][c2] != -1)
+ {
+ double * t2 = mlpi->q[c] ;
+ avg += t2[c2];
+ c3 ++;
+ }
+ }
+ if ((c3 > 0) && (avg > 0))
+ /* avg = 1 / ((q[0] + ... + q[l]) /c3) => c3 / avg*/
+ mlpi->q_averaged[c] = (double) c3 / avg;
+ else
+ mlpi->q_averaged[c] = 0.0;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': `%s' average sum: %f,
average: %f, weight: %f\n",
+ GNUNET_i2s (&address->peer),
+ mlp_ats_to_string(mlp->q[c]),
+ avg,
+ avg / (double) c3,
+ mlpi->q_averaged[c]);
+
+ break;
+ case GNUNET_ATS_QUALITY_NET_DISTANCE:
+ c3 = 0;
+ for (c2 = 0; c2 < MLP_AVERAGING_QUEUE_LENGTH; c2++)
+ {
+ if (mlpi->q[c][c2] != -1)
+ {
+ double * t2 = mlpi->q[c] ;
+ avg += t2[c2];
+ c3 ++;
+ }
+ }
+ if ((c3 > 0) && (avg > 0))
+ /* avg = 1 / ((q[0] + ... + q[l]) /c3) => c3 / avg*/
+ mlpi->q_averaged[c] = (double) c3 / avg;
+ else
+ mlpi->q_averaged[c] = 0.0;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': `%s' average sum: %f,
average: %f, weight: %f\n",
+ GNUNET_i2s (&address->peer),
+ mlp_ats_to_string(mlp->q[c]),
+ avg,
+ avg / (double) c3,
+ mlpi->q_averaged[c]);
+
+ break;
+ default:
+ break;
+ }
+
+ if ((mlpi->c_b != 0) && (mlpi->r_q[c] != 0))
+ {
+
+ /* Get current number of columns */
+ int found = GNUNET_NO;
+ int cols = glp_get_num_cols(mlp->prob);
+ int *ind = GNUNET_malloc (cols * sizeof (int) + 1);
+ double *val = GNUNET_malloc (cols * sizeof (double) + 1);
+
+ /* Get the matrix row of quality */
+ int length = glp_get_mat_row(mlp->prob, mlp->r_q[c], ind, val);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "cols %i, length %i c_b %i\n",
cols, length, mlpi->c_b);
+ int c4;
+ /* Get the index if matrix row of quality */
+ for (c4 = 1; c4 <= length; c4++ )
+ {
+ if (mlpi->c_b == ind[c4])
+ {
+ /* Update the value */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating quality `%s' column
`%s' row `%s' : %f -> %f\n",
+ mlp_ats_to_string(mlp->q[c]),
+ glp_get_col_name (mlp->prob, ind[c4]),
+ glp_get_row_name (mlp->prob, mlp->r_q[c]),
+ val[c4],
+ mlpi->q_averaged[c]);
+ val[c4] = mlpi->q_averaged[c];
+ found = GNUNET_YES;
+ break;
+ }
+ }
+
+ if (found == GNUNET_NO)
+ {
+
+ ind[length+1] = mlpi->c_b;
+ val[length+1] = mlpi->q_averaged[c];
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%i ind[%i] val[%i]: %i %f\n",
length+1, length+1, length+1, mlpi->c_b, mlpi->q_averaged[c]);
+ glp_set_mat_row (mlp->prob, mlpi->r_q[c], length+1, ind, val);
+ }
+ else
+ {
+ /* Get the index if matrix row of quality */
+ glp_set_mat_row (mlp->prob, mlpi->r_q[c], length, ind, val);
+ }
+
+ GNUNET_free (ind);
+ GNUNET_free (val);
+ }
+ }
+}
+
+#endif
+
+/**
* Add constraints that are iterating over "forall addresses"
* and collects all existing peers for "forall peers" constraints
*
@@ -444,35 +831,6 @@
return GNUNET_OK;
}
-#if 0
-/**
- * Find the required ATS information for an address
- *
- * @param addr the address
- * @param ats_index the desired ATS index
- *
- * @return the index on success, otherwise GNUNET_SYSERR
- */
-static int
-mlp_lookup_ats (struct ATS_Address *addr, int ats_index)
-{
- struct GNUNET_ATS_Information * ats = addr->ats;
- int c = 0;
- int found = GNUNET_NO;
- for (c = 0; c < addr->ats_count; c++)
- {
- if (ats[c].type == ats_index)
- {
- found = GNUNET_YES;
- break;
- }
- }
- if (found == GNUNET_YES)
- return c;
- else
- return GNUNET_SYSERR;
-}
-#endif
/**
* Adds the problem constraints for all addresses
@@ -648,7 +1006,6 @@
glp_set_row_bnds (mlp->prob, peer->r_c2, GLP_FX, 1.0, 1.0);
/* Adding rows for c 9) */
-#if ENABLE_C9
peer->r_c9 = glp_add_rows (mlp->prob, 1);
GNUNET_asprintf(&name, "c9_%s", GNUNET_i2s(&peer->id));
glp_set_row_name (mlp->prob, peer->r_c9, name);
@@ -661,7 +1018,7 @@
ja[mlp->ci] = mlp->c_r;
ar[mlp->ci] = -peer->f;
mlp->ci++;
-#endif
+
/* For all addresses of this peer */
while (addr != NULL)
{
@@ -740,7 +1097,7 @@
* @return GNUNET_OK to continue
*/
static int
-create_columns_it (void *cls, const struct GNUNET_HashCode * key, void *value)
+mlp_create_address_columns_it (void *cls, const struct GNUNET_HashCode * key,
void *value)
{
struct GAS_MLP_Handle *mlp = cls;
struct ATS_Address *address = value;
@@ -748,9 +1105,22 @@
unsigned int col;
char *name;
- GNUNET_assert (address->solver_information != NULL);
- mlpi = address->solver_information;
+ if (NULL != address->solver_information)
+ {
+ GNUNET_free (address->solver_information);
+ address->solver_information = NULL;
+ }
+ /* Check if we have to add this peer due to a pending request */
+ if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(mlp->peers, key))
+ return GNUNET_OK;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding column for peer %s address %p\n",
+ GNUNET_i2s(&address->peer), address);
+
+ mlpi = GNUNET_malloc (sizeof (struct MLP_information));
+ address->solver_information = mlpi;
+
/* Add bandwidth column */
col = glp_add_cols (mlp->prob, 2);
mlpi->c_b = col;
@@ -782,362 +1152,7 @@
return GNUNET_OK;
}
-
-
/**
- * Solves the LP problem
- *
- * @param mlp the MLP Handle
- * @param s_ctx context to return results
- * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
- */
-static int
-mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp, struct
GAS_MLP_SolutionContext *s_ctx)
-{
- int res;
- struct GNUNET_TIME_Relative duration;
- struct GNUNET_TIME_Absolute end;
- struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get();
-
- /* LP presolver?
- * Presolver is required if the problem was modified and an existing
- * valid basis is now invalid */
- if (mlp->presolver_required == GNUNET_YES)
- mlp->control_param_lp.presolve = GLP_ON;
- else
- mlp->control_param_lp.presolve = GLP_OFF;
-
- /* Solve LP problem to have initial valid solution */
-lp_solv:
- res = glp_simplex(mlp->prob, &mlp->control_param_lp);
- if (res == 0)
- {
- /* The LP problem instance has been successfully solved. */
- }
- else if (res == GLP_EITLIM)
- {
- /* simplex iteration limit has been exceeded. */
- // TODO Increase iteration limit?
- }
- else if (res == GLP_ETMLIM)
- {
- /* Time limit has been exceeded. */
- // TODO Increase time limit?
- }
- else
- {
- /* Problem was ill-defined, retry with presolver */
- if (mlp->presolver_required == GNUNET_NO)
- {
- mlp->presolver_required = GNUNET_YES;
- goto lp_solv;
- }
- else
- {
- /* Problem was ill-defined, no way to handle that */
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "ats-mlp",
- "Solving LP problem failed: %i %s\n", res, mlp_solve_to_string(res));
- return GNUNET_SYSERR;
- }
- }
-
- end = GNUNET_TIME_absolute_get ();
- duration = GNUNET_TIME_absolute_get_difference (start, end);
- mlp->lp_solved++;
- mlp->lp_total_duration += duration.rel_value;
- s_ctx->lp_duration = duration;
-
- GNUNET_STATISTICS_update (mlp->stats,"# LP problem solved", 1, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# LP execution time (ms)",
duration.rel_value, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# LP execution time average (ms)",
- mlp->lp_total_duration / mlp->lp_solved, GNUNET_NO);
-
- /* Analyze problem status */
- res = glp_get_status (mlp->prob);
- switch (res) {
- /* solution is optimal */
- case GLP_OPT:
- /* solution is feasible */
- case GLP_FEAS:
- break;
-
- /* Problem was ill-defined, no way to handle that */
- default:
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "ats-mlp",
- "Solving LP problem failed, no solution: %s\n",
mlp_status_to_string(res));
- return GNUNET_SYSERR;
- break;
- }
-
- /* solved sucessfully, no presolver required next time */
- mlp->presolver_required = GNUNET_NO;
-
- return GNUNET_OK;
-}
-
-
-/**
- * Solves the MLP problem
- *
- * @param mlp the MLP Handle
- * @param s_ctx context to return results
- * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
- */
-int
-mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp, struct
GAS_MLP_SolutionContext *s_ctx)
-{
- int res;
- struct GNUNET_TIME_Relative duration;
- struct GNUNET_TIME_Absolute end;
- struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get();
-
- /* solve MLP problem */
- res = glp_intopt(mlp->prob, &mlp->control_param_mlp);
-
- if (res == 0)
- {
- /* The MLP problem instance has been successfully solved. */
- }
- else if (res == GLP_EITLIM)
- {
- /* simplex iteration limit has been exceeded. */
- // TODO Increase iteration limit?
- }
- else if (res == GLP_ETMLIM)
- {
- /* Time limit has been exceeded. */
- // TODO Increase time limit?
- }
- else
- {
- /* Problem was ill-defined, no way to handle that */
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "ats-mlp",
- "Solving MLP problem failed: %s\n", mlp_solve_to_string(res));
- return GNUNET_SYSERR;
- }
-
- end = GNUNET_TIME_absolute_get ();
- duration = GNUNET_TIME_absolute_get_difference (start, end);
- mlp->mlp_solved++;
- mlp->mlp_total_duration += duration.rel_value;
- s_ctx->mlp_duration = duration;
-
- GNUNET_STATISTICS_update (mlp->stats,"# MLP problem solved", 1, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time (ms)",
duration.rel_value, GNUNET_NO);
- GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time average (ms)",
- mlp->mlp_total_duration / mlp->mlp_solved,
GNUNET_NO);
-
- /* Analyze problem status */
- res = glp_mip_status(mlp->prob);
- switch (res) {
- /* solution is optimal */
- case GLP_OPT:
- /* solution is feasible */
- case GLP_FEAS:
- break;
-
- /* Problem was ill-defined, no way to handle that */
- default:
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
- "ats-mlp",
- "Solving MLP problem failed, %s\n\n", mlp_status_to_string(res));
- return GNUNET_SYSERR;
- break;
- }
-
- return GNUNET_OK;
-}
-
-int GAS_mlp_solve_problem (void *solver, struct GAS_MLP_SolutionContext *ctx);
-
-
-static void
-mlp_scheduler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct GAS_MLP_Handle *mlp = cls;
- struct GAS_MLP_SolutionContext ctx;
-
- mlp->mlp_task = GNUNET_SCHEDULER_NO_TASK;
-
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduled problem solving\n");
-
- if (mlp->addr_in_problem != 0)
- GAS_mlp_solve_problem(mlp, &ctx);
-}
-
-
-
-
-static void
-update_quality (struct GAS_MLP_Handle *mlp, struct ATS_Address * address)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating quality metrics for peer
`%s'\n",
- GNUNET_i2s (&address->peer));
-
- GNUNET_assert (NULL != address);
- GNUNET_assert (NULL != address->solver_information);
-// GNUNET_assert (NULL != address->ats);
-
- struct MLP_information *mlpi = address->solver_information;
- //struct GNUNET_ATS_Information *ats = address->ats;
- GNUNET_assert (mlpi != NULL);
-
- int c;
- for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
- {
-
- /* FIXME int index = mlp_lookup_ats(address, mlp->q[c]); */
- int index = GNUNET_SYSERR;
-
- if (index == GNUNET_SYSERR)
- continue;
- /* FIXME
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' value
`%s': %f\n",
- GNUNET_i2s (&address->peer),
- mlp_ats_to_string(mlp->q[c]),
- (double) ats[index].value);
-
- int i = mlpi->q_avg_i[c];*/
- double * qp = mlpi->q[c];
- /* FIXME
- qp[i] = (double) ats[index].value;
- */
-
- int t;
- for (t = 0; t < MLP_AVERAGING_QUEUE_LENGTH; t++)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': `%s' queue[%u]: %f\n",
- GNUNET_i2s (&address->peer),
- mlp_ats_to_string(mlp->q[c]),
- t,
- qp[t]);
- }
-
- if (mlpi->q_avg_i[c] + 1 < (MLP_AVERAGING_QUEUE_LENGTH))
- mlpi->q_avg_i[c] ++;
- else
- mlpi->q_avg_i[c] = 0;
-
-
- int c2;
- int c3;
- double avg = 0.0;
- switch (mlp->q[c])
- {
- case GNUNET_ATS_QUALITY_NET_DELAY:
- c3 = 0;
- for (c2 = 0; c2 < MLP_AVERAGING_QUEUE_LENGTH; c2++)
- {
- if (mlpi->q[c][c2] != -1)
- {
- double * t2 = mlpi->q[c] ;
- avg += t2[c2];
- c3 ++;
- }
- }
- if ((c3 > 0) && (avg > 0))
- /* avg = 1 / ((q[0] + ... + q[l]) /c3) => c3 / avg*/
- mlpi->q_averaged[c] = (double) c3 / avg;
- else
- mlpi->q_averaged[c] = 0.0;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': `%s' average sum: %f,
average: %f, weight: %f\n",
- GNUNET_i2s (&address->peer),
- mlp_ats_to_string(mlp->q[c]),
- avg,
- avg / (double) c3,
- mlpi->q_averaged[c]);
-
- break;
- case GNUNET_ATS_QUALITY_NET_DISTANCE:
- c3 = 0;
- for (c2 = 0; c2 < MLP_AVERAGING_QUEUE_LENGTH; c2++)
- {
- if (mlpi->q[c][c2] != -1)
- {
- double * t2 = mlpi->q[c] ;
- avg += t2[c2];
- c3 ++;
- }
- }
- if ((c3 > 0) && (avg > 0))
- /* avg = 1 / ((q[0] + ... + q[l]) /c3) => c3 / avg*/
- mlpi->q_averaged[c] = (double) c3 / avg;
- else
- mlpi->q_averaged[c] = 0.0;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': `%s' average sum: %f,
average: %f, weight: %f\n",
- GNUNET_i2s (&address->peer),
- mlp_ats_to_string(mlp->q[c]),
- avg,
- avg / (double) c3,
- mlpi->q_averaged[c]);
-
- break;
- default:
- break;
- }
-
- if ((mlpi->c_b != 0) && (mlpi->r_q[c] != 0))
- {
-
- /* Get current number of columns */
- int found = GNUNET_NO;
- int cols = glp_get_num_cols(mlp->prob);
- int *ind = GNUNET_malloc (cols * sizeof (int) + 1);
- double *val = GNUNET_malloc (cols * sizeof (double) + 1);
-
- /* Get the matrix row of quality */
- int length = glp_get_mat_row(mlp->prob, mlp->r_q[c], ind, val);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "cols %i, length %i c_b %i\n",
cols, length, mlpi->c_b);
- int c4;
- /* Get the index if matrix row of quality */
- for (c4 = 1; c4 <= length; c4++ )
- {
- if (mlpi->c_b == ind[c4])
- {
- /* Update the value */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating quality `%s' column
`%s' row `%s' : %f -> %f\n",
- mlp_ats_to_string(mlp->q[c]),
- glp_get_col_name (mlp->prob, ind[c4]),
- glp_get_row_name (mlp->prob, mlp->r_q[c]),
- val[c4],
- mlpi->q_averaged[c]);
- val[c4] = mlpi->q_averaged[c];
- found = GNUNET_YES;
- break;
- }
- }
-
- if (found == GNUNET_NO)
- {
-
- ind[length+1] = mlpi->c_b;
- val[length+1] = mlpi->q_averaged[c];
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%i ind[%i] val[%i]: %i %f\n",
length+1, length+1, length+1, mlpi->c_b, mlpi->q_averaged[c]);
- glp_set_mat_row (mlp->prob, mlpi->r_q[c], length+1, ind, val);
- }
- else
- {
- /* Get the index if matrix row of quality */
- glp_set_mat_row (mlp->prob, mlpi->r_q[c], length, ind, val);
- }
-
- GNUNET_free (ind);
- GNUNET_free (val);
- }
- }
-}
-
-#endif
-
-/**
* Create the MLP problem
*
* @param mlp the MLP handle
@@ -1211,10 +1226,10 @@
}
/* Add columns for addresses */
- //GNUNET_CONTAINER_multihashmap_iterate (addresses, create_columns_it, mlp);
+ GNUNET_CONTAINER_multihashmap_iterate (addresses,
mlp_create_address_columns_it, mlp);
/* Add constraints */
- //mlp_add_constraints_all_addresses (mlp, addresses);
+ mlp_add_constraints_all_addresses (mlp, addresses);
/* Load the matrix */
glp_load_matrix(mlp->prob, elements /*(mlp->ci-1)*/, mlp->ia, mlp->ja,
mlp->ar);
@@ -1227,11 +1242,11 @@
* Solves the MLP problem
*
* @param solver the MLP Handle
- * @param ctx solution context
+ * @param addresses the address hashmap
* @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
*/
int
-GAS_mlp_solve_problem (void *solver)
+GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap *
addresses)
{
struct GAS_MLP_Handle *mlp = solver;
int res = 0;
@@ -1248,7 +1263,7 @@
{
LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem size changed,
rebuilding\n");
mlp_delete_problem (mlp);
- mlp_create_problem (mlp, NULL);
+ mlp_create_problem (mlp, addresses);
}
else
{
@@ -1416,10 +1431,15 @@
LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' without
address request \n", GNUNET_i2s(&address->peer));
return;
}
+ if (NULL != address->solver_information)
+ {
+ GNUNET_break (0);
+ }
+
LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' with
address request \n", GNUNET_i2s(&address->peer));
/* Problem size changed: new address for peer with pending request */
mlp->mlp_prob_changed = GNUNET_YES;
- GAS_mlp_solve_problem (solver);
+ GAS_mlp_solve_problem (solver, addresses);
}
/**
@@ -1468,7 +1488,7 @@
/* Problem size changed: new address for peer with pending request */
mlp->mlp_prob_updated = GNUNET_YES;
- GAS_mlp_solve_problem (solver);
+ GAS_mlp_solve_problem (solver, addresses);
return;
#if 0
@@ -1584,6 +1604,11 @@
GNUNET_assert (NULL != address);
/* TODO Delete address here */
+ if (NULL != address->solver_information)
+ {
+ GNUNET_free (address->solver_information);
+ address->solver_information = NULL;
+ }
/* Is this peer included in the problem? */
if (NULL == (p = GNUNET_CONTAINER_multihashmap_get (mlp->peers,
&address->peer.hashPubKey)))
@@ -1595,7 +1620,7 @@
/* Problem size changed: new address for peer with pending request */
mlp->mlp_prob_changed = GNUNET_YES;
- GAS_mlp_solve_problem (solver);
+ GAS_mlp_solve_problem (solver, addresses);
return;
#if 0
@@ -1715,7 +1740,7 @@
/* Added new peer, we have to rebuild problem before solving */
mlp->mlp_prob_changed = GNUNET_YES;
}
- GAS_mlp_solve_problem (mlp);
+ GAS_mlp_solve_problem (mlp, addresses);
/* Get prefered address */
GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
@@ -2081,7 +2106,7 @@
/* Setup GLPK */
/* Redirect GLPK output to GNUnet logging */
- glp_error_hook((void *) mlp, &mlp_term_hook);
+ glp_term_hook (&mlp_term_hook, (void *) mlp);
/* Init LP solving parameters */
glp_init_smcp(&mlp->control_param_lp);
Modified: gnunet/src/ats/gnunet-service-ats_addresses_mlp.h
===================================================================
--- gnunet/src/ats/gnunet-service-ats_addresses_mlp.h 2013-02-20 16:24:28 UTC
(rev 26168)
+++ gnunet/src/ats/gnunet-service-ats_addresses_mlp.h 2013-02-20 17:53:31 UTC
(rev 26169)
@@ -350,11 +350,11 @@
* Solves the MLP problem
*
* @param solver the MLP Handle
- * @param ctx solution context
+ * @param addresses the address hashmap
* @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
*/
int
-GAS_mlp_solve_problem (void *solver);
+GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap *
addresses);
/**
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r26169 - gnunet/src/ats,
gnunet <=