KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > mapper > lib > JormStorageManager


1 /**
2  * Copyright (C) 2001-2004 France Telecom R&D
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package org.objectweb.speedo.mapper.lib;
19
20 import org.objectweb.perseus.persistence.api.StorageManager;
21 import org.objectweb.perseus.persistence.api.PersistenceException;
22 import org.objectweb.perseus.persistence.api.NoDSIPersistenceException;
23 import org.objectweb.perseus.persistence.api.ConnectionHolder;
24 import org.objectweb.perseus.persistence.api.WorkingSet;
25 import org.objectweb.perseus.persistence.api.State;
26 import org.objectweb.jorm.api.PException;
27 import org.objectweb.jorm.api.PBinding;
28 import org.objectweb.jorm.api.PExceptionNoDSI;
29 import org.objectweb.jorm.api.PAccessor;
30 import org.objectweb.jorm.naming.api.PName;
31 import org.objectweb.fractal.api.control.BindingController;
32 import org.objectweb.util.monolog.api.Logger;
33 import org.objectweb.util.monolog.api.BasicLevel;
34 import org.objectweb.speedo.api.ExceptionHelper;
35 import org.objectweb.speedo.mapper.api.JormFactory;
36 import org.objectweb.speedo.mim.api.LifeCycle;
37 import org.objectweb.speedo.mim.api.SpeedoAccessor;
38 import org.objectweb.speedo.mim.api.SpeedoProxy;
39
40 import javax.jdo.listener.InstanceLifecycleEvent;
41
42 import java.util.Iterator JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.HashMap JavaDoc;
45 import java.util.HashSet JavaDoc;
46 import java.util.Set JavaDoc;
47
48
49 /**
50  * This class is an implementation of the StorageManager interface based on
51  * Jorm.The single hypothesis concerns the architecture of the CacheEntry:
52  * - the CacheEntry implements the PBinding interface
53  * - the obj parameters implement State and PAceessor.
54  *
55  * @author S.Chassande-Barrioz
56  */

57 public class JormStorageManager
58         implements StorageManager, BindingController {
59
60     public final static String JavaDoc JORM_FACTORY_BINDING = "jorm-factory";
61     public final static String JavaDoc LOGGER_NAME = "org.objectweb.jorm.storageManager";
62
63     protected JormFactory jormFactory = null;
64
65     protected Logger logger = null;
66
67     /**
68      * listes for each working set the persistent object removed in other
69      * working set. When a working set want to read a persistent object from
70      * the data support, a prefetch buffer can be used. But the prefetch buffer
71      * can contains a removed object.
72      */

73     protected Map JavaDoc ws2removedpo = new HashMap JavaDoc();
74     
75     //IMPLEMENTATION OF THE UserBindingControler INTERFACE //
76
//------------------------------------------------------//
77

78     public String JavaDoc[] listFc() {
79         return new String JavaDoc[] { JORM_FACTORY_BINDING };
80     }
81
82     public Object JavaDoc lookupFc(String JavaDoc s) {
83         if (JORM_FACTORY_BINDING.equals(s)) {
84             return jormFactory;
85         }
86         return null;
87     }
88
89     public void bindFc(String JavaDoc s, Object JavaDoc o) {
90         if ("logger".equals(s)) {
91             logger = (Logger) o;
92         } else if (JORM_FACTORY_BINDING.equals(s)) {
93             jormFactory = (JormFactory) o;
94         }
95     }
96
97     public void unbindFc(String JavaDoc s) {
98         if (JORM_FACTORY_BINDING.equals(s)) {
99             jormFactory = null;
100         }
101     }
102
103
104     //IMPLEMENTATION OF THE StorageManager INTERFACE //
105
//-----------------------------------------------//
106

107     public Object JavaDoc export(ConnectionHolder context, Object JavaDoc obj) throws PersistenceException {
108         PBinding pb = (PBinding) obj;
109         try {
110             if (pb.getStatus() == PBinding.LIFECYCLE_DELTOWRITE) {
111                 pb.write(context, (PAccessor) obj);
112             }
113             return pb.export(context);
114         } catch (PException e) {
115             throw new PersistenceException(e);
116         }
117     }
118
119     public Object JavaDoc export(ConnectionHolder context, Object JavaDoc obj, Object JavaDoc hints) throws PersistenceException {
120         PBinding pb = (PBinding) obj;
121         try {
122             if (pb.getStatus() == PBinding.LIFECYCLE_DELTOWRITE) {
123                 pb.write(context, (PAccessor) obj);
124             }
125             return pb.export(context, hints);
126         } catch (PException e) {
127             throw new PersistenceException(e);
128         }
129     }
130
131     public void unexport(ConnectionHolder context, Object JavaDoc oid) throws PersistenceException {
132         if (logger.isLoggable(BasicLevel.DEBUG)) {
133             logger.log(BasicLevel.DEBUG,
134                     "unexport ctx=" + context + " / oid=" + oid);
135         }
136         try {
137             ((PName) oid).unexport(context);
138         } catch (PException e) {
139             throw new PersistenceException(e);
140         }
141         registerUnexport(context.getWorkingSet(), oid);
142     }
143
144     public void unexport(ConnectionHolder context, Object JavaDoc oid, Object JavaDoc hints) throws PersistenceException {
145         if (logger.isLoggable(BasicLevel.DEBUG)) {
146             logger.log(BasicLevel.DEBUG,
147                     "unexport(hints) ctx=" + context + " / oid=" + oid);
148         }
149         try {
150             ((PName) oid).unexport(context, hints);
151         } catch (PException e) {
152             throw new PersistenceException(e);
153         }
154         registerUnexport(context.getWorkingSet(), oid);
155     }
156
157     public void read(ConnectionHolder context, Object JavaDoc oid, State obj) throws PersistenceException {
158         if (logger.isLoggable(BasicLevel.DEBUG))
159             logger.log(BasicLevel.DEBUG, "read ctx=" + context
160                     + " / oid=" + oid
161                     + " / obj.class=" + obj.getClass().getName());
162         SpeedoProxy pb = (SpeedoProxy) obj.getCacheEntry();
163         int jdoStatus = ((SpeedoAccessor) obj).jdoGetStatus();
164         if (pb.getStatus() == PBinding.LIFECYCLE_DELTOWRITE
165                 && jdoStatus != LifeCycle.PERSISTENT_DELETED
166                 && jdoStatus != LifeCycle.PERSISTENT_NEW_DELETED) {
167             throw new PersistenceException(
168                     "Concurrency problem, transaction must be rolledback");
169         }
170         try {
171             pb.read(context, (PAccessor) obj);
172             //modified with rebind
173
((SpeedoAccessor) obj).indexFieldModified(Integer.MAX_VALUE, true);
174             pb.getSpeedoHome().sendEvent(InstanceLifecycleEvent.LOAD, pb, null, false);
175         } catch (PExceptionNoDSI e) {
176             if (logger.isLoggable(BasicLevel.DEBUG)) {
177                 logger.log(BasicLevel.DEBUG, "read ==> NO DSI");
178             }
179             throw new NoDSIPersistenceException(e);
180         } catch (PException e) {
181             Exception JavaDoc ie = ExceptionHelper.getNested(e);
182             logger.log(BasicLevel.ERROR, "read ctx=" + context
183                         + " / oid=" + oid
184                         + " / obj.class=" + obj.getClass().getName(), ie);
185             throw new PersistenceException(ie);
186         }
187     }
188
189     public void read(WorkingSet ws, Object JavaDoc oid, State obj) throws PersistenceException {
190         Object JavaDoc conn = ws.getConnectionHolder().getCHConnectionForRead();
191         if (logger.isLoggable(BasicLevel.DEBUG))
192             logger.log(BasicLevel.DEBUG, "read conn=" + conn
193                     + " / oid=" + oid
194                     + " / obj.class=" + obj.getClass().getName()
195                     + " / tx=" + ws);
196         SpeedoProxy pb = (SpeedoProxy) obj.getCacheEntry();
197         int jdoStatus = ((SpeedoAccessor) obj).jdoGetStatus();
198         if (pb.getStatus() == PBinding.LIFECYCLE_DELTOWRITE
199                 && jdoStatus != LifeCycle.PERSISTENT_DELETED
200                 && jdoStatus != LifeCycle.PERSISTENT_NEW_DELETED) {
201             throw new PersistenceException(
202                     "Concurrency problem, transaction must be rolledback");
203         }
204         Object JavaDoc ctx = usePrefetchBuffer(ws, oid) ? ws : null;
205         try {
206             pb.read(conn, (PAccessor) obj, ctx);
207             //modified with rebind
208
((SpeedoAccessor) obj).indexFieldModified(Integer.MAX_VALUE, true);
209             pb.getSpeedoHome().sendEvent(InstanceLifecycleEvent.LOAD, pb, null, false);
210         } catch (PExceptionNoDSI e) {
211             if (logger.isLoggable(BasicLevel.DEBUG)) {
212                 logger.log(BasicLevel.DEBUG, "read ==> NO DSI");
213             }
214             throw new NoDSIPersistenceException(e);
215         } catch (PException e) {
216             Exception JavaDoc ie = ExceptionHelper.getNested(e);
217             logger.log(BasicLevel.ERROR, "read conn=" + conn
218                     + " / oid=" + oid
219                     + " / obj.class=" + obj.getClass().getName()
220                     + " / tx=" + ws, ie);
221             throw new PersistenceException(ie);
222         }
223     }
224
225     public void write(ConnectionHolder context, Object JavaDoc oid, State obj) throws PersistenceException {
226         SpeedoProxy pb = (SpeedoProxy) obj.getCacheEntry();
227         if (logger.isLoggable(BasicLevel.DEBUG)) {
228             logger.log(BasicLevel.DEBUG, "write ctx=" + context
229                     + " / oid=" + oid
230                     + " / obj.class=" + obj.getClass().getName()
231                     + " / binding.status=" + pb.getStatus());
232         }
233         int s = pb.getStatus();
234         if (s == PBinding.LIFECYCLE_ACTIVEFORIO
235                 || s == PBinding.LIFECYCLE_NEWTOWRITE
236                 || s == PBinding.LIFECYCLE_DELTOWRITE) {
237             if (s != PBinding.LIFECYCLE_DELTOWRITE) {
238                 pb.getSpeedoHome().sendEvent(InstanceLifecycleEvent.STORE, pb, null, true);
239             }
240             try {
241                 pb.write(context, (PAccessor) obj);
242             } catch (PExceptionNoDSI e) {
243                 throw new NoDSIPersistenceException(e);
244             } catch (PException e) {
245                 throw new PersistenceException(e);
246             }
247             if (s != PBinding.LIFECYCLE_DELTOWRITE) {
248                 pb.getSpeedoHome().sendEvent(InstanceLifecycleEvent.STORE, pb, null, false);
249             }
250         }
251     }
252
253     public void beginWS(WorkingSet ws) {
254         synchronized(ws2removedpo) {
255             ws2removedpo.put(ws, new RemovedPOMemento(ws));
256             if (logger.isLoggable(BasicLevel.DEBUG)) {
257                 logger.log(BasicLevel.DEBUG, "Begin of WS"
258                         + "\n\t-ws=" + ws);
259             }
260         }
261     }
262
263     /**
264      * forget the working set
265      */

266     public void endWS(WorkingSet ws) {
267         synchronized(ws2removedpo) {
268             RemovedPOMemento mem = (RemovedPOMemento) ws2removedpo.remove(ws);
269             StringBuffer JavaDoc sb = null;
270             if (mem.removedPOFromWS != null) {
271                 for (Iterator JavaDoc it = ws2removedpo.values().iterator(); it.hasNext();) {
272                     RemovedPOMemento _mem = (RemovedPOMemento) it.next();
273                     _mem.addRemovedPOFromOtherWS(mem.removedPOFromWS);
274                     if (logger.isLoggable(BasicLevel.DEBUG)) {
275                         if (sb == null) {
276                             sb = new StringBuffer JavaDoc();
277                             sb.append("Add\n\t-oids= ");
278                             sb.append(mem.removedPOFromWS);
279                         }
280                         sb.append("\n\t-ws= " + _mem.ws);
281                     }
282                 }
283                 if (logger.isLoggable(BasicLevel.DEBUG)) {
284                     logger.log(BasicLevel.DEBUG, sb.toString());
285                 }
286             }
287         }
288     }
289
290     private void registerUnexport(WorkingSet ws, Object JavaDoc oid) {
291         synchronized(ws2removedpo) {
292             ((RemovedPOMemento) ws2removedpo.get(ws)).registerRemovedPOFromWS(oid);
293             if (logger.isLoggable(BasicLevel.DEBUG)) {
294                 logger.log(BasicLevel.DEBUG, "Register the removed object:"
295                         + "\n\t-oid=" + oid
296                         + "\n\t-ws=" + ws);
297             }
298         }
299     }
300     
301     /**
302      * check if the persistent object has not been removed in another context.
303      * Indeed in case of Jorm uses prefetch buffers, the persistent will be
304      * loaded even if it has been removed from the data base.
305      **/

306     private boolean usePrefetchBuffer(WorkingSet ws, Object JavaDoc oid) {
307         synchronized(ws2removedpo) {
308             boolean res = !((RemovedPOMemento) ws2removedpo.get(ws)).isRemoved(oid);
309             if (logger.isLoggable(BasicLevel.DEBUG)) {
310                 logger.log(BasicLevel.DEBUG,(res ? "": "NOT " ) + "USE prefetch buffer"
311                         + "\n\t-oid=" + oid
312                         + "\n\t-ws= " + ws);
313             }
314             return res;
315         }
316     }
317 }
318 /**
319  * This structure registers the removed objects from a particular working set.
320  * So an instance of this class has to be associated to a working set.
321  *
322  * @author S.Chassande-Barrioz
323  */

324 class RemovedPOMemento {
325     /**
326      * contains the identifiers of persitent objects which have been removed
327      * from the working set linked to this.
328      * this field is used at the end of a working set to transmit the list of
329      * removed object from this working set.
330      */

331     public HashSet JavaDoc removedPOFromWS = null;
332     
333     /**
334      * contains the identifiers of persistent objects which have been removed
335      * from the working set linked to this or from another working set.
336      * this field is used to choose if it is possible to use a prefetch buffer
337      * for a given identifier
338      */

339     public HashSet JavaDoc removedPO = null;
340     
341     public final WorkingSet ws;
342     
343     public RemovedPOMemento(WorkingSet _ws) {
344         this.ws = _ws;
345     }
346     
347     /**
348      * register the unexport of a persistent object from the linked working set
349      * @param oid is the identifier of the unexported persistent object
350      */

351     public void registerRemovedPOFromWS(Object JavaDoc oid) {
352         if (removedPOFromWS == null) {
353             removedPOFromWS = new HashSet JavaDoc();
354         }
355         removedPOFromWS.add(oid);
356         if (removedPO == null) {
357             removedPO = new HashSet JavaDoc();
358         }
359         removedPO.add(oid);
360     }
361     
362     /**
363      * Keeps in memory that persistent objects has been removed from another
364      * working set
365      * @param oids is the set of identifier of persistent object which have
366      * been unexported in another working set.
367      */

368     public void addRemovedPOFromOtherWS(Set oids) {
369         if (removedPO == null) {
370             removedPO = new HashSet JavaDoc();
371         }
372         removedPO.addAll(oids);
373     }
374     
375     /**
376      * Indicates if a persistent object has been removed from the current
377      * working set or another.
378      * @param oid is the identifier of the persistent object which could be
379      * previously removed.
380      */

381     public boolean isRemoved(Object JavaDoc oid) {
382         return removedPO != null && removedPO.contains(oid);
383     }
384 }
385
Popular Tags