1 /**
2  *  Copyright Terracotta, Inc.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */

16 package net.sf.ehcache.transaction;
17
18 import net.sf.ehcache.Ehcache;
19 import net.sf.ehcache.FeaturesManager;
20 import net.sf.ehcache.terracotta.ClusteredInstanceFactory;
21 import net.sf.ehcache.terracotta.TerracottaClient;
22 import net.sf.ehcache.transaction.xa.XidTransactionID;
23
24 import java.util.Set;
25 import java.util.UUID;
26 import java.util.concurrent.atomic.AtomicReference;
27
28 import javax.transaction.xa.Xid;
29
30 /**
31  * A TransactionIDFactory implementation with delegates calls to either a clustered
32  * or non-clustered factory
33  *
34  * @author Ludovic Orban
35  */

36 public class DelegatingTransactionIDFactory implements TransactionIDFactory {
37
38     private final FeaturesManager featuresManager;
39     private final TerracottaClient terracottaClient;
40     private final String cacheManagerName;
41     private volatile ClusteredInstanceFactory clusteredInstanceFactory;
42     private volatile AtomicReference<TransactionIDFactory> transactionIDFactory = new AtomicReference<TransactionIDFactory>();
43
44     /**
45      * Create a new DelegatingTransactionIDFactory
46      *
47      * @param terracottaClient a terracotta client
48      * @param cacheManagerName the name of the cache manager which creates this.
49      */

50     public DelegatingTransactionIDFactory(FeaturesManager featuresManager, TerracottaClient terracottaClient, String cacheManagerName) {
51         this.featuresManager = featuresManager;
52         this.terracottaClient = terracottaClient;
53         this.cacheManagerName = cacheManagerName;
54     }
55
56     private TransactionIDFactory get() {
57         ClusteredInstanceFactory cif = terracottaClient.getClusteredInstanceFactory();
58         if (cif != null && cif != this.clusteredInstanceFactory) {
59             this.transactionIDFactory.set(cif.createTransactionIDFactory(UUID.randomUUID().toString(), cacheManagerName));
60             this.clusteredInstanceFactory = cif;
61         }
62
63         if (transactionIDFactory.get() == null) {
64             TransactionIDFactory constructed;
65             if (featuresManager == null) {
66                 constructed = new TransactionIDFactoryImpl();
67             } else {
68                 constructed = featuresManager.createTransactionIDFactory();
69             }
70             if (transactionIDFactory.compareAndSet(null, constructed)) {
71                 return constructed;
72             } else {
73                 return transactionIDFactory.get();
74             }
75         } else {
76             return transactionIDFactory.get();
77         }
78     }
79
80     /**
81      * {@inheritDoc}
82      */

83     public TransactionID createTransactionID() {
84         return get().createTransactionID();
85     }
86
87     /**
88      * {@inheritDoc}
89      */

90     public TransactionID restoreTransactionID(TransactionIDSerializedForm serializedForm) {
91         return get().restoreTransactionID(serializedForm);
92     }
93
94     /**
95      * {@inheritDoc}
96      */

97     public XidTransactionID createXidTransactionID(Xid xid, Ehcache cache) {
98         return get().createXidTransactionID(xid, cache);
99     }
100
101     /**
102      * {@inheritDoc}
103      */

104     public XidTransactionID restoreXidTransactionID(XidTransactionIDSerializedForm serializedForm) {
105         return get().restoreXidTransactionID(serializedForm);
106     }
107
108     @Override
109     public void markForCommit(TransactionID transactionID) {
110         get().markForCommit(transactionID);
111     }
112
113     @Override
114     public void markForRollback(XidTransactionID transactionID) {
115         get().markForRollback(transactionID);
116     }
117
118     @Override
119     public boolean isDecisionCommit(TransactionID transactionID) {
120         return get().isDecisionCommit(transactionID);
121     }
122
123     @Override
124     public void clear(TransactionID transactionID) {
125         get().clear(transactionID);
126     }
127
128     @Override
129     public Set<XidTransactionID> getAllXidTransactionIDsFor(Ehcache cache) {
130         return get().getAllXidTransactionIDsFor(cache);
131     }
132
133     @Override
134     public Set<TransactionID> getAllTransactionIDs() {
135         return get().getAllTransactionIDs();
136     }
137
138     @Override
139     public boolean isExpired(TransactionID transactionID) {
140         return get().isExpired(transactionID);
141     }
142
143     @Override
144     public Boolean isPersistent() {
145         if (transactionIDFactory.get() == null) {
146             return null;
147         } else {
148             return get().isPersistent();
149         }
150     }
151 }
152