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.net.DatagramPacket; import java.util.ArrayList; import java.util.List; 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.Decision; /** * Name: Paxos<br> * Description: <br> * * Creation date: Apr 1, 2012<br> * $Id$ * * @author Samuel Benz benz@geoid.ch */ public class Paxos { private Value value = null; private int ballot = 0; private final Acceptor acceptor; private final long instance; /** * Public constructor * * @param acceptor a acceptor instance * @param instance the instance of paxos */ public Paxos(Acceptor acceptor,Long instance){ this.acceptor = acceptor; this.instance = instance; if(acceptor.getHistory().containsKey(instance)){ Decision d = acceptor.getHistory().get(instance); ballot = d.getBallot(); value = d.getValue(); } } /** * Return the value * * @return the value */ public Value getValue(){ return value; } /** * Get the instance * * @return paxos instance */ public long getInstance(){ return instance; } /** * Process a packet within a paxos instance * * @param p * @return the answer packet */ public List<DatagramPacket> process(DatagramPacket p) { List<DatagramPacket> out = new ArrayList<DatagramPacket>(); if(p != null){ Message request = Message.fromWire(p.getData()); // 1a if(request.getType() == MessageType.Prepare){ if(request.getBallot() > ballot){ // 1b ballot = request.getBallot(); Message m = new Message(instance,acceptor.getID(),PaxosRole.Proposer,MessageType.Promise,ballot,value); // WARNING: do not send packets directly to the address! NIO channel don't like this! //byte[] b = Message.toWire(m); //DatagramPacket packet = new DatagramPacket(b,b.length,p.getAddress(),p.getPort()); //out.add(packet); send(out,m); }else{ // the NACK message Message m = new Message(instance,acceptor.getID(),PaxosRole.Proposer,MessageType.Nack,ballot,value); send(out,m); } }else if (request.getType() == MessageType.Accept){ if(request.getBallot() >= ballot){ // >= see P1a ballot = request.getBallot(); if(value == null){ // otherwise you can reserve a new ballot and overwrite the old value value = request.getValue(); } if(value != null){ // 2b acceptor.getHistory().put(instance,new Decision(0,instance,ballot,value)); Message m1 = new Message(instance,acceptor.getID(),PaxosRole.Proposer,MessageType.Accepted,ballot,value); send(out,m1); Message m2 = new Message(instance,acceptor.getID(),PaxosRole.Learner,MessageType.Accepted,ballot,value); send(out,m2); // decided } } } } if(value != null){ acceptor.getInstanceList().remove(instance); } return out; } private void send(List<DatagramPacket> l,Message m){ try { byte[] b = Message.toWire(m); DatagramPacket p = new DatagramPacket(b,b.length,Configuration.getGroup(m.getReceiver())); l.add(p); } catch (Exception e) { } } }