/** * Copyright (c) 2007-2009 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags * * This file is part of SMaRt. * * SMaRt is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SMaRt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with SMaRt. If not, see . */ package navigators.smart.statemanagment; import java.util.Arrays; import java.util.HashSet; import java.util.Hashtable; import navigators.smart.reconfiguration.ReconfigurationManager; /** * TODO: Não sei se esta classe sera usada. Para já, deixo ficar * * Verificar se as alterações para suportar dinamismo estão corretas * @author Joao Sousa */ public class StateManager { private StateLog log; private HashSet senderEids = null; private HashSet senderStates = null; //******* EDUARDO BEGIN: estas variaveis devem ser acessadas a partir da classe ReconfigurationManager **************// //private int f; //private int n; //private int me; //******* EDUARDO END **************// private int lastEid; private int waitingEid; private int replica; private byte[] state; private ReconfigurationManager manager; public StateManager(ReconfigurationManager manager) { //******* EDUARDO BEGIN **************// this.manager = manager; int k = this.manager.getStaticConf().getCheckpointPeriod(); //******* EDUARDO END **************// this.log = new StateLog(k); senderEids = new HashSet(); senderStates = new HashSet(); this.replica = 0; if (replica == manager.getStaticConf().getProcessId()) changeReplica(); this.state = null; this.lastEid = -1; this.waitingEid = -1; } public int getReplica() { return replica; } public void changeReplica() { //******* EDUARDO BEGIN **************// int pos = -1; do { //TODO: Verificar se continua correto pos = this.manager.getCurrentViewPos(replica); replica = this.manager.getCurrentViewProcesses()[(pos + 1) % manager.getCurrentViewN()]; //replica = (replica + 1) % manager.getCurrentViewN(); //******* EDUARDO END **************// } while (replica == manager.getStaticConf().getProcessId()); } public void setReplicaState(byte[] state) { this.state = state; } public byte[] getReplicaState() { return state; } public void addEID(int sender, int eid) { senderEids.add(new SenderEid(sender, eid)); } public void emptyEIDs() { senderEids.clear(); } public void emptyEIDs(int eid) { for (SenderEid m : senderEids) if (m.eid <= eid) senderEids.remove(m); } public void addState(int sender, TransferableState state) { senderStates.add(new SenderState(sender, state)); } public void emptyStates() { senderStates.clear(); } public int getWaiting() { return waitingEid; } public void setWaiting(int wait) { this.waitingEid = wait; } public void setLastEID(int eid) { lastEid = eid; } public int getLastEID() { return lastEid; } public boolean moreThenF_EIDs(int eid) { int count = 0; HashSet replicasCounted = new HashSet(); for (SenderEid m : senderEids) { if (m.eid == eid && !replicasCounted.contains(m.sender)) { replicasCounted.add(m.sender); count++; } } //******* EDUARDO BEGIN **************// return count > manager.getCurrentViewF(); //******* EDUARDO END **************// } public boolean moreThanF_Replies() { int count = 0; HashSet replicasCounted = new HashSet(); for (SenderState m : senderStates) { if (!replicasCounted.contains(m.sender)) { replicasCounted.add(m.sender); count++; } } //******* EDUARDO BEGIN **************// return count > manager.getCurrentViewF(); //******* EDUARDO END **************// } public TransferableState getValidHash() { SenderState[] st = new SenderState[senderStates.size()]; senderStates.toArray(st); int count = 0; for (int i = 0; i < st.length; i++) { for (int j = i; j < st.length; j++) { if (st[i].state.equals(st[j].state) && st[j].state.hasState()) count++; //******* EDUARDO BEGIN **************// if (count > manager.getCurrentViewF()) return st[j].state; //******* EDUARDO END **************// } } return null; } public int getNumValidHashes() { SenderState[] st = new SenderState[senderStates.size()]; senderStates.toArray(st); int count = 0; for (int i = 0; i < st.length; i++) { for (int j = i; j < st.length; j++) { if (st[i].state.equals(st[j].state) && st[j].state.hasState()) count++; } } return count; } public int getReplies() { return senderStates.size(); } public StateLog getLog() { return log; } private class SenderEid { private int sender; private int eid; SenderEid(int sender, int eid) { this.sender = sender; this.eid = eid; } @Override public boolean equals(Object obj) { if (obj instanceof SenderEid) { SenderEid m = (SenderEid) obj; return (m.eid == this.eid && m.sender == this.sender); } return false; } @Override public int hashCode() { int hash = 1; hash = hash * 31 + this.sender; hash = hash * 31 + this.eid; return hash; } } private class SenderState { private int sender; private TransferableState state; SenderState(int sender, TransferableState state) { this.sender = sender; this.state = state; } @Override public boolean equals(Object obj) { if (obj instanceof SenderState) { SenderState m = (SenderState) obj; return (this.state.equals(m.state) && m.sender == this.sender); } return false; } @Override public int hashCode() { int hash = 1; hash = hash * 31 + this.sender; hash = hash * 31 + this.state.hashCode(); return hash; } } }