forked from Parallele_Programmierung/Labs
Kap. 4: Actors/Akka
parent
3e16aa8f36
commit
480a9f985c
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp;
|
||||||
|
|
||||||
|
public class ListenerActor {
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record FindMsg(List<String> filenames, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record PleaseCleanupAndStop() {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ResultMsg(List<String> result) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record WorkMsg(String filename, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record FindMsg(List<String> filenames, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record PleaseCleanupAndStop() {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ResultMsg(List<String> result) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record WorkMsg(String filename, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record FindMsg(List<String> filenames, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record PleaseCleanupAndStop() {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ResultMsg(List<String> result) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record WorkMsg(String filename, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record FindMsg(List<String> filenames, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record PleaseCleanupAndStop() {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ResultMsg(List<String> result) {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package pp.messages;
|
||||||
|
|
||||||
|
public record WorkMsg(String filename, String searchword) {
|
||||||
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
Loading…
Reference in New Issue