package elte.java2_utikalauz5.rmi; import java.rmi.Naming; import java.rmi.server.UnicastRemoteObject; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; import java.util.Hashtable; import java.util.Enumeration; /** A kétfázisú megegyezési protokollt megvalósító osztály. Ezen osztály objektumai képesek egy-egy tranzakció levezénylésére. Használatakor ne feledjünk el a következő jogokat megadni!
grant signedBy "utikalauz" {
  permission java.security.AllPermission;
};
@link.forrásfájl {@docRoot}/../data/rmi/src TranzakcioManager.java @link.letöltés {@docRoot}/../data/rmi TranzakcioManager.jar @since Java 2 Útikalauz programozóknak */ public class TranzakcioManager extends UnicastRemoteObject implements TranzakcioManagerInterface { /** Verziószám. */ private final static long serialVersionUID = 15L; String nev; // A tranzakció - szöveges - azonosítóját tárolja Hashtable rv; // A tranzakcióban résztvevők identitását tárolja boolean koordinator_dontese=true; // Feltesszük, hogy mindenkinél OK. boolean dontottem=false; // Külső helyről még abortálhatják Object koordinator_dontese_mutex = new Object(); // Kölcsönös kizáráshoz public TranzakcioManager(String nev) throws RemoteException { super(); this.nev=nev; rv=new Hashtable(); } // Egy - esetleg új - résztvevő feljegyzése ... // Az "rvneve" paraméter kulcs, tehát ha egy résztvevő ugyanazon a // néven kétszer is bejegyezteti magát, az nem okozhat problémát // (az előző bejegyzés egyszerűen "önmagával" felül lesz írva) // Az objektumreferencia hash-elésével az ilyen problémák is // kiszűrhetőek lennének, de most ezzel inkább nem foglalkozunk. public void Tranzakcio_Resztvevo_Bejegyzese(String rvneve, TranzakcioResztvevoInterface kit) throws RemoteException { synchronized (rv) { rv.put(rvneve, kit); // Szöveges azonosítót+referenciát } } // Egy külső (nem közvetlen résztvevő) alkalmazás (pl. a kezdeményező) // kérheti a tranzakció abortálását public void Abortal() throws TranzakcioException, RemoteException { synchronized (koordinator_dontese_mutex) { if (dontottem) { throw new TranzakcioException("Akkor próbáltak abortálni, amikor "+ "a végeredmény már nem befolyásolható!"); } koordinator_dontese=false; } } // Itt történik a kétfázisú megegyezés ... public boolean Dontes() throws TranzakcioException, RemoteException { Enumeration resztvevok=rv.elements(); boolean b=false; // Végigkérdezi a résztvevőket, hogy felkészültek-e a // beállítások véglegesítésére while (resztvevok.hasMoreElements()) { System.out.println("Következő résztvevő megkéredezése ("+ this.nev+") ..."); TranzakcioResztvevoInterface o= (TranzakcioResztvevoInterface) resztvevok.nextElement(); try { b=o.Felkeszul(this.nev); // Felkészült? } catch (java.rmi.RemoteException e) { synchronized (koordinator_dontese_mutex) { koordinator_dontese=false; // ABORT } } synchronized (koordinator_dontese_mutex) { koordinator_dontese=(koordinator_dontese && b); } } // Itt már megvan a döntés a tranzakció kimeneteléről // Értesítjük a résztvevőket a tranzakció kimeneteléről synchronized (koordinator_dontese_mutex) { dontottem=true; } if (koordinator_dontese) { System.out.println("A "+this.nev+" tranzakció véglegesíthető."); } else { System.out.println("A "+this.nev+" tranzakció abortálva lesz."); } resztvevok=rv.elements(); while (resztvevok.hasMoreElements()) { System.out.println("Következő résztvevő értesítése ("+ this.nev+") ..."); TranzakcioResztvevoInterface o= (TranzakcioResztvevoInterface) resztvevok.nextElement(); try { o.Veglegesit(koordinator_dontese,this.nev); } catch (java.rmi.RemoteException e) { throw new TranzakcioException("Tranzakcio fuggoben maradt!"); } } // A hívónak is visszaadjuk a végeredményt return koordinator_dontese; // Nem kell szinkronizálni ... } // Visszaadja a tranzakció szöveges azonosítóját public String getTid() throws RemoteException { return this.nev; } }