package org.jacorb.demo.bank.concurrency; /** * Simple Transaction Service example, code taken and adapted * from http://www.wiley.com/compbooks/vogel/ejb/code.html */ import org.omg.CORBA.*; import org.omg.CosTransactions.*; import org.omg.CosConcurrencyControl.*; import org.omg.CosConcurrencyControl.*; public class AccountImpl extends AccountPOA { private float balance; private float newBalance; private TransactionalLockSet lock_set; private String name; private int id; private Coordinator current_transaction = null; private boolean prepared = false; public AccountImpl( TransactionalLockSet lock_set, String name, float deposit, int id ) { this.name = name; this.lock_set = lock_set; this.id = id; balance = deposit; newBalance = balance; } public synchronized float get_balance( Control control ){ try { Coordinator coord = control.get_coordinator(); // If my transaction change account or nobody change account if( lock_set.try_lock( coord, lock_mode.read ) ) { float r = newBalance; lock_set.unlock( coord, lock_mode.read ); return r; } else { // Anybody change account get_last valid data return balance; } } catch ( Exception e ) { e.printStackTrace(); throw new org.omg.CORBA.INTERNAL(); } } public synchronized void debit( float amount, Control control ) throws InsufficientFunds { try { Coordinator coord = control.get_coordinator(); // lock account for write while( ! lock_set.try_lock( coord, lock_mode.write ) ){ try { wait(); } catch ( Exception e ){ e.printStackTrace(); } } // check founds if( amount > newBalance ) { lock_set.unlock( coord, lock_mode.write ); System.out.println("Resource: " + name + " account unlocked"); throw new InsufficientFunds(); } newBalance -= amount; if( current_transaction == null ){ current_transaction = coord; coord.register_resource( _this() ); }; } catch( Unavailable u ) { System.err.println("Account " + name + "::debit: exception: " + u ); } catch( LockNotHeld h ) { System.err.println("Account " + name + "::debit: exception: " + h ); } catch( Inactive i ) { System.err.println("Account " + name + "::debit: exception: " + i ); } catch( SystemException se ) { System.err.println("Account " + name + "::debit: exception: " + se ); }; } public synchronized void credit( float amount, Control control ) { try { Coordinator coord = control.get_coordinator(); // lock account for write while( ! lock_set.try_lock( coord, lock_mode.write ) ){ try { wait(); } catch ( Exception e ){ e.printStackTrace(); } } newBalance += amount; if( current_transaction == null ){ current_transaction = coord; coord.register_resource( _this() ); }; } catch( Unavailable u ) { System.err.println("Account " + name + "::credit: exception: " + u ); } catch( Inactive i ) { System.err.println("Account " + name + "::credit: exception: " + i ); } catch( SystemException se ) { System.err.println("Account " + name + "::credit: exception: " + se ); } } public TransactionalLockSet get_lock_set(){ return lock_set; }; public java.lang.String owner(){ return name; }; public int account_code(){ return id; }; // implement methods of the Resource interface public synchronized Vote prepare() { if( balance == newBalance ) return Vote.VoteReadOnly; return Vote.VoteCommit; } public synchronized void rollback() { newBalance = balance; current_transaction = null; notifyAll(); } public synchronized void commit() { balance = newBalance; current_transaction = null; notifyAll(); } public synchronized void commit_one_phase() { if(prepare() == Vote.VoteCommit) { commit(); } } public synchronized void forget() { System.out.println("Resource " + name + " : forget()"); } }