diff --git a/src/pp.11.01-FindWords/README.md b/src/pp.11.01-FindWords/README.md
new file mode 100644
index 0000000..f8a4db0
--- /dev/null
+++ b/src/pp.11.01-FindWords/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Paralleles Suchen/Finden eines Suchstrings in einigen wenigen Textdateien"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-01-FindWords.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-Solutions.html#laboraufgabe-paralleles-suchenfinden-eines-suchstrings-in-einigen-wenigen-textdateien)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/11-actors.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/11-actors.html)
diff --git a/src/pp.11.01-FindWords/justfile b/src/pp.11.01-FindWords/justfile
new file mode 100644
index 0000000..6c0be50
--- /dev/null
+++ b/src/pp.11.01-FindWords/justfile
@@ -0,0 +1,17 @@
+# Justfile (https://just.systems/) for starting Maven standard targets
+
+default:
+ just exec pp.Main ""
+
+exec class args: compile
+ mvn exec:java -Dexec.args="{{args}}" -Dexec.mainClass={{class}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test: compile
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+package:
+ mvn package
diff --git a/src/pp.11.01-FindWords/pom.xml b/src/pp.11.01-FindWords/pom.xml
new file mode 100644
index 0000000..f72ca37
--- /dev/null
+++ b/src/pp.11.01-FindWords/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ pp
+ pp.11.01-FindWords
+ 1.0-SNAPSHOT
+ jar
+
+ pp.Main
+ 16
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ com.typesafe.akka
+ akka-actor_3
+ 2.8.5
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/ListenerActor.java b/src/pp.11.01-FindWords/src/main/java/pp/ListenerActor.java
new file mode 100644
index 0000000..b0f89b0
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/ListenerActor.java
@@ -0,0 +1,4 @@
+package pp;
+
+public class ListenerActor {
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/Main.java b/src/pp.11.01-FindWords/src/main/java/pp/Main.java
new file mode 100644
index 0000000..f25ba7b
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/Main.java
@@ -0,0 +1,20 @@
+package pp;
+
+import java.util.Arrays;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import pp.messages.FindMsg;
+
+public class Main {
+
+ public static void main(String... args) {
+ var system = ActorSystem.create();
+ var master = system.actorOf(Props.create(MasterActor.class));
+ String[] files = { "src/main/resources/test1.txt", "src/main/resources/test2.txt", "src/main/resources/test3.txt", "src/main/resources/test4.txt" };
+ var msg = new FindMsg(Arrays.asList(files), "Erlang");
+ master.tell(msg, ActorRef.noSender());
+ }
+
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/MasterActor.java b/src/pp.11.01-FindWords/src/main/java/pp/MasterActor.java
new file mode 100644
index 0000000..e3e5b31
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/MasterActor.java
@@ -0,0 +1,43 @@
+package pp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import akka.actor.AbstractActor;
+import akka.actor.ActorRef;
+import pp.messages.FindMsg;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+
+public class MasterActor extends AbstractActor {
+ private int numOfChild;
+ private final List result = new ArrayList<>();
+ private ActorRef listener;
+
+ public MasterActor() {
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(FindMsg.class, this::handleFindMsg) //
+ .match(ResultMsg.class, this::handleResultMsg) //
+ .build();
+ }
+
+ private void handleFindMsg(FindMsg msg) {
+ // TODO ausformulieren
+ }
+
+ private void handleResultMsg(ResultMsg msg) {
+ getSender().tell(new PleaseCleanupAndStop(), getSelf());
+ this.numOfChild--;
+ this.result.addAll(msg.result());
+ if (this.numOfChild == 0) {
+ this.listener.tell(new ResultMsg(this.result), getSelf());
+ getContext().stop(getSelf());
+ }
+ }
+
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/WorkerActor.java b/src/pp.11.01-FindWords/src/main/java/pp/WorkerActor.java
new file mode 100644
index 0000000..ff025cf
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/WorkerActor.java
@@ -0,0 +1,46 @@
+package pp;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import akka.actor.AbstractActor;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class WorkerActor extends AbstractActor {
+ private Path path;
+ private Pattern searchPattern;
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(WorkMsg.class, this::handleWorkMsg) //
+ .match(PleaseCleanupAndStop.class,
+ (m) -> getContext().stop(getSelf())) //
+ .build();
+ }
+
+ private void handleWorkMsg(WorkMsg msg) throws IOException {
+ this.path = Paths.get(msg.filename());
+ this.searchPattern = Pattern
+ .compile(".*\\b" + msg.searchword() + "\\b.*");
+ var result = new ArrayList();
+ var lines = Files.readAllLines(this.path, StandardCharsets.UTF_8);
+ var count = 0;
+ for (var line : lines) {
+ count++;
+ if (this.searchPattern.matcher(line).matches()) {
+ result.add(this.path + " " + count + " : " + line);
+ }
+ }
+ // TODO: Resultat (result) an den MasterActor (Absender der WorkMsg msg)
+ // zurücksenden
+ }
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/messages/FindMsg.java b/src/pp.11.01-FindWords/src/main/java/pp/messages/FindMsg.java
new file mode 100644
index 0000000..9ab411d
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/messages/FindMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record FindMsg(List filenames, String searchword) {
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/messages/PleaseCleanupAndStop.java b/src/pp.11.01-FindWords/src/main/java/pp/messages/PleaseCleanupAndStop.java
new file mode 100644
index 0000000..ab9668e
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/messages/PleaseCleanupAndStop.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record PleaseCleanupAndStop() {
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/messages/ResultMsg.java b/src/pp.11.01-FindWords/src/main/java/pp/messages/ResultMsg.java
new file mode 100644
index 0000000..12aa132
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/messages/ResultMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record ResultMsg(List result) {
+}
diff --git a/src/pp.11.01-FindWords/src/main/java/pp/messages/WorkMsg.java b/src/pp.11.01-FindWords/src/main/java/pp/messages/WorkMsg.java
new file mode 100644
index 0000000..7743f97
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/java/pp/messages/WorkMsg.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record WorkMsg(String filename, String searchword) {
+}
diff --git a/src/pp.11.01-FindWords/src/main/resources/test1.txt b/src/pp.11.01-FindWords/src/main/resources/test1.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test1.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test2.txt b/src/pp.11.01-FindWords/src/main/resources/test2.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test2.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test3.txt b/src/pp.11.01-FindWords/src/main/resources/test3.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test3.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test4.txt b/src/pp.11.01-FindWords/src/main/resources/test4.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test4.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test5.txt b/src/pp.11.01-FindWords/src/main/resources/test5.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test5.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test6.txt b/src/pp.11.01-FindWords/src/main/resources/test6.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test6.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test7.txt b/src/pp.11.01-FindWords/src/main/resources/test7.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test7.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords/src/main/resources/test8.txt b/src/pp.11.01-FindWords/src/main/resources/test8.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords/src/main/resources/test8.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/README.md b/src/pp.11.01-FindWords_solution/README.md
new file mode 100644
index 0000000..f8a4db0
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Paralleles Suchen/Finden eines Suchstrings in einigen wenigen Textdateien"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-01-FindWords.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-Solutions.html#laboraufgabe-paralleles-suchenfinden-eines-suchstrings-in-einigen-wenigen-textdateien)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/11-actors.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/11-actors.html)
diff --git a/src/pp.11.01-FindWords_solution/justfile b/src/pp.11.01-FindWords_solution/justfile
new file mode 100644
index 0000000..6c0be50
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/justfile
@@ -0,0 +1,17 @@
+# Justfile (https://just.systems/) for starting Maven standard targets
+
+default:
+ just exec pp.Main ""
+
+exec class args: compile
+ mvn exec:java -Dexec.args="{{args}}" -Dexec.mainClass={{class}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test: compile
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+package:
+ mvn package
diff --git a/src/pp.11.01-FindWords_solution/pom.xml b/src/pp.11.01-FindWords_solution/pom.xml
new file mode 100644
index 0000000..08b48cf
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ pp
+ pp.11.01-FindWords_solution
+ 1.0-SNAPSHOT
+ jar
+
+ pp.Main
+ 16
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ com.typesafe.akka
+ akka-actor_3
+ 2.8.5
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/ListenerActor.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/ListenerActor.java
new file mode 100644
index 0000000..13234b7
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/ListenerActor.java
@@ -0,0 +1,16 @@
+package pp;
+
+import akka.actor.AbstractActor;
+import pp.messages.ResultMsg;
+
+public class ListenerActor extends AbstractActor {
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(ResultMsg.class, (msg) -> {
+ msg.result().forEach(System.out::println);
+ getContext().getSystem().terminate();
+ }).build();
+ }
+
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/Main.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/Main.java
new file mode 100644
index 0000000..2275ad7
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/Main.java
@@ -0,0 +1,20 @@
+package pp;
+
+import java.util.Arrays;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import pp.messages.FindMsg;
+
+public class Main {
+
+ public static void main(String... args) {
+ var system = ActorSystem.create();
+ var master = system.actorOf(Props.create(MasterActor.class));
+ String[] files = { "src/main/resources/test1.txt", "src/main/resources/test2.txt", "src/main/resources/test3.txt", "src/main/resources/test4.txt" };
+ var msg = new FindMsg(Arrays.asList(files), "Erlang");
+ master.tell(msg, ActorRef.noSender());
+ }
+
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/MasterActor.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/MasterActor.java
new file mode 100644
index 0000000..011d940
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/MasterActor.java
@@ -0,0 +1,53 @@
+package pp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import akka.actor.AbstractActor;
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import pp.messages.FindMsg;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class MasterActor extends AbstractActor {
+ private int numOfChild;
+ private final List result = new ArrayList<>();
+ private final ActorRef listener;
+
+ public MasterActor() {
+ this.listener = getContext().actorOf(Props.create(ListenerActor.class));
+ }
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(FindMsg.class, this::handleFindMsg) //
+ .match(ResultMsg.class, this::handleResultMsg) //
+ .build();
+ }
+
+ private void handleFindMsg(FindMsg msg) {
+ var filenames = msg.filenames();
+ var searchword = msg.searchword();
+ this.numOfChild = msg.filenames().size();
+ for (var filename : filenames) {
+ var job = new WorkMsg(filename, searchword);
+ var findActor = getContext()
+ .actorOf(Props.create(WorkerActor.class));
+ findActor.tell(job, getSelf());
+ }
+
+ }
+
+ private void handleResultMsg(ResultMsg msg) {
+ getSender().tell(new PleaseCleanupAndStop(), getSelf());
+ this.numOfChild--;
+ this.result.addAll(msg.result());
+ if (this.numOfChild == 0) {
+ this.listener.tell(new ResultMsg(this.result), getSelf());
+ getContext().stop(getSelf());
+ }
+ }
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/WorkerActor.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/WorkerActor.java
new file mode 100644
index 0000000..c69edcd
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/WorkerActor.java
@@ -0,0 +1,44 @@
+package pp;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import akka.actor.AbstractActor;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class WorkerActor extends AbstractActor {
+ private Path path;
+ private Pattern searchPattern;
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(WorkMsg.class, this::handleWorkMsg) //
+ .match(PleaseCleanupAndStop.class,
+ (m) -> getContext().stop(getSelf())) //
+ .build();
+ }
+
+ private void handleWorkMsg(WorkMsg msg) throws IOException {
+ this.path = Paths.get(msg.filename());
+ this.searchPattern = Pattern
+ .compile(".*\\b" + msg.searchword() + "\\b.*");
+ var result = new ArrayList();
+ var lines = Files.readAllLines(this.path, StandardCharsets.UTF_8);
+ var count = 0;
+ for (var line : lines) {
+ count++;
+ if (this.searchPattern.matcher(line).matches()) {
+ result.add(this.path + " " + count + " : " + line);
+ }
+ }
+ getSender().tell(new ResultMsg(result), getSelf());
+ }
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/FindMsg.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/FindMsg.java
new file mode 100644
index 0000000..9ab411d
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/FindMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record FindMsg(List filenames, String searchword) {
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/PleaseCleanupAndStop.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/PleaseCleanupAndStop.java
new file mode 100644
index 0000000..ab9668e
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/PleaseCleanupAndStop.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record PleaseCleanupAndStop() {
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/ResultMsg.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/ResultMsg.java
new file mode 100644
index 0000000..12aa132
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/ResultMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record ResultMsg(List result) {
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/WorkMsg.java b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/WorkMsg.java
new file mode 100644
index 0000000..7743f97
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/java/pp/messages/WorkMsg.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record WorkMsg(String filename, String searchword) {
+}
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test1.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test1.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test1.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test2.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test2.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test2.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test3.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test3.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test3.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test4.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test4.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test4.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test5.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test5.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test5.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test6.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test6.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test6.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test7.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test7.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test7.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.01-FindWords_solution/src/main/resources/test8.txt b/src/pp.11.01-FindWords_solution/src/main/resources/test8.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.01-FindWords_solution/src/main/resources/test8.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/README.md b/src/pp.11.02-RouterFindWords/README.md
new file mode 100644
index 0000000..399f826
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Paralleles Suchen/Finden eines Suchstrings in sehr vielen Textdateien mit einem Router"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-02-RouterFindWords.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-Solutions.html#laboraufgabe-paralleles-suchenfinden-eines-suchstrings-in-sehr-vielen-textdateien-mit-einem-router)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/11-actors.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/11-actors.html)
diff --git a/src/pp.11.02-RouterFindWords/justfile b/src/pp.11.02-RouterFindWords/justfile
new file mode 100644
index 0000000..6c0be50
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/justfile
@@ -0,0 +1,17 @@
+# Justfile (https://just.systems/) for starting Maven standard targets
+
+default:
+ just exec pp.Main ""
+
+exec class args: compile
+ mvn exec:java -Dexec.args="{{args}}" -Dexec.mainClass={{class}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test: compile
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+package:
+ mvn package
diff --git a/src/pp.11.02-RouterFindWords/pom.xml b/src/pp.11.02-RouterFindWords/pom.xml
new file mode 100644
index 0000000..1043d38
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ pp
+ pp.11.02-RouterFindWords
+ 1.0-SNAPSHOT
+ jar
+
+ pp.Main
+ 16
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ com.typesafe.akka
+ akka-actor_3
+ 2.8.5
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/ListenerActor.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/ListenerActor.java
new file mode 100644
index 0000000..13234b7
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/ListenerActor.java
@@ -0,0 +1,16 @@
+package pp;
+
+import akka.actor.AbstractActor;
+import pp.messages.ResultMsg;
+
+public class ListenerActor extends AbstractActor {
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(ResultMsg.class, (msg) -> {
+ msg.result().forEach(System.out::println);
+ getContext().getSystem().terminate();
+ }).build();
+ }
+
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/Main.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/Main.java
new file mode 100644
index 0000000..9b3ad75
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/Main.java
@@ -0,0 +1,23 @@
+package pp;
+
+import java.util.Arrays;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import pp.messages.FindMsg;
+
+public class Main {
+
+ public static void main(String... args) {
+ var system = ActorSystem.create();
+ var master = system.actorOf(Props.create(MasterActor.class));
+ String[] files = { "src/main/resources/test1.txt", "src/main/resources/test2.txt", "src/main/resources/test3.txt",
+ "src/main/resources/test4.txt",
+ "src/main/resources/test5.txt", "src/main/resources/test6.txt", "src/main/resources/test7.txt",
+ "src/main/resources/test8.txt" };
+ var msg = new FindMsg(Arrays.asList(files), "Erlang");
+ master.tell(msg, ActorRef.noSender());
+ }
+
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/MasterActor.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/MasterActor.java
new file mode 100644
index 0000000..6e43b6f
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/MasterActor.java
@@ -0,0 +1,54 @@
+package pp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import akka.actor.AbstractActor;
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import pp.messages.FindMsg;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class MasterActor extends AbstractActor {
+ private int numOfChild;
+ private final List result = new ArrayList<>();
+ private final ActorRef listener;
+
+ public MasterActor() {
+ this.listener = getContext().actorOf(Props.create(ListenerActor.class));
+ }
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(FindMsg.class, this::handleFindMsg) //
+ .match(ResultMsg.class, this::handleResultMsg) //
+ .build();
+ }
+
+ private void handleFindMsg(FindMsg msg) {
+ var filenames = msg.filenames();
+ var searchword = msg.searchword();
+ this.numOfChild = msg.filenames().size();
+ for (var filename : filenames) {
+ var job = new WorkMsg(filename, searchword);
+ var findActor = getContext()
+ .actorOf(Props.create(WorkerActor.class));
+ findActor.tell(job, getSelf());
+ }
+
+ }
+
+ private void handleResultMsg(ResultMsg msg) {
+ getSender().tell(new PleaseCleanupAndStop(), getSelf());
+ this.numOfChild--;
+ this.result.addAll(msg.result());
+ if (this.numOfChild == 0) {
+ this.listener.tell(new ResultMsg(this.result), getSelf());
+ getContext().stop(getSelf());
+ }
+ }
+
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/WorkerActor.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/WorkerActor.java
new file mode 100644
index 0000000..c69edcd
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/WorkerActor.java
@@ -0,0 +1,44 @@
+package pp;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import akka.actor.AbstractActor;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class WorkerActor extends AbstractActor {
+ private Path path;
+ private Pattern searchPattern;
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(WorkMsg.class, this::handleWorkMsg) //
+ .match(PleaseCleanupAndStop.class,
+ (m) -> getContext().stop(getSelf())) //
+ .build();
+ }
+
+ private void handleWorkMsg(WorkMsg msg) throws IOException {
+ this.path = Paths.get(msg.filename());
+ this.searchPattern = Pattern
+ .compile(".*\\b" + msg.searchword() + "\\b.*");
+ var result = new ArrayList();
+ var lines = Files.readAllLines(this.path, StandardCharsets.UTF_8);
+ var count = 0;
+ for (var line : lines) {
+ count++;
+ if (this.searchPattern.matcher(line).matches()) {
+ result.add(this.path + " " + count + " : " + line);
+ }
+ }
+ getSender().tell(new ResultMsg(result), getSelf());
+ }
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/FindMsg.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/FindMsg.java
new file mode 100644
index 0000000..9ab411d
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/FindMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record FindMsg(List filenames, String searchword) {
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/PleaseCleanupAndStop.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/PleaseCleanupAndStop.java
new file mode 100644
index 0000000..ab9668e
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/PleaseCleanupAndStop.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record PleaseCleanupAndStop() {
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/ResultMsg.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/ResultMsg.java
new file mode 100644
index 0000000..12aa132
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/ResultMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record ResultMsg(List result) {
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/WorkMsg.java b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/WorkMsg.java
new file mode 100644
index 0000000..7743f97
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/java/pp/messages/WorkMsg.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record WorkMsg(String filename, String searchword) {
+}
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test1.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test1.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test1.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test2.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test2.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test2.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test3.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test3.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test3.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test4.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test4.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test4.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test5.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test5.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test5.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test6.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test6.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test6.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test7.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test7.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test7.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords/src/main/resources/test8.txt b/src/pp.11.02-RouterFindWords/src/main/resources/test8.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords/src/main/resources/test8.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/README.md b/src/pp.11.02-RouterFindWords_solution/README.md
new file mode 100644
index 0000000..399f826
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Paralleles Suchen/Finden eines Suchstrings in sehr vielen Textdateien mit einem Router"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-02-RouterFindWords.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/11-Solutions.html#laboraufgabe-paralleles-suchenfinden-eines-suchstrings-in-sehr-vielen-textdateien-mit-einem-router)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/11-actors.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/11-actors.html)
diff --git a/src/pp.11.02-RouterFindWords_solution/justfile b/src/pp.11.02-RouterFindWords_solution/justfile
new file mode 100644
index 0000000..6c0be50
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/justfile
@@ -0,0 +1,17 @@
+# Justfile (https://just.systems/) for starting Maven standard targets
+
+default:
+ just exec pp.Main ""
+
+exec class args: compile
+ mvn exec:java -Dexec.args="{{args}}" -Dexec.mainClass={{class}}
+clean:
+ mvn clean
+compile:
+ mvn compile
+test: compile
+ mvn test
+javadoc:
+ mvn javadoc:javadoc
+package:
+ mvn package
diff --git a/src/pp.11.02-RouterFindWords_solution/pom.xml b/src/pp.11.02-RouterFindWords_solution/pom.xml
new file mode 100644
index 0000000..c1c1129
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ pp
+ pp.11.02-RouterFindWords_solution
+ 1.0-SNAPSHOT
+ jar
+
+ pp.Main
+ 16
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ com.typesafe.akka
+ akka-actor_3
+ 2.8.5
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/ListenerActor.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/ListenerActor.java
new file mode 100644
index 0000000..13234b7
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/ListenerActor.java
@@ -0,0 +1,16 @@
+package pp;
+
+import akka.actor.AbstractActor;
+import pp.messages.ResultMsg;
+
+public class ListenerActor extends AbstractActor {
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(ResultMsg.class, (msg) -> {
+ msg.result().forEach(System.out::println);
+ getContext().getSystem().terminate();
+ }).build();
+ }
+
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/Main.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/Main.java
new file mode 100644
index 0000000..9b3ad75
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/Main.java
@@ -0,0 +1,23 @@
+package pp;
+
+import java.util.Arrays;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import pp.messages.FindMsg;
+
+public class Main {
+
+ public static void main(String... args) {
+ var system = ActorSystem.create();
+ var master = system.actorOf(Props.create(MasterActor.class));
+ String[] files = { "src/main/resources/test1.txt", "src/main/resources/test2.txt", "src/main/resources/test3.txt",
+ "src/main/resources/test4.txt",
+ "src/main/resources/test5.txt", "src/main/resources/test6.txt", "src/main/resources/test7.txt",
+ "src/main/resources/test8.txt" };
+ var msg = new FindMsg(Arrays.asList(files), "Erlang");
+ master.tell(msg, ActorRef.noSender());
+ }
+
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/MasterActor.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/MasterActor.java
new file mode 100644
index 0000000..ddd60b6
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/MasterActor.java
@@ -0,0 +1,70 @@
+package pp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import akka.actor.AbstractActor;
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.routing.ActorRefRoutee;
+import akka.routing.RoundRobinRoutingLogic;
+import akka.routing.Routee;
+import akka.routing.Router;
+import pp.messages.FindMsg;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class MasterActor extends AbstractActor {
+ private int numOfChild;
+ private final List result = new ArrayList<>();
+ private final ActorRef listener;
+
+ private final List routees;
+ private final Router router;
+
+ private static final int WORKER_NUM = 5;
+
+ public MasterActor() {
+ this.listener = getContext().actorOf(Props.create(ListenerActor.class));
+ this.routees = new ArrayList<>();
+ for (var i = 0; i < MasterActor.WORKER_NUM; i++) {
+ var r = getContext().actorOf(Props.create(WorkerActor.class));
+ getContext().watch(r);
+ this.routees.add(new ActorRefRoutee(r));
+ }
+ this.router = new Router(new RoundRobinRoutingLogic(), this.routees);
+ }
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(FindMsg.class, this::handleFindMsg) //
+ .match(ResultMsg.class, this::handleResultMsg) //
+ .build();
+ }
+
+ private void handleFindMsg(FindMsg msg) {
+ var filenames = msg.filenames();
+ var searchword = msg.searchword();
+ this.numOfChild = msg.filenames().size();
+ for (var filename : filenames) {
+ var job = new WorkMsg(filename, searchword);
+ this.router.route(job, getSelf());
+ }
+
+ }
+
+ private void handleResultMsg(ResultMsg msg) {
+ this.numOfChild--;
+ this.result.addAll(msg.result());
+ if (this.numOfChild == 0) {
+ for (var routee : this.routees) {
+ routee.send(new PleaseCleanupAndStop(), getSelf());
+ }
+ this.listener.tell(new ResultMsg(this.result), getSelf());
+ getContext().stop(getSelf());
+ }
+ }
+
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/WorkerActor.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/WorkerActor.java
new file mode 100644
index 0000000..c69edcd
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/WorkerActor.java
@@ -0,0 +1,44 @@
+package pp;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import akka.actor.AbstractActor;
+import pp.messages.PleaseCleanupAndStop;
+import pp.messages.ResultMsg;
+import pp.messages.WorkMsg;
+
+public class WorkerActor extends AbstractActor {
+ private Path path;
+ private Pattern searchPattern;
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder() //
+ .match(WorkMsg.class, this::handleWorkMsg) //
+ .match(PleaseCleanupAndStop.class,
+ (m) -> getContext().stop(getSelf())) //
+ .build();
+ }
+
+ private void handleWorkMsg(WorkMsg msg) throws IOException {
+ this.path = Paths.get(msg.filename());
+ this.searchPattern = Pattern
+ .compile(".*\\b" + msg.searchword() + "\\b.*");
+ var result = new ArrayList();
+ var lines = Files.readAllLines(this.path, StandardCharsets.UTF_8);
+ var count = 0;
+ for (var line : lines) {
+ count++;
+ if (this.searchPattern.matcher(line).matches()) {
+ result.add(this.path + " " + count + " : " + line);
+ }
+ }
+ getSender().tell(new ResultMsg(result), getSelf());
+ }
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/FindMsg.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/FindMsg.java
new file mode 100644
index 0000000..9ab411d
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/FindMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record FindMsg(List filenames, String searchword) {
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/PleaseCleanupAndStop.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/PleaseCleanupAndStop.java
new file mode 100644
index 0000000..ab9668e
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/PleaseCleanupAndStop.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record PleaseCleanupAndStop() {
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/ResultMsg.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/ResultMsg.java
new file mode 100644
index 0000000..12aa132
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/ResultMsg.java
@@ -0,0 +1,6 @@
+package pp.messages;
+
+import java.util.List;
+
+public record ResultMsg(List result) {
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/WorkMsg.java b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/WorkMsg.java
new file mode 100644
index 0000000..7743f97
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/java/pp/messages/WorkMsg.java
@@ -0,0 +1,4 @@
+package pp.messages;
+
+public record WorkMsg(String filename, String searchword) {
+}
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test1.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test1.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test1.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test2.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test2.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test2.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test3.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test3.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test3.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test4.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test4.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test4.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test5.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test5.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test5.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test6.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test6.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test6.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test7.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test7.txt
new file mode 100644
index 0000000..6c165c1
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test7.txt
@@ -0,0 +1,4 @@
+Akka Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.
diff --git a/src/pp.11.02-RouterFindWords_solution/src/main/resources/test8.txt b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test8.txt
new file mode 100644
index 0000000..2b51d14
--- /dev/null
+++ b/src/pp.11.02-RouterFindWords_solution/src/main/resources/test8.txt
@@ -0,0 +1,4 @@
+Erlang Idiom: Der Teil eines Programms der absolut korrekt sein muss, da er andere (potenziell unsicherere) Teile überwacht und ggf. neu startet.
+Man sollte bestrebt sein, den Error Kernel zu minimieren, damit wenigstens dort Fehlerfreiheit garantiert werden kann.
+Im Actor-Paradigma sollte jeder Prozess der einen Anwendungszweck hat (Worker) einen übergeordneten Supervisor-Prozess haben, der als dessen Error-Kernel fungiert.
+Es spricht nichts dagegen, auch komplexere Supervisor-Prozesse von einfacheren Error-Kernel-beinhaltenden Meta-Supervisor-Prozessen überwachen zu lassen.