HierarchyControlUnit.java 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. package classes.holonControlUnit;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import classes.AbstractCanvasObject;
  7. import classes.Edge;
  8. import classes.GroupNode;
  9. import classes.Holon;
  10. import classes.HolonObject;
  11. import classes.HolonSwitch;
  12. import classes.Node;
  13. import classes.holonControlUnit.messages.NeighborhoodMsg;
  14. import classes.holonControlUnit.messages.OrderMsg;
  15. import classes.holonControlUnit.messages.SplitMsg;
  16. import classes.holonControlUnit.messages.SplitMsg.SenderRealtion;
  17. import classes.holonControlUnit.messages.SplitOrderMsg;
  18. import classes.holonControlUnit.messages.StateMsg;
  19. import classes.holonControlUnit.messages.MergeMsg;
  20. import classes.holonControlUnit.messages.MergeOrderMsg;
  21. import classes.holonControlUnit.messages.Message;
  22. public class HierarchyControlUnit {
  23. private HolonControlUnit hcu;
  24. private String superHolon;
  25. private ArrayList<String> subHolons;
  26. private ArrayList<String> physicalNeighbors;
  27. private ArrayList<String> virtualNeighbors;
  28. private ArrayList<ArrayList<MergeMsg>> receivedMergeRequests; //store merge requests for each timestep
  29. private ArrayList<HashMap<String, MergeMsg>> sendMergeRequests;
  30. private HashMap<Integer, ArrayList<MergeMsg>> receivedMergeACKII;
  31. private HashMap<Integer, Boolean> alreadyMerged;
  32. /** stores whether the part between this holon and the child is occupied by the superholon */
  33. private HashMap<Holon, ArrayList<Edge>> pathsToChildren;
  34. private HashMap<Holon, ArrayList<Edge>> potPathsToChildren;
  35. private HashMap<Holon, Holon> potPathsToChildrenOcc;
  36. private ArrayList<String> occRequests;
  37. public HierarchyControlUnit(HolonControlUnit hcu) {
  38. this.hcu = hcu;
  39. this.subHolons = new ArrayList<>();
  40. this.physicalNeighbors = new ArrayList<>();
  41. this.virtualNeighbors = new ArrayList<>();
  42. this.receivedMergeRequests = new ArrayList<ArrayList<MergeMsg>>();
  43. this.sendMergeRequests = new ArrayList<HashMap<String, MergeMsg>>();
  44. this.alreadyMerged = new HashMap<>();
  45. this.receivedMergeACKII = new HashMap<>();
  46. this.pathsToChildren = new HashMap<Holon, ArrayList<Edge>>();
  47. this.potPathsToChildren = new HashMap<Holon, ArrayList<Edge>>();
  48. this.potPathsToChildrenOcc = new HashMap<Holon, Holon>();
  49. this.occRequests = new ArrayList<>();
  50. }
  51. public ArrayList<String> getPhysicalNeighbors() {
  52. return physicalNeighbors;
  53. }
  54. public void setPhysicalNeighbors(ArrayList<String> physicalNeighbors) {
  55. this.physicalNeighbors = physicalNeighbors;
  56. }
  57. public void addPhysicalNeighbor(String physicalNeighbor) {
  58. if(!this.physicalNeighbors.contains(physicalNeighbor)) {
  59. this.physicalNeighbors.add(physicalNeighbor);
  60. }
  61. }
  62. public ArrayList<String> getVirtualNeighbors() {
  63. return virtualNeighbors;
  64. }
  65. public void setVirtualNeighbors(ArrayList<String> virtualNeighbors) {
  66. this.virtualNeighbors = virtualNeighbors;
  67. }
  68. public void resetVirtualNeighbors() {
  69. this.virtualNeighbors.clear();
  70. }
  71. public void addSubHolon(String subHolon) {
  72. if(this.subHolons.contains(subHolon))
  73. return;
  74. //propagate new virtual neighbor for all subholons
  75. ArrayList<String> list = new ArrayList<String>();
  76. list.add(subHolon);
  77. String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, list));
  78. for(String sub : this.subHolons) {
  79. this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
  80. }
  81. if(this.subHolons.size() > 0) {
  82. body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, this.subHolons));
  83. this.hcu.getCommunicator().sendMsg(subHolon, Message.Type.NEIGHBORHOOD, body);
  84. }
  85. this.subHolons.add(subHolon);
  86. }
  87. public void removeSubHolon(String subHolon) {
  88. if(!this.subHolons.remove(subHolon)) {
  89. System.err.println(this.hcu.getHolon().getUniqueID()+" could not remove sub holon "+subHolon+"\n\t"+subHolons);
  90. return;
  91. }
  92. ArrayList<String> list = new ArrayList<String>();
  93. list.add(subHolon);
  94. String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.REMOVE_VIRTUAL_NEIGHBOR, list));
  95. for(String sub : this.subHolons) {
  96. this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
  97. }
  98. }
  99. public String getSuperHolon() {
  100. return this.superHolon;
  101. }
  102. public void setSuperHolon(String parent) {
  103. this.superHolon = parent;
  104. }
  105. public ArrayList<String> getSubHolons() {
  106. return this.subHolons;
  107. }
  108. public ArrayList<MergeMsg> getMergeRequestsForTimeStep(int timeStep){
  109. if(timeStep >= 0 && timeStep < this.receivedMergeRequests.size()) {
  110. return this.receivedMergeRequests.get(timeStep);
  111. }
  112. return new ArrayList<MergeMsg>();
  113. }
  114. public ArrayList<MergeMsg> getReceivedMergeAckII(int timeStep){
  115. return this.receivedMergeACKII.getOrDefault(timeStep, new ArrayList<>());
  116. }
  117. public HashMap<Holon, ArrayList<Edge>> getPathsToChildren() {
  118. return pathsToChildren;
  119. }
  120. public void addVirtualNeighbor(String virtualNeighbor) {
  121. if(!this.virtualNeighbors.contains(virtualNeighbor)) {
  122. this.virtualNeighbors.add(virtualNeighbor);
  123. }
  124. }
  125. public void addVirtualNeighbors(ArrayList<String> virtualNeighbors) {
  126. for(int i=0; i<virtualNeighbors.size(); i++) {
  127. String virtualNeighbor = virtualNeighbors.get(i);
  128. if(!this.virtualNeighbors.contains(virtualNeighbor))
  129. this.virtualNeighbors.add(virtualNeighbor);
  130. }
  131. }
  132. public void removeVirtualNeighbor(String virtualNeighbor) {
  133. this.virtualNeighbors.remove(virtualNeighbor);
  134. }
  135. public void removeVirtualNeighbors(ArrayList<String> virtualNeighbor) {
  136. this.virtualNeighbors.removeAll(virtualNeighbor);
  137. }
  138. public void addEdgeTo(AbstractCanvasObject b) {
  139. if(b instanceof HolonObject && ((HolonObject)b).holon != null) {
  140. //add holon of b as physical neighbor
  141. Holon ho = ((HolonObject) b).holon;
  142. if(!this.physicalNeighbors.contains(ho.getUniqueID())) {
  143. this.physicalNeighbors.add(ho.getUniqueID());
  144. }
  145. } else if(b instanceof HolonSwitch) {
  146. //get edges of b and add them if switch is open
  147. HolonSwitch hs = (HolonSwitch) b;
  148. if(!this.physicalNeighbors.contains(hs.getUniqueID())) {
  149. this.physicalNeighbors.add(hs.getUniqueID());
  150. }
  151. } else if(b instanceof Node) {
  152. Node n = (Node) b;
  153. if(!this.physicalNeighbors.contains(n.getUniqueID()))
  154. this.physicalNeighbors.add(n.getUniqueID());
  155. } else if (b instanceof GroupNode) {
  156. GroupNode n = (GroupNode) b;
  157. if(!this.physicalNeighbors.contains(n.getUniqueID()))
  158. this.physicalNeighbors.add(n.getUniqueID());
  159. }
  160. }
  161. public void removeEdgeTo(AbstractCanvasObject b) {
  162. if(b instanceof HolonObject) {
  163. //remove holon of b as physical neighbor
  164. Holon ho = ((HolonObject) b).holon;
  165. this.physicalNeighbors.remove(ho.getUniqueID());
  166. } else if(b instanceof HolonSwitch) {
  167. //get edges of b and add them if switch is open
  168. HolonSwitch hs = (HolonSwitch) b;
  169. this.physicalNeighbors.remove(hs.getUniqueID());
  170. } else if(b instanceof Node) {
  171. Node n = (Node) b;
  172. this.physicalNeighbors.remove(n.getUniqueID());
  173. } else if (b instanceof GroupNode) {
  174. GroupNode n = (GroupNode) b;
  175. this.physicalNeighbors.remove(n.getUniqueID());
  176. }
  177. }
  178. public void removeEdge(Edge e) {
  179. AbstractCanvasObject a = e.getA();
  180. AbstractCanvasObject b = e.getB();
  181. if(a.equals(this.hcu.getHolon().getHolonObject())) {
  182. removeEdgeTo(b);
  183. } else {
  184. removeEdgeTo(a);
  185. }
  186. //check if connection to super or subholon is affected
  187. Holon h = this.hcu.getHolon();
  188. if(h.getLayer() > 1 && h.getParent().holonControlUnit.getHierarchyController().getPathsToChildren().get(h).contains(e)) {
  189. //path to superholon is affected
  190. h.split(null);
  191. }
  192. Map<Holon, ArrayList<Edge>> set = Map.copyOf(this.pathsToChildren);
  193. for(Holon c : set.keySet()) {
  194. if(set.get(c).contains(e)) {
  195. //path to subholon c is affected
  196. c.split(null);
  197. }
  198. }
  199. }
  200. public void receiveMergeReq(MergeMsg msg, String sender) {
  201. if(!canMerge(msg.getRequester(), msg.getPower())) {
  202. return;
  203. }
  204. int timeStep = msg.getTimeStep();
  205. if(timeStep >= 0) {
  206. if(timeStep >= this.receivedMergeRequests.size() && timeStep <= this.hcu.getHolon().model.getIterations()) {
  207. for(int i=this.receivedMergeRequests.size(); i<=timeStep; i++) {
  208. this.receivedMergeRequests.add(new ArrayList<MergeMsg>());
  209. }
  210. }
  211. if(this.receivedMergeRequests.get(timeStep) == null)
  212. this.receivedMergeRequests.add(new ArrayList<MergeMsg>());
  213. for(MergeMsg m : this.receivedMergeRequests.get(timeStep)) {
  214. if(m.getPower() == msg.getPower() && m.getRequester() == msg.getRequester()
  215. && m.getPredictedPowerUsage() == msg.getPredictedPowerUsage() && m.getNetThroughput() == msg.getNetThroughput()) {
  216. if (m.getTimeStep() < msg.getTimeStep()) {
  217. m = msg;
  218. }
  219. System.err.println("duplicate");
  220. return;
  221. }
  222. }
  223. this.receivedMergeRequests.get(timeStep).add(msg);
  224. }
  225. }
  226. public void receiveMergeAck(MergeMsg msg, String sender) {
  227. if(this.superHolon.equals(sender) || this.subHolons.contains(sender) || !canMerge(msg.getRequester(), msg.getPower())
  228. || this.alreadyMergedAtTimeStep(msg.getTimeStep())) {
  229. return;
  230. }
  231. int i = msg.getRedirectedBy().size();
  232. if(msg.getTimeStep() < 1 || msg.getTimeStep()-1-i < 0)
  233. return;
  234. String red = i > 0 ? msg.getRedirectedBy().get(0) : sender;
  235. HashMap<String, MergeMsg> map = this.sendMergeRequests.get(msg.getTimeStep()-1-i);
  236. if(red != null && map.containsKey(red) && map.get(red).getPower() == msg.getPower()) {
  237. //tell sender that we are still interested in merging
  238. StateMsg state = new StateMsg(this.hcu.getStateEstimator().getPowerUsage(), this.hcu.getStateEstimator().getNetThroughput(),
  239. this.hcu.getStateEstimator().getPredictedPowerUsage(), this.hcu.getStateEstimator().getStateIndicator());
  240. MergeMsg m = new MergeMsg(MergeMsg.Type.ACK_II, msg.getPower(), this.hcu.getStateEstimator().getNetThroughput(),
  241. msg.getPredictedPowerUsage(), this.hcu.getHolon().getUniqueID(), msg.getTimeStep(), state, msg.getRedirectedBy());
  242. String body = this.hcu.getCommunicator().getGson().toJson(m, MergeMsg.class);
  243. this.hcu.getCommunicator().sendMsg(sender, Message.Type.MERGE, body);
  244. }
  245. }
  246. public void receiveMergeAckII(MergeMsg msg, String sender) {
  247. if(!canMerge(msg.getRequester(), msg.getPower()) || this.alreadyMergedAtTimeStep(msg.getTimeStep())) {
  248. return;
  249. }
  250. ArrayList<MergeMsg> list = this.receivedMergeACKII.getOrDefault(msg.getTimeStep(), new ArrayList<>());
  251. list.add(msg);
  252. this.receivedMergeACKII.put(msg.getTimeStep(), list);
  253. }
  254. public void receiveMergeAckIII(MergeMsg msg, String sender) {
  255. //dont merge with two holons at a time
  256. this.alreadyMerged.put(msg.getTimeStep(), true);
  257. if(this.hcu.getHolon().getParent().getParent() != null) {
  258. splitSuperHolon(msg.getTimeStep());
  259. }
  260. }
  261. public void merge(MergeMsg msg, int timeStep) {
  262. if(!this.canMerge(msg.getRequester(), 0f)) {
  263. return;
  264. }
  265. this.sendMergeAckIII(timeStep, msg);
  266. Holon child = this.hcu.getHolon().model.getHolonsByID().get(msg.getRequester());
  267. if(msg.getRedirectedBy() == null || msg.getRedirectedBy().size() == 0) {
  268. ArrayList<Edge> path = this.potPathsToChildren.get(child);
  269. if(path == null) {
  270. return;
  271. }
  272. this.potPathsToChildren.remove(child);
  273. Holon occupier = this.potPathsToChildrenOcc.get(child);
  274. this.potPathsToChildrenOcc.remove(child);
  275. Holon holder = this.hcu.getHolon().containsPath(path, this.hcu.getHolon());
  276. if(holder != null && !holder.equals(this.hcu.getHolon())) {
  277. //the path already used by a child holon
  278. //order the holder to merge with the child
  279. MergeOrderMsg m = new MergeOrderMsg(msg, this.hcu.getHolon().getUniqueID());
  280. String body = this.hcu.getCommunicator().getGson().toJson(m, MergeOrderMsg.class);
  281. this.hcu.getCommunicator().sendMsg(holder.getUniqueID(), Message.Type.MERGE_ORDER, body);
  282. this.alreadyMerged.put(timeStep, true);
  283. return;
  284. }
  285. this.hcu.getHolon().merge(child, path, occupier);
  286. this.hcu.getStateEstimator().receiveState(msg.getRequester(), msg.getState());
  287. } else {
  288. MergeOrderMsg m = new MergeOrderMsg(msg, this.hcu.getHolon().getUniqueID());
  289. String body = this.hcu.getCommunicator().getGson().toJson(m, MergeOrderMsg.class);
  290. this.hcu.getCommunicator().sendMsg(msg.getRedirectedBy().get(0), Message.Type.MERGE_ORDER, body);
  291. }
  292. this.alreadyMerged.put(timeStep, true);
  293. }
  294. public void receiveMergeOrder(MergeOrderMsg msg, String sender) {
  295. MergeMsg merge = msg.getOrginalMergeMsg();
  296. if(!this.hcu.getHolon().isASuperiorHolon(sender) || !canMerge(merge.getRequester(), merge.getPower())) {
  297. return;
  298. }
  299. //merge with the specified holon
  300. Holon child = this.hcu.getHolon().model.getHolonsByID().get(merge.getRequester());
  301. HashMap<Float, ArrayList<Edge>> paths = this.hcu.getHolon().model
  302. .getShortestPathToHolarchy(this.hcu.getHolon().getMinimumModel(), child.getMinimumModel());
  303. HashMap<Float, ArrayList<Edge>> free_paths = new HashMap<Float, ArrayList<Edge>>();
  304. for(Float f : paths.keySet()) {
  305. ArrayList<Edge> path = paths.get(f);
  306. List<Holon> holder = this.hcu.getHolon().isPathOccupied(path);
  307. if( holder.size() == 0 || holder.contains(this.hcu.getHolon())
  308. || holder.contains(this.hcu.getHolon().model.getHolonsByID().get(this.hcu.getHierarchyController().getSuperHolon()))
  309. || holder.contains(child)) {
  310. //path between this holon and child holon is free
  311. free_paths.put(f, path);
  312. }
  313. }
  314. if(free_paths.size() > 0) {
  315. //a free path is available
  316. this.hcu.getHolon().merge(child, free_paths.get(this.hcu.getHolon().getShortestPath(free_paths)), null);
  317. this.hcu.getStateEstimator().receiveState(merge.getRequester(), merge.getState());
  318. OrderMsg order = new OrderMsg(merge.getPower(), this.hcu.getHolon().model.getCurIteration());
  319. this.hcu.getCommunicator().sendMsg(merge.getRequester(), Message.Type.ORDER, this.hcu.getCommunicator().getGson().toJson(order));
  320. }
  321. }
  322. public void receiveMergeOccReq(MergeMsg msg) {
  323. // accept if requested power would decrease required power
  324. ArrayList<Float> addedPower = new ArrayList<>();
  325. addedPower.add(msg.getPower());
  326. addedPower.addAll(msg.getPredictedPowerUsage());
  327. if(this.hcu.decreasesPowerUsage(addedPower, this.hcu.getStateEstimator().getPowerUsage(), this.hcu.getStateEstimator().getPredictedPowerUsage(),
  328. this.hcu.getStateAssembler().getDesiredPowerUsage(msg.getTimeStep()))) {
  329. MergeMsg ack = new MergeMsg(MergeMsg.Type.OCC_ACK, msg.getPower(), msg.getNetThroughput(), msg.getPredictedPowerUsage(), msg.getRequester(),
  330. msg.getTimeStep(), msg.getState(), msg.getRedirectedBy());
  331. String body = this.hcu.getCommunicator().getGson().toJson(ack, MergeMsg.class);
  332. this.hcu.getCommunicator().sendMsg(msg.getRequester(), Message.Type.MERGE, body);
  333. }
  334. }
  335. public void receiveMergeOccAck(MergeMsg msg, String sender) {
  336. // the holon which path is reused for merging accepted to use its path
  337. this.occRequests.add(sender);
  338. }
  339. public void sendMergeReq(float powerUsage, ArrayList<Float> predictedPowerUsage, int timeStep, String physicalNeighbor) {
  340. MergeMsg msg = new MergeMsg(MergeMsg.Type.REQ, powerUsage, this.hcu.getStateEstimator().getNetThroughput(),
  341. predictedPowerUsage, this.hcu.getHolon().getUniqueID(), timeStep, null, new ArrayList<>());
  342. if(this.sendMergeRequests.size() <= timeStep) {
  343. for(int i=this.sendMergeRequests.size(); i<=timeStep; i++) {
  344. this.sendMergeRequests.add(new HashMap<>());
  345. }
  346. }
  347. this.sendMergeRequests.get(timeStep).put(physicalNeighbor, msg);
  348. String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
  349. this.hcu.getCommunicator().sendMsg(physicalNeighbor, Message.Type.MERGE, body);
  350. }
  351. public void sendMergeAck(int timeStep, MergeMsg req) {
  352. Holon child = this.hcu.getHolon().model.getHolonsByID().get(req.getRequester());
  353. HashMap<Float, ArrayList<Edge>> paths = this.hcu.getHolon().model
  354. .getShortestPathToHolarchy(this.hcu.getHolon().getMinimumModel(), child.getMinimumModel());
  355. HashMap<Float, ArrayList<Edge>> free_paths = new HashMap<Float, ArrayList<Edge>>();
  356. HashMap<Float, ArrayList<Edge>> occ_paths = new HashMap<Float, ArrayList<Edge>>();
  357. HashMap<ArrayList<Edge>, List<Holon>> occ_by = new HashMap<>();
  358. for(Float f : paths.keySet()) {
  359. ArrayList<Edge> path = paths.get(f);
  360. List<Holon> holder = this.hcu.getHolon().isPathOccupied(path);
  361. if( holder.size() == 0 || holder.contains(this.hcu.getHolon())
  362. || holder.contains(this.hcu.getHolon().model.getHolonsByID().get(this.hcu.getHierarchyController().getSuperHolon()))
  363. || holder.contains(child)) {
  364. //path between this holon and child holon is free
  365. free_paths.put(f, path);
  366. } else if(holder.size() == 1) {
  367. if(this.hcu.getHolon().isASubordinatedHolon(holder.get(0)) || child.isASubordinatedHolon(holder.get(0))) {
  368. free_paths.put(f, path);
  369. } else {
  370. //path between this holon and child holon is already occupied
  371. occ_paths.put(f, path);
  372. occ_by.put(path, holder);
  373. }
  374. }
  375. }
  376. if(free_paths.size() > 0) {
  377. //a free path is available, store it and inform the requester
  378. this.potPathsToChildren.put(child, free_paths.get(this.hcu.getHolon().getShortestPath(free_paths)));
  379. this.potPathsToChildrenOcc.put(child, null);
  380. MergeMsg msg = new MergeMsg(MergeMsg.Type.ACK, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
  381. this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy());
  382. String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
  383. this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, body);
  384. return;
  385. }
  386. //only use an occupied path when this holon runs independent
  387. if(occ_paths.size() > 0 && this.hcu.getHolon().getParent() != null && this.hcu.getHolon().getParent().getParent() == null) {
  388. //ask the occupier whether it is fine for him to merge
  389. //the path can only occupied by one other holon, more occupiers are not considered
  390. //start with shortest path
  391. for(ArrayList<Edge> p : this.hcu.getHolon().sortPaths(occ_paths)) {
  392. String occupier = occ_by.get(p).get(0).getUniqueID();
  393. ArrayList<Float> combinedPredictedPower = new ArrayList<>();
  394. for(int i=0;i<Math.min(req.getPredictedPowerUsage().size(), this.hcu.getStateEstimator().getPredictedPowerUsage().size()); i++) {
  395. combinedPredictedPower.add(this.hcu.getStateEstimator().getPredictedPowerUsage().get(i) + req.getPredictedPowerUsage().get(i));
  396. }
  397. MergeMsg occMsg = new MergeMsg(MergeMsg.Type.OCC_REQ, this.hcu.getStateEstimator().getPowerUsage()+req.getPower(),
  398. this.hcu.getStateEstimator().getNetThroughput() + req.getNetThroughput(), combinedPredictedPower, this.hcu.getHolon().getUniqueID(),
  399. timeStep, null, null);
  400. String body = this.hcu.getCommunicator().getGson().toJson(occMsg, MergeMsg.class);
  401. this.hcu.getCommunicator().sendMsg(occupier, Message.Type.MERGE, body);
  402. if(this.occRequests.contains(occupier)) {
  403. this.occRequests.remove(occupier);
  404. this.potPathsToChildren.put(child, p);
  405. this.potPathsToChildrenOcc.put(child, occ_by.get(p).get(0));
  406. //the request was accepted
  407. MergeMsg merge = new MergeMsg(MergeMsg.Type.ACK, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
  408. this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy());
  409. String b = this.hcu.getCommunicator().getGson().toJson(merge, MergeMsg.class);
  410. this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, b);
  411. return;
  412. }
  413. }
  414. return;
  415. }
  416. }
  417. public void sendMergeAckIII(int timeStep, MergeMsg req) {
  418. MergeMsg msg = new MergeMsg(MergeMsg.Type.ACK_III, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
  419. this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy());
  420. String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
  421. this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, body);
  422. }
  423. public void propagateMergeReqToParent(int timeStep) {
  424. if(timeStep < 0 || timeStep >= this.hcu.getHolon().model.getIterations() || timeStep >= this.receivedMergeRequests.size()
  425. || this.hcu.getHolon().getLayer() <= 1)
  426. return;
  427. for(MergeMsg req : this.receivedMergeRequests.get(timeStep)) {
  428. if(req.getRequester().equals(this.hcu.getHolon().getUniqueID()) || req.getRequester().equals(this.superHolon)
  429. || req.getRedirectedBy().contains(this.hcu.getHolon().getUniqueID()) || req.getRedirectedBy().contains(this.superHolon))
  430. continue;
  431. req.getRedirectedBy().add(this.hcu.getHolon().getUniqueID());
  432. String body = this.hcu.getCommunicator().getGson().toJson(req, MergeMsg.class);
  433. this.hcu.getCommunicator().sendMsg(this.superHolon, Message.Type.MERGE, body);
  434. }
  435. }
  436. public void splitSubHolon(String id, int timeStep) {
  437. if(!this.subHolons.contains(id)) {
  438. return;
  439. }
  440. if(!this.hcu.getHolon().canRunIndependent(id)) {
  441. //the holon can not run independent since this holon occupies an object also used by s
  442. this.hcu.getHierarchyController().sendSplitOrder(id, timeStep);
  443. return;
  444. }
  445. SplitMsg msg = new SplitMsg(SenderRealtion.SUPERHOLON, timeStep);
  446. String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitMsg.class);
  447. this.hcu.getCommunicator().sendMsg(id, Message.Type.SPLIT, body);
  448. this.hcu.getHolon().splitById(id);
  449. }
  450. public void splitSuperHolon(int timeStep) {
  451. SplitMsg msg = new SplitMsg(SenderRealtion.SUBHOLON, timeStep);
  452. String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitMsg.class);
  453. this.hcu.getCommunicator().sendMsg(this.superHolon, Message.Type.SPLIT, body);
  454. this.hcu.getHolon().split(null);
  455. }
  456. public void sendSplitOrder(String child, int timeStep) {
  457. SplitOrderMsg msg = new SplitOrderMsg(timeStep);
  458. String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitOrderMsg.class);
  459. this.hcu.getCommunicator().sendMsg(child, Message.Type.SPLIT_ORDER, body);
  460. }
  461. public void receiveSplitOrder(SplitOrderMsg order, String sender) {
  462. // find the path which is occupied by the parent holon
  463. List<Holon> toSplit = this.hcu.getHolon().getPathToChildOccupiedByParent();
  464. if(!sender.equals(this.superHolon) || toSplit.size() == 0) {
  465. return;
  466. }
  467. for(Holon child : toSplit) {
  468. this.splitSubHolon(child.getUniqueID(), order.getTimeStep());
  469. }
  470. this.splitSuperHolon(order.getTimeStep());
  471. }
  472. public void receiveSplitMsg(SplitMsg msg, String sender) {
  473. if(msg.getType() == SenderRealtion.SUPERHOLON && this.superHolon.equals(sender)) {
  474. // System.out.println(this.hcu.getHolon().getUniqueID()+" my super holon kicked me out :(");
  475. } else if (msg.getType() == SenderRealtion.SUBHOLON && this.subHolons.contains(sender)) {
  476. // System.out.println(this.hcu.getHolon().getUniqueID()+" my child holon abandoned me :(");
  477. }
  478. }
  479. /**
  480. * get all physical neighbors that are not subholons (or a subholon of a subholon) and not virtual neighbors
  481. * @return
  482. */
  483. public ArrayList<String> getPhysicalNeighborsFromOtherHolarchy(){
  484. ArrayList<String> neighbors = new ArrayList<String>();
  485. for(String s : this.physicalNeighbors) {
  486. if(!s.contains("Switch") && !s.contains("Node") && !s.contains("Group Node") && !s.equals(this.superHolon)
  487. && !this.subHolons.contains(s) && !this.virtualNeighbors.contains(s)) {
  488. neighbors.add(s);
  489. } else if(s.contains("Switch") || s.contains("Node") || s.contains("Group Node")) {
  490. ArrayList<String> potNeighbors = this.hcu.getHolon().model.getAllConnectionsFromObject(s, this.hcu.getHolon().getUniqueID());
  491. for(String s2 : potNeighbors) {
  492. if(!s2.equals(this.superHolon) && !this.subHolons.contains(s2) && !this.virtualNeighbors.contains(s2)) {
  493. neighbors.add(s2);
  494. }
  495. }
  496. }
  497. }
  498. return neighbors;
  499. }
  500. public boolean alreadyMergedAtTimeStep(int timeStep) {
  501. return this.alreadyMerged.getOrDefault(timeStep, false) || (timeStep > 0 ? this.alreadyMerged.getOrDefault(timeStep-1, false) : false)
  502. || (timeStep > 1 ? this.alreadyMerged.getOrDefault(timeStep-2, false) : false)
  503. || (timeStep > 2 ? this.alreadyMerged.getOrDefault(timeStep-3, false) : false);
  504. }
  505. /**
  506. * checks if the other holon is a subholon (or subholon of subholon), this superholon or if the added throughput would burn any edges
  507. * @param other
  508. * @param addedThroughput
  509. * @return
  510. */
  511. public boolean canMerge(String other, float addedThroughput) {
  512. Holon thisHolon = this.hcu.getHolon();
  513. Holon otherHolon = thisHolon.model.getHolonsByID().get(other);
  514. if(other.equals(thisHolon.getUniqueID()) || !thisHolon.model.checkHolonObjectsAreConnected(thisHolon, otherHolon)
  515. || thisHolon.isASuperiorHolon(other) || otherHolon.isASuperiorHolon(this.hcu.getHolon().getUniqueID())
  516. || thisHolon.isASubordinatedHolon(otherHolon) || otherHolon.isASubordinatedHolon(thisHolon)) {
  517. // this holon and the other holon can not merge because:
  518. // a) this holon and other holon are the same or
  519. // b) other holon is not connected to this holon or the new throughput would burn a cable or
  520. // c) other holon is a superior holon of this holon or
  521. // d) this holon is a superior holon of other holon
  522. return false;
  523. }
  524. return true;
  525. }
  526. public boolean canSplit(String child) {
  527. return true;
  528. }
  529. public void resetPaths() {
  530. this.potPathsToChildren.clear();
  531. this.potPathsToChildrenOcc.clear();
  532. }
  533. }