PageRenderTime 47ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/src/plugins/select/bluegene/ba/block_allocator.c

https://github.com/cfenoy/slurm
C | 3372 lines | 2555 code | 329 blank | 488 comment | 608 complexity | 6c61c1ad98648645d8aa3896e78e8425 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*****************************************************************************\
  2. * block_allocator.c - Assorted functions for layout of bluegene blocks,
  3. * wiring, mapping for smap, etc.
  4. * $Id$
  5. *****************************************************************************
  6. * Copyright (C) 2004-2007 The Regents of the University of California.
  7. * Copyright (C) 2008-2009 Lawrence Livermore National Security.
  8. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  9. * Written by Dan Phung <phung4@llnl.gov>, Danny Auble <da@llnl.gov>
  10. *
  11. * This file is part of SLURM, a resource management program.
  12. * For details, see <http://www.schedmd.com/slurmdocs/>.
  13. * Please also read the included file: DISCLAIMER.
  14. *
  15. * SLURM is free software; you can redistribute it and/or modify it under
  16. * the terms of the GNU General Public License as published by the Free
  17. * Software Foundation; either version 2 of the License, or (at your option)
  18. * any later version.
  19. *
  20. * In addition, as a special exception, the copyright holders give permission
  21. * to link the code of portions of this program with the OpenSSL library under
  22. * certain conditions as described in each individual source file, and
  23. * distribute linked combinations including the two. You must obey the GNU
  24. * General Public License in all respects for all of the code used other than
  25. * OpenSSL. If you modify file(s) with this exception, you may extend this
  26. * exception to your version of the file(s), but you are not obligated to do
  27. * so. If you do not wish to do so, delete this exception statement from your
  28. * version. If you delete this exception statement from all source files in
  29. * the program, then also delete it here.
  30. *
  31. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  32. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  33. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  34. * details.
  35. *
  36. * You should have received a copy of the GNU General Public License along
  37. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  38. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  39. \*****************************************************************************/
  40. #if HAVE_CONFIG_H
  41. # include "config.h"
  42. #endif
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <math.h>
  46. #include "block_allocator.h"
  47. #include "src/common/slurmdb_defs.h"
  48. #include "src/common/timers.h"
  49. #include "src/common/uid.h"
  50. /*
  51. * structure that holds switch path information for finding the wiring
  52. * path without setting the configuration.
  53. *
  54. * - dim - Which Axis it is on
  55. * - geometry - node location
  56. * - in - ingress port.
  57. * - out - egress port.
  58. *
  59. */
  60. typedef struct {
  61. int dim;
  62. uint16_t geometry[HIGHEST_DIMENSIONS];
  63. int in;
  64. int out;
  65. } ba_path_switch_t;
  66. #define DEBUG_PA
  67. #define BEST_COUNT_INIT 20
  68. /* Global */
  69. bool _initialized = false;
  70. bool _wires_initialized = false;
  71. bool _mp_map_initialized = false;
  72. /* _ba_system is the "current" system that the structures will work
  73. * on */
  74. List path = NULL;
  75. List best_path = NULL;
  76. int best_count;
  77. uint16_t *deny_pass = NULL;
  78. char *p = '\0';
  79. /* extern Global */
  80. my_bluegene_t *bg = NULL;
  81. ba_mp_t ***ba_main_grid = NULL;
  82. typedef enum {
  83. BLOCK_ALGO_FIRST,
  84. BLOCK_ALGO_SECOND
  85. } block_algo_t;
  86. /** internal helper functions */
  87. /* */
  88. static int _check_for_options(select_ba_request_t* ba_request);
  89. /* */
  90. static int _append_geo(uint16_t *geo, List geos, int rotate);
  91. /* */
  92. static int _fill_in_coords(List results, List start_list,
  93. uint16_t *geometry, int conn_type);
  94. /* */
  95. static int _copy_the_path(List nodes, ba_switch_t *curr_switch,
  96. ba_switch_t *mark_switch,
  97. int source, int dim);
  98. /* */
  99. static int _find_yz_path(ba_mp_t *ba_node, uint16_t *first,
  100. uint16_t *geometry, int conn_type);
  101. #ifndef HAVE_BG_FILES
  102. /* */
  103. static int _emulate_ext_wiring(ba_mp_t ***grid);
  104. #endif
  105. /** */
  106. static int _reset_the_path(ba_switch_t *curr_switch, int source,
  107. int target, int dim);
  108. /* */
  109. static void _delete_path_list(void *object);
  110. /* find the first block match in the system */
  111. static int _find_match(select_ba_request_t* ba_request, List results);
  112. /** */
  113. static bool _node_used(ba_mp_t* ba_node, int x_size);
  114. /* */
  115. static void _switch_config(ba_mp_t* source, ba_mp_t* target, int dim,
  116. int port_src, int port_tar);
  117. /* */
  118. static int _set_external_wires(int dim, int count, ba_mp_t* source,
  119. ba_mp_t* target);
  120. /* */
  121. static char *_set_internal_wires(List nodes, int size, int conn_type);
  122. /* */
  123. static int _find_x_path(List results, ba_mp_t *ba_node, uint16_t *start,
  124. int x_size, int found, int conn_type,
  125. block_algo_t algo);
  126. /* */
  127. static int _remove_node(List results, uint16_t *mp_tar);
  128. /* */
  129. static int _find_next_free_using_port_2(ba_switch_t *curr_switch,
  130. int source_port,
  131. List nodes, int dim,
  132. int count);
  133. /* */
  134. /* static int _find_passthrough(ba_switch_t *curr_switch, int source_port, */
  135. /* List nodes, int dim, */
  136. /* int count, int highest_phys_x); */
  137. /* */
  138. static int _finish_torus(List results,
  139. ba_switch_t *curr_switch, int source_port,
  140. int dim, int count, uint16_t *start);
  141. /* */
  142. static uint16_t *_set_best_path();
  143. /* */
  144. static int _set_one_dim(uint16_t *start, uint16_t *end, uint16_t *coord);
  145. /* */
  146. static void _destroy_geo(void *object);
  147. extern void destroy_ba_node(void *ptr)
  148. {
  149. ba_mp_t *ba_node = (ba_mp_t *)ptr;
  150. if (ba_node) {
  151. xfree(ba_node->loc);
  152. xfree(ba_node);
  153. }
  154. }
  155. /*
  156. * create a block request. Note that if the geometry is given,
  157. * then size is ignored. If elongate is true, the algorithm will try
  158. * to fit that a block of cubic shape and then it will try other
  159. * elongated geometries. (ie, 2x2x2 -> 4x2x1 -> 8x1x1).
  160. *
  161. * IN/OUT - ba_request: structure to allocate and fill in.
  162. *
  163. * ALL below IN's need to be set within the ba_request before the call
  164. * if you want them to be used.
  165. * ALL below OUT's are set and returned within the ba_request.
  166. * IN - avail_node_bitmap: bitmap of usable midplanes.
  167. * IN - blrtsimage: BlrtsImage for this block if not default
  168. * IN - conn_type: connection type of request (TORUS or MESH or SMALL)
  169. * IN - elongate: if true, will try to fit different geometries of
  170. * same size requests
  171. * IN/OUT - geometry: requested/returned geometry of block
  172. * IN - linuximage: LinuxImage for this block if not default
  173. * IN - mloaderimage: MLoaderImage for this block if not default
  174. * IN - nodecards: Number of nodecards in each block in request only
  175. * used of small block allocations.
  176. * OUT - passthroughs: if there were passthroughs used in the
  177. * generation of the block.
  178. * IN - procs: Number of real processors requested
  179. * IN - quarters: Number of midplane quarters in each block in request only
  180. * used of small block allocations.
  181. * IN - RamDiskimage: RamDiskImage for this block if not default
  182. * IN - rotate: if true, allows rotation of block during fit
  183. * OUT - save_name: hostlist of midplanes used in block
  184. * IN/OUT - size: requested/returned count of midplanes in block
  185. * IN - start: geo location of where to start the allocation
  186. * IN - start_req: if set use the start variable to start at
  187. * return success of allocation/validation of params
  188. */
  189. extern int new_ba_request(select_ba_request_t* ba_request)
  190. {
  191. int i=0;
  192. float sz=1;
  193. int i2, picked, total_sz=1, size2=0;
  194. uint16_t *geo_ptr;
  195. int messed_with = 0;
  196. int checked[DIM_SIZE[X]];
  197. uint16_t geo[cluster_dims];
  198. memset(geo, 0, sizeof(geo));
  199. ba_request->save_name= NULL;
  200. ba_request->rotate_count= 0;
  201. ba_request->elongate_count = 0;
  202. ba_request->elongate_geos = list_create(_destroy_geo);
  203. memcpy(geo, ba_request->geometry, sizeof(geo));
  204. if (ba_request->deny_pass == (uint16_t)NO_VAL)
  205. ba_request->deny_pass = ba_deny_pass;
  206. if (!(cluster_flags & CLUSTER_FLAG_BG)) {
  207. if (geo[X] != (uint16_t)NO_VAL) {
  208. for (i=0; i<cluster_dims; i++) {
  209. if ((geo[i] < 1) || (geo[i] > DIM_SIZE[i])) {
  210. error("new_ba_request Error, "
  211. "request geometry is invalid %d",
  212. geo[i]);
  213. return 0;
  214. }
  215. }
  216. ba_request->size = ba_request->geometry[X];
  217. } else if (ba_request->size) {
  218. ba_request->geometry[X] = ba_request->size;
  219. } else
  220. return 0;
  221. return 1;
  222. }
  223. if (geo[X] != (uint16_t)NO_VAL) {
  224. for (i=0; i<cluster_dims; i++){
  225. if ((geo[i] < 1) || (geo[i] > DIM_SIZE[i])) {
  226. error("new_ba_request Error, "
  227. "request geometry is invalid dim %d "
  228. "can't be %c, largest is %c",
  229. i,
  230. alpha_num[geo[i]],
  231. alpha_num[DIM_SIZE[i]]);
  232. return 0;
  233. }
  234. }
  235. _append_geo(geo, ba_request->elongate_geos, 0);
  236. sz=1;
  237. for (i=0; i<cluster_dims; i++)
  238. sz *= ba_request->geometry[i];
  239. ba_request->size = sz;
  240. sz=0;
  241. }
  242. deny_pass = &ba_request->deny_pass;
  243. if (ba_request->elongate || sz) {
  244. sz=1;
  245. /* decompose the size into a cubic geometry */
  246. ba_request->rotate= 1;
  247. ba_request->elongate = 1;
  248. for (i=0; i<cluster_dims; i++) {
  249. total_sz *= DIM_SIZE[i];
  250. geo[i] = 1;
  251. }
  252. if (ba_request->size==1) {
  253. _append_geo(geo,
  254. ba_request->elongate_geos,
  255. ba_request->rotate);
  256. goto endit;
  257. }
  258. if (ba_request->size<=DIM_SIZE[Y]) {
  259. geo[X] = 1;
  260. geo[Y] = ba_request->size;
  261. geo[Z] = 1;
  262. sz=ba_request->size;
  263. _append_geo(geo,
  264. ba_request->elongate_geos,
  265. ba_request->rotate);
  266. }
  267. i = ba_request->size/4;
  268. if (!(ba_request->size%2)
  269. && i <= DIM_SIZE[Y]
  270. && i <= DIM_SIZE[Z]
  271. && i*i == ba_request->size) {
  272. geo[X] = 1;
  273. geo[Y] = i;
  274. geo[Z] = i;
  275. sz=ba_request->size;
  276. _append_geo(geo,
  277. ba_request->elongate_geos,
  278. ba_request->rotate);
  279. }
  280. if (ba_request->size > total_sz || ba_request->size < 1) {
  281. return 0;
  282. }
  283. sz = ba_request->size % (DIM_SIZE[Y] * DIM_SIZE[Z]);
  284. if (!sz) {
  285. i = ba_request->size / (DIM_SIZE[Y] * DIM_SIZE[Z]);
  286. geo[X] = i;
  287. geo[Y] = DIM_SIZE[Y];
  288. geo[Z] = DIM_SIZE[Z];
  289. sz=ba_request->size;
  290. if ((geo[X]*geo[Y]*geo[Z]) == ba_request->size)
  291. _append_geo(geo,
  292. ba_request->elongate_geos,
  293. ba_request->rotate);
  294. else
  295. error("%d I was just trying to add a "
  296. "geo of %d%d%d "
  297. "while I am trying to request "
  298. "%d midplanes",
  299. __LINE__, geo[X], geo[Y], geo[Z],
  300. ba_request->size);
  301. }
  302. // startagain:
  303. picked=0;
  304. for(i=0; i<DIM_SIZE[X]; i++)
  305. checked[i]=0;
  306. for (i=0; i<cluster_dims; i++) {
  307. total_sz *= DIM_SIZE[i];
  308. geo[i] = 1;
  309. }
  310. sz = 1;
  311. picked=0;
  312. tryagain:
  313. size2 = ba_request->size;
  314. //messedup:
  315. for (i=picked; i<cluster_dims; i++) {
  316. if (size2 <= 1)
  317. break;
  318. sz = size2 % DIM_SIZE[i];
  319. if (!sz) {
  320. geo[i] = DIM_SIZE[i];
  321. size2 /= DIM_SIZE[i];
  322. } else if (size2 > DIM_SIZE[i]) {
  323. for(i2=(DIM_SIZE[i]-1); i2 > 1; i2--) {
  324. /* go through each number to see if
  325. the size is divisable by a smaller
  326. number that is
  327. good in the other dims. */
  328. if (!(size2%i2) && !checked[i2]) {
  329. size2 /= i2;
  330. if (i==0)
  331. checked[i2]=1;
  332. if (i2<DIM_SIZE[i]) {
  333. geo[i] = i2;
  334. } else {
  335. goto tryagain;
  336. }
  337. if ((i2-1)!=1 &&
  338. i!=(cluster_dims-1))
  339. break;
  340. }
  341. }
  342. /* This size can not be made into a
  343. block return. If you want to try
  344. until we find the next largest block
  345. uncomment the code below and the goto
  346. above. If a user specifies a max
  347. node count the job will never
  348. run.
  349. */
  350. if (i2==1) {
  351. if (!list_count(
  352. ba_request->elongate_geos))
  353. error("Can't make a block of "
  354. "%d into a cube.",
  355. ba_request->size);
  356. goto endit;
  357. /* ba_request->size +=1; */
  358. /* goto startagain; */
  359. }
  360. } else {
  361. geo[i] = sz;
  362. break;
  363. }
  364. }
  365. if ((geo[X]*geo[Y]) <= DIM_SIZE[Y]) {
  366. ba_request->geometry[X] = 1;
  367. ba_request->geometry[Y] = geo[X] * geo[Y];
  368. ba_request->geometry[Z] = geo[Z];
  369. _append_geo(ba_request->geometry,
  370. ba_request->elongate_geos,
  371. ba_request->rotate);
  372. }
  373. if ((geo[X]*geo[Z]) <= DIM_SIZE[Y]) {
  374. ba_request->geometry[X] = 1;
  375. ba_request->geometry[Y] = geo[Y];
  376. ba_request->geometry[Z] = geo[X] * geo[Z];
  377. _append_geo(ba_request->geometry,
  378. ba_request->elongate_geos,
  379. ba_request->rotate);
  380. }
  381. /* Make sure geo[X] is even and then see if we can get
  382. it into the Y or Z dim. */
  383. if (!(geo[X]%2) && ((geo[X]/2) <= DIM_SIZE[Y])) {
  384. if (geo[Y] == 1) {
  385. ba_request->geometry[Y] = geo[X]/2;
  386. messed_with = 1;
  387. } else
  388. ba_request->geometry[Y] = geo[Y];
  389. if (!messed_with && geo[Z] == 1) {
  390. messed_with = 1;
  391. ba_request->geometry[Z] = geo[X]/2;
  392. } else
  393. ba_request->geometry[Z] = geo[Z];
  394. if (messed_with) {
  395. messed_with = 0;
  396. ba_request->geometry[X] = 2;
  397. _append_geo(ba_request->geometry,
  398. ba_request->elongate_geos,
  399. ba_request->rotate);
  400. }
  401. }
  402. if (geo[X] == DIM_SIZE[X]
  403. && (geo[Y] < DIM_SIZE[Y]
  404. || geo[Z] < DIM_SIZE[Z])) {
  405. if (DIM_SIZE[Y]<DIM_SIZE[Z]) {
  406. i = DIM_SIZE[Y];
  407. DIM_SIZE[Y] = DIM_SIZE[Z];
  408. DIM_SIZE[Z] = i;
  409. }
  410. ba_request->geometry[X] = geo[X];
  411. ba_request->geometry[Y] = geo[Y];
  412. ba_request->geometry[Z] = geo[Z];
  413. if (ba_request->geometry[Y] < DIM_SIZE[Y]) {
  414. i = (DIM_SIZE[Y] - ba_request->geometry[Y]);
  415. ba_request->geometry[Y] +=i;
  416. }
  417. if (ba_request->geometry[Z] < DIM_SIZE[Z]) {
  418. i = (DIM_SIZE[Z] - ba_request->geometry[Z]);
  419. ba_request->geometry[Z] +=i;
  420. }
  421. for(i = DIM_SIZE[X]; i>0; i--) {
  422. ba_request->geometry[X]--;
  423. i2 = (ba_request->geometry[X]
  424. * ba_request->geometry[Y]
  425. * ba_request->geometry[Z]);
  426. if (i2 < ba_request->size) {
  427. ba_request->geometry[X]++;
  428. messed_with = 1;
  429. break;
  430. }
  431. }
  432. if (messed_with) {
  433. messed_with = 0;
  434. _append_geo(ba_request->geometry,
  435. ba_request->elongate_geos,
  436. ba_request->rotate);
  437. }
  438. }
  439. if ((geo[X]*geo[Y]*geo[Z]) == ba_request->size)
  440. _append_geo(geo,
  441. ba_request->elongate_geos,
  442. ba_request->rotate);
  443. else
  444. error("%d I was just trying to add a geo of %d%d%d "
  445. "while I am trying to request %d midplanes",
  446. __LINE__, geo[X], geo[Y], geo[Z],
  447. ba_request->size);
  448. /* Having the functions pow and powf on an aix system doesn't seem to
  449. * link well, so since this is only for aix and this doesn't really
  450. * need to be there just don't allow this extra calculation.
  451. */
  452. #ifndef HAVE_AIX
  453. /* see if We can find a cube or square root of the
  454. size to make an easy cube */
  455. for(i=0; i<cluster_dims-1; i++) {
  456. sz = powf((float)ba_request->size,
  457. (float)1/(cluster_dims-i));
  458. if (pow(sz,(cluster_dims-i)) == ba_request->size)
  459. break;
  460. }
  461. if (i < (cluster_dims-1)) {
  462. /* we found something that looks like a cube! */
  463. int i3 = i;
  464. for (i=0; i<i3; i++)
  465. geo[i] = 1;
  466. for (i=i3; i<cluster_dims; i++)
  467. if (sz<=DIM_SIZE[i])
  468. geo[i] = sz;
  469. else
  470. goto endit;
  471. if ((geo[X]*geo[Y]*geo[Z]) == ba_request->size)
  472. _append_geo(geo,
  473. ba_request->elongate_geos,
  474. ba_request->rotate);
  475. else
  476. error("%d I was just trying to add "
  477. "a geo of %d%d%d "
  478. "while I am trying to request "
  479. "%d midplanes",
  480. __LINE__, geo[X], geo[Y], geo[Z],
  481. ba_request->size);
  482. }
  483. #endif //HAVE_AIX
  484. }
  485. endit:
  486. if (!(geo_ptr = list_peek(ba_request->elongate_geos)))
  487. return 0;
  488. ba_request->elongate_count++;
  489. ba_request->geometry[X] = geo_ptr[X];
  490. ba_request->geometry[Y] = geo_ptr[Y];
  491. ba_request->geometry[Z] = geo_ptr[Z];
  492. sz=1;
  493. for (i=0; i<cluster_dims; i++)
  494. sz *= ba_request->geometry[i];
  495. ba_request->size = sz;
  496. return 1;
  497. }
  498. /**
  499. * print a block request
  500. */
  501. extern void print_ba_request(select_ba_request_t* ba_request)
  502. {
  503. int i;
  504. if (ba_request == NULL){
  505. error("print_ba_request Error, request is NULL");
  506. return;
  507. }
  508. debug(" ba_request:");
  509. debug(" geometry:\t");
  510. for (i=0; i<cluster_dims; i++){
  511. debug("%d", ba_request->geometry[i]);
  512. }
  513. debug(" size:\t%d", ba_request->size);
  514. debug(" conn_type:\t%d", ba_request->conn_type[X]);
  515. debug(" rotate:\t%d", ba_request->rotate);
  516. debug(" elongate:\t%d", ba_request->elongate);
  517. }
  518. /* If emulating a system set up a known configuration for wires in a
  519. * system of the size given.
  520. * If a real bluegene system, query the system and get all wiring
  521. * information of the system.
  522. */
  523. extern void init_wires(void)
  524. {
  525. int x, y, z, i;
  526. ba_mp_t *source = NULL;
  527. if (_wires_initialized)
  528. return;
  529. for(x=0;x<DIM_SIZE[X];x++) {
  530. for(y=0;y<DIM_SIZE[Y];y++) {
  531. for(z=0;z<DIM_SIZE[Z];z++) {
  532. source = &ba_main_grid[x][y][z];
  533. for(i=0; i<NUM_PORTS_PER_NODE; i++) {
  534. _switch_config(source, source,
  535. X, i, i);
  536. _switch_config(source, source,
  537. Y, i, i);
  538. _switch_config(source, source,
  539. Z, i, i);
  540. }
  541. }
  542. }
  543. }
  544. #ifdef HAVE_BG_FILES
  545. _set_external_wires(0,0,NULL,NULL);
  546. if (bridge_setup_system() == -1)
  547. return;
  548. #endif
  549. _wires_initialized = true;
  550. return;
  551. }
  552. /*
  553. * copy the path of the nodes given
  554. *
  555. * IN nodes List of ba_mp_t *'s: nodes to be copied
  556. * OUT dest_nodes List of ba_mp_t *'s: filled in list of nodes
  557. * wiring.
  558. * Return on success SLURM_SUCCESS, on error SLURM_ERROR
  559. */
  560. extern int copy_node_path(List nodes, List *dest_nodes)
  561. {
  562. int rc = SLURM_ERROR;
  563. #ifdef HAVE_BG_L_P
  564. ListIterator itr = NULL;
  565. ListIterator itr2 = NULL;
  566. ba_mp_t *ba_node = NULL, *new_ba_node = NULL;
  567. int dim;
  568. ba_switch_t *curr_switch = NULL, *new_switch = NULL;
  569. if (!nodes)
  570. return SLURM_ERROR;
  571. if (!*dest_nodes)
  572. *dest_nodes = list_create(destroy_ba_node);
  573. itr = list_iterator_create(nodes);
  574. while ((ba_node = list_next(itr))) {
  575. itr2 = list_iterator_create(*dest_nodes);
  576. while ((new_ba_node = list_next(itr2))) {
  577. if (ba_node->coord[X] == new_ba_node->coord[X] &&
  578. ba_node->coord[Y] == new_ba_node->coord[Y] &&
  579. ba_node->coord[Z] == new_ba_node->coord[Z])
  580. break; /* we found it */
  581. }
  582. list_iterator_destroy(itr2);
  583. if (!new_ba_node) {
  584. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  585. info("adding %c%c%c as a new node",
  586. alpha_num[ba_node->coord[X]],
  587. alpha_num[ba_node->coord[Y]],
  588. alpha_num[ba_node->coord[Z]]);
  589. new_ba_node = ba_copy_mp(ba_node);
  590. ba_setup_mp(new_ba_node, false, false);
  591. list_push(*dest_nodes, new_ba_node);
  592. }
  593. new_ba_node->used = true;
  594. for(dim=0;dim<cluster_dims;dim++) {
  595. curr_switch = &ba_node->axis_switch[dim];
  596. new_switch = &new_ba_node->axis_switch[dim];
  597. if (curr_switch->int_wire[0].used) {
  598. if (!_copy_the_path(*dest_nodes,
  599. curr_switch, new_switch,
  600. 0, dim)) {
  601. rc = SLURM_ERROR;
  602. break;
  603. }
  604. }
  605. }
  606. }
  607. list_iterator_destroy(itr);
  608. rc = SLURM_SUCCESS;
  609. #endif
  610. return rc;
  611. }
  612. extern ba_mp_t *coord2ba_mp(const uint16_t *coord)
  613. {
  614. if ((coord[X] >= DIM_SIZE[X]) || (coord[Y] >= DIM_SIZE[Y]) ||
  615. (coord[Z] >= DIM_SIZE[Z])) {
  616. error("Invalid coordinate %d:%d:%d",
  617. coord[X], coord[Y], coord[Z]);
  618. return NULL;
  619. }
  620. return &ba_main_grid[coord[X]][coord[Y]][coord[Z]];
  621. }
  622. /*
  623. * Try to allocate a block.
  624. *
  625. * IN - ba_request: allocation request
  626. * OUT - results: List of results of the allocation request. Each
  627. * list entry will be a coordinate. allocate_block will create the
  628. * list, but the caller must destroy it.
  629. *
  630. * return: success or error of request
  631. */
  632. extern int allocate_block(select_ba_request_t* ba_request, List results)
  633. {
  634. if (!ba_initialized){
  635. error("Error, configuration not initialized, "
  636. "calling ba_init(NULL, 1)");
  637. ba_init(NULL, 1);
  638. }
  639. if (!ba_request){
  640. error("allocate_block Error, request not initialized");
  641. return 0;
  642. }
  643. // _backup_ba_system();
  644. if (_find_match(ba_request, results)){
  645. return 1;
  646. } else {
  647. return 0;
  648. }
  649. }
  650. /*
  651. * Admin wants to remove a previous allocation.
  652. * will allow Admin to delete a previous allocation retrival by letter code.
  653. */
  654. extern int remove_block(List nodes, bool is_small)
  655. {
  656. int dim;
  657. ba_mp_t* curr_ba_node = NULL;
  658. ba_mp_t* ba_node = NULL;
  659. ba_switch_t *curr_switch = NULL;
  660. ListIterator itr;
  661. itr = list_iterator_create(nodes);
  662. while ((curr_ba_node = (ba_mp_t*) list_next(itr))) {
  663. /* since the list that comes in might not be pointers
  664. to the main list we need to point to that main list */
  665. ba_node = &ba_main_grid[curr_ba_node->coord[X]]
  666. [curr_ba_node->coord[Y]]
  667. [curr_ba_node->coord[Z]];
  668. if (curr_ba_node->used)
  669. ba_node->used &= (~BA_MP_USED_TRUE);
  670. /* Small blocks don't use wires, and only have 1 node,
  671. so just break. */
  672. if (is_small)
  673. break;
  674. for(dim=0;dim<cluster_dims;dim++) {
  675. curr_switch = &ba_node->axis_switch[dim];
  676. if (curr_switch->int_wire[0].used) {
  677. _reset_the_path(curr_switch, 0, 1, dim);
  678. }
  679. }
  680. }
  681. list_iterator_destroy(itr);
  682. return 1;
  683. }
  684. /*
  685. * Used to set a block into a virtual system. The system can be
  686. * cleared first and this function sets all the wires and midplanes
  687. * used in the nodelist given. The nodelist is a list of ba_mp_t's
  688. * that are already set up. This is very handly to test if there are
  689. * any passthroughs used by one block when adding another block that
  690. * also uses those wires, and neither use any overlapping
  691. * midplanes. Doing a simple bitmap & will not reveal this.
  692. *
  693. * Returns SLURM_SUCCESS if nodelist fits into system without
  694. * conflict, and SLURM_ERROR if nodelist conflicts with something
  695. * already in the system.
  696. */
  697. extern int check_and_set_mp_list(List nodes)
  698. {
  699. int rc = SLURM_ERROR;
  700. #ifdef HAVE_BG_L_P
  701. int i, j;
  702. ba_switch_t *ba_switch = NULL, *curr_ba_switch = NULL;
  703. ba_mp_t *ba_node = NULL, *curr_ba_node = NULL;
  704. ListIterator itr = NULL;
  705. if (!nodes)
  706. return rc;
  707. itr = list_iterator_create(nodes);
  708. while ((ba_node = list_next(itr))) {
  709. /* info("checking %c%c%c", */
  710. /* ba_node->coord[X], */
  711. /* ba_node->coord[Y], */
  712. /* ba_node->coord[Z]); */
  713. curr_ba_node = &ba_main_grid[ba_node->coord[X]]
  714. [ba_node->coord[Y]]
  715. [ba_node->coord[Z]];
  716. if (ba_node->used && curr_ba_node->used) {
  717. /* Only error if the midplane isn't already
  718. * marked down or in a error state outside of
  719. * the bluegene block.
  720. */
  721. uint16_t base_state, node_flags;
  722. base_state = curr_ba_node->state & NODE_STATE_BASE;
  723. node_flags = curr_ba_node->state & NODE_STATE_FLAGS;
  724. if (!(node_flags & (NODE_STATE_DRAIN | NODE_STATE_FAIL))
  725. && (base_state != NODE_STATE_DOWN)) {
  726. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  727. info("I have already been to "
  728. "this node %c%c%c %s",
  729. alpha_num[ba_node->coord[X]],
  730. alpha_num[ba_node->coord[Y]],
  731. alpha_num[ba_node->coord[Z]],
  732. node_state_string(
  733. curr_ba_node->state));
  734. rc = SLURM_ERROR;
  735. goto end_it;
  736. }
  737. }
  738. if (ba_node->used)
  739. curr_ba_node->used = ba_node->used;
  740. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  741. info("check_and_set_mp_list: "
  742. "%s is used ?= %d %d",
  743. curr_ba_node->coord_str,
  744. curr_ba_node->used, ba_node->used);
  745. for(i=0; i<cluster_dims; i++) {
  746. ba_switch = &ba_node->axis_switch[i];
  747. curr_ba_switch = &curr_ba_node->axis_switch[i];
  748. //info("checking dim %d", i);
  749. for(j=0; j<NUM_PORTS_PER_NODE; j++) {
  750. //info("checking port %d", j);
  751. if (ba_switch->int_wire[j].used
  752. && curr_ba_switch->int_wire[j].used
  753. && j != curr_ba_switch->
  754. int_wire[j].port_tar) {
  755. if (ba_debug_flags
  756. & DEBUG_FLAG_BG_ALGO_DEEP)
  757. info("%c%c%c dim %d port %d "
  758. "is already in use to %d",
  759. alpha_num[ba_node->
  760. coord[X]],
  761. alpha_num[ba_node->
  762. coord[Y]],
  763. alpha_num[ba_node->
  764. coord[Z]],
  765. i,
  766. j,
  767. curr_ba_switch->
  768. int_wire[j].port_tar);
  769. rc = SLURM_ERROR;
  770. goto end_it;
  771. }
  772. if (!ba_switch->int_wire[j].used)
  773. continue;
  774. /* info("setting %c%c%c dim %d port %d -> %d",*/
  775. /* alpha_num[ba_node->coord[X]], */
  776. /* alpha_num[ba_node->coord[Y]], */
  777. /* alpha_num[ba_node->coord[Z]], */
  778. /* i, */
  779. /* j, */
  780. /* ba_switch->int_wire[j].port_tar); */
  781. curr_ba_switch->int_wire[j].used = 1;
  782. curr_ba_switch->int_wire[j].port_tar
  783. = ba_switch->int_wire[j].port_tar;
  784. }
  785. }
  786. }
  787. rc = SLURM_SUCCESS;
  788. end_it:
  789. list_iterator_destroy(itr);
  790. #endif
  791. return rc;
  792. }
  793. /*
  794. * Used to find, and set up midplanes and the wires in the virtual
  795. * system and return them in List results
  796. *
  797. * IN/OUT results - a list with a NULL destroyer filled in with
  798. * midplanes and wires set to create the block with the api. If
  799. * only interested in the hostlist NULL can be excepted also.
  800. * IN ba_request - request for the block
  801. *
  802. * To be set in the ba_request
  803. * start - where to start the allocation. (optional)
  804. * geometry or size - the requested geometry of the block. (required)
  805. * conn_type - mesh, torus, or small. (required)
  806. *
  807. * RET char * - hostlist of midplanes results represent must be
  808. * xfreed. NULL on failure
  809. */
  810. extern char *set_bg_block(List results, select_ba_request_t* ba_request)
  811. {
  812. char *name = NULL;
  813. ba_mp_t* ba_node = NULL;
  814. int send_results = 0;
  815. int found = 0;
  816. xassert(ba_request);
  817. if (cluster_dims == 1) {
  818. if (ba_request->start[X]>=DIM_SIZE[X])
  819. return NULL;
  820. ba_request->size = ba_request->geometry[X];
  821. ba_node = &ba_main_grid[ba_request->start[X]][0][0];
  822. } else {
  823. int dim;
  824. ba_request->size = 1;
  825. for (dim=0; dim<cluster_dims; dim++) {
  826. if (ba_request->start[dim] >= DIM_SIZE[dim])
  827. return NULL;
  828. if ((int16_t)ba_request->geometry[dim] <= 0) {
  829. error("problem with geometry of %c in dim %d, "
  830. "needs to be at least 1",
  831. alpha_num[ba_request->geometry[dim]],
  832. dim);
  833. return NULL;
  834. }
  835. ba_request->size *= ba_request->geometry[dim];
  836. }
  837. ba_node = coord2ba_mp(ba_request->start);
  838. }
  839. if (!ba_node)
  840. return NULL;
  841. if (!results)
  842. results = list_create(NULL);
  843. else
  844. send_results = 1;
  845. /* This midplane should have already been checked if it was in
  846. use or not */
  847. list_append(results, ba_node);
  848. if (ba_request->conn_type[0] >= SELECT_SMALL) {
  849. /* adding the ba_node and ending */
  850. ba_node->used |= BA_MP_USED_TRUE;
  851. name = xstrdup_printf("%s", ba_node->coord_str);
  852. goto end_it;
  853. } else if (ba_request->conn_type[0] == SELECT_NAV)
  854. ba_request->conn_type[0] = bg_conf->default_conn_type[0];
  855. found = _find_x_path(results, ba_node,
  856. ba_node->coord,
  857. ba_request->geometry[X],
  858. 1,
  859. ba_request->conn_type[0], BLOCK_ALGO_FIRST);
  860. if (!found) {
  861. bool is_small = 0;
  862. if (ba_request->conn_type[0] == SELECT_SMALL)
  863. is_small = 1;
  864. debug2("trying less efficient code");
  865. remove_block(results, is_small);
  866. list_flush(results);
  867. list_append(results, ba_node);
  868. found = _find_x_path(results, ba_node,
  869. ba_node->coord,
  870. ba_request->geometry[X],
  871. 1,
  872. ba_request->conn_type[0],
  873. BLOCK_ALGO_SECOND);
  874. }
  875. if (found) {
  876. if (cluster_flags & CLUSTER_FLAG_BG) {
  877. List start_list = NULL;
  878. ListIterator itr;
  879. start_list = list_create(NULL);
  880. itr = list_iterator_create(results);
  881. while ((ba_node = (ba_mp_t*) list_next(itr))) {
  882. list_append(start_list, ba_node);
  883. }
  884. list_iterator_destroy(itr);
  885. if (!_fill_in_coords(results,
  886. start_list,
  887. ba_request->geometry,
  888. ba_request->conn_type[0])) {
  889. list_destroy(start_list);
  890. goto end_it;
  891. }
  892. list_destroy(start_list);
  893. }
  894. } else {
  895. goto end_it;
  896. }
  897. name = _set_internal_wires(results,
  898. ba_request->size,
  899. ba_request->conn_type[0]);
  900. end_it:
  901. if (!send_results && results) {
  902. list_destroy(results);
  903. results = NULL;
  904. }
  905. if (name!=NULL) {
  906. debug2("name = %s", name);
  907. } else {
  908. debug2("can't allocate");
  909. xfree(name);
  910. }
  911. return name;
  912. }
  913. /* Rotate a 3-D geometry array through its six permutations */
  914. extern void ba_rotate_geo(uint16_t *req_geometry, int rot_cnt)
  915. {
  916. uint16_t tmp;
  917. switch (rot_cnt) {
  918. case 0: /* ABC -> ACB */
  919. case 2: /* CAB -> CBA */
  920. case 4: /* BCA -> BAC */
  921. SWAP(req_geometry[Y], req_geometry[Z], tmp);
  922. break;
  923. case 1: /* ACB -> CAB */
  924. case 3: /* CBA -> BCA */
  925. case 5: /* BAC -> ABC */
  926. SWAP(req_geometry[X], req_geometry[Y], tmp);
  927. break;
  928. }
  929. }
  930. /********************* Local Functions *********************/
  931. /*
  932. * This function is here to check options for rotating and elongating
  933. * and set up the request based on the count of each option
  934. */
  935. static int _check_for_options(select_ba_request_t* ba_request)
  936. {
  937. int temp;
  938. int set=0;
  939. uint16_t *geo = NULL;
  940. ListIterator itr;
  941. if (ba_request->rotate) {
  942. rotate_again:
  943. debug2("Rotating! %d",ba_request->rotate_count);
  944. if (ba_request->rotate_count==(cluster_dims-1)) {
  945. temp=ba_request->geometry[X];
  946. ba_request->geometry[X]=ba_request->geometry[Z];
  947. ba_request->geometry[Z]=temp;
  948. ba_request->rotate_count++;
  949. set=1;
  950. } else if (ba_request->rotate_count<(cluster_dims*2)) {
  951. temp=ba_request->geometry[X];
  952. ba_request->geometry[X]=ba_request->geometry[Y];
  953. ba_request->geometry[Y]=ba_request->geometry[Z];
  954. ba_request->geometry[Z]=temp;
  955. ba_request->rotate_count++;
  956. set=1;
  957. } else
  958. ba_request->rotate = false;
  959. if (set) {
  960. if (ba_request->geometry[X]<=DIM_SIZE[X]
  961. && ba_request->geometry[Y]<=DIM_SIZE[Y]
  962. && ba_request->geometry[Z]<=DIM_SIZE[Z])
  963. return 1;
  964. else {
  965. set = 0;
  966. goto rotate_again;
  967. }
  968. }
  969. }
  970. if (ba_request->elongate) {
  971. elongate_again:
  972. debug2("Elongating! %d",ba_request->elongate_count);
  973. ba_request->rotate_count=0;
  974. ba_request->rotate = true;
  975. set = 0;
  976. itr = list_iterator_create(ba_request->elongate_geos);
  977. for(set=0; set<=ba_request->elongate_count; set++)
  978. geo = list_next(itr);
  979. list_iterator_destroy(itr);
  980. if (geo == NULL)
  981. return 0;
  982. ba_request->elongate_count++;
  983. ba_request->geometry[X] = geo[X];
  984. ba_request->geometry[Y] = geo[Y];
  985. ba_request->geometry[Z] = geo[Z];
  986. if (ba_request->geometry[X]<=DIM_SIZE[X]
  987. && ba_request->geometry[Y]<=DIM_SIZE[Y]
  988. && ba_request->geometry[Z]<=DIM_SIZE[Z]) {
  989. return 1;
  990. } else
  991. goto elongate_again;
  992. }
  993. return 0;
  994. }
  995. /*
  996. * grab all the geometries that we can get and append them to the list geos
  997. */
  998. static int _append_geo(uint16_t *geometry, List geos, int rotate)
  999. {
  1000. ListIterator itr;
  1001. uint16_t *geo_ptr = NULL;
  1002. uint16_t *geo = NULL;
  1003. int temp_geo;
  1004. int i, j;
  1005. if (rotate) {
  1006. for (i = (cluster_dims - 1); i >= 0; i--) {
  1007. for (j = 1; j <= i; j++) {
  1008. if ((geometry[j-1] > geometry[j])
  1009. && (geometry[j] <= DIM_SIZE[j-i])
  1010. && (geometry[j-1] <= DIM_SIZE[j])) {
  1011. temp_geo = geometry[j-1];
  1012. geometry[j-1] = geometry[j];
  1013. geometry[j] = temp_geo;
  1014. }
  1015. }
  1016. }
  1017. }
  1018. itr = list_iterator_create(geos);
  1019. while ((geo_ptr = list_next(itr)) != NULL) {
  1020. if (geometry[X] == geo_ptr[X]
  1021. && geometry[Y] == geo_ptr[Y]
  1022. && geometry[Z] == geo_ptr[Z])
  1023. break;
  1024. }
  1025. list_iterator_destroy(itr);
  1026. if (geo_ptr == NULL) {
  1027. geo = xmalloc(sizeof(int)*cluster_dims);
  1028. geo[X] = geometry[X];
  1029. geo[Y] = geometry[Y];
  1030. geo[Z] = geometry[Z];
  1031. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1032. info("adding geo %c%c%c",
  1033. alpha_num[geo[X]], alpha_num[geo[Y]],
  1034. alpha_num[geo[Z]]);
  1035. list_append(geos, geo);
  1036. }
  1037. return 1;
  1038. }
  1039. /*
  1040. * Fill in the paths and extra midplanes we need for the block.
  1041. * Basically copy the x path sent in with the start_list in each Y and
  1042. * Z dimension filling in every midplane for the block and then
  1043. * completing the Y and Z wiring, tying the whole block together.
  1044. *
  1045. * IN/OUT results - total list of midplanes after this function
  1046. * returns successfully. Should be
  1047. * an exact copy of the start_list at first.
  1048. * IN start_list - exact copy of results at first, This should only be
  1049. * a list of midplanes on the X dim. We will work off this and
  1050. * the geometry to fill in this wiring for the X dim in all the
  1051. * Y and Z coords.
  1052. * IN geometry - What the block looks like
  1053. * IN conn_type - Mesh or Torus
  1054. *
  1055. * RET: 0 on failure 1 on success
  1056. */
  1057. static int _fill_in_coords(List results, List start_list,
  1058. uint16_t *geometry, int conn_type)
  1059. {
  1060. ba_mp_t *ba_node = NULL;
  1061. ba_mp_t *check_node = NULL;
  1062. int rc = 1;
  1063. ListIterator itr = NULL;
  1064. int y=0, z=0;
  1065. ba_switch_t *curr_switch = NULL;
  1066. ba_switch_t *next_switch = NULL;
  1067. if (!start_list || !results)
  1068. return 0;
  1069. /* go through the start_list and add all the midplanes */
  1070. itr = list_iterator_create(start_list);
  1071. while ((check_node = (ba_mp_t*) list_next(itr))) {
  1072. curr_switch = &check_node->axis_switch[X];
  1073. for(y=0; y<geometry[Y]; y++) {
  1074. if ((check_node->coord[Y]+y) >= DIM_SIZE[Y]) {
  1075. rc = 0;
  1076. goto failed;
  1077. }
  1078. for(z=0; z<geometry[Z]; z++) {
  1079. if ((check_node->coord[Z]+z) >= DIM_SIZE[Z]) {
  1080. rc = 0;
  1081. goto failed;
  1082. }
  1083. ba_node = &ba_main_grid
  1084. [check_node->coord[X]]
  1085. [check_node->coord[Y]+y]
  1086. [check_node->coord[Z]+z];
  1087. if ((ba_node->coord[Y] == check_node->coord[Y])
  1088. && (ba_node->coord[Z]
  1089. == check_node->coord[Z]))
  1090. continue;
  1091. if (!_node_used(ba_node, geometry[X])) {
  1092. if (ba_debug_flags
  1093. & DEBUG_FLAG_BG_ALGO_DEEP)
  1094. info("here Adding %c%c%c",
  1095. alpha_num[ba_node->
  1096. coord[X]],
  1097. alpha_num[ba_node->
  1098. coord[Y]],
  1099. alpha_num[ba_node->
  1100. coord[Z]]);
  1101. list_append(results, ba_node);
  1102. next_switch = &ba_node->axis_switch[X];
  1103. /* since we are going off the
  1104. * main system we can send NULL
  1105. * here
  1106. */
  1107. _copy_the_path(NULL, curr_switch,
  1108. next_switch,
  1109. 0, X);
  1110. } else {
  1111. rc = 0;
  1112. goto failed;
  1113. }
  1114. }
  1115. }
  1116. }
  1117. list_iterator_destroy(itr);
  1118. itr = list_iterator_create(start_list);
  1119. check_node = (ba_mp_t*) list_next(itr);
  1120. list_iterator_destroy(itr);
  1121. itr = list_iterator_create(results);
  1122. while ((ba_node = (ba_mp_t*) list_next(itr))) {
  1123. if (!_find_yz_path(ba_node,
  1124. check_node->coord,
  1125. geometry,
  1126. conn_type)){
  1127. rc = 0;
  1128. goto failed;
  1129. }
  1130. }
  1131. if (deny_pass) {
  1132. if ((*deny_pass & PASS_DENY_Y)
  1133. && (*deny_pass & PASS_FOUND_Y)) {
  1134. debug("We don't allow Y passthoughs");
  1135. rc = 0;
  1136. } else if ((*deny_pass & PASS_DENY_Z)
  1137. && (*deny_pass & PASS_FOUND_Z)) {
  1138. debug("We don't allow Z passthoughs");
  1139. rc = 0;
  1140. }
  1141. }
  1142. failed:
  1143. list_iterator_destroy(itr);
  1144. return rc;
  1145. }
  1146. /*
  1147. * Copy a path through the wiring of a switch to another switch on a
  1148. * starting port on a dimension.
  1149. *
  1150. * IN/OUT: nodes - Local list of midplanes you are keeping track of. If
  1151. * you visit any new midplanes a copy from ba_main_grid
  1152. * will be added to the list. If NULL the path will be
  1153. * set in mark_switch of the main virtual system (ba_main_grid).
  1154. * IN: curr_switch - The switch you want to copy the path of
  1155. * IN/OUT: mark_switch - The switch you want to fill in. On success
  1156. * this switch will contain a complete path from the curr_switch
  1157. * starting from the source port.
  1158. * IN: source - source port number (If calling for the first time
  1159. * should be 0 since we are looking for 1 at the end)
  1160. * IN: dim - Dimension XYZ
  1161. *
  1162. * RET: on success 1, on error 0
  1163. */
  1164. static int _copy_the_path(List nodes, ba_switch_t *curr_switch,
  1165. ba_switch_t *mark_switch,
  1166. int source, int dim)
  1167. {
  1168. uint16_t *mp_tar;
  1169. uint16_t *mark_mp_tar;
  1170. uint16_t *node_curr;
  1171. uint16_t port_tar, port_tar1;
  1172. ba_switch_t *next_switch = NULL;
  1173. ba_switch_t *next_mark_switch = NULL;
  1174. /* Copy the source used and port_tar */
  1175. mark_switch->int_wire[source].used =
  1176. curr_switch->int_wire[source].used;
  1177. mark_switch->int_wire[source].port_tar =
  1178. curr_switch->int_wire[source].port_tar;
  1179. port_tar = curr_switch->int_wire[source].port_tar;
  1180. /* Now to the same thing from the other end */
  1181. mark_switch->int_wire[port_tar].used =
  1182. curr_switch->int_wire[port_tar].used;
  1183. mark_switch->int_wire[port_tar].port_tar =
  1184. curr_switch->int_wire[port_tar].port_tar;
  1185. port_tar1 = port_tar;
  1186. /* follow the path */
  1187. node_curr = curr_switch->ext_wire[0].mp_tar;
  1188. mp_tar = curr_switch->ext_wire[port_tar].mp_tar;
  1189. if (mark_switch->int_wire[source].used)
  1190. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1191. info("setting dim %d %c%c%c %d-> %c%c%c %d",
  1192. dim,
  1193. alpha_num[node_curr[X]],
  1194. alpha_num[node_curr[Y]],
  1195. alpha_num[node_curr[Z]],
  1196. source,
  1197. alpha_num[mp_tar[X]],
  1198. alpha_num[mp_tar[Y]],
  1199. alpha_num[mp_tar[Z]],
  1200. port_tar);
  1201. if (port_tar == 1) {
  1202. /* found the end of the line */
  1203. mark_switch->int_wire[1].used =
  1204. curr_switch->int_wire[1].used;
  1205. mark_switch->int_wire[1].port_tar =
  1206. curr_switch->int_wire[1].port_tar;
  1207. return 1;
  1208. }
  1209. mark_mp_tar = mark_switch->ext_wire[port_tar].mp_tar;
  1210. port_tar = curr_switch->ext_wire[port_tar].port_tar;
  1211. if (node_curr[X] == mp_tar[X]
  1212. && node_curr[Y] == mp_tar[Y]
  1213. && node_curr[Z] == mp_tar[Z]) {
  1214. /* We are going to the same node! this should never
  1215. happen */
  1216. debug5("something bad happened!! "
  1217. "we are on %c%c%c and are going to it "
  1218. "from port %d - > %d",
  1219. alpha_num[node_curr[X]],
  1220. alpha_num[node_curr[Y]],
  1221. alpha_num[node_curr[Z]],
  1222. port_tar1, port_tar);
  1223. return 0;
  1224. }
  1225. /* see what the next switch is going to be */
  1226. next_switch = &ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]].
  1227. axis_switch[dim];
  1228. if (!nodes) {
  1229. /* If no nodes then just get the next switch to fill
  1230. in from the main system */
  1231. next_mark_switch = &ba_main_grid[mark_mp_tar[X]]
  1232. [mark_mp_tar[Y]]
  1233. [mark_mp_tar[Z]]
  1234. .axis_switch[dim];
  1235. } else {
  1236. ba_mp_t *ba_node = NULL;
  1237. ListIterator itr = list_iterator_create(nodes);
  1238. /* see if we have already been to this node */
  1239. while ((ba_node = list_next(itr))) {
  1240. if (ba_node->coord[X] == mark_mp_tar[X] &&
  1241. ba_node->coord[Y] == mark_mp_tar[Y] &&
  1242. ba_node->coord[Z] == mark_mp_tar[Z])
  1243. break; /* we found it */
  1244. }
  1245. list_iterator_destroy(itr);
  1246. if (!ba_node) {
  1247. /* If node grab a copy and add it to the list */
  1248. ba_node = ba_copy_mp(&ba_main_grid[mark_mp_tar[X]]
  1249. [mark_mp_tar[Y]]
  1250. [mark_mp_tar[Z]]);
  1251. ba_setup_mp(ba_node, false, false);
  1252. list_push(nodes, ba_node);
  1253. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1254. info("haven't seen %c%c%c adding it",
  1255. alpha_num[ba_node->coord[X]],
  1256. alpha_num[ba_node->coord[Y]],
  1257. alpha_num[ba_node->coord[Z]]);
  1258. }
  1259. next_mark_switch = &ba_node->axis_switch[dim];
  1260. }
  1261. /* Keep going until we reach the end of the line */
  1262. return _copy_the_path(nodes, next_switch, next_mark_switch,
  1263. port_tar, dim);
  1264. }
  1265. static int _find_yz_path(ba_mp_t *ba_node, uint16_t *first,
  1266. uint16_t *geometry, int conn_type)
  1267. {
  1268. ba_mp_t *next_node = NULL;
  1269. uint16_t *mp_tar = NULL;
  1270. ba_switch_t *dim_curr_switch = NULL;
  1271. ba_switch_t *dim_next_switch = NULL;
  1272. int i2;
  1273. int count = 0;
  1274. for(i2=1;i2<=2;i2++) {
  1275. if (geometry[i2] > 1) {
  1276. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1277. info("%d node %c%c%c port 2 -> ",
  1278. i2,
  1279. alpha_num[ba_node->coord[X]],
  1280. alpha_num[ba_node->coord[Y]],
  1281. alpha_num[ba_node->coord[Z]]);
  1282. dim_curr_switch = &ba_node->axis_switch[i2];
  1283. if (dim_curr_switch->int_wire[2].used) {
  1284. debug5("returning here");
  1285. return 0;
  1286. }
  1287. mp_tar = dim_curr_switch->ext_wire[2].mp_tar;
  1288. next_node =
  1289. &ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]];
  1290. dim_next_switch = &next_node->axis_switch[i2];
  1291. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1292. info("%c%c%c port 5",
  1293. alpha_num[next_node->coord[X]],
  1294. alpha_num[next_node->coord[Y]],
  1295. alpha_num[next_node->coord[Z]]);
  1296. if (dim_next_switch->int_wire[5].used) {
  1297. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1298. info("returning here 2");
  1299. return 0;
  1300. }
  1301. debug5("%d %d %d %d",i2, mp_tar[i2],
  1302. first[i2], geometry[i2]);
  1303. /* Here we need to see where we are in
  1304. * reference to the geo of this dimension. If
  1305. * we have not gotten the number we need in
  1306. * the direction we just go to the next node
  1307. * with 5 -> 1. If we have all the midplanes
  1308. * we need then we go through and finish the
  1309. * torus if needed
  1310. */
  1311. if (mp_tar[i2] < first[i2])
  1312. count = mp_tar[i2]+(DIM_SIZE[i2]-first[i2]);
  1313. else
  1314. count = (mp_tar[i2]-first[i2]);
  1315. if (count == geometry[i2]) {
  1316. debug5("found end of me %c%c%c",
  1317. alpha_num[mp_tar[X]],
  1318. alpha_num[mp_tar[Y]],
  1319. alpha_num[mp_tar[Z]]);
  1320. if (conn_type == SELECT_TORUS) {
  1321. dim_curr_switch->int_wire[0].used = 1;
  1322. dim_curr_switch->int_wire[0].port_tar
  1323. = 2;
  1324. dim_curr_switch->int_wire[2].used = 1;
  1325. dim_curr_switch->int_wire[2].port_tar
  1326. = 0;
  1327. dim_curr_switch = dim_next_switch;
  1328. if (deny_pass
  1329. && (mp_tar[i2] != first[i2])) {
  1330. if (i2 == 1)
  1331. *deny_pass |=
  1332. PASS_FOUND_Y;
  1333. else
  1334. *deny_pass |=
  1335. PASS_FOUND_Z;
  1336. }
  1337. while (mp_tar[i2] != first[i2]) {
  1338. if (ba_debug_flags
  1339. & DEBUG_FLAG_BG_ALGO_DEEP)
  1340. info("on dim %d at %d "
  1341. "looking for %d",
  1342. i2,
  1343. mp_tar[i2],
  1344. first[i2]);
  1345. if (dim_curr_switch->
  1346. int_wire[2].used) {
  1347. if (ba_debug_flags
  1348. & DEBUG_FLAG_BG_ALGO_DEEP)
  1349. info("returning"
  1350. " here 3");
  1351. return 0;
  1352. }
  1353. dim_curr_switch->
  1354. int_wire[2].used = 1;
  1355. dim_curr_switch->
  1356. int_wire[2].port_tar
  1357. = 5;
  1358. dim_curr_switch->
  1359. int_wire[5].used
  1360. = 1;
  1361. dim_curr_switch->
  1362. int_wire[5].
  1363. port_tar = 2;
  1364. mp_tar = dim_curr_switch->
  1365. ext_wire[2].mp_tar;
  1366. next_node = &ba_main_grid
  1367. [mp_tar[X]]
  1368. [mp_tar[Y]]
  1369. [mp_tar[Z]];
  1370. dim_curr_switch =
  1371. &next_node->
  1372. axis_switch[i2];
  1373. }
  1374. if (ba_debug_flags
  1375. & DEBUG_FLAG_BG_ALGO_DEEP)
  1376. info("back to first on dim %d "
  1377. "at %d looking for %d",
  1378. i2,
  1379. mp_tar[i2],
  1380. first[i2]);
  1381. dim_curr_switch->
  1382. int_wire[5].used = 1;
  1383. dim_curr_switch->
  1384. int_wire[5].port_tar
  1385. = 1;
  1386. dim_curr_switch->
  1387. int_wire[1].used
  1388. = 1;
  1389. dim_curr_switch->
  1390. int_wire[1].
  1391. port_tar = 5;
  1392. }
  1393. } else if (count < geometry[i2]) {
  1394. if (conn_type == SELECT_TORUS ||
  1395. (conn_type == SELECT_MESH &&
  1396. (mp_tar[i2] != first[i2]))) {
  1397. dim_curr_switch->
  1398. int_wire[0].used = 1;
  1399. dim_curr_switch->
  1400. int_wire[0].port_tar
  1401. = 2;
  1402. dim_curr_switch->
  1403. int_wire[2].used
  1404. = 1;
  1405. dim_curr_switch->
  1406. int_wire[2].
  1407. port_tar = 0;
  1408. dim_next_switch->int_wire[5].used
  1409. = 1;
  1410. dim_next_switch->
  1411. int_wire[5].port_tar
  1412. = 1;
  1413. dim_next_switch->
  1414. int_wire[1].used = 1;
  1415. dim_next_switch->
  1416. int_wire[1].port_tar
  1417. = 5;
  1418. }
  1419. } else {
  1420. error("We were only looking for %d "
  1421. "in the %d dim, but now we have %d",
  1422. geometry[i2], i2, count);
  1423. return 0;
  1424. }
  1425. } else if ((geometry[i2] == 1) && (conn_type == SELECT_TORUS)) {
  1426. /* FIX ME: This is put here because we got
  1427. into a state where the Y dim was not being
  1428. processed correctly. This will set up the
  1429. 0 -> 1 port correctly. We should probably
  1430. find out why this was happening in the
  1431. first place though. A reproducer was to
  1432. have
  1433. MPs=[310x323] Type=TORUS
  1434. MPs=[200x233] Type=TORUS
  1435. MPs=[300x303] Type=TORUS
  1436. MPs=[100x133] Type=TORUS
  1437. MPs=[000x033] Type=TORUS
  1438. MPs=[400x433] Type=TORUS
  1439. and then add
  1440. MPs=[330x333] Type=TORUS
  1441. */
  1442. dim_curr_switch = &ba_node->axis_switch[i2];
  1443. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1444. info("%d node %c%c%c port 0 -> 1",
  1445. i2,
  1446. alpha_num[ba_node->coord[X]],
  1447. alpha_num[ba_node->coord[Y]],
  1448. alpha_num[ba_node->coord[Z]]);
  1449. dim_curr_switch->int_wire[0].used = 1;
  1450. dim_curr_switch->int_wire[0].port_tar = 1;
  1451. dim_curr_switch->int_wire[1].used = 1;
  1452. dim_curr_switch->int_wire[1].port_tar = 0;
  1453. }
  1454. }
  1455. return 1;
  1456. }
  1457. #ifndef HAVE_BG_FILES
  1458. /** */
  1459. static int _emulate_ext_wiring(ba_mp_t ***grid)
  1460. {
  1461. int x;
  1462. ba_mp_t *source = NULL, *target = NULL;
  1463. if (cluster_dims == 1) {
  1464. for(x=0;x<DIM_SIZE[X];x++) {
  1465. source = &grid[x][0][0];
  1466. if (x<(DIM_SIZE[X]-1))
  1467. target = &grid[x+1][0][0];
  1468. else
  1469. target = &grid[0][0][0];
  1470. _set_external_wires(X, x, source, target);
  1471. }
  1472. } else {
  1473. int y,z;
  1474. for(x=0;x<DIM_SIZE[X];x++) {
  1475. for(y=0;y<DIM_SIZE[Y];y++) {
  1476. for(z=0;z<DIM_SIZE[Z];z++) {
  1477. source = &grid[x][y][z];
  1478. if (x<(DIM_SIZE[X]-1)) {
  1479. target = &grid[x+1][y][z];
  1480. } else
  1481. target = &grid[0][y][z];
  1482. _set_external_wires(X, x, source,
  1483. target);
  1484. if (y<(DIM_SIZE[Y]-1))
  1485. target = &grid[x][y+1][z];
  1486. else
  1487. target = &grid[x][0][z];
  1488. _set_external_wires(Y, y, source,
  1489. target);
  1490. if (z<(DIM_SIZE[Z]-1))
  1491. target = &grid[x][y][z+1];
  1492. else
  1493. target = &grid[x][y][0];
  1494. _set_external_wires(Z, z, source,
  1495. target);
  1496. }
  1497. }
  1498. }
  1499. }
  1500. return 1;
  1501. }
  1502. #endif
  1503. static int _reset_the_path(ba_switch_t *curr_switch, int source,
  1504. int target, int dim)
  1505. {
  1506. uint16_t *mp_tar;
  1507. uint16_t *node_curr;
  1508. int port_tar, port_tar1;
  1509. ba_switch_t *next_switch = NULL;
  1510. if (source < 0 || source >= NUM_PORTS_PER_NODE) {
  1511. fatal("source port was %d can only be 0->%d",
  1512. source, NUM_PORTS_PER_NODE);
  1513. }
  1514. if (target < 0 || target >= NUM_PORTS_PER_NODE) {
  1515. fatal("target port was %d can only be 0->%d",
  1516. target, NUM_PORTS_PER_NODE);
  1517. }
  1518. /*set the switch to not be used */
  1519. if (!curr_switch->int_wire[source].used) {
  1520. /* This means something overlapping the removing block
  1521. already cleared this, or the path just never was
  1522. complete in the first place. */
  1523. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1524. info("I reached the end, the source isn't used");
  1525. return 1;
  1526. }
  1527. curr_switch->int_wire[source].used = 0;
  1528. port_tar = curr_switch->int_wire[source].port_tar;
  1529. if (port_tar < 0 || port_tar >= NUM_PORTS_PER_NODE) {
  1530. fatal("port_tar port was %d can only be 0->%d",
  1531. source, NUM_PORTS_PER_NODE);
  1532. return 1;
  1533. }
  1534. port_tar1 = port_tar;
  1535. curr_switch->int_wire[source].port_tar = source;
  1536. curr_switch->int_wire[port_tar].used = 0;
  1537. curr_switch->int_wire[port_tar].port_tar = port_tar;
  1538. if (port_tar == target) {
  1539. return 1;
  1540. }
  1541. /* follow the path */
  1542. node_curr = curr_switch->ext_wire[0].mp_tar;
  1543. mp_tar = curr_switch->ext_wire[port_tar].mp_tar;
  1544. port_tar = curr_switch->ext_wire[port_tar].port_tar;
  1545. if (source == port_tar1) {
  1546. debug("got this bad one %c%c%c %d %d -> %c%c%c %d",
  1547. alpha_num[node_curr[X]],
  1548. alpha_num[node_curr[Y]],
  1549. alpha_num[node_curr[Z]],
  1550. source,
  1551. port_tar1,
  1552. alpha_num[mp_tar[X]],
  1553. alpha_num[mp_tar[Y]],
  1554. alpha_num[mp_tar[Z]],
  1555. port_tar);
  1556. return 0;
  1557. }
  1558. debug5("from %c%c%c %d %d -> %c%c%c %d",
  1559. alpha_num[node_curr[X]],
  1560. alpha_num[node_curr[Y]],
  1561. alpha_num[node_curr[Z]],
  1562. source,
  1563. port_tar1,
  1564. alpha_num[mp_tar[X]],
  1565. alpha_num[mp_tar[Y]],
  1566. alpha_num[mp_tar[Z]],
  1567. port_tar);
  1568. if (node_curr[X] == mp_tar[X]
  1569. && node_curr[Y] == mp_tar[Y]
  1570. && node_curr[Z] == mp_tar[Z]) {
  1571. debug5("%d something bad happened!!", dim);
  1572. return 0;
  1573. }
  1574. next_switch =
  1575. &ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]].axis_switch[dim];
  1576. return _reset_the_path(next_switch, port_tar, target, dim);
  1577. // return 1;
  1578. }
  1579. extern void ba_create_system()
  1580. {
  1581. int x,y,z, i = 0;
  1582. if (ba_main_grid)
  1583. ba_destroy_system();
  1584. best_count=BEST_COUNT_INIT;
  1585. ba_main_grid = (ba_mp_t***)
  1586. xmalloc(sizeof(ba_mp_t**) * DIM_SIZE[X]);
  1587. for (x=0; x<DIM_SIZE[X]; x++) {
  1588. ba_main_grid[x] = (ba_mp_t**)
  1589. xmalloc(sizeof(ba_mp_t*) * DIM_SIZE[Y]);
  1590. for (y=0; y<DIM_SIZE[Y]; y++) {
  1591. ba_main_grid[x][y] = (ba_mp_t*)
  1592. xmalloc(sizeof(ba_mp_t)
  1593. * DIM_SIZE[Z]);
  1594. for (z=0; z<DIM_SIZE[Z]; z++){
  1595. ba_mp_t *ba_mp = &ba_main_grid[x][y][z];
  1596. ba_mp->coord[X] = x;
  1597. ba_mp->coord[Y] = y;
  1598. ba_mp->coord[Z] = z;
  1599. snprintf(ba_mp->coord_str,
  1600. sizeof(ba_mp->coord_str),
  1601. "%c%c%c",
  1602. alpha_num[ba_mp->coord[X]],
  1603. alpha_num[ba_mp->coord[Y]],
  1604. alpha_num[ba_mp->coord[Z]]);
  1605. ba_setup_mp(ba_mp, true, false);
  1606. ba_mp->state = NODE_STATE_IDLE;
  1607. /* This might get changed
  1608. later, but just incase set
  1609. it up here.
  1610. */
  1611. ba_mp->index = i++;
  1612. }
  1613. }
  1614. }
  1615. if ((cluster_flags & CLUSTER_FLAG_BGL) ||
  1616. (cluster_flags & CLUSTER_FLAG_BGP)) {
  1617. init_wires();
  1618. #ifndef HAVE_BG_FILES
  1619. _emulate_ext_wiring(ba_main_grid);
  1620. #endif
  1621. }
  1622. path = list_create(_delete_path_list);
  1623. best_path = list_create(_delete_path_list);
  1624. }
  1625. /** */
  1626. extern void ba_destroy_system(void)
  1627. {
  1628. int x, y;
  1629. if (path) {
  1630. list_destroy(path);
  1631. path = NULL;
  1632. }
  1633. if (best_path) {
  1634. list_destroy(best_path);
  1635. best_path = NULL;
  1636. }
  1637. #ifdef HAVE_BG_FILES
  1638. if (bg)
  1639. bridge_free_bg(bg);
  1640. #endif
  1641. _mp_map_initialized = false;
  1642. _wires_initialized = true;
  1643. if (ba_main_grid) {
  1644. for (x=0; x<DIM_SIZE[X]; x++) {
  1645. for (y=0; y<DIM_SIZE[Y]; y++)
  1646. xfree(ba_main_grid[x][y]);
  1647. xfree(ba_main_grid[x]);
  1648. }
  1649. xfree(ba_main_grid);
  1650. ba_main_grid = NULL;
  1651. }
  1652. }
  1653. extern bool ba_sub_block_in_bitmap(select_jobinfo_t *jobinfo,
  1654. bitstr_t *usable_bitmap, bool step)
  1655. {
  1656. /* This shouldn't be called. */
  1657. xassert(0);
  1658. return false;
  1659. }
  1660. extern int ba_sub_block_in_bitmap_clear(select_jobinfo_t *jobinfo,
  1661. bitstr_t *usable_bitmap)
  1662. {
  1663. /* this doesn't do anything since above doesn't. */
  1664. return SLURM_SUCCESS;
  1665. }
  1666. extern ba_mp_t *ba_sub_block_in_record(
  1667. bg_record_t *bg_record, uint32_t *node_count,
  1668. select_jobinfo_t *jobinfo)
  1669. {
  1670. /* This shouldn't be called. */
  1671. xassert(0);
  1672. return false;
  1673. }
  1674. extern int ba_sub_block_in_record_clear(
  1675. bg_record_t *bg_record, struct step_record *step_ptr)
  1676. {
  1677. /* this does…

Large files files are truncated, but you can click here to view the full file