package model.osagaia; //import model.interfaces.control.IBusinessComponent; import model.interfaces.control.IControlUnit; import util.streams.samples.Sample; import model.StopBCException; /** * Control Unit of a BC container<br> * Service offering methods to: * <ul> * <li> Connect/reconnect input or output to a connector. * Reconnections suspend the process on a semaphore until the connector is available. * They are done into a thread in order to not suspend the platform * when a connector is not yet created. * <li> Disconnect input or output from the connector. * <li> Run the BC * <li> Stop the BC * <li> Wait for the BC to terminate * <li> Return the BCes QoS level * </ul> * * @author Dalmau */ // Classe de l'UC d'un composant osagaia public final class ControlUnit implements IControlUnit { private InputUnit[] ue; // UEs du composant private OutputUnit us; // US du composant private BCModel cc; // CM private String[] nomconnecteurSortie; // connecteurs auxquels il est connecte private String[] nomconnecteurEntree; // connecteurs auxquels il est connecte private boolean arret; private int indexEntree; /** * Construction of a Control Unit * @param inputConnector names of the connectors in input * @param outputConnector names of the connectors at output * @param inputUnit Input Units of the container * @param bc BC * @param outputUnit Output Unit of the container */ public ControlUnit(String[] inputConnector, String[] outputConnector, InputUnit[] inputUnit, BCModel bc, OutputUnit outputUnit) { ue = (InputUnit[])inputUnit; for (int i=0; i<ue.length; i++) { if (ue[i] != null) ue[i].setControlUnit(this); } us = (OutputUnit)outputUnit; cc = bc; nomconnecteurEntree = inputConnector; nomconnecteurSortie = outputConnector; arret = false; indexEntree = 0; } // Methodes appelables par la PF //********************* // CONTROLE UC //********************* /** * Stops the UC when the BC is to be stopped */ public synchronized void stop() { arret = true; notifyAll(); } //********************* // CONTROLE UE et US //********************* /** * Connects the container to a connector as input<br> * This connection is done in a thread which waits until the connector is available * * @param numero number of IU to connect * @param inputConnector name of the connector for input */ public synchronized void connectIU(int numero, String inputConnector) { if( ue[numero] != null) { // connecter l'UE // La connexion est faite dans un thread parce qu'elle est bloquante // La PF appelle cette methode mais ne doit pas etre bloquee new InputUnitConnectionThread(ue[numero], inputConnector).start(); } } /** * Reconnectes au IU afer redirecting the connectors (migration) * @param numero number of the IU to reconnect * @param inputConnector connector to connet to this IU */ public void connectIUAfterRedirection(int numero, String inputConnector) { if( ue[numero] != null) { // connecter l'UE // La connexion est faite dans un thread parce qu'elle est bloquante // La PF appelle cette methode mais ne doit pas etre bloquee new InputUnitConnectionAfterRedirectionThread(ue[numero], inputConnector, nomconnecteurEntree, nomconnecteurSortie).start(); } } /** * Connects the container to a connector as output<br> * This connection is done in a thread which waits until the connector is available * * @param outputConnector name of the connector for output */ public synchronized void connectOU(String outputConnector) { if( us != null) { // connecter l'US // La connexion est faite dans un thread parce qu'elle est bloquante // La PF appelle cette methode mais ne doit pas etre bloquee new OutputUnitConnectionThread(us, outputConnector).start(); } } /** * Disconnects the container from one connector in input * @param numero number of Iu to disconnect */ public void disconnectIU(int numero) { // deconnexion de l'entree du conteneur de CM // La PF appelle cette methode qui n'est pas bloquante if( ue[numero] != null) ue[numero].disconnection(); } /** * Disconnects the container from the connectors in input and output. */ public void disconnection() { // l'UE et l'US se deconnectent des connecteurs // La PF appelle cette methode qui n'est pas bloquante for (int i=0; i<ue.length; i++) { if( ue[i] != null) ue[i].disconnection(); } if( us != null) us.disconnection(); } //*********************************** // CONTROLE COMPOSANT METIER //*********************************** /** * Starts the BC */ public void start_CM() { // lancement du CM cc.start(); } /** * Stops the BC */ public void stop_CM() { // arret du CM via l'UE et l'US => exception cc.stop(); for (int i=0; i<ue.length; i++) { if( ue[i] != null) { ue[i].stop(); // arreter l'UE => exception au CM s'il tente de lire } } if( us != null) { us.stop(); // arreter l'US => exception au CM s'il tente d'ecrire } } /** * Wait for BC to terminate */ public void join_CM() { // attente de terminaison du CM cc.join(); } /** * reads the actual BC's Qos level (as the BC indicates it by its method levelStateQoS()) * @return the actual BC's Qos level (as the BC indicates it by its method levelStateQoS()) */ public float sendBCQoSLevel() { // envoi de la QdS e la PF return cc.readQoS(); // QdS transmise par le CM } // Methodes non appelables par la PF mais utilisees par le conteneur de CM /** * * Connects the container to connectors for input and output<br> * These connections are done in a threads which wait until the connectors are vailable */ public void connection() { // l'UE et l'US decouvrent les connecteurs et s'y connectent // Le conteneur de CM appelle cette methode dans un thread car elle est bloquante for (int i=0; i<nomconnecteurSortie.length; i++) { if( us != null) connectOU(nomconnecteurSortie[i]); } for (int i=0; i<ue.length; i++) { if( ue[i] != null) connectIU(i, nomconnecteurEntree[i]); } } /** * Returns the first available input in any input of the container * @return the first available input in any input of the container * @throws StopBCException when the BC is to be stopped */ public synchronized Sample getFirstInput() throws StopBCException { boolean trouve = false; int index = indexEntree; while ((!trouve) && (!arret)) { if (ue[index] != null) { if (ue[index].isInputAvailable()) trouve = true; else { index++; if (index == ue.length) index = 0; } } if ((!trouve) && (index == indexEntree)) { try { wait(); } catch (InterruptedException ie) {} } } if (arret) throw(new StopBCException("CM arrete lors d'une lecture dans l'UE")); else { indexEntree = index +1; if (indexEntree == ue.length) indexEntree = 0; Sample ech = ue[index].readInInputUnit(); ech.setInputNumber(index); return ech; } } // Methode utilisee par les buffers des connecteurs en entree pour signaler qu'ils ont quelque chose. /** * Used to indicate to the CU that an input is available * @param number number of the input on which data is available */ public synchronized void setInputAvailable(int number) { if (number != -1) { // le buffer connait l'UE if (ue[number] != null) { // il exite bien une UE de ce numero cc.deposeListener(ue[number]); // appel de l'ecouteur d'evenements } } notifyAll(); // debloquer le CM s'il est bloque dans getFirstInput } /** * The BC controled by this CU * @return the BC controled by this CU */ public BCModel getCM() { return cc; } }