- Système de de lecture/ecriture fichier fini.
- Système de tâche presque fini et synchronisation. Reste à alerter SBE d'une nouvelle tâche et permettre à un SBE d'attendre un tâche
This commit is contained in:
parent
38a403d6a1
commit
e3635b980b
@ -10,8 +10,7 @@ import lightcontainer.protocol.rules.reader.FilelistRule;
|
||||
import lightcontainer.protocol.rules.reader.HelloRule;
|
||||
import lightcontainer.protocol.rules.reader.SavefileRule;
|
||||
import lightcontainer.protocol.rules.reader.SigninRule;
|
||||
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
||||
import lightcontainer.protocol.rules.writer.SignOkRule;
|
||||
import lightcontainer.protocol.rules.writer.*;
|
||||
import lightcontainer.repository.ClientHandlerRepository;
|
||||
import lightcontainer.repository.FileFrontEnd;
|
||||
import lightcontainer.repository.ProtocolRepositoryImpl;
|
||||
@ -62,12 +61,15 @@ public class App {
|
||||
ProtocolRepository protocolRep = new ProtocolRepositoryImpl();
|
||||
|
||||
protocolRep.addReader(new HelloRule());
|
||||
protocolRep.addReader(new SigninRule());
|
||||
protocolRep.addReader(new FilelistRule());
|
||||
protocolRep.addReader(new SavefileRule());
|
||||
protocolRep.addReader(new SigninRule(protocolRep));
|
||||
protocolRep.addReader(new FilelistRule(protocolRep));
|
||||
protocolRep.addReader(new SavefileRule(protocolRep));
|
||||
|
||||
protocolRep.addWriter(new SignOkRule());
|
||||
protocolRep.addWriter(new SignErrorRule());
|
||||
protocolRep.addWriter(new FilesRule());
|
||||
protocolRep.addWriter(new SaveFileOkRule());
|
||||
protocolRep.addWriter(new SaveFileErrorRule());
|
||||
|
||||
new UnicastServerListener(clientRep, protocolRep, UNICAST_PORT);
|
||||
new MulticastServerListener(storeRep, protocolRep, MULTICAST_IP, MULTICAST_PORT);
|
||||
|
@ -5,7 +5,6 @@ import lightcontainer.enumerations.TaskType;
|
||||
|
||||
public class Task {
|
||||
// Variables
|
||||
private TaskType type; // TODO : Supprimer car innutile ?
|
||||
private TaskStatus status;
|
||||
private String command;
|
||||
private String client;
|
||||
@ -21,4 +20,21 @@ public class Task {
|
||||
Task task = new Task(TaskStatus.PENDING, command, client);
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de savoir si la réponse est destinée au client
|
||||
* @param storeDomain Nom du store back end fournissant la réponse.
|
||||
* @return TRUE si le client doit recevoir cette réponse.
|
||||
*/
|
||||
public boolean isResponseOfClient(String storeDomain) {
|
||||
return (this.storeDomain == storeDomain && status == TaskStatus.PENDING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de récupérer le login du client associé à la tâche
|
||||
* @return Login du client
|
||||
*/
|
||||
public String getClient() {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
||||
|
||||
private BufferedReader reader;
|
||||
private PrintWriter writer;
|
||||
private ProtocolWriter.ProtocolResult response;
|
||||
|
||||
// Constructor
|
||||
public ClientHandler(Socket client, ClientHandlerFFE ffe, ProtocolRepository protocolRep) {
|
||||
@ -86,20 +87,27 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
||||
while (this.client_run) {
|
||||
try {
|
||||
String command = this.reader.readLine();
|
||||
// TODO gestion de la réception de commandes, fichier, ...
|
||||
if (command != null) System.out.println("Client: " + command);
|
||||
|
||||
ProtocolReader.ProtocolResult ruleResult = protocolRep.executeReader(command + "\r\n");
|
||||
|
||||
if (isConnected()) {
|
||||
ProtocolWriter.ProtocolResult writerCommand = ruleResult.getResultCommand();
|
||||
ruleResult.read(
|
||||
this.client.getInputStream()
|
||||
);
|
||||
|
||||
if (ruleResult.getReceiver() == ProtocolReader.ResultCmdReceiver.STOREBACKEND) {
|
||||
fileFrontEnd.newCommand(command, ruleResult.getResultCommand()); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
|
||||
fileFrontEnd.newCommand(command, writerCommand.getCommand()); // Envoie dans la file de tâche FileFrontEnd en attente d'un traitement d'un StorBackEnd
|
||||
|
||||
// Attend la fin de la réalisation de la tâche
|
||||
waitTaskResponse();
|
||||
|
||||
writer.write(response.getCommand()); // Renvoye au client
|
||||
writer.flush();
|
||||
response.write(this.client.getOutputStream()); // Ecrit au client si nécessaire
|
||||
} else {
|
||||
writer.write(ruleResult.getResultCommand()); // Renvoye au client
|
||||
writer.write(writerCommand.getCommand()); // Renvoye au client
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
@ -107,6 +115,25 @@ public class ClientHandler implements Runnable, AutoCloseable {
|
||||
authentication(ruleResult);
|
||||
}
|
||||
} catch (IOException ignore) { }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet au Client d'attendre la fin de la réalisation de sa tâche
|
||||
*/
|
||||
private void waitTaskResponse() {
|
||||
synchronized (this) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) { e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
|
||||
public void respond(ProtocolWriter.ProtocolResult response) {
|
||||
this.response = response;
|
||||
synchronized (this) {
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
||||
this.client_run = true;
|
||||
while (this.client_run) {
|
||||
try {
|
||||
alertAvalaible();
|
||||
waitAction();
|
||||
|
||||
// Request
|
||||
ProtocolWriter.ProtocolResult requestResult = protocolRep.executeWriter(this.currentCommand);
|
||||
@ -92,8 +92,11 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
||||
if (responseCommand != null)
|
||||
System.out.println("StoreBackEnd: " + responseCommand);
|
||||
ProtocolReader.ProtocolResult responseResult = protocolRep.executeReader(responseCommand);
|
||||
responseResult.read(this.store.getInputStream());
|
||||
System.out.println("StoreBackEnd response to client: " + responseResult.getResultCommand());
|
||||
|
||||
alertAvalaible(responseResult.getResultCommand());
|
||||
// TODO : Faire en sorte que getResultCommand retourne un ProtocolWriter
|
||||
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
@ -113,12 +116,20 @@ public class StoreProcessor extends Thread implements AutoCloseable {
|
||||
/**
|
||||
* Permet de déclarer le StoreBackEnd disponible
|
||||
*/
|
||||
private void alertAvalaible() {
|
||||
private void alertAvalaible(ProtocolWriter.ProtocolResult responseCommand) {
|
||||
synchronized (this) {
|
||||
waitAction();
|
||||
this.currentCommand = null;
|
||||
|
||||
fileFrontEnd.onStoreAvailable(this);
|
||||
fileFrontEnd.onStoreAvailable(this, responseCommand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet au Store d'attendre une action à réaliser
|
||||
*/
|
||||
private void waitAction() {
|
||||
synchronized (this) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) { e.printStackTrace(); }
|
||||
|
@ -6,8 +6,22 @@ import lightcontainer.domains.Task;
|
||||
* Enumeration defining the status of a {@link Task}.
|
||||
*/
|
||||
public enum TaskStatus {
|
||||
|
||||
/**
|
||||
* En attente d'être traitée
|
||||
*/
|
||||
PENDING,
|
||||
|
||||
/**
|
||||
* En train d'être traitée
|
||||
*/
|
||||
PROCESSING,
|
||||
|
||||
/**
|
||||
* Une erreur est survenue
|
||||
*/
|
||||
ERROR,
|
||||
|
||||
|
||||
SUCCESS
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package lightcontainer.interfaces;
|
||||
|
||||
import lightcontainer.domains.client.StoreProcessor;
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
import lightcontainer.repository.FileFrontEnd;
|
||||
|
||||
/**
|
||||
@ -10,6 +11,7 @@ public interface StoreProcessorFFE {
|
||||
/**
|
||||
* Allows a {@link StoreProcessor} to notify the FFE that it's available.
|
||||
* @param store The store processor that is now available.
|
||||
* @param responseCommand
|
||||
*/
|
||||
void onStoreAvailable(StoreProcessor store);
|
||||
void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package lightcontainer.interfaces;
|
||||
import lightcontainer.domains.client.ClientHandler;
|
||||
import lightcontainer.domains.server.MulticastServerListener;
|
||||
import lightcontainer.domains.server.UnicastServerListener;
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
import lightcontainer.repository.ClientHandlerRepository;
|
||||
|
||||
/**
|
||||
@ -20,4 +21,6 @@ public interface UnicastCHR {
|
||||
* @param client Client Handler to add.
|
||||
*/
|
||||
void addClient(ClientHandler client);
|
||||
|
||||
void respondToClient(String client, ProtocolWriter.ProtocolResult response);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public abstract class ProtocolReader {
|
||||
/**
|
||||
* Command qui sera renvoyée par exemple au client
|
||||
*/
|
||||
private String resultCommand;
|
||||
private ProtocolWriter.ProtocolResult resultCommand;
|
||||
|
||||
/**
|
||||
* Désigne vers ou cette commande est envoyée.
|
||||
@ -44,7 +44,7 @@ public abstract class ProtocolReader {
|
||||
* Récupérer la commande à envoyer
|
||||
* @return Commande
|
||||
*/
|
||||
public String getResultCommand() {
|
||||
public ProtocolWriter.ProtocolResult getResultCommand() {
|
||||
return resultCommand;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public abstract class ProtocolReader {
|
||||
* @param resultCommand Commande à envoyer
|
||||
* @param receiver Le receveur de cette commande
|
||||
*/
|
||||
public void setResultCommand(String resultCommand, ResultCmdReceiver receiver) {
|
||||
public void setResultCommand(ProtocolWriter.ProtocolResult resultCommand, ResultCmdReceiver receiver) {
|
||||
this.resultCommand = resultCommand;
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public abstract class ProtocolWriter {
|
||||
Matcher ruleMatcher = this.rulePattern.matcher(command); // Vérifie que tout match (cf. Matcher). Si match alors on retourne la commande build, sinon on retourne NULL
|
||||
|
||||
if (ruleMatcher.matches()) {
|
||||
ProtocolResult result = onExecuted();
|
||||
ProtocolResult result = onExecuted(data);
|
||||
result.setCommand(command);
|
||||
return (T) result;
|
||||
}
|
||||
@ -70,6 +70,8 @@ public abstract class ProtocolWriter {
|
||||
/**
|
||||
* Cette méthode est appelée lors de l'exécution de la règle
|
||||
*/
|
||||
protected abstract <T extends ProtocolResult> T onExecuted();
|
||||
protected <T extends ProtocolResult> T onExecuted(String... data) {
|
||||
return (T) new ProtocolResult();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,21 @@
|
||||
package lightcontainer.protocol.rules.reader;
|
||||
|
||||
import lightcontainer.interfaces.ProtocolRepository;
|
||||
import lightcontainer.protocol.ProtocolReader;
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
import lightcontainer.protocol.rules.writer.FilesRule;
|
||||
import lightcontainer.protocol.rules.writer.SignOkRule;
|
||||
|
||||
public class FilelistRule extends ProtocolReader {
|
||||
// Constants
|
||||
private static final String PATTERN = "^FILELIST\r\n$";
|
||||
|
||||
private ProtocolRepository protocolRep;
|
||||
|
||||
// Constructor
|
||||
public FilelistRule() {
|
||||
public FilelistRule(ProtocolRepository protocolRep) {
|
||||
super(PATTERN);
|
||||
this.protocolRep = protocolRep;
|
||||
}
|
||||
|
||||
public class Result extends ProtocolResult { }
|
||||
@ -20,7 +27,7 @@ public class FilelistRule extends ProtocolReader {
|
||||
@Override
|
||||
protected FilelistRule.Result onExecuted(String... data) {
|
||||
FilelistRule.Result result = new Result();
|
||||
result.setResultCommand("FILES endbenja.txt!500\r\n", ResultCmdReceiver.CLIENT);
|
||||
result.setResultCommand(this.protocolRep.executeWriter(FilesRule.NAME, "endbenja.txt!500"), ResultCmdReceiver.CLIENT);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package lightcontainer.protocol.rules.reader;
|
||||
|
||||
import lightcontainer.interfaces.ProtocolRepository;
|
||||
import lightcontainer.protocol.ProtocolReader;
|
||||
import lightcontainer.protocol.rules.writer.SaveFileErrorRule;
|
||||
import lightcontainer.protocol.rules.writer.SaveFileOkRule;
|
||||
import lightcontainer.utils.FileReceiver;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -12,9 +15,12 @@ public class SavefileRule extends ProtocolReader {
|
||||
private static final int FILE_NAME = 0; // Index file name.
|
||||
private static final int FILE_SIZE = 1; // Index file size.
|
||||
|
||||
private ProtocolRepository protocolRep;
|
||||
|
||||
// Constructor
|
||||
public SavefileRule() {
|
||||
public SavefileRule(ProtocolRepository protocolRep) {
|
||||
super(PATTERN);
|
||||
this.protocolRep = protocolRep;
|
||||
}
|
||||
|
||||
public class Result extends ProtocolResult {
|
||||
@ -38,9 +44,9 @@ public class SavefileRule extends ProtocolReader {
|
||||
if (!fileReceiver.receiveFile(reader, this.filename, this.size))
|
||||
throw new IOException();
|
||||
|
||||
this.setResultCommand("SAVEFILE_OK\r\n", ResultCmdReceiver.CLIENT);
|
||||
this.setResultCommand(protocolRep.executeWriter(SaveFileOkRule.NAME), ResultCmdReceiver.CLIENT);
|
||||
} catch (IOException e) {
|
||||
this.setResultCommand("SAVEFILE_ERROR\r\n", ResultCmdReceiver.CLIENT);
|
||||
this.setResultCommand(protocolRep.executeWriter(SaveFileErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package lightcontainer.protocol.rules.reader;
|
||||
|
||||
import lightcontainer.interfaces.ProtocolRepository;
|
||||
import lightcontainer.protocol.ProtocolReader;
|
||||
import lightcontainer.protocol.rules.writer.SignErrorRule;
|
||||
import lightcontainer.protocol.rules.writer.SignOkRule;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -10,9 +13,12 @@ public class SigninRule extends ProtocolReader {
|
||||
private static final int LOGIN = 0; // Index du domain dans le tableau de données
|
||||
private static final int PASSWORD = 1; // Index du port dans le tableau de données
|
||||
|
||||
private ProtocolRepository protocolRep;
|
||||
|
||||
// Constructor
|
||||
public SigninRule() {
|
||||
public SigninRule(ProtocolRepository protocolRep) {
|
||||
super(PATTERN);
|
||||
this.protocolRep = protocolRep;
|
||||
}
|
||||
|
||||
public class Result extends ProtocolResult {
|
||||
@ -50,9 +56,9 @@ public class SigninRule extends ProtocolReader {
|
||||
|
||||
// TODO : Création d'une règle d'écriture SIGN_OK et SIGN_ERROR proprement
|
||||
if (result.checkCredentials()) {
|
||||
result.setResultCommand("SIGN_OK\r\n", ResultCmdReceiver.CLIENT);
|
||||
result.setResultCommand(this.protocolRep.executeWriter(SignOkRule.NAME), ResultCmdReceiver.CLIENT);
|
||||
} else {
|
||||
result.setResultCommand("SIGN_ERROR\r\n", ResultCmdReceiver.CLIENT);
|
||||
result.setResultCommand(this.protocolRep.executeWriter(SignErrorRule.NAME), ResultCmdReceiver.CLIENT);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package lightcontainer.protocol.rules.writer;
|
||||
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
|
||||
public class FilesRule extends ProtocolWriter {
|
||||
|
||||
private static final String PATTERN = "^FILES(( [^ !]{1,20})!([0-9]{1,10})){0,50}\r\n$";
|
||||
|
||||
public static final String NAME = "FILES";
|
||||
|
||||
public FilesRule() {
|
||||
super(NAME, PATTERN);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package lightcontainer.protocol.rules.writer;
|
||||
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
|
||||
public class SaveFileErrorRule extends ProtocolWriter {
|
||||
|
||||
private static final String PATTERN = "^SAVEFILE_ERROR\r\n$";
|
||||
|
||||
public static final String NAME = "SAVEFILE_ERROR";
|
||||
|
||||
public SaveFileErrorRule() {
|
||||
super(NAME, PATTERN);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package lightcontainer.protocol.rules.writer;
|
||||
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
|
||||
public class SaveFileOkRule extends ProtocolWriter {
|
||||
|
||||
private static final String PATTERN = "^SAVEFILE_OK\r\n$";
|
||||
|
||||
public static final String NAME = "SAVEFILE_OK";
|
||||
|
||||
public SaveFileOkRule() {
|
||||
super(NAME, PATTERN);
|
||||
}
|
||||
|
||||
}
|
@ -11,4 +11,5 @@ public class SignErrorRule extends ProtocolWriter {
|
||||
public SignErrorRule() {
|
||||
super(NAME, PATTERN);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package lightcontainer.repository;
|
||||
import lightcontainer.domains.client.ClientHandler;
|
||||
import lightcontainer.domains.server.UnicastServerListener;
|
||||
import lightcontainer.interfaces.UnicastCHR;
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -54,6 +55,13 @@ public class ClientHandlerRepository implements AutoCloseable, UnicastCHR {
|
||||
this.handlers.add(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void respondToClient(String login, ProtocolWriter.ProtocolResult response) {
|
||||
for (ClientHandler client : handlers) {
|
||||
client.respond(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoClosable Function
|
||||
* Closes all ClientHandlers stored in this repository and deallocates all resources.
|
||||
|
@ -5,8 +5,10 @@ import lightcontainer.domains.Task;
|
||||
import lightcontainer.interfaces.ClientHandlerFFE;
|
||||
import lightcontainer.interfaces.ProtocolRepository;
|
||||
import lightcontainer.interfaces.StoreProcessorFFE;
|
||||
import lightcontainer.protocol.ProtocolWriter;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
|
||||
@ -28,16 +30,27 @@ public class FileFrontEnd implements ClientHandlerFFE, StoreProcessorFFE {
|
||||
*/
|
||||
public void alertStoreProcessors(Task task) {
|
||||
// On avertit les stor processors d'une nouvelle tâche
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet à un {@link StoreProcessor} d'avertir le FFE qu'il est disponible
|
||||
*
|
||||
* @param store
|
||||
* @param store Le SBE qui s'est occupé de la tâche
|
||||
* @param response La réponse à envoyer au client
|
||||
*/
|
||||
@Override
|
||||
public void onStoreAvailable(StoreProcessor store) {
|
||||
public void onStoreAvailable(StoreProcessor store, ProtocolWriter.ProtocolResult response) {
|
||||
// TODO : Chercher une tâche appropriée
|
||||
Iterator<Task> it = tasks.iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
Task task = it.next();
|
||||
if (task.isResponseOfClient(store.getName())) {
|
||||
clientRepository.respondToClient(task.getClient(), response);
|
||||
it.remove(); // Suppression de la tâche
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user