perf_ats_solver.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010,2011 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file ats/perf_ats_solver.c
  18. * @brief generic performance test for ATS solvers
  19. * @author Christian Grothoff
  20. * @author Matthias Wachs
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_statistics_service.h"
  25. #include "gnunet-service-ats_addresses.h"
  26. #include "gnunet-service-ats_plugins.h"
  27. #include "gnunet-service-ats_normalization.h"
  28. #include "gnunet-service-ats_preferences.h"
  29. #include "gnunet_ats_service.h"
  30. #include "gnunet_ats_plugin.h"
  31. #include "test_ats_api_common.h"
  32. #define DEFAULT_UPDATE_PERCENTAGE 20
  33. #define DEFAULT_PEERS_START 10
  34. #define DEFAULT_PEERS_END 10
  35. #define DEFAULT_ADDRESSES 10
  36. #define DEFAULT_ATS_COUNT 2
  37. /**
  38. * Handle for statistics.
  39. */
  40. struct GNUNET_STATISTICS_Handle *GSA_stats;
  41. /**
  42. * Handle for ATS address component
  43. */
  44. struct PerfHandle
  45. {
  46. /**
  47. * Performance peers
  48. */
  49. struct PerfPeer *peers;
  50. /**
  51. * Solver handle
  52. */
  53. struct GNUNET_ATS_SolverFunctions *sf;
  54. /**
  55. * Statistics stat;
  56. */
  57. struct GNUNET_STATISTICS_Handle *stat;
  58. /**
  59. * A multihashmap to store all addresses
  60. */
  61. struct GNUNET_CONTAINER_MultiPeerMap *addresses;
  62. /**
  63. * Solver functions
  64. * */
  65. struct GNUNET_ATS_PluginEnvironment env;
  66. /**
  67. * Array for results for each iteration with length iterations
  68. */
  69. struct Iteration *iterations_results;
  70. /**
  71. * The current result
  72. */
  73. struct Result *current_result;
  74. /**
  75. * Current number of peers benchmarked
  76. */
  77. int current_p;
  78. /**
  79. * Current number of addresses benchmarked
  80. */
  81. int current_a;
  82. /**
  83. * Solver description as string
  84. */
  85. char *ats_string;
  86. /**
  87. * Configured ATS solver
  88. */
  89. int ats_mode;
  90. /**
  91. * #peers to start benchmarking with
  92. */
  93. int N_peers_start;
  94. /**
  95. * #peers to end benchmarking with
  96. */
  97. int N_peers_end;
  98. /**
  99. * #addresses to benchmarking with
  100. */
  101. int N_address;
  102. /**
  103. * Percentage of peers to update
  104. */
  105. int opt_update_percent;
  106. /**
  107. * Create gnuplot file
  108. */
  109. int create_datafile;
  110. /**
  111. * Measure updates
  112. */
  113. int measure_updates;
  114. /**
  115. * Number of iterations
  116. */
  117. int total_iterations;
  118. /**
  119. * Current iteration
  120. */
  121. int current_iteration;
  122. /**
  123. * Is a bulk operation running?
  124. */
  125. int bulk_running;
  126. /**
  127. * Is a bulk operation running?
  128. */
  129. int expecting_solution;
  130. /**
  131. * Was the problem just updates?
  132. */
  133. int performed_update;
  134. };
  135. /**
  136. * Data structure to store results for a single iteration
  137. */
  138. struct Iteration
  139. {
  140. struct Result **results_array;
  141. struct Result **update_results_array;
  142. };
  143. /**
  144. * Result for a solver calculcation
  145. */
  146. struct Result
  147. {
  148. /**
  149. * Previous element in the linked list
  150. */
  151. struct Result *prev;
  152. /**
  153. * Next element in the linked list
  154. */
  155. struct Result *next;
  156. /**
  157. * Number of peers this solution included
  158. */
  159. int peers;
  160. /**
  161. * Number of addresses per peer this solution included
  162. */
  163. int addresses;
  164. /**
  165. * Is this an update or a full solution
  166. */
  167. int update;
  168. /**
  169. * Was the solution valid or did the solver fail
  170. */
  171. int valid;
  172. /**
  173. * Result of the solver
  174. */
  175. enum GAS_Solver_Additional_Information info;
  176. /**
  177. * Duration of setting up the problem in the solver
  178. */
  179. struct GNUNET_TIME_Relative d_setup_full;
  180. /**
  181. * Duration of solving the LP problem in the solver
  182. * MLP solver only
  183. */
  184. struct GNUNET_TIME_Relative d_lp_full;
  185. /**
  186. * Duration of solving the MLP problem in the solver
  187. * MLP solver only
  188. */
  189. struct GNUNET_TIME_Relative d_mlp_full;
  190. /**
  191. * Duration of solving whole problem in the solver
  192. */
  193. struct GNUNET_TIME_Relative d_total_full;
  194. /**
  195. * Start time of setting up the problem in the solver
  196. */
  197. struct GNUNET_TIME_Absolute s_setup;
  198. /**
  199. * Start time of solving the LP problem in the solver
  200. * MLP solver only
  201. */
  202. struct GNUNET_TIME_Absolute s_lp;
  203. /**
  204. * Start time of solving the MLP problem in the solver
  205. * MLP solver only
  206. */
  207. struct GNUNET_TIME_Absolute s_mlp;
  208. /**
  209. * Start time of solving whole problem in the solver
  210. */
  211. struct GNUNET_TIME_Absolute s_total;
  212. /**
  213. * End time of setting up the problem in the solver
  214. */
  215. struct GNUNET_TIME_Absolute e_setup;
  216. /**
  217. * End time of solving the LP problem in the solver
  218. * MLP solver only
  219. */
  220. struct GNUNET_TIME_Absolute e_lp;
  221. /**
  222. * End time of solving the MLP problem in the solver
  223. * MLP solver only
  224. */
  225. struct GNUNET_TIME_Absolute e_mlp;
  226. /**
  227. * End time of solving whole problem in the solver
  228. */
  229. struct GNUNET_TIME_Absolute e_total;
  230. };
  231. /**
  232. * Peer used for the benchmarking
  233. */
  234. struct PerfPeer
  235. {
  236. /**
  237. * Peer identitity
  238. */
  239. struct GNUNET_PeerIdentity id;
  240. /**
  241. * Head of linked list of addresses used with this peer
  242. */
  243. struct ATS_Address *head;
  244. /**
  245. * Head of linked list of addresses used with this peer
  246. */
  247. struct ATS_Address *tail;
  248. };
  249. /**
  250. * ATS performance handle
  251. */
  252. static struct PerfHandle ph;
  253. /**
  254. * Return value
  255. */
  256. static int ret;
  257. /**
  258. * Do shutdown
  259. */
  260. static void
  261. end_now (int res)
  262. {
  263. if (NULL != ph.stat)
  264. {
  265. GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
  266. ph.stat = NULL;
  267. }
  268. GNUNET_free (ph.peers);
  269. GNUNET_free (ph.iterations_results);
  270. GAS_normalization_stop ();
  271. GAS_preference_done ();
  272. ret = res;
  273. }
  274. /**
  275. * Create a peer used for benchmarking
  276. *
  277. * @param cp the number of the peer
  278. */
  279. static void
  280. perf_create_peer (int cp)
  281. {
  282. GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
  283. &ph.peers[cp].id, sizeof(struct
  284. GNUNET_PeerIdentity));
  285. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp,
  286. GNUNET_i2s (&ph.peers[cp].id));
  287. }
  288. /**
  289. * Perform an update for an address
  290. *
  291. * @param cur the address to update
  292. */
  293. static void
  294. perf_update_address (struct ATS_Address *cur)
  295. {
  296. int r_type;
  297. int abs_val;
  298. double rel_val;
  299. r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2);
  300. switch (r_type)
  301. {
  302. case 0:
  303. abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
  304. rel_val = (100 + (double) abs_val) / 100;
  305. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  306. "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
  307. GNUNET_i2s (&cur->peer), cur,
  308. "GNUNET_ATS_QUALITY_NET_DELAY",
  309. abs_val, rel_val);
  310. ph.sf->s_address_update_property (ph.sf->cls, cur,
  311. GNUNET_ATS_QUALITY_NET_DELAY,
  312. abs_val, rel_val);
  313. break;
  314. case 1:
  315. abs_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10);
  316. rel_val = (100 + (double) abs_val) / 100;
  317. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  318. "Updating peer `%s' address %p type %s abs val %u rel val %.3f\n",
  319. GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE",
  320. abs_val, rel_val);
  321. ph.sf->s_address_update_property (ph.sf->cls, cur,
  322. GNUNET_ATS_QUALITY_NET_DISTANCE,
  323. abs_val, rel_val);
  324. break;
  325. default:
  326. break;
  327. }
  328. }
  329. static void
  330. bandwidth_changed_cb (void *cls,
  331. struct ATS_Address *address)
  332. {
  333. if ((0 == address->assigned_bw_out) && (0 == address->assigned_bw_in))
  334. return;
  335. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  336. "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
  337. GNUNET_i2s (&address->peer),
  338. address,
  339. address->assigned_bw_out,
  340. address->assigned_bw_in);
  341. if (GNUNET_YES == ph.bulk_running)
  342. GNUNET_break (0);
  343. return;
  344. }
  345. static const double *
  346. get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
  347. {
  348. return GAS_preference_get_by_peer (NULL, id);
  349. }
  350. static void
  351. perf_address_initial_update (void *dead,
  352. struct GNUNET_CONTAINER_MultiPeerMap *addresses,
  353. struct ATS_Address *address)
  354. {
  355. double delay;
  356. double distance;
  357. uint32_t random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
  358. delay = (100 + (double) random) / 100;
  359. ph.sf->s_address_update_property (ph.sf->cls,
  360. address, GNUNET_ATS_QUALITY_NET_DELAY,
  361. 100, delay);
  362. random = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100);
  363. distance = (100 + (double) random) / 100;
  364. ph.sf->s_address_update_property (ph.sf->cls, address,
  365. GNUNET_ATS_QUALITY_NET_DISTANCE,
  366. 10, distance);
  367. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  368. "Initial update address %p : %.2f %.2f\n",
  369. address, delay, distance);
  370. }
  371. struct DUA_Ctx
  372. {
  373. int r;
  374. int c_cur_a;
  375. };
  376. static int
  377. do_update_address (void *cls,
  378. const struct GNUNET_PeerIdentity *pid,
  379. void *value)
  380. {
  381. struct DUA_Ctx *ctx = cls;
  382. struct ATS_Address *addr = value;
  383. if (ctx->c_cur_a == ctx->r)
  384. perf_update_address (addr);
  385. ctx->c_cur_a++;
  386. return GNUNET_OK;
  387. }
  388. /**
  389. * Update a certain percentage of peers
  390. *
  391. * @param cp the current number of peers
  392. * @param ca the current number of addresses
  393. * @param percentage_peers the percentage of peers to update
  394. */
  395. static void
  396. perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int
  397. percentage_peers)
  398. {
  399. int c_peer;
  400. int c_select;
  401. int c_cur_p;
  402. int r;
  403. int count;
  404. unsigned int m[cp];
  405. struct DUA_Ctx dua_ctx;
  406. count = cp * ((double) percentage_peers / 100);
  407. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  408. "Updating %u of %u peers \n", count, cp);
  409. for (c_peer = 0; c_peer < cp; c_peer++)
  410. m[c_peer] = 0;
  411. c_select = 0;
  412. while (c_select < count)
  413. {
  414. r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp);
  415. if (0 == m[r])
  416. {
  417. m[r] = 1;
  418. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  419. "Updating peer [%u] \n", r);
  420. c_select++;
  421. }
  422. }
  423. for (c_cur_p = 0; c_cur_p < cp; c_cur_p++)
  424. {
  425. if (1 == m[c_cur_p])
  426. {
  427. r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca);
  428. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  429. "Updating peer [%u] address [%u]\n", c_cur_p, r);
  430. dua_ctx.c_cur_a = 0;
  431. dua_ctx.r = r;
  432. GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
  433. &ph.peers[c_cur_p].id,
  434. &do_update_address,
  435. &dua_ctx);
  436. }
  437. }
  438. }
  439. /**
  440. * Create an address for a peer
  441. *
  442. * @param cp index of the peer
  443. * @param ca index of the address
  444. * @return the address
  445. */
  446. static struct ATS_Address *
  447. perf_create_address (int cp, int ca)
  448. {
  449. struct ATS_Address *a;
  450. a = create_address (&ph.peers[cp].id,
  451. "Test 1", "test 1", strlen ("test 1") + 1, 0);
  452. GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
  453. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  454. return a;
  455. }
  456. /**
  457. * Information callback for the solver
  458. *
  459. * @param op the solver operation
  460. * @param stat status of the solver operation
  461. * @param add additional solver information
  462. */
  463. static void
  464. solver_info_cb (void *cls,
  465. enum GAS_Solver_Operation op,
  466. enum GAS_Solver_Status stat,
  467. enum GAS_Solver_Additional_Information add)
  468. {
  469. char *add_info;
  470. switch (add)
  471. {
  472. case GAS_INFO_NONE:
  473. add_info = "GAS_INFO_NONE";
  474. break;
  475. case GAS_INFO_FULL:
  476. add_info = "GAS_INFO_MLP_FULL";
  477. break;
  478. case GAS_INFO_UPDATED:
  479. add_info = "GAS_INFO_MLP_UPDATED";
  480. break;
  481. case GAS_INFO_PROP_ALL:
  482. add_info = "GAS_INFO_PROP_ALL";
  483. break;
  484. case GAS_INFO_PROP_SINGLE:
  485. add_info = "GAS_INFO_PROP_SINGLE";
  486. break;
  487. default:
  488. add_info = "INVALID";
  489. break;
  490. }
  491. struct Result *tmp;
  492. switch (op)
  493. {
  494. case GAS_OP_SOLVE_START:
  495. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  496. "Solver notifies `%s' with result `%s' `%s'\n",
  497. "GAS_OP_SOLVE_START",
  498. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
  499. if (GNUNET_NO == ph.expecting_solution)
  500. {
  501. /* We do not expect a solution at the moment */
  502. GNUNET_break (0);
  503. return;
  504. }
  505. if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result))
  506. {
  507. tmp = GNUNET_new (struct Result);
  508. /* Create new result */
  509. if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
  510. {
  511. ph.current_result = tmp;
  512. // fprintf (stderr,"UPDATE %u %u\n",ph.current_iteration-1, ph.current_p);
  513. ph.iterations_results[ph.current_iteration
  514. - 1].update_results_array[ph.current_p] = tmp;
  515. }
  516. else
  517. {
  518. ph.current_result = tmp;
  519. // fprintf (stderr,"FULL %u %u\n",ph.current_iteration-1, ph.current_p);
  520. ph.iterations_results[ph.current_iteration
  521. - 1].results_array[ph.current_p] = tmp;
  522. }
  523. ph.current_result->addresses = ph.current_a;
  524. ph.current_result->peers = ph.current_p;
  525. ph.current_result->s_total = GNUNET_TIME_absolute_get ();
  526. ph.current_result->d_total_full = GNUNET_TIME_UNIT_FOREVER_REL;
  527. ph.current_result->d_setup_full = GNUNET_TIME_UNIT_FOREVER_REL;
  528. ph.current_result->d_lp_full = GNUNET_TIME_UNIT_FOREVER_REL;
  529. ph.current_result->d_mlp_full = GNUNET_TIME_UNIT_FOREVER_REL;
  530. ph.current_result->info = add;
  531. if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update))
  532. {
  533. ph.current_result->update = GNUNET_YES;
  534. }
  535. else
  536. {
  537. ph.current_result->update = GNUNET_NO;
  538. }
  539. }
  540. return;
  541. case GAS_OP_SOLVE_STOP:
  542. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  543. "Solver notifies `%s' with result `%s', `%s'\n",
  544. "GAS_OP_SOLVE_STOP",
  545. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
  546. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  547. {
  548. /* We do not expect a solution at the moment */
  549. GNUNET_break (0);
  550. return;
  551. }
  552. if (GAS_STAT_SUCCESS == stat)
  553. ph.current_result->valid = GNUNET_YES;
  554. else
  555. ph.current_result->valid = GNUNET_NO;
  556. if (NULL != ph.current_result)
  557. {
  558. /* Finalize result */
  559. ph.current_result->e_total = GNUNET_TIME_absolute_get ();
  560. ph.current_result->d_total_full = GNUNET_TIME_absolute_get_difference (
  561. ph.current_result->s_total, ph.current_result->e_total);
  562. }
  563. ph.current_result = NULL;
  564. return;
  565. case GAS_OP_SOLVE_SETUP_START:
  566. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  567. "Solver notifies `%s' with result `%s'\n",
  568. "GAS_OP_SOLVE_SETUP_START",
  569. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  570. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  571. {
  572. GNUNET_break (0);
  573. return;
  574. }
  575. if (GAS_STAT_SUCCESS == stat)
  576. ph.current_result->valid = GNUNET_YES;
  577. else
  578. ph.current_result->valid = GNUNET_NO;
  579. ph.current_result->s_setup = GNUNET_TIME_absolute_get ();
  580. return;
  581. case GAS_OP_SOLVE_SETUP_STOP:
  582. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  583. "Solver notifies `%s' with result `%s'\n",
  584. "GAS_OP_SOLVE_SETUP_STOP",
  585. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  586. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  587. {
  588. GNUNET_break (0);
  589. return;
  590. }
  591. if (GAS_STAT_SUCCESS == stat)
  592. ph.current_result->valid = GNUNET_YES;
  593. else
  594. ph.current_result->valid = GNUNET_NO;
  595. ph.current_result->e_setup = GNUNET_TIME_absolute_get ();
  596. ph.current_result->d_setup_full = GNUNET_TIME_absolute_get_difference (
  597. ph.current_result->s_setup, ph.current_result->e_setup);
  598. return;
  599. case GAS_OP_SOLVE_MLP_LP_START:
  600. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  601. "Solver notifies `%s' with result `%s'\n",
  602. "GAS_OP_SOLVE_LP_START",
  603. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  604. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  605. {
  606. GNUNET_break (0);
  607. return;
  608. }
  609. if (GAS_STAT_SUCCESS == stat)
  610. ph.current_result->valid = GNUNET_YES;
  611. else
  612. ph.current_result->valid = GNUNET_NO;
  613. ph.current_result->s_lp = GNUNET_TIME_absolute_get ();
  614. return;
  615. case GAS_OP_SOLVE_MLP_LP_STOP:
  616. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  617. "Solver notifies `%s' with result `%s'\n",
  618. "GAS_OP_SOLVE_LP_STOP",
  619. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  620. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  621. {
  622. GNUNET_break (0);
  623. return;
  624. }
  625. if (GAS_STAT_SUCCESS == stat)
  626. ph.current_result->valid = GNUNET_YES;
  627. else
  628. ph.current_result->valid = GNUNET_NO;
  629. ph.current_result->e_lp = GNUNET_TIME_absolute_get ();
  630. ph.current_result->d_lp_full = GNUNET_TIME_absolute_get_difference (
  631. ph.current_result->s_lp, ph.current_result->e_lp);
  632. return;
  633. case GAS_OP_SOLVE_MLP_MLP_START:
  634. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  635. "Solver notifies `%s' with result `%s'\n",
  636. "GAS_OP_SOLVE_MLP_START",
  637. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  638. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  639. {
  640. GNUNET_break (0);
  641. return;
  642. }
  643. if (GAS_STAT_SUCCESS == stat)
  644. ph.current_result->valid = GNUNET_YES;
  645. else
  646. ph.current_result->valid = GNUNET_NO;
  647. ph.current_result->s_mlp = GNUNET_TIME_absolute_get ();
  648. return;
  649. case GAS_OP_SOLVE_MLP_MLP_STOP:
  650. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  651. "Solver notifies `%s' with result `%s'\n",
  652. "GAS_OP_SOLVE_MLP_STOP",
  653. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  654. if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result))
  655. {
  656. GNUNET_break (0);
  657. return;
  658. }
  659. if (GAS_STAT_SUCCESS == stat)
  660. ph.current_result->valid = GNUNET_YES;
  661. else
  662. ph.current_result->valid = GNUNET_NO;
  663. ph.current_result->e_mlp = GNUNET_TIME_absolute_get ();
  664. ph.current_result->d_mlp_full = GNUNET_TIME_absolute_get_difference (
  665. ph.current_result->s_mlp, ph.current_result->e_mlp);
  666. return;
  667. case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
  668. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  669. "Solver notifies `%s' with result `%s'\n",
  670. "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
  671. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  672. return;
  673. case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
  674. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  675. "Solver notifies `%s' with result `%s'\n",
  676. "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
  677. (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
  678. if (GAS_STAT_SUCCESS != stat)
  679. {
  680. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  681. "Solver `%s' failed to update problem with %u peers and %u address!\n",
  682. ph.ats_string, ph.current_p, ph.current_a);
  683. }
  684. return;
  685. default:
  686. break;
  687. }
  688. }
  689. /**
  690. * Evaluate results for a specific iteration
  691. *
  692. * @param iteration the iteration to evaluate
  693. */
  694. static void
  695. evaluate (int iteration)
  696. {
  697. struct Result *cur;
  698. int cp;
  699. for (cp = ph.N_peers_start; cp <= ph.N_peers_end; cp++)
  700. {
  701. cur = ph.iterations_results[ph.current_iteration - 1].results_array[cp];
  702. if (0 == cp)
  703. continue;
  704. if (NULL == cur)
  705. {
  706. GNUNET_break (0);
  707. fprintf (stderr,
  708. "Missing result for %u peers\n", cp);
  709. continue;
  710. }
  711. if (GNUNET_NO == cur->valid)
  712. {
  713. fprintf (stderr,
  714. "Total time to solve %s for %u peers %u addresses: %s\n",
  715. (GNUNET_YES == cur->update) ? "updated" : "full",
  716. cur->peers, cur->addresses, "Failed to solve!");
  717. continue;
  718. }
  719. if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
  720. cur->d_total_full.rel_value_us)
  721. {
  722. fprintf (stderr,
  723. "Total time to solve %s for %u peers %u addresses: %llu us\n",
  724. (GNUNET_YES == cur->update) ? "updated" : "full",
  725. cur->peers, cur->addresses,
  726. (unsigned long long) cur->d_total_full.rel_value_us);
  727. }
  728. if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
  729. cur->d_setup_full.rel_value_us)
  730. {
  731. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  732. "Total time to setup %s %u peers %u addresses: %llu us\n",
  733. (GNUNET_YES == cur->update) ? "updated" : "full",
  734. cur->peers, cur->addresses,
  735. (unsigned long long) cur->d_setup_full.rel_value_us);
  736. }
  737. if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
  738. cur->d_lp_full.rel_value_us)
  739. {
  740. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  741. "Total time to solve %s LP for %u peers %u addresses: %llu us\n",
  742. (GNUNET_YES == cur->update) ? "updated" : "full",
  743. cur->peers,
  744. cur->addresses,
  745. (unsigned long long ) cur->d_lp_full.rel_value_us);
  746. }
  747. if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us !=
  748. cur->d_mlp_full.rel_value_us)
  749. {
  750. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  751. "Total time to solve %s MLP for %u peers %u addresses: %llu us\n",
  752. (GNUNET_YES == cur->update) ? "updated" : "full",
  753. cur->peers, cur->addresses,
  754. (unsigned long long ) cur->d_mlp_full.rel_value_us);
  755. }
  756. }
  757. }
  758. static unsigned int
  759. get_connectivity_cb (void *cls,
  760. const struct GNUNET_PeerIdentity *peer)
  761. {
  762. return GNUNET_CONTAINER_multipeermap_contains (ph.addresses,
  763. peer);
  764. }
  765. /**
  766. * Evaluate average results for all iterations
  767. */
  768. static void
  769. write_all_iterations (void)
  770. {
  771. int c_iteration;
  772. int c_peer;
  773. struct GNUNET_DISK_FileHandle *f_full;
  774. struct GNUNET_DISK_FileHandle *f_update;
  775. char *data_fn_full;
  776. char *data_fn_update;
  777. char *data;
  778. f_full = NULL;
  779. f_update = NULL;
  780. data_fn_full = NULL;
  781. if (GNUNET_NO == ph.create_datafile)
  782. return;
  783. GNUNET_asprintf (&data_fn_full,
  784. "perf_%s_full_%u-%u_%u_%u.data",
  785. ph.ats_string,
  786. ph.total_iterations,
  787. ph.N_peers_start,
  788. ph.N_peers_end,
  789. ph.N_address);
  790. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  791. "Using data file `%s'\n",
  792. data_fn_full);
  793. f_full = GNUNET_DISK_file_open (data_fn_full,
  794. GNUNET_DISK_OPEN_WRITE
  795. | GNUNET_DISK_OPEN_CREATE,
  796. GNUNET_DISK_PERM_USER_EXEC
  797. | GNUNET_DISK_PERM_USER_READ
  798. | GNUNET_DISK_PERM_USER_WRITE);
  799. if (NULL == f_full)
  800. {
  801. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  802. "Cannot open data file `%s'\n",
  803. data_fn_full);
  804. GNUNET_free (data_fn_full);
  805. return;
  806. }
  807. data =
  808. "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
  809. if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data, strlen (data)))
  810. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  811. "Cannot write data to log file `%s'\n",
  812. data_fn_full);
  813. data_fn_update = NULL;
  814. if (GNUNET_YES == ph.measure_updates)
  815. {
  816. GNUNET_asprintf (&data_fn_update, "perf_%s_update_%u-%u_%u_%u.data",
  817. ph.ats_string,
  818. ph.total_iterations,
  819. ph.N_peers_start,
  820. ph.N_peers_end,
  821. ph.N_address);
  822. f_update = GNUNET_DISK_file_open (data_fn_update,
  823. GNUNET_DISK_OPEN_WRITE
  824. | GNUNET_DISK_OPEN_CREATE,
  825. GNUNET_DISK_PERM_USER_EXEC
  826. | GNUNET_DISK_PERM_USER_READ
  827. | GNUNET_DISK_PERM_USER_WRITE);
  828. if (NULL == f_update)
  829. {
  830. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  831. "Cannot open gnuplot file `%s'\n", data_fn_update);
  832. GNUNET_free (data_fn_update);
  833. if (NULL != f_full)
  834. GNUNET_DISK_file_close (f_full);
  835. GNUNET_free (data_fn_full);
  836. return;
  837. }
  838. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  839. "Using update data file `%s'\n",
  840. data_fn_update);
  841. data =
  842. "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n";
  843. if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen (data)))
  844. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  845. "Cannot write data to log file `%s'\n",
  846. data_fn_update);
  847. }
  848. for (c_peer = ph.N_peers_start; c_peer <= ph.N_peers_end; c_peer++)
  849. {
  850. char *data_str;
  851. char *data_tmp;
  852. char *data_upd_str;
  853. char *data_upd_tmp;
  854. GNUNET_asprintf (&data_str, "%u;%u", c_peer, ph.N_address);
  855. if (ph.measure_updates)
  856. GNUNET_asprintf (&data_upd_str, "%u;%u", c_peer, ph.N_address);
  857. for (c_iteration = 0; c_iteration < ph.total_iterations; c_iteration++)
  858. {
  859. struct Result *cur_full_res;
  860. struct Result *cur_upd_res;
  861. // fprintf (stderr, "P: %u I: %u == %p \n", c_peer, c_iteration, cur_res);
  862. cur_full_res = ph.iterations_results[c_iteration].results_array[c_peer];
  863. if (c_peer == 0)
  864. continue;
  865. if (NULL == cur_full_res)
  866. continue;
  867. if (ph.measure_updates)
  868. {
  869. cur_upd_res =
  870. ph.iterations_results[c_iteration].update_results_array[c_peer];
  871. data_upd_tmp = GNUNET_strdup (data_upd_str);
  872. GNUNET_free (data_upd_str);
  873. if (GNUNET_YES == cur_full_res->valid)
  874. {
  875. GNUNET_asprintf (&data_upd_str, "%s;%llu", data_upd_tmp,
  876. (NULL == cur_upd_res) ? 0 :
  877. cur_upd_res->d_total_full.rel_value_us);
  878. }
  879. else
  880. {
  881. GNUNET_asprintf (&data_upd_str, "%s;", data_upd_tmp);
  882. }
  883. GNUNET_free (data_upd_tmp);
  884. }
  885. // fprintf (stderr, "P: %u I: %u: P %i A %i\n", c_peer, c_iteration, cur_res->peers, cur_res->addresses);
  886. // fprintf (stderr, "D total: %llu\n", (long long unsigned int) cur_res->d_total.rel_value_us);
  887. data_tmp = GNUNET_strdup (data_str);
  888. GNUNET_free (data_str);
  889. if (GNUNET_YES == cur_full_res->valid)
  890. {
  891. GNUNET_asprintf (&data_str, "%s;%llu", data_tmp,
  892. cur_full_res->d_total_full.rel_value_us);
  893. }
  894. else
  895. {
  896. GNUNET_asprintf (&data_str, "%s;", data_tmp);
  897. }
  898. GNUNET_free (data_tmp);
  899. }
  900. data_tmp = GNUNET_strdup (data_str);
  901. GNUNET_free (data_str);
  902. GNUNET_asprintf (&data_str, "%s\n", data_tmp);
  903. GNUNET_free (data_tmp);
  904. fprintf (stderr, "Result full solution: %s\n", data_str);
  905. if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data_str, strlen (
  906. data_str)))
  907. GNUNET_break (0);
  908. GNUNET_free (data_str);
  909. if (ph.measure_updates)
  910. {
  911. data_upd_tmp = GNUNET_strdup (data_upd_str);
  912. GNUNET_free (data_upd_str);
  913. GNUNET_asprintf (&data_upd_str, "%s\n", data_upd_tmp);
  914. GNUNET_free (data_upd_tmp);
  915. fprintf (stderr, "Result updated solution: `%s'\n", data_upd_str);
  916. if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data_upd_str,
  917. strlen (data_upd_str)))
  918. GNUNET_break (0);
  919. GNUNET_free (data_upd_str);
  920. }
  921. }
  922. if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full)))
  923. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
  924. data_fn_full);
  925. GNUNET_free (data_fn_full);
  926. if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (
  927. f_update)))
  928. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n",
  929. data_fn_update);
  930. GNUNET_free (data_fn_update);
  931. }
  932. static int
  933. do_delete_address (void *cls,
  934. const struct GNUNET_PeerIdentity *pid,
  935. void *value)
  936. {
  937. struct ATS_Address *cur = value;
  938. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  939. "Deleting addresses for peer %u\n",
  940. pid);
  941. GNUNET_assert (GNUNET_OK ==
  942. GNUNET_CONTAINER_multipeermap_remove (ph.addresses,
  943. pid,
  944. cur));
  945. ph.sf->s_del (ph.sf->cls, cur);
  946. GNUNET_free (cur->atsi);
  947. GNUNET_free (cur);
  948. return GNUNET_OK;
  949. }
  950. /**
  951. * Run a performance iteration
  952. */
  953. static void
  954. perf_run_iteration (void)
  955. {
  956. int cp;
  957. int ca;
  958. int count_p = ph.N_peers_end;
  959. int count_a = ph.N_address;
  960. struct ATS_Address *cur_addr;
  961. uint32_t net;
  962. ph.iterations_results[ph.current_iteration - 1].results_array =
  963. GNUNET_malloc ((count_p + 1) * sizeof(struct Result *));
  964. if (ph.measure_updates)
  965. ph.iterations_results[ph.current_iteration - 1].update_results_array =
  966. GNUNET_malloc ((count_p + 1) * sizeof(struct Result *));
  967. ph.peers = GNUNET_malloc ((count_p) * sizeof(struct PerfPeer));
  968. for (cp = 0; cp < count_p; cp++)
  969. perf_create_peer (cp);
  970. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  971. "Iteration %u of %u, added %u peers\n", ph.current_iteration,
  972. ph.total_iterations, cp);
  973. for (cp = 0; cp < count_p; cp++)
  974. {
  975. fprintf (stderr, "%u..", cp);
  976. if (GNUNET_NO == ph.bulk_running)
  977. {
  978. ph.bulk_running = GNUNET_YES;
  979. ph.sf->s_bulk_start (ph.sf->cls);
  980. }
  981. ph.current_p = cp + 1;
  982. for (ca = 0; ca < count_a; ca++)
  983. {
  984. cur_addr = perf_create_address (cp, ca);
  985. /* Add address */
  986. /* Random network selection */
  987. // net = 1 + GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_NT_COUNT - 1);
  988. /* Random equally distributed network selection */
  989. net = 1 + (ca % (GNUNET_NT_COUNT - 1));
  990. /* fprintf (stderr, "Network: %u `%s'\n",
  991. * mod_net , GNUNET_NT_to_string(mod_net)); */
  992. cur_addr->atsi = GNUNET_new (struct GNUNET_ATS_Information);
  993. cur_addr->atsi_count = 1;
  994. cur_addr->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
  995. cur_addr->atsi[0].value = htonl (net);
  996. ph.sf->s_add (ph.sf->cls, cur_addr, net);
  997. ph.current_a = ca + 1;
  998. perf_address_initial_update (NULL, ph.addresses, cur_addr);
  999. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1000. "Adding address for peer %u address %u in network %s\n", cp,
  1001. ca,
  1002. GNUNET_NT_to_string (net));
  1003. }
  1004. /* Notify solver about request */
  1005. ph.sf->s_get (ph.sf->cls, &ph.peers[cp].id);
  1006. if (cp + 1 >= ph.N_peers_start)
  1007. {
  1008. /* Disable bulk to solve the problem */
  1009. if (GNUNET_YES == ph.bulk_running)
  1010. {
  1011. ph.expecting_solution = GNUNET_YES;
  1012. ph.bulk_running = GNUNET_NO;
  1013. ph.sf->s_bulk_stop (ph.sf->cls);
  1014. }
  1015. else
  1016. GNUNET_break (0);
  1017. /* Problem is solved by the solver here due to unlocking */
  1018. ph.expecting_solution = GNUNET_NO;
  1019. /* Update the problem */
  1020. if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates))
  1021. {
  1022. /* Update */
  1023. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1024. "Updating problem with %u peers and %u addresses\n", cp + 1,
  1025. ca);
  1026. ph.expecting_solution = GNUNET_YES;
  1027. ph.performed_update = GNUNET_YES;
  1028. if (GNUNET_NO == ph.bulk_running)
  1029. {
  1030. ph.bulk_running = GNUNET_YES;
  1031. ph.sf->s_bulk_start (ph.sf->cls);
  1032. }
  1033. perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent);
  1034. ph.bulk_running = GNUNET_NO;
  1035. ph.sf->s_bulk_stop (ph.sf->cls);
  1036. /* Problem is solved by the solver here due to unlocking */
  1037. ph.performed_update = GNUNET_NO;
  1038. ph.expecting_solution = GNUNET_NO;
  1039. }
  1040. GNUNET_assert (GNUNET_NO == ph.bulk_running);
  1041. }
  1042. }
  1043. fprintf (stderr, "\n");
  1044. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1045. "Done, cleaning up addresses\n");
  1046. if (GNUNET_NO == ph.bulk_running)
  1047. {
  1048. ph.sf->s_bulk_start (ph.sf->cls);
  1049. ph.bulk_running = GNUNET_YES;
  1050. }
  1051. for (cp = 0; cp < count_p; cp++)
  1052. {
  1053. GNUNET_CONTAINER_multipeermap_get_multiple (ph.addresses,
  1054. &ph.peers[cp].id,
  1055. &do_delete_address,
  1056. NULL);
  1057. }
  1058. if (GNUNET_NO == ph.bulk_running)
  1059. {
  1060. ph.sf->s_bulk_stop (ph.sf->cls);
  1061. ph.bulk_running = GNUNET_NO;
  1062. }
  1063. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1064. "Iteration done\n");
  1065. GNUNET_free (ph.peers);
  1066. }
  1067. static void
  1068. run (void *cls, char *const *args, const char *cfgfile,
  1069. const struct GNUNET_CONFIGURATION_Handle *cfg)
  1070. {
  1071. GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL);
  1072. char *sep;
  1073. char *src_filename = GNUNET_strdup (__FILE__);
  1074. char *test_filename = cls;
  1075. char *solver;
  1076. char *plugin;
  1077. struct GNUNET_CONFIGURATION_Handle *solver_cfg;
  1078. unsigned long long quotas_in[GNUNET_NT_COUNT];
  1079. unsigned long long quotas_out[GNUNET_NT_COUNT];
  1080. int c;
  1081. int c2;
  1082. /* Extract test name */
  1083. if (NULL == (sep = (strstr (src_filename, ".c"))))
  1084. {
  1085. GNUNET_free (src_filename);
  1086. GNUNET_break (0);
  1087. ret = 1;
  1088. return;
  1089. }
  1090. sep[0] = '\0';
  1091. if (NULL != (sep = strstr (test_filename, ".exe")))
  1092. sep[0] = '\0';
  1093. if (NULL == (solver = strstr (test_filename, src_filename)))
  1094. {
  1095. GNUNET_free (src_filename);
  1096. GNUNET_break (0);
  1097. ret = 1;
  1098. return;
  1099. }
  1100. solver += strlen (src_filename) + 1;
  1101. if (0 == strcmp (solver, "proportional"))
  1102. {
  1103. ph.ats_string = "proportional";
  1104. }
  1105. else if (0 == strcmp (solver, "mlp"))
  1106. {
  1107. ph.ats_string = "mlp";
  1108. }
  1109. else if ((0 == strcmp (solver, "ril")))
  1110. {
  1111. ph.ats_string = "ril";
  1112. }
  1113. else
  1114. {
  1115. GNUNET_free (src_filename);
  1116. GNUNET_break (0);
  1117. ret = 1;
  1118. return;
  1119. }
  1120. GNUNET_free (src_filename);
  1121. /* Calculcate peers */
  1122. if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end))
  1123. {
  1124. ph.N_peers_start = DEFAULT_PEERS_START;
  1125. ph.N_peers_end = DEFAULT_PEERS_END;
  1126. }
  1127. if (0 == ph.N_address)
  1128. ph.N_address = DEFAULT_ADDRESSES;
  1129. if (ph.N_peers_start != ph.N_peers_end)
  1130. fprintf (stderr,
  1131. "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n",
  1132. ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address,
  1133. ph.total_iterations);
  1134. else
  1135. fprintf (stderr,
  1136. "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n",
  1137. ph.ats_string, ph.N_peers_end, ph.N_address, ph.total_iterations);
  1138. if (0 == ph.opt_update_percent)
  1139. ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE;
  1140. /* Load quotas */
  1141. solver_cfg = GNUNET_CONFIGURATION_create ();
  1142. if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load (
  1143. solver_cfg,
  1144. "perf_ats_solver.conf"))))
  1145. {
  1146. GNUNET_break (0);
  1147. end_now (1);
  1148. return;
  1149. }
  1150. if (GNUNET_NT_COUNT != load_quotas (solver_cfg,
  1151. quotas_out, quotas_in, GNUNET_NT_COUNT))
  1152. {
  1153. GNUNET_break (0);
  1154. end_now (1);
  1155. return;
  1156. }
  1157. /* Create array of DLL to store results for iterations */
  1158. ph.iterations_results = GNUNET_malloc (sizeof(struct Iteration)
  1159. * ph.total_iterations);
  1160. /* Load solver */
  1161. ph.env.cfg = solver_cfg;
  1162. ph.stat = GNUNET_STATISTICS_create ("ats", cfg);
  1163. ph.env.stats = ph.stat;
  1164. ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
  1165. ph.env.addresses = ph.addresses;
  1166. ph.env.bandwidth_changed_cb = bandwidth_changed_cb;
  1167. ph.env.get_connectivity = &get_connectivity_cb;
  1168. ph.env.get_preferences = &get_preferences_cb;
  1169. ph.env.network_count = GNUNET_NT_COUNT;
  1170. ph.env.info_cb = &solver_info_cb;
  1171. for (c = 0; c < GNUNET_NT_COUNT; c++)
  1172. {
  1173. ph.env.out_quota[c] = quotas_out[c];
  1174. ph.env.in_quota[c] = quotas_in[c];
  1175. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1176. "Loading network quotas: `%s' %llu %llu \n",
  1177. GNUNET_NT_to_string (c),
  1178. ph.env.out_quota[c],
  1179. ph.env.in_quota[c]);
  1180. }
  1181. GAS_normalization_start ();
  1182. GAS_preference_init ();
  1183. GNUNET_asprintf (&plugin,
  1184. "libgnunet_plugin_ats_%s",
  1185. ph.ats_string);
  1186. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1187. _ ("Initializing solver `%s'\n"),
  1188. ph.ats_string);
  1189. if (NULL == (ph.sf = GNUNET_PLUGIN_load (plugin, &ph.env)))
  1190. {
  1191. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1192. _ ("Failed to initialize solver `%s'!\n"),
  1193. plugin);
  1194. ret = 1;
  1195. return;
  1196. }
  1197. /* Do the benchmark */
  1198. for (ph.current_iteration = 1; ph.current_iteration <= ph.total_iterations;
  1199. ph.current_iteration++)
  1200. {
  1201. fprintf (stderr,
  1202. "Iteration %u of %u starting\n",
  1203. ph.current_iteration,
  1204. ph.total_iterations);
  1205. perf_run_iteration ();
  1206. evaluate (ph.current_iteration);
  1207. fprintf (stderr,
  1208. "Iteration %u of %u done\n",
  1209. ph.current_iteration,
  1210. ph.total_iterations);
  1211. }
  1212. if (ph.create_datafile)
  1213. write_all_iterations ();
  1214. /* Unload solver*/
  1215. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1216. _ ("Unloading solver `%s'\n"),
  1217. ph.ats_string);
  1218. GNUNET_PLUGIN_unload (plugin, ph.sf);
  1219. ph.sf = NULL;
  1220. GNUNET_free (plugin);
  1221. for (c = 0; c < ph.total_iterations; c++)
  1222. {
  1223. for (c2 = ph.N_peers_start; c2 < ph.N_peers_end; c2++)
  1224. {
  1225. if (0 == c2)
  1226. continue;
  1227. if (ph.measure_updates)
  1228. GNUNET_free (
  1229. ph.iterations_results[c].update_results_array[c2]);
  1230. GNUNET_free (ph.iterations_results[c].results_array[c2]);
  1231. }
  1232. if (ph.measure_updates)
  1233. GNUNET_free (ph.iterations_results[c].update_results_array);
  1234. GNUNET_free (ph.iterations_results[c].results_array);
  1235. }
  1236. GNUNET_free (ph.iterations_results);
  1237. GNUNET_CONFIGURATION_destroy (solver_cfg);
  1238. GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO);
  1239. }
  1240. /**
  1241. * Main function of the benchmark
  1242. *
  1243. * @param argc argument count
  1244. * @param argv argument values
  1245. */
  1246. int
  1247. main (int argc, char *argv[])
  1248. {
  1249. /* extract command line arguments */
  1250. ph.opt_update_percent = 0;
  1251. ph.N_peers_start = 0;
  1252. ph.N_peers_end = 0;
  1253. ph.N_address = 0;
  1254. ph.ats_string = NULL;
  1255. ph.create_datafile = GNUNET_NO;
  1256. ph.measure_updates = GNUNET_NO;
  1257. ph.total_iterations = 1;
  1258. static struct GNUNET_GETOPT_CommandLineOption options[] = {
  1259. GNUNET_GETOPT_option_uint ('a',
  1260. "addresses",
  1261. gettext_noop ("addresses to use"),
  1262. &ph.N_address),
  1263. GNUNET_GETOPT_option_uint ('s',
  1264. "start",
  1265. gettext_noop ("start with peer"),
  1266. &ph.N_peers_start),
  1267. GNUNET_GETOPT_option_uint ('e',
  1268. "end",
  1269. gettext_noop ("end with peer"),
  1270. &ph.N_peers_end),
  1271. GNUNET_GETOPT_option_uint ('i',
  1272. "iterations",
  1273. gettext_noop (
  1274. "number of iterations used for averaging (default: 1)"),
  1275. &ph.total_iterations),
  1276. GNUNET_GETOPT_option_uint ('p',
  1277. "percentage",
  1278. gettext_noop (
  1279. "update a fix percentage of addresses"),
  1280. &ph.opt_update_percent),
  1281. GNUNET_GETOPT_option_flag ('d',
  1282. "data",
  1283. gettext_noop ("create data file"),
  1284. &ph.create_datafile),
  1285. GNUNET_GETOPT_option_flag ('u',
  1286. "update",
  1287. gettext_noop ("measure updates"),
  1288. &ph.measure_updates),
  1289. GNUNET_GETOPT_OPTION_END
  1290. };
  1291. GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
  1292. return ret;
  1293. }
  1294. /* end of file perf_ats_solver.c */