package platform.supervisor;
/**
*
* @author Dalmau
*/
import platform.ClassManager.ClassLoaderFromJarFile;
import platform.containersregister.ContainersManager;
import platform.containersregister.ConnectorsRegistration;
import platform.containersregister.OsagaiaContainerDescriptor;
import platform.containersregister.ConnectedInput;
import platform.containersregister.KorronteaContainerDescriptor;
import platform.containersregister.ComponentsRegistration;
import model.interfaces.IContainer;
import model.osagaia.BCContainer;
import model.osagaia.BCModel;
import model.korrontea.ConnectorContainer;
import platform.servicesregister.ServicesRegisterManager;
import platform.servicesregister.ServiceClosedException;
import platform.servicesregister.ServiceInUseException;
import platform.context.ContextManager;
import platform.context.ContextInformation;
import platform.context.status.HostStatus;
import network.NetworkEmissionService;
import network.NetworkReceptionService;
import network.NetworkEmitterContainer;
import network.NetworkReceptorContainer;
import network.platform.PlatformMessagesEmitter;
import network.platform.PlatformMessagesReceptor;
import network.platform.NetworkPlatformMessage;
import network.AddressesChecker;
import util.NetworkAddress;
import platform.InternalPlatformMessage;
import platform.plugins.installables.network.routing.ReplyForRouteMessage;
import platform.plugins.installables.network.routing.NoRouteException;
import platform.plugins.installables.network.DNS.KalimuchoDNS;
import platform.plugins.installables.application.BCCommandSenderPlugin;
import util.Commands;
import util.Parameters;
/**
* The supervisor is a thread which listens for messages coming from others platforms and executes these command.
* The supervisor execute command for:<br>
* creating/removing a component or a connector<br>
* migrate a component<br>
* connect/disconnect inputs/outputs of components or connectors<br>
* reply to request about host/component/connectors state.
*
* @author Dalmau
*/
public class Supervisor extends Thread {
private AddressesChecker addressesChecker;
// liens du superviseur avec les autres services de la PF
private NetworkEmissionService serviceEmissionReseau;
private NetworkReceptionService serviceReceptionReseau;
private PlatformMessagesEmitter emetteurDeMessages;
private PlatformMessagesReceptor receptionMessages;
private ContextManager gestionnaireContexte;
// Enregistrement des composants et des connecteurs
private ContainersManager gestionnaireDeConteneurs;
private ComponentsRegistration composants; // Liste des composants crees
private ConnectorsRegistration connecteurs; // Liste des connecteurs crees
// Indicateur d'activite du superviseur
private boolean enMarche;
/**
* Construction of the supervisor<br>
* Find the services, run the host load watcher
*/
public Supervisor() {
// Creation des listes de composants et de connecteurs
gestionnaireDeConteneurs = (ContainersManager) ServicesRegisterManager.platformWaitForService(Parameters.CONTAINERS_MANAGER);
connecteurs = gestionnaireDeConteneurs.getConnecteurs(); // liste des connecteurs
composants = gestionnaireDeConteneurs.getComposants(); // liste des conteneurs de CM
// Recherches des services
// Service d'acces aux adresses de cette plateforme
addressesChecker = (AddressesChecker) ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_ADDRESSES);
// Services d'acces aux reseaux
NetworkEmitterContainer nec = (NetworkEmitterContainer) ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_EMISSIONS_CONTAINER);
serviceEmissionReseau = nec.getNetworkEmissionService();
emetteurDeMessages = nec.getPlatformMessagesEmitter();
NetworkReceptorContainer nrc = (NetworkReceptorContainer) ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_RECEPTIONS_CONTAINER);
serviceReceptionReseau = nrc.getNetworkReceptionService();
receptionMessages = nrc.getPlatformMessagesReceptor();
receptionMessages.inscription(Parameters.SUPERVISOR);
// Service de gestion du contexte
gestionnaireContexte = (ContextManager) ServicesRegisterManager.platformWaitForService(Parameters.CONTEXT_MANAGER);
// Enregistrer le service superviseur
try {
ServicesRegisterManager.registerService(Parameters.SUPERVISOR, this);
} catch (ServiceInUseException mbiue) {
System.err.println("Supervisor service created twice");
}
}
// arret du superviseur lorsque l'on arrete la PF
/**
* Stops the supervisor.<br>
* A signal is sent indicationg tha this platform is stopped.
* All the connectors are destroyed.
*/
public void stopThread() {
// lever une alarme d'arret
gestionnaireContexte.signalEvent(new ContextInformation("Kalimucho platform stopped by user"));
// arreter le run du superviseur (n'accepte plus de commandes)
enMarche = false;
receptionMessages.desinscription(Parameters.SUPERVISOR);
// supprimer tous les connecteurs
while (connecteurs.getConnectorsNumber() != 0) {
supprimerconnecteur(connecteurs.getConnectorAt(0).getNom());
}
}
// Boucle de traitement des messages reeus par la PF
/**
* Wait for command and execute them
*/
@Override
public void run() {
try {
System.out.println("Supervisor ready: (IP address = " + addressesChecker.getMyFirstAddress(NetworkAddress.TYPE_IPV4).getNormalizedAddress() + ")");
} catch (Exception ignore) {
//Don't crash if no address
System.out.println("Supervisor ready : localhost only");
}
enMarche = true;
while (enMarche) { // La PF peut etre arretee par stopThread
// traitement des commandes reeues par reseau
String cmd = null;
// Attendre une commande sur la reseau
NetworkPlatformMessage lu = receptionMessages.retirerMessage(Parameters.SUPERVISOR);
if (lu != null) {
cmd = lu.getContent(); // recuperer la chaene de cars contenant la commande reeue
if (cmd != null) { // si on a reeu une commande la traiter
traiterCommande(lu);
}
}
}
}
// Methodes internes de fonctionnement de la PF
// creation/suppression de conteneur
// Deconnexion de l'entree ou la sortie d'un composant
// Reconnexion de l'entree ou la sortie d'un composant (e un nouveau connecteur)
// Lancement et arret un CM
// Renvoi de la QdS d'un CM d'un conteneur
// Renvoi de l'etat de l'hete
// ************************
// Creation d'un composant
// ************************
public void creerComposant(String nom, String classeCM, CommandAnalyser cmde) {
// reeoit le nom symbolique du composant osagaia
// le nom de la classe du CM qu'il contient
// les connexions en entree : liste de noms de connecteurs
// les connexions en sortie : liste de noms de connecteurs
// creer un conteneur de CM
BCContainer osagaia = new BCContainer(nom, classeCM, cmde.getSplittedEntryList(), cmde.getSplittedOutputList());
// Enregistrer ce conteneur de CM dans la liste
composants.ajouterConteneur(new OsagaiaContainerDescriptor(osagaia, osagaia.getClassLoader(), nom, cmde.getSplittedEntryList(), cmde.getSplittedOutputList()));
}
// *************************
// Creation d'un connecteur
// *************************
private void creerconnecteur(String name, String input, String output) {
// reeoit le nom symbolique du connecteur korrontea
// la connexion en entree = interne ou @ de l'emetteur
// la connexion en sortie = interne ou @ oe envoyer
// Pour les connecteurs en 2 parties demander e la PF qui accueille l'autre extremite du connecteur de la creer
new ThreadCreationConnecteur(name, input, output);
}
// ******************************
// Creation d'un cnnecteur relai
// ******************************
private void creerconnecteurRelais(String nom, String entree, String sortie, String sender) {
// reeoit le nom symbolique du connecteur korrontea
// la connexion en entree = @ de l'emetteur
// la connexion en sortie = @ oe envoyer
if ((entree.equals(Commands.ES_INTERNE)) || (sortie.equals(Commands.ES_INTERNE))) {
System.err.println("Cant create relai connector from: " + entree + " to: " + sortie);
} else { // il s'agit bien d'un connecteur dont l'entree et la sortie sont externes (relais)
// On ne verifie pas que l'entree et la sortie soient accessibles car cette commande est toujours envoyee
// par une PF qui cree un connecteur et qui a deja verifie que ce soit faisable
// Demander aux PFs qui accueillent les autres extremites du connecteur de les creer
// Sauf a celle qui a envoye la commande
NetworkAddress ent = new NetworkAddress(entree);
NetworkAddress sort = new NetworkAddress(sortie);
NetworkAddress send = null;
if (sender != null) send = new NetworkAddress(sender);
if (!ent.equals(send)) { // l'entree ne correspond pas a celui qui a envoye la commande
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.CREATE_PART_OF_CONNECTOR + " " + nom + " " + Commands.ES_INTERNE + " " + addressesChecker.getMyFirstAddress(ent.getType()).getNormalizedAddress());
emetteurDeMessages.postMessage(envoi);
}
if (!sort.equals(send)) { // la sortie ne correspond pas a celui qui a envoye la commande
// envoyer la commande de creation e l'autre PF pour la sortie
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.CREATE_PART_OF_CONNECTOR + " " + nom + " " + addressesChecker.getMyFirstAddress(sort.getType()).getNormalizedAddress() + " " + Commands.ES_INTERNE);
emetteurDeMessages.postMessage(envoi);
}
creerExtremiteconnecteur(nom, entree, sortie); // creation de la partie locale du connecteur
}
}
// *****************************************************
// Creation de la partie locale d'un connecteur reparti
// *****************************************************
private void creerExtremiteconnecteur(String nom, String entree, String sortie) {
// reeoit le nom symbolique du connecteur korrontea
// la connexion en entree = interne ou @ de l'emetteur
// la connexion en sortie = interne ou @ oe envoyer
// creer un conteneur de flux
ConnectorContainer korrontea = new ConnectorContainer(nom);
// Enregistrer ce conteneur de flux dans la liste
connecteurs.ajouterConteneur(new KorronteaContainerDescriptor(korrontea, nom, entree, sortie));
// Creer, si necessaire le thread emetteur ou recepteur
if (!entree.equals(Commands.ES_INTERNE)) { // entree par reseau => creer un thread recepteur
// Creation du thread de reception par reseau
serviceReceptionReseau.createConnectorReceptionThread(nom, new NetworkAddress(entree)); // lancer un processus pour cette entree reseau
}
if (!sortie.equals(Commands.ES_INTERNE)) { // sortie par reseau => creer un thread emetteur
// Creation du thread d'emission sur le reseau
serviceEmissionReseau.createConnectorEmissionThread(nom, new NetworkAddress(sortie)); // lancer un processus pour cette sortie reseau
}
try {
model.korrontea.ControlUnit uc = (model.korrontea.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.startUEandUS(); // lancement de l'UE (attente de connexion du composant osagaia)
uc.start_BC(); // lancement du CM de transfert de flux
} catch (ServiceClosedException sce) {
System.err.println("Can't create connector : " + nom);
}
}
// ****************************************
// Deconnexion d'une entree d'un composant
// ****************************************
private void deconnecterEntreeComposant(String nom, int numero) {
// deconnexion de l'entree d'un conteneur de CM
// le CM n'est pas arrete il attent une reconnexion e un autre connecteur
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.disconnectIU(numero); // deconnecter l'UE du conteneur de CM
composants.changerEntreeConteneur(nom, numero, ComponentsRegistration.DECONNECTE);
} catch (ServiceClosedException sce) {
System.err.println("Component input deconnection: " + nom + " unknown component");
}
}
// ****************************************
// Reconnexion d'une entree d'un composant
// ****************************************
private void reconnecterEntreeComposant(String nom, int numero, String entree) {
// reconnexion de l'entree d'un conteneur de CM qui a ete deconnecte
// soit par la PF soit par suppression du connecteur auquel il etait connecte
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.connectIU(numero, entree); // reconnecter l'UE du conteneur de CM
composants.changerEntreeConteneur(nom, numero, entree);
} catch (ServiceClosedException sce) {
System.err.println("Component input reconnection: " + nom + " unknown component");
}
}
// ****************************************
// Duplication de la sortie d'un composant
// ****************************************
private void dupliquerSortieComposant(String nom, String sortie) {
// ajout de connexion sur la sortie d'un conteneur de CM
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.connectOU(sortie); // connecter l'US du conteneur de CM
composants.ajouterSortieConteneur(nom, sortie);
} catch (ServiceClosedException sce) {
System.err.println("Component output reconnection: " + nom + " unknown component");
}
}
// ********************************************************************************
// Redirection de l'entree d'un connecteur vers un autre hote ou vers l'hote local
// ********************************************************************************
private void redirigerEntreeconnecteur(String nom, String vers, String sender) {
// Utilise lors de la migration d'un composant :
new ThreadRedirigerEntreeConnecteur(nom, vers, sender);
}
// *********************************************************************************
// Redirection de la sortie d'un connecteur vers un autre hote ou vers l'hote local
// *********************************************************************************
private void redirigerSortieconnecteur(String nom, String vers, String sender) {
// Utilise lors de la migration d'un composant :
// la sortie du connecteur peut etre locale ou distante mais l'entree est obligatoirement locale
new ThreadRedirigerSortieConnecteur(nom, vers, sender);
}
// ***************************
// Suppression d'un composant
// ***************************
private void supprimerComposant(String nom) {
OsagaiaContainerDescriptor designation = composants.trouverConteneur(nom);
if (designation == null) return; // le composant n'existe pas => on nefait rien
// suppression d'un conteneur de CM
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(nom));
try { // desenregistrer ce CM s'il envoie des commandes a la PF
BCCommandSenderPlugin commandes = (BCCommandSenderPlugin) ServicesRegisterManager.lookForService(Parameters.APPLICATION_COMMAND_SERVICE);
commandes.removeReplyListener(nom);
} catch (ServiceClosedException sce) {
} // le service d'envoi de commandes n'est pas installe
uc.stop();
uc.disconnection(); // deconnecter le composant de ses connecteurs d'entree et de sortie
uc.stop_CM(); // arreter le CM
uc.join_CM(); // attendre que le CM s'arrete
designation.stopConteneur(); // arreter le conteneur de CM
composants.enleverConteneur(nom); // supprimer ce conteneur de la liste
} catch (ServiceClosedException sce) {
System.err.println("Component remove: " + nom + " unknown component");
}
}
// ****************************
// Suppression d'un connecteur
// ****************************
/*
* La version de supprimerconnecteur qui suit permet de supprimer un connecteur distribue ou relais
* en n'envoyant la commande de suppression qu'a une seule plates-formes accueillant ce connecteur.
* Cette PF transmet a l'autre PF un ordre de suppression du connecteur.
* ATTENTION car cette commande n'arrivant pas de la PF qui
* supervise cet hote, elle peut arriver dans un ordre quelconque vis a vis des commandes
* de cette PF ce qui fait qu'un connecteur supprime par un hote distant puis recree
* par la PF peut etre recree avant d'etre supprime.
*/
private void supprimerconnecteur(String nom) {
KorronteaContainerDescriptor designation = connecteurs.trouverConteneur(nom);
if (designation == null) return; // le connecteur n'existe pas => on nefait rien
// Pour les connecteurs en 2 ou 3 parties
// demander aux PFs qui accueillent les autres extremites du connecteur de la supprimer
if (!designation.getSortie().equals(Commands.ES_INTERNE)) {
// envoyer e la PF qui accueille la sortie du connecteur une demande de suppression
String sortie = designation.getSortie();
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.REMOVE_PART_OF_CONNECTOR + " " + nom);
emetteurDeMessages.postDirectMessage(envoi);
}
if (!designation.getEntree().equals(Commands.ES_INTERNE)) {
// envoyer e la PF qui accueille l'entree du connecteur une demande de suppression
String entree = designation.getEntree();
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.REMOVE_PART_OF_CONNECTOR + " " + nom);
emetteurDeMessages.postDirectMessage(envoi);
}
supprimerExtremiteconnecteur(nom, null); // supprimer le connecteur : commande locale
}
// **********************************************************
// Suppression de la partie locale d'un connecteur distribue
// **********************************************************
private void supprimerExtremiteconnecteur(String nom, String sender) {
// Suppression d'un connecteur ou d'une partie locale de connecteur
// Rechercher le connecteur dans la liste
KorronteaContainerDescriptor designation = connecteurs.trouverConteneur(nom);
if (designation == null) return; // le connecteur n'existe pas => on ne fait rien
String sortie = designation.getSortie();
String entree = designation.getEntree();
String expediteur = sender;
NetworkAddress ent = new NetworkAddress(entree);
NetworkAddress sort = new NetworkAddress(sortie);
NetworkAddress send = null;
if (sender != null) send = new NetworkAddress(sender);
if (sender != null) { // la commande est arrivee par reseau
if (send.isIPv4()) {
expediteur = send.getNormalizedAddress(); // normaliser l'@ de l'expediteur
}
if (!sortie.equals(Commands.ES_INTERNE)) {
// envoyer e la PF qui accueille la sortie du connecteur une demande de suppression
if (!sort.equals(send)) { // si ce n'est pas l'expediteur
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.REMOVE_PART_OF_CONNECTOR + " " + nom);
emetteurDeMessages.postDirectMessage(envoi);
}
}
if (!entree.equals(Commands.ES_INTERNE)) {
// envoyer e la PF qui accueille l'entree du connecteur une demande de suppression
if (!ent.equals(send)) { // si ce n'est pas l'expediteur
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.REMOVE_PART_OF_CONNECTOR + " " + nom);
emetteurDeMessages.postDirectMessage(envoi);
}
}
}
try {
model.korrontea.ControlUnit uc = (model.korrontea.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.stopUEandUS(); // arreter l'UE, l'US et le CM
uc.join_BC(); // attendre que le CM s'arrete
if (!sortie.equals(Commands.ES_INTERNE)) {
// sortie par reseau => arreter le thread d'emission et attendre qu'il soit arrete
serviceEmissionReseau.removeConnectorEmissionThread(nom);
}
if (!entree.equals(Commands.ES_INTERNE)) {
// entree par reseau => arreter le thread de reception et attendre qu'il soit arrete
serviceReceptionReseau.removeConnectorReceptionThread(nom);
}
designation.stopConteneur(); // supprimer le connecteur
connecteurs.enleverConteneur(nom); // supprimer ce conteneur de la liste
composants.deconnecterESConteneur(nom); // deconnecter les CM qui etaient connectes e ce connecteur
} catch (ServiceClosedException sce) {
System.err.println("Connector remove: " + nom + " unknown component");
}
}
// ********************************************************************************
// Envoi d'un composant migre
// Ceci n'est fait qu'apres avoir recu l'autorisation de migration du destinataire
// ********************************************************************************
private void envoyerComposant(String nom, String vers) {
// Serialiser un composant
OsagaiaContainerDescriptor designation = composants.trouverConteneur(nom);
if (designation == null) { // le composant n'existe pas => on nefait rien
System.err.println("Send component: " + nom + " unknown component");
} else {
// Envoyer le composant au destinataire
BCModel cm = ((BCContainer) designation.getContainer()).getBC();
String entree = designation.getEntryList(); // liste des entrees de ce composant
String sortie = designation.getOutputList(); // liste des sorties de ce composant
supprimerComposant(nom); // supprimer le composant envoye
InternalPlatformMessage tr = new InternalPlatformMessage(Parameters.SUPERVISOR, vers, cm);
tr.addContent(Commands.RECEIVE_COMPONENT + " " + nom + " " + entree + " " + sortie); // creer le message
emetteurDeMessages.postMessage(new NetworkPlatformMessage(tr));
// rediriger les sorties de tous les connecteurs en entree de ce composant
for (int i = 0; i < designation.getEntree().length; i++) {
if ((!designation.getEntree()[i].equals(Commands.ES_NULL)) && (!designation.getEntree()[i].equals(Commands.ES_NOT_USED))) {
redirigerSortieconnecteur(designation.getEntree()[i], vers, null);
}
}
// rediriger les entrees de tous les connecteurs en sortie de ce composant
for (int i = 0; i < designation.getSortie().length; i++) {
if ((!designation.getSortie()[i].equals(Commands.ES_NULL)) && (!designation.getSortie()[i].equals(Commands.ES_NOT_USED))) {
redirigerEntreeconnecteur(designation.getSortie()[i], vers, null);
}
}
}
}
// **************************************************************
// Reception d'un composant migre et relancement de ce composant
// **************************************************************
private void recevoirComposant(String nom, CommandAnalyser decoupage, NetworkPlatformMessage recu) {
try {
InternalPlatformMessage complet = new InternalPlatformMessage(recu);
if (complet.getBC() != null) {
ClassLoaderFromJarFile cl = (ClassLoaderFromJarFile) complet.getClassLoader();
cl.addLink();
BCContainer osagaia = new BCContainer(nom, complet.getBC(), cl, decoupage.getSplittedEntryList(), decoupage.getSplittedOutputList());
osagaia.setSerialized();
// Enregistrer ce conteneur de CM dans la liste
composants.ajouterConteneur(new OsagaiaContainerDescriptor(osagaia, cl, nom, decoupage.getSplittedEntryList(), decoupage.getSplittedOutputList()));
} else {
System.err.println("Cant load migrated BC: " + nom);
}
} catch (ClassNotFoundException cnfe) {
System.err.println("Cant find class for migrated BC: " + nom);
}
}
// *******************************
// Lancement d'un composant
// Cette methode est-elle utile ?
// *******************************
private void lancerCM(String nom) {
// lancement du CM place dans le conteneur dont le nom est passe en parametre
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.start_CM();
} catch (ServiceClosedException sce) {
System.err.println("Component run: " + nom + " unknown component");
}
}
// *******************************
// Arret d'un composant
// Cette methode est-elle utile ?
// *******************************
private void arreterCM(String nom) {
// arret du CM place dans le conteneur dont le nom est passe en parametre
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(nom));
uc.stop_CM();
} catch (ServiceClosedException sce) {
System.err.println("Component stop: " + nom + " unknown component");
}
}
//**************************************************************
// Methode generale de traitement des commandes de la PF
// Analyse du message reeu et execution de la commande associee
//**************************************************************
public void traiterCommande(NetworkPlatformMessage recu) {
String cmd = recu.getContent();
String expediteur = recu.getExpeditorAddress();
if (expediteur.equals("")) expediteur = recu.getAddress();
int portReponse = recu.getExpeditorPort();
if (recu.getReplyTo().equals(Parameters.SUPERVISOR)) {
System.out.println("***** Executing command :" + cmd + " sent by " + expediteur + " ID: " + recu.getSenderID());
// System.out.println("***** Date :"+System.currentTimeMillis());
}
try {
// Decoupage de la commande en champs
CommandAnalyser decoupage = new CommandAnalyser(cmd);
long tempsDebut;
if (Parameters.TIME_MEASURE) {
tempsDebut = System.nanoTime();
}
if (decoupage.getSplittedCommand().length < 1) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
String commande = decoupage.getSplittedCommand()[0]; // la partie commande
// Commande de creation d'un composant
if (commande.equals(Commands.CREER_COMPOSANT)) { // creation d'un conteneur de CM
if ((decoupage.getSplittedCommand().length < 5) || (decoupage.getSplittedEntryList().length < 1) || (decoupage.getSplittedOutputList().length < 1)) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (4)
String nom = decoupage.getSplittedCommand()[1];
String classeCM = decoupage.getSplittedCommand()[2];
creerComposant(nom, classeCM, decoupage); // execution de la commande
}
// Commande de lancement d'un composant
else if (commande.equals(Commands.LANCER_COMPOSANT)) { // lancement d'un CM
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
lancerCM(nom); // execution de la commande
}
// Commande d'arret d'un composant
else if (commande.equals(Commands.ARRETER_COMPOSANT)) { // Arret d'un CM
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
arreterCM(nom); // execution de la commande
}
// Commande de creation d'un connecteur
else if (commande.equals(Commands.CREER_connecteur)) { // Creation d'un conteneur de flux
if (decoupage.getSplittedCommand().length < 4) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (3)
String nom = decoupage.getSplittedCommand()[1];
String entree = decoupage.getSplittedCommand()[2];
String sortie = decoupage.getSplittedCommand()[3];
creerconnecteur(nom, entree, sortie); // execution de la commande
}
// Commande de creation d'un connecteur relai
else if (commande.equals(Commands.CREATE_RELAY_CONNECTOR)) { // Creation d'un conteneur de flux
if (decoupage.getSplittedCommand().length < 4) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (3)
String nom = decoupage.getSplittedCommand()[1];
String entree = decoupage.getSplittedCommand()[2];
String sortie = decoupage.getSplittedCommand()[3];
creerconnecteurRelais(nom, entree, sortie, expediteur); // execution de la commande
}
// Commande de creation de la partie locale d'un conecteur reparti
else if (commande.equals(Commands.CREATE_PART_OF_CONNECTOR)) {
if (decoupage.getSplittedCommand().length < 4) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
// Commande envoyee par la PF qui a cree l'autre extremite d'un connecteur reparti
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (3)
String nom = decoupage.getSplittedCommand()[1];
String entree = decoupage.getSplittedCommand()[2];
String sortie = decoupage.getSplittedCommand()[3];
creerExtremiteconnecteur(nom, entree, sortie); // execution de la commande
}
// Commande de creation de la partie locale d'un conecteur reparti utilisant un reali
// Commande de suppression d'un composant
else if (commande.equals(Commands.SUPPRIMER_COMPOSANT)) { // Suppression d'un conteneur de CM
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
supprimerComposant(nom); // execution de la commande
}
// Commande de suppression d'un connecteur
else if (commande.equals(Commands.SUPPRIMER_connecteur)) { // Suppresssion d'un conteneur de flux
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
supprimerconnecteur(nom); // execution de la commande
}
// Commande de suppression de la partie locale d'un connecteur reparti
else if (commande.equals(Commands.REMOVE_PART_OF_CONNECTOR)) {
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
// Commande envoyee par la PF qui a supprime l'autre extremite du connecteur
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
supprimerExtremiteconnecteur(nom, expediteur); // execution de la commande
}
// Commande d'envoi de la QdS d'un composant ou d'un connecteur
else if (commande.equals(Commands.LIREQDS)) { // envoi de la QdS d'un conteneur de flux ou de CM
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
String qds = String.valueOf(gestionnaireContexte.getComponentQdS(nom)); // lecture de la QdS via l'UC
NetworkPlatformMessage reponse = new NetworkPlatformMessage(recu.getReplyTo(), expediteur);
reponse.setPortNumber(portReponse);
reponse.addContent(qds);
emetteurDeMessages.postMessage(reponse); // envoyer ea par reseau
}
// Commande d'envoi de l'etat de l'hote
else if (commande.equals(Commands.LIRE_ETAT)) { // envoi de l'etat de l'hote
if (decoupage.getSplittedCommand().length < 1) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF a laquelle signaler les evenements
NetworkPlatformMessage reponse = new NetworkPlatformMessage(recu.getReplyTo(), expediteur);
reponse.setPortNumber(portReponse);
HostStatus etat = gestionnaireContexte.getHostStatus();
reponse.addContent(etat.toMessage());
reponse.setSerializedObject(etat.toByteArray());
emetteurDeMessages.postMessage(reponse); // envoyer ea par reseau
}
// Commande d'envoi de l'etat d'un composant ou d'un connecteur
else if (commande.equals(Commands.LIRE_ETAT_CONTENEUR)) { // envoi de l'etat d'un conteneur
if (decoupage.getSplittedCommand().length < 2) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
String nom = decoupage.getSplittedCommand()[1];
String etat = "";
OsagaiaContainerDescriptor designationComposant = composants.trouverConteneur(nom);
if (designationComposant != null) { // c'est un composant
etat = new String("Osagaia container input=" + designationComposant.getEntryList() + " output=" + designationComposant.getOutputList());
} else {
KorronteaContainerDescriptor designationconnecteur = connecteurs.trouverConteneur(nom);
if (designationconnecteur != null) { // c'est un connecteur
etat = new String("Korrontea container input=" + designationconnecteur.getEntree() + " output=" + designationconnecteur.getSortie() + " debit: " + gestionnaireContexte.getConnectorTrafficAverage(nom));
} else etat = new String("Unknown container: " + nom);
}
NetworkPlatformMessage reponse = new NetworkPlatformMessage(recu.getReplyTo(), expediteur);
reponse.setPortNumber(portReponse);
reponse.addContent(etat);
emetteurDeMessages.postMessage(reponse); // envoyer ea par reseau
}
// Commande deconnexion de l'entree d'un composant
else if (commande.equals(Commands.DECONNECTER_ENTREE_COMPOSANT)) {
if (decoupage.getSplittedCommand().length < 3) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
// deconnexion de l'entree d'un conteneur de CM
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation du parametre de la commande
String nom = decoupage.getSplittedCommand()[1];
int numero = -1;
try {
numero = Integer.parseInt(decoupage.getSplittedCommand()[2]);
} catch (NumberFormatException nfe) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
deconnecterEntreeComposant(nom, numero); // execution de la commande
}
// Commande reconnexion de l'entree d'un composant
else if (commande.equals(Commands.RECONNECTER_ENTREE_COMPOSANT)) {
if (decoupage.getSplittedCommand().length < 4) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
// Reconnexion de l'entree d'un conteneur de CM e un nouveau connecteur
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (2)
String nom = decoupage.getSplittedCommand()[1];
int numero = -1;
try {
numero = Integer.parseInt(decoupage.getSplittedCommand()[2]);
} catch (NumberFormatException nfe) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
String entree = decoupage.getSplittedCommand()[3];
reconnecterEntreeComposant(nom, numero, entree); // execution de la commande
}
// Commande reconnexion ou de duplication de la sortie d'un composant
else if (commande.equals(Commands.RECONNECTER_SORTIE_COMPOSANT)) {
if (decoupage.getSplittedCommand().length < 3) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
// Reconnexion de la sortie d'un conteneur de CM e un nouveau connecteur
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (2)
String nom = decoupage.getSplittedCommand()[1];
String sortie = decoupage.getSplittedCommand()[2];
dupliquerSortieComposant(nom, sortie); // execution de la commande
}
// Commande d'envoi d'un composant en migration
else if (commande.equals(Commands.ENVOYER_COMPOSANT)) {
if (decoupage.getSplittedCommand().length < 3) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, true); // la PF e laquelle signaler les evenements
String nom = decoupage.getSplittedCommand()[1];
String vers = decoupage.getSplittedCommand()[2];
envoyerComposant(nom, vers);
}
// Commande de reception d'un composant migre
else if (commande.equals(Commands.RECEIVE_COMPONENT)) { // creation d'un conteneur de CM
if ((decoupage.getSplittedCommand().length < 4) || (decoupage.getSplittedEntryList().length < 1) || (decoupage.getSplittedOutputList().length < 1)) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
// Recuperation des parametres de la commande (4)
String nom = decoupage.getSplittedCommand()[1];
recevoirComposant(nom, decoupage, recu); // execution de la commande
}
// Commande de redirection de l'entree d'un connecteur vers un autre hote ou vers cet hote
else if (commande.equals(Commands.REDIRECT_INPUT_OF_CONNECTOR)) {
if (decoupage.getSplittedCommand().length < 3) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
String nom = decoupage.getSplittedCommand()[1];
String vers = decoupage.getSplittedCommand()[2];
redirigerEntreeconnecteur(nom, vers, expediteur);
}
// Commande de redirection de la sortie d'un connecteur vers un autre hote ou vers cet hote
else if (commande.equals(Commands.REDIRECT_OUTPUT_OF_CONNECTOR)) {
if (decoupage.getSplittedCommand().length < 3) {
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
return;
}
setReferentPlatform(expediteur, portReponse, false); // la PF e laquelle signaler les evenements
String nom = decoupage.getSplittedCommand()[1];
String vers = decoupage.getSplittedCommand()[2];
redirigerSortieconnecteur(nom, vers, expediteur);
} else if (commande.equals(Commands.ENVOYER_DNS)) {
setReferentPlatform(expediteur, portReponse, false); // la PF a laquelle signaler les evenements
NetworkPlatformMessage reponse = new NetworkPlatformMessage(recu.getReplyTo(), expediteur);
reponse.setPortNumber(portReponse);
try {
KalimuchoDNS dns = (KalimuchoDNS) ServicesRegisterManager.lookForService(Parameters.KALIMUCHO_DNS_MANAGER);
reponse.addContent(addressesChecker.getHostIdentifier());
reponse.setSerializedObject(dns.getHostsAsByteArray());
// dns.dump();
} catch (ServiceClosedException sce) {
reponse.addContent("No DNS active for " + addressesChecker.getHostIdentifier());
}
emetteurDeMessages.postMessage(reponse); // envoyer ea par reseau
//gestionnaireContexte.getHostStatus().dump();
}
// Commande inconnue => erreur
else {
System.err.println("Supervisor: unknown command: " + cmd + " received from: " + expediteur);
}
// Partie utilisee pour faire des mesures de temps d'execution des commandes par la PF
if (Parameters.TIME_MEASURE) {
float val = System.nanoTime();
val = (val - tempsDebut) / 1000000;
System.out.println("temps d'execution de la commande " + cmd + " : " + val + " ms");
}
} catch (CommandSyntaxException cse) { // commande syntaxiquement incorrecte => erreur
System.err.println("Supervisor: incorrect command: " + cmd + " received from: " + expediteur);
}
}
//*******************************************************************************************************
// Methode permettant d'indiquer au gestionnaire de contexte a quelle PF envoyer les infos de contexte
// Ceci est provisoire et ne sert que parce les informations de contexte ne sont pas traitees localement
//*******************************************************************************************************
private void setReferentPlatform(String expediteur, int portReponse, boolean ref) {
NetworkAddress exp = new NetworkAddress(expediteur);
if (ref) {
gestionnaireContexte.setReferentPlatform(expediteur, portReponse);
} else {
gestionnaireContexte.setRelayReferentPlatform(expediteur, portReponse);
}
}
private class ThreadCreationConnecteur extends Thread {
private String name;
private String input;
private String output;
public ThreadCreationConnecteur(String nom, String entree, String sortie) {
name = nom;
input = entree;
output = sortie;
start();
}
@Override
public void run() {
String nom = name;
String entree = input;
String sortie = output;
NetworkAddress ent = new NetworkAddress(entree);
entree = ent.getNormalizedAddress();
NetworkAddress sort = new NetworkAddress(sortie);
sortie = sort.getNormalizedAddress();
boolean aFinir = true; // indique si l'on doit creer localement un connecteur
// ce ne sera pas le cas si on n'a pas de route directe => creation d'un connecteur relai
// verifier que les adresses fournies ne soient pas les miennes
// Si c'est le cas l'entree ou la sortie sont internes
if (!entree.equals(Commands.ES_INTERNE)) { // l'entree n'est pas locale
if (addressesChecker.isPresentAddress(ent)) entree = Commands.ES_INTERNE;
}
if (!sortie.equals(Commands.ES_INTERNE)) { // la sortie n'est pas locale
if (addressesChecker.isPresentAddress(sort)) sortie = Commands.ES_INTERNE;
}
if (!entree.equals(Commands.ES_INTERNE)) { // l'entree n'est pas locale
try {
ReplyForRouteMessage route = emetteurDeMessages.findRoute(ent); // chercher une route vers cette entree
if (sortie.equals(Commands.ES_INTERNE)) { // entree externe sortie locale
if (route.isDirect()) { // entree externe sortie locale et la route pour l'entree est directe
// on va creer on connecteur reparti dont l'autre extremite est a l'entree et qui envoie ici
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.CREATE_PART_OF_CONNECTOR + " " + nom + " " + Commands.ES_INTERNE + " " + addressesChecker.getMyFirstAddress(ent.getType()).getNormalizedAddress());
emetteurDeMessages.postDirectMessage(envoi);
} else { // entree externe sortie locale et la route pour l'entree est indirecte
// on va faire creer un connecteur relai dont l'entree est sur 'entree' et la sortie ici
NetworkAddress via = new NetworkAddress(route.getVia());
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, route.getVia());
envoi.addContent(Commands.CREATE_RELAY_CONNECTOR + " " + nom + " " + entree + " " + addressesChecker.getMyFirstAddress(via.getType()).getNormalizedAddress());
emetteurDeMessages.postDirectMessage(envoi);
ent = via;
entree = via.getNormalizedAddress();
}
} else { // l'entree est externe la sortie aussi => c'est un connecteur relai
if (route.isDirect()) { // il faut que l'entree soit accessible directement
ReplyForRouteMessage routeSortie = emetteurDeMessages.findRoute(new NetworkAddress(sortie));
if (routeSortie.isDirect()) { // l'entre et la sortie sont accessibles directement
sortie = routeSortie.getVia();
sort = new NetworkAddress(sortie);
creerconnecteurRelais(nom, entree, sortie, null); // on cree ici le connecteur relais de entree vers sortie
aFinir = false; // la commande est traitee => c'est termine
} else { // connecteur relais non faisable car pas d'acces direct a la sortie
System.err.println("Creation a connector: can't reach " + sortie);
aFinir = false;
}
} else { // connecteur relais non faisable car pas d'acces direct a l'entree
System.err.println("Creation a connector: can't reach " + entree);
aFinir = false;
}
}
} catch (NoRouteException nr) { // on ne peut pas atteindre l'entree ou la sortie
System.err.println("Creation a connector: can't reach " + entree + " or " + sortie);
aFinir = false;
}
} else { // l'entree est interne
if (!sortie.equals(Commands.ES_INTERNE)) { // entree interne sortie externe
try {
ReplyForRouteMessage routeSortie = emetteurDeMessages.findRoute(sort);
if (routeSortie.isDirect()) { // entree interne sortie externe et la sortie est directement accessible
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.CREATE_PART_OF_CONNECTOR + " " + nom + " " + addressesChecker.getMyFirstAddress(sort.getType()).getNormalizedAddress() + " " + Commands.ES_INTERNE);
emetteurDeMessages.postDirectMessage(envoi);
} else { // l'entree est interne et la sortie n'est pas directement accessible
// on va faire creer un connecteur reparti dont l'entree est ici et la sortie sur 'sortie'
NetworkAddress via = new NetworkAddress(routeSortie.getVia());
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, routeSortie.getVia());
envoi.addContent(Commands.CREATE_RELAY_CONNECTOR + " " + nom + " " + addressesChecker.getMyFirstAddress(via.getType()).getNormalizedAddress() + " " + sortie);
emetteurDeMessages.postDirectMessage(envoi);
sort = via;
sortie = sort.getNormalizedAddress();
}
} catch (NoRouteException nr) { // on ne peut pas atteindre la sortie
System.err.println("Creation a connector: can't reach " + sortie);
aFinir = false;
}
}
}
if (aFinir) creerExtremiteconnecteur(nom, entree, sortie); // creation de la partie locale du connecteur
}
}
private class ThreadRedirigerEntreeConnecteur extends Thread {
private String nom;
private String vers;
private String sender;
public ThreadRedirigerEntreeConnecteur(String name, String to, String exp) {
nom = name;
vers = to;
sender = exp;
start();
}
@Override
public void run() {
KorronteaContainerDescriptor designation = connecteurs.trouverConteneur(nom);
if (designation == null) return; // le connecteur n'existe pas => on ne fait rien
String sortie = designation.getSortie();
String entree = designation.getEntree();
NetworkAddress ent = new NetworkAddress(entree);
NetworkAddress sort = new NetworkAddress(sortie);
NetworkAddress send = null;
if (sender != null) send = new NetworkAddress(sender);
NetworkAddress to = new NetworkAddress(vers);
boolean aFinir = true; // indique si l'on doit creer localement un connecteur
if (!entree.equals(Commands.ES_INTERNE)) { // l'entre de ce connecteur arrivait par reseau
// entree par reseau => arreter le thread de reception et attendre qu'il soit arrete
serviceReceptionReseau.removeConnectorReceptionThread(nom);
// demander a la PF qui etait connectee a cette entre de supprimer son morceau de connecteur
if (!ent.equals(send)) {
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.REMOVE_PART_OF_CONNECTOR + " " + nom);
emetteurDeMessages.postDirectMessage(envoi);
}
}
vers = to.getNormalizedAddress();
if (!addressesChecker.isPresentAddress(to)) {
if (!sortie.equals(Commands.ES_INTERNE)) { // la sortie de ce connecteur partait sur reseau
// supprimer la partie locale du connecteur et transmettre la commande a 'sortie'
supprimerExtremiteconnecteur(nom, null);
if (!sort.equals(send)) {
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.REDIRECT_INPUT_OF_CONNECTOR + " " + nom + " " + vers);
emetteurDeMessages.postDirectMessage(envoi);
}
aFinir = false; // on n'a rien de plus a faire
} else {
try { // relier l'entree de ce connecteur a 'vers'
ReplyForRouteMessage route = emetteurDeMessages.findRoute(to); // chercher une route vers cette entree
ent = new NetworkAddress(route.getVia());
entree = ent.getNormalizedAddress();
if (route.isDirect()) { // entree externe sortie locale et la route pour l'entree est directe
// on va creer on connecteur reparti dont l'autre extremite est a l'entree et qui envoie ici
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.CREATE_PART_OF_CONNECTOR + " " + nom + " " + Commands.ES_INTERNE + " " + addressesChecker.getMyFirstAddress(ent.getType()).getNormalizedAddress());
emetteurDeMessages.postDirectMessage(envoi);
} else { // entree externe sortie locale et la route pour l'entree est indirecte
// on va faire creer un connecteur relai dont l'entree est sur 'vers' et la sortie ici
NetworkAddress via = new NetworkAddress(route.getVia());
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, route.getVia());
envoi.addContent(Commands.CREATE_RELAY_CONNECTOR + " " + nom + " " + vers + " " + addressesChecker.getMyFirstAddress(via.getType()).getNormalizedAddress());
emetteurDeMessages.postDirectMessage(envoi);
}
} catch (NoRouteException nr) { // on ne peut pas atteindre l'entree ou la sortie
System.err.println("Creation a connector: can't reach " + to.getNormalizedAddress());
aFinir = false;
}
}
if (aFinir) {
// lancer un processus pour cette entree reseau
serviceReceptionReseau.createConnectorReceptionThread(nom, new NetworkAddress(entree));
designation.setEntree(entree);
}
} else { // l'entree du connecteur est devenue interne
designation.setEntree(Commands.ES_INTERNE);
}
}
}
private class ThreadRedirigerSortieConnecteur extends Thread {
private String nom;
private String vers;
private String sender;
public ThreadRedirigerSortieConnecteur(String name, String to, String exp) {
nom = name;
vers = to;
sender = exp;
start();
}
@Override
public void run() {
KorronteaContainerDescriptor designation = connecteurs.trouverConteneur(nom);
if (designation == null) return; // le connecteur n'existe pas => on ne fait rien
String sortie = designation.getSortie();
String entree = designation.getEntree();
NetworkAddress ent = new NetworkAddress(entree);
NetworkAddress sort = new NetworkAddress(sortie);
NetworkAddress send = null;
if (sender != null) send = new NetworkAddress(sender);
NetworkAddress to = new NetworkAddress(vers);
boolean aFinir = true; // indique si l'on doit creer localement un connecteur
if (!sortie.equals(Commands.ES_INTERNE)) { // la sortie de ce connecteur arrivait par reseau
// sortiee par reseau => arreter le thread d'emission et attendre qu'il soit arrete
serviceEmissionReseau.removeConnectorEmissionThread(nom);
// demander a la PF qui etait connectee a cette sortie de supprimer son morceau de connecteur
if (!sort.equals(send)) {
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.REMOVE_PART_OF_CONNECTOR + " " + nom);
emetteurDeMessages.postDirectMessage(envoi);
}
}
vers = to.getNormalizedAddress();
if (!addressesChecker.isPresentAddress(to)) {
if (!entree.equals(Commands.ES_INTERNE)) { // l'entree de ce connecteur partait sur reseau
// supprimer la partie locale du connecteur et transmettre la commande a 'sortie'
supprimerExtremiteconnecteur(nom, null);
if (!ent.equals(send)) {
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, entree);
envoi.addContent(Commands.REDIRECT_OUTPUT_OF_CONNECTOR + " " + nom + " " + vers);
emetteurDeMessages.postDirectMessage(envoi);
}
aFinir = false; // on n'a rien de plus a faire
} else {
try { // relier la sortie de ce connecteur a 'vers'
ReplyForRouteMessage route = emetteurDeMessages.findRoute(to); // chercher une route vers cette entree
sort = new NetworkAddress(route.getVia());
sortie = sort.getNormalizedAddress();
if (route.isDirect()) { // entree externe sortie locale et la route pour l'entree est directe
// on va creer on connecteur reparti dont l'autre extremite est a l'entree et qui envoie ici
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, sortie);
envoi.addContent(Commands.CREATE_PART_OF_CONNECTOR + " " + nom + " " + addressesChecker.getMyFirstAddress(sort.getType()).getNormalizedAddress() + " " + Commands.ES_INTERNE);
emetteurDeMessages.postDirectMessage(envoi);
} else { // entree externe sortie locale et la route pour l'entree est indirecte
// on va faire creer un connecteur relai dont l'entree ici et la sortie sur 'vers'
NetworkAddress via = new NetworkAddress(route.getVia());
NetworkPlatformMessage envoi = new NetworkPlatformMessage(Parameters.SUPERVISOR, route.getVia());
envoi.addContent(Commands.CREATE_RELAY_CONNECTOR + " " + nom + " " + addressesChecker.getMyFirstAddress(via.getType()).getNormalizedAddress() + " " + vers);
emetteurDeMessages.postDirectMessage(envoi);
}
} catch (NoRouteException nr) { // on ne peut pas atteindre l'entree ou la sortie
System.err.println("Creation a connector: can't reach " + to.getNormalizedAddress());
aFinir = false;
}
}
if (aFinir) {
// lancer un processus pour cette sortie reseau
serviceEmissionReseau.createConnectorEmissionThread(nom, new NetworkAddress(sortie));
designation.setSortie(sortie);
}
} else { // la sortie du connecteur est devenue interne il faut y reconnecter le composant
designation.setSortie(Commands.ES_INTERNE);
ConnectedInput comp = composants.trouveComposantEntreeSur(nom);
try {
model.osagaia.ControlUnit uc = (model.osagaia.ControlUnit) (ServicesRegisterManager.lookForService(comp.getName()));
uc.connectIUAfterRedirection(comp.getInput(), nom);
} catch (ServiceClosedException sce) {
System.err.println("Component input reconnection: " + nom + " unknown component");
}
}
}
}
}