HierarchyControlUnit.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. package classes.holonControlUnit;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import classes.AbstractCanvasObject;
  6. import classes.Edge;
  7. import classes.GroupNode;
  8. import classes.Holon;
  9. import classes.HolonObject;
  10. import classes.HolonSwitch;
  11. import classes.Node;
  12. import classes.holonControlUnit.messages.NeighborhoodMsg;
  13. import classes.holonControlUnit.messages.OrderMsg;
  14. import classes.holonControlUnit.messages.SplitMsg;
  15. import classes.holonControlUnit.messages.SplitMsg.SenderRealtion;
  16. import classes.holonControlUnit.messages.StateMsg;
  17. import classes.holonControlUnit.messages.MergeMsg;
  18. import classes.holonControlUnit.messages.MergeOrderMsg;
  19. import classes.holonControlUnit.messages.Message;
  20. public class HierarchyControlUnit {
  21. private HolonControlUnit hcu;
  22. private String superHolon;
  23. private ArrayList<String> subHolons;
  24. private ArrayList<String> physicalNeighbors;
  25. private ArrayList<String> virtualNeighbors;
  26. private ArrayList<ArrayList<MergeMsg>> receivedMergeRequests; //store merge requests for each timestep
  27. private ArrayList<HashMap<String, MergeMsg>> sendMergeRequests;
  28. public HierarchyControlUnit(HolonControlUnit hcu) {
  29. this.hcu = hcu;
  30. this.subHolons = new ArrayList<>();
  31. this.physicalNeighbors = new ArrayList<>();
  32. this.virtualNeighbors = new ArrayList<>();
  33. this.receivedMergeRequests = new ArrayList<ArrayList<MergeMsg>>();
  34. this.sendMergeRequests = new ArrayList<HashMap<String, MergeMsg>>();
  35. }
  36. public ArrayList<String> getPhysicalNeighbors() {
  37. return physicalNeighbors;
  38. }
  39. public void setPhysicalNeighbors(ArrayList<String> physicalNeighbors) {
  40. this.physicalNeighbors = physicalNeighbors;
  41. }
  42. public void addPhysicalNeighbor(String physicalNeighbor) {
  43. if(!this.physicalNeighbors.contains(physicalNeighbor)) {
  44. this.physicalNeighbors.add(physicalNeighbor);
  45. }
  46. }
  47. public ArrayList<String> getVirtualNeighbors() {
  48. return virtualNeighbors;
  49. }
  50. public void setVirtualNeighbors(ArrayList<String> virtualNeighbors) {
  51. this.virtualNeighbors = virtualNeighbors;
  52. }
  53. public void resetVirtualNeighbors() {
  54. this.virtualNeighbors.clear();
  55. }
  56. public void addSubHolon(String subHolon) {
  57. if(this.subHolons.contains(subHolon))
  58. return;
  59. //propagate new virtual neighbor for all subholons
  60. ArrayList<String> list = new ArrayList<String>();
  61. list.add(subHolon);
  62. String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, list));
  63. for(String sub : this.subHolons) {
  64. this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
  65. }
  66. if(this.subHolons.size() > 0) {
  67. body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, this.subHolons));
  68. this.hcu.getCommunicator().sendMsg(subHolon, Message.Type.NEIGHBORHOOD, body);
  69. }
  70. this.subHolons.add(subHolon);
  71. }
  72. public void removeSubHolon(String subHolon) {
  73. if(!this.subHolons.remove(subHolon)) {
  74. System.err.println(this.hcu.getHolon().getUniqueID()+" could not remove sub holon "+subHolon+"\n\t"+subHolons);
  75. return;
  76. }
  77. ArrayList<String> list = new ArrayList<String>();
  78. list.add(subHolon);
  79. String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.REMOVE_VIRTUAL_NEIGHBOR, list));
  80. for(String sub : this.subHolons) {
  81. this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
  82. }
  83. }
  84. public String getSuperHolon() {
  85. return this.superHolon;
  86. }
  87. public void setSuperHolon(String parent) {
  88. this.superHolon = parent;
  89. }
  90. public ArrayList<String> getSubHolons() {
  91. return this.subHolons;
  92. }
  93. public ArrayList<ArrayList<MergeMsg>> getMergeRequests() {
  94. return receivedMergeRequests;
  95. }
  96. public ArrayList<MergeMsg> getMergeRequestsForTimeStep(int timeStep){
  97. if(timeStep >= 0 && timeStep < this.receivedMergeRequests.size()) {
  98. return this.receivedMergeRequests.get(timeStep);
  99. }
  100. return new ArrayList<MergeMsg>();
  101. }
  102. public void addVirtualNeighbor(String virtualNeighbor) {
  103. if(!this.virtualNeighbors.contains(virtualNeighbor)) {
  104. this.virtualNeighbors.add(virtualNeighbor);
  105. }
  106. }
  107. public void addVirtualNeighbors(ArrayList<String> virtualNeighbors) {
  108. for(int i=0; i<virtualNeighbors.size(); i++) {
  109. String virtualNeighbor = virtualNeighbors.get(i);
  110. if(!this.virtualNeighbors.contains(virtualNeighbor))
  111. this.virtualNeighbors.add(virtualNeighbor);
  112. }
  113. }
  114. public void removeVirtualNeighbor(String virtualNeighbor) {
  115. this.virtualNeighbors.remove(virtualNeighbor);
  116. }
  117. public void removeVirtualNeighbors(ArrayList<String> virtualNeighbor) {
  118. this.virtualNeighbors.removeAll(virtualNeighbor);
  119. }
  120. public void addEdgeTo(AbstractCanvasObject b) {
  121. if(b instanceof HolonObject && ((HolonObject)b).holon != null) {
  122. //add holon of b as physical neighbor
  123. Holon ho = ((HolonObject) b).holon;
  124. if(!this.physicalNeighbors.contains(ho.getUniqueID())) {
  125. this.physicalNeighbors.add(ho.getUniqueID());
  126. }
  127. } else if(b instanceof HolonSwitch) {
  128. //get edges of b and add them if switch is open
  129. HolonSwitch hs = (HolonSwitch) b;
  130. if(!this.physicalNeighbors.contains(hs.getUniqueID())) {
  131. this.physicalNeighbors.add(hs.getUniqueID());
  132. }
  133. } else if(b instanceof Node) {
  134. Node n = (Node) b;
  135. if(!this.physicalNeighbors.contains(n.getUniqueID()))
  136. this.physicalNeighbors.add(n.getUniqueID());
  137. } else if (b instanceof GroupNode) {
  138. GroupNode n = (GroupNode) b;
  139. if(!this.physicalNeighbors.contains(n.getUniqueID()))
  140. this.physicalNeighbors.add(n.getUniqueID());
  141. }
  142. }
  143. public void removeEdgeTo(AbstractCanvasObject b) {
  144. if(b instanceof HolonObject) {
  145. //remove holon of b as physical neighbor
  146. Holon ho = ((HolonObject) b).holon;
  147. this.physicalNeighbors.remove(ho.getUniqueID());
  148. } else if(b instanceof HolonSwitch) {
  149. //get edges of b and add them if switch is open
  150. HolonSwitch hs = (HolonSwitch) b;
  151. this.physicalNeighbors.remove(hs.getUniqueID());
  152. } else if(b instanceof Node) {
  153. Node n = (Node) b;
  154. this.physicalNeighbors.remove(n.getUniqueID());
  155. } else if (b instanceof GroupNode) {
  156. GroupNode n = (GroupNode) b;
  157. this.physicalNeighbors.remove(n.getUniqueID());
  158. }
  159. }
  160. public void removeEdge(Edge e) {
  161. AbstractCanvasObject a = e.getA();
  162. AbstractCanvasObject b = e.getB();
  163. if(a.equals(this.hcu.getHolon().getHolonObject())) {
  164. removeEdgeTo(b);
  165. } else {
  166. removeEdgeTo(a);
  167. }
  168. //check if connection to super or subholon is affected
  169. Holon h = this.hcu.getHolon();
  170. if(h.getLayer() > 1 && h.getParent().getPathsToChildren().get(h).contains(e)) {
  171. //path to superholon is affected
  172. h.merge("State Holon", true);
  173. }
  174. Map<Holon, ArrayList<Edge>> set = Map.copyOf(h.getPathsToChildren());
  175. for(Holon c : set.keySet()) {
  176. if(set.get(c).contains(e)) {
  177. //path to subholon c is affected
  178. c.merge("State Holon", true);
  179. }
  180. }
  181. }
  182. public void receiveMergeReq(MergeMsg msg, String sender) {
  183. if(!canMerge(msg.getRequester(), msg.getPower())) {
  184. return;
  185. }
  186. int timeStep = msg.getTimeStep();
  187. if(timeStep >= 0) {
  188. if(timeStep >= this.receivedMergeRequests.size() && timeStep <= this.hcu.getHolon().model.getIterations()) {
  189. for(int i=this.receivedMergeRequests.size(); i<=timeStep; i++) {
  190. this.receivedMergeRequests.add(new ArrayList<MergeMsg>());
  191. }
  192. }
  193. if(this.receivedMergeRequests.get(timeStep) == null)
  194. this.receivedMergeRequests.add(new ArrayList<MergeMsg>());
  195. for(MergeMsg m : this.receivedMergeRequests.get(timeStep)) {
  196. if(m.getPower() == msg.getPower() && m.getRequester() == msg.getRequester()
  197. && m.getPredictedPowerUsage() == msg.getPredictedPowerUsage() && m.getNetThroughput() == msg.getNetThroughput()) {
  198. if (m.getTimeStep() < msg.getTimeStep()) {
  199. m = msg;
  200. }
  201. System.err.println("duplicate");
  202. return;
  203. }
  204. }
  205. this.receivedMergeRequests.get(timeStep).add(msg);
  206. }
  207. }
  208. public void receiveMergeAck(MergeMsg msg, String sender) {
  209. // float requiredPower = this.hcu.getStateAssembler().getDesiredPowerUsage() - this.hcu.getStateEstimator().getPowerUsage();
  210. if(this.superHolon.equals(sender) || this.subHolons.contains(sender) || !canMerge(msg.getRequester(), msg.getPower())) {
  211. // || !this.hcu.decreasesPowerUsage(msg.getPredictedPowerUsage(), this.hcu.getStateEstimator().getPowerUsage(),
  212. // this.hcu.getStateEstimator().getPredictedPowerUsage(), requiredPower)) {
  213. return;
  214. }
  215. // HashMap<String, MergeMsg> map = this.sendMergeRequests.get(msg.getTimeStep()-1);
  216. // if(map.containsKey(sender) && this.hcu.matchPowerRange(map.get(sender).getPower(), msg.getPower())
  217. // && true) {
  218. // //tell sender that we are still interested in merging
  219. // map.clear(); //delete all merge request for this timestep so we dont merge with two holons at a time
  220. // StateMsg state = new StateMsg(this.hcu.getStateEstimator().getPowerUsage(), this.hcu.getStateEstimator().getNetThroughput(),
  221. // this.hcu.getStateEstimator().getPredictedPowerUsage(), this.hcu.getStateEstimator().getStateIndicator());
  222. // MergeMsg m = new MergeMsg(MergeMsg.Type.ACK_II, msg.getPower(), this.hcu.getStateEstimator().getNetThroughput(),
  223. // msg.getPredictedPowerUsage(), this.hcu.getHolon().getUniqueID(), msg.getTimeStep(), state, msg.getRedirectedBy());
  224. // String body = this.hcu.getCommunicator().getGson().toJson(m, MergeMsg.class);
  225. // this.hcu.getCommunicator().sendMsg(sender, Message.Type.MERGE, body);
  226. // return;
  227. // }
  228. int i = msg.getRedirectedBy().size();
  229. if(msg.getTimeStep() < 1 || msg.getTimeStep()-1-i < 0)
  230. return;
  231. String red = i > 0 ? msg.getRedirectedBy().get(0) : sender;
  232. HashMap<String, MergeMsg> map = this.sendMergeRequests.get(msg.getTimeStep()-1-i);
  233. if(red != null && map.containsKey(red) && this.hcu.matchPowerRange(map.get(red).getPower(), msg.getPower())) {
  234. //tell sender that we are still interested in merging
  235. map.clear(); //delete all merge request for this timestep so we dont merge with two holons at a time
  236. StateMsg state = new StateMsg(this.hcu.getStateEstimator().getPowerUsage(), this.hcu.getStateEstimator().getNetThroughput(),
  237. this.hcu.getStateEstimator().getPredictedPowerUsage(), this.hcu.getStateEstimator().getStateIndicator());
  238. MergeMsg m = new MergeMsg(MergeMsg.Type.ACK_II, msg.getPower(), this.hcu.getStateEstimator().getNetThroughput(),
  239. msg.getPredictedPowerUsage(), this.hcu.getHolon().getUniqueID(), msg.getTimeStep(), state, msg.getRedirectedBy(),
  240. msg.isAllowOccupiedPath());
  241. String body = this.hcu.getCommunicator().getGson().toJson(m, MergeMsg.class);
  242. this.hcu.getCommunicator().sendMsg(sender, Message.Type.MERGE, body);
  243. }
  244. }
  245. public void receiveMergeAckII(MergeMsg msg, String sender) {
  246. if(!canMerge(msg.getRequester(), msg.getPower())) {
  247. return;
  248. }
  249. if(msg.getRedirectedBy() == null || msg.getRedirectedBy().size() == 0) {
  250. this.hcu.getHolon().merge(sender, msg.isAllowOccupiedPath());
  251. this.hcu.getStateEstimator().receiveState(sender, msg.getState());
  252. } else {
  253. MergeOrderMsg m = new MergeOrderMsg(msg, this.hcu.getHolon().getUniqueID());
  254. String body = this.hcu.getCommunicator().getGson().toJson(m, MergeOrderMsg.class);
  255. this.hcu.getCommunicator().sendMsg(msg.getRedirectedBy().get(0), Message.Type.MERGE_ORDER, body);
  256. }
  257. }
  258. public void receiveMergeOrder(MergeOrderMsg msg, String sender) {
  259. MergeMsg merge = msg.getOrginalMergeMsg();
  260. // System.out.println(this.hcu.getHolon().getUniqueID()+" I have to merge :( "+merge.getRedirectedBy());
  261. if(!this.hcu.getHolon().isASuperiorHolon(sender) || !canMerge(merge.getRequester(),merge.getPower()))
  262. return;
  263. this.hcu.getHolon().merge(merge.getRequester(), merge.isAllowOccupiedPath());
  264. this.hcu.getStateEstimator().receiveState(merge.getRequester(), merge.getState());
  265. OrderMsg order = new OrderMsg(merge.getPower(), this.hcu.getHolon().model.getCurIteration());
  266. this.hcu.getCommunicator().sendMsg(merge.getRequester(), Message.Type.ORDER, this.hcu.getCommunicator().getGson().toJson(order));
  267. }
  268. public void sendMergeReq(float powerUsage, ArrayList<Float> predictedPowerUsage, int timeStep, String physicalNeighbor) {
  269. MergeMsg msg = new MergeMsg(MergeMsg.Type.REQ, powerUsage, this.hcu.getStateEstimator().getNetThroughput(),
  270. predictedPowerUsage, this.hcu.getHolon().getUniqueID(), timeStep, null, new ArrayList<>(), true);
  271. if(this.sendMergeRequests.size() <= timeStep) {
  272. for(int i=this.sendMergeRequests.size(); i<=timeStep; i++) {
  273. this.sendMergeRequests.add(new HashMap<>());
  274. }
  275. }
  276. this.sendMergeRequests.get(timeStep).put(physicalNeighbor, msg);
  277. String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
  278. this.hcu.getCommunicator().sendMsg(physicalNeighbor, Message.Type.MERGE, body);
  279. }
  280. public void sendMergeAck(int timeStep, MergeMsg req, boolean allowOccupiedPath) {
  281. MergeMsg msg = new MergeMsg(MergeMsg.Type.ACK, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
  282. this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy(), allowOccupiedPath);
  283. String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
  284. this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, body);
  285. }
  286. public void propagateMergeReqToParent(int timeStep) {
  287. if(timeStep < 0 || timeStep >= this.hcu.getHolon().model.getIterations() || timeStep >= this.receivedMergeRequests.size()
  288. || this.hcu.getHolon().getLayer() <= 1)
  289. return;
  290. for(MergeMsg req : this.receivedMergeRequests.get(timeStep)) {
  291. if(req.getRequester().equals(this.hcu.getHolon().getUniqueID()) || req.getRequester().equals(this.superHolon)
  292. || req.getRedirectedBy().contains(this.hcu.getHolon().getUniqueID()) || req.getRedirectedBy().contains(this.superHolon))
  293. continue;
  294. req.getRedirectedBy().add(this.hcu.getHolon().getUniqueID());
  295. String body = this.hcu.getCommunicator().getGson().toJson(req, MergeMsg.class);
  296. this.hcu.getCommunicator().sendMsg(this.superHolon, Message.Type.MERGE, body);
  297. }
  298. }
  299. public void splitSubHolon(String id, int timeStep) {
  300. if(!this.subHolons.contains(id))
  301. return;
  302. SplitMsg msg = new SplitMsg(SenderRealtion.SUPERHOLON, timeStep);
  303. String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitMsg.class);
  304. this.hcu.getCommunicator().sendMsg(id, Message.Type.SPLIT, body);
  305. this.hcu.getHolon().splitById(id);
  306. }
  307. public void splitSuperHolon(int timeStep) {
  308. SplitMsg msg = new SplitMsg(SenderRealtion.SUBHOLON, timeStep);
  309. String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitMsg.class);
  310. this.hcu.getCommunicator().sendMsg(this.superHolon, Message.Type.SPLIT, body);
  311. this.hcu.getHolon().split(null, true);
  312. }
  313. public void receiveSplitMsg(SplitMsg msg, String sender) {
  314. if(msg.getType() == SenderRealtion.SUPERHOLON && this.superHolon.equals(sender)) {
  315. // System.out.println(this.hcu.getHolon().getUniqueID()+" my super holon kicked me out :(");
  316. } else if (msg.getType() == SenderRealtion.SUBHOLON && this.subHolons.contains(sender)) {
  317. // System.out.println(this.hcu.getHolon().getUniqueID()+" my child holon abandoned me :(");
  318. }
  319. }
  320. /**
  321. * get all physical neighbors that are not subholons (or a subholon of a subholon) and not virtual neighbors
  322. * @return
  323. */
  324. public ArrayList<String> getPhysicalNeighborsFromOtherHolarchy(){
  325. ArrayList<String> neighbors = new ArrayList<String>();
  326. for(String s : this.physicalNeighbors) {
  327. if(!s.contains("Switch") && !s.contains("Node") && !s.contains("Group Node") && !s.equals(this.superHolon)
  328. && !this.subHolons.contains(s) && !this.virtualNeighbors.contains(s)) {
  329. neighbors.add(s);
  330. } else if(s.contains("Switch") || s.contains("Node") || s.contains("Group Node")) {
  331. ArrayList<String> potNeighbors = this.hcu.getHolon().model.getAllConnectionsFromObject(s, this.hcu.getHolon().getUniqueID());
  332. for(String s2 : potNeighbors) {
  333. if(!s2.equals(this.superHolon) && !this.subHolons.contains(s2) && !this.virtualNeighbors.contains(s2)) {
  334. neighbors.add(s2);
  335. }
  336. }
  337. }
  338. }
  339. return neighbors;
  340. }
  341. /**
  342. * checks if the other holon is a subholon (or subholon of subholon), this superholon or if the added throughput would burn any edges
  343. * @param other
  344. * @param addedThroughput
  345. * @return
  346. */
  347. public boolean canMerge(String other, float addedThroughput) {
  348. Holon thisHolon = this.hcu.getHolon();
  349. Holon otherHolon = thisHolon.model.getHolonsByID().get(other);
  350. if(other.equals(thisHolon.getUniqueID()) || !thisHolon.model.checkHolonObjectsAreConnected(thisHolon, otherHolon, addedThroughput)
  351. || thisHolon.isASuperiorHolon(other) || otherHolon.isASuperiorHolon(this.hcu.getHolon().getUniqueID())) {
  352. // this holon and the other holon can not merge because:
  353. // a) this holon and other holon are the same or
  354. // b) other holon is not connected to this holon or the new throughput would burn a cable or
  355. // c) other holon is a superior holon of this holon or
  356. // d) this holon is a superior holon of other holon
  357. return false;
  358. }
  359. return true;
  360. }
  361. }