📄 xact.java
字号:
private final void releaseAllLocks() { getLockFactory().unlockGroup(getCompatibilitySpace(), this); } void resetDefaultLocking() { setDefaultLockingPolicy( newLockingPolicy(LockingPolicy.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE, true)); if (SanityManager.DEBUG) { SanityManager.ASSERT(defaultLocking != null); } } protected void preComplete(Integer commitOrAbort) throws StandardException { /* If a transaction is in COMMIT/ABORT at this point, most probably * some thing went wrong in earlier attempt to commit or abort, * so we don't know wther the log records got written in previous * attempt. It's is better to bring down the system than make recovery * fail with a duplicate log records of COMMIT/ABORT for the same Transaction. */ if (inComplete != null) if (commitOrAbort.equals(COMMIT)) throw logFactory.markCorrupt( StandardException.newException(SQLState.XACT_COMMIT_EXCEPTION)); else throw logFactory.markCorrupt( StandardException.newException(SQLState.XACT_ABORT_EXCEPTION)); inComplete = commitOrAbort; if (!postCompleteMode) doComplete(commitOrAbort); } protected void postComplete(int commitflag, Integer commitOrAbort) throws StandardException { if (postCompleteMode) doComplete(commitOrAbort); // if we are want to commitNoSync with KEEP_LOCKS flag set, don't // release any locks if ((commitflag & Transaction.KEEP_LOCKS) == 0) { releaseAllLocks(); } else { if (SanityManager.DEBUG) { SanityManager.ASSERT(commitOrAbort.equals(COMMIT), "cannot keep locks around after an ABORT"); } } setIdleState(); inComplete = null; } protected void doComplete(Integer commitOrAbort) throws StandardException { // throw away all our savepoints if (savePoints != null) savePoints.removeAllElements(); // notify any of our observers that we are completing. notifyObservers(commitOrAbort); checkObserverException(); if (SanityManager.DEBUG) { if (countObservers() != 0) { System.out.println( "There should be 0 observers, but we still have " + countObservers() + " observers."); notifyObservers(null); } } } private void checkObserverException() throws StandardException { if (observerException != null) { StandardException se = observerException; observerException = null; throw se; } } /** If this is a user transaction (not an internal or nested top transaction), and this is not already taking care of post commit work, and not an XA transaction, then take care of hi prioirty work right now using this thread and this context manager. Otherwise, leave it to the post commit daemon. */ protected boolean doPostCommitWorkInTran() { return (!inPostCommitProcessing && !recoveryTransaction && isUserTransaction() && (myGlobalId == null)); } public boolean handlesPostTerminationWork() { // recovery transaction cannot handle post termination work return (recoveryTransaction == false); } public void recoveryTransaction() { recoveryTransaction = true; // remove myself from the transaction table because I am really a // "fake" transaction. All interaction I have with the transaction // table should happen after I have assumed the identity of one of the // recovery transaction that has its state frozen in the transaction // table. xactFactory.remove(myId); } private final void postTermination() throws StandardException { // move all the postTermination work to the postCommit queue int count = (postTerminationWorks == null) ? 0 : postTerminationWorks.size(); for (int i = 0; i < count; i++) addPostCommitWork((Serviceable)postTerminationWorks.get(i)); if (count > 0) postTerminationWorks.clear(); // if there are post commit work to be done, transfer them to the // daemon. The log is flushed, all locks released and the // transaction has ended at this point. if (postCommitWorks != null && !postCommitWorks.isEmpty()) { int pcsize = postCommitWorks.size(); // do we want to do post commit work with this transaction object? if (doPostCommitWorkInTran()) { try { inPostCommitProcessing = true; // to avoid confusion, copy the post commit work to an array if this // is going to do some work now Serviceable[] work = new Serviceable[pcsize]; work = (Serviceable[])postCommitWorks.toArray(work); // clear this for post commit processing to queue its own post // commit works - when it commits, it will send all its post // commit request to the daemon instead of dealing with it here. postCommitWorks.clear(); //All the post commit work that is part of the database creation //should be done on this thread immediately. boolean doWorkInThisThread = xactFactory.inDatabaseCreation(); for (int i = 0; i < pcsize; i++) { //process work that should be done immediately or //when we are in still in database creattion. //All the other work should be submitted //to the post commit thread to be processed asynchronously if (doWorkInThisThread || work[i].serviceImmediately()) { try { // this may cause other post commit work to be // added. when that transaction commits, those // work will be transfered to the daemon if (work[i].performWork(xc.getContextManager()) == Serviceable.DONE) work[i] = null; // if REQUEUE, leave it on for the postcommit // daemon to handle } catch (StandardException se) { // don't try to service this again work[i] = null; // try to handle it here. If we fail, then let the error percolate. xc.cleanupOnError(se); } } // either it need not be serviedASAP or it needs // requeueing, send it off. Note that this is one case // where a REQUEUE ends up in the high priority queue. // Unfortunately, there is no easy way to tell. If the // Servicable is well mannered, it can change itself from // serviceASAP to not serviceASAP if it returns REQUEUE. if (work[i] != null) { boolean needHelp = xactFactory.submitPostCommitWork(work[i]); work[i] = null; if (needHelp) doWorkInThisThread = true; } } } finally { inPostCommitProcessing = false; // if something untoward happends, clear the queue. if (postCommitWorks != null) postCommitWorks.clear(); } } else { // this is for non-user transaction or post commit work that is // submitted in PostCommitProcessing. (i.e., a post commit // work submitting other post commit work) for (int i = 0; i < pcsize; i++) { // SanityManager.DEBUG_PRINT("PostTermination",postCommitWorks.elementAt((i)).toString()); xactFactory.submitPostCommitWork((Serviceable)postCommitWorks.get((i))); } } postCommitWorks.clear(); } } /** Does a save point exist in the stack with the given name. Returns the position of the savepoint in the array */ private int getSavePointPosition( String name, Object kindOfSavepoint, boolean forRollbackOrRelease) { if ((savePoints == null) || (savePoints.empty())) return -1; for (int i = savePoints.size() - 1; i >= 0; i--) { SavePoint savepoint = (SavePoint)savePoints.elementAt(i); if (savepoint.getName().equals(name)) { if (forRollbackOrRelease && savepoint.getKindOfSavepoint() != null) { if (savepoint.getKindOfSavepoint().equals(kindOfSavepoint)) return(i); } else { return(i); } } } return -1; } /** Pop all savepoints upto the one with the given name and rollback all changes made since this savepoint was pushed. If release is true then this savepoint is popped as well, otherwise it is left in the stack (at the top). @return true if any work is rolled back, false if no work is rolled back @exception StandardException Standard cloudscape policy @exception StandardException Thrown if a error of severity less than TransactionException#SEVERITY is encountered during the rollback of this savepoint. */ protected boolean popSavePoints(int position, boolean release) throws StandardException { if (release) { savePoints.setSize(position); return false; } LogInstant rollbackTo = null; int size = savePoints.size(); for (int i = position; i < size; i++) { SavePoint rollbackSavePoint = (SavePoint) savePoints.elementAt(i); LogInstant li = rollbackSavePoint.getSavePoint(); if (li != null) { rollbackTo = li; break; } } savePoints.setSize(position + 1); if (rollbackTo == null) return false; // now perform the rollback try { logger.undo(this, getId(), rollbackTo, getLastLogInstant()); } catch (StandardException se) { // This catches any exceptions that have Transaction severity // or less (e.g. Statement exception). If we received any lesser // error then we abort the transaction anyway. if (se.getSeverity() < ExceptionSeverity.TRANSACTION_SEVERITY) { throw StandardException.newException( SQLState.XACT_ROLLBACK_EXCEPTION, se); } throw se; } return true; } /** @exception StandardException Cloudscape Standard error policy */ public RawTransaction startNestedTopTransaction() throws StandardException { return xactFactory.startNestedTopTransaction(xc.getFactory(), xc.getContextManager()); } /** * see if this transaction is a user transaction. * * @return true if this transaction is a user transaction */ private boolean isUserTransaction() { String context_id = getContextId(); return( (context_id == XactFactory.USER_CONTEXT_ID || context_id.equals(XactFactory.USER_CONTEXT_ID))); } /** * see if this transaction has ever done anything. * * MT - single thread through synchronizing this. This method may be * called by other thread to test the state of this transaction. That's * why we need to synchronize with all methods which enters or exits the * Idle state. * * Local method which read the state need not be synchronized because * the other thread may look at the state but it may not change it. * * @return true if this transaction is not in idle or closed state */ public final boolean isActive() { // synchronized(this) -- int access, implicit synchronization // due to atomic action int localState = state; return (localState != CLOSED && localState != IDLE); } /** * see if this transaction is in PREPARED state. * * MT - single thread through synchronizing this. This method may be * called by other thread to test the state of this transaction. * * @return true if this transaction is in PREPARED state. */ public final boolean isPrepared() { // synchronized(this) -- int access, implicit synchronization // due to atomic action return(state == PREPARED); } /** See if this transaction is in the idle state, called by other thread to test the state of this transaction. That's why we need to synchronzied with all methods whcih enters or exits the idle state @return true if it is idle, otherwise false */ public boolean isIdle() { // synchronized(this) -- int access, implicit synchronization // due to atomic action if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("XATrace")) SanityManager.DEBUG("XATrace","RawTran, isIdle, state = " + state); } return (state == IDLE); } /** see if this transaction is in a pristine state. <BR>MT - called only by the same thread that owns the xact, no need to synchronize. @return true if it hasn't done any updates, otherwise false */ public boolean isPristine() { return (state == IDLE || state == ACTIVE); } public boolean inAbort() { return ABORT.equals(inComplete); } public FileResource getFileHandler() { return dataFactory.getFileHandler(); } /** * put this into the beginXact log record to help recovery * if we needs to rolled back first, put that in */ protected int statusForBeginXactLog() { return recoveryRollbackFirst() ? RECOVERY_ROLLBACK_FIRST : 0; } /** * put this into the endXact log record to help recovery, * nothing to add */ protected int statusForEndXactLog() { // during recovery, the beginXact may be logged by a non-standard // transaction and hence the end xact it log // must also contain whatever a non-standard Transaction will output. return savedEndStatus; } /** Set the transa
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -