URingPaxos-master/src/java/ch/usi/da/paxos/ring/InstanceSkipper.java
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.");
		}
	}

}
