diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9d80520 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,47 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Main", + "request": "launch", + "mainClass": "linda.search.basic.Main", + "projectName": "Projet PDR" + }, + { + "type": "java", + "name": "Launch Searcher", + "request": "launch", + "mainClass": "linda.search.basic.Searcher", + "args": [ + "4000" + ], + "projectName": "Projet PDR" + }, + { + "type": "java", + "name": "Launch Manager", + "request": "launch", + "mainClass": "linda.search.basic.Manager", + "args": [ + "4000", + "/usr/share/dict/french", + "agneau" + ], + "projectName": "Projet PDR" + }, + { + "type": "java", + "name": "Launch LindaServer", + "request": "launch", + "mainClass": "linda.server.LindaServer", + "args": [ + "4000" + ], + "projectName": "Projet PDR" + } + ] +} \ No newline at end of file diff --git a/src/main/java/linda/search/basic/Main.java b/src/main/java/linda/search/basic/Main.java index b05cc24..6111bd7 100644 --- a/src/main/java/linda/search/basic/Main.java +++ b/src/main/java/linda/search/basic/Main.java @@ -4,7 +4,7 @@ import linda.*; public class Main { - private static final int NB_SEARCHER = 10; + private static final int NB_SEARCHER = 2; public static void main(String args[]) throws InterruptedException { // if (args.length != 2) { @@ -13,20 +13,21 @@ public class Main { // } Linda linda = new linda.shm.CentralizedLinda(); - Manager manager1 = new Manager(linda, "/usr/share/dict/french", "abasourdir"); + Manager manager1 = new Manager(linda, "/usr/share/dict/french", "abasourdir", 500); Thread thread1 = new Thread(manager1); - thread1.start(); Manager manager2 = new Manager(linda, "/usr/share/dict/french", "agneau"); Thread thread2 = new Thread(manager2); - thread2.start(); for (int i = 0; i < NB_SEARCHER; i++) { Searcher searcher = new Searcher(linda); (new Thread(searcher)).start(); } + thread1.start(); + Thread.sleep(100); + thread2.start(); thread1.join(); thread2.join(); } -} +} \ No newline at end of file diff --git a/src/main/java/linda/search/basic/Manager.java b/src/main/java/linda/search/basic/Manager.java index f61511c..793326b 100644 --- a/src/main/java/linda/search/basic/Manager.java +++ b/src/main/java/linda/search/basic/Manager.java @@ -1,12 +1,21 @@ package linda.search.basic; import java.util.UUID; -import java.util.Timer; -import java.util.TimerTask; import java.util.stream.Stream; + +import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Paths; -import linda.*; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; + +import linda.Callback; +import linda.Linda; +import linda.Tuple; +import linda.Linda.eventMode; +import linda.Linda.eventTiming; +import linda.server.LindaClient; +import linda.server.SCallback; public class Manager implements Runnable { @@ -17,6 +26,7 @@ public class Manager implements Runnable { private String search; private int bestvalue = Integer.MAX_VALUE; // lower is better private String bestresult; + private Integer timeout = null; public Manager(Linda linda, String pathname, String search) { this.linda = linda; @@ -26,12 +36,34 @@ public class Manager implements Runnable { this.search = search; } + public Manager(Linda linda, String pathname, String search, int timeout) { + this(linda, pathname, search); + this.timeout = timeout; + } + + public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException { + if (args.length != 3) { + System.err.println("linda.search.basic.Main search file."); + return; + } + int port = Integer.parseInt(args[0]); + String url = "rmi://localhost:" + port + "/linda"; + LindaClient lc = new LindaClient(url); + + String dict = args[1]; + String word = args[2]; + + Manager manager = new Manager(lc, dict, word); + Thread thread = new Thread(manager); + thread.start(); + } + private void addSearch() { System.out.println("Search (" + this.reqUUID + ") for " + this.search); linda.eventRegister( Linda.eventMode.TAKE, Linda.eventTiming.FUTURE, new Tuple(Code.Result, this.reqUUID, String.class, Integer.class), - new CbGetResult()); + new CbUpdate()); linda.write(new Tuple(Code.Request, this.reqUUID, this.search)); } @@ -43,18 +75,35 @@ public class Manager implements Runnable { } } - private void waitForEndSearch() { - linda.take(new Tuple(Code.Searcher, "done", this.reqUUID)); // wait for the search to be finished - linda.take(new Tuple(Code.Request, this.reqUUID, String.class)); // remove search query - System.out.println("query done"); + class CbLoop implements Callback { + + eventMode mode; + eventTiming timing; + Tuple template; + + CbLoop(eventMode mode, eventTiming timing, Tuple template) { + this.mode = mode; + this.timing = timing; + this.template = template; + + linda.eventRegister(this.mode, this.timing, this.template, this); + } + + public void call(Tuple t) { + linda.eventRegister(this.mode, this.timing, this.template, this); + } } - private void waitForResult() { - linda.take(new Tuple(Code.Searcher, "end", this.reqUUID)); - System.out.println("Final result: \"" + bestresult + '"'); + private class CbEnd implements Callback { + @Override + public void call(Tuple t) { + new CbLoop(eventMode.TAKE, eventTiming.IMMEDIATE, t); // on supprime tous les futurs "done" + linda.take(new Tuple(Code.Request, reqUUID, String.class)); // remove search query + System.out.println("query done"); + } } - private class CbGetResult implements linda.Callback { + private class CbUpdate implements SCallback { public void call(Tuple t) { // [ Result, ?UUID, ?String, ?Integer ] UUID reqUUID = (UUID) t.get(1); String s = (String) t.get(2); @@ -68,7 +117,8 @@ public class Manager implements Runnable { // Tant qu'il reste des mots à chercher, ou des résultats à traiter if ((linda.tryRead(new Tuple(Code.Result, reqUUID, String.class, Integer.class)) != null) - || (linda.tryRead(new Tuple(Code.Value, String.class, reqUUID)) != null)) { + || (linda.tryRead(new Tuple(Code.Value, String.class, reqUUID)) != null) + || (linda.tryRead(new Tuple(Code.Request, reqUUID, String.class)) != null)) { linda.eventRegister( Linda.eventMode.TAKE, Linda.eventTiming.IMMEDIATE, @@ -81,10 +131,51 @@ public class Manager implements Runnable { } } + class TimeoutExit implements Runnable { + @Override + public void run() { + try { + Thread.sleep(timeout); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + System.out.println("Search (" + reqUUID + ") timed out "); + linda.take(new Tuple(Code.Request, reqUUID, String.class)); // remove search query + linda.takeAll(new Tuple(Code.Value, String.class, reqUUID)); // remove words + + new CbLoop(Linda.eventMode.TAKE, Linda.eventTiming.IMMEDIATE, + new Tuple(Code.Result, reqUUID, String.class, Integer.class)); // remove results + + new CbLoop(Linda.eventMode.TAKE, Linda.eventTiming.IMMEDIATE, + new Tuple(Code.Searcher, "done", reqUUID)); // remove "done" messages + + new CbLoop(Linda.eventMode.TAKE, Linda.eventTiming.IMMEDIATE, + new Tuple(Code.Searcher, "end", reqUUID)); // remove "end" messages + + // TODO: chercheur doivent écrire qui ils cherchent, pour que le manager puisse + // se stopper su personne ne le cherche + } + } + public void run() { - this.loadData(); - this.addSearch(); - this.waitForEndSearch(); - this.waitForResult(); + if (this.timeout != null) { + TimeoutExit exit = new TimeoutExit(); + Thread thread = new Thread(exit); + thread.start(); + } + + this.loadData(); // on charge les mots du dict + this.addSearch(); // on enregistre la query + + this.linda.eventRegister( // on attend la fin de la recherche + eventMode.TAKE, eventTiming.IMMEDIATE, + new Tuple(Code.Searcher, "done", this.reqUUID), + new CbEnd()); + + // on affiche le résultat (ou on le récupère...) + linda.take(new Tuple(Code.Searcher, "end", this.reqUUID)); + System.out.println("Final result: \"" + bestresult + '"'); + linda.debug("Tuple Space : "); } } diff --git a/src/main/java/linda/search/basic/Searcher.java b/src/main/java/linda/search/basic/Searcher.java index c42bdd3..0c7bb0a 100644 --- a/src/main/java/linda/search/basic/Searcher.java +++ b/src/main/java/linda/search/basic/Searcher.java @@ -1,8 +1,9 @@ package linda.search.basic; import linda.*; +import linda.server.LindaClient; + import java.util.Arrays; -import java.util.Collection; import java.util.UUID; public class Searcher implements Runnable { @@ -13,6 +14,20 @@ public class Searcher implements Runnable { this.linda = linda; } + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("linda.search.basic.Main search file."); + return; + } + int port = Integer.parseInt(args[0]); + String url = "rmi://localhost:" + port + "/linda"; + LindaClient lc = new LindaClient(url); + + Searcher searcher = new Searcher(lc); + Thread thread = new Thread(searcher); + thread.start(); + } + private void search(Tuple treq) { UUID reqUUID = (UUID) treq.get(1); String req = (String) treq.get(2); @@ -37,9 +52,9 @@ public class Searcher implements Runnable { public void run() { System.out.println("Ready to search"); - linda.read(new Tuple(Code.Request, UUID.class, String.class)); - Collection treqs = linda.readAll(new Tuple(Code.Request, UUID.class, String.class)); - for (Tuple treq : treqs) { + Tuple treq; + while (true) { + treq = linda.read(new Tuple(Code.Request, UUID.class, String.class)); search(treq); } } diff --git a/src/main/java/linda/server/LindaRemote.java b/src/main/java/linda/server/LindaRemote.java index 7266cc9..790c7bc 100644 --- a/src/main/java/linda/server/LindaRemote.java +++ b/src/main/java/linda/server/LindaRemote.java @@ -1,8 +1,8 @@ package linda.server; +import linda.Callback; import linda.Linda; import linda.Tuple; -import linda.Callback; import java.util.Collection; @@ -23,8 +23,9 @@ public interface LindaRemote extends Remote { public Collection takeAll(Tuple template) throws RemoteException; public Collection readAll(Tuple template) throws RemoteException; - - public void eventRegister(Linda.eventMode mode, Linda.eventTiming timing, Tuple template, Callback callback) throws RemoteException; + + public void eventRegister(Linda.eventMode mode, Linda.eventTiming timing, Tuple template, Callback callback) + throws RemoteException; public void debug(String prefix) throws RemoteException; } diff --git a/src/main/java/linda/server/LindaServer.java b/src/main/java/linda/server/LindaServer.java index 34c23b1..31bb703 100644 --- a/src/main/java/linda/server/LindaServer.java +++ b/src/main/java/linda/server/LindaServer.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.rmi.server.UnicastRemoteObject; import java.rmi.*; +import java.rmi.registry.LocateRegistry; import linda.Callback; import linda.Linda; @@ -21,16 +22,40 @@ public class LindaServer extends UnicastRemoteObject implements LindaRemote { this.lindaInstance = new CentralizedLinda(); } + public static void main(String[] args) { + Integer port = 4000; + + if (args.length == 2) { + port = Integer.parseInt(args[1]); + } + + String url = "rmi://localhost:" + port + "/linda"; + + try { + LindaServer ls = new LindaServer(); + LocateRegistry.createRegistry(port); + Naming.rebind(url, ls); + System.out.println("L'instance Linda a été publiée sur le registre (" + url + ") !"); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void write(Tuple t) { + System.out.println("received write request;" + t); lindaInstance.write(t); } public Tuple take(Tuple template) throws RemoteException { - return lindaInstance.take(template); + Tuple res = lindaInstance.take(template); + System.out.println("received take request, with template: " + template + "\nreturning:" + res); + return res; } public Tuple read(Tuple template) throws RemoteException { - return lindaInstance.read(template); + Tuple res = lindaInstance.read(template); + System.out.println("received read request, with template: " + template + "\nreturning:" + res); + return res; } public Tuple tryTake(Tuple template) throws RemoteException { @@ -49,7 +74,8 @@ public class LindaServer extends UnicastRemoteObject implements LindaRemote { return lindaInstance.readAll(template); } - public void eventRegister(Linda.eventMode mode, Linda.eventTiming timing, Tuple template, Callback callback) throws RemoteException { + public void eventRegister(Linda.eventMode mode, Linda.eventTiming timing, Tuple template, Callback callback) + throws RemoteException { lindaInstance.eventRegister(mode, timing, template, callback); } diff --git a/src/main/java/linda/server/SCallback.java b/src/main/java/linda/server/SCallback.java new file mode 100644 index 0000000..c579a68 --- /dev/null +++ b/src/main/java/linda/server/SCallback.java @@ -0,0 +1,16 @@ +package linda.server; + +import java.io.Serializable; + +import linda.Callback; +import linda.Tuple; + +public interface SCallback extends Serializable, Callback { + /** + * Callback when a tuple appears. + * See Linda.eventRegister for details. + * + * @param t the new tuple + */ + void call(Tuple t); +} diff --git a/src/main/java/linda/shm/CentralizedLinda.java b/src/main/java/linda/shm/CentralizedLinda.java index ec3df7d..bdb8b91 100644 --- a/src/main/java/linda/shm/CentralizedLinda.java +++ b/src/main/java/linda/shm/CentralizedLinda.java @@ -11,15 +11,13 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Lock; class Reveil { - Lock lock = new ReentrantLock(); - - Tuple template; Condition condition; + Tuple template; Reveil(Tuple template) { this.template = template; @@ -271,7 +269,7 @@ public class CentralizedLinda implements Linda { } public void debug(String prefix) { - System.out.println(prefix + tuples); + System.out.println(prefix + tuples.size()); } } diff --git a/src/test/java/linda/test/ServerTest.java b/src/test/java/linda/test/ServerTest.java deleted file mode 100644 index fd6cc70..0000000 --- a/src/test/java/linda/test/ServerTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package linda.test; - -import linda.server.LindaServer; - -import java.rmi.*; -import java.rmi.registry.*; - -public class ServerTest { - - public static void main(String[] args) { - try { - LindaServer ls = new LindaServer(); - LocateRegistry.createRegistry(Integer.parseInt(args[1])); - Naming.rebind(args[0], ls); - System.out.println("L'instance Linda a été publié sur le registre (" + args[0] + ") !\n"); - } catch (Exception e) { - e.printStackTrace(); - } - } - -}