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;
}
}