Source code: org/mobicents/slee/runtime/SbbEntityFactory.java
1 /*
2 * Created on Feb 3, 2005
3 *
4 * The Mobicents Open SLEE Project
5 *
6 * A SLEE for the People
7 *
8 * The source code contained in this file is in in the public domain.
9 * It can be used in any project or product without prior permission,
10 * license or royalty payments. There is no claim of correctness and
11 * NO WARRANTY OF ANY KIND provided with this code.
12 */
13 package org.mobicents.slee.runtime;
14
15 import java.rmi.dgc.VMID;
16 import java.util.HashMap;
17
18 import javax.slee.SbbID;
19 import javax.slee.ServiceID;
20 import javax.transaction.SystemException;
21
22 import org.jboss.logging.Logger;
23 import org.mobicents.slee.container.SleeContainer;
24 import org.mobicents.slee.runtime.SbbEntity.PrepareAction;
25 import org.mobicents.slee.runtime.transaction.TransactionManagerImpl;
26
27 /**
28 *
29 * SbbEntityFactory -- implements a map from SBB Entity Id to SBB Entity instances.
30 * This is the sole place where Sbb Entities are created and destroyed.
31 * We keep a map of SBB Entity ID to SBB Entity here and return Sbb Entities that
32 * are stored in this map.
33 *
34 * @author F.Moggia
35 * @author M. Ranganathan
36 * @author Tim Fox ( streamlining )
37 */
38 public class SbbEntityFactory {
39
40 /* NB!! We must not a map to cache sbb entities.
41 * There can be multiple active transactions each of which accesses the same sbb entity
42 * at any one time in the SLEE.
43 * Therefore, by using a map to store the sbb entities one tx can see the transactional
44 * state of the other tx before it has committed.
45 * I.e. we would have no transaction isolation.
46 * Instead, if we want to cache the sbb entity for the lifetime of the tx for
47 * performance reasons, we need to store in a *per transaction* cache
48 */
49
50 private static String tcache = TransactionManagerImpl.TCACHE;
51
52 private SleeContainer serviceContainer;
53
54 //private static int counter;
55
56 private static Logger log = Logger.getLogger(SbbEntityFactory.class);
57
58
59 public SbbEntityFactory(SleeContainer container) {
60 this.serviceContainer = container;
61 }
62
63 private String genId()
64 {
65 //Use a GUID for the sbb entity id - a counter won't work in a cluster
66 VMID vmid = new VMID();
67 return vmid.toString();
68 }
69
70 public SbbEntity createSbbEntity(SbbID sbbId, ServiceID svcId,
71 String parentSbbEntityId, String convergenceName) {
72 try {
73 String sbbeId = genId();
74 log.debug("createSbbEntity: Creating non-root sbb entity with id:" + sbbeId);
75
76 SbbEntity sbbe = new SbbEntity(this.serviceContainer, sbbeId,
77 sbbId, convergenceName, svcId);
78 sbbe.setParentSbbEntity(parentSbbEntityId);
79 sbbe.setRootSbbId(this.serviceContainer.getService(svcId)
80 .getRootSbbEntityId(convergenceName));
81
82 // storing in cache is deferred until successful commit.
83
84 log.debug("Putting it in the map");
85 putInTxCache(sbbeId, sbbe);
86 return sbbe;
87 } catch (Exception ex) {
88 String s = "unexpected error in creating sbbEntity!";
89 log.error(s,ex);
90 throw new RuntimeException(s, ex);
91 }
92 }
93
94 public SbbEntity createRootSbbEnity(SbbID sbbId, ServiceID svcId,
95 String convergenceName) {
96 try {
97 String sbbeId = genId();
98
99 log.debug("Creating root sbb entity with id:" + sbbeId);
100
101 SbbEntity sbbe = new SbbEntity(this.serviceContainer, sbbeId,
102 sbbId, convergenceName, svcId);
103 sbbe.setParentSbbEntity(sbbeId);
104 sbbe.setRootSbbId(sbbeId);
105 // Defer the store to cache until the enclosing tx commits.
106 log.debug("Putting it in the map");
107 putInTxCache(sbbeId, sbbe);
108 return sbbe;
109 } catch (Exception ex) {
110 String s = "unexpected exception in createSbbEntity";
111 log.error(s,ex);
112 throw new RuntimeException(s, ex);
113 }
114 }
115
116 private void putInTxCache(String sbbeID, SbbEntity sbb) {
117 try {
118
119 SleeContainer.getTransactionManager().putDeferredData("sbb" + sbbeID, sbb);
120
121 } catch (SystemException e) {
122 String s = "Failed to put sbb in tx cache";
123 log.error(s, e);
124 throw new RuntimeException(s, e);
125 }
126 }
127
128
129 /**
130 * Remove the entity id to entity map. Call this when destroying the
131 * sbb entity -- when we no longer need to hold a reference to it.
132 *
133 * @param sbbeId
134 */
135 public void removeFromCache(String sbbeId) {
136
137 try {
138 SleeContainer.getTransactionManager().removeDeferredData("sbb" + sbbeId);
139 } catch (SystemException e) {
140 String s = "Failed to remove sbb from tx cache";
141 log.error(s, e);
142 throw new RuntimeException(s, e);
143 }
144
145
146 }
147
148 /**
149 * Call this function when you want to get an instantiated SbbEntity from the
150 * cache.
151 *
152 * @param sbbeId
153 * @return
154 */
155 public SbbEntity getSbbEntity(String sbbeId) {
156
157 log.debug("getSbbEntity : " + sbbeId);
158
159 /* NB!! We must not use a map to cache sbb entities.
160 * There can be multiple active transactions each of which accesses the same sbb entity
161 * at any one time in the SLEE.
162 * Therefore, by using a map to store the sbb entities one tx can see the transactional
163 * state of the other tx before it has committed.
164 * I.e. we would have no transaction isolation.
165 * Instead, if we want to cache the sbb entity for the lifetime of the tx for
166 * performance reasons, we need to store in a *per transaction* cache
167 */
168
169 try {
170
171
172 //Look for it in the per transaction cache
173 SbbEntity sbb = (SbbEntity)SleeContainer.getTransactionManager().getDeferredData("sbb" + sbbeId);
174
175 if (sbb == null) {
176 //Load it from the treecache
177 log.debug("Cannot find sbb in per tx cache - loading from treecache");
178
179 sbb = new SbbEntity(this.serviceContainer, sbbeId);
180
181 SleeContainer.getTransactionManager().putDeferredData("sbb" + sbbeId, sbb);
182 } else {
183 log.debug("Found sbb in per tx cache");
184
185 }
186
187
188 return sbb;
189
190 } catch (SystemException e) {
191 String s = "Failed to get sbb from tx cache";
192 log.error(s, e);
193 throw new RuntimeException(s, e);
194 }
195
196 }
197
198 public boolean isStale(String sbbeId){
199 try {
200 return SleeContainer.getTransactionManager().getNode(tcache,"sbbentity" + "/" + sbbeId) == null;
201 } catch (SystemException e) {
202 // TODO Auto-generated catch block
203 String s = "failed to check cache";
204 log.error (s,e);
205 throw new RuntimeException(s,e);
206 }
207 }
208 }