1 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 ; 16 import java.util.ArrayList ; 17 import javax.transaction.xa.Xid ; 18 19 22 public class FosTxContextFactory implements FosManager, FosLoggerFactory { 23 26 private final static String TXDIR = ".fostx"; 27 30 private MonologFactory loggerFactory; 31 34 private Logger logger; 35 38 private Logger entityLogger; 39 42 private String dbDir = null; 43 46 private long txId; 47 50 private ArrayList txList; 51 54 private ArrayList xidList = null; 55 58 private int nbActiveTx = 0; 59 60 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 (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 (); 77 File txdir = new File (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 String [] txids = txdir.list(); 87 FosTxContext txc; 88 Xid 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 (); 98 xidList.add(xid); 99 } 100 } 101 } else { 102 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 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 125 String getTxId() { 126 String 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 138 void deleteDirContent(File dir) throws Exception { 139 File 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 154 synchronized void setActiveTX(boolean activate) { 155 if (activate) 156 nbActiveTx++; 157 else 158 nbActiveTx--; 159 } 160 161 164 int getNbActiveTX() { 165 return nbActiveTx; 166 } 167 168 170 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 dbdf = new File (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 txdir = new File (dbDir + File.separator + TXDIR); 186 if (FosLoggerFactory.DEBUG) 187 logger.log(BasicLevel.DEBUG, "INITIALIZE operation: dbdir=\"" + dbDir + "\""); 188 try { 189 File 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 e) { 197 throw new FosException("Problem during DbDir initialization.", e); 198 } 199 } 200 201 206 public Xid [] getXidForRecovery() { 207 Xid [] res; 208 if (xidList == null) 209 res = new Xid [0]; 210 res = (Xid []) xidList.toArray(); 211 xidList = null; 212 return res; 213 } 214 215 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 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 257 260 public String getDbDir() { 261 return dbDir; 262 } 263 264 267 public void setDbDir(String dbdir) { 268 dbDir = dbdir; 269 } 270 271 272 274 283 public Logger getLogger(byte entity, boolean factory) { 284 String 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 |