📄 logtofile.java
字号:
// setup checktpoint daemon ///////////////////////////////////////////////////////////// checkpointDaemon = rawStoreFactory.getDaemon(); if (checkpointDaemon != null) { myClientNumber = checkpointDaemon.subscribe(this, true /*onDemandOnly */); } } /** Checkpoint the rawStore. <P> MT- Only one checkpoint is to be taking place at any given time. <P> The steps of a checkpoint are <OL> <LI> switch to a new log file if possible <PRE> freeze the log (for the transition to a new log file) flush current log file create and flush the new log file (with file number 1 higher than the previous log file). The new log file becomes the current log file. unfreeze the log </PRE> <LI> start checkpoint transaction <LI> gather interesting information about the rawStore: the current log instant (redoLWM) the earliest active transaction begin tran log record instant (undoLWM), all the truncation LWM set by clients of raw store (replication) <LI> clean the buffer cache <LI> log the next checkpoint log record, which contains (repPoint, undoLWM, redoLWM) and commit checkpoint transaction. <LI> synchronously write the control file containing the next checkpoint log record log instant <LI> the new checkpoint becomes the current checkpoint. Somewhere near the beginning of each log file should be a checkpoint log record (not guarenteed to be there) <LI> see if the log can be truncated <P> The earliest useful log record is determined by the repPoint and the undoLWM, whichever is earlier. <P> Every log file whose log file number is smaller than the earliest useful log record's log file number can be deleted. <P><PRE> Transactions can be at the following states w/r to a checkpoint - consider the log as a continous stream and not as series of log files for the sake of clarity. |(BT)-------(ET)| marks the begin and end of a transaction. . checkpoint started . |__undoLWM | . V |___redoLWM . |___TruncationLWM . | . V 1 |-----------------| 2 |--------------------------------| 3 |-------| 4 |--------------------------------------(end of log) 5 |-^-| . Checkpoint Log Record ---A--->|<-------B--------->|<-------------C----------- </PRE> <P> There are only 3 periods of interest : <BR> A) before undoLWM, B) between undo and redo LWM, C) after redoLWM. <P> Transaction 1 started in A and terminates in B.<BR> During redo, we should only see log records and endXact from this transaction in the first phase (between undoLWM and redoLWM). No beginXact log record for this transaction will be seen. <P> Transaction 2 started in B (right on the undoLWM) and terminated in C.<BR> Any transaction that terminates in C must have a beginXact at or after undoLWM. In other words, no transaction can span A, B and C. During redo, we will see beginXact, other log records and endXact for this transaction. <P> Transaction 3 started in B and ended in B.<BR> During redo, we will see beginXact, other log records and endXact for this transaction. <P> Transaction 4 begins in B and never ends.<BR> During redo, we will see beginXact, other log records. In undo, this loser transaction will be rolled back. <P> Transaction 5 is the transaction taking the checkpoint.<BR> The checkpoint action started way back in time but the checkpoint log record is only written after the buffer cache has been flushed. <P> Note that if any time elapse between taking the undoLWM and the redoLWM, then it will create a 4th period of interest. @exception StandardException - encounter exception while doing checkpoint. */ public boolean checkpoint(RawStoreFactory rsf, DataFactory df, TransactionFactory tf, boolean wait) throws StandardException { // call checkpoint with no pre-started transaction boolean done = checkpointWithTran(null, rsf, df, tf); //above checpoint call will return 'false' without //performing the checkpoint if some other thread is doing checkpoint. //In cases like backup it is necesary to wait for the //checkpoint to complete before copying the files. 'wait' flag get passed //in as 'true' by such cases. //When wait flag is true, we will wait here until the other thread which //is actually doing the the checkpoint completes. if(!done && wait) { synchronized(this) { //wait until the thread that is doing the checkpoint completes it. while(inCheckpoint) { try { wait(); } catch (InterruptedException ie) { throw StandardException.interrupt(ie); } } done = true; } } return done; } /** checkpoint with pre-start transaction @exception StandardException Cloudscape Standard Error Policy */ protected boolean checkpointWithTran(RawTransaction cptran, RawStoreFactory rsf, DataFactory df, TransactionFactory tf) throws StandardException { boolean proceed = true; LogInstant redoLWM; // we may be called to stop the database after a bad error, make sure // logout is set if (logOut == null) { return false; } long approxLogLength; synchronized (this) { // has someone else found a problem in the raw store? if (corrupt != null) { throw StandardException.newException(SQLState.LOG_STORE_CORRUPT, corrupt); } // if another checkpoint is in progress, don't do anything if (inCheckpoint == true) proceed = false; else inCheckpoint = true; approxLogLength = endPosition; // current end position // don't return from inside of a sync block } if (!proceed) { return false; } // needCPtran == true if we are not supplied with a pre-started transaction boolean needCPTran = (cptran == null); if (SanityManager.DEBUG) { if (logSwitchInterval == 0) { SanityManager.THROWASSERT( "switching log file: Approx log length = " + approxLogLength + " logSwitchInterval = 0"); } } try { if (approxLogLength > logSwitchInterval) { switchLogFile(); //log switch is occuring in conjuction with the //checkpoint, set the amount of log written from last checkpoint to zero. logWrittenFromLastCheckPoint = 0; }else { //checkpoint is happening without the log switch, //in the middle of a log file. Amount of log written already for //the current log file should not be included in caluculation //of when next check point is due. By assigning the negative //value of amount of log writtent for this file. Later it will //be subtracted when we switch the log file or while calculating whether //we are due a for checkpoint a flush time. logWrittenFromLastCheckPoint = -endPosition; } if (SanityManager.DEBUG) { // if this debug flag is set on, just switch log file if (SanityManager.DEBUG_ON(TEST_LOG_SWITCH_LOG)) return false; } // start a checkpoint transaction if (needCPTran) cptran = tf.startInternalTransaction(rsf, ContextService.getFactory().getCurrentContextManager()); ///////////////////////////////////////////////////// // gather a snapshot of the various interesting points of the log ///////////////////////////////////////////////////// long undoLWM_long; long redoLWM_long; synchronized(this) // we could synchronized on something else, it // doesn't matter as long as logAndDo sync on // the same thing { // The redo LWM is the current log instant. We are going to // clean the cache shortly, any log record before this point // will not ever need to be redone. redoLWM_long = currentInstant(); redoLWM = new LogCounter(redoLWM_long); // The undo LWM is what we need to rollback all transactions. // Synchronize this with the starting of a new transaction so // that the transaction factory can have a consistent view // See FileLogger.logAndDo LogCounter undoLWM = (LogCounter)(tf.firstUpdateInstant()); if (undoLWM == null) undoLWM_long = redoLWM_long; // no active transaction else undoLWM_long = undoLWM.getValueAsLong(); } ///////////////////////////////////////////////////// // clean the buffer cache ///////////////////////////////////////////////////// df.checkpoint(); ///////////////////////////////////////////////////// // write out the checkpoint log record ///////////////////////////////////////////////////// // send the checkpoint record to the log Formatable transactionTable = tf.getTransactionTable(); CheckpointOperation nextCheckpoint = new CheckpointOperation( redoLWM_long, undoLWM_long, transactionTable); cptran.logAndDo(nextCheckpoint); LogCounter checkpointInstant = (LogCounter)(cptran.getLastLogInstant()); if (checkpointInstant != null) { // since checkpoint is an internal transaction, I need to // flush it to make sure it actually goes to the log flush(checkpointInstant); } else { throw StandardException.newException( SQLState.LOG_CANNOT_LOG_CHECKPOINT); } cptran.commit(); if (needCPTran) { cptran.close(); // if we started it, we will close it cptran = null; } ///////////////////////////////////////////////////// // write out the log control file which contains the last // successful checkpoint log record ///////////////////////////////////////////////////// if (!writeControlFile(getControlFileName(), checkpointInstant.getValueAsLong())) { throw StandardException.newException( SQLState.LOG_CONTROL_FILE, getControlFileName()); } // next checkpoint becomes the current checkpoint currentCheckpoint = nextCheckpoint; //////////////////////////////////////////////////// // see if we can reclaim some log space //////////////////////////////////////////////////// if (!logArchived()) { truncateLog(currentCheckpoint); } //delete the committted container drop stubs that are no longer //required during recovery. df.removeDroppedContainerFileStubs(redoLWM); } catch (IOException ioe) { throw markCorrupt( StandardException.newException(SQLState.LOG_IO_ERROR, ioe)); } finally { synchronized(this) { inCheckpoint = false; notifyAll(); } if (cptran != null && needCPTran) { try { cptran.commit(); cptran.close(); } catch (StandardException se) { throw markCorrupt(StandardException.newException( SQLState.LOG_CORRUPTED, se)); } } } return true; } /** Flush all unwritten log record up to the log instance indicated to disk and sync. Also check to see if database is frozen or corrupt. <P>MT - not needed, wrapper method @param where flush log up to here @exception StandardException Standard Cloudscape error policy */ public void flush(LogInstant where) throws StandardException { long fileNumber; long wherePosition; if (where == null) { // don't flush, just use this to check if database is frozen or // corrupt fileNumber = 0; wherePosition = LogCounter.INVALID_LOG_INSTANT; } else { LogCounter whereC = (LogCounter) where; fileNumber = whereC.getLogFileNumber(); wherePosition = whereC.getLogFilePosition(); } flush(fileNumber, wherePosition); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -