use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.
the class IgniteTxAdapter method state.
/**
* @param state State to set.
* @param timedOut Timeout flag.
*
* @return {@code True} if state changed.
*/
protected final boolean state(TransactionState state, boolean timedOut) {
boolean valid = false;
TransactionState prev;
boolean notify = false;
WALPointer ptr = null;
synchronized (this) {
prev = this.state;
switch(state) {
case ACTIVE:
{
valid = prev == SUSPENDED;
break;
}
case PREPARING:
{
valid = prev == ACTIVE;
break;
}
case PREPARED:
{
valid = prev == PREPARING;
break;
}
case COMMITTING:
{
valid = prev == PREPARED;
break;
}
case UNKNOWN:
{
if (setDone())
notify = true;
valid = prev == ROLLING_BACK || prev == COMMITTING;
break;
}
case COMMITTED:
{
if (setDone())
notify = true;
valid = prev == COMMITTING;
break;
}
case ROLLED_BACK:
{
if (setDone())
notify = true;
valid = prev == ROLLING_BACK;
break;
}
case MARKED_ROLLBACK:
{
valid = prev == ACTIVE || prev == PREPARING || prev == PREPARED || prev == SUSPENDED;
break;
}
case ROLLING_BACK:
{
valid = prev == ACTIVE || prev == MARKED_ROLLBACK || prev == PREPARING || prev == PREPARED || prev == SUSPENDED || (prev == COMMITTING && local() && !dht());
break;
}
case SUSPENDED:
{
valid = prev == ACTIVE;
break;
}
}
if (valid) {
if (timedOut)
this.timedOut = true;
this.state = state;
if (log.isDebugEnabled())
log.debug("Changed transaction state [prev=" + prev + ", new=" + this.state + ", tx=" + this + ']');
recordStateChangedEvent(state);
notifyAll();
} else {
if (log.isDebugEnabled())
log.debug("Invalid transaction state transition [invalid=" + state + ", cur=" + this.state + ", tx=" + this + ']');
}
if (valid) {
// Seal transactions maps.
if (state != ACTIVE && state != SUSPENDED)
seal();
if (state == PREPARED || state == COMMITTED || state == ROLLED_BACK) {
cctx.tm().setMvccState(this, state);
ptr = cctx.tm().logTxRecord(this);
}
}
}
if (valid) {
if (ptr != null && (state == COMMITTED || state == ROLLED_BACK))
try {
cctx.wal().flush(ptr, false);
} catch (IgniteCheckedException e) {
String msg = "Failed to fsync ptr: " + ptr;
U.error(log, msg, e);
throw new IgniteException(msg, e);
}
}
if (notify) {
GridFutureAdapter<IgniteInternalTx> fut = finFut;
if (fut != null)
fut.onDone(this);
}
return valid;
}
use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.
the class CheckpointHistory method onWalTruncated.
/**
* Clears checkpoint history after WAL truncation.
*
* @param highBound Upper bound.
* @return List of checkpoint entries removed from history.
*/
public List<CheckpointEntry> onWalTruncated(WALPointer highBound) {
List<CheckpointEntry> removed = new ArrayList<>();
for (CheckpointEntry cpEntry : histMap.values()) {
WALPointer cpPnt = cpEntry.checkpointMark();
if (highBound.compareTo(cpPnt) <= 0)
break;
if (!removeCheckpoint(cpEntry))
break;
removed.add(cpEntry);
}
return removed;
}
use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.
the class CheckpointHistory method searchEarliestWalPointer.
/**
* Search the earliest WAL pointer for particular group, matching by counter for partitions.
*
* @param grpId Group id.
* @param partsCounter Partition mapped to update counter.
* @param margin Margin pointer.
* @return Earliest WAL pointer for group specified.
*/
@Nullable
public WALPointer searchEarliestWalPointer(int grpId, Map<Integer, Long> partsCounter, long margin) throws IgniteCheckedException {
if (F.isEmpty(partsCounter))
return null;
Map<Integer, Long> modifiedPartsCounter = new HashMap<>(partsCounter);
WALPointer minPtr = null;
LinkedList<WalPointerCandidate> historyPointerCandidate = new LinkedList<>();
for (Long cpTs : checkpoints(true)) {
CheckpointEntry cpEntry = entry(cpTs);
minPtr = getMinimalPointer(partsCounter, margin, minPtr, historyPointerCandidate, cpEntry);
Iterator<Map.Entry<Integer, Long>> iter = modifiedPartsCounter.entrySet().iterator();
WALPointer ptr = cpEntry.checkpointMark();
if (!wal.reserved(ptr)) {
throw new IgniteCheckedException("WAL pointer appropriate to the checkpoint was not reserved " + "[cp=(" + cpEntry.checkpointId() + ", " + U.format(cpEntry.timestamp()) + "), ptr=" + ptr + ']');
}
while (iter.hasNext()) {
Map.Entry<Integer, Long> entry = iter.next();
Long foundCntr = cpEntry.partitionCounter(wal, grpId, entry.getKey());
if (foundCntr != null && foundCntr <= entry.getValue()) {
iter.remove();
if (ptr == null) {
throw new IgniteCheckedException("Could not find start pointer for partition [part=" + entry.getKey() + ", partCntrSince=" + entry.getValue() + "]");
}
if (foundCntr + margin > entry.getValue()) {
historyPointerCandidate.add(new WalPointerCandidate(grpId, entry.getKey(), entry.getValue(), ptr, foundCntr));
continue;
}
partsCounter.put(entry.getKey(), entry.getValue() - margin);
if (minPtr == null || ptr.compareTo(minPtr) < 0)
minPtr = ptr;
}
}
if (F.isEmpty(modifiedPartsCounter))
break;
}
if (!F.isEmpty(modifiedPartsCounter)) {
Map.Entry<Integer, Long> entry = modifiedPartsCounter.entrySet().iterator().next();
throw new IgniteCheckedException("Could not find start pointer for partition [part=" + entry.getKey() + ", partCntrSince=" + entry.getValue() + "]");
}
minPtr = getMinimalPointer(partsCounter, margin, minPtr, historyPointerCandidate, null);
return minPtr;
}
use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.
the class CheckpointMarkersStorage method readCheckpointStatus.
/**
* @return Read checkpoint status.
* @throws IgniteCheckedException If failed to read checkpoint status page.
*/
@SuppressWarnings("TooBroadScope")
public CheckpointStatus readCheckpointStatus() throws IgniteCheckedException {
long lastStartTs = 0;
long lastEndTs = 0;
UUID startId = CheckpointStatus.NULL_UUID;
UUID endId = CheckpointStatus.NULL_UUID;
File startFile = null;
File endFile = null;
WALPointer startPtr = CheckpointStatus.NULL_PTR;
WALPointer endPtr = CheckpointStatus.NULL_PTR;
File dir = cpDir;
if (!dir.exists()) {
log.warning("Read checkpoint status: checkpoint directory is not found.");
return new CheckpointStatus(0, startId, startPtr, endId, endPtr);
}
File[] files = dir.listFiles();
for (File file : files) {
Matcher matcher = CP_FILE_NAME_PATTERN.matcher(file.getName());
if (matcher.matches()) {
long ts = Long.parseLong(matcher.group(1));
UUID id = UUID.fromString(matcher.group(2));
CheckpointEntryType type = CheckpointEntryType.valueOf(matcher.group(3));
if (type == CheckpointEntryType.START && ts > lastStartTs) {
lastStartTs = ts;
startId = id;
startFile = file;
} else if (type == CheckpointEntryType.END && ts > lastEndTs) {
lastEndTs = ts;
endId = id;
endFile = file;
}
}
}
ByteBuffer buf = ByteBuffer.allocate(WALPointer.POINTER_SIZE);
buf.order(ByteOrder.nativeOrder());
if (startFile != null)
startPtr = readPointer(startFile, buf);
if (endFile != null)
endPtr = readPointer(endFile, buf);
if (log.isInfoEnabled())
log.info("Read checkpoint status [startMarker=" + startFile + ", endMarker=" + endFile + ']');
return new CheckpointStatus(lastStartTs, startId, startPtr, endId, endPtr);
}
use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.
the class CheckpointWorkflow method markCheckpointBegin.
/**
* First stage of checkpoint which collects demanded information(dirty pages mostly).
*
* @param cpTs Checkpoint start timestamp.
* @param curr Current checkpoint event info.
* @param tracker Checkpoint metrics tracker.
* @param workProgressDispatcher Work progress dispatcher.
* @return Checkpoint collected info.
* @throws IgniteCheckedException if fail.
*/
public Checkpoint markCheckpointBegin(long cpTs, CheckpointProgressImpl curr, CheckpointMetricsTracker tracker, WorkProgressDispatcher workProgressDispatcher) throws IgniteCheckedException {
Collection<DataRegion> checkpointedRegions = dataRegions.get();
List<CheckpointListener> dbLsnrs = getRelevantCheckpointListeners(checkpointedRegions);
CheckpointRecord cpRec = new CheckpointRecord(memoryRecoveryRecordPtr);
memoryRecoveryRecordPtr = null;
IgniteFuture snapFut = null;
CheckpointPagesInfoHolder cpPagesHolder;
int dirtyPagesCount;
boolean hasPartitionsToDestroy;
WALPointer cpPtr = null;
CheckpointContextImpl ctx0 = new CheckpointContextImpl(curr, new PartitionAllocationMap(), checkpointCollectPagesInfoPool, workProgressDispatcher);
checkpointReadWriteLock.readLock();
try {
for (CheckpointListener lsnr : dbLsnrs) lsnr.beforeCheckpointBegin(ctx0);
ctx0.awaitPendingTasksFinished();
} finally {
checkpointReadWriteLock.readUnlock();
}
tracker.onLockWaitStart();
checkpointReadWriteLock.writeLock();
try {
curr.transitTo(LOCK_TAKEN);
tracker.onMarkStart();
// Listeners must be invoked before we write checkpoint record to WAL.
for (CheckpointListener lsnr : dbLsnrs) lsnr.onMarkCheckpointBegin(ctx0);
ctx0.awaitPendingTasksFinished();
tracker.onListenersExecuteEnd();
if (curr.nextSnapshot())
snapFut = snapshotMgr.onMarkCheckPointBegin(curr.snapshotOperation(), ctx0.partitionStatMap());
fillCacheGroupState(cpRec);
// There are allowable to replace pages only after checkpoint entry was stored to disk.
cpPagesHolder = beginAllCheckpoints(checkpointedRegions, curr.futureFor(MARKER_STORED_TO_DISK));
curr.currentCheckpointPagesCount(cpPagesHolder.pagesNum());
dirtyPagesCount = cpPagesHolder.pagesNum();
hasPartitionsToDestroy = !curr.getDestroyQueue().pendingReqs().isEmpty();
if (dirtyPagesCount > 0 || curr.nextSnapshot() || hasPartitionsToDestroy) {
// No page updates for this checkpoint are allowed from now on.
if (wal != null)
cpPtr = wal.log(cpRec);
if (cpPtr == null)
cpPtr = CheckpointStatus.NULL_PTR;
}
curr.transitTo(PAGE_SNAPSHOT_TAKEN);
} finally {
checkpointReadWriteLock.writeUnlock();
tracker.onLockRelease();
}
curr.transitTo(LOCK_RELEASED);
for (CheckpointListener lsnr : dbLsnrs) lsnr.onCheckpointBegin(ctx0);
if (snapFut != null) {
try {
snapFut.get();
} catch (IgniteException e) {
U.error(log, "Failed to wait for snapshot operation initialization: " + curr.snapshotOperation(), e);
}
}
if (dirtyPagesCount > 0 || hasPartitionsToDestroy) {
tracker.onWalCpRecordFsyncStart();
// Sync log outside the checkpoint write lock.
if (wal != null)
wal.flush(cpPtr, true);
tracker.onWalCpRecordFsyncEnd();
CheckpointEntry checkpointEntry = null;
if (checkpointMarkersStorage != null)
checkpointEntry = checkpointMarkersStorage.writeCheckpointEntry(cpTs, cpRec.checkpointId(), cpPtr, cpRec, CheckpointEntryType.START, skipSync);
curr.transitTo(MARKER_STORED_TO_DISK);
tracker.onSplitAndSortCpPagesStart();
GridConcurrentMultiPairQueue<PageMemoryEx, FullPageId> cpPages = splitAndSortCpPagesIfNeeded(cpPagesHolder);
tracker.onSplitAndSortCpPagesEnd();
return new Checkpoint(checkpointEntry, cpPages, curr);
} else {
if (curr.nextSnapshot() && wal != null)
wal.flush(null, true);
return new Checkpoint(null, GridConcurrentMultiPairQueue.EMPTY, curr);
}
}
Aggregations