1
package com.eucalyptus.util;
3
import java.lang.ref.WeakReference;
4
import java.util.Calendar;
6
import java.util.concurrent.ConcurrentNavigableMap;
7
import java.util.concurrent.ConcurrentSkipListMap;
9
import javax.persistence.EntityManager;
10
import javax.persistence.EntityManagerFactory;
11
import javax.persistence.EntityTransaction;
13
import org.apache.commons.lang.time.StopWatch;
14
import org.apache.log4j.Logger;
15
import org.hibernate.Session;
16
import org.hibernate.ejb.EntityManagerFactoryImpl;
18
public class TxHandle implements Comparable<TxHandle>, EntityTransaction {
19
private static Logger LOG = Logger.getLogger( TxHandle.class );
20
private static ConcurrentNavigableMap<String, TxHandle> outstanding = new ConcurrentSkipListMap<String,TxHandle>();
22
private EntityManager em;
23
private WeakReference<Session> session;
24
private EntityTransaction delegate;
25
private StackTraceElement owner;
26
private Calendar startTime;
27
private String txUuid;
28
private StopWatch stopWatch;
30
private volatile long splitTime = 0l;
31
public TxHandle( String ctx ) {
32
this.txUuid = String.format("%s:%s:%s",ctx, DebugUtil.TRACE ? EntityWrapper.getMyStackTraceElement( ) : "n.a", UUID.randomUUID( ).toString( ) );
33
this.startTime = Calendar.getInstance( );
34
this.stopWatch = new StopWatch( );
35
this.stopWatch.start( );
36
EntityManagerFactory anemf = ( EntityManagerFactoryImpl ) DatabaseUtil.getEntityManagerFactory( ctx );
38
this.em = anemf.createEntityManager( );
39
this.delegate = em.getTransaction( );
40
this.delegate.begin( );
41
this.session = new WeakReference<Session>(( Session ) em.getDelegate( ));
42
outstanding.put( txUuid, this );
43
} catch ( Throwable e ) {
46
throw new RuntimeException( e );
50
public boolean isExpired() {
51
long splitTime = split( );
52
return (splitTime-DatabaseUtil.MAX_OPEN_TIME)>this.startTime.getTimeInMillis( );
55
public long splitOperation( ) {
56
long oldSplit = splitTime;
57
this.stopWatch.split( );
58
splitTime = this.stopWatch.getSplitTime( );
59
this.stopWatch.unsplit( );
60
return splitTime - oldSplit;
63
public long split( ) {
64
this.stopWatch.split( );
65
splitTime = this.stopWatch.getSplitTime( );
66
this.stopWatch.unsplit( );
70
public void rollback( ) {
71
if( this.session != null ) {
72
this.session.clear( );
75
if ( this.delegate != null && this.delegate.isActive( ) ) {
76
this.delegate.rollback( );
78
} catch( Throwable e ) {
82
if( this.txUuid != null ) {
83
outstanding.remove( this.txUuid );
85
if( this.em != null ) {
92
private void verifyOpen( ) {
93
if( this.delegate == null || this.em == null ) {
94
throw new RuntimeException( "Calling a closed tx handle: " + this.txUuid );
98
public void commit( ) {
99
if( this.session != null ) {
100
this.session.clear( );
104
this.delegate.commit( );
105
} catch( RuntimeException e ) {
106
if( this.delegate != null && this.delegate.isActive( ) ) {
107
this.delegate.rollback( );
112
this.delegate = null;
113
outstanding.remove( this.txUuid );
114
if( this.em != null ) {
121
public static void printTxStatus( ) {
122
for ( String uuid : outstanding.keySet( ) ) {
123
TxHandle tx = outstanding.get( uuid );
124
if( tx.isExpired() ) {
125
LOG.error( LogUtil.subheader( "Long outstanding transaction handle for: " + uuid + " " + tx.txUuid ) );
126
outstanding.remove( uuid );
131
public String getTxUuid( ) {
136
public boolean getRollbackOnly( ) {
137
return delegate.getRollbackOnly( );
140
public boolean isActive( ) {
141
return delegate.isActive( );
144
public void setRollbackOnly( ) {
145
delegate.setRollbackOnly( );
148
public Session getSession( ) {
149
if( session.get( ) == null ) {
150
RuntimeException e = new RuntimeException( "Someone is calling a closed tx handle: " + this.txUuid );
154
return session.get( );
157
public Calendar getStartTime( ) {
161
public EntityManager getEntityManager( ) {
165
public void begin( ) {
170
public int hashCode( ) {
171
final int prime = 31;
173
result = prime * result + ( ( owner == null ) ? 0 : owner.hashCode( ) );
174
result = prime * result + ( ( startTime == null ) ? 0 : startTime.hashCode( ) );
179
public boolean equals( Object obj ) {
180
if ( this == obj ) return true;
181
if ( obj == null ) return false;
182
if ( getClass( ) != obj.getClass( ) ) return false;
183
TxHandle other = ( TxHandle ) obj;
184
if ( owner == null ) {
185
if ( other.owner != null ) return false;
186
} else if ( !owner.equals( other.owner ) ) return false;
187
if ( startTime == null ) {
188
if ( other.startTime != null ) return false;
189
} else if ( !startTime.equals( other.startTime ) ) return false;
194
public int compareTo( TxHandle o ) {
195
return this.startTime.compareTo( o.getStartTime( ) );