package eu.hgross.blaubot.core; import eu.hgross.blaubot.core.statemachine.ConnectionStateMachine; import eu.hgross.blaubot.core.statemachine.states.FreeState; import eu.hgross.blaubot.core.statemachine.states.KingState; import eu.hgross.blaubot.core.statemachine.states.PeasantState; import eu.hgross.blaubot.core.statemachine.states.PrinceState; import eu.hgross.blaubot.admin.ACKPronouncePrinceAdminMessage; import eu.hgross.blaubot.admin.PronouncePrinceAdminMessage; /** * Configuration object specific to a given {@link IBlaubotAdapter} implementation. * Contains adapter specific constants. * * @author Henning Gross {@literal (mail.to@henning-gross.de)} * */ public class ConnectionStateMachineConfig { private int crowningPreparationTimeout = 850; private int kingWithoutPeasantsTimeout = 10000; private int kingdomMergeOldKingBowDownTimeout = 400; private int princeAckTimeout = 800; public ConnectionStateMachineConfig() { } public int getCrowningPreparationTimeout() { return crowningPreparationTimeout; } /** * The preparation time for the prince to be crowned. * == the time all peasants will wait before connecting to the * prince, if the king connection gets lost. * * Only relevant in {@link PeasantState} and {@link PrinceState}. * * @param crowningPreparationTimeout the preparation time */ public void setCrowningPreparationTimeout(int crowningPreparationTimeout) { this.crowningPreparationTimeout = crowningPreparationTimeout; } public int getKingWithoutPeasantsTimeout() { return kingWithoutPeasantsTimeout; } /** * The timeout after the {@link ConnectionStateMachine} will go to {@link FreeState}, * if no peasants are connected. * * Only relevant in {@link KingState} * * @param kingWithoutPeasantsTimeout the timeout */ public void setKingWithoutPeasantsTimeout(int kingWithoutPeasantsTimeout) { this.kingWithoutPeasantsTimeout = kingWithoutPeasantsTimeout; } public static void validateTimeouts(ConnectionStateMachineConfig cfg, BlaubotAdapterConfig adapterConfig) { if(cfg.getCrowningPreparationTimeout() < adapterConfig.getKeepAliveInterval()) { throw new IllegalArgumentException("The crowningPreparationTimeout should be (significantly) greater than the keep-alive interval."); } if(cfg.getKingWithoutPeasantsTimeout() < cfg.getCrowningPreparationTimeout()) { throw new IllegalArgumentException("The kingWithoutPeasantsTimeout should be (significantly) greater than crowningPreparationTimeout."); } } public int getKingdomMergeOldKingBowDownTimeout() { return kingdomMergeOldKingBowDownTimeout; } /** * This timeout is used when a king gets informed about another king and decides to bow his kingdom * down to the other king. * To do that, the king informs all peasants and the prince to join the new king. * Then he waits kingdomMergeOldKingBowDownTimeout ms before he disconnects all remaining connections * of his former peasants and prince. * After that he joins the new king himself. * * @param kingdomMergeOldKingBowDownTimeout the timeout to wait before the king cuts his peasant connections on a kingdom merger */ public void setKingdomMergeOldKingBowDownTimeout(int kingdomMergeOldKingBowDownTimeout) { this.kingdomMergeOldKingBowDownTimeout = kingdomMergeOldKingBowDownTimeout; } public int getPrinceAckTimeout() { return princeAckTimeout; } /** * After the prince gets pronounced via a {@link PronouncePrinceAdminMessage}, the pronounced device has to * respond within this timeouts time interval with an {@link ACKPronouncePrinceAdminMessage} to accept * his new position. If he does not respond fast enough, the pronouncing process is retriggered. * * @param princeAckTimeout the timeout to set */ public void setPrinceAckTimeout(int princeAckTimeout) { this.princeAckTimeout = princeAckTimeout; } }