Skip to content

Commit

Permalink
Assign clientId on connection start
Browse files Browse the repository at this point in the history
  • Loading branch information
dgomezferro committed Sep 20, 2012
1 parent 4f9951f commit 2059524
Show file tree
Hide file tree
Showing 15 changed files with 493 additions and 66 deletions.
19 changes: 19 additions & 0 deletions src/main/java/com/yahoo/pasc/paxos/client/ClientState.java
Expand Up @@ -19,18 +19,21 @@
import java.util.BitSet; import java.util.BitSet;


import com.yahoo.pasc.ProcessState; import com.yahoo.pasc.ProcessState;
import com.yahoo.pasc.paxos.messages.Hello;
import com.yahoo.pasc.paxos.messages.Request; import com.yahoo.pasc.paxos.messages.Request;


public class ClientState implements ProcessState { public class ClientState implements ProcessState {
int clientId; int clientId;
int servers; int servers;
int quorum; int quorum;
int connected; int connected;
int disconnected;
int inlineThreshold; int inlineThreshold;
TimestampMessage asyncMessages []; TimestampMessage asyncMessages [];


long timestamp = -1; long timestamp = -1;
Request pendingRequest; Request pendingRequest;
Hello pendingHello;
BitSet acks = new BitSet(); BitSet acks = new BitSet();
// byte[] value; // byte[] value;
private int from; private int from;
Expand Down Expand Up @@ -77,6 +80,14 @@ public void setConnected(int connected) {
this.connected = connected; this.connected = connected;
} }


public int getDisconnected() {
return disconnected;
}

public void setDisconnected(int disconnected) {
this.disconnected = disconnected;
}

public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
Expand All @@ -93,6 +104,14 @@ public void setPendingRequest(Request pendingRequest) {
this.pendingRequest = pendingRequest; this.pendingRequest = pendingRequest;
} }


public Hello getPendingHello() {
return pendingHello;
}

public void setPendingHello(Hello pendingHello) {
this.pendingHello = pendingHello;
}

public BitSet getAcks() { public BitSet getAcks() {
return acks; return acks;
} }
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/com/yahoo/pasc/paxos/client/PaxosClient.java
Expand Up @@ -31,15 +31,19 @@


import com.yahoo.pasc.PascRuntime; import com.yahoo.pasc.PascRuntime;
import com.yahoo.pasc.paxos.client.handlers.AsyncMessageHandler; import com.yahoo.pasc.paxos.client.handlers.AsyncMessageHandler;
import com.yahoo.pasc.paxos.client.handlers.ByeHandler;
import com.yahoo.pasc.paxos.client.handlers.HelloHandler; import com.yahoo.pasc.paxos.client.handlers.HelloHandler;
import com.yahoo.pasc.paxos.client.handlers.ReplyHandler; import com.yahoo.pasc.paxos.client.handlers.ReplyHandler;
import com.yahoo.pasc.paxos.client.handlers.ServerHelloHandler;
import com.yahoo.pasc.paxos.client.handlers.SubmitHandler; import com.yahoo.pasc.paxos.client.handlers.SubmitHandler;
import com.yahoo.pasc.paxos.client.handlers.TimeoutHandler; import com.yahoo.pasc.paxos.client.handlers.TimeoutHandler;
import com.yahoo.pasc.paxos.client.messages.Submit; import com.yahoo.pasc.paxos.client.messages.Submit;
import com.yahoo.pasc.paxos.client.messages.Timeout; import com.yahoo.pasc.paxos.client.messages.Timeout;
import com.yahoo.pasc.paxos.messages.AsyncMessage; import com.yahoo.pasc.paxos.messages.AsyncMessage;
import com.yahoo.pasc.paxos.messages.Bye;
import com.yahoo.pasc.paxos.messages.Hello; import com.yahoo.pasc.paxos.messages.Hello;
import com.yahoo.pasc.paxos.messages.Reply; import com.yahoo.pasc.paxos.messages.Reply;
import com.yahoo.pasc.paxos.messages.ServerHello;


public class PaxosClient { public class PaxosClient {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
Expand Down Expand Up @@ -96,11 +100,13 @@ public static void main(String[] args) throws Exception {


String [] serverHosts = host.split(","); String [] serverHosts = host.split(",");


HelloHandler hello = new HelloHandler(); ServerHelloHandler shello = new ServerHelloHandler();
ReplyHandler reply = new ReplyHandler(); ReplyHandler reply = new ReplyHandler();
SubmitHandler submit = new SubmitHandler(); SubmitHandler submit = new SubmitHandler();
TimeoutHandler tout = new TimeoutHandler(); TimeoutHandler tout = new TimeoutHandler();
AsyncMessageHandler asyncm = new AsyncMessageHandler(); AsyncMessageHandler asyncm = new AsyncMessageHandler();
ByeHandler bye = new ByeHandler();
HelloHandler hello = new HelloHandler();


Random rnd = new Random(); Random rnd = new Random();


Expand All @@ -109,11 +115,13 @@ public static void main(String[] args) throws Exception {
ClientState clientState = new ClientState(clientId, servers, quorum, inlineThreshold, asynSize); ClientState clientState = new ClientState(clientId, servers, quorum, inlineThreshold, asynSize);
final PascRuntime<ClientState> runtime = new PascRuntime<ClientState>(protection); final PascRuntime<ClientState> runtime = new PascRuntime<ClientState>(protection);
runtime.setState(clientState); runtime.setState(clientState);
runtime.addHandler(Hello.class, hello); runtime.addHandler(ServerHello.class, shello);
runtime.addHandler(Reply.class, reply); runtime.addHandler(Reply.class, reply);
runtime.addHandler(Submit.class, submit); runtime.addHandler(Submit.class, submit);
runtime.addHandler(Timeout.class, tout); runtime.addHandler(Timeout.class, tout);
runtime.addHandler(AsyncMessage.class, asyncm); runtime.addHandler(AsyncMessage.class, asyncm);
runtime.addHandler(Bye.class, bye);
runtime.addHandler(Hello.class, hello);


final PaxosClientHandler handler = new PaxosClientHandler(runtime, new SimpleClient(requestSize), final PaxosClientHandler handler = new PaxosClientHandler(runtime, new SimpleClient(requestSize),
serverHosts, clientId, clients, timeout, zkConnection, executor); serverHosts, clientId, clients, timeout, zkConnection, executor);
Expand Down
57 changes: 44 additions & 13 deletions src/main/java/com/yahoo/pasc/paxos/client/PaxosClientHandler.java
Expand Up @@ -23,6 +23,7 @@
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Random;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
Expand All @@ -32,7 +33,6 @@
import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooKeeper;
import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channel;
Expand Down Expand Up @@ -62,12 +62,14 @@
import com.yahoo.pasc.paxos.messages.Hello; import com.yahoo.pasc.paxos.messages.Hello;
import com.yahoo.pasc.paxos.messages.InlineRequest; import com.yahoo.pasc.paxos.messages.InlineRequest;
import com.yahoo.pasc.paxos.messages.Request; import com.yahoo.pasc.paxos.messages.Request;
import com.yahoo.pasc.paxos.messages.ServerHello;
import com.yahoo.pasc.paxos.messages.serialization.ManualDecoder; import com.yahoo.pasc.paxos.messages.serialization.ManualDecoder;
import com.yahoo.pasc.paxos.messages.serialization.ManualEncoder; import com.yahoo.pasc.paxos.messages.serialization.ManualEncoder;


public class PaxosClientHandler extends SimpleChannelUpstreamHandler implements PaxosInterface, Watcher { public class PaxosClientHandler extends SimpleChannelUpstreamHandler implements PaxosInterface, Watcher {


private static final Logger LOG = LoggerFactory.getLogger(PaxosClientHandler.class); private static final Logger LOG = LoggerFactory.getLogger(PaxosClientHandler.class);
private static final int MAX_CLIENTS = 4096;


private int clientId; private int clientId;
private int clients; private int clients;
Expand Down Expand Up @@ -107,6 +109,7 @@ public ChannelPipeline getPipeline() throws Exception {
this.servers = servers; this.servers = servers;
this.serverChannels = new Channel[servers.length]; this.serverChannels = new Channel[servers.length];
Arrays.fill(payload, (byte) 5); Arrays.fill(payload, (byte) 5);
generateClientId();
for (int i = 0; i < servers.length; ++i) { for (int i = 0; i < servers.length; ++i) {
tryConnect(i); tryConnect(i);
} }
Expand Down Expand Up @@ -171,8 +174,17 @@ public void start() throws KeeperException, InterruptedException {


@Override @Override
public void process(WatchedEvent event) { public void process(WatchedEvent event) {
if (event.getType() != EventType.NodeChildrenChanged) switch (event.getType()) {
case NodeChildrenChanged:
case None:
break;
default:
return; return;
}

if (event.getState() != Watcher.Event.KeeperState.SyncConnected) {
return;
}


try { try {
leader = getLeadership(zk.getChildren(ELECTION_PATH, this)); leader = getLeadership(zk.getChildren(ELECTION_PATH, this));
Expand Down Expand Up @@ -230,12 +242,23 @@ synchronized void resubmitRequest(long timestamp) {
timer.schedule(resubmit, timeout); timer.schedule(resubmit, timeout);
} }
} }

private Random random = new Random();


@Override private void generateClientId() {
public synchronized void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { clientId = random.nextInt(MAX_CLIENTS);
}

private void sendHello(Channel c) {
Hello hello = new Hello(clientId); Hello hello = new Hello(clientId);
hello.storeReplica(hello); hello.storeReplica(hello);
e.getChannel().write(hello); runtime.handleMessage(hello);
c.write(hello);
}

@Override
public synchronized void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
sendHello(e.getChannel());
} }


private long messagesReceived = 0; private long messagesReceived = 0;
Expand All @@ -245,9 +268,10 @@ public synchronized void channelConnected(ChannelHandlerContext ctx, ChannelStat
@Override @Override
public synchronized void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { public synchronized void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Object message = e.getMessage(); Object message = e.getMessage();
if (message instanceof Hello) { if (message instanceof ServerHello) {
Hello hello = (Hello) e.getMessage(); ServerHello hello = (ServerHello) e.getMessage();
serverChannels[hello.getClientId()] = e.getChannel(); serverChannels[hello.getServerId()] = e.getChannel();
LOG.warn("Received hello: " + message);
} }
LOG.trace("Received {}", message); LOG.trace("Received {}", message);
List<Message> messages = runtime.handleMessage((Message) message); List<Message> messages = runtime.handleMessage((Message) message);
Expand All @@ -257,9 +281,15 @@ public synchronized void messageReceived(ChannelHandlerContext ctx, MessageEvent
if (m instanceof Connected) { if (m instanceof Connected) {
lastTime = System.nanoTime(); lastTime = System.nanoTime();


// new Thread(new ThroughputMonitor()).start(); // new Thread(new ThroughputMonitor()).start();


clientInterface.connected(); clientInterface.connected();
} else if (m instanceof Reconnect) {
generateClientId();
for (Channel c : serverChannels) {
if (c != null)
sendHello(c);
}
} else if (m instanceof Received) { } else if (m instanceof Received) {
if (resubmit != null) if (resubmit != null)
resubmit.cancel(); resubmit.cancel();
Expand Down Expand Up @@ -434,22 +464,23 @@ public void run() {
} }
System.out.println(String.format("Throughput: %8.8f m/s", (messagesReceived - startMessagges) System.out.println(String.format("Throughput: %8.8f m/s", (messagesReceived - startMessagges)
/ ((double) (System.currentTimeMillis() - startTime) / 1000))); / ((double) (System.currentTimeMillis() - startTime) / 1000)));
System.out.println(String.format("Latency: %4.4f ms", (totalTime / (double) latencyReceived) / 1000000)); System.out
.println(String.format("Latency: %4.4f ms", (totalTime / (double) latencyReceived) / 1000000));


barrier.close(); barrier.close();

for (Channel c : serverChannels) { for (Channel c : serverChannels) {
if (c != null) { if (c != null) {
c.close(); c.close();
} }
} }

try { try {
Thread.sleep(2000); Thread.sleep(2000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore // ignore
} }

System.exit(0); System.exit(0);
} catch (KeeperException e) { } catch (KeeperException e) {
LOG.error("Couldn't measure throughput", e); LOG.error("Couldn't measure throughput", e);
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/yahoo/pasc/paxos/client/Reconnect.java
@@ -0,0 +1,33 @@
/**
* Copyright (c) 2011 Yahoo! Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/

package com.yahoo.pasc.paxos.client;

import com.yahoo.pasc.Message;

public class Reconnect extends Message {

@Override
protected boolean verify() {
return true;
}

@Override
public void storeReplica(Message m) {

}

}
67 changes: 67 additions & 0 deletions src/main/java/com/yahoo/pasc/paxos/client/handlers/ByeHandler.java
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2011 Yahoo! Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/

package com.yahoo.pasc.paxos.client.handlers;

import java.util.Arrays;
import java.util.List;

import com.yahoo.pasc.Message;
import com.yahoo.pasc.MessageHandler;
import com.yahoo.pasc.paxos.client.ClientState;
import com.yahoo.pasc.paxos.client.Reconnect;
import com.yahoo.pasc.paxos.messages.Bye;
import com.yahoo.pasc.paxos.messages.Hello;

public class ByeHandler implements MessageHandler<Bye, ClientState, Reconnect> {

@Override
public boolean guardPredicate(Bye receivedMessage) {
return true;
}

@Override
public List<Reconnect> processMessage(Bye bye, ClientState state) {
List<Reconnect> descriptors = null;
if (!matches(bye, state)) {
return null;
}
int disconnected = state.getDisconnected();
disconnected++;
state.setDisconnected(disconnected);
int maxFaults = state.getServers() / 2 - 1;
if (disconnected == maxFaults) {
// Send the first message if connected to all servers
descriptors = Arrays.asList(new Reconnect());
}
return descriptors;
}

private boolean matches(Bye bye, ClientState state) {
Hello hello = state.getPendingHello();
if (hello == null)
return false;
return hello.getClientId() == bye.getClientId();
}

@Override
public List<Message> getOutputMessages(ClientState state, List<Reconnect> descriptors) {
if (descriptors != null && descriptors.size() > 0) {
return Arrays.<Message> asList(new Reconnect());
}
return null;
}
}
Expand Up @@ -22,34 +22,25 @@
import com.yahoo.pasc.Message; import com.yahoo.pasc.Message;
import com.yahoo.pasc.MessageHandler; import com.yahoo.pasc.MessageHandler;
import com.yahoo.pasc.paxos.client.ClientState; import com.yahoo.pasc.paxos.client.ClientState;
import com.yahoo.pasc.paxos.client.Connected;
import com.yahoo.pasc.paxos.messages.Hello; import com.yahoo.pasc.paxos.messages.Hello;


public class HelloHandler implements MessageHandler<Hello, ClientState, Connected> { public class HelloHandler implements MessageHandler<Hello, ClientState, Hello> {


@Override @Override
public boolean guardPredicate(Hello receivedMessage) { public boolean guardPredicate(Hello receivedMessage) {
return true; return true;
} }


@Override @Override
public List<Connected> processMessage(Hello hello, ClientState state) { public List<Hello> processMessage(Hello hello, ClientState state) {
List<Connected> descriptors = null; state.setPendingHello(hello);
int connected = state.getConnected(); state.setConnected(0);
connected++; state.setDisconnected(0);
state.setConnected(connected); return Arrays.asList(hello);
if (connected == state.getServers()) {
// Send the first message if connected to all servers
descriptors = Arrays.asList(new Connected());
}
return descriptors;
} }


@Override @Override
public List<Message> getOutputMessages(ClientState state, List<Connected> descriptors) { public List<Message> getOutputMessages(ClientState state, List<Hello> messages) {
if (descriptors != null && descriptors.size() > 0) { return Arrays.<Message>asList(messages.get(0));
return Arrays.<Message> asList(new Connected());
}
return null;
} }
} }

0 comments on commit 2059524

Please sign in to comment.