📄 filelogger.java
字号:
rawInput.close(); } catch (IOException ioe) { throw logFactory.markCorrupt( StandardException.newException( SQLState.LOG_READ_LOG_FOR_UNDO, ioe, prepareId)); } } } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { SanityManager.DEBUG(LogToFile.DBG_FLAG, "Finish prepare" + ", clr skipped = " + clrskipped + ", record seen = " + logrecordseen + "\n"); } } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { SanityManager.DEBUG( LogToFile.DBG_FLAG, "----------------------------------------------------\n" + "End of recovery rePrepare\n" + ", clr skipped = " + clrskipped + ", record seen = " + logrecordseen + "\n----------------------------------------------------\n"); } } } /** Undo a part of or the entire transaction. Begin rolling back the log record at undoStartAt and stopping at (inclusive) the log record at undoStopAt. <P>MT - Not needed. A transaction must be single threaded thru undo, each RawTransaction has its own logger, therefore no need to synchronize. The RawTransaction must handle synchronizing with multiple threads during rollback. @param t the transaction that needs to be rolled back @param undoId the transaction ID @param undoStopAt the last log record that should be rolled back @param undoStartAt the first log record that should be rolled back @exception StandardException Standard Cloudscape error policy @see Logger#undo */ public void undo( RawTransaction t, TransactionId undoId, LogInstant undoStopAt, LogInstant undoStartAt) throws StandardException { if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { if (undoStartAt != null) { SanityManager.DEBUG( LogToFile.DBG_FLAG, "\nUndo transaction: " + undoId.toString() + "start at " + undoStartAt.toString() + " stop at " + undoStopAt.toString() ); } else { SanityManager.DEBUG( LogToFile.DBG_FLAG, "\nUndo transaction: " + undoId.toString() + "start at end of log stop at " + undoStopAt.toString()); } } } // statistics int clrgenerated = 0; int clrskipped = 0; int logrecordseen = 0; StreamLogScan scanLog; Compensation compensation = null; Undoable lop = null; // stream to read the log record - initial size 4096, scanLog needs // to resize if the log record is larget than that. ArrayInputStream rawInput = null; try { if (undoStartAt == null) { // don't know where to start, rollback from end of log scanLog = (StreamLogScan) logFactory.openBackwardsScan(undoStopAt); } else { if (undoStartAt.lessThan(undoStopAt)) { // nothing to undo! return; } long undoStartInstant = ((LogCounter) undoStartAt).getValueAsLong(); scanLog = (StreamLogScan) logFactory.openBackwardsScan(undoStartInstant, undoStopAt); } if (SanityManager.DEBUG) SanityManager.ASSERT( scanLog != null, "cannot open log for undo"); rawInput = new ArrayInputStream(new byte[4096]); LogRecord record; while ((record = scanLog.getNextRecord(rawInput, undoId, 0)) != null) { if (SanityManager.DEBUG) { SanityManager.ASSERT( record.getTransactionId().equals(undoId), "getNextRecord return unqualified log record for undo"); } logrecordseen++; if (record.isCLR()) { clrskipped++; // the loggable is still in the input stream, get rid of it record.skipLoggable(); // read the undoInstant long undoInstant = rawInput.readLong(); if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { SanityManager.DEBUG( LogToFile.DBG_FLAG, "Skipping over CLRs, reset scan to " + LogCounter.toDebugString(undoInstant)); } } scanLog.resetPosition(new LogCounter(undoInstant)); // scanLog now positioned at the beginning of the log // record that was rolled back by this CLR. // The scan is a backward one so getNextRecord will skip // over the record that was rolled back and go to the one // previous to it continue; } lop = record.getUndoable(); if (lop != null) { int optionalDataLength = rawInput.readInt(); int savePosition = rawInput.getPosition(); rawInput.setLimit(savePosition, optionalDataLength); compensation = lop.generateUndo(t, rawInput); if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { SanityManager.DEBUG( LogToFile.DBG_FLAG, "Rollback log record at instant " + LogCounter.toDebugString(scanLog.getInstant()) + " : " + lop); } } clrgenerated++; if (compensation != null) { // generateUndo may have read stuff off the // stream, reset it for the undo operation. rawInput.setLimit(savePosition, optionalDataLength); // log the compensation op that rolls back the // operation at this instant t.logAndUndo( compensation, new LogCounter(scanLog.getInstant()), rawInput); compensation.releaseResource(t); compensation = null; } // if compensation is null, log operation is redo only } // if this is not an undoable operation, continue with next log // record } } catch (ClassNotFoundException cnfe) { throw logFactory.markCorrupt( StandardException.newException(SQLState.LOG_CORRUPTED, cnfe)); } catch (IOException ioe) { throw logFactory.markCorrupt( StandardException.newException( SQLState.LOG_READ_LOG_FOR_UNDO, ioe)); } catch (StandardException se) { // TODO (4327) - exceptions caught here are nested in the exception // below but for some reason the nested exceptions are not logged // or reported in any way. throw logFactory.markCorrupt( StandardException.newException( SQLState.LOG_UNDO_FAILED, se, undoId, lop, compensation)); } finally { if (compensation != null) { // errored out compensation.releaseResource(t); } if (rawInput != null) { try { rawInput.close(); } catch (IOException ioe) { throw logFactory.markCorrupt( StandardException.newException( SQLState.LOG_READ_LOG_FOR_UNDO, ioe, undoId)); } } } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { SanityManager.DEBUG( LogToFile.DBG_FLAG, "Finish undo" + ", clr generated = " + clrgenerated + ", clr skipped = " + clrskipped + ", record seen = " + logrecordseen + "\n"); } } } /** Recovery Redo loop. <P> The log stream is scanned from the beginning (or from the undo low water mark of a checkpoint) forward until the end. The purpose of the redo pass is to repeat history, i.e, to repeat exactly the same set of changes the rawStore went thru right before it stopped. With each log record that is encountered in the redo pass: <OL> <LI>if it isFirst(), then the transaction factory is called upon to create a new transaction object. <LI>if it needsRedo(), its doMe() is called (if it is a compensation operation, then the undoable operation needs to be created first before the doMe is called). <LI>if it isComplete(), then the transaction object is closed. </OL> <P> MT - caller provides synchronization @param transFactory - the transaction factory @param redoLWM - if checkpoint seen, starting from this point on, apply redo if necessary @return the log instant of the next log record (or the instant just after the last log record). This is used to determine where the log truly ends @exception StandardException Standard Cloudscape error policy @exception IOException error reading log file @exception ClassNotFoundException log file corrupted @see LogToFile#recover */ protected long redo( RawTransaction recoveryTransaction, TransactionFactory transFactory, StreamLogScan redoScan, long redoLWM, long ttabInstant) throws IOException, StandardException, ClassNotFoundException { // begin debug info if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { SanityManager.DEBUG( LogToFile.DBG_FLAG, "In recovery redo, redoLWM = " + redoLWM); } } int scanCount = 0; int redoCount = 0; int prepareCount = 0; int clrCount = 0; int btranCount = 0; int etranCount = 0; // end debug info TransactionId tranId = null; // the current log instant long instant = LogCounter.INVALID_LOG_INSTANT; ////////////////////////////////////////////////////////////////////// // During redo time, the byte array in the logOutputBuffer is not used. // Use it to read the log record - if it is not big enough, scan // will resize it. We could create a brand new log input stream that // has nothing to do with logIn or logOutputBuffer but that seem like // a waste of memory. ////////////////////////////////////////////////////////////////////// logIn.setData(logOutputBuffer.getByteArray()); // use this scan to reconstitute operation to be undone // when we see a CLR in the redo scan StreamLogScan undoScan = null; Loggable op = null; long logEnd = 0; // we need to determine the log's true end try { // scan the log forward in redo pass and go to the end LogRecord record; while((record = redoScan.getNextRecord(logIn, null, 0)) != null) { scanCount++; long undoInstant = 0; // last known good instant instant = redoScan.getInstant(); // last known good log end logEnd = redoScan.getLogRecordEnd(); // NOTE NOTE -- be very careful about the undoInstant, it is // read off the input stream in this debug section. // if we change the log format we will need to change the way // the undo instant is gotten. Also, once it is read off, it // should not be read from the stream any more // NOTE NOTE if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON(LogToFile.DUMP_LOG_ONLY) || SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) { if (SanityManager.DEBUG_ON(LogToFile.DUMP_LOG_ONLY)) SanityManager.DEBUG_SET(LogToFile.DBG_FLAG); op = record.getLoggable(); tranId = record.getTransactionId(); if (record.isCLR()) { // !!!!!!! this moves the file pointer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -