123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- package classes.holonControlUnit;
- import java.util.ArrayList;
- import java.util.HashMap;
- 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.SplitMsg;
- import classes.holonControlUnit.messages.SplitMsg.SenderRealtion;
- import classes.holonControlUnit.messages.StateMsg;
- import classes.holonControlUnit.messages.MergeMsg;
- 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;
-
- 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>>();
- }
-
- 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<ArrayList<MergeMsg>> getMergeRequests() {
- return receivedMergeRequests;
- }
-
- public ArrayList<MergeMsg> getMergeRequestsForTimeStep(int timeStep){
- if(timeStep >= 0 && timeStep < this.receivedMergeRequests.size()) {
- return this.receivedMergeRequests.get(timeStep);
- }
- return new ArrayList<MergeMsg>();
- }
- 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().getPathsToChildren().get(h).contains(e)) {
- //path to superholon is affected
- h.merge("State Holon");
- }
- Map<Holon, ArrayList<Edge>> set = Map.copyOf(h.getPathsToChildren());
- for(Holon c : set.keySet()) {
- if(set.get(c).contains(e)) {
- //path to subholon c is affected
- c.merge("State Holon");
- }
- }
- }
-
- 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>());
- ArrayList<MergeMsg> list = this.receivedMergeRequests.get(timeStep);
- for(MergeMsg m : list) {
- if(m.getPower() == msg.getPower() && m.getRequester() == msg.getRequester() && m.getTimeStep() == msg.getTimeStep()) {
- boolean b = true;
- for(int i=0; i<m.getPredictedPowerUsage().size(); i++) {
- if(m.getPredictedPowerUsage().get(i) != msg.getPredictedPowerUsage().get(i)) {
- b = false;
- break;
- }
- }
- //the request is a duplicate
- if(b)
- return;
- }
- }
- list.add(msg);
- }
- }
-
- public void receiveMergeAck(MergeMsg msg, String sender) {
- if(this.superHolon.equals(sender) || this.subHolons.contains(sender) || !canMerge(msg.getRequester(), msg.getPower())) {
- return;
- }
-
- HashMap<String, MergeMsg> map = this.sendMergeRequests.get(msg.getTimeStep()-1);
- if(map.containsKey(sender) && this.hcu.matchPowerRange(map.get(sender).getPower(), msg.getPower(),
- map.get(sender).getPredictedPowerUsage(), this.hcu.getOptimizer().getCurrentPowerThreshold())) {
- //tell sender that we are still interested in merging
- map.clear(); //delete all merge request for this timestep so we dont merge with two holons at a time
- 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);
- return;
- }
- int i = msg.getRedirectedBy().size();
- if(msg.getTimeStep() < 1 || msg.getTimeStep()-1-i < 0)
- return;
-
- String red = i > 0 ? msg.getRedirectedBy().get(0) : null;
- map = this.sendMergeRequests.get(msg.getTimeStep()-1-i);
- if(red != null && map.containsKey(red) && this.hcu.matchPowerRange(map.get(red).getPower(), msg.getPower(),
- map.get(red).getPredictedPowerUsage(), this.hcu.getOptimizer().getCurrentPowerThreshold())) {
- //tell sender that we are still interested in merging
- map.clear(); //delete all merge request for this timestep so we dont merge with two holons at a time
- 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())) {
- return;
- }
- this.hcu.getHolon().merge(sender);
- if(msg.getRedirectedBy() == null || msg.getRedirectedBy().size() == 0) {
- this.hcu.getStateEstimator().receiveState(sender, msg.getState());
- }
- }
-
- 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) {
- 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);
- }
-
- 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))
- 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;
- 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 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;
- }
-
- /**
- * 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, addedThroughput)
- || thisHolon.isASuperiorHolon(other) || otherHolon.isASuperiorHolon(this.hcu.getHolon().getUniqueID())) {
- // this holon and the other holon can not merge because:
- // a) this holon and other holon are the same
- // b) other holon is not connected to this holon or the new throughput would burn a cable
- // c) other holon is a superior holon of this holon
- // d) this holon is a superior holon of other holon
- return false;
- }
-
- return true;
- }
- }
|