LCB
This commit is contained in:
parent
ad59dd7c4d
commit
ec8ee67745
@ -1,6 +1,5 @@
|
||||
package cs451;
|
||||
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.NetEventType;
|
||||
import cs451.parser.Coordinator;
|
||||
@ -17,23 +16,21 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static String formatOutput(Integer id, Integer host, Message.TYPE tpe){
|
||||
private static String formatOutput(Integer id, Integer host, NetEventType tpe){
|
||||
switch (tpe){
|
||||
case DATA:
|
||||
return "d "+host+" "+id+"\n";
|
||||
case ACK:
|
||||
case DLVR:
|
||||
return "d "+host+" "+id+"\n";
|
||||
case BCST:
|
||||
return "b "+id+"\n";
|
||||
default:
|
||||
return "";
|
||||
return "? "+host+" "+id+"\n";
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeOutput(String filepath) throws IOException {
|
||||
FileWriter writer = new FileWriter(filepath);
|
||||
|
||||
for(Pair<Pair<Integer,Integer>, Message.TYPE> mhpt : mh_tpe){
|
||||
for(Pair<Pair<Integer,Integer>, NetEventType> mhpt : mh_tpe){
|
||||
try {
|
||||
writer.write(formatOutput(mhpt.first().first(),mhpt.first().second(),mhpt.second()));
|
||||
} catch (IOException e) {
|
||||
@ -65,7 +62,7 @@ public class Main {
|
||||
}
|
||||
|
||||
private static Host me = null;
|
||||
private static final Queue<Pair<Pair<Integer,Integer>,Message.TYPE>> mh_tpe = new ConcurrentLinkedQueue<>();
|
||||
private static final Queue<Pair<Pair<Integer,Integer>,NetEventType>> mh_tpe = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private static Parser parser = null;
|
||||
|
||||
@ -103,13 +100,13 @@ public class Main {
|
||||
NetManager.start(me,parser,(t,ne) -> {
|
||||
Logger.error(t+"(" + ne.message.src + "):" + ne.message.toString());
|
||||
if(t == NetEventType.DLVR){
|
||||
Pair<Pair<Integer, Integer>, Message.TYPE> mhpt = new Pair<>(new Pair<>(ne.message.id, ne.message.src), ne.message.tpe);
|
||||
Pair<Pair<Integer, Integer>, NetEventType> mhpt = new Pair<>(new Pair<>(ne.message.id, ne.message.src), t);
|
||||
System.out.print(formatOutput(mhpt.first().first(),mhpt.first().second(),mhpt.second()));
|
||||
mh_tpe.add(mhpt);
|
||||
}else if(t== NetEventType.BCST){
|
||||
Pair<Pair<Integer, Integer>, Message.TYPE> mhpt = new Pair<>(new Pair<>(ne.message.id, ne.message.src), ne.message.tpe);
|
||||
Pair<Pair<Integer, Integer>, NetEventType> mhpt = new Pair<>(new Pair<>(ne.message.id, ne.message.src), t);
|
||||
System.out.print(formatOutput(mhpt.first().first(),mhpt.first().second(),mhpt.second()));
|
||||
mh_tpe.add(new Pair<>(new Pair<>(ne.message.id,ne.message.src),ne.message.tpe));
|
||||
mh_tpe.add(mhpt);
|
||||
}
|
||||
}, (t,ne) -> Logger.error("ERR"+t+" - "+ne.getMessage()));
|
||||
|
||||
|
@ -8,6 +8,7 @@ import cs451.parser.Parser;
|
||||
import cs451.tools.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.BiConsumer;
|
||||
@ -39,6 +40,9 @@ public abstract class NetManager {
|
||||
|
||||
public static Integer WINDOW_WIDTH;
|
||||
|
||||
public static Integer BUNDLE_SIZE;
|
||||
|
||||
public static List<Host> hosts;
|
||||
|
||||
private static boolean isStopped = false;
|
||||
|
||||
@ -72,23 +76,32 @@ public abstract class NetManager {
|
||||
onErrorHandler = oeh;
|
||||
|
||||
registerNetHandler(new NetHandlerSCKT( NetHandlerFD.class, NetHandlerDFLT.class));
|
||||
registerNetHandler(new NetHandlerFD( NetHandlerSL.class, NetHandlerSCKT.class));
|
||||
registerNetHandler(new NetHandlerSL( NetHandlerPL.class, NetHandlerFD.class));
|
||||
registerNetHandler(new NetHandlerFD( NetHandlerBNDL.class, NetHandlerSCKT.class));
|
||||
registerNetHandler(new NetHandlerBNDL( NetHandlerSL.class, NetHandlerFD.class));
|
||||
registerNetHandler(new NetHandlerSL( NetHandlerPL.class, NetHandlerBNDL.class));
|
||||
registerNetHandler(new NetHandlerPL( NetHandlerBEB.class, NetHandlerSL.class));
|
||||
registerNetHandler(new NetHandlerBEB( NetHandlerURB.class, NetHandlerPL.class));
|
||||
registerNetHandler(new NetHandlerURB( NetHandlerFIFO.class, NetHandlerBEB.class));
|
||||
registerNetHandler(new NetHandlerFIFO( NetHandlerTOPL.class, NetHandlerURB.class));
|
||||
registerNetHandler(new NetHandlerTOPL( NetHandlerDFLT.class, NetHandlerFIFO.class));
|
||||
registerNetHandler(new NetHandlerURB( NetHandlerLCB.class, NetHandlerBEB.class));
|
||||
//registerNetHandler(new NetHandlerFIFO( NetHandlerLCB.class, NetHandlerURB.class));
|
||||
registerNetHandler(new NetHandlerLCB( NetHandlerTOPL.class, NetHandlerURB.class));
|
||||
registerNetHandler(new NetHandlerTOPL( NetHandlerDFLT.class, NetHandlerLCB.class));
|
||||
|
||||
registerNetHandler(new NetHandlerDFLT( NetHandlerDFLT.class, NetHandlerDFLT.class));
|
||||
|
||||
hosts = p.hosts();
|
||||
nm_listeners.values().forEach(neh -> neh.start(h,p));
|
||||
ex = new ThreadPoolExecutor(THREAD_COUNT,THREAD_COUNT+THREAD_BOOST_COUNT,30,TimeUnit.SECONDS,new LinkedBlockingQueue<>());
|
||||
ex.prestartAllCoreThreads();
|
||||
|
||||
i_tex.scheduleAtFixedRate(()-> {
|
||||
System.err.println("NetManager DeliverIf/BroadcastIf");
|
||||
nm_listeners.values().forEach(NetEventHandlerInterface::deliverIf);
|
||||
nm_listeners.values().forEach(NetEventHandlerInterface::broadcastIf);
|
||||
nm_listeners.values().forEach(neh->{
|
||||
if(neh.condbd.getAndSet(false)){
|
||||
neh.deliverIf();
|
||||
neh.broadcastIf();
|
||||
}
|
||||
|
||||
});
|
||||
}, 0, INTERNAL_WAIT, TimeUnit.MILLISECONDS);
|
||||
|
||||
fd_tex.scheduleAtFixedRate(()-> {
|
||||
@ -116,13 +129,16 @@ public abstract class NetManager {
|
||||
* @return true if NM and NEH are done
|
||||
*/
|
||||
public static boolean isDone() {
|
||||
return isStopped || nm_listeners.values().stream().map(nmh ->{
|
||||
return isStopped ||
|
||||
(ex.getActiveCount()==0 &&
|
||||
ex.getQueue().size()==0 &&
|
||||
nm_listeners.values().stream().allMatch(nmh->{
|
||||
if(!nmh.isDone()){
|
||||
System.err.println("NetManager Waiting for: "+nmh.getClass().getSimpleName());
|
||||
System.out.println("Waiting for "+nmh.getClass().getSimpleName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).reduce(ex.getActiveCount()==0 && ex.getQueue().size()==0,(b1, b2) -> b1 && b2);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@ -212,7 +228,6 @@ public abstract class NetManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,164 +0,0 @@
|
||||
package cs451.net.event;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* Message abstraction class
|
||||
*
|
||||
* @author C. Hölzl
|
||||
*/
|
||||
public class Message implements Comparable<Message> {
|
||||
|
||||
/**
|
||||
* Type of Message
|
||||
*/
|
||||
public enum TYPE {
|
||||
NONE("NONE", 'N'),
|
||||
ERR("ERR", 'E'),
|
||||
BCST("BCST", 'B'),
|
||||
DATA("DATA", ' '),
|
||||
ACK("ACK", 'A'),
|
||||
HRTB("HRTB",'H');
|
||||
|
||||
public final Character c;
|
||||
public final String tag;
|
||||
TYPE(String tag, Character c){
|
||||
this.tag = tag;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Integer src = -1;
|
||||
public final Integer id;
|
||||
public TYPE tpe;
|
||||
|
||||
/**
|
||||
* Creates a new message from a given message
|
||||
* @param m Message to copy
|
||||
* @return Message
|
||||
*/
|
||||
public static Message MSG(Message m) {
|
||||
return new Message(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Data Message
|
||||
* @param id message id
|
||||
* @return Message
|
||||
*/
|
||||
public static Message DMSG(Integer id){
|
||||
return new Message(id,TYPE.DATA);
|
||||
}
|
||||
public static Message DMSG(Integer id, Integer src) {
|
||||
return new Message(id,TYPE.DATA,src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Heartbeat Message
|
||||
* @return Message
|
||||
*/
|
||||
public static Message HRTB(){
|
||||
return new Message(0,TYPE.HRTB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Message of a given type
|
||||
* @param mess_id Message ID
|
||||
* @param tpe Message Type
|
||||
* @return Message
|
||||
*/
|
||||
public static Message TMSG(Integer mess_id, TYPE tpe) {
|
||||
return new Message(mess_id, tpe);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Empty Message with no type nor ID
|
||||
*/
|
||||
public static Message EMPTY(){
|
||||
return new Message(-1, TYPE.NONE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a character to a given type
|
||||
* @param c char to convert
|
||||
* @return Type
|
||||
*/
|
||||
private static TYPE CharacterToTpe(Character c){
|
||||
return Arrays.stream(TYPE.values()).filter(type -> type.c==c).findFirst().orElse(TYPE.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a message from a ByteBuffer
|
||||
* @param b buffer
|
||||
* @return Message
|
||||
*/
|
||||
public static Message FromBuffer(ByteBuffer b) {
|
||||
Character tpe = b.getChar();
|
||||
Integer id = b.getInt();
|
||||
Integer src = b.getInt();
|
||||
return new Message(id,CharacterToTpe(tpe),src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a message into a ByteBuffer
|
||||
* @param b buffer
|
||||
*/
|
||||
public void ToBuffer(ByteBuffer b){
|
||||
b.putChar(tpe.c);
|
||||
b.putInt(id);
|
||||
b.putInt(src);
|
||||
}
|
||||
|
||||
private Message(Message m) {
|
||||
this.id = m.id;
|
||||
this.tpe = m.tpe;
|
||||
this.src = m.src;
|
||||
}
|
||||
private Message(Integer id, TYPE tpe){
|
||||
this.id = id;
|
||||
this.tpe = tpe;
|
||||
}
|
||||
private Message(Integer id, TYPE tpe, Integer src){
|
||||
this.id = id;
|
||||
this.tpe = tpe;
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (tpe == TYPE.DATA) {
|
||||
return src + "-" + id;
|
||||
}
|
||||
return src + "-" + tpe.c + id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Message m = (Message) obj;
|
||||
return id.equals(m.id) && src.equals(m.src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id,src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Message m) {
|
||||
return id.compareTo(m.id);
|
||||
}
|
||||
}
|
@ -1,62 +1,48 @@
|
||||
package cs451.net.event;
|
||||
|
||||
import cs451.net.event.message.Message;
|
||||
import cs451.net.event.message.NetMessageAbstract;
|
||||
import cs451.parser.Host;
|
||||
|
||||
/**
|
||||
* NetEvent abstraction class
|
||||
*
|
||||
* Holds a {@link cs451.net.event.Message} and a {@link cs451.parser.Host}
|
||||
* Holds a {@link Message} and a {@link cs451.parser.Host}
|
||||
*
|
||||
* @author C. Hölzl
|
||||
*/
|
||||
public class NetEvent {
|
||||
|
||||
public final Host peer;
|
||||
public final Message message;
|
||||
public final NetMessageAbstract message;
|
||||
|
||||
private NetEvent(Host peer, Message message) {
|
||||
private NetEvent(Host peer, NetMessageAbstract m) {
|
||||
this.peer = peer;
|
||||
this.message = message;
|
||||
this.message = m;
|
||||
}
|
||||
|
||||
|
||||
public static NetEvent Message(Host peer, Integer mess_id){
|
||||
return new NetEvent(peer, Message.DMSG(mess_id));
|
||||
public static NetEvent Message(NetMessageAbstract m){
|
||||
return new NetEvent(NO_PEER, NetMessageAbstract.MSG(m));
|
||||
}
|
||||
|
||||
public static NetEvent Message(Host peer, Integer mess_id, Message.TYPE tpe){
|
||||
return new NetEvent(peer, Message.TMSG(mess_id,tpe));
|
||||
public static NetEvent Message(Host peer, NetMessageAbstract m){
|
||||
return new NetEvent(peer, NetMessageAbstract.MSG(m));
|
||||
}
|
||||
|
||||
public static NetEvent Message(Host peer, Message m){
|
||||
return new NetEvent(peer, Message.MSG(m));
|
||||
}
|
||||
|
||||
public static NetEvent Message(Message m){
|
||||
return new NetEvent(NO_PEER,Message.MSG(m));
|
||||
}
|
||||
|
||||
public static NetEvent Message(Integer mess_id){
|
||||
return new NetEvent(NO_PEER, Message.DMSG(mess_id));
|
||||
}
|
||||
|
||||
public static NetEvent Message(Integer src, Integer mess_id) {
|
||||
return new NetEvent(NO_PEER, Message.DMSG(mess_id,src));
|
||||
}
|
||||
|
||||
public static NetEvent MessageACK(Host peer, Message message) {
|
||||
NetEvent ne = NetEvent.Message(peer,message);
|
||||
ne.message.tpe = Message.TYPE.ACK;
|
||||
return ne;
|
||||
public static NetEvent MessageACK(Host peer, NetMessageAbstract m) {
|
||||
return new NetEvent(peer,NetMessageAbstract.ACK(m));
|
||||
}
|
||||
|
||||
public static NetEvent MessageHRTB(Host peer){
|
||||
return NetEvent.Message(peer,Message.HRTB());
|
||||
return new NetEvent(peer,NetMessageAbstract.HRTB());
|
||||
}
|
||||
|
||||
public static NetEvent MessageCRSH(Host peer){
|
||||
return new NetEvent(peer,NetMessageAbstract.EMPTY());
|
||||
}
|
||||
|
||||
public static NetEvent EMPTY(){
|
||||
return new NetEvent(NO_PEER, Message.EMPTY());
|
||||
return new NetEvent(NO_PEER, NetMessageAbstract.EMPTY());
|
||||
}
|
||||
|
||||
public static final Host NO_PEER = null;
|
||||
|
@ -10,5 +10,5 @@ public enum NetEventType {
|
||||
DLVR,
|
||||
BCST,
|
||||
CRSH,
|
||||
RCVR;
|
||||
RCVR
|
||||
}
|
||||
|
112
257844/src/main/java/cs451/net/event/message/Message.java
Normal file
112
257844/src/main/java/cs451/net/event/message/Message.java
Normal file
@ -0,0 +1,112 @@
|
||||
package cs451.net.event.message;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* Message abstraction class
|
||||
*
|
||||
* @author C. Hölzl
|
||||
*/
|
||||
public class Message extends NetMessageAbstract {
|
||||
|
||||
public final HashMap<Integer,Integer> dependencies;
|
||||
|
||||
private Message(Integer src, Integer id, TYPE tpe, HashMap<Integer,Integer> dependencies){
|
||||
super(src, id, tpe);
|
||||
this.dependencies = dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a message from a ByteBuffer
|
||||
* @param b buffer
|
||||
* @return Message
|
||||
*/
|
||||
public static Message FromBuffer(ByteBuffer b) {
|
||||
if(b.remaining() < 14) return getBuilder().build();
|
||||
|
||||
Character tpe = b.getChar();
|
||||
int id = b.getInt();
|
||||
int src = b.getInt();
|
||||
int depLen = b.getInt();
|
||||
HashMap<Integer,Integer> newdep = new HashMap<>(depLen);
|
||||
for (int i = 0; i < depLen; i++) {
|
||||
if(b.remaining()<8) break;
|
||||
newdep.put(b.getInt(),b.getInt());
|
||||
}
|
||||
return new Message(src, id, NetMessageInterface.CharacterToTpe(tpe), newdep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a message into a ByteBuffer
|
||||
* @param b buffer
|
||||
*/
|
||||
public void ToBuffer(ByteBuffer b){
|
||||
if(b.remaining() < 14 + 8*dependencies.keySet().size()) return;
|
||||
|
||||
b.putChar(tpe.c);
|
||||
b.putInt(id);
|
||||
b.putInt(src);
|
||||
b.putInt(dependencies.keySet().size());
|
||||
for (Integer i : dependencies.keySet()) {
|
||||
b.putInt(i);
|
||||
b.putInt(dependencies.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return src + "-" + tpe.c + id + " - " +dependencies.toString();
|
||||
}
|
||||
|
||||
public static final Message HRTB_MSG = Message.getBuilder().setId(0).setTpe(TYPE.HRTB).build();
|
||||
|
||||
public static MessageBuilder getBuilder(){
|
||||
return new MessageBuilder();
|
||||
}
|
||||
public static MessageBuilder getBuilder(NetMessageAbstract m){
|
||||
if (m instanceof Message)
|
||||
return new MessageBuilder((Message) m);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
public static class MessageBuilder{
|
||||
private int id = -1;
|
||||
private int src = -1;
|
||||
private TYPE tpe = TYPE.NONE;
|
||||
private HashMap<Integer,Integer> dependencies = new HashMap<>(0);
|
||||
|
||||
public MessageBuilder(){}
|
||||
public MessageBuilder(Message m){
|
||||
this.id = m.id;
|
||||
this.src = m.src;
|
||||
this.tpe = m.tpe;
|
||||
this.dependencies = m.dependencies;
|
||||
}
|
||||
|
||||
public Message build(){
|
||||
return new Message(src,id,tpe,dependencies);
|
||||
}
|
||||
|
||||
public MessageBuilder setTpe(TYPE tpe) {
|
||||
this.tpe = tpe;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder setId(int id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder setSrc(int src) {
|
||||
this.src = src;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder setDependencies(HashMap<Integer,Integer> dependencies) {
|
||||
this.dependencies = dependencies;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
118
257844/src/main/java/cs451/net/event/message/MessageBundle.java
Normal file
118
257844/src/main/java/cs451/net/event/message/MessageBundle.java
Normal file
@ -0,0 +1,118 @@
|
||||
package cs451.net.event.message;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MessageBundle extends NetMessageAbstract {
|
||||
|
||||
public final List<Message> messageList;
|
||||
|
||||
private MessageBundle(int src, int id, TYPE tpe, List<Message> messageList) {
|
||||
super(src,id,tpe);
|
||||
this.messageList = messageList;
|
||||
}
|
||||
|
||||
public static NetMessageAbstract FromBuffer(ByteBuffer b) {
|
||||
ArrayList<Message> msgl = new ArrayList<>();
|
||||
int mlen = Math.min(NetManager.BUNDLE_SIZE+1, b.getInt());
|
||||
for (int i = 0; i< mlen; i++) {
|
||||
Message m = Message.FromBuffer(b);
|
||||
if (m.tpe == TYPE.NONE)
|
||||
break;
|
||||
msgl.add(m);
|
||||
}
|
||||
return getBuilder().setMessageList(msgl).build();
|
||||
}
|
||||
@Override
|
||||
public void ToBuffer(ByteBuffer b) {
|
||||
if (b.remaining() < 4) return;
|
||||
|
||||
b.putInt(messageList.size());
|
||||
for (Message message : messageList) {
|
||||
message.ToBuffer(b);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return tpe.c + "-" + Arrays.toString(messageList.toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final MessageBundle m = (MessageBundle) obj;
|
||||
return messageList.equals(m.messageList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(messageList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(NetMessageAbstract message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static MessageBundleBuilder getBuilder(){
|
||||
return new MessageBundleBuilder();
|
||||
}
|
||||
public static MessageBundleBuilder getBuilder(NetMessageAbstract m){
|
||||
if (m instanceof MessageBundle)
|
||||
return new MessageBundleBuilder((MessageBundle) m);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
public static class MessageBundleBuilder{
|
||||
private int id = -1;
|
||||
private int src = -1;
|
||||
private TYPE tpe = TYPE.NONE;
|
||||
private List<Message> messageList = new ArrayList<>(0);
|
||||
|
||||
public MessageBundleBuilder(){}
|
||||
public MessageBundleBuilder(MessageBundle m){
|
||||
this.id = m.id;
|
||||
this.src = m.src;
|
||||
this.tpe = m.tpe;
|
||||
this.messageList = m.messageList;
|
||||
}
|
||||
|
||||
public MessageBundle build(){
|
||||
return new MessageBundle(src,id,tpe,messageList);
|
||||
}
|
||||
|
||||
public MessageBundleBuilder setTpe(TYPE tpe) {
|
||||
this.tpe = tpe;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBundleBuilder setId(int id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBundleBuilder setSrc(int src) {
|
||||
this.src = src;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBundleBuilder setMessageList(List<Message> dependencies) {
|
||||
this.messageList = dependencies;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package cs451.net.event.message;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class NetMessageAbstract implements NetMessageInterface {
|
||||
public final TYPE tpe;
|
||||
public final Integer src;
|
||||
public final Integer id;
|
||||
|
||||
public NetMessageAbstract(Integer src,Integer id, TYPE tpe) {
|
||||
this.src = src;
|
||||
this.id = id;
|
||||
this.tpe = tpe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final NetMessageAbstract m = (NetMessageAbstract) obj;
|
||||
return id.equals(m.id) && src.equals(m.src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id,src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(NetMessageAbstract m) {
|
||||
return id.compareTo(m.id);
|
||||
}
|
||||
|
||||
|
||||
public static NetMessageAbstract MSG(NetMessageAbstract m) {
|
||||
if (m instanceof Message)
|
||||
return Message.getBuilder(m).build();
|
||||
if (m instanceof MessageBundle)
|
||||
return MessageBundle.getBuilder(m).build();
|
||||
|
||||
return EMPTY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Ack Message
|
||||
* @return Message
|
||||
*/
|
||||
public static NetMessageAbstract ACK(NetMessageAbstract m){
|
||||
if(m instanceof Message)
|
||||
return Message.getBuilder(m).setTpe(TYPE.ACK).setDependencies(new HashMap<>()).build();
|
||||
return EMPTY();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a Heartbeat Message
|
||||
* @return Message
|
||||
*/
|
||||
public static NetMessageAbstract HRTB(){
|
||||
return MessageBundle.getBuilder().setMessageList(List.of(Message.HRTB_MSG)).setTpe(TYPE.HRTB).build();
|
||||
}
|
||||
|
||||
public boolean isHeartBeat(){
|
||||
if (this instanceof Message){
|
||||
return this.tpe==TYPE.HRTB;
|
||||
}else if (this instanceof MessageBundle){
|
||||
return ((MessageBundle)this).messageList.size()>0 &&
|
||||
((MessageBundle)this).messageList.get(0).tpe==TYPE.HRTB;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Empty Message with no type nor ID
|
||||
*/
|
||||
public static Message EMPTY(){
|
||||
return Message.getBuilder().build();
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package cs451.net.event.message;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
public interface NetMessageInterface extends Comparable<NetMessageAbstract> {
|
||||
|
||||
/**
|
||||
* Type of Message
|
||||
*/
|
||||
enum TYPE {
|
||||
NONE("NONE", 'N'),
|
||||
DATA("DATA", 'D'),
|
||||
ACK("ACK", 'A'),
|
||||
HRTB("HRTB",'H');
|
||||
|
||||
public final Character c;
|
||||
public final String tag;
|
||||
TYPE(String tag, Character c){
|
||||
this.tag = tag;
|
||||
this.c = c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a character to a given type
|
||||
* @param c char to convert
|
||||
* @return Type
|
||||
*/
|
||||
static TYPE CharacterToTpe(Character c){
|
||||
return Arrays.stream(TYPE.values()).filter(type -> type.c==c).findFirst().orElse(TYPE.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a message from a ByteBuffer
|
||||
*
|
||||
* @param b buffer
|
||||
* @return Message
|
||||
*/
|
||||
static NetMessageAbstract FromBuffer(ByteBuffer b) {
|
||||
return MessageBundle.FromBuffer(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a message into a ByteBuffer
|
||||
* @param b buffer
|
||||
*/
|
||||
void ToBuffer(ByteBuffer b);
|
||||
}
|
@ -5,6 +5,8 @@ import cs451.net.event.NetEvent;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* NetEventHandler abstraction class
|
||||
*
|
||||
@ -12,13 +14,14 @@ import cs451.parser.Parser;
|
||||
*/
|
||||
public abstract class NetEventHandlerAbstract implements NetEventHandlerInterface {
|
||||
|
||||
|
||||
/**
|
||||
* Deliver & Broadcast Layers to handle resulting operation
|
||||
*/
|
||||
private final Class<? extends NetEventHandlerAbstract> deliverLayer;
|
||||
private final Class<? extends NetEventHandlerAbstract> broadcastLayer;
|
||||
|
||||
public final AtomicBoolean condbd = new AtomicBoolean(false);
|
||||
|
||||
|
||||
/**
|
||||
* Initialized the main NetEventHandler fields
|
||||
@ -30,6 +33,12 @@ public abstract class NetEventHandlerAbstract implements NetEventHandlerInterfac
|
||||
this.broadcastLayer = broadcastLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a conditional Broadcast/Delivery
|
||||
*/
|
||||
public void requestCondBD(Boolean v){
|
||||
condbd.set(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers a NetEvent Synchronously
|
||||
|
@ -1,12 +1,10 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* NetEventHandler for Best Effort Broadcast
|
||||
*
|
||||
@ -16,8 +14,7 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class NetHandlerBEB extends NetEventHandlerAbstract {
|
||||
|
||||
private List<Host> hosts;
|
||||
private Host h;
|
||||
private static Host h;
|
||||
|
||||
public NetHandlerBEB(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
@ -26,14 +23,13 @@ public class NetHandlerBEB extends NetEventHandlerAbstract {
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
deliverNextAsync(NetEvent.Message(h,ne.message));
|
||||
hosts.parallelStream().forEach(h -> broadcastNextSync(NetEvent.Message(h, ne.message)));
|
||||
NetManager.hosts.parallelStream().filter(ch->ch.getId()!=h.getId()).forEach(h -> broadcastNextSync(NetEvent.Message(h, ne.message)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h,p);
|
||||
this.h = h;
|
||||
hosts = p.hosts().stream().filter(ch -> ch.getId()!=h.getId()).collect(Collectors.toList());
|
||||
NetHandlerBEB.h = h;
|
||||
}
|
||||
|
||||
}
|
||||
|
68
257844/src/main/java/cs451/net/handler/NetHandlerBNDL.java
Normal file
68
257844/src/main/java/cs451/net/handler/NetHandlerBNDL.java
Normal file
@ -0,0 +1,68 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.net.event.message.Message;
|
||||
import cs451.net.event.message.MessageBundle;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
/**
|
||||
* NetEventHandler for BLUNDLER
|
||||
*
|
||||
* Groups Multiple messages into larger packets (and de-groups them on receive
|
||||
*
|
||||
* @author C. Hölzl
|
||||
*/
|
||||
public class NetHandlerBNDL extends NetEventHandlerAbstract {
|
||||
|
||||
private static final ConcurrentHashMap<Integer, PriorityBlockingQueue<Message>> sending = new ConcurrentHashMap<>();
|
||||
|
||||
public NetHandlerBNDL(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer, broadcastLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void broadcastIf() {
|
||||
NetManager.hosts.forEach(h-> sending.computeIfPresent(h.getId(),(hid, mq)->{
|
||||
while(mq.size()>0){
|
||||
ArrayList<Message> msgl = new ArrayList<>(NetManager.BUNDLE_SIZE);
|
||||
mq.drainTo(msgl, NetManager.BUNDLE_SIZE);
|
||||
broadcastNextAsync(NetEvent.Message(h, MessageBundle.getBuilder().setMessageList(msgl).build()));
|
||||
}
|
||||
return mq;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
sending.computeIfPresent(ne.peer.getId(),(h, q) -> {
|
||||
if(ne.message instanceof Message) {
|
||||
q.add((Message) ne.message);
|
||||
requestCondBD(true);
|
||||
}
|
||||
return q;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
if (ne.message instanceof MessageBundle) {
|
||||
((MessageBundle) ne.message).messageList.forEach(msg -> deliverNextAsync(NetEvent.Message(ne.peer,msg)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return sending.values().stream().allMatch(v->v.size()==0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
p.hosts().stream().filter(ch->ch.getId()!=h.getId()).forEach(ch->sending.put(ch.getId(),new PriorityBlockingQueue<>()));
|
||||
}
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
@ -19,8 +17,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class NetHandlerFD extends NetEventHandlerAbstract {
|
||||
|
||||
private List<Host> hosts;
|
||||
private static final ConcurrentHashMap<Integer,Integer> alive = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer,Integer> should_I = new ConcurrentHashMap<>();
|
||||
|
||||
public NetHandlerFD(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer, broadcastLayer);
|
||||
@ -28,20 +26,24 @@ public class NetHandlerFD extends NetEventHandlerAbstract {
|
||||
|
||||
@Override
|
||||
public synchronized void beat() {
|
||||
hosts.forEach(h-> {
|
||||
alive.computeIfPresent(h.getId(),(k, v) -> {
|
||||
NetManager.hosts.forEach(h-> {
|
||||
should_I.computeIfPresent(h.getId(),(k, v) -> {
|
||||
if(v>=0)
|
||||
broadcastNextSync(NetEvent.MessageHRTB(h));
|
||||
return v+1;
|
||||
});
|
||||
alive.computeIfPresent(h.getId(), (k,v) -> v+1);
|
||||
if(alive.getOrDefault(h.getId(),0) > NetManager.FD_MAX_TRIES){
|
||||
crashNextSync(NetEvent.Message(h, Message.EMPTY()));
|
||||
crashNextSync(NetEvent.MessageCRSH(h));
|
||||
alive.remove(h.getId());
|
||||
should_I.remove(h.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
should_I.computeIfPresent(ne.peer.getId(),(k, v)->-1);
|
||||
if (alive.containsKey(ne.peer.getId())){
|
||||
broadcastNextSync(ne);
|
||||
}
|
||||
@ -50,15 +52,16 @@ public class NetHandlerFD extends NetEventHandlerAbstract {
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
alive.computeIfPresent(ne.peer.getId(), (k,v) -> 0);
|
||||
if (ne.message.tpe != Message.TYPE.HRTB) {
|
||||
if (!ne.message.isHeartBeat()) {
|
||||
deliverNextSync(ne);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h, p);
|
||||
hosts = p.hosts();
|
||||
hosts.stream().filter(ch->ch.getId()!=h.getId()).forEach(ch-> alive.put(ch.getId(),-1));
|
||||
NetManager.hosts.stream().filter(ch->ch.getId()!=h.getId()).forEach(ch-> {
|
||||
alive.put(ch.getId(),-1);
|
||||
should_I.put(ch.getId(),-1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.net.event.NetEventType;
|
||||
import cs451.net.event.*;
|
||||
import cs451.net.event.message.NetMessageAbstract;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -24,50 +23,53 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
public class NetHandlerFIFO extends NetEventHandlerAbstract {
|
||||
|
||||
private final AtomicInteger sn = new AtomicInteger(1);
|
||||
private final Map<Integer,Integer> rsn = new ConcurrentHashMap<>();
|
||||
private final PriorityBlockingQueue<Message> pending = new PriorityBlockingQueue<>();
|
||||
|
||||
private Host me;
|
||||
private static final ConcurrentHashMap<Integer,AtomicInteger> rsn = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer,PriorityBlockingQueue<NetMessageAbstract>> pending = new ConcurrentHashMap<>();
|
||||
|
||||
public NetHandlerFIFO(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void broadcast(NetEvent ne) {
|
||||
Integer snv = sn.getAndIncrement();
|
||||
NetManager.complete(NetEventType.BCST, NetEvent.Message(me, snv, Message.TYPE.BCST));
|
||||
broadcastNextAsync(NetEvent.Message(me.getId(),snv));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deliverIf(){
|
||||
pending.removeIf(hmp -> {
|
||||
Integer crsn = rsn.getOrDefault(hmp.src, 1);
|
||||
if (hmp.id.equals(crsn)) {
|
||||
NetManager.complete(NetEventType.DLVR,NetEvent.Message(hmp));
|
||||
deliverNextSync(NetEvent.Message(hmp));
|
||||
rsn.put(hmp.src, crsn + 1);
|
||||
return true;
|
||||
pending.forEach((hid, mq) -> {
|
||||
AtomicInteger crsn = rsn.get(hid);
|
||||
if(crsn == null) return;
|
||||
Collection<NetMessageAbstract> msgc = new ArrayList<>();
|
||||
mq.drainTo(msgc);
|
||||
msgc.forEach(msg ->
|
||||
crsn.getAndUpdate(v -> {
|
||||
if (msg.id.equals(v)){
|
||||
deliverNextSync(NetEvent.Message(msg));
|
||||
return v+1;
|
||||
}else{
|
||||
mq.add(msg);
|
||||
return v;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
pending.add(ne.message);
|
||||
pending.computeIfPresent(ne.message.src, (h, mq) -> {
|
||||
mq.add(ne.message);
|
||||
requestCondBD(true);
|
||||
return mq;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return pending.stream().noneMatch(hmp -> hmp.id.equals(rsn.getOrDefault(hmp.src, 1)));
|
||||
return pending.values().stream().allMatch(hmp -> hmp.stream().noneMatch(msg-> msg.id.equals(rsn.getOrDefault(msg.src, new AtomicInteger(1)).get())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h,p);
|
||||
me = h;
|
||||
for (Host host : p.hosts()) {
|
||||
pending.put(host.getId(),new PriorityBlockingQueue<>());
|
||||
rsn.put(host.getId(), new AtomicInteger(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
98
257844/src/main/java/cs451/net/handler/NetHandlerLCB.java
Normal file
98
257844/src/main/java/cs451/net/handler/NetHandlerLCB.java
Normal file
@ -0,0 +1,98 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.net.event.message.Message;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NetHandlerLCB extends NetEventHandlerAbstract {
|
||||
|
||||
private static Map<Integer, List<Integer>> causality;
|
||||
private static final ConcurrentHashMap<Integer, PriorityBlockingQueue<Message>> undelivered = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer, AtomicInteger> state = new ConcurrentHashMap<>();
|
||||
|
||||
public NetHandlerLCB(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer, broadcastLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deliverIf() {
|
||||
AtomicBoolean deliveredOne = new AtomicBoolean(false);
|
||||
do {
|
||||
deliveredOne.set(false);
|
||||
|
||||
undelivered.forEach((hid, mq) -> {
|
||||
AtomicInteger crsn = state.get(hid);
|
||||
if(crsn == null) return;
|
||||
Collection<Message> msgc = new ArrayList<>();
|
||||
mq.drainTo(msgc);
|
||||
msgc.forEach(msg ->
|
||||
crsn.getAndUpdate(v -> {
|
||||
if (msg.id.equals(v+1) && checkDependencies(msg.src,msg.dependencies)){
|
||||
deliverNextSync(NetEvent.Message(msg));
|
||||
deliveredOne.set(true);
|
||||
return v+1;
|
||||
}else{
|
||||
mq.add(msg);
|
||||
return v;
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
}while((deliveredOne.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
broadcastNextSync(NetEvent.Message(Message.getBuilder(ne.message).setDependencies(getDependencies(ne.message.src)).build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
undelivered.computeIfPresent(ne.message.src,(k, lv) -> {
|
||||
lv.add((Message) ne.message);
|
||||
return lv;
|
||||
});
|
||||
requestCondBD(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h, p);
|
||||
causality = p.causality();
|
||||
for (Host host : p.hosts()) {
|
||||
undelivered.put(host.getId(), new PriorityBlockingQueue<>());
|
||||
state.put(host.getId(), new AtomicInteger(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return undelivered.values().stream().allMatch(AbstractCollection::isEmpty);
|
||||
}
|
||||
|
||||
private HashMap<Integer,Integer> getDependencies(Integer hid){
|
||||
HashMap<Integer,Integer> dependencies = new HashMap<>();
|
||||
List<Integer> hc = causality.getOrDefault(hid, Collections.emptyList());
|
||||
for (Integer hci : hc) {
|
||||
dependencies.put(hci, state.get(hci).get());
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private Boolean checkDependencies(Integer hid, HashMap<Integer,Integer> md){
|
||||
HashMap<Integer,Integer> cd = getDependencies(hid);
|
||||
for(Integer k : cd.keySet()){
|
||||
if(cd.get(k) < md.get(k)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.*;
|
||||
import cs451.net.event.message.NetMessageInterface;
|
||||
import cs451.tools.Pair;
|
||||
|
||||
import java.util.Set;
|
||||
@ -15,7 +16,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class NetHandlerPL extends NetEventHandlerAbstract {
|
||||
|
||||
private final Set<Pair<Integer,Message>> delivered = ConcurrentHashMap.newKeySet();
|
||||
private static final Set<Pair<Integer, NetMessageInterface>> delivered = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public NetHandlerPL(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
|
@ -1,15 +1,14 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.*;
|
||||
import cs451.net.event.message.NetMessageInterface;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -24,14 +23,10 @@ import java.util.concurrent.Executors;
|
||||
*/
|
||||
public class NetHandlerSCKT extends NetEventHandlerAbstract {
|
||||
|
||||
private static final Integer BUFF_SIZE = 128;
|
||||
private static final Integer BUFF_SIZE = 2048;
|
||||
|
||||
private static final ExecutorService tex = Executors.newSingleThreadExecutor();
|
||||
|
||||
private List<Host> hosts;
|
||||
|
||||
private DatagramSocket socket = null;
|
||||
|
||||
private static DatagramSocket socket = null;
|
||||
|
||||
public NetHandlerSCKT(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
@ -60,15 +55,15 @@ public class NetHandlerSCKT extends NetEventHandlerAbstract {
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buff = new byte[BUFF_SIZE];
|
||||
DatagramPacket datagram = new DatagramPacket(buff, buff.length);
|
||||
byte[] b = new byte[BUFF_SIZE];
|
||||
DatagramPacket datagram = new DatagramPacket(b, b.length);
|
||||
try {
|
||||
socket.receive(datagram);
|
||||
Optional<Integer> rhid = hosts.stream().filter(h -> h.getAddr().equals(datagram.getSocketAddress())).map(Host::getId).findFirst();
|
||||
Optional<Integer> rhid = NetManager.hosts.stream().filter(h -> h.getAddr().equals(datagram.getSocketAddress())).map(Host::getId).findFirst();
|
||||
|
||||
deliverNextAsync(NetEvent.Message(
|
||||
new Host((InetSocketAddress) datagram.getSocketAddress(), rhid.orElse(-1)),
|
||||
Message.FromBuffer(ByteBuffer.wrap(datagram.getData()))
|
||||
NetMessageInterface.FromBuffer(ByteBuffer.wrap(datagram.getData()))
|
||||
));
|
||||
} catch (IOException e) {
|
||||
NetManager.error(NetEventType.DLVR,e);
|
||||
@ -78,17 +73,13 @@ public class NetHandlerSCKT extends NetEventHandlerAbstract {
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h,p);
|
||||
hosts = p.hosts();
|
||||
|
||||
try {
|
||||
this.socket = new DatagramSocket(h.getPort());
|
||||
socket = new DatagramSocket(h.getPort());
|
||||
} catch (SocketException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
tex.execute(()->{
|
||||
while (true) {
|
||||
while (!socket.isClosed()) {
|
||||
deliver(NetEvent.EMPTY());
|
||||
}
|
||||
});
|
||||
|
@ -1,10 +1,8 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.event.*;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
import cs451.net.event.message.NetMessageAbstract;
|
||||
import cs451.tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
@ -23,10 +21,9 @@ import java.util.concurrent.*;
|
||||
*/
|
||||
public class NetHandlerSL extends NetEventHandlerAbstract {
|
||||
|
||||
private List<Host> hosts;
|
||||
Set<Integer> hasTimeout = ConcurrentHashMap.newKeySet();
|
||||
private static final Set<Integer> hasTimeout = ConcurrentHashMap.newKeySet();
|
||||
|
||||
PriorityBlockingQueue<Pair<Integer,Message>> sending = new PriorityBlockingQueue<>();
|
||||
private static final PriorityBlockingQueue<Pair<Integer, NetMessageAbstract>> sending = new PriorityBlockingQueue<>();
|
||||
|
||||
public NetHandlerSL(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
@ -35,14 +32,14 @@ public class NetHandlerSL extends NetEventHandlerAbstract {
|
||||
@Override
|
||||
public synchronized void beat(){
|
||||
sending.removeIf(ppm -> hasTimeout.contains(ppm.first()));
|
||||
sending.stream().limit(NetManager.WINDOW_WIDTH).forEach(ppm -> hosts.stream().filter(hl->hl.getId()==(ppm.first())).findFirst()
|
||||
sending.stream().limit(NetManager.WINDOW_WIDTH).forEach(ppm -> NetManager.hosts.stream().filter(hl->hl.getId()==(ppm.first())).findFirst()
|
||||
.ifPresent(host -> broadcastNextSync(NetEvent.Message(host, ppm.second()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
if (!hasTimeout.contains(ne.peer.getId()))
|
||||
sending.add(new Pair<>(ne.peer.getId(),Message.MSG(ne.message)));
|
||||
sending.add(new Pair<>(ne.peer.getId(), ne.message));
|
||||
broadcastNextSync(ne);
|
||||
}
|
||||
|
||||
@ -51,7 +48,7 @@ public class NetHandlerSL extends NetEventHandlerAbstract {
|
||||
switch (ne.message.tpe){
|
||||
case ACK:
|
||||
sending.removeIf(ppm -> (ne.peer.getId()==ppm.first() &&
|
||||
ppm.second().equals(ne.message)));
|
||||
ne.message.equals(ppm.second())));
|
||||
break;
|
||||
case DATA:
|
||||
broadcastNextSync(NetEvent.MessageACK(ne.peer,ne.message));
|
||||
@ -72,10 +69,4 @@ public class NetHandlerSL extends NetEventHandlerAbstract {
|
||||
public boolean isDone() {
|
||||
return sending.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
this.hosts = p.hosts();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,10 +2,12 @@ package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.net.event.NetEventType;
|
||||
import cs451.net.event.message.Message;
|
||||
import cs451.net.event.message.NetMessageInterface;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
@ -20,11 +22,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
*/
|
||||
public class NetHandlerTOPL extends NetEventHandlerAbstract {
|
||||
|
||||
private final AtomicInteger toSend = new AtomicInteger(0);
|
||||
private final AtomicInteger delivered = new AtomicInteger(0);
|
||||
private final AtomicInteger waiting = new AtomicInteger(0);
|
||||
private static final AtomicInteger sn = new AtomicInteger(1);
|
||||
|
||||
private static final AtomicInteger toSend = new AtomicInteger(0);
|
||||
private static final AtomicInteger delivered = new AtomicInteger(0);
|
||||
private static final AtomicInteger waiting = new AtomicInteger(0);
|
||||
|
||||
private final AtomicBoolean status = new AtomicBoolean(false);
|
||||
|
||||
private Host me;
|
||||
|
||||
@ -34,25 +37,29 @@ public class NetHandlerTOPL extends NetEventHandlerAbstract {
|
||||
|
||||
@Override
|
||||
public synchronized void broadcastIf() {
|
||||
if( !status.get() ) return;
|
||||
while (toSend.get() > 0 && waiting.get() < NetManager.WINDOW_WIDTH) {
|
||||
toSend.decrementAndGet();
|
||||
waiting.incrementAndGet();
|
||||
broadcastNextSync(NetEvent.EMPTY());
|
||||
|
||||
Message newMess = Message.getBuilder().setSrc(me.getId()).setId(sn.getAndIncrement()).setTpe(NetMessageInterface.TYPE.DATA).build();
|
||||
NetManager.complete(NetEventType.BCST, NetEvent.Message(me, newMess));
|
||||
broadcastNextSync(NetEvent.Message(newMess));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
status.set(true);
|
||||
requestCondBD(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deliver(NetEvent ne) {
|
||||
NetManager.complete(NetEventType.DLVR,ne);
|
||||
if (ne.message.src == me.getId()) {
|
||||
delivered.incrementAndGet();
|
||||
waiting.decrementAndGet();
|
||||
requestCondBD(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +70,6 @@ public class NetHandlerTOPL extends NetEventHandlerAbstract {
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h,p);
|
||||
me = h;
|
||||
toSend.set(p.messageCount());
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.net.event.message.NetMessageAbstract;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
import cs451.tools.Pair;
|
||||
@ -22,14 +23,10 @@ import java.util.concurrent.*;
|
||||
*/
|
||||
public class NetHandlerURB extends NetEventHandlerAbstract {
|
||||
|
||||
|
||||
private final Set<Integer> correct = ConcurrentHashMap.newKeySet();
|
||||
private final Map<Pair<Integer,Integer>, Set<Integer>> ack = new ConcurrentHashMap<>();
|
||||
private final Set<Pair<Integer,Integer>> delivered = ConcurrentHashMap.newKeySet();
|
||||
private final Set<Pair<Integer,Integer>> pending = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private Integer myId;
|
||||
|
||||
private static final Set<Integer> correct = ConcurrentHashMap.newKeySet();
|
||||
private static final Map<Pair<Integer,Integer>, Set<Integer>> ack = new ConcurrentHashMap<>();
|
||||
private static final Set<Pair<Integer, Integer>> delivered = ConcurrentHashMap.newKeySet();
|
||||
private static final Map<Pair<Integer, Integer>, NetMessageAbstract> pending = new ConcurrentHashMap<>();
|
||||
|
||||
public NetHandlerURB(Class<? extends NetEventHandlerAbstract> deliverLayer, Class<? extends NetEventHandlerAbstract> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
@ -37,15 +34,16 @@ public class NetHandlerURB extends NetEventHandlerAbstract {
|
||||
|
||||
@Override
|
||||
public synchronized void deliverIf(){
|
||||
pending.stream().filter(smp -> ack.getOrDefault(smp,ConcurrentHashMap.newKeySet()).containsAll(correct)).
|
||||
pending.keySet().stream().filter(smp ->
|
||||
ack.getOrDefault(smp,ConcurrentHashMap.newKeySet()).containsAll(correct)).
|
||||
filter(delivered::add).
|
||||
forEach(smp -> deliverNextAsync(NetEvent.Message(smp.first(),smp.second())));
|
||||
forEach(smp -> deliverNextAsync(NetEvent.Message(pending.get(smp))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(NetEvent ne) {
|
||||
pending.add(new Pair<>(myId, ne.message.id));
|
||||
ne.message.src = myId;
|
||||
pending.put(new Pair<>(ne.message.src, ne.message.id),NetMessageAbstract.MSG(ne.message));
|
||||
requestCondBD(true);
|
||||
broadcastNextSync(ne);
|
||||
}
|
||||
|
||||
@ -59,25 +57,25 @@ public class NetHandlerURB extends NetEventHandlerAbstract {
|
||||
v.add(ne.peer.getId());
|
||||
return v;
|
||||
});
|
||||
if(pending.add(smp)){
|
||||
if(pending.putIfAbsent(smp, NetMessageAbstract.MSG(ne.message))==null){
|
||||
broadcastNextAsync(ne);
|
||||
}
|
||||
requestCondBD(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void crash(NetEvent ne) {
|
||||
correct.remove(ne.peer.getId());
|
||||
requestCondBD(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return delivered.containsAll(pending);
|
||||
return delivered.containsAll(pending.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
super.start(h,p);
|
||||
p.hosts().forEach(ch-> correct.add(ch.getId()));
|
||||
myId = h.getId();
|
||||
}
|
||||
}
|
@ -4,12 +4,23 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ConfigParser {
|
||||
|
||||
private String path;
|
||||
|
||||
private int messages;
|
||||
private final ConcurrentHashMap<Integer,List<Integer>> causality = new ConcurrentHashMap<>();
|
||||
|
||||
public ConfigParser(List<Host> hosts) {
|
||||
for (Host host : hosts) {
|
||||
causality.put(host.getId(),new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean populate(String value) {
|
||||
@ -17,13 +28,21 @@ public class ConfigParser {
|
||||
path = file.getPath();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
|
||||
int lineNum = 1;
|
||||
int lineNum = 0;
|
||||
for (String line; (line = br.readLine()) != null; lineNum++) {
|
||||
switch(lineNum){
|
||||
case 1:
|
||||
messages = Integer.parseInt(line);
|
||||
break;
|
||||
default:
|
||||
System.out.println(line);
|
||||
String[] lparts = line.trim().split(" ");
|
||||
if (lineNum == 0){
|
||||
messages = Integer.parseInt(lparts[0]);
|
||||
}else if (lineNum>=1 && lineNum<=causality.keySet().size()){
|
||||
Integer hid = Integer.parseInt(lparts[0]);
|
||||
List<Integer> vl = causality.get(hid);
|
||||
if(vl != null){
|
||||
for(int i = 1; i < lparts.length; ++i){
|
||||
vl.add(Integer.parseInt(lparts[i]));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -41,4 +60,8 @@ public class ConfigParser {
|
||||
public int getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public Map<Integer, List<Integer>> getCausality() {
|
||||
return causality;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Parser {
|
||||
|
||||
@ -57,8 +58,9 @@ public class Parser {
|
||||
}
|
||||
|
||||
if (argsNum == Constants.ARG_LIMIT_CONFIG) {
|
||||
configParser = new ConfigParser();
|
||||
configParser = new ConfigParser(hosts());
|
||||
if (!configParser.populate(args[Constants.CONFIG_VALUE])) {
|
||||
help();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,4 +110,8 @@ public class Parser {
|
||||
return configParser.getMessages();
|
||||
}
|
||||
|
||||
public Map<Integer, List<Integer>> causality(){
|
||||
return configParser.getCausality();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ public abstract class ParamDetector {
|
||||
|
||||
int messages = p.messageCount();
|
||||
int processCount = p.hosts().size();
|
||||
int windowWidthMult = Math.toIntExact(Math.round(Math.pow(2.0,(4-(processCount/4.0)))));
|
||||
int windowWidth = bound(coresPerProcess*windowWidthMult,4,messages);
|
||||
int windowWidthMult = Math.toIntExact(Math.round(Math.pow(2.0,(2-(processCount/2.0)))));
|
||||
int windowWidth = bound(coresPerProcess*windowWidthMult,2,messages);
|
||||
|
||||
System.out.println("Process expected to broadcast "+messages+" messages.");
|
||||
System.out.println("Starting Process with WindowWidth of "+windowWidth+" (~ x"+windowWidthMult+").");
|
||||
@ -42,5 +42,8 @@ public abstract class ParamDetector {
|
||||
//We might want to PingPong To set Custom Timing Limitations....
|
||||
NetManager.FD_MAX_TRIES = 10;
|
||||
NetManager.FD_WAIT = 1000;
|
||||
|
||||
NetManager.BUNDLE_SIZE = 2;
|
||||
NetManager.WINDOW_WIDTH *= NetManager.BUNDLE_SIZE;
|
||||
}
|
||||
}
|
||||
|
8
bnr.sh
8
bnr.sh
@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -eq 2 ]; then
|
||||
if [ $# -eq 3 ]; then
|
||||
export _JAVA_OPTIONS="-Xmx16G"
|
||||
./257844/build.sh
|
||||
sudo echo 1
|
||||
echo "Running with $1 processes and $2 messages"
|
||||
yes "" | ./validate.py -r 257844/run.sh -b fifo -l 257844/bin/logs -p $1 -m $2
|
||||
echo "Running $1 with $2 processes and $3 messages"
|
||||
yes "" | ./validate.py -r 257844/run.sh -b $1 -l 257844/bin/logs -p $2 -m $3
|
||||
else
|
||||
echo "Missing Arguments ..."
|
||||
echo "Usage: $0 process_count message_count"
|
||||
echo "Usage: $0 fifo|lcausal process_count message_count"
|
||||
fi
|
||||
|
142
validate.py
142
validate.py
@ -201,14 +201,144 @@ class FifoBroadcastValidation(Validation):
|
||||
return True
|
||||
|
||||
class LCausalBroadcastValidation(Validation):
|
||||
def __init__(self, processes, outputDir, causalRelationships):
|
||||
super().__init__(processes, outputDir)
|
||||
|
||||
def generateConfig(self):
|
||||
raise NotImplementedError()
|
||||
hosts = tempfile.NamedTemporaryFile(mode='w')
|
||||
config = tempfile.NamedTemporaryFile(mode='w')
|
||||
|
||||
def checkProcess(self, pid):
|
||||
raise NotImplementedError()
|
||||
# Hosts file
|
||||
for i in range(1, self.processes + 1):
|
||||
hosts.write("{} localhost {}\n".format(i, PROCESSES_BASE_IP+i))
|
||||
hosts.flush()
|
||||
|
||||
self.lcausalDeps = defaultdict(list)
|
||||
|
||||
# # of messages
|
||||
config.write("{}\n".format(self.messages))
|
||||
|
||||
# Config file; Create some random locality. Each process may have
|
||||
# up to N processes / 2 locally dependent processes.
|
||||
for thisproc in range(1, self.processes + 1):
|
||||
config.write(str(thisproc) + " ")
|
||||
|
||||
# Add random number of dependencies
|
||||
deps = [i for i in range(1, self.processes + 1) if i != thisproc]
|
||||
for j in range(0, random.randint(0, int(self.processes/2))):
|
||||
depidx = random.randint(0, len(deps) - 1)
|
||||
otherproc = deps[depidx]
|
||||
config.write(str(otherproc) + " ")
|
||||
self.lcausalDeps[thisproc].append(otherproc)
|
||||
del deps[depidx]
|
||||
config.write("\n")
|
||||
|
||||
config.flush()
|
||||
|
||||
return (hosts, config)
|
||||
|
||||
def filePathForPID(self, pid):
|
||||
return os.path.join(self.outputDirPath, 'proc{:02d}.output'.format(pid))
|
||||
|
||||
|
||||
def verifyCausality(self, fromPid, broadcastSeq, toPid, fromHistory):
|
||||
ok = True
|
||||
filename = self.filePathForPID(toPid)
|
||||
toPidFile = open(filename)
|
||||
toHistory = defaultdict(lambda: 0)
|
||||
|
||||
for lineNumber, line in enumerate(toPidFile):
|
||||
tokens = line.split()
|
||||
if tokens[0] == 'd':
|
||||
# Record most-recently received value from process. This is
|
||||
# sufficient due to LCausal also adhering to FIFO.
|
||||
if tokens[1] in fromHistory:
|
||||
toHistory[tokens[1]] = int(tokens[2])
|
||||
|
||||
if tokens[1] == fromPid and tokens[2] == broadcastSeq:
|
||||
# Found the dependent broadcast, ensure that history is consistent
|
||||
# up to this point
|
||||
for pid, seq in fromHistory.items():
|
||||
if toHistory[pid] < seq:
|
||||
print("File {}, Line {}: \n\tDelivered dependent message {}:{} with unresolved dependency\n"
|
||||
"\t Message was dependent on {}:{} but only delivered up to {}:{}".format(filename, lineNumber + 1,fromPid, broadcastSeq, pid,seq, pid, toHistory[pid]))
|
||||
ok = False
|
||||
|
||||
return ok
|
||||
|
||||
|
||||
|
||||
def checkLCausal(self, pid):
|
||||
if pid not in self.lcausalDeps:
|
||||
return True
|
||||
|
||||
depHistory = defaultdict(lambda: 0)
|
||||
pidFile = open(self.filePathForPID(pid))
|
||||
|
||||
for line in pidFile.readlines():
|
||||
ltokens = line.split()
|
||||
|
||||
# If token is broadcast, for each other process in the system,
|
||||
# verify that that token was delivered with adherance to the
|
||||
# causality as recorded in the @var depHistory up to this point
|
||||
if ltokens[0] == 'b':
|
||||
for i in range(1, self.processes+1):
|
||||
if i == pid:
|
||||
continue
|
||||
if not self.verifyCausality(
|
||||
fromPid=str(pid),
|
||||
broadcastSeq=ltokens[1],
|
||||
toPid=i,
|
||||
fromHistory=depHistory
|
||||
):
|
||||
return False
|
||||
|
||||
# If token is deliver and is in the set of causally dependent processes,
|
||||
# record it as being part of the dependent history up to this point.
|
||||
if ltokens[0] == 'd' and int(ltokens[1]) in self.lcausalDeps[pid]:
|
||||
depHistory[ltokens[1]] = int(ltokens[2])
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def checkFIFO(self, pid):
|
||||
filePath = os.path.join(self.outputDirPath, 'proc{:02d}.output'.format(pid))
|
||||
|
||||
i = 1
|
||||
nextMessage = defaultdict(lambda : 1)
|
||||
filename = os.path.basename(filePath)
|
||||
|
||||
with open(filePath) as f:
|
||||
for lineNumber, line in enumerate(f):
|
||||
tokens = line.split()
|
||||
|
||||
# Check broadcast
|
||||
if tokens[0] == 'b':
|
||||
msg = int(tokens[1])
|
||||
if msg != i:
|
||||
print("File {}, Line {}: Messages broadcast out of order. Expected message {} but broadcast message {}".format(filename, lineNumber, i, msg))
|
||||
return False
|
||||
i += 1
|
||||
|
||||
# Check delivery
|
||||
if tokens[0] == 'd':
|
||||
sender = int(tokens[1])
|
||||
msg = int(tokens[2])
|
||||
if msg != nextMessage[sender]:
|
||||
print("File {}, Line {}: Message delivered out of order. Expected message {}, but delivered message {}".format(filename, lineNumber, nextMessage[sender], msg))
|
||||
return False
|
||||
else:
|
||||
nextMessage[sender] = msg + 1
|
||||
return True
|
||||
|
||||
|
||||
def checkAll(self, continueOnError=True):
|
||||
print("LCausal verification:")
|
||||
for pid in range(1, self.processes+1):
|
||||
ret = self.checkFIFO(pid)
|
||||
ret &= self.checkLCausal(pid)
|
||||
|
||||
if not ret and not continueOnError:
|
||||
return False
|
||||
return True
|
||||
|
||||
class StressTest:
|
||||
def __init__(self, procs, concurrency, attempts, attemptsRatio):
|
||||
@ -359,7 +489,7 @@ def main(processes, messages, runscript, broadcastType, logsDir, testConfig):
|
||||
if broadcastType == "fifo":
|
||||
validation = FifoBroadcastValidation(processes, messages, logsDir)
|
||||
else:
|
||||
validation = LCausalBroadcastValidation(processes, messages, logsDir, None)
|
||||
validation = LCausalBroadcastValidation(processes, messages, logsDir)
|
||||
|
||||
hostsFile, configFile = validation.generateConfig()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user