package ch.usi.da.paxos.old; /* * 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 java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicLong; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.EventType; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; import ch.usi.da.paxos.message.Value; import ch.usi.da.paxos.storage.Promise; /** * Name: Proposer<br> * Description: <br> * * Creation date: Apr 1, 2012<br> * $Id$ * * @author Samuel Benz benz@geoid.ch */ public class Proposer implements Watcher { private final int threadCount = 5; /** * Server start time */ public final long start_time = System.currentTimeMillis(); private final int ID; private volatile boolean leader = false; private final ZooKeeper zoo; private final String path = "/paxos"; private AtomicLong globalInstance = new AtomicLong(); private final ExecutorService executer = Executors.newFixedThreadPool(threadCount); private final ExecutorService leader_sender = Executors.newFixedThreadPool(threadCount); private final ExecutorService reserver = Executors.newFixedThreadPool(1); private final ExecutorService leader_listener = Executors.newFixedThreadPool(1); private final BlockingQueue<Value> values = new LinkedBlockingQueue<Value>(500); private final BlockingQueue<Promise> promises = new LinkedBlockingQueue<Promise>(10); private volatile boolean perf_test = false; private final AtomicLong send_count = new AtomicLong(0); private final AtomicLong recv_count = new AtomicLong(0); private final AtomicLong recv_bytes = new AtomicLong(0); /** * Public constructor * * @param id proposer id * @param config path to config file * @throws IOException */ public Proposer(int id,String config) throws IOException{ this.ID = id; if(Configuration.getConfiguration().isEmpty()){ Configuration.read(config); } zoo = new ZooKeeper(Configuration.zookeeper,3000,this); init(); } private void init() throws IOException{ setLeader(true); // initially everybody is a leader // register the leader selection watcher try { if(zoo.exists(path,false) == null){ zoo.create(path,null,Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); } zoo.getChildren(path, true); // start watching zoo.create(path + "/" + this.getID(),null,Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL); } catch (Exception e) { //e.printStackTrace(); System.out.println("Running without zookeeper. So no leader election!"); } } /** * Get the proposer ID * * @return the ID */ public int getID() { return ID; } /** * @return the send counter */ public AtomicLong getSendCount(){ return send_count; } /** * @return the receive counter */ public AtomicLong getRecvCount(){ return recv_count; } /** * @return the receive counter */ public AtomicLong getRecvBytes(){ return recv_bytes; } /** * @return if performance test is enabled */ public boolean isPerfTest(){ return perf_test; } /** * @param b */ public void setPerfTest(boolean b){ perf_test = b; } /** * Is this proposer a leader * * @return is leader */ public boolean isLeader(){ return leader; } /** * Set the leader state * * @param l true if this is a leader * @throws IOException */ public synchronized void setLeader(boolean l) throws IOException{ boolean old = leader; leader = l; if(old == false && l == true){ // proposer -> leader leader_listener.execute(new LeaderListener(this)); for(int n=0;n<threadCount;n++){ executer.execute(new ProposerListener(this)); } reserver.execute(new ProposerReserver(this)); }else if(old == true && l == false){ // leader -> proposer for(int n=0;n<threadCount;n++){ leader_sender.execute(new LeaderSender(this)); } } } /** * Get the paxos instance counter * * @return the instance */ public AtomicLong getInstance(){ return globalInstance; } /** * This is the blocking queue for the values to propose * * @return the values queue */ public BlockingQueue<Value> getValueQueue(){ return values; } /** * Get the blocking queue with the reserved promises * * @return the promise queue */ public BlockingQueue<Promise> getPromiseQueue(){ return promises; } @Override public void process(WatchedEvent event) { int max = -1; try { if(event.getType() == EventType.NodeChildrenChanged){ List<String> l = zoo.getChildren(path, true); for(String s : l){ int i = Integer.parseInt(s); if(i > max){ max = i; } } if(max == this.getID()){ System.out.println("I'm the new leader :-)!"); setLeader(true); }else{ System.out.println("I'm a dumb follower :-(!"); setLeader(false); } } } catch (KeeperException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * @param args * @throws IOException * @throws NumberFormatException */ public static void main(String[] args) throws IOException { if(args.length > 1){ Proposer p = new Proposer(Integer.parseInt(args[0]),args[1]); if(Configuration.getConfiguration().isEmpty()){ Configuration.read(args[1]); } BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String s; while ((s = in.readLine()) != null && s.length() != 0){ try{ if(s.contains("start")){ if(!p.isPerfTest()){ p.setPerfTest(true); Thread t = new Thread(new StatsOutputWriter(p)); t.start(); int conc_values = 80; for(int i=0;i<conc_values;i++){ p.getValueQueue().put(new Value(System.currentTimeMillis()+ "" + p.getID(),new byte[6000])); } } } else{ p.getValueQueue().put(new Value(System.currentTimeMillis()+ "" + p.getID(),s.getBytes())); } }catch(NumberFormatException e){ System.err.println("Error while parsing input as integer!"); } catch (InterruptedException e) { } } System.exit(0); }else{ System.err.println("Use propose.sh <id> <config>!"); System.exit(1); } } }