123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- package classes.holonControlUnit;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import classes.AbstractCanvasObject;
- import classes.Edge;
- import classes.GroupNode;
- import classes.Holon;
- import classes.HolonObject;
- import classes.HolonSwitch;
- import classes.Node;
- import classes.holonControlUnit.messages.NeighborhoodMsg;
- import classes.holonControlUnit.messages.OrderMsg;
- import classes.holonControlUnit.messages.SplitMsg;
- import classes.holonControlUnit.messages.SplitMsg.SenderRealtion;
- import classes.holonControlUnit.messages.SplitOrderMsg;
- import classes.holonControlUnit.messages.StateMsg;
- import classes.holonControlUnit.messages.MergeMsg;
- import classes.holonControlUnit.messages.MergeOrderMsg;
- import classes.holonControlUnit.messages.Message;
- public class HierarchyControlUnit {
- private HolonControlUnit hcu;
- private String superHolon;
- private ArrayList<String> subHolons;
- private ArrayList<String> physicalNeighbors;
- private ArrayList<String> virtualNeighbors;
- private ArrayList<ArrayList<MergeMsg>> receivedMergeRequests; //store merge requests for each timestep
- private ArrayList<HashMap<String, MergeMsg>> sendMergeRequests;
- private HashMap<Integer, ArrayList<MergeMsg>> receivedMergeACKII;
- private HashMap<Integer, Boolean> alreadyMerged;
- /** stores whether the part between this holon and the child is occupied by the superholon */
- private HashMap<Holon, ArrayList<Edge>> pathsToChildren;
- private HashMap<Holon, ArrayList<Edge>> potPathsToChildren;
- private HashMap<Holon, Holon> potPathsToChildrenOcc;
- private ArrayList<String> occRequests;
-
- public HierarchyControlUnit(HolonControlUnit hcu) {
- this.hcu = hcu;
- this.subHolons = new ArrayList<>();
- this.physicalNeighbors = new ArrayList<>();
- this.virtualNeighbors = new ArrayList<>();
- this.receivedMergeRequests = new ArrayList<ArrayList<MergeMsg>>();
- this.sendMergeRequests = new ArrayList<HashMap<String, MergeMsg>>();
- this.alreadyMerged = new HashMap<>();
- this.receivedMergeACKII = new HashMap<>();
- this.pathsToChildren = new HashMap<Holon, ArrayList<Edge>>();
- this.potPathsToChildren = new HashMap<Holon, ArrayList<Edge>>();
- this.potPathsToChildrenOcc = new HashMap<Holon, Holon>();
- this.occRequests = new ArrayList<>();
- }
-
- public ArrayList<String> getPhysicalNeighbors() {
- return physicalNeighbors;
- }
- public void setPhysicalNeighbors(ArrayList<String> physicalNeighbors) {
- this.physicalNeighbors = physicalNeighbors;
- }
-
- public void addPhysicalNeighbor(String physicalNeighbor) {
- if(!this.physicalNeighbors.contains(physicalNeighbor)) {
- this.physicalNeighbors.add(physicalNeighbor);
- }
- }
- public ArrayList<String> getVirtualNeighbors() {
- return virtualNeighbors;
- }
- public void setVirtualNeighbors(ArrayList<String> virtualNeighbors) {
- this.virtualNeighbors = virtualNeighbors;
- }
-
- public void resetVirtualNeighbors() {
- this.virtualNeighbors.clear();
- }
-
- public void addSubHolon(String subHolon) {
- if(this.subHolons.contains(subHolon))
- return;
- //propagate new virtual neighbor for all subholons
- ArrayList<String> list = new ArrayList<String>();
- list.add(subHolon);
- String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, list));
- for(String sub : this.subHolons) {
- this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
- }
- if(this.subHolons.size() > 0) {
- body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, this.subHolons));
- this.hcu.getCommunicator().sendMsg(subHolon, Message.Type.NEIGHBORHOOD, body);
- }
- this.subHolons.add(subHolon);
- }
-
- public void removeSubHolon(String subHolon) {
- if(!this.subHolons.remove(subHolon)) {
- System.err.println(this.hcu.getHolon().getUniqueID()+" could not remove sub holon "+subHolon+"\n\t"+subHolons);
- return;
- }
- ArrayList<String> list = new ArrayList<String>();
- list.add(subHolon);
- String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.REMOVE_VIRTUAL_NEIGHBOR, list));
- for(String sub : this.subHolons) {
- this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
- }
- }
-
- public String getSuperHolon() {
- return this.superHolon;
- }
-
- public void setSuperHolon(String parent) {
- this.superHolon = parent;
- }
-
- public ArrayList<String> getSubHolons() {
- return this.subHolons;
- }
-
- public ArrayList<MergeMsg> getMergeRequestsForTimeStep(int timeStep){
- if(timeStep >= 0 && timeStep < this.receivedMergeRequests.size()) {
- return this.receivedMergeRequests.get(timeStep);
- }
- return new ArrayList<MergeMsg>();
- }
-
- public ArrayList<MergeMsg> getReceivedMergeAckII(int timeStep){
- return this.receivedMergeACKII.getOrDefault(timeStep, new ArrayList<>());
- }
- public HashMap<Holon, ArrayList<Edge>> getPathsToChildren() {
- return pathsToChildren;
- }
- public void addVirtualNeighbor(String virtualNeighbor) {
- if(!this.virtualNeighbors.contains(virtualNeighbor)) {
- this.virtualNeighbors.add(virtualNeighbor);
- }
- }
-
- public void addVirtualNeighbors(ArrayList<String> virtualNeighbors) {
- for(int i=0; i<virtualNeighbors.size(); i++) {
- String virtualNeighbor = virtualNeighbors.get(i);
- if(!this.virtualNeighbors.contains(virtualNeighbor))
- this.virtualNeighbors.add(virtualNeighbor);
- }
- }
-
- public void removeVirtualNeighbor(String virtualNeighbor) {
- this.virtualNeighbors.remove(virtualNeighbor);
- }
- public void removeVirtualNeighbors(ArrayList<String> virtualNeighbor) {
- this.virtualNeighbors.removeAll(virtualNeighbor);
- }
-
- public void addEdgeTo(AbstractCanvasObject b) {
- if(b instanceof HolonObject && ((HolonObject)b).holon != null) {
- //add holon of b as physical neighbor
- Holon ho = ((HolonObject) b).holon;
- if(!this.physicalNeighbors.contains(ho.getUniqueID())) {
- this.physicalNeighbors.add(ho.getUniqueID());
- }
- } else if(b instanceof HolonSwitch) {
- //get edges of b and add them if switch is open
- HolonSwitch hs = (HolonSwitch) b;
- if(!this.physicalNeighbors.contains(hs.getUniqueID())) {
- this.physicalNeighbors.add(hs.getUniqueID());
- }
- } else if(b instanceof Node) {
- Node n = (Node) b;
- if(!this.physicalNeighbors.contains(n.getUniqueID()))
- this.physicalNeighbors.add(n.getUniqueID());
- } else if (b instanceof GroupNode) {
- GroupNode n = (GroupNode) b;
- if(!this.physicalNeighbors.contains(n.getUniqueID()))
- this.physicalNeighbors.add(n.getUniqueID());
- }
- }
-
- public void removeEdgeTo(AbstractCanvasObject b) {
- if(b instanceof HolonObject) {
- //remove holon of b as physical neighbor
- Holon ho = ((HolonObject) b).holon;
- this.physicalNeighbors.remove(ho.getUniqueID());
- } else if(b instanceof HolonSwitch) {
- //get edges of b and add them if switch is open
- HolonSwitch hs = (HolonSwitch) b;
- this.physicalNeighbors.remove(hs.getUniqueID());
- } else if(b instanceof Node) {
- Node n = (Node) b;
- this.physicalNeighbors.remove(n.getUniqueID());
- } else if (b instanceof GroupNode) {
- GroupNode n = (GroupNode) b;
- this.physicalNeighbors.remove(n.getUniqueID());
-
- }
- }
-
- public void removeEdge(Edge e) {
- AbstractCanvasObject a = e.getA();
- AbstractCanvasObject b = e.getB();
- if(a.equals(this.hcu.getHolon().getHolonObject())) {
- removeEdgeTo(b);
- } else {
- removeEdgeTo(a);
- }
- //check if connection to super or subholon is affected
- Holon h = this.hcu.getHolon();
- if(h.getLayer() > 1 && h.getParent().holonControlUnit.getHierarchyController().getPathsToChildren().get(h).contains(e)) {
- //path to superholon is affected
- h.split(null);
- }
- Map<Holon, ArrayList<Edge>> set = Map.copyOf(this.pathsToChildren);
- for(Holon c : set.keySet()) {
- if(set.get(c).contains(e)) {
- //path to subholon c is affected
- c.split(null);
- }
- }
- }
-
- public void receiveMergeReq(MergeMsg msg, String sender) {
- if(!canMerge(msg.getRequester(), msg.getPower())) {
- return;
- }
-
- int timeStep = msg.getTimeStep();
- if(timeStep >= 0) {
- if(timeStep >= this.receivedMergeRequests.size() && timeStep <= this.hcu.getHolon().model.getIterations()) {
- for(int i=this.receivedMergeRequests.size(); i<=timeStep; i++) {
- this.receivedMergeRequests.add(new ArrayList<MergeMsg>());
- }
- }
- if(this.receivedMergeRequests.get(timeStep) == null)
- this.receivedMergeRequests.add(new ArrayList<MergeMsg>());
- for(MergeMsg m : this.receivedMergeRequests.get(timeStep)) {
- if(m.getPower() == msg.getPower() && m.getRequester() == msg.getRequester()
- && m.getPredictedPowerUsage() == msg.getPredictedPowerUsage() && m.getNetThroughput() == msg.getNetThroughput()) {
- if (m.getTimeStep() < msg.getTimeStep()) {
- m = msg;
- }
- System.err.println("duplicate");
- return;
- }
- }
- this.receivedMergeRequests.get(timeStep).add(msg);
- }
- }
-
- public void receiveMergeAck(MergeMsg msg, String sender) {
- if(this.superHolon.equals(sender) || this.subHolons.contains(sender) || !canMerge(msg.getRequester(), msg.getPower())
- || this.alreadyMergedAtTimeStep(msg.getTimeStep())) {
- return;
- }
-
- int i = msg.getRedirectedBy().size();
- if(msg.getTimeStep() < 1 || msg.getTimeStep()-1-i < 0)
- return;
-
- String red = i > 0 ? msg.getRedirectedBy().get(0) : sender;
- HashMap<String, MergeMsg> map = this.sendMergeRequests.get(msg.getTimeStep()-1-i);
- if(red != null && map.containsKey(red) && map.get(red).getPower() == msg.getPower()) {
- //tell sender that we are still interested in merging
- StateMsg state = new StateMsg(this.hcu.getStateEstimator().getPowerUsage(), this.hcu.getStateEstimator().getNetThroughput(),
- this.hcu.getStateEstimator().getPredictedPowerUsage(), this.hcu.getStateEstimator().getStateIndicator());
- MergeMsg m = new MergeMsg(MergeMsg.Type.ACK_II, msg.getPower(), this.hcu.getStateEstimator().getNetThroughput(),
- msg.getPredictedPowerUsage(), this.hcu.getHolon().getUniqueID(), msg.getTimeStep(), state, msg.getRedirectedBy());
- String body = this.hcu.getCommunicator().getGson().toJson(m, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(sender, Message.Type.MERGE, body);
- }
- }
-
- public void receiveMergeAckII(MergeMsg msg, String sender) {
- if(!canMerge(msg.getRequester(), msg.getPower()) || this.alreadyMergedAtTimeStep(msg.getTimeStep())) {
- return;
- }
- ArrayList<MergeMsg> list = this.receivedMergeACKII.getOrDefault(msg.getTimeStep(), new ArrayList<>());
- list.add(msg);
- this.receivedMergeACKII.put(msg.getTimeStep(), list);
- }
-
- public void receiveMergeAckIII(MergeMsg msg, String sender) {
- //dont merge with two holons at a time
- this.alreadyMerged.put(msg.getTimeStep(), true);
- if(this.hcu.getHolon().getParent().getParent() != null) {
- splitSuperHolon(msg.getTimeStep());
- }
- }
-
- public void merge(MergeMsg msg, int timeStep) {
- if(!this.canMerge(msg.getRequester(), 0f)) {
- return;
- }
- this.sendMergeAckIII(timeStep, msg);
- Holon child = this.hcu.getHolon().model.getHolonsByID().get(msg.getRequester());
- if(msg.getRedirectedBy() == null || msg.getRedirectedBy().size() == 0) {
- ArrayList<Edge> path = this.potPathsToChildren.get(child);
- if(path == null) {
- return;
- }
- this.potPathsToChildren.remove(child);
- Holon occupier = this.potPathsToChildrenOcc.get(child);
- this.potPathsToChildrenOcc.remove(child);
-
- Holon holder = this.hcu.getHolon().containsPath(path, this.hcu.getHolon());
- if(holder != null && !holder.equals(this.hcu.getHolon())) {
- //the path already used by a child holon
- //order the holder to merge with the child
- MergeOrderMsg m = new MergeOrderMsg(msg, this.hcu.getHolon().getUniqueID());
- String body = this.hcu.getCommunicator().getGson().toJson(m, MergeOrderMsg.class);
- this.hcu.getCommunicator().sendMsg(holder.getUniqueID(), Message.Type.MERGE_ORDER, body);
- this.alreadyMerged.put(timeStep, true);
- return;
- }
- this.hcu.getHolon().merge(child, path, occupier);
-
- this.hcu.getStateEstimator().receiveState(msg.getRequester(), msg.getState());
- } else {
- MergeOrderMsg m = new MergeOrderMsg(msg, this.hcu.getHolon().getUniqueID());
- String body = this.hcu.getCommunicator().getGson().toJson(m, MergeOrderMsg.class);
- this.hcu.getCommunicator().sendMsg(msg.getRedirectedBy().get(0), Message.Type.MERGE_ORDER, body);
- }
- this.alreadyMerged.put(timeStep, true);
- }
-
- public void receiveMergeOrder(MergeOrderMsg msg, String sender) {
- MergeMsg merge = msg.getOrginalMergeMsg();
- if(!this.hcu.getHolon().isASuperiorHolon(sender) || !canMerge(merge.getRequester(), merge.getPower())) {
- return;
- }
- //merge with the specified holon
- Holon child = this.hcu.getHolon().model.getHolonsByID().get(merge.getRequester());
- HashMap<Float, ArrayList<Edge>> paths = this.hcu.getHolon().model
- .getShortestPathToHolarchy(this.hcu.getHolon().getMinimumModel(), child.getMinimumModel());
- HashMap<Float, ArrayList<Edge>> free_paths = new HashMap<Float, ArrayList<Edge>>();
- for(Float f : paths.keySet()) {
- ArrayList<Edge> path = paths.get(f);
- List<Holon> holder = this.hcu.getHolon().isPathOccupied(path);
- if( holder.size() == 0 || holder.contains(this.hcu.getHolon())
- || holder.contains(this.hcu.getHolon().model.getHolonsByID().get(this.hcu.getHierarchyController().getSuperHolon()))
- || holder.contains(child)) {
- //path between this holon and child holon is free
- free_paths.put(f, path);
- }
- }
- if(free_paths.size() > 0) {
- //a free path is available
- this.hcu.getHolon().merge(child, free_paths.get(this.hcu.getHolon().getShortestPath(free_paths)), null);
-
- this.hcu.getStateEstimator().receiveState(merge.getRequester(), merge.getState());
- OrderMsg order = new OrderMsg(merge.getPower(), this.hcu.getHolon().model.getCurIteration());
- this.hcu.getCommunicator().sendMsg(merge.getRequester(), Message.Type.ORDER, this.hcu.getCommunicator().getGson().toJson(order));
- }
- }
-
- public void receiveMergeOccReq(MergeMsg msg) {
- // accept if requested power would decrease required power
- ArrayList<Float> addedPower = new ArrayList<>();
- addedPower.add(msg.getPower());
- addedPower.addAll(msg.getPredictedPowerUsage());
- if(this.hcu.decreasesPowerUsage(addedPower, this.hcu.getStateEstimator().getPowerUsage(), this.hcu.getStateEstimator().getPredictedPowerUsage(),
- this.hcu.getStateAssembler().getDesiredPowerUsage(msg.getTimeStep()))) {
- MergeMsg ack = new MergeMsg(MergeMsg.Type.OCC_ACK, msg.getPower(), msg.getNetThroughput(), msg.getPredictedPowerUsage(), msg.getRequester(),
- msg.getTimeStep(), msg.getState(), msg.getRedirectedBy());
- String body = this.hcu.getCommunicator().getGson().toJson(ack, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(msg.getRequester(), Message.Type.MERGE, body);
- }
- }
-
- public void receiveMergeOccAck(MergeMsg msg, String sender) {
- // the holon which path is reused for merging accepted to use its path
- this.occRequests.add(sender);
- }
-
- public void sendMergeReq(float powerUsage, ArrayList<Float> predictedPowerUsage, int timeStep, String physicalNeighbor) {
- MergeMsg msg = new MergeMsg(MergeMsg.Type.REQ, powerUsage, this.hcu.getStateEstimator().getNetThroughput(),
- predictedPowerUsage, this.hcu.getHolon().getUniqueID(), timeStep, null, new ArrayList<>());
- if(this.sendMergeRequests.size() <= timeStep) {
- for(int i=this.sendMergeRequests.size(); i<=timeStep; i++) {
- this.sendMergeRequests.add(new HashMap<>());
- }
- }
- this.sendMergeRequests.get(timeStep).put(physicalNeighbor, msg);
- String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(physicalNeighbor, Message.Type.MERGE, body);
- }
-
- public void sendMergeAck(int timeStep, MergeMsg req) {
- Holon child = this.hcu.getHolon().model.getHolonsByID().get(req.getRequester());
- HashMap<Float, ArrayList<Edge>> paths = this.hcu.getHolon().model
- .getShortestPathToHolarchy(this.hcu.getHolon().getMinimumModel(), child.getMinimumModel());
- HashMap<Float, ArrayList<Edge>> free_paths = new HashMap<Float, ArrayList<Edge>>();
- HashMap<Float, ArrayList<Edge>> occ_paths = new HashMap<Float, ArrayList<Edge>>();
- HashMap<ArrayList<Edge>, List<Holon>> occ_by = new HashMap<>();
- for(Float f : paths.keySet()) {
- ArrayList<Edge> path = paths.get(f);
- List<Holon> holder = this.hcu.getHolon().isPathOccupied(path);
- if( holder.size() == 0 || holder.contains(this.hcu.getHolon())
- || holder.contains(this.hcu.getHolon().model.getHolonsByID().get(this.hcu.getHierarchyController().getSuperHolon()))
- || holder.contains(child)) {
- //path between this holon and child holon is free
- free_paths.put(f, path);
- } else if(holder.size() == 1) {
- if(this.hcu.getHolon().isASubordinatedHolon(holder.get(0)) || child.isASubordinatedHolon(holder.get(0))) {
- free_paths.put(f, path);
- } else {
- //path between this holon and child holon is already occupied
- occ_paths.put(f, path);
- occ_by.put(path, holder);
- }
- }
- }
- if(free_paths.size() > 0) {
- //a free path is available, store it and inform the requester
- this.potPathsToChildren.put(child, free_paths.get(this.hcu.getHolon().getShortestPath(free_paths)));
- this.potPathsToChildrenOcc.put(child, null);
- MergeMsg msg = new MergeMsg(MergeMsg.Type.ACK, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
- this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy());
- String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, body);
- return;
- }
- //only use an occupied path when this holon runs independent
- if(occ_paths.size() > 0 && this.hcu.getHolon().getParent() != null && this.hcu.getHolon().getParent().getParent() == null) {
- //ask the occupier whether it is fine for him to merge
- //the path can only occupied by one other holon, more occupiers are not considered
- //start with shortest path
- for(ArrayList<Edge> p : this.hcu.getHolon().sortPaths(occ_paths)) {
- String occupier = occ_by.get(p).get(0).getUniqueID();
- ArrayList<Float> combinedPredictedPower = new ArrayList<>();
- for(int i=0;i<Math.min(req.getPredictedPowerUsage().size(), this.hcu.getStateEstimator().getPredictedPowerUsage().size()); i++) {
- combinedPredictedPower.add(this.hcu.getStateEstimator().getPredictedPowerUsage().get(i) + req.getPredictedPowerUsage().get(i));
- }
- MergeMsg occMsg = new MergeMsg(MergeMsg.Type.OCC_REQ, this.hcu.getStateEstimator().getPowerUsage()+req.getPower(),
- this.hcu.getStateEstimator().getNetThroughput() + req.getNetThroughput(), combinedPredictedPower, this.hcu.getHolon().getUniqueID(),
- timeStep, null, null);
- String body = this.hcu.getCommunicator().getGson().toJson(occMsg, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(occupier, Message.Type.MERGE, body);
- if(this.occRequests.contains(occupier)) {
- this.occRequests.remove(occupier);
- this.potPathsToChildren.put(child, p);
- this.potPathsToChildrenOcc.put(child, occ_by.get(p).get(0));
- //the request was accepted
- MergeMsg merge = new MergeMsg(MergeMsg.Type.ACK, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
- this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy());
- String b = this.hcu.getCommunicator().getGson().toJson(merge, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, b);
- return;
- }
- }
- return;
- }
- }
-
- public void sendMergeAckIII(int timeStep, MergeMsg req) {
- MergeMsg msg = new MergeMsg(MergeMsg.Type.ACK_III, req.getPower(), this.hcu.getStateEstimator().getNetThroughput(), req.getPredictedPowerUsage(),
- this.hcu.getHolon().getUniqueID(), timeStep, req.getState(), req.getRedirectedBy());
- String body = this.hcu.getCommunicator().getGson().toJson(msg, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(req.getRequester(), Message.Type.MERGE, body);
- }
-
- public void propagateMergeReqToParent(int timeStep) {
- if(timeStep < 0 || timeStep >= this.hcu.getHolon().model.getIterations() || timeStep >= this.receivedMergeRequests.size()
- || this.hcu.getHolon().getLayer() <= 1)
- return;
- for(MergeMsg req : this.receivedMergeRequests.get(timeStep)) {
- if(req.getRequester().equals(this.hcu.getHolon().getUniqueID()) || req.getRequester().equals(this.superHolon)
- || req.getRedirectedBy().contains(this.hcu.getHolon().getUniqueID()) || req.getRedirectedBy().contains(this.superHolon))
- continue;
- req.getRedirectedBy().add(this.hcu.getHolon().getUniqueID());
- String body = this.hcu.getCommunicator().getGson().toJson(req, MergeMsg.class);
- this.hcu.getCommunicator().sendMsg(this.superHolon, Message.Type.MERGE, body);
- }
- }
-
- public void splitSubHolon(String id, int timeStep) {
- if(!this.subHolons.contains(id)) {
- return;
- }
- if(!this.hcu.getHolon().canRunIndependent(id)) {
- //the holon can not run independent since this holon occupies an object also used by s
- this.hcu.getHierarchyController().sendSplitOrder(id, timeStep);
- return;
- }
- SplitMsg msg = new SplitMsg(SenderRealtion.SUPERHOLON, timeStep);
- String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitMsg.class);
- this.hcu.getCommunicator().sendMsg(id, Message.Type.SPLIT, body);
- this.hcu.getHolon().splitById(id);
- }
-
- public void splitSuperHolon(int timeStep) {
- SplitMsg msg = new SplitMsg(SenderRealtion.SUBHOLON, timeStep);
- String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitMsg.class);
- this.hcu.getCommunicator().sendMsg(this.superHolon, Message.Type.SPLIT, body);
- this.hcu.getHolon().split(null);
- }
-
- public void sendSplitOrder(String child, int timeStep) {
- SplitOrderMsg msg = new SplitOrderMsg(timeStep);
- String body = this.hcu.getCommunicator().getGson().toJson(msg, SplitOrderMsg.class);
- this.hcu.getCommunicator().sendMsg(child, Message.Type.SPLIT_ORDER, body);
- }
-
- public void receiveSplitOrder(SplitOrderMsg order, String sender) {
- // find the path which is occupied by the parent holon
- List<Holon> toSplit = this.hcu.getHolon().getPathToChildOccupiedByParent();
- if(!sender.equals(this.superHolon) || toSplit.size() == 0) {
- return;
- }
- for(Holon child : toSplit) {
- this.splitSubHolon(child.getUniqueID(), order.getTimeStep());
- }
- this.splitSuperHolon(order.getTimeStep());
- }
-
- public void receiveSplitMsg(SplitMsg msg, String sender) {
- if(msg.getType() == SenderRealtion.SUPERHOLON && this.superHolon.equals(sender)) {
- // System.out.println(this.hcu.getHolon().getUniqueID()+" my super holon kicked me out :(");
- } else if (msg.getType() == SenderRealtion.SUBHOLON && this.subHolons.contains(sender)) {
- // System.out.println(this.hcu.getHolon().getUniqueID()+" my child holon abandoned me :(");
- }
- }
-
- /**
- * get all physical neighbors that are not subholons (or a subholon of a subholon) and not virtual neighbors
- * @return
- */
- public ArrayList<String> getPhysicalNeighborsFromOtherHolarchy(){
- ArrayList<String> neighbors = new ArrayList<String>();
-
- for(String s : this.physicalNeighbors) {
- if(!s.contains("Switch") && !s.contains("Node") && !s.contains("Group Node") && !s.equals(this.superHolon)
- && !this.subHolons.contains(s) && !this.virtualNeighbors.contains(s)) {
- neighbors.add(s);
- } else if(s.contains("Switch") || s.contains("Node") || s.contains("Group Node")) {
- ArrayList<String> potNeighbors = this.hcu.getHolon().model.getAllConnectionsFromObject(s, this.hcu.getHolon().getUniqueID());
- for(String s2 : potNeighbors) {
- if(!s2.equals(this.superHolon) && !this.subHolons.contains(s2) && !this.virtualNeighbors.contains(s2)) {
- neighbors.add(s2);
- }
- }
- }
- }
-
- return neighbors;
- }
-
- public boolean alreadyMergedAtTimeStep(int timeStep) {
- return this.alreadyMerged.getOrDefault(timeStep, false) || (timeStep > 0 ? this.alreadyMerged.getOrDefault(timeStep-1, false) : false)
- || (timeStep > 1 ? this.alreadyMerged.getOrDefault(timeStep-2, false) : false)
- || (timeStep > 2 ? this.alreadyMerged.getOrDefault(timeStep-3, false) : false);
- }
-
- /**
- * checks if the other holon is a subholon (or subholon of subholon), this superholon or if the added throughput would burn any edges
- * @param other
- * @param addedThroughput
- * @return
- */
- public boolean canMerge(String other, float addedThroughput) {
- Holon thisHolon = this.hcu.getHolon();
- Holon otherHolon = thisHolon.model.getHolonsByID().get(other);
- if(other.equals(thisHolon.getUniqueID()) || !thisHolon.model.checkHolonObjectsAreConnected(thisHolon, otherHolon)
- || thisHolon.isASuperiorHolon(other) || otherHolon.isASuperiorHolon(this.hcu.getHolon().getUniqueID())
- || thisHolon.isASubordinatedHolon(otherHolon) || otherHolon.isASubordinatedHolon(thisHolon)) {
- // this holon and the other holon can not merge because:
- // a) this holon and other holon are the same or
- // b) other holon is not connected to this holon or the new throughput would burn a cable or
- // c) other holon is a superior holon of this holon or
- // d) this holon is a superior holon of other holon
- return false;
- }
-
- return true;
- }
-
- public boolean canSplit(String child) {
-
- return true;
- }
-
- public void resetPaths() {
- this.potPathsToChildren.clear();
- this.potPathsToChildrenOcc.clear();
- }
-
- }
|