📄 transaction.java
字号:
// You can redistribute this software and/or modify it under the terms of// the Ozone Core License version 1 published by ozone-db.org.//// The original code and portions created by SMB are// Copyright (C) 1997-2000 by SMB GmbH. All rights reserved.//// $Id: Transaction.java,v 1.65 2000/11/10 17:03:42 daniela Exp $package org.ozoneDB.core;import java.io.*;import java.util.*;import java.lang.reflect.*;import org.ozoneDB.DxLib.*;import org.ozoneDB.*;import org.ozoneDB.core.DbRemote.*;import org.ozoneDB.core.dr.*;import org.ozoneDB.util.*;/** * This class represents an internal transaction.<p> * * Most methods of this class are synchronized. In fact, this is not strictly * needed because a transaction is invoked by one thread (associated with this * transaction) only.<p> * * All public methods are wrapped into try/catch statements to convert thrown * exception into OzoneInternalExc. So the client gets OzoneRemoteExc, if an * object could not be found or something; OzoneInternalExc, if there was a * critical internal error; any other exceptions were thrown by the user code. * * * @author <a href="http://www.softwarebuero.de/">SMB</a> * @version $Revision: 1.65 $Date: 2000/11/10 17:03:42 $ */public final class Transaction implements Locker { /** Status of a transaction: transaction is not active. */ public final static int STATUS_NONE = 1; /** Status of a transaction: transaction has been started. */ public final static int STATUS_STARTED = 2; /** Status of a transaction: transaction is about to prepare. */ public final static int STATUS_PREPARING = 3; /** Status of a transaction: transaction has been successfully prepared. */ public final static int STATUS_PREPARED = 4; /** Status of a transaction: transaction is about to commit.*/ public final static int STATUS_COMMITING = 5; /** Status of a transaction: transaction has been successfully committed. */ public final static int STATUS_COMMITED = 6; /** Status of a transaction: transaction is about to abort. */ public final static int STATUS_ABORTING = 7; /** Status of a transaction: transaction has been aborted. */ public final static int STATUS_ABORTED = 8; public final static int HASHTABLE_INIT_SIZE = 100; /** * The environment of this object. */ protected transient Env env; protected TransactionID taID; protected String ownerName; protected User owner; protected int status; protected boolean rollbackOnly; protected int maxLockLevel; /** * Data that the Store implementation uses to hold data that is associated * with this transaction. Usually this is a table of all containers that are * currently joined to this transaction. */ public Object data; protected int commandCount; /** * The ID of the object (container) that blocks this transaction. */ protected ObjectID blocker; protected long startTime; protected int acquireCount; protected boolean stopped; /** * Construct a new transaction. * * * @param _env Environment of this transaction. * @param _command Command that will be performed by run(). * @param _owner User that has started this transaction. */ public Transaction( Env _env, User _owner ) { env = _env; taID = new TransactionID( env.nextID() ); owner = _owner; data = env.store.newTransactionData(); reset(); } /** * Construct a new transaction. THIS TRANSACTION CAN BE USED FOR TESTING * ONLY! */ public Transaction( TransactionID _taID ) { taID = _taID; reset(); } public synchronized void stop() { stopped = true; } public void reset() { startTime = System.currentTimeMillis(); status = STATUS_STARTED; commandCount = 0; } public int status() { return status; } public User owner() { return owner; } public int maxLockLevel() { return maxLockLevel; } /** * Set a lock on the container specified by the given object ID and join * the container to this transaction. * * * @param id ObjectID of the container which we try to join to this transaction. * @param lockLevel The lock level we need on this object (container). * @return The container for the specified id, if all was ok. * @throws ObjectNotFoundExc If there is no such object. */ public ObjectContainer acquireObject( ObjectID id, int lockLevel ) throws Exception { // this is not good style but this method is a hotspot and we should // do all we can to make it fast if (env.transactionManager.exclusiveThread != null && env.transactionManager.exclusiveThread != Thread.currentThread()) { env.transactionManager.checkExclusion(); } ObjectContainer container = env.store.containerForID( this, id ); if (container == null) { throw new ObjectNotFoundExc( "No such object." ); } acquireContainer( container, lockLevel ); return container; } protected void acquireContainer( ObjectContainer container, int lockLevel ) throws Exception { if (stopped == true) { throw new TransactionExc( "Stopped.", TransactionExc.STOPPED ); } maxLockLevel = lockLevel > maxLockLevel ? lockLevel : maxLockLevel; acquireCount++; // this should help to let the following code execute without // interrupt and so ensure that the container that we retrieve from // the store is not deactivated while this method is running // Thread.currentThread().yield(); // transaktion als blockiert markieren (kante in lock-graphen einfuegen); // vor deadlock-erkennung: es werden auch deadlocks mit // transaktionen erkannt, die selber erstmal auf deadlock checken // aber auf keinem fall zuwenige (race-cond. zwischen deadlock-pruefung // und lock setzen) blocker = container.id(); // try to aquire the lock of the container; wait until the locks is // successfully aquired int prevLevel = container.lock().tryAcquire( this, lockLevel ); if (prevLevel == Lock.NOT_ACQUIRED) { synchronized (this) { while (prevLevel == Lock.NOT_ACQUIRED) { try { env.logWriter.newEntry( this, toString() + " blocked by lock...", LogWriter.DEBUG ); wait(); env.logWriter.newEntry( this, toString() + " checking lock again...", LogWriter.DEBUG ); } catch (Exception e) { } // since the container was maybe deactivated while waiting we // reload it here again container = env.store.containerForID( this, blocker ); if (container == null) { throw new ObjectNotFoundExc( "No such object." ); } // throw an exception if we are forced to abort because of a deadlock container.lock().checkDeadlock( this ); prevLevel = container.lock().tryAcquire( this, lockLevel ); } } } // transaction is no longer blocked blocker = null; // after acquiring the lock we update the lock level of the container if (prevLevel < lockLevel) { if (owner == null) { throw new PermissionError( "No such user." ); } if (!env.userManager.checkPermission( owner, container, lockLevel )) { throw new PermissionError( "User does not have proper access rights." ); } env.store.updateLockLevel( this, container ); } container.touch(); } public boolean performCommand( DbCommand command ) { if (env.logWriter.hasTarget( LogWriter.DEBUG )) { env.logWriter.newEntry( this, "performCommand(): " + toString() + ", " + command.toString(), LogWriter.DEBUG ); } commandCount++; boolean result = true; try { // result goes in command.result command.perform( this ); } catch (TransactionError e) { throw e; } catch (Throwable e) { env.logWriter.newEntry( this, toString() + ": uncaught exception: (" + e + ")", e, LogWriter.WARN ); if (e instanceof PermissionError) { e = new PermissionDeniedExc( e.toString() ); } rollbackOnly = true; command.result = e; result = false; } return result; } public synchronized void prepareCommit() throws Exception { if (env.logWriter.hasTarget( LogWriter.DEBUG )) { env.logWriter.newEntry( this, "==> PREPARECOMMIT() ", LogWriter.DEBUG ); } status = STATUS_PREPARING; env.store.prepareCommitTransaction( this ); status = STATUS_PREPARED; } /** * Commit this transaction. The transaction has to be in PREPARED state. * Ones this method is called it MUST commit the entire transaction * stuff without any exception. */ public synchronized void commit() throws Exception {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -