package org.jacorb.concurrency; /* * JacORB concurrency control service - a free CCS for JacORB * * Copyright (C) 1999-2004 LogicLand group, Viacheslav Tararin. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.util.Enumeration; import java.util.Hashtable; import org.omg.CosConcurrencyControl.LockCoordinator; import org.omg.CosConcurrencyControl.LockCoordinatorHelper; import org.omg.CosTransactions.Coordinator; import org.omg.CosTransactions.HeuristicCommit; import org.omg.CosTransactions.HeuristicHazard; import org.omg.CosTransactions.HeuristicMixed; import org.omg.CosTransactions.HeuristicRollback; import org.omg.CosTransactions.NotPrepared; import org.omg.CosTransactions.ResourcePOA; import org.omg.CosTransactions.Status; import org.omg.CosTransactions.Vote; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAPackage.ServantNotActive; class TransactionCoordinator extends ResourcePOA /* implements Runnable */ { static final int ACTIVE = 0; static final int COMMITED = 1; static final int PREPARED = 2; static final int ROLLEDBACK = 3; private Coordinator current; private POA poa; private Hashtable locksets = new Hashtable(); private int state; private LockSetFactoryImpl factory; TransactionCoordinator( LockSetFactoryImpl factory, Coordinator current, POA poa ) { this.current = current; this.poa = poa; this.factory = factory; Status status = current.get_status(); if( status.equals( Status.StatusActive ) ){ state = ACTIVE; } else if( status.equals( Status.StatusPrepared ) || status.equals( Status.StatusPreparing ) ) { state = PREPARED; } else if ( status.equals( Status.StatusCommitted ) || status.equals( Status.StatusUnknown ) || status.equals( Status.StatusNoTransaction ) || status.equals( Status.StatusCommitting ) ) { state = COMMITED; } else if (status.equals( Status.StatusRollingBack ) || status.equals( Status.StatusMarkedRollback) || status.equals( Status.StatusRolledBack) ) { state = ROLLEDBACK; } }; Coordinator get_coordinator() { return current; }; synchronized Status get_state(){ switch( state ){ case ACTIVE: return Status.StatusActive; case COMMITED: return Status.StatusCommitted; case PREPARED: return Status.StatusPrepared; case ROLLEDBACK: return Status.StatusRolledBack; } return Status.StatusNoTransaction; }; public synchronized Vote prepare() throws HeuristicMixed,HeuristicHazard { if( state == ACTIVE ){ state = PREPARED; return Vote.VoteCommit; } return Vote.VoteRollback; }; public synchronized void rollback() throws HeuristicCommit,HeuristicMixed,HeuristicHazard { if( state == ACTIVE ) { state = ROLLEDBACK; run(); } }; public synchronized void commit() throws NotPrepared,HeuristicRollback,HeuristicMixed,HeuristicHazard{ if( state == PREPARED ) { state = COMMITED; run(); } else { throw new NotPrepared(); } }; public synchronized void commit_one_phase() throws HeuristicHazard { if( state == ACTIVE ){ state = COMMITED; run(); } }; public synchronized void forget(){ throw new org.omg.CORBA.NO_IMPLEMENT(); }; synchronized LockCoordinator get_lock_coordinator( TransactionalLockSetImpl ls ){ LockCoordinatorImpl lc = (LockCoordinatorImpl)locksets.get( ls ); if( lc == null ){ lc = new LockCoordinatorImpl( this, ls ); locksets.put( ls, lc ); } try { return LockCoordinatorHelper.narrow(poa.servant_to_reference(lc)); } catch ( Exception e ){ e.printStackTrace( System.out ); throw new org.omg.CORBA.INTERNAL(); } }; synchronized void set_lock_coordinator( TransactionalLockSetImpl ls ){ check_state(); LockCoordinatorImpl lc = (LockCoordinatorImpl)locksets.get( ls ); if( lc == null ){ lc = new LockCoordinatorImpl( this, ls ); locksets.put( ls, lc ); } }; synchronized void remove_coordinator( TransactionalLockSetImpl ls ){ LockCoordinatorImpl lc = (LockCoordinatorImpl)locksets.get( ls ); if( lc != null ){ try { byte [] ObjId = poa.servant_to_id( lc ); poa.deactivate_object( ObjId ); } catch ( Exception e ) { } locksets.remove( ls ); } }; public void run() { Enumeration enumeration = locksets.elements(); while( enumeration.hasMoreElements() ){ LockCoordinatorImpl lc = (LockCoordinatorImpl)enumeration.nextElement(); lc.drop_locks(); try { byte [] ObjId = poa.servant_to_id( lc ); poa.deactivate_object( ObjId ); } catch ( ServantNotActive e ) { } catch ( Exception e ){ e.printStackTrace( System.out ); throw new org.omg.CORBA.INTERNAL(); } }; factory.remove_me( this ); }; private void check_state(){ if( state == PREPARED || state == COMMITED ) { throw new org.omg.CORBA.INVALID_TRANSACTION(); } else if( state == ROLLEDBACK ) { throw new org.omg.CORBA.TRANSACTION_ROLLEDBACK(); } }; };