📄 xactfactory.java
字号:
int rbcount = 0; // recoveryTransacion assumes the identity of the most recent xact while(ttab.getMostRecentTransactionForRollback(recoveryTransaction)) { if (SanityManager.DEBUG) { SanityManager.ASSERT( recoveryTransaction.handlesPostTerminationWork() == false, "recovery transaction handles post termination work"); } rbcount++; recoveryTransaction.abort(); } if (SanityManager.DEBUG) { if (rbcount > 0 || irbcount > 0) { // RESOLVE: put this in the log trace // System.out.println( // "Recovery rolled back " + irbcount + // " internal transactions," // + rbcount + " user transactions"); } } } /** Run through all prepared transactions known to this factory and restore their state such that they remain after recovery, and can be found and handled by a XA transaction manager. This includes creating a context manager for each, pushing a xact context, and reclaiming update locks on all data changed by the transaction. Expected to be called just after the redo and undo recovery loops, where the transaction table should be empty except for prepared xacts. Used only in recovery. @exception StandardException Cloudscape Standard Error policy */ public void handlePreparedXacts( RawStoreFactory rsf) throws StandardException { if (SanityManager.DEBUG) { if (rawStoreFactory != null) SanityManager.ASSERT( rawStoreFactory == rsf, "raw store factory different"); } int prepared_count = 0; if (ttab.hasPreparedRecoveredXact()) { // if there any prepared xacts // At this point recovery has used one context and one transaction // to deal with all transactions. Prepared transactions are to // be left in the transaction table, but the must have real and // separate CM's and transactions associated with them. // save old context. Errors may go to funky contexts (the new // context we created to bring the prepared transaction into the // real world after recovery) after we switch contexts, but any // error we get at this point is going to shut down the db. while (true) { // allocate new context and associate new xact with it. ContextManager cm = contextFactory.newContextManager(); contextFactory.setCurrentContextManager(cm); try { RawTransaction rawtran = startTransaction( rawStoreFactory, cm, AccessFactoryGlobals.USER_TRANS_NAME); if (ttab.getMostRecentPreparedRecoveredXact(rawtran)) { // found a prepared xact. The reprepare() call will // accumulate locks, and change the transaction table entry // to not be "in-recovery" so that it won't show up again. rawtran.reprepare(); if (SanityManager.DEBUG) prepared_count++; } else { // get rid of last transaction allocated. rawtran.destroy(); break; } } finally { contextFactory.resetCurrentContextManager(cm); } } } if (SanityManager.DEBUG) { // RESOLVE - need to only do this under a debug flag. // SanityManager.DEBUG_PRINT("", // "Recovery re-prepared " + prepared_count + " xa transactions."); } } /** Get the earliest log instant that is still active, ie, the first log record logged by the earliest transaction that is still active. <BR> The logging system must guarentee that the transaction table is populated in the order transactions are started. Used in recovery only. */ public LogInstant firstUpdateInstant() { return ttab.getFirstLogInstant(); } /* ** Methods of Corruptable */ /** Really this is just a convience routine for callers that might not have access to a log factory. */ public StandardException markCorrupt(StandardException originalError) { logFactory.markCorrupt(originalError); return originalError; } /* ** Implementation specific methods. */ public void setNewTransactionId(TransactionId oldxid, Xact t) { XactId xid; boolean excludeMe = true; // by default if (oldxid != null) excludeMe = remove(oldxid); synchronized(this) { xid = new XactId(tranId++); } t.setTransactionId(t.getGlobalId(), xid); // RESOLVE: How does a real global xact id get set? // If we got rid of the oldxid, that means this transaction object has // merely committed and starting the next transaction with the same // xact object. In that case, the transaction context will remain the // same and won't be pushed. We need to add this transaction with the // new id back into the transaction table. If we did not get rid of // the old oldxid, that means this is a brand new transaction being // created. The pushTransactionContext call will add it to the // transaction table with the appropriate flags if (oldxid != null) add(t, excludeMe); } /* ** Set the shortTranId, this is called by the log factory after recovery */ public void resetTranId() { XactId xid = (XactId)ttab.largestUpdateXactId(); if (xid != null) tranId = xid.getId() + 1; else tranId = 1; } /** Create a new RawTransaction, a context for it and push the context onto the current context manager. Then add the transacion to the transaction table. @param contextName the name of the transaction context @param xact the Transaction object @param abortAll if true, then any error will abort the whole transaction. Otherwise, let XactContext.cleanupOnError decide what to do @param rsf the raw store factory @param excludeMe during systeme quiesce, i.e., this transaction should not be allowed to be active during a quiesce state. @exception StandardException Standard Cloudscape error policy */ protected void pushTransactionContext(ContextManager cm, String contextName, Xact xact, boolean abortAll, RawStoreFactory rsf, boolean excludeMe) throws StandardException { if (cm.getContext(contextName) != null) { throw StandardException.newException( SQLState.XACT_TRANSACTION_ACTIVE); } XactContext xc = new XactContext(cm, contextName, xact, abortAll, rsf); // this transaction is now added to the transaction table. // This will cause an idle transaction to take on an identity, which is // unfortunate. The reason why we have to add the transaction to the // table right now is because the transaction table is used to bring // system to quisce state to regulate who can go active during quiesce // state, and if we add the transaction // when it goes active, then there is a window where this transaction // can sneak in. The transaction table itself does not keep track of // whether transactions can be started or not because quiesce related // transactions can start after all other user // transactions are excluded. // RESOLVE: need to put more thought on the overall requirement and // design of the transaction table that satisfies the need of all the // clients, namely: checkpoint, recovery, quiesce mode, transaction table. add(xact, excludeMe); } /** Add a transaction to the list of transactions that has updated the raw store. <P> This is called underneath the BeginXact log operation's doMe method. The logging system must guarentee that transactions are added in the true order they are started, as defined by the order of beginXact log record in the log. */ protected void addUpdateTransaction( TransactionId id, RawTransaction t, int transactionStatus) { if (SanityManager.DEBUG) SanityManager.ASSERT( id != null, "addding update transaction with null id"); ttab.addUpdateTransaction(id, t, transactionStatus); } /** Remove a transaction from the list of transactions that has updated the raw store. */ protected void removeUpdateTransaction(TransactionId id) { if (SanityManager.DEBUG) SanityManager.ASSERT( id != null, "remove update transaction with null id"); ttab.removeUpdateTransaction(id); } /** Change state of transaction to prepared. Used by recovery to update the transaction table entry to prepared state. */ protected void prepareTransaction(TransactionId id) { if (SanityManager.DEBUG) SanityManager.ASSERT( id != null, "prepare transaction with null id"); ttab.prepareTransaction(id); } /** Submit this post commit work to the post commit daemon */ public boolean submitPostCommitWork(Serviceable work) { if (rawStoreDaemon != null) return rawStoreDaemon.enqueue(work, work.serviceASAP()); return false; } public void setRawStoreFactory(RawStoreFactory rsf) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(rsf != null, "rawStoreFactory == null"); } rawStoreFactory = rsf; // no need to remember raw store factory, // just remember which daemon to use rawStoreDaemon = rsf.getDaemon(); // now its ok to look for the log and data factory // log factory is booted by the data factory logFactory = (LogFactory) Monitor.findServiceModule(this, rsf.getLogFactoryModule()); // data factory is booted by the raw store implementation dataFactory = (DataFactory) Monitor.findServiceModule(this, rsf.getDataFactoryModule()); } /** Returns true if there is no in flight updating tranasaction. Caller must be aware that if there is no other mechanism to stop transactions from starting and ending, then this information is outdated as soon as it is reported. Only call this function in special times - e.g, during recovery */ public boolean noActiveUpdateTransaction() { return (ttab.hasActiveUpdateTransaction() == false); } /* remove the transaction Id an return false iff the transaction is found in the table and it doesn't need exclusion from quiesce state */ protected boolean remove(TransactionId xactId) { return ttab.remove(xactId); } protected void add(Xact xact, boolean excludeMe) { ttab.add(xact, excludeMe); } /** Make a new UUID for whomever that wants it */ public UUID makeNewUUID() { return uuidFactory.createUUID(); } /** Decide if a transaction of this contextId needs to flush the log when it commits */ public boolean flushLogOnCommit(String contextName) { // // if this is a user transaction, flush the log // if this is an internal or nested top transaction, do not // flush, let it age out. // return (contextName == USER_CONTEXT_ID || contextName.equals(USER_CONTEXT_ID)); } /** Get a locking policy for a transaction. */ final LockingPolicy getLockingPolicy( int mode, int isolation, boolean stricterOk) { if (mode == LockingPolicy.MODE_NONE) isolation = TransactionController.ISOLATION_NOLOCK; LockingPolicy policy = lockingPolicies[mode][isolation]; if ((policy != null) || (!stricterOk)) return policy; for (mode++; mode <= LockingPolicy.MODE_CONTAINER; mode++) { for (int i = isolation; i <= TransactionController.ISOLATION_SERIALIZABLE; i++) { policy = lockingPolicies[mode][i]; if (policy != null) return policy; } } return null; } /* Return the transaction table to be logged with the checkpoint operation */ public Formatable getTransactionTable() { return ttab; } /* Use this transaction table, which is gotten from a checkpoint operation. Use ONLY during recovery. */ public void useTransactionTable(Formatable transactionTable) throws StandardException { if (ttab != null && transactionTable != null) { throw StandardException.newException( SQLState.XACT_TRANSACTION_TABLE_IN_USE); } if (ttab == null) { if (transactionTable == null) ttab = new TransactionTable(); else { if (SanityManager.DEBUG) { if ((transactionTable instanceof TransactionTable) == false) { SanityManager.THROWASSERT( "using transaction table which is of class " + transactionTable.getClass().getName()); } } ttab = (TransactionTable)transactionTable; } } // else transactionTable must be null, if we already have a transaction // table, no need to do anything } public TransactionInfo[] getTransactionInfo() { if (SanityManager.DEBUG) SanityManager.ASSERT(ttab != null, "transaction table is null"); return ttab.getTransactionInfo(); } // @return false, if the Database creation finished public boolean inDatabaseCreation() { return inCreateNoLog; } /* * Return the module providing XAresource interface to the transaction * table. * * @exception StandardException Standard cloudscape exception policy. */ public /* XAResourceManager */ Object getXAResourceManager() throws StandardException { if (xa_resource == null) xa_resource = new XactXAResourceManager(rawStoreFactory, ttab); return(xa_resource); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -