package ch.usi.da.paxos.ring; /* * Copyright (c) 2013 Università della Svizzera italiana (USI) * * This file is part of URingPaxos. * * URingPaxos 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. * * URingPaxos 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 URingPaxos. If not, see <http://www.gnu.org/licenses/>. */ import org.apache.log4j.Logger; import ch.usi.da.paxos.api.ConfigKey; import ch.usi.da.paxos.api.PaxosRole; import ch.usi.da.paxos.message.Message; import ch.usi.da.paxos.message.MessageType; import ch.usi.da.paxos.message.Value; import ch.usi.da.paxos.storage.Promise; /** * Name: InstanceSkipper<br> * Description: <br> * * Creation date: Mar 08, 2013<br> * $Id$ * * @author Samuel Benz benz@geoid.ch */ public class InstanceSkipper implements Runnable { private final static Logger logger = Logger.getLogger(InstanceSkipper.class); private final CoordinatorRole coordinator; private final RingManager ring; private final long boot_time; private final int static_latency_compensation; public InstanceSkipper(RingManager ring,CoordinatorRole coordinator) { this.coordinator = coordinator; this.ring = ring; if(ring.getConfiguration().containsKey(ConfigKey.multi_ring_start_time)){ this.boot_time = Long.parseLong(ring.getConfiguration().get(ConfigKey.multi_ring_start_time)); }else{ this.boot_time = 0; } logger.info("InstanceSkipper use boot time: " + boot_time); String latency_compensation = System.getenv("LAT"); int static_latency; try{ if(latency_compensation != null){ static_latency = Integer.parseInt(latency_compensation); logger.warn("InstanceSkipper use static latency compensation: " + static_latency); }else{ static_latency = 0; } }catch(NumberFormatException e){ static_latency = 0; } static_latency_compensation = static_latency; } @Override public void run() { if(coordinator.multi_ring_lambda>0){ while(ring.isNodeCoordinator()){ try { long time = System.currentTimeMillis(); int latency_compensation = 0; if(static_latency_compensation == 0){ latency_compensation = static_latency_compensation; } long valueSent = coordinator.value_count.get(); float executionTime = ((float)(time-boot_time-latency_compensation)) / 1000.0f; long expectedValues = (long) ((coordinator.multi_ring_lambda) * executionTime); long skip = expectedValues - valueSent; if(skip > 0) { if(logger.isTraceEnabled()){ logger.trace(String.format("InstanceSkipper sent skip %d values", skip)); } Promise p = null; try { p = coordinator.getPromiseQueue().take(); // wait for a promise } catch (InterruptedException e) { } //send Phase2 with skip value if(p != null){ Value v = new Value(Value.getSkipID(),Long.toString(skip).getBytes()); coordinator.value_count.addAndGet(skip); Message m = new Message(p.getInstance(),ring.getNodeID(),PaxosRole.Acceptor,MessageType.Phase2,p.getBallot(),0,v); if(ring.getNetwork().getLearner() != null){ ring.getNetwork().getLearner().deliver(ring,m); } if(ring.getNetwork().getAcceptor() != null){ ring.getNetwork().getAcceptor().deliver(ring,m); }else{ // else should never happen, since there is no coordinator without acceptor! ring.getNetwork().send(m); } } } Thread.sleep(coordinator.multi_ring_delta_t); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } logger.debug("InstanceSkipper stopped."); } } }