KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > perseus > fos > lib > FosTxContextFactory


1 /**
2  * Copyright (C) 2000
3  */

4
5 package org.objectweb.perseus.fos.lib;
6
7 import org.objectweb.perseus.fos.api.FosException;
8 import org.objectweb.perseus.fos.api.FosLoggerFactory;
9 import org.objectweb.perseus.fos.api.FosManager;
10 import org.objectweb.perseus.fos.api.FosTransaction;
11 import org.objectweb.util.monolog.api.BasicLevel;
12 import org.objectweb.util.monolog.api.Logger;
13 import org.objectweb.util.monolog.api.MonologFactory;
14
15 import java.io.File JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import javax.transaction.xa.Xid JavaDoc;
18
19 /**
20  * @author S. Chassande-Barrioz, P. D�chamboux
21  */

22 public class FosTxContextFactory implements FosManager, FosLoggerFactory {
23     /**
24      * The directory under dbDir into which log files are stored.
25      */

26     private final static String JavaDoc TXDIR = ".fostx";
27     /**
28      * For creating all loggers related to FOS and its adapter.
29      */

30     private MonologFactory loggerFactory;
31     /**
32      * The logger into which traces about FosTxContextFactory are produced.
33      */

34     private Logger logger;
35     /**
36      * The logger into which traces about FosTxContext are produced.
37      */

38     private Logger entityLogger;
39     /**
40      * The directory under which is stored all information related to the FOS.
41      */

42     private String JavaDoc dbDir = null;
43     /**
44      * The next transaction identifier to be delivered.
45      */

46     private long txId;
47     /**
48      * The transactions that have been created and not released.
49      */

50     private ArrayList JavaDoc txList;
51     /**
52      * The list of Xid of distributed transactions that need to be recovered.
53      */

54     private ArrayList JavaDoc xidList = null;
55     /**
56      *
57      */

58     private int nbActiveTx = 0;
59
60     /**
61      * Starts a FosTxContextFactory. It either initializes the FOS repository
62      * if it is the first start. In other cases, it verifies the consistency
63      * of the repository and it manages a cold recovery if the FOS had not
64      * cleanly stop.
65      */

66     public synchronized void start() throws FosException {
67         if (loggerFactory == null)
68             throw new FosException("MonologFactory required to execute a FosManager.");
69         if (dbDir == null)
70             throw new FosException("DbDir required to execute a FosManager.");
71         if (!new File JavaDoc(dbDir).exists())
72             throw new FosException("DbDir [" + dbDir + "] must exist for activating FOS.");
73         logger = getLogger(FosLoggerFactory.TXCONTEXT, true);
74         entityLogger = getLogger(FosLoggerFactory.TXCONTEXT, false);
75         txId = 0;
76         txList = new ArrayList JavaDoc();
77         File JavaDoc txdir = new File JavaDoc(dbDir + File.separator + TXDIR);
78         if (FosLoggerFactory.DEBUG)
79             logger.log(BasicLevel.DEBUG, "START operation: dbdir=\"" + dbDir + "\"");
80         if (txdir.exists()) {
81             if (FosLoggerFactory.DEBUG)
82                 logger.log(BasicLevel.DEBUG, "TX directory already exists.");
83             if (!txdir.isDirectory())
84                 throw new FosException("TxDir not a directory - see: " + txdir.getPath());
85             // Performs the cold recovery phase
86
String JavaDoc[] txids = txdir.list();
87             FosTxContext txc;
88             Xid JavaDoc xid;
89             for (int i = 0; i < txids.length; i++) {
90                 txc = new FosTxContext(entityLogger, this);
91                 xid = txc.recover(dbDir + File.separator + TXDIR + File.separator
92                     + txids[i]);
93                 if (xid != null) {
94                     if (FosLoggerFactory.DEBUG)
95                         logger.log(BasicLevel.DEBUG, "Need DTP recovery for TX: " + xid);
96                     if (xidList == null)
97                         xidList = new ArrayList JavaDoc();
98                     xidList.add(xid);
99                 }
100             }
101         } else {
102             // First activation: initializes TXDIR
103
if (FosLoggerFactory.DEBUG)
104                 logger.log(BasicLevel.DEBUG, "TX directory does not exist: creates it.");
105             txdir.mkdir();
106         }
107         logger.log(BasicLevel.INFO,
108             "FosTxContextFactory started: dbDir is <" + dbDir + ">.");
109     }
110
111     /**
112      * Stops a FosTxContextFactory.
113      */

114     public synchronized void stop() throws FosException {
115         if (txList == null)
116             throw new FosException("FOS manager has not been started.");
117         if (txList.size() > 0)
118             throw new FosException("There are still transactions to be released.");
119         txList = null;
120     }
121
122     /**
123      * Delivers a new transaction identifier.
124      */

125     String JavaDoc getTxId() {
126         String JavaDoc res = dbDir + File.separator + TXDIR + File.separator
127             + Long.toString(txId);
128         if (txId == Long.MAX_VALUE)
129             txId = 0;
130         else
131             txId++;
132         return res;
133     }
134
135     /**
136      * Recursively deletes the content of a directory.
137      */

138     void deleteDirContent(File JavaDoc dir) throws Exception JavaDoc {
139         File JavaDoc lf[] = dir.listFiles();
140         for (int i = 0; i < lf.length; i++) {
141             if (lf[i].isDirectory()) {
142                 deleteDirContent(lf[i]);
143             }
144             lf[i].delete();
145         }
146     }
147
148     /**
149      * Activates or deactivates a transaction wrt to the number of active
150      * transactions.
151      * @param activate If true, handles a new active transaction. Otherwise,
152      * handles the inactivation of a transaction.
153      */

154     synchronized void setActiveTX(boolean activate) {
155         if (activate)
156             nbActiveTx++;
157         else
158             nbActiveTx--;
159     }
160
161     /**
162      * Gets the number of active transactions.
163      */

164     int getNbActiveTX() {
165         return nbActiveTx;
166     }
167
168     // IMPLEMENTATION OF METHODS FROM THE FosManager INTERFACE
169

170     /**
171      * Initializes the root directory for storing files representing data
172      * objects. It removes all existing data files and creates all data for
173      * managing transactions.
174      */

175     public synchronized void initialize() throws FosException {
176         if (loggerFactory == null)
177             throw new FosException("MonologFactory required to execute a FosManager.");
178         if (dbDir == null)
179             throw new FosException("DbDir required to execute a FosManager.");
180         File JavaDoc dbdf = new File JavaDoc(dbDir);
181         if (!dbdf.exists())
182             throw new FosException("DbDir [" + dbDir + "] must exist for initializing FOS.");
183         logger = getLogger(FosLoggerFactory.TXCONTEXT, true);
184         entityLogger = getLogger(FosLoggerFactory.TXCONTEXT, false);
185         File JavaDoc txdir = new File JavaDoc(dbDir + File.separator + TXDIR);
186         if (FosLoggerFactory.DEBUG)
187             logger.log(BasicLevel.DEBUG, "INITIALIZE operation: dbdir=\"" + dbDir + "\"");
188         try {
189             File JavaDoc lf[] = dbdf.listFiles();
190             for (int i = 0; i < lf.length; i++) {
191                 if (lf[i].isDirectory()) {
192                     deleteDirContent(lf[i]);
193                 }
194                 lf[i].delete();
195             }
196         } catch (Exception JavaDoc e) {
197             throw new FosException("Problem during DbDir initialization.", e);
198         }
199     }
200
201     /**
202      * Gets all the Xid of distributed transaction that need to be recovered
203      * by a DTP monitor.
204      * @return The array of Xid of transactions that need to be recovered.
205      */

206     public Xid JavaDoc[] getXidForRecovery() {
207         Xid JavaDoc[] res;
208         if (xidList == null)
209             res = new Xid JavaDoc[0];
210         res = (Xid JavaDoc[]) xidList.toArray();
211         xidList = null;
212         return res;
213     }
214
215     /**
216      * Creates a new TxContext for managing transactional I/Os with Data Object
217      * Files.
218      */

219     public synchronized FosTransaction createTxContext() throws FosException {
220         if (xidList != null)
221             throw new FosException("Cannot use FOS while distributed TX need to be recovered.");
222         FosTransaction res = new FosTxContext(entityLogger, this);
223         if (FosLoggerFactory.DEBUG)
224             logger.log(BasicLevel.DEBUG, "Creates a new TxContext: " + res);
225         txList.add(res);
226         return res;
227     }
228
229     /**
230      * Releases a FosTxContext. Useful if adding a context pool.
231      * @param txc The FosTxContext to be released.
232      */

233     public synchronized void releaseTxContext(FosTransaction txc) throws FosException {
234         if (FosLoggerFactory.DEBUG)
235             logger.log(BasicLevel.DEBUG, "Releases TxContext: " + txc);
236         if (!txList.contains(txc))
237             throw new FosException("Transaction not created with this factory.");
238         if (txc.isActive()) {
239             if (!((FosTxContext) txc).isPrepared()) {
240                 logger.log(BasicLevel.WARN, "Releases active transaction: " + txc
241                     + " - forces rollback!!");
242                 txc.rollback();
243             } else {
244                 if (((FosTxContext) txc).getXid() == null) {
245                     logger.log(BasicLevel.WARN, "Releases prepared transaction: "
246                         + txc + " - forces commit!!");
247                     txc.commit();
248                 } else
249                     throw new FosException("Releases a prepared DTP transaction.");
250             }
251         }
252         txList.remove(txc);
253     }
254
255     // IMPLEMENTATION OF METHODS FROM THE FosAttributeControler INTERFACE
256

257     /**
258      * Gives access to the FOS root directory (named dbDir).
259      */

260     public String JavaDoc getDbDir() {
261         return dbDir;
262     }
263
264     /**
265      * Changes the FOS root directory.
266      */

267     public void setDbDir(String JavaDoc dbdir) {
268         dbDir = dbdir;
269     }
270
271
272     // IMPLEMENTATION OF METHODS FROM THE FosLoggerFactory INTERFACE
273

274     /**
275      * Gives access to the logger associated to a given kind of entities managed
276      * by this FOS adapter, which are further classified into factories or
277      * non-factories.
278      * @param entity The kind of entity (see CONNECTION, MANAGEDCONNECTION,
279      * XARESOURCE and TXCONTEXT constants defined above).
280      * @param factory Specifies if the concerned entity is a factory.
281      * @return The relevant logger.
282      */

283     public Logger getLogger(byte entity, boolean factory) {
284         String JavaDoc res = "org.objectweb.perseus.jdo.fos[dbDir=" + dbDir + "]";
285         if (factory)
286             res += ".fact";
287         else
288             res += ".inst";
289         switch (entity) {
290         case FosLoggerFactory.CONNECTION:
291             res += ".connx";
292             break;
293         case FosLoggerFactory.MANAGEDCONNECTION:
294             res += ".mancn";
295             break;
296         case FosLoggerFactory.XARESOURCE:
297             res += ".xares";
298             break;
299         case FosLoggerFactory.TXCONTEXT:
300             res += ".txctx";
301             break;
302         default :
303             ;
304         }
305         return loggerFactory.getLogger(res);
306     }
307
308     public void setMonologFactory(MonologFactory mf) {
309         loggerFactory = mf;
310     }
311 }
312
Popular Tags