Kap. 4: Actors/Akka

main
Sandro Leuchter 2024-12-10 23:25:04 +01:00
parent 3e16aa8f36
commit 480a9f985c
76 changed files with 1144 additions and 0 deletions

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,76 @@
<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>pp</groupId>
<artifactId>pp.11.01-FindWords</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<exec.mainClass>pp.Main</exec.mainClass>
<maven.compiler.release>16</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_3</artifactId>
<version>2.8.5</version>
</dependency>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile exec:java</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,4 @@
package pp;
public class ListenerActor {
}

View File

@ -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());
}
}

View File

@ -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<String> 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());
}
}
}

View File

@ -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<String>();
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
}
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record FindMsg(List<String> filenames, String searchword) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record PleaseCleanupAndStop() {
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record ResultMsg(List<String> result) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record WorkMsg(String filename, String searchword) {
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,76 @@
<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>pp</groupId>
<artifactId>pp.11.01-FindWords_solution</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<exec.mainClass>pp.Main</exec.mainClass>
<maven.compiler.release>16</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_3</artifactId>
<version>2.8.5</version>
</dependency>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile exec:java</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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<String> 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());
}
}
}

View File

@ -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<String>();
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());
}
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record FindMsg(List<String> filenames, String searchword) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record PleaseCleanupAndStop() {
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record ResultMsg(List<String> result) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record WorkMsg(String filename, String searchword) {
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,76 @@
<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>pp</groupId>
<artifactId>pp.11.02-RouterFindWords</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<exec.mainClass>pp.Main</exec.mainClass>
<maven.compiler.release>16</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_3</artifactId>
<version>2.8.5</version>
</dependency>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile exec:java</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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<String> 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());
}
}
}

View File

@ -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<String>();
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());
}
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record FindMsg(List<String> filenames, String searchword) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record PleaseCleanupAndStop() {
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record ResultMsg(List<String> result) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record WorkMsg(String filename, String searchword) {
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,76 @@
<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>pp</groupId>
<artifactId>pp.11.02-RouterFindWords_solution</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<exec.mainClass>pp.Main</exec.mainClass>
<maven.compiler.release>16</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_3</artifactId>
<version>2.8.5</version>
</dependency>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile exec:java</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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<String> result = new ArrayList<>();
private final ActorRef listener;
private final List<Routee> 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());
}
}
}

View File

@ -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<String>();
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());
}
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record FindMsg(List<String> filenames, String searchword) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record PleaseCleanupAndStop() {
}

View File

@ -0,0 +1,6 @@
package pp.messages;
import java.util.List;
public record ResultMsg(List<String> result) {
}

View File

@ -0,0 +1,4 @@
package pp.messages;
public record WorkMsg(String filename, String searchword) {
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.