nCheckpoints++;
boolean success = false;
boolean traced = false;
LogManager logManager = envImpl.getLogManager();
/*
* Set the checkpoint state so that concurrent eviction can be
* coordinated.
*/
checkpointDirtyMap.beginCheckpoint(flushAll, flushExtraLevel);
try {
/*
* Eviction can run during checkpoint as long as it follows the
* same rules for using provisional logging and for propagating
* logging of the checkpoint dirty set up the tree. We have to lock
* out the evictor after the logging of checkpoint start until
* we've selected the dirty set and decided on the highest level to
* be flushed. See SR 11163, 11349.
*/
long checkpointStart = DbLsn.NULL_LSN;
long firstActiveLsn = DbLsn.NULL_LSN;
/* Log the checkpoint start. */
SingleItemEntry startEntry =
new SingleItemEntry(LogEntryType.LOG_CKPT_START,
new CheckpointStart(checkpointId,
invokingSource));
checkpointStart =
logManager.log(startEntry, ReplicationContext.NO_REPLICATE);
/*
* Note the first active LSN point. The definition of
* firstActiveLsn is that all log entries for active transactions
* are equal to or after that LSN. This is the starting point for
* replaying LNs during recovery and will be stored in the CkptEnd
* entry.
*
* Use the checkpointStart as the firstActiveLsn if firstActiveLsn
* is null, meaning that no txns are active.
*
* The current value must be retrieved from TxnManager after
* logging CkptStart. If it were instead retrieved before logging
* CkptStart, the following failure could occur. [#20270]
*
* ... getFirstActiveLsn returns NULL_LSN, will use 200 CkptStart
* 100 LN-A in Txn-1
* 200 CkptStart
* 300 BIN-B refers to 100 LN-A
* 400 CkptEnd
* ... Crash and recover. Recovery does not undo 100 LN-A.
* ... Txn-1 is uncommitted, yet 100 LN-A takes effect.
*/
firstActiveLsn = envImpl.getTxnManager().getFirstActiveLsn();
if (firstActiveLsn == DbLsn.NULL_LSN) {
firstActiveLsn = checkpointStart;
}
/*
* In a replicated system, the checkpointer will be flushing out
* the VLSNIndex, which is HA metadata. Check that the in-memory
* version encompasses all metadata up to the point of the
* CheckpointStart record. This is no-op for non-replicated
* systems. [#19754]
*/
envImpl.awaitVLSNConsistency();
/* Find the set of dirty INs that must be logged. */
checkpointDirtyMap.selectDirtyINsForCheckpoint();
/* Call hook after dirty map creation and before flushing. */
TestHookExecute.doHookIfSet(beforeFlushHook);
/* Flush IN nodes. */
flushDirtyNodes(envImpl, checkpointDirtyMap, allowDeltas,
checkpointStart, highPriority, flushStats);
/*
* Flush MapLNs if not already done by flushDirtyNodes. Only flush
* a database if it has not already been flushed since checkpoint
* start. Lastly, flush the DB mapping tree root.
*/
checkpointDirtyMap.flushMapLNs(checkpointStart);
checkpointDirtyMap.flushRoot(checkpointStart);
/*
* Flush replication information if necessary so that the VLSNIndex
* cache is flushed and is recoverable.
*/
envImpl.preCheckpointEndFlush();
/*
* Flush utilization info AFTER flushing IN nodes to reduce the
* inaccuracies caused by the sequence FileSummaryLN-LN-BIN.
*/
envImpl.getUtilizationProfile().flushFileUtilization
(envImpl.getUtilizationTracker().getTrackedFiles());
DbTree dbTree = envImpl.getDbTree();
boolean willDeleteFiles = !cleanerState.isEmpty();
CheckpointEnd ckptEnd = new CheckpointEnd
(invokingSource, checkpointStart, envImpl.getRootLsn(),
firstActiveLsn,
envImpl.getNodeSequence().getLastLocalNodeId(),
envImpl.getNodeSequence().getLastReplicatedNodeId(),
dbTree.getLastLocalDbId(), dbTree.getLastReplicatedDbId(),
envImpl.getTxnManager().getLastLocalTxnId(),
envImpl.getTxnManager().getLastReplicatedTxnId(),
checkpointId, willDeleteFiles, cleaner.getLogSummary());
SingleItemEntry endEntry =
new SingleItemEntry(LogEntryType.LOG_CKPT_END, ckptEnd);
/*
* Log checkpoint end and update state kept about the last
* checkpoint location. Send a trace message *before* the
* checkpoint end log entry. This is done so that the normal trace
* message doesn't affect the time-based isRunnable() calculation,
* which only issues a checkpoint if a log record has been written
* since the last checkpoint.
*/
trace(envImpl, invokingSource, true);
traced = true;
/*
* Always flush to ensure that cleaned files are not referenced,
* and to ensure that this checkpoint is not wasted if we crash.
*/
lastCheckpointEnd =
logManager.logForceFlush(endEntry,
true /*fsyncRequired*/,
ReplicationContext.NO_REPLICATE);
lastCheckpointStart = checkpointStart;