1 4 5 package org.objectweb.perseus.fos.lib; 6 7 import org.objectweb.perseus.fos.api.FosAccess; 8 import org.objectweb.perseus.fos.api.FosException; 9 import org.objectweb.perseus.fos.api.FosLoggerFactory; 10 import org.objectweb.perseus.fos.api.FosStructure; 11 import org.objectweb.perseus.fos.api.FosTransaction; 12 import org.objectweb.util.monolog.api.BasicLevel; 13 import org.objectweb.util.monolog.api.Logger; 14 15 import java.io.File ; 16 import java.io.ObjectInputStream ; 17 import java.io.IOException ; 18 import java.util.HashMap ; 19 import java.util.Iterator ; 20 import javax.transaction.xa.Xid ; 21 22 25 public class FosTxContext implements FosTransaction { 26 29 private Logger logger; 30 33 private FosTxContextFactory txContextFactory; 34 38 private Xid xid; 39 43 private boolean active; 44 47 private boolean prepared; 48 51 private boolean updated; 52 55 private HashMap fofList; 56 59 private FosLogFile logFile; 60 61 67 FosTxContext(Logger el, FosTxContextFactory ftcf) throws FosException { 68 logger = el; 69 txContextFactory = ftcf; 70 xid = null; 71 active = false; 72 prepared = false; 73 updated = false; 74 fofList = null; 75 logFile = null; 76 if (FosLoggerFactory.DEBUG) 77 logger.log(BasicLevel.DEBUG, "Constructs a new FosTxContext."); 78 } 79 80 84 private synchronized FosObjectFile getOf(String ofn) { 85 FosObjectFile fof = (FosObjectFile) fofList.get(ofn); 86 if (fof == null) { 87 fof = new FosObjectFile(ofn); 88 fofList.put(ofn, fof); 89 } 90 return fof; 91 } 92 93 96 boolean isPrepared() { 97 if (FosLoggerFactory.DEBUG) 98 logger.log(BasicLevel.DEBUG, "FOS Transaction " 99 + (prepared ? "prepared." : "not prepared.")); 100 return prepared; 101 } 102 103 106 Xid getXid() { 107 if (FosLoggerFactory.DEBUG) 108 logger.log(BasicLevel.DEBUG, "FOS Transaction DTP id: " + xid); 109 return xid; 110 } 111 112 117 Xid recover(String txid) throws FosException { 118 if (FosLoggerFactory.DEBUG) 119 logger.log(BasicLevel.DEBUG, "Recovers transaction: " + txid); 120 logFile = new FosLogFile(txid); 121 try { 122 logFile.recover(); 123 xid = logFile.getXid(); 124 prepared = logFile.isPrepared(); 125 Iterator it = logFile.iterateModifiedOf(); 126 FosObjectFile fof; 127 String ofn; 128 while (it.hasNext()) { 129 ofn = (String ) it.next(); 130 if (FosLoggerFactory.DEBUG) 131 logger.log(BasicLevel.DEBUG, "Recovers ObjectFile: " + ofn); 132 fof = new FosObjectFile(ofn); 133 fof.recover(); 134 if (!prepared) 135 fof.rollback(); 136 else if (xid == null) 137 fof.commit(); 138 } 139 if (prepared && (xid != null)) { 140 if (FosLoggerFactory.DEBUG) 141 logger.log(BasicLevel.DEBUG, "DTP - cannot do local decision: " + xid); 142 return xid; 143 } 144 logFile.completed(); 145 return null; 146 } catch (Exception e) { 147 throw new FosException("Cannot recover transaction [nested exception].", e); 148 } 149 } 150 151 153 156 public void begin() throws FosException { 157 begin(null); 158 } 159 160 165 public void begin(Xid xid) throws FosException { 166 if (FosLoggerFactory.DEBUG) 167 logger.log(BasicLevel.DEBUG, "Begins a FOS transaction - XID: " + xid); 168 txContextFactory.setActiveTX(true); 169 this.xid = xid; 170 active = true; 171 prepared = false; 172 updated = false; 173 fofList = new HashMap (); 174 if (xid != null) { 175 try { 176 logFile = new FosLogFile(txContextFactory.getTxId()); 177 logFile.writeXid(xid); 178 } catch (Exception e) { 179 throw new FosException("Cannot begin transaction [nested exception].", e); 180 } 181 } else 182 logFile = null; 183 } 184 185 189 public boolean isActive() { 190 if (FosLoggerFactory.DEBUG) 191 logger.log(BasicLevel.DEBUG, "FOS Transaction " 192 + (active ? "active." : "inactive.")); 193 return active; 194 } 195 196 200 public boolean prepare() throws FosException { 201 if (FosLoggerFactory.DEBUG) 202 logger.log(BasicLevel.DEBUG, "Prepares a FOS transaction - XID: " + xid); 203 prepared = true; 204 if (!updated) { 205 if (FosLoggerFactory.DEBUG) 206 logger.log(BasicLevel.DEBUG, "Read-Only transaction!"); 207 return true; 208 } 209 try { 210 if (logFile == null) { 211 logFile = new FosLogFile(txContextFactory.getTxId()); 212 logFile.writeXid(null); 213 } 214 Iterator it = fofList.values().iterator(); 215 while (it.hasNext()) 216 logFile.writeObjectFile(((FosObjectFile) it.next()).isModified()); 217 logFile.writeEnd(); 218 return false; 219 } catch (Exception e) { 220 throw new FosException("Cannot prepare transaction [nested exception].", e); 221 } 222 } 223 224 227 public void commit() throws FosException { 228 if (FosLoggerFactory.DEBUG) 229 logger.log(BasicLevel.DEBUG, "Commits a FOS transaction - XID: " + xid); 230 if (!active) 231 throw new FosException("Cannot commit inactive transaction."); 232 if (!prepared) 233 prepare(); 234 txContextFactory.setActiveTX(false); 235 try { 236 if (!updated) { 237 if (FosLoggerFactory.DEBUG) 238 logger.log(BasicLevel.DEBUG, "Read-Only transaction!"); 239 } else { 240 logFile.completed(); 241 Iterator it = fofList.values().iterator(); 242 while (it.hasNext()) 243 ((FosObjectFile) it.next()).commit(); 244 } 245 xid = null; 246 active = false; 247 prepared = false; 248 updated = false; 249 fofList = null; 250 logFile = null; 251 } catch (Exception e) { 252 throw new FosException("Cannot commit transaction [nested exception].", e); 253 } 254 } 255 256 259 public void rollback() throws FosException { 260 if (FosLoggerFactory.DEBUG) 261 logger.log(BasicLevel.DEBUG, "Rollbacks a FOS transaction - XID: " + xid); 262 if (!active) 263 throw new FosException("Cannot rollback inactive transaction."); 264 txContextFactory.setActiveTX(false); 265 try { 266 if (!updated) { 267 if (FosLoggerFactory.DEBUG) 268 logger.log(BasicLevel.DEBUG, "Read-Only transaction!"); 269 } else { 270 if (logFile != null) 271 logFile.completed(); 272 Iterator it = fofList.values().iterator(); 273 while (it.hasNext()) 274 ((FosObjectFile) it.next()).rollback(); 275 } 276 xid = null; 277 active = false; 278 prepared = false; 279 updated = false; 280 fofList = null; 281 logFile = null; 282 } catch (Exception e) { 283 throw new FosException("Cannot rollback transaction [nested exception].", e); 284 } 285 } 286 287 289 298 public boolean exist(String dirof, String id) throws FosException { 299 if (FosLoggerFactory.DEBUG) 300 logger.log(BasicLevel.DEBUG, "EXIST operation: dirof=\"" + dirof 301 + "\", id=\"" + id + "\""); 302 if (prepared || !active) 303 throw new FosException("FOS transaction context not ready to perform operations."); 304 FosObjectFile fof = getOf(txContextFactory.getDbDir() + File.separator 305 + dirof + File.separator + id); 306 if (FosLoggerFactory.DEBUG) 307 logger.log(BasicLevel.DEBUG, "Object " + (fof.exist() ? "exists" : "does not exist")); 308 return fof.exist(); 309 } 310 311 316 public boolean existDir(String dirof) throws FosException { 317 return (new File (txContextFactory.getDbDir() + File.separator + dirof)).exists(); 318 } 319 320 330 public void read(String dirof, String id, FosStructure fs, Object ctxt) 331 throws FosException { 332 read(dirof, id, fs, this, ctxt); 333 } 334 335 public void read(String dirof, String id, FosStructure fs, 336 FosAccess conn, Object ctxt) throws FosException { 337 if (FosLoggerFactory.DEBUG) 338 logger.log(BasicLevel.DEBUG, "READ operation: dirof=\"" + dirof 339 + "\", id=\"" + id + "\", FosStructure=" + fs); 340 if (prepared || !active) 341 throw new FosException("FOS transaction context not ready to perform operations."); 342 if ((dirof == null) || (id == null) || (fs == null)) 343 throw new FosException("Wrong parameters."); 344 FosObjectFile fof = getOf(txContextFactory.getDbDir() + File.separator 345 + dirof + File.separator + id); 346 if (!fof.exist()) { 347 throw new FosException("Cannot read: Data Object does not exist."); 348 } 349 ObjectInputStream ois = null; 350 try { 351 ois = fof.openReader(); 352 fs.readFile(ois, conn, ctxt); 353 ois.close(); 354 ois = null; 355 } catch (Exception e) { 356 if (ois != null) { 357 try { 358 ois.close(); 359 } catch (IOException e2) { 360 } 361 } 362 throw new FosException("I/O problem [nested exception].", e); 363 } 364 } 365 366 375 public void delete(String dirof, String id) throws FosException { 376 if (FosLoggerFactory.DEBUG) 377 logger.log(BasicLevel.DEBUG, "REMOVE operation: dirof=\"" + dirof 378 + "\", id=\"" + id + "\""); 379 if (prepared || !active) 380 throw new FosException("FOS transaction context not ready to perform operations."); 381 if ((dirof == null) || (id == null)) 382 throw new FosException("Wrong parameters."); 383 FosObjectFile fof = getOf(txContextFactory.getDbDir() + File.separator 384 + dirof + File.separator + id); 385 try { 386 if (!fof.exist()) 387 throw new FosException("Cannot remove: Data Object does not exist."); 388 if (FosLoggerFactory.DEBUG) 389 logger.log(BasicLevel.DEBUG, "Really removes!!"); 390 fof.delete(); 391 updated = true; 392 } catch (Exception e) { 393 throw new FosException("I/O problem [nested exception].", e); 394 } 395 } 396 397 402 public void deleteDir(String dirof) throws FosException { 403 String dirpath = txContextFactory.getDbDir() + File.separator + dirof; 404 synchronized(txContextFactory) { 405 if (txContextFactory.getNbActiveTX() != 0) 406 throw new FosException("Cannot perform deleteDir: some TX are still active"); 407 if (! existDir(dirof)) 408 throw new FosException("Cannot perform deleteDir: directory does not exist"); 409 try { 410 txContextFactory.deleteDirContent(new File (dirpath)); 411 } catch (Exception e) { 412 throw new FosException("Fails performing deleteDir", e); 413 } 414 } 415 } 416 417 424 public Iterator scan(String dirof) throws FosException { 425 if (FosLoggerFactory.DEBUG) 426 logger.log(BasicLevel.DEBUG, "SCANEXTENSION operation: dirof=\"" 427 + dirof + "\""); 428 if (prepared || !active) 429 throw new FosException("FOS transaction context not ready to perform operations."); 430 if (dirof == null) 431 throw new FosException("Wrong parameters."); 432 return new FosExtension(txContextFactory.getDbDir() + File.separator 433 + dirof); 434 } 435 436 447 public void write(String dirof, String id, FosStructure fs, Object ctxt) 448 throws FosException { 449 write(dirof, id, fs, this, ctxt); 450 } 451 452 public void write(String dirof, String id, FosStructure fs, 453 FosAccess conn, Object ctxt) throws FosException { 454 if (FosLoggerFactory.DEBUG) 455 logger.log(BasicLevel.DEBUG, "WRITE operation: dirof=\"" + dirof 456 + "\", id=\"" + id + "\", FosStructure=" + fs); 457 if (prepared || !active) 458 throw new FosException("FOS transaction context not ready to perform operations."); 459 if ((dirof == null) || (id == null) || (fs == null)) 460 throw new FosException("Wrong parameters."); 461 File od = new File (txContextFactory.getDbDir() + File.separator + dirof); 462 if (!od.exists()) { 463 if (FosLoggerFactory.DEBUG) 464 logger.log(BasicLevel.DEBUG, "Create ObjectFile DIR: " + od.getPath()); 465 od.mkdirs(); 466 } 467 FosObjectFile fof = getOf(txContextFactory.getDbDir() + File.separator 468 + dirof + File.separator + id); 469 if (FosLoggerFactory.DEBUG) 470 logger.log(BasicLevel.DEBUG, "FosObjectFile: " + fof); 471 try { 472 fs.writeFile(fof.openWriter(), conn, ctxt); 473 fof.closeWriter(); 474 updated = true; 475 } catch (Exception e) { 476 throw new FosException("I/O problem [nested exception].", e); 477 } 478 } 479 } 480 | Popular Tags |