diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2013-02-21 14:38:26 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2013-02-21 14:38:26 +0000 |
commit | f3738485c15930fc8c1386ed8d2b9734087403fa (patch) | |
tree | b49a4e5b37874b4fc721c6a442f078e7e47e396d /src | |
parent | a6312a8a926cded91ff48ef2fb673954941f1ff5 (diff) | |
download | gnunet-f3738485c15930fc8c1386ed8d2b9734087403fa.tar.gz gnunet-f3738485c15930fc8c1386ed8d2b9734087403fa.zip |
changes
Diffstat (limited to 'src')
-rw-r--r-- | src/ats/gnunet-service-ats_addresses_mlp.c | 217 | ||||
-rw-r--r-- | src/ats/gnunet-service-ats_addresses_mlp.h | 16 |
2 files changed, 148 insertions, 85 deletions
diff --git a/src/ats/gnunet-service-ats_addresses_mlp.c b/src/ats/gnunet-service-ats_addresses_mlp.c index a9eefbdee..6af971179 100644 --- a/src/ats/gnunet-service-ats_addresses_mlp.c +++ b/src/ats/gnunet-service-ats_addresses_mlp.c | |||
@@ -230,7 +230,32 @@ mlp_ats_to_string (int ats_index) | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | #if 0 | 233 | /** |
234 | * Translate glpk status error codes to text | ||
235 | * @param retcode return code | ||
236 | * @return string with result | ||
237 | */ | ||
238 | const char * | ||
239 | mlp_status_to_string (int retcode) | ||
240 | { | ||
241 | switch (retcode) { | ||
242 | case GLP_UNDEF: | ||
243 | return "solution is undefined"; | ||
244 | case GLP_FEAS: | ||
245 | return "solution is feasible"; | ||
246 | case GLP_INFEAS: | ||
247 | return "solution is infeasible"; | ||
248 | case GLP_NOFEAS: | ||
249 | return "no feasible solution exists"; | ||
250 | case GLP_OPT: | ||
251 | return "solution is optimal"; | ||
252 | case GLP_UNBND: | ||
253 | return "solution is unbounded"; | ||
254 | default: | ||
255 | GNUNET_break (0); | ||
256 | return "unknown error"; | ||
257 | } | ||
258 | } | ||
234 | 259 | ||
235 | /** | 260 | /** |
236 | * Translate glpk solver error codes to text | 261 | * Translate glpk solver error codes to text |
@@ -263,6 +288,8 @@ mlp_solve_to_string (int retcode) | |||
263 | return "time limit exceeded"; | 288 | return "time limit exceeded"; |
264 | case GLP_ENOPFS: | 289 | case GLP_ENOPFS: |
265 | return "no primal feasible solution"; | 290 | return "no primal feasible solution"; |
291 | case GLP_ENODFS: | ||
292 | return "no dual feasible solution"; | ||
266 | case GLP_EROOT: | 293 | case GLP_EROOT: |
267 | return "root LP optimum not provided"; | 294 | return "root LP optimum not provided"; |
268 | case GLP_ESTOP: | 295 | case GLP_ESTOP: |
@@ -286,34 +313,7 @@ mlp_solve_to_string (int retcode) | |||
286 | } | 313 | } |
287 | 314 | ||
288 | 315 | ||
289 | /** | 316 | #if 0 |
290 | * Translate glpk status error codes to text | ||
291 | * @param retcode return code | ||
292 | * @return string with result | ||
293 | */ | ||
294 | const char * | ||
295 | mlp_status_to_string (int retcode) | ||
296 | { | ||
297 | switch (retcode) { | ||
298 | case GLP_UNDEF: | ||
299 | return "solution is undefined"; | ||
300 | case GLP_FEAS: | ||
301 | return "solution is feasible"; | ||
302 | case GLP_INFEAS: | ||
303 | return "solution is infeasible"; | ||
304 | case GLP_NOFEAS: | ||
305 | return "no feasible solution exists"; | ||
306 | case GLP_OPT: | ||
307 | return "solution is optimal"; | ||
308 | case GLP_UNBND: | ||
309 | return "solution is unbounded"; | ||
310 | default: | ||
311 | GNUNET_break (0); | ||
312 | return "unknown error"; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | 317 | /** |
318 | * Find a peer in the DLL | 318 | * Find a peer in the DLL |
319 | * | 319 | * |
@@ -1175,7 +1175,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON | |||
1175 | p->ia[p->ci], p->ja[p->ci], p->ar[p->ci]); | 1175 | p->ia[p->ci], p->ja[p->ci], p->ar[p->ci]); |
1176 | #endif | 1176 | #endif |
1177 | p->ci++; | 1177 | p->ci++; |
1178 | 1178 | #if 0 | |
1179 | for (tp = mlp->peer_head; tp != NULL; tp = tp->next) | 1179 | for (tp = mlp->peer_head; tp != NULL; tp = tp->next) |
1180 | for (ta = tp->head; ta != NULL; ta = ta->next) | 1180 | for (ta = tp->head; ta != NULL; ta = ta->next) |
1181 | { | 1181 | { |
@@ -1193,6 +1193,7 @@ mlp_add_constraints_all_addresses (struct GAS_MLP_Handle *mlp, struct GNUNET_CON | |||
1193 | #endif | 1193 | #endif |
1194 | p->ci++; | 1194 | p->ci++; |
1195 | } | 1195 | } |
1196 | #endif | ||
1196 | } | 1197 | } |
1197 | } | 1198 | } |
1198 | 1199 | ||
@@ -1212,6 +1213,7 @@ mlp_create_address_columns_it (void *cls, const struct GNUNET_HashCode * key, vo | |||
1212 | struct GAS_MLP_Handle *mlp = cls; | 1213 | struct GAS_MLP_Handle *mlp = cls; |
1213 | struct MLP_Problem *p = &mlp->p; | 1214 | struct MLP_Problem *p = &mlp->p; |
1214 | struct ATS_Address *address = value; | 1215 | struct ATS_Address *address = value; |
1216 | struct ATS_Peer *peer; | ||
1215 | struct MLP_information *mlpi; | 1217 | struct MLP_information *mlpi; |
1216 | unsigned int col; | 1218 | unsigned int col; |
1217 | char *name; | 1219 | char *name; |
@@ -1226,6 +1228,10 @@ mlp_create_address_columns_it (void *cls, const struct GNUNET_HashCode * key, vo | |||
1226 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(mlp->peers, key)) | 1228 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(mlp->peers, key)) |
1227 | return GNUNET_OK; | 1229 | return GNUNET_OK; |
1228 | 1230 | ||
1231 | /* Get peer */ | ||
1232 | peer = GNUNET_CONTAINER_multihashmap_get (mlp->peers, key); | ||
1233 | peer->processed = GNUNET_NO; | ||
1234 | |||
1229 | p->num_addresses ++; | 1235 | p->num_addresses ++; |
1230 | mlpi = GNUNET_malloc (sizeof (struct MLP_information)); | 1236 | mlpi = GNUNET_malloc (sizeof (struct MLP_information)); |
1231 | address->solver_information = mlpi; | 1237 | address->solver_information = mlpi; |
@@ -1378,11 +1384,88 @@ mlp_create_problem (struct GAS_MLP_Handle *mlp, struct GNUNET_CONTAINER_MultiHas | |||
1378 | 1384 | ||
1379 | /* Load the matrix */ | 1385 | /* Load the matrix */ |
1380 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n"); | 1386 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n"); |
1381 | //glp_load_matrix(mlp->prob, (mlp->ci-1), mlp->ia, mlp->ja, mlp->ar); | 1387 | glp_load_matrix(p->prob, (p->ci)-1, p->ia, p->ja, p->ar); |
1382 | 1388 | ||
1383 | return res; | 1389 | return res; |
1384 | } | 1390 | } |
1385 | 1391 | ||
1392 | /** | ||
1393 | * Solves the LP problem | ||
1394 | * | ||
1395 | * @param mlp the MLP Handle | ||
1396 | * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure | ||
1397 | */ | ||
1398 | static int | ||
1399 | mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp) | ||
1400 | { | ||
1401 | int res = 0; | ||
1402 | if (GNUNET_YES == mlp->mlp_prob_changed) | ||
1403 | { | ||
1404 | /* Problem was recreated: use LP presolver */ | ||
1405 | mlp->control_param_lp.presolve = GLP_ON; | ||
1406 | } | ||
1407 | else | ||
1408 | { | ||
1409 | /* Problem was not recreated: do not use LP presolver */ | ||
1410 | mlp->control_param_lp.presolve = GLP_OFF; | ||
1411 | } | ||
1412 | |||
1413 | res = glp_simplex(mlp->p.prob, &mlp->control_param_lp); | ||
1414 | if (0 == res) | ||
1415 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n", res, mlp_solve_to_string(res)); | ||
1416 | else | ||
1417 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem failed: 0x%02X %s\n", res, mlp_solve_to_string(res)); | ||
1418 | |||
1419 | /* Analyze problem status */ | ||
1420 | res = glp_get_status (mlp->p.prob); | ||
1421 | switch (res) { | ||
1422 | /* solution is optimal */ | ||
1423 | case GLP_OPT: | ||
1424 | /* solution is feasible */ | ||
1425 | case GLP_FEAS: | ||
1426 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n", | ||
1427 | res, mlp_status_to_string(res)); | ||
1428 | return GNUNET_OK; | ||
1429 | /* Problem was ill-defined, no way to handle that */ | ||
1430 | default: | ||
1431 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem failed, no solution: 0x%02X %s\n", | ||
1432 | res, mlp_status_to_string(res)); | ||
1433 | return GNUNET_SYSERR; | ||
1434 | } | ||
1435 | } | ||
1436 | |||
1437 | |||
1438 | /** | ||
1439 | * Solves the MLP problem | ||
1440 | * | ||
1441 | * @param mlp the MLP Handle | ||
1442 | * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure | ||
1443 | */ | ||
1444 | int | ||
1445 | mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp) | ||
1446 | { | ||
1447 | int res = 0; | ||
1448 | res = glp_intopt(mlp->p.prob, &mlp->control_param_mlp); | ||
1449 | if (0 == res) | ||
1450 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", res, mlp_solve_to_string(res)); | ||
1451 | else | ||
1452 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem failed: 0x%02X %s\n", res, mlp_solve_to_string(res)); | ||
1453 | /* Analyze problem status */ | ||
1454 | res = glp_mip_status(mlp->p.prob); | ||
1455 | switch (res) { | ||
1456 | /* solution is optimal */ | ||
1457 | case GLP_OPT: | ||
1458 | /* solution is feasible */ | ||
1459 | case GLP_FEAS: | ||
1460 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: %s\n", mlp_status_to_string(res)); | ||
1461 | return GNUNET_OK; | ||
1462 | /* Problem was ill-defined, no way to handle that */ | ||
1463 | default: | ||
1464 | LOG (GNUNET_ERROR_TYPE_DEBUG,"Solving MLP problem failed, %s\n\n", mlp_status_to_string(res)); | ||
1465 | return GNUNET_SYSERR; | ||
1466 | } | ||
1467 | } | ||
1468 | |||
1386 | 1469 | ||
1387 | /** | 1470 | /** |
1388 | * Solves the MLP problem | 1471 | * Solves the MLP problem |
@@ -1396,7 +1479,10 @@ GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addr | |||
1396 | { | 1479 | { |
1397 | struct GAS_MLP_Handle *mlp = solver; | 1480 | struct GAS_MLP_Handle *mlp = solver; |
1398 | int res = 0; | 1481 | int res = 0; |
1399 | 1482 | struct GNUNET_TIME_Absolute start_lp; | |
1483 | struct GNUNET_TIME_Relative duration_lp; | ||
1484 | struct GNUNET_TIME_Absolute start_mlp; | ||
1485 | struct GNUNET_TIME_Relative duration_mlp; | ||
1400 | GNUNET_assert (NULL != solver); | 1486 | GNUNET_assert (NULL != solver); |
1401 | 1487 | ||
1402 | if ((GNUNET_NO == mlp->mlp_prob_changed) && (GNUNET_NO == mlp->mlp_prob_updated)) | 1488 | if ((GNUNET_NO == mlp->mlp_prob_changed) && (GNUNET_NO == mlp->mlp_prob_updated)) |
@@ -1416,6 +1502,27 @@ GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addr | |||
1416 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n"); | 1502 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n"); |
1417 | } | 1503 | } |
1418 | 1504 | ||
1505 | /* Run LP solver */ | ||
1506 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Running LP solver \n"); | ||
1507 | start_lp = GNUNET_TIME_absolute_get(); | ||
1508 | mlp_solve_lp_problem (mlp); | ||
1509 | duration_lp = GNUNET_TIME_absolute_get_duration (start_lp); | ||
1510 | |||
1511 | /* Run LP solver */ | ||
1512 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n"); | ||
1513 | start_mlp = GNUNET_TIME_absolute_get(); | ||
1514 | mlp_solve_lp_problem (mlp); | ||
1515 | duration_mlp = GNUNET_TIME_absolute_get_duration (start_mlp); | ||
1516 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Solver took LP %llu ms, MLP %llu ms\n", | ||
1517 | (unsigned long long) duration_lp.rel_value, | ||
1518 | (unsigned long long) duration_mlp.rel_value); | ||
1519 | |||
1520 | /* Reset change and update marker */ | ||
1521 | mlp->mlp_prob_updated = GNUNET_NO; | ||
1522 | mlp->mlp_prob_changed = GNUNET_NO; | ||
1523 | |||
1524 | return res; | ||
1525 | |||
1419 | /* Solve problem */ | 1526 | /* Solve problem */ |
1420 | #if 0 | 1527 | #if 0 |
1421 | struct GAS_MLP_Handle *mlp = solver; | 1528 | struct GAS_MLP_Handle *mlp = solver; |
@@ -1544,12 +1651,6 @@ GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addr | |||
1544 | mlp->semaphore = GNUNET_NO; | 1651 | mlp->semaphore = GNUNET_NO; |
1545 | return res; | 1652 | return res; |
1546 | #endif | 1653 | #endif |
1547 | |||
1548 | /* Reset change and update marker */ | ||
1549 | mlp->mlp_prob_updated = GNUNET_NO; | ||
1550 | mlp->mlp_prob_changed = GNUNET_NO; | ||
1551 | |||
1552 | return res; | ||
1553 | } | 1654 | } |
1554 | 1655 | ||
1555 | /** | 1656 | /** |
@@ -1950,34 +2051,9 @@ void | |||
1950 | GAS_mlp_done (void *solver) | 2051 | GAS_mlp_done (void *solver) |
1951 | { | 2052 | { |
1952 | struct GAS_MLP_Handle *mlp = solver; | 2053 | struct GAS_MLP_Handle *mlp = solver; |
1953 | struct ATS_Peer * peer; | ||
1954 | struct ATS_Address *addr; | ||
1955 | |||
1956 | GNUNET_assert (mlp != NULL); | 2054 | GNUNET_assert (mlp != NULL); |
1957 | 2055 | ||
1958 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down mlp solver\n"); | 2056 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down mlp solver\n"); |
1959 | |||
1960 | if (mlp->mlp_task != GNUNET_SCHEDULER_NO_TASK) | ||
1961 | { | ||
1962 | GNUNET_SCHEDULER_cancel(mlp->mlp_task); | ||
1963 | mlp->mlp_task = GNUNET_SCHEDULER_NO_TASK; | ||
1964 | } | ||
1965 | |||
1966 | /* clean up peer list */ | ||
1967 | peer = mlp->peer_head; | ||
1968 | while (peer != NULL) | ||
1969 | { | ||
1970 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up peer `%s'\n", GNUNET_i2s (&peer->id)); | ||
1971 | GNUNET_CONTAINER_DLL_remove(mlp->peer_head, mlp->peer_tail, peer); | ||
1972 | for (addr = peer->head; NULL != addr; addr = peer->head) | ||
1973 | { | ||
1974 | GNUNET_CONTAINER_DLL_remove(peer->head, peer->tail, addr); | ||
1975 | GNUNET_free (addr->solver_information); | ||
1976 | addr->solver_information = NULL; | ||
1977 | } | ||
1978 | GNUNET_free (peer); | ||
1979 | peer = mlp->peer_head; | ||
1980 | } | ||
1981 | mlp_delete_problem (mlp); | 2057 | mlp_delete_problem (mlp); |
1982 | 2058 | ||
1983 | GNUNET_CONTAINER_multihashmap_iterate (mlp->peers, &mlp_free_peers, mlp->peers); | 2059 | GNUNET_CONTAINER_multihashmap_iterate (mlp->peers, &mlp_free_peers, mlp->peers); |
@@ -2023,7 +2099,6 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
2023 | unsigned long long tmp; | 2099 | unsigned long long tmp; |
2024 | unsigned int b_min; | 2100 | unsigned int b_min; |
2025 | unsigned int n_min; | 2101 | unsigned int n_min; |
2026 | struct GNUNET_TIME_Relative i_exec; | ||
2027 | int c; | 2102 | int c; |
2028 | int c2; | 2103 | int c2; |
2029 | int found; | 2104 | int found; |
@@ -2214,14 +2289,6 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
2214 | } | 2289 | } |
2215 | } | 2290 | } |
2216 | 2291 | ||
2217 | /* Get minimum number of connections from configuration */ | ||
2218 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (cfg, "ats", | ||
2219 | "MLP_EXEC_INTERVAL", | ||
2220 | &i_exec)) | ||
2221 | mlp->exec_interval = i_exec; | ||
2222 | else | ||
2223 | mlp->exec_interval = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30); | ||
2224 | |||
2225 | /* Assign options to handle */ | 2292 | /* Assign options to handle */ |
2226 | mlp->stats = (struct GNUNET_STATISTICS_Handle *) stats; | 2293 | mlp->stats = (struct GNUNET_STATISTICS_Handle *) stats; |
2227 | mlp->bw_changed_cb = bw_changed_cb; | 2294 | mlp->bw_changed_cb = bw_changed_cb; |
@@ -2233,12 +2300,6 @@ GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
2233 | mlp->pv.b_min = b_min; | 2300 | mlp->pv.b_min = b_min; |
2234 | mlp->pv.n_min = n_min; | 2301 | mlp->pv.n_min = n_min; |
2235 | mlp->pv.m_q = GNUNET_ATS_QualityPropertiesCount; | 2302 | mlp->pv.m_q = GNUNET_ATS_QualityPropertiesCount; |
2236 | |||
2237 | mlp->semaphore = GNUNET_NO; | ||
2238 | mlp->max_iterations = max_iterations; | ||
2239 | mlp->max_exec_duration = max_duration; | ||
2240 | mlp->last_execution = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
2241 | mlp->auto_solve = GNUNET_YES; | ||
2242 | mlp->mlp_prob_changed = GNUNET_NO; | 2303 | mlp->mlp_prob_changed = GNUNET_NO; |
2243 | mlp->mlp_prob_updated = GNUNET_NO; | 2304 | mlp->mlp_prob_updated = GNUNET_NO; |
2244 | 2305 | ||
diff --git a/src/ats/gnunet-service-ats_addresses_mlp.h b/src/ats/gnunet-service-ats_addresses_mlp.h index ce445964d..920bea405 100644 --- a/src/ats/gnunet-service-ats_addresses_mlp.h +++ b/src/ats/gnunet-service-ats_addresses_mlp.h | |||
@@ -52,10 +52,15 @@ | |||
52 | 52 | ||
53 | struct ATS_Peer | 53 | struct ATS_Peer |
54 | { | 54 | { |
55 | struct GNUNET_PeerIdentity id; | ||
56 | |||
57 | /* Was this peer already added to the current problem? */ | ||
58 | int processed; | ||
59 | #if 0 | ||
55 | struct ATS_Peer *next; | 60 | struct ATS_Peer *next; |
56 | struct ATS_Peer *prev; | 61 | struct ATS_Peer *prev; |
57 | 62 | ||
58 | struct GNUNET_PeerIdentity id; | 63 | |
59 | 64 | ||
60 | /* Array of quality preferences */ | 65 | /* Array of quality preferences */ |
61 | double f_q[GNUNET_ATS_QualityPropertiesCount]; | 66 | double f_q[GNUNET_ATS_QualityPropertiesCount]; |
@@ -70,6 +75,7 @@ struct ATS_Peer | |||
70 | 75 | ||
71 | struct ATS_Address *head; | 76 | struct ATS_Address *head; |
72 | struct ATS_Address *tail; | 77 | struct ATS_Address *tail; |
78 | #endif | ||
73 | }; | 79 | }; |
74 | 80 | ||
75 | struct GAS_MLP_SolutionContext | 81 | struct GAS_MLP_SolutionContext |
@@ -216,8 +222,6 @@ struct GAS_MLP_Handle | |||
216 | 222 | ||
217 | struct MLP_Variables pv; | 223 | struct MLP_Variables pv; |
218 | 224 | ||
219 | |||
220 | |||
221 | /** | 225 | /** |
222 | * GLPK LP control parameter | 226 | * GLPK LP control parameter |
223 | */ | 227 | */ |
@@ -251,11 +255,8 @@ struct GAS_MLP_Handle | |||
251 | */ | 255 | */ |
252 | int mlp_prob_changed; | 256 | int mlp_prob_changed; |
253 | 257 | ||
254 | /** | ||
255 | * Solves the task in an regular interval | ||
256 | */ | ||
257 | GNUNET_SCHEDULER_TaskIdentifier mlp_task; | ||
258 | 258 | ||
259 | #if 0 | ||
259 | /** | 260 | /** |
260 | * Interval between scheduled problem solving | 261 | * Interval between scheduled problem solving |
261 | */ | 262 | */ |
@@ -329,6 +330,7 @@ struct GAS_MLP_Handle | |||
329 | 330 | ||
330 | struct ATS_Peer *peer_head; | 331 | struct ATS_Peer *peer_head; |
331 | struct ATS_Peer *peer_tail; | 332 | struct ATS_Peer *peer_tail; |
333 | #endif | ||
332 | }; | 334 | }; |
333 | 335 | ||
334 | 336 | ||