implemented fifo
This commit is contained in:
parent
d43005ac48
commit
9e4e8190ac
32
257844/.gitignore
vendored
Normal file
32
257844/.gitignore
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/java
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=java
|
||||
|
||||
target/
|
||||
bin/da_proc.jar
|
||||
|
||||
### Java ###
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/java
|
11
257844/257844.iml
Normal file
11
257844/257844.iml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
1
257844/bin/README
Normal file
1
257844/bin/README
Normal file
@ -0,0 +1 @@
|
||||
This is a reserved directory name! Store the binary generated by `build.sh` in this directory
|
1
257844/bin/deploy/README
Normal file
1
257844/bin/deploy/README
Normal file
@ -0,0 +1 @@
|
||||
This is a reserved directory name, do not delete or use in your application!
|
9
257844/build.sh
Executable file
9
257844/build.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Change the current working directory to the location of the present file
|
||||
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
mvn clean compile assembly:single
|
||||
mv target/da_project-1.0-SNAPSHOT-jar-with-dependencies.jar bin/da_proc.jar
|
7
257844/cleanup.sh
Executable file
7
257844/cleanup.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Change the current working directory to the location of the present file
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
rm -f "$DIR"/bin/da_proc.jar
|
||||
rm -rf "$DIR"/target
|
62
257844/pom.xml
Normal file
62
257844/pom.xml
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cs451</groupId>
|
||||
<artifactId>da_project</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<name>DA_Project</name>
|
||||
<url>https://www.helcel.net</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.11</maven.compiler.source>
|
||||
<maven.compiler.target>1.11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
||||
<plugins>
|
||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<release>11</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<release>11</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<release>11</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>cs451.Main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
9
257844/run.sh
Executable file
9
257844/run.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Change the current working directory to the location of the present file
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
ret=0
|
||||
exec 3>&1; $(java -jar "$DIR"/bin/da_proc.jar "$@" >&3); ret=$?; exec 3>&-
|
||||
|
||||
exit $ret
|
139
257844/src/main/java/cs451/Main.java
Normal file
139
257844/src/main/java/cs451/Main.java
Normal file
@ -0,0 +1,139 @@
|
||||
package cs451;
|
||||
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.NetEventType;
|
||||
import cs451.parser.Coordinator;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
import cs451.tools.Logger;
|
||||
import cs451.tools.Pair;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static String formatOutput(Integer id, Integer host, Message.TYPE tpe){
|
||||
switch (tpe){
|
||||
case DATA:
|
||||
return "d "+host+" "+id+"\n";
|
||||
case ACK:
|
||||
return "d "+host+" "+id+"\n";
|
||||
case BCST:
|
||||
return "b "+id+"\n";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeOutput(String filepath) throws IOException {
|
||||
FileWriter writer = new FileWriter(filepath);
|
||||
|
||||
for(Pair<Pair<Integer,Integer>, Message.TYPE> mhpt : mh_tpe){
|
||||
try {
|
||||
writer.write(formatOutput(mhpt.first().first(),mhpt.first().second(),mhpt.second()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private static void handleSignal() {
|
||||
//immediately stop network packet processing
|
||||
System.out.println("Immediately stopping network packet processing.");
|
||||
|
||||
NetManager.stop();
|
||||
|
||||
//write/flush output file if necessary
|
||||
System.out.println("Writing output.");
|
||||
|
||||
try {
|
||||
writeOutput(parser.output());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void initSignalHandlers() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(Main::handleSignal));
|
||||
}
|
||||
|
||||
private static Host me = null;
|
||||
private static final Queue<Pair<Pair<Integer,Integer>,Message.TYPE>> mh_tpe = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private static Parser parser = null;
|
||||
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
parser = new Parser(args);
|
||||
parser.parse();
|
||||
|
||||
initSignalHandlers();
|
||||
|
||||
// example
|
||||
long pid = ProcessHandle.current().pid();
|
||||
System.out.println("My PID is " + pid + ".");
|
||||
System.out.println("Use 'kill -SIGINT " + pid + " ' or 'kill -SIGTERM " + pid + " ' to stop processing packets.");
|
||||
|
||||
System.out.println("My id is " + parser.myId() + ".");
|
||||
System.out.println("List of hosts is:");
|
||||
for (Host host : parser.hosts()) {
|
||||
if (host.getId() == parser.myId()) {
|
||||
me = host;
|
||||
}
|
||||
System.out.println(host.getId() + ", " + host.getIp() + ", " + host.getPort());
|
||||
}
|
||||
|
||||
System.out.println("Barrier: " + parser.barrierIp() + ":" + parser.barrierPort());
|
||||
System.out.println("Signal: " + parser.signalIp() + ":" + parser.signalPort());
|
||||
System.out.println("Output: " + parser.output());
|
||||
// if config is defined; always check before parser.config()
|
||||
if (parser.hasConfig()) {
|
||||
System.out.println("Config: " + parser.config());
|
||||
}
|
||||
Coordinator coordinator = new Coordinator(parser.myId(), parser.barrierIp(), parser.barrierPort(), parser.signalIp(), parser.signalPort());
|
||||
|
||||
NetManager.start(me,parser,(t,ne) -> {
|
||||
Logger.error(t+"(" + ne.message.src + "):" + ne.message.toString());
|
||||
if(t == NetEventType.DLVR){
|
||||
mh_tpe.add(new Pair<>(new Pair<>(ne.message.id,ne.message.src),ne.message.tpe));
|
||||
}else if(t== NetEventType.SEND){
|
||||
mh_tpe.add(new Pair<>(new Pair<>(ne.message.id,ne.message.src),ne.message.tpe));
|
||||
}
|
||||
}, (t,ne) -> {
|
||||
Logger.error("ERR"+t+" - "+ne.getMessage());
|
||||
});
|
||||
|
||||
System.out.println("Waiting for all processes for finish initialization");
|
||||
coordinator.waitOnBarrier();
|
||||
|
||||
System.out.println("Broadcasting messages...");
|
||||
NetManager.send();
|
||||
|
||||
while(!NetManager.isDone()) {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
System.out.println("Stopping NetManager");
|
||||
NetManager.stop();
|
||||
|
||||
System.out.println("Signaling end of broadcasting messages");
|
||||
coordinator.finishedBroadcasting();
|
||||
|
||||
try {
|
||||
writeOutput(parser.output());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// Sleep for 1 hour
|
||||
Thread.sleep(60 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
}
|
138
257844/src/main/java/cs451/net/NetManager.java
Normal file
138
257844/src/main/java/cs451/net/NetManager.java
Normal file
@ -0,0 +1,138 @@
|
||||
package cs451.net;
|
||||
|
||||
import cs451.net.event.*;
|
||||
|
||||
import cs451.net.handler.*;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
import cs451.tools.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
|
||||
|
||||
public abstract class NetManager {
|
||||
private static final Integer THREAD_COUNT = 8;
|
||||
|
||||
private static boolean isStopped = false;
|
||||
|
||||
private static final Map<Class<? extends NetEventHandler>, NetEventHandler> nm_listeners = new HashMap<>();
|
||||
|
||||
private static final ThreadPoolExecutor ex = new ThreadPoolExecutor(THREAD_COUNT,THREAD_COUNT,60,TimeUnit.SECONDS,new LinkedBlockingQueue<>());
|
||||
|
||||
private static BiConsumer<NetEventType,NetEvent> onCompleteHandler;
|
||||
private static BiConsumer<NetEventType,Exception> onErrorHandler;
|
||||
|
||||
|
||||
private static void registerNetHandler(NetEventHandler handler){
|
||||
nm_listeners.put(handler.getClass(),handler);
|
||||
}
|
||||
|
||||
public static void start(Host h, Parser p, BiConsumer<NetEventType,NetEvent> och, BiConsumer<NetEventType,Exception> oeh) {
|
||||
onCompleteHandler = och;
|
||||
onErrorHandler = oeh;
|
||||
|
||||
registerNetHandler(new NetHandlerSCKT( NetHandlerSL.class, NetHandlerDFLT.class));
|
||||
registerNetHandler(new NetHandlerSL( NetHandlerPL.class, NetHandlerSCKT.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 NetHandlerDFLT( NetHandlerDFLT.class, NetHandlerDFLT.class));
|
||||
|
||||
nm_listeners.values().forEach(neh -> neh.start(h,p));
|
||||
ex.prestartAllCoreThreads();
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
isStopped = true;
|
||||
nm_listeners.values().forEach(NetEventHandler::stop);
|
||||
ex.shutdown();
|
||||
System.out.println("NetManager handled "+ex.getCompletedTaskCount()+" tasks during this run.");
|
||||
}
|
||||
|
||||
public static boolean isDone() {
|
||||
return isStopped || nm_listeners.values().stream().map(NetEventHandler::isDone).reduce(ex.getActiveCount()==0 && ex.getQueue().size()==0,(b1, b2) -> b1 && b2);
|
||||
}
|
||||
|
||||
|
||||
//=================================================================================================================
|
||||
//=================================================================================================================
|
||||
|
||||
public static void handle(Class<? extends NetEventHandler> layer, NetEventType event, NetEvent ne){
|
||||
try {
|
||||
ex.getQueue().add(new NetEventRunner(ne, layer, event));
|
||||
}catch(IllegalStateException ise){
|
||||
error(event,ise);
|
||||
}
|
||||
}
|
||||
|
||||
public static void complete(NetEventType t,NetEvent ne){
|
||||
onCompleteHandler.accept(t,ne);
|
||||
}
|
||||
|
||||
public static void error(NetEventType t,Exception e){
|
||||
onErrorHandler.accept(t,e);
|
||||
}
|
||||
|
||||
//=================================================================================================================
|
||||
//=================================================================================================================
|
||||
|
||||
public static void deliver(Class<? extends NetEventHandler> layer, NetEvent ne) {
|
||||
handle(layer,NetEventType.DLVR,ne);
|
||||
}
|
||||
|
||||
public static void send(Class<? extends NetEventHandler> layer, NetEvent ne) {
|
||||
handle(layer,NetEventType.SEND,ne);
|
||||
}
|
||||
|
||||
public static void crash(Class<? extends NetEventHandler> layer, NetEvent ne) {
|
||||
handle(layer,NetEventType.CRSH,ne);
|
||||
}
|
||||
|
||||
public static void send() {
|
||||
new NetEventRunner(NetEvent.EMPTY(),NetHandlerTOPL.class,NetEventType.SEND).run();
|
||||
}
|
||||
|
||||
public static void deliverSync(Class<? extends NetEventHandler> layer, NetEvent ne) {
|
||||
new NetEventRunner(ne,layer,NetEventType.DLVR).run();
|
||||
}
|
||||
public static void sendSync(Class<? extends NetEventHandler> layer, NetEvent ne) {
|
||||
new NetEventRunner(ne,layer,NetEventType.SEND).run();
|
||||
}
|
||||
|
||||
//=================================================================================================================
|
||||
//=================================================================================================================
|
||||
|
||||
private static class NetEventRunner implements Runnable {
|
||||
|
||||
private final NetEvent ne;
|
||||
private final Class<? extends NetEventHandler> lt;
|
||||
private final NetEventType net;
|
||||
|
||||
private NetEventRunner(NetEvent ne, Class<? extends NetEventHandler> lt, NetEventType net) {
|
||||
this.ne = ne;
|
||||
this.lt = lt;
|
||||
this.net = net;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Logger.debug(this.lt.getSimpleName()+"_"+this.net+ ": " + ((ne.peer==null)?"?":ne.peer.getId()) + " - "+ne.message.toString()+"");
|
||||
|
||||
NetEventHandler nl = nm_listeners.getOrDefault(this.lt, null);
|
||||
if (nl != null) {
|
||||
nl.onEvent(this.net,ne);
|
||||
}else{
|
||||
error(this.net,new UnsupportedOperationException("No Handler for "+this.lt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
110
257844/src/main/java/cs451/net/event/Message.java
Normal file
110
257844/src/main/java/cs451/net/event/Message.java
Normal file
@ -0,0 +1,110 @@
|
||||
package cs451.net.event;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Message implements Comparable {
|
||||
|
||||
public enum TYPE {
|
||||
NONE("NONE", 'N'),
|
||||
ERR("ERR", 'E'),
|
||||
DATA("DATA", ' '),
|
||||
ACK("ACK", 'A'),
|
||||
BCST("BCST", 'B');
|
||||
|
||||
public final Character c;
|
||||
public final String tag;
|
||||
TYPE(String tag, Character c){
|
||||
this.tag = tag;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int src = -1;
|
||||
public final int id;
|
||||
public TYPE tpe;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static Message TMSG(Integer mess_id, TYPE tpe) {
|
||||
return new Message(mess_id, tpe);
|
||||
}
|
||||
|
||||
public static Message EMPTY(){
|
||||
return new Message(-1, TYPE.NONE);
|
||||
}
|
||||
|
||||
private static TYPE CharacterToTpe(Character c){
|
||||
return Arrays.stream(TYPE.values()).filter(type -> type.c==c).findFirst().orElse(TYPE.NONE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public void ToBuffer(ByteBuffer b){
|
||||
b.putChar(tpe.c);
|
||||
b.putInt(id);
|
||||
b.putInt(src);
|
||||
}
|
||||
|
||||
public 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() {
|
||||
switch(tpe) {
|
||||
case DATA:
|
||||
return src+"-"+ id;
|
||||
default:
|
||||
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 == m.id && src == m.src;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id,src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object obj) {
|
||||
final Message m = (Message) obj;
|
||||
return id-m.id;
|
||||
}
|
||||
}
|
52
257844/src/main/java/cs451/net/event/NetEvent.java
Normal file
52
257844/src/main/java/cs451/net/event/NetEvent.java
Normal file
@ -0,0 +1,52 @@
|
||||
package cs451.net.event;
|
||||
|
||||
import cs451.parser.Host;
|
||||
|
||||
public class NetEvent {
|
||||
|
||||
public final Host peer;
|
||||
public final Message message;
|
||||
|
||||
private NetEvent(Host peer, Message message) {
|
||||
this.peer = peer;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public static NetEvent Message(Host peer, Integer mess_id){
|
||||
return new NetEvent(peer, Message.DMSG(mess_id));
|
||||
}
|
||||
|
||||
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, Message m){
|
||||
return new NetEvent(peer,new Message(m));
|
||||
}
|
||||
|
||||
public static NetEvent Message(Message m){
|
||||
return new NetEvent(NO_PEER,new Message(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 EMPTY(){
|
||||
return new NetEvent(NO_PEER, Message.EMPTY());
|
||||
}
|
||||
|
||||
public static final Host NO_PEER = null;
|
||||
}
|
8
257844/src/main/java/cs451/net/event/NetEventType.java
Normal file
8
257844/src/main/java/cs451/net/event/NetEventType.java
Normal file
@ -0,0 +1,8 @@
|
||||
package cs451.net.event;
|
||||
|
||||
public enum NetEventType {
|
||||
DLVR,
|
||||
SEND,
|
||||
CRSH,
|
||||
RCVR;
|
||||
}
|
84
257844/src/main/java/cs451/net/handler/NetEventHandler.java
Normal file
84
257844/src/main/java/cs451/net/handler/NetEventHandler.java
Normal file
@ -0,0 +1,84 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.net.event.NetEventType;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
import cs451.tools.Logger;
|
||||
|
||||
public abstract class NetEventHandler {
|
||||
|
||||
/*
|
||||
* 1 - 50ms - 50ms
|
||||
* 2 - 400ms - 450ms
|
||||
* 3 - 1350ms - 1800ms
|
||||
* 4 - 3200ms - 5000ms
|
||||
*/
|
||||
public static final int MS_WAIT = 50;
|
||||
public static final int MAX_TRIES = 5;
|
||||
|
||||
public static final Integer SEND_WINDOW = 3;
|
||||
|
||||
|
||||
|
||||
private final Class<? extends NetEventHandler> deliverLayer;
|
||||
private final Class<? extends NetEventHandler> broadcastLayer;
|
||||
|
||||
|
||||
NetEventHandler(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
this.deliverLayer = deliverLayer;
|
||||
this.broadcastLayer = broadcastLayer;
|
||||
}
|
||||
|
||||
public void deliverNextSync(NetEvent ne){
|
||||
NetManager.deliverSync(deliverLayer,ne);
|
||||
}
|
||||
public void sendNextSync(NetEvent ne){
|
||||
NetManager.sendSync(broadcastLayer,ne);
|
||||
}
|
||||
|
||||
public void deliverNext(NetEvent ne){
|
||||
NetManager.deliver(deliverLayer,ne);
|
||||
}
|
||||
public void sendNext(NetEvent ne){
|
||||
NetManager.send(broadcastLayer,ne);
|
||||
}
|
||||
|
||||
public void onEvent(NetEventType et, NetEvent ne){
|
||||
switch (et){
|
||||
case DLVR: deliver(ne);
|
||||
break;
|
||||
case SEND: send(ne);
|
||||
break;
|
||||
case CRSH: crash(ne);
|
||||
break;
|
||||
case RCVR: recover(ne);
|
||||
break;
|
||||
default:
|
||||
Logger.error("Unhandled EventType:"+et);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(NetEvent ne){
|
||||
NetManager.error(NetEventType.SEND,new Exception("Default Handler"));
|
||||
}
|
||||
|
||||
public void deliver(NetEvent ne){
|
||||
NetManager.error(NetEventType.DLVR,new Exception("Default Handler"));
|
||||
}
|
||||
|
||||
public void crash(NetEvent ne){
|
||||
NetManager.error(NetEventType.CRSH,new Exception("Default Handler"));
|
||||
}
|
||||
|
||||
public void recover(NetEvent ne){
|
||||
NetManager.error(NetEventType.RCVR,new Exception("Default Handler"));
|
||||
}
|
||||
|
||||
public void start(Host h, Parser p) {}
|
||||
|
||||
public void stop() {}
|
||||
|
||||
public boolean isDone(){ return true;}
|
||||
}
|
40
257844/src/main/java/cs451/net/handler/NetHandlerBEB.java
Normal file
40
257844/src/main/java/cs451/net/handler/NetHandlerBEB.java
Normal file
@ -0,0 +1,40 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NetHandlerBEB extends NetEventHandler {
|
||||
|
||||
private List<Host> hosts;
|
||||
private Host h;
|
||||
|
||||
public NetHandlerBEB(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void send(NetEvent ne) {
|
||||
for(Host h : hosts){
|
||||
if(this.h.getId() != h.getId()) {
|
||||
sendNext(NetEvent.Message(h, ne.message));
|
||||
}else{
|
||||
deliverNext(NetEvent.Message(h,ne.message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
deliverNext(ne);
|
||||
}
|
||||
|
||||
public void start(Host h, Parser p) {
|
||||
this.h = h;
|
||||
hosts = p.hosts();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
public class NetHandlerDFLT extends NetEventHandler {
|
||||
|
||||
public NetHandlerDFLT(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
}
|
59
257844/src/main/java/cs451/net/handler/NetHandlerFIFO.java
Normal file
59
257844/src/main/java/cs451/net/handler/NetHandlerFIFO.java
Normal file
@ -0,0 +1,59 @@
|
||||
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.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NetHandlerFIFO extends NetEventHandler {
|
||||
|
||||
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;
|
||||
|
||||
public NetHandlerFIFO(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NetEvent ne) {
|
||||
Integer snv = sn.getAndIncrement();
|
||||
NetManager.complete(NetEventType.SEND, NetEvent.Message(me, snv, Message.TYPE.BCST));
|
||||
sendNext(NetEvent.Message(me.getId(),snv));
|
||||
}
|
||||
|
||||
private void deliverIf(){
|
||||
synchronized (pending) {
|
||||
pending.removeIf(hmp -> {
|
||||
Integer crsn = rsn.getOrDefault(hmp.src, 1);
|
||||
if (hmp.id == crsn) {
|
||||
deliverNextSync(NetEvent.Message(hmp));
|
||||
NetManager.complete(NetEventType.DLVR,NetEvent.Message(hmp));
|
||||
rsn.put(hmp.src, crsn + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
pending.add(ne.message);
|
||||
deliverIf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
me = h;
|
||||
}
|
||||
}
|
30
257844/src/main/java/cs451/net/handler/NetHandlerPL.java
Normal file
30
257844/src/main/java/cs451/net/handler/NetHandlerPL.java
Normal file
@ -0,0 +1,30 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.*;
|
||||
import cs451.tools.Pair;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class NetHandlerPL extends NetEventHandler {
|
||||
|
||||
private final Set<Pair<Integer,Message>> delivered = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public NetHandlerPL(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NetEvent event) {
|
||||
sendNext(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent event) {
|
||||
if(delivered.add(new Pair<>(event.peer.getId(),event.message))){
|
||||
deliverNext(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
94
257844/src/main/java/cs451/net/handler/NetHandlerSCKT.java
Normal file
94
257844/src/main/java/cs451/net/handler/NetHandlerSCKT.java
Normal file
@ -0,0 +1,94 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.*;
|
||||
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.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class NetHandlerSCKT extends NetEventHandler {
|
||||
|
||||
private static final Integer BUFF_SIZE = 128;
|
||||
|
||||
private List<Host> hosts;
|
||||
|
||||
private DatagramSocket socket = null;
|
||||
private final AtomicBoolean receiving = new AtomicBoolean(true);
|
||||
|
||||
|
||||
public NetHandlerSCKT(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NetEvent event) {
|
||||
if(socket.isClosed()){
|
||||
NetManager.error(NetEventType.SEND,new SocketException("Socket Closed"));
|
||||
return;
|
||||
}
|
||||
ByteBuffer b = ByteBuffer.allocate(BUFF_SIZE);
|
||||
event.message.ToBuffer(b);
|
||||
DatagramPacket datagram = new DatagramPacket(b.array(), b.position(), event.peer.getAddr());
|
||||
try {
|
||||
socket.send(datagram);
|
||||
} catch (IOException e) {
|
||||
NetManager.error(NetEventType.SEND,e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent event) {
|
||||
if(socket.isClosed()){
|
||||
NetManager.error(NetEventType.DLVR,new SocketException("Socket Closed"));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buff = new byte[BUFF_SIZE];
|
||||
DatagramPacket datagram = new DatagramPacket(buff, buff.length);
|
||||
try {
|
||||
socket.receive(datagram);
|
||||
Optional<Integer> rhid = hosts.stream().filter(h -> h.getAddr().equals(datagram.getSocketAddress())).map(Host::getId).findFirst();
|
||||
|
||||
deliverNext(NetEvent.Message(
|
||||
new Host((InetSocketAddress) datagram.getSocketAddress(), rhid.orElse(-1)),
|
||||
Message.FromBuffer(ByteBuffer.wrap(datagram.getData()))
|
||||
));
|
||||
} catch (IOException e) {
|
||||
NetManager.error(NetEventType.DLVR,e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
Objects.requireNonNull(h);
|
||||
Objects.requireNonNull(p);
|
||||
hosts = p.hosts();
|
||||
|
||||
try {
|
||||
this.socket = new DatagramSocket(h.getPort());
|
||||
} catch (SocketException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
receiving.set(true);
|
||||
new Thread(() -> {
|
||||
while (receiving.get()) {
|
||||
this.deliver(NetEvent.EMPTY());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
socket.close();
|
||||
receiving.set(false);
|
||||
}
|
||||
}
|
89
257844/src/main/java/cs451/net/handler/NetHandlerSL.java
Normal file
89
257844/src/main/java/cs451/net/handler/NetHandlerSL.java
Normal file
@ -0,0 +1,89 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.Message;
|
||||
import cs451.net.NetManager;
|
||||
import cs451.net.event.*;
|
||||
import cs451.tools.Pair;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class NetHandlerSL extends NetEventHandler {
|
||||
|
||||
private static final Set<Message> EMPTY_SET = ConcurrentHashMap.newKeySet();
|
||||
|
||||
Set<Integer> hasTimeout = ConcurrentHashMap.newKeySet();
|
||||
Map<Integer, Set<Message>> hasAck = new ConcurrentHashMap<>();
|
||||
Map<Pair<Integer, Message>, Integer> retryCounter = new ConcurrentHashMap<>();
|
||||
|
||||
public NetHandlerSL(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
|
||||
private void handleTimeout(NetEvent ne) {
|
||||
if (hasAck.getOrDefault(ne.peer.getId(),EMPTY_SET).contains(ne.message)) {
|
||||
return;
|
||||
}
|
||||
if (retryCounter.compute(new Pair<>(ne.peer.getId(),ne.message), (k, ov) -> (ov == null) ? 2 : ov + 1) >= MAX_TRIES) {
|
||||
timeout(ne);
|
||||
} else {
|
||||
send(ne);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTimeout(NetEvent ne) {
|
||||
new Thread(()->{
|
||||
Integer t = retryCounter.getOrDefault(new Pair<>(ne.peer.getId(), ne.message), 1);
|
||||
new Timer().schedule(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run () {
|
||||
handleTimeout(ne);
|
||||
}
|
||||
}, MS_WAIT*t*t*t);
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NetEvent ne) {
|
||||
if (hasTimeout.contains(ne.peer.getId())) {
|
||||
return;
|
||||
}
|
||||
sendNext(ne);
|
||||
checkTimeout(ne);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
if (hasTimeout.contains(ne.peer.getId())) {
|
||||
return;
|
||||
}
|
||||
switch (ne.message.tpe){
|
||||
case ACK:
|
||||
hasAck.compute(ne.peer.getId(),(k, s) -> {
|
||||
if(s == null) s = ConcurrentHashMap.newKeySet();
|
||||
s.add(ne.message);
|
||||
return s;
|
||||
});
|
||||
break;
|
||||
case DATA:
|
||||
sendNext(NetEvent.MessageACK(ne.peer,ne.message));
|
||||
deliverNext(ne);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void timeout(NetEvent event) {
|
||||
if(hasTimeout.add(event.peer.getId())) {
|
||||
NetManager.crash(NetHandlerURB.class, event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
58
257844/src/main/java/cs451/net/handler/NetHandlerTOPL.java
Normal file
58
257844/src/main/java/cs451/net/handler/NetHandlerTOPL.java
Normal file
@ -0,0 +1,58 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NetHandlerTOPL extends NetEventHandler {
|
||||
|
||||
private final AtomicInteger toSend = new AtomicInteger(0);
|
||||
private final AtomicInteger delivered = new AtomicInteger(0);
|
||||
private final AtomicInteger waiting = new AtomicInteger(0);
|
||||
|
||||
private Host me;
|
||||
|
||||
public NetHandlerTOPL(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer, broadcastLayer);
|
||||
}
|
||||
|
||||
|
||||
private void sendIf(){
|
||||
synchronized (waiting) {
|
||||
while (waiting.get() < SEND_WINDOW && toSend.get() > 0) {
|
||||
toSend.getAndDecrement();
|
||||
waiting.getAndIncrement();
|
||||
sendNextSync(NetEvent.EMPTY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NetEvent ne) {
|
||||
sendIf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
if (ne.message.src == me.getId()) {
|
||||
synchronized (waiting) {
|
||||
delivered.getAndIncrement();
|
||||
waiting.getAndDecrement();
|
||||
}
|
||||
sendIf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return toSend.get()==0 && waiting.get()==0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Host h, Parser p) {
|
||||
me = h;
|
||||
toSend.set(p.messageCount());
|
||||
}
|
||||
}
|
65
257844/src/main/java/cs451/net/handler/NetHandlerURB.java
Normal file
65
257844/src/main/java/cs451/net/handler/NetHandlerURB.java
Normal file
@ -0,0 +1,65 @@
|
||||
package cs451.net.handler;
|
||||
|
||||
import cs451.net.event.NetEvent;
|
||||
import cs451.parser.Host;
|
||||
import cs451.parser.Parser;
|
||||
import cs451.tools.Pair;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
public class NetHandlerURB extends NetEventHandler {
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public NetHandlerURB(Class<? extends NetEventHandler> deliverLayer, Class<? extends NetEventHandler> broadcastLayer) {
|
||||
super(deliverLayer,broadcastLayer);
|
||||
}
|
||||
|
||||
private void deliverIf(){
|
||||
pending.stream().filter(smp -> ack.getOrDefault(smp,ConcurrentHashMap.newKeySet()).containsAll(correct)).
|
||||
filter(delivered::add).
|
||||
forEach(smp -> deliverNext(NetEvent.Message(smp.first(),smp.second())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NetEvent ne) {
|
||||
pending.add(new Pair<>(myId, ne.message.id));
|
||||
ne.message.src = myId;
|
||||
sendNext(ne);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliver(NetEvent ne) {
|
||||
ack.compute(new Pair<>(ne.message.src,ne.message.id),(k, v) -> {
|
||||
if(v == null){
|
||||
v = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
v.add(ne.peer.getId());
|
||||
return v;
|
||||
});
|
||||
if(pending.add(new Pair<>(ne.message.src,ne.message.id))){
|
||||
sendNext(ne);
|
||||
}
|
||||
deliverIf();
|
||||
}
|
||||
|
||||
public void crash(NetEvent ne) {
|
||||
correct.remove(ne.peer.getId());
|
||||
deliverIf();
|
||||
}
|
||||
|
||||
public void start(Host h, Parser p) {
|
||||
p.hosts().forEach(ch-> correct.add(ch.getId()));
|
||||
myId = h.getId();
|
||||
}
|
||||
}
|
54
257844/src/main/java/cs451/parser/BarrierParser.java
Normal file
54
257844/src/main/java/cs451/parser/BarrierParser.java
Normal file
@ -0,0 +1,54 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class BarrierParser {
|
||||
|
||||
private static final String BARRIER_KEY = "--barrier";
|
||||
|
||||
private static final int BARRIER_ARGS_NUM = 2;
|
||||
private static final String COLON_REGEX = ":";
|
||||
private static final String IP_START_REGEX = "/";
|
||||
|
||||
private static String ip;
|
||||
private static int port;
|
||||
|
||||
public boolean populate(String key, String value) {
|
||||
if (!key.equals(BARRIER_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] barrier = value.split(COLON_REGEX);
|
||||
if (barrier.length != BARRIER_ARGS_NUM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
String ipTest = InetAddress.getByName(barrier[0]).toString();
|
||||
if (ipTest.startsWith(IP_START_REGEX)) {
|
||||
ip = ipTest.substring(1);
|
||||
} else {
|
||||
ip = InetAddress.getByName(ipTest.split(IP_START_REGEX)[0]).getHostAddress();
|
||||
}
|
||||
|
||||
port = Integer.parseInt(barrier[1]);
|
||||
if (port <= 0) {
|
||||
System.err.println("Barrier port must be a positive number!");
|
||||
return false;
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
44
257844/src/main/java/cs451/parser/ConfigParser.java
Normal file
44
257844/src/main/java/cs451/parser/ConfigParser.java
Normal file
@ -0,0 +1,44 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConfigParser {
|
||||
|
||||
private String path;
|
||||
|
||||
private int messages;
|
||||
|
||||
|
||||
public boolean populate(String value) {
|
||||
File file = new File(value);
|
||||
path = file.getPath();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
|
||||
int lineNum = 1;
|
||||
for (String line; (line = br.readLine()) != null; lineNum++) {
|
||||
switch(lineNum){
|
||||
case 1:
|
||||
messages = Integer.parseInt(line);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Problem with the hosts file!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public int getMessages() {
|
||||
return messages;
|
||||
}
|
||||
}
|
30
257844/src/main/java/cs451/parser/Constants.java
Normal file
30
257844/src/main/java/cs451/parser/Constants.java
Normal file
@ -0,0 +1,30 @@
|
||||
package cs451.parser;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final int ARG_LIMIT_NO_CONFIG = 10;
|
||||
public static final int ARG_LIMIT_CONFIG = 11;
|
||||
|
||||
// indexes for id
|
||||
public static final int ID_KEY = 0;
|
||||
public static final int ID_VALUE = 1;
|
||||
|
||||
// indexes for hosts
|
||||
public static final int HOSTS_KEY = 2;
|
||||
public static final int HOSTS_VALUE = 3;
|
||||
|
||||
// indexes for barrier
|
||||
public static final int BARRIER_KEY = 4;
|
||||
public static final int BARRIER_VALUE = 5;
|
||||
|
||||
// indexes for signal
|
||||
public static final int SIGNAL_KEY = 6;
|
||||
public static final int SIGNAL_VALUE = 7;
|
||||
|
||||
// indexes for output
|
||||
public static final int OUTPUT_KEY = 8;
|
||||
public static final int OUTPUT_VALUE = 9;
|
||||
|
||||
// indexes for config
|
||||
public static final int CONFIG_VALUE = 10;
|
||||
}
|
74
257844/src/main/java/cs451/parser/Coordinator.java
Normal file
74
257844/src/main/java/cs451/parser/Coordinator.java
Normal file
@ -0,0 +1,74 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.net.Socket;
|
||||
|
||||
public class Coordinator {
|
||||
|
||||
private final int pid;
|
||||
|
||||
private final String barrierIp;
|
||||
private final int barrierPort;
|
||||
|
||||
private final String signalIp;
|
||||
private final int signalPort;
|
||||
|
||||
private final Socket signalSocket;
|
||||
|
||||
public Coordinator(int pid, String barrierIp, int barrierPort, String signalIp, int signalPort) {
|
||||
this.pid = pid;
|
||||
this.barrierIp = barrierIp;
|
||||
this.barrierPort = barrierPort;
|
||||
this.signalIp = signalIp;
|
||||
this.signalPort = signalPort;
|
||||
|
||||
signalSocket = connectToHost(this.signalIp, this.signalPort);
|
||||
}
|
||||
|
||||
public void waitOnBarrier() {
|
||||
try {
|
||||
Socket socket = connectToHost(barrierIp, barrierPort);
|
||||
InputStream input = socket.getInputStream();
|
||||
InputStreamReader reader = new InputStreamReader(input);
|
||||
System.out.println("Accessing barrier...");
|
||||
|
||||
while (reader.read() != -1) {
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
System.out.println("I/O error: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void finishedBroadcasting() {
|
||||
try {
|
||||
signalSocket.close();
|
||||
} catch (IOException ex) {
|
||||
System.out.println("I/O error: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Socket connectToHost(String ip, int port) {
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = new Socket(ip, port);
|
||||
OutputStream output = socket.getOutputStream();
|
||||
DataOutputStream writer = new DataOutputStream(output);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(8);
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
bb.putLong(pid);
|
||||
|
||||
writer.write(bb.array(), 0, 8);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("I/O error: " + ex.getMessage());
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
}
|
78
257844/src/main/java/cs451/parser/Host.java
Normal file
78
257844/src/main/java/cs451/parser/Host.java
Normal file
@ -0,0 +1,78 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class Host {
|
||||
|
||||
private static final String IP_START_REGEX = "/";
|
||||
|
||||
private int id = -1;
|
||||
private String ip = null;
|
||||
private int port = -1;
|
||||
private SocketAddress addr = null;
|
||||
|
||||
public Host(InetSocketAddress addr, Integer id){
|
||||
this.addr = addr;
|
||||
this.ip = addr.getHostString();
|
||||
this.port = addr.getPort();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Host(){}
|
||||
|
||||
public Host(Integer id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean populate(String idString, String ipString, String portString) {
|
||||
try {
|
||||
id = Integer.parseInt(idString);
|
||||
|
||||
String ipTest = InetAddress.getByName(ipString).toString();
|
||||
if (ipTest.startsWith(IP_START_REGEX)) {
|
||||
ip = ipTest.substring(1);
|
||||
} else {
|
||||
ip = InetAddress.getByName(ipTest.split(IP_START_REGEX)[0]).getHostAddress();
|
||||
}
|
||||
|
||||
port = Integer.parseInt(portString);
|
||||
if (port <= 0) {
|
||||
System.err.println("Port in the hosts file must be a positive number!");
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
if (port == -1) {
|
||||
System.err.println("Id in the hosts file must be a number!");
|
||||
} else {
|
||||
System.err.println("Port in the hosts file must be a number!");
|
||||
}
|
||||
return false;
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.addr = new InetSocketAddress(ip, port);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public SocketAddress getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
}
|
87
257844/src/main/java/cs451/parser/HostsParser.java
Normal file
87
257844/src/main/java/cs451/parser/HostsParser.java
Normal file
@ -0,0 +1,87 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class HostsParser {
|
||||
|
||||
private static final String HOSTS_KEY = "--hosts";
|
||||
private static final String SPACES_REGEX = "\\s+";
|
||||
|
||||
private String filename;
|
||||
private final List<Host> hosts = new ArrayList<>();
|
||||
|
||||
public boolean populate(String key, String filename) {
|
||||
if (!key.equals(HOSTS_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.filename = filename;
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
|
||||
int lineNum = 1;
|
||||
for (String line; (line = br.readLine()) != null; lineNum++) {
|
||||
if (line.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] splits = line.split(SPACES_REGEX);
|
||||
if (splits.length != 3) {
|
||||
System.err.println("Problem with the line " + lineNum + " in the hosts file!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Host newHost = new Host();
|
||||
if (!newHost.populate(splits[0], splits[1], splits[2])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hosts.add(newHost);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Problem with the hosts file!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!checkIdRange()) {
|
||||
System.err.println("Hosts ids are not within the range!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// sort by id
|
||||
hosts.sort(new HostsComparator());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkIdRange() {
|
||||
int num = hosts.size();
|
||||
for (Host host : hosts) {
|
||||
if (host.getId() < 1 || host.getId() > num) {
|
||||
System.err.println("Id of a host is not in the right range!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean inRange(int id) {
|
||||
return id <= hosts.size();
|
||||
}
|
||||
|
||||
public List<Host> getHosts() {
|
||||
return hosts;
|
||||
}
|
||||
|
||||
static class HostsComparator implements Comparator<Host> {
|
||||
|
||||
public int compare(Host a, Host b) {
|
||||
return a.getId() - b.getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
31
257844/src/main/java/cs451/parser/IdParser.java
Normal file
31
257844/src/main/java/cs451/parser/IdParser.java
Normal file
@ -0,0 +1,31 @@
|
||||
package cs451.parser;
|
||||
|
||||
public class IdParser {
|
||||
|
||||
private static final String ID_KEY = "--id";
|
||||
|
||||
private int id;
|
||||
|
||||
public boolean populate(String key, String value) {
|
||||
if (!key.equals(ID_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
id = Integer.parseInt(value);
|
||||
if (id <= 0) {
|
||||
System.err.println("Id must be a positive number!");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Id must be a number!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
25
257844/src/main/java/cs451/parser/OutputParser.java
Normal file
25
257844/src/main/java/cs451/parser/OutputParser.java
Normal file
@ -0,0 +1,25 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class OutputParser {
|
||||
|
||||
private static final String OUTPUT_KEY = "--output";
|
||||
|
||||
private String path;
|
||||
|
||||
public boolean populate(String key, String value) {
|
||||
if (!key.equals(OUTPUT_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File file = new File(value);
|
||||
path = file.getPath();
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
111
257844/src/main/java/cs451/parser/Parser.java
Normal file
111
257844/src/main/java/cs451/parser/Parser.java
Normal file
@ -0,0 +1,111 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Parser {
|
||||
|
||||
private final String[] args;
|
||||
private long pid;
|
||||
private IdParser idParser;
|
||||
private HostsParser hostsParser;
|
||||
private BarrierParser barrierParser;
|
||||
private SignalParser signalParser;
|
||||
private OutputParser outputParser;
|
||||
private ConfigParser configParser;
|
||||
|
||||
public Parser(String[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public void parse() {
|
||||
pid = ProcessHandle.current().pid();
|
||||
|
||||
idParser = new IdParser();
|
||||
hostsParser = new HostsParser();
|
||||
barrierParser = new BarrierParser();
|
||||
signalParser = new SignalParser();
|
||||
outputParser = new OutputParser();
|
||||
configParser = null;
|
||||
|
||||
int argsNum = args.length;
|
||||
if (argsNum != Constants.ARG_LIMIT_NO_CONFIG && argsNum != Constants.ARG_LIMIT_CONFIG) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (!idParser.populate(args[Constants.ID_KEY], args[Constants.ID_VALUE])) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (!hostsParser.populate(args[Constants.HOSTS_KEY], args[Constants.HOSTS_VALUE])) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (!hostsParser.inRange(idParser.getId())) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (!barrierParser.populate(args[Constants.BARRIER_KEY], args[Constants.BARRIER_VALUE])) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (!signalParser.populate(args[Constants.SIGNAL_KEY], args[Constants.SIGNAL_VALUE])) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (!outputParser.populate(args[Constants.OUTPUT_KEY], args[Constants.OUTPUT_VALUE])) {
|
||||
help();
|
||||
}
|
||||
|
||||
if (argsNum == Constants.ARG_LIMIT_CONFIG) {
|
||||
configParser = new ConfigParser();
|
||||
if (!configParser.populate(args[Constants.CONFIG_VALUE])) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void help() {
|
||||
System.err.println("Usage: ./run.sh --id ID --hosts HOSTS --barrier NAME:PORT --signal NAME:PORT --output OUTPUT [config]");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
public int myId() {
|
||||
return idParser.getId();
|
||||
}
|
||||
|
||||
public List<Host> hosts() {
|
||||
return hostsParser.getHosts();
|
||||
}
|
||||
|
||||
public String barrierIp() {
|
||||
return barrierParser.getIp();
|
||||
}
|
||||
|
||||
public int barrierPort() {
|
||||
return barrierParser.getPort();
|
||||
}
|
||||
|
||||
public String signalIp() {
|
||||
return signalParser.getIp();
|
||||
}
|
||||
|
||||
public int signalPort() {
|
||||
return signalParser.getPort();
|
||||
}
|
||||
|
||||
public String output() {
|
||||
return outputParser.getPath();
|
||||
}
|
||||
|
||||
public boolean hasConfig() {
|
||||
return configParser != null;
|
||||
}
|
||||
|
||||
public String config() {
|
||||
return configParser.getPath();
|
||||
}
|
||||
|
||||
public int messageCount(){
|
||||
return configParser.getMessages();
|
||||
}
|
||||
|
||||
}
|
54
257844/src/main/java/cs451/parser/SignalParser.java
Normal file
54
257844/src/main/java/cs451/parser/SignalParser.java
Normal file
@ -0,0 +1,54 @@
|
||||
package cs451.parser;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class SignalParser {
|
||||
|
||||
private static final String SIGNAL_KEY = "--signal";
|
||||
|
||||
private static final int SIGNAL_ARGS_NUM = 2;
|
||||
private static final String COLON_REGEX = ":";
|
||||
private static final String IP_START_REGEX = "/";
|
||||
|
||||
private static String ip;
|
||||
private static int port;
|
||||
|
||||
public boolean populate(String key, String value) {
|
||||
if (!key.equals(SIGNAL_KEY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] signal = value.split(COLON_REGEX);
|
||||
if (signal.length != SIGNAL_ARGS_NUM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
String ipTest = InetAddress.getByName(signal[0]).toString();
|
||||
if (ipTest.startsWith(IP_START_REGEX)) {
|
||||
ip = ipTest.substring(1);
|
||||
} else {
|
||||
ip = InetAddress.getByName(ipTest.split(IP_START_REGEX)[0]).getHostAddress();
|
||||
}
|
||||
|
||||
port = Integer.parseInt(signal[1]);
|
||||
if (port <= 0) {
|
||||
System.err.println("Signal port must be a positive number!");
|
||||
return false;
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
42
257844/src/main/java/cs451/tools/Logger.java
Normal file
42
257844/src/main/java/cs451/tools/Logger.java
Normal file
@ -0,0 +1,42 @@
|
||||
package cs451.tools;
|
||||
|
||||
public abstract class Logger {
|
||||
|
||||
public enum LOG_LEVEL{
|
||||
ERR(-1),
|
||||
INFO(0),
|
||||
DEBUG(1),
|
||||
ALL(99);
|
||||
|
||||
public final Integer v;
|
||||
LOG_LEVEL(Integer v){
|
||||
this.v = v;
|
||||
}
|
||||
public boolean isEnabled(){
|
||||
return this.v <= LVL.v;
|
||||
}
|
||||
}
|
||||
|
||||
private static final LOG_LEVEL LVL = LOG_LEVEL.ALL;
|
||||
|
||||
public static void info(String msg){
|
||||
if(LOG_LEVEL.INFO.isEnabled()){
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(String msg){
|
||||
if(LOG_LEVEL.DEBUG.isEnabled()){
|
||||
System.err.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void error(String msg){
|
||||
if(LOG_LEVEL.ERR.isEnabled()){
|
||||
System.err.println(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
58
257844/src/main/java/cs451/tools/Pair.java
Normal file
58
257844/src/main/java/cs451/tools/Pair.java
Normal file
@ -0,0 +1,58 @@
|
||||
package cs451.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Pair<S, T> implements Comparable {
|
||||
private final S x;
|
||||
private final T y;
|
||||
private final List<Object> vl = new ArrayList<>();
|
||||
|
||||
public Pair(S x, T y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
vl.add(x.toString());
|
||||
vl.add(y.toString());
|
||||
}
|
||||
|
||||
public S first(){
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public T second(){
|
||||
return this.y;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return this.vl.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.vl.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Pair other = (Pair) obj;
|
||||
return this.vl.equals(other.vl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
Pair co = (Pair)o;
|
||||
|
||||
return ((int)co.second())- ((int)second());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user