use of org.apache.ignite.internal.processors.cache.tree.PendingRow in project ignite by apache.
the class IgniteCacheOffheapManagerImpl method expire.
/**
* {@inheritDoc}
*/
@Override
public boolean expire(GridCacheContext cctx, IgniteInClosure2X<GridCacheEntryEx, GridCacheVersion> c, int amount) throws IgniteCheckedException {
assert !cctx.isNear() : cctx.name();
if (hasPendingEntries && pendingEntries != null) {
GridCacheVersion obsoleteVer = null;
long now = U.currentTimeMillis();
GridCursor<PendingRow> cur;
if (grp.sharedGroup())
cur = pendingEntries.find(new PendingRow(cctx.cacheId()), new PendingRow(cctx.cacheId(), now, 0));
else
cur = pendingEntries.find(null, new PendingRow(CU.UNDEFINED_CACHE_ID, now, 0));
if (!cur.next())
return false;
int cleared = 0;
cctx.shared().database().checkpointReadLock();
try {
do {
PendingRow row = cur.get();
if (amount != -1 && cleared > amount)
return true;
if (row.key.partition() == -1)
row.key.partition(cctx.affinity().partition(row.key));
assert row.key != null && row.link != 0 && row.expireTime != 0 : row;
if (pendingEntries.removex(row)) {
if (obsoleteVer == null)
obsoleteVer = ctx.versions().next();
c.apply(cctx.cache().entryEx(row.key), obsoleteVer);
}
cleared++;
} while (cur.next());
} finally {
cctx.shared().database().checkpointReadUnlock();
}
}
return false;
}
use of org.apache.ignite.internal.processors.cache.tree.PendingRow in project ignite by apache.
the class CachePartitionDefragmentationManager method copyPartitionData.
/**
* Defragmentate partition.
*
* @param partCtx
* @param treeIter
* @throws IgniteCheckedException If failed.
*/
private void copyPartitionData(PartitionContext partCtx, TreeIterator treeIter) throws IgniteCheckedException {
CacheDataTree tree = partCtx.oldCacheDataStore.tree();
CacheDataTree newTree = partCtx.newCacheDataStore.tree();
newTree.enableSequentialWriteMode();
PendingEntriesTree newPendingTree = partCtx.newCacheDataStore.pendingTree();
AbstractFreeList<CacheDataRow> freeList = partCtx.newCacheDataStore.getCacheStoreFreeList();
long cpLockThreshold = 150L;
defragmentationCheckpoint.checkpointTimeoutLock().checkpointReadLock();
try {
AtomicLong lastCpLockTs = new AtomicLong(System.currentTimeMillis());
AtomicInteger entriesProcessed = new AtomicInteger();
treeIter.iterate(tree, partCtx.cachePageMemory, (tree0, io, pageAddr, idx) -> {
checkCancellation();
if (System.currentTimeMillis() - lastCpLockTs.get() >= cpLockThreshold) {
defragmentationCheckpoint.checkpointTimeoutLock().checkpointReadUnlock();
defragmentationCheckpoint.checkpointTimeoutLock().checkpointReadLock();
lastCpLockTs.set(System.currentTimeMillis());
}
AbstractDataLeafIO leafIo = (AbstractDataLeafIO) io;
CacheDataRow row = tree.getRow(io, pageAddr, idx);
int cacheId = row.cacheId();
// Reuse row that we just read.
row.link(0);
// "insertDataRow" will corrupt page memory if we don't do this.
if (row instanceof DataRow && !partCtx.oldGrpCtx.storeCacheIdInDataPage())
((DataRow) row).cacheId(CU.UNDEFINED_CACHE_ID);
freeList.insertDataRow(row, IoStatisticsHolderNoOp.INSTANCE);
// Put it back.
if (row instanceof DataRow)
((DataRow) row).cacheId(cacheId);
newTree.putx(row);
long newLink = row.link();
partCtx.linkMap.put(leafIo.getLink(pageAddr, idx), newLink);
if (row.expireTime() != 0)
newPendingTree.putx(new PendingRow(cacheId, row.expireTime(), newLink));
entriesProcessed.incrementAndGet();
return true;
});
checkCancellation();
defragmentationCheckpoint.checkpointTimeoutLock().checkpointReadUnlock();
defragmentationCheckpoint.checkpointTimeoutLock().checkpointReadLock();
freeList.saveMetadata(IoStatisticsHolderNoOp.INSTANCE);
copyCacheMetadata(partCtx);
} finally {
defragmentationCheckpoint.checkpointTimeoutLock().checkpointReadUnlock();
}
}
use of org.apache.ignite.internal.processors.cache.tree.PendingRow in project ignite by apache.
the class IgniteCacheOffheapManagerImpl method removeCacheData.
/**
* @param cacheId Cache ID.
*/
private void removeCacheData(int cacheId) {
assert grp.affinityNode();
try {
if (grp.sharedGroup()) {
assert cacheId != CU.UNDEFINED_CACHE_ID;
for (CacheDataStore store : cacheDataStores()) store.clear(cacheId);
// Clear non-persistent pending tree if needed.
if (pendingEntries != null) {
PendingRow row = new PendingRow(cacheId);
GridCursor<PendingRow> cursor = pendingEntries.find(row, row, PendingEntriesTree.WITHOUT_KEY);
while (cursor.next()) {
boolean res = pendingEntries.removex(cursor.get());
assert res;
}
}
}
} catch (IgniteCheckedException e) {
throw new IgniteException(e.getMessage(), e);
}
}
use of org.apache.ignite.internal.processors.cache.tree.PendingRow in project ignite by apache.
the class PendingTreeCorruptionTest method testCorruptionWhileLoadingData.
/**
*/
@Test
public void testCorruptionWhileLoadingData() throws Exception {
IgniteEx ig = startGrid(0);
ig.cluster().state(ClusterState.ACTIVE);
String expireCacheName = "cacheWithExpire";
String regularCacheName = "cacheWithoutExpire";
String grpName = "cacheGroup";
IgniteCache<Object, Object> expireCache = ig.getOrCreateCache(new CacheConfiguration<>(expireCacheName).setExpiryPolicyFactory(AccessedExpiryPolicy.factoryOf(new Duration(MINUTES, 10))).setGroupName(grpName));
IgniteCache<Object, Object> regularCache = ig.getOrCreateCache(new CacheConfiguration<>(regularCacheName).setGroupName(grpName));
// This will initialize partition and cache structures.
expireCache.put(0, 0);
expireCache.remove(0);
int expireCacheId = CU.cacheGroupId(expireCacheName, grpName);
CacheGroupContext grp = ig.context().cache().cacheGroup(CU.cacheId(grpName));
IgniteCacheOffheapManager.CacheDataStore store = grp.topology().localPartition(0).dataStore();
assertNotNull(store);
// Get pending tree of expire cache.
PendingEntriesTree pendingTree = store.pendingTree();
long year = TimeUnit.DAYS.toMillis(365);
long expiration = System.currentTimeMillis() + year;
ig.context().cache().context().database().checkpointReadLock();
try {
// Carefully calculated number. Just enough for the first split to happen, but not more.
for (int i = 0; i < 202; i++) // link != 0
pendingTree.putx(new PendingRow(expireCacheId, expiration, expiration + i));
// Open cursor, it'll cache first leaf of the tree.
GridCursor<PendingRow> cur = pendingTree.find(null, new PendingRow(expireCacheId, expiration + year, 0), PendingEntriesTree.WITHOUT_KEY);
// Required for "do" loop to work.
assertTrue(cur.next());
int cnt = 0;
// Emulate real expiry loop but with a more precise control.
do {
PendingRow row = cur.get();
pendingTree.removex(row);
// with its sibling, meaning that cached "nextPageId" points to empty page from reuse list.
if (row.link - row.expireTime == 100) {
// Put into another cache will take a page from reuse list first. This means that cached
// "nextPageId" points to a data page.
regularCache.put(0, 0);
}
cnt++;
} while (cur.next());
assertEquals(202, cnt);
} finally {
ig.context().cache().context().database().checkpointReadUnlock();
}
}
use of org.apache.ignite.internal.processors.cache.tree.PendingRow in project ignite by apache.
the class UpgradePendingTreeToPerPartitionTask method processPendingTree.
/**
* Move pending rows for CacheGroup entries to per-partition PendingTree.
* Invalid pending rows will be ignored.
*
* @param grp Cache group.
* @param oldPendingEntries Old-style PendingTree.
* @throws IgniteCheckedException If error occurs.
*/
private void processPendingTree(CacheGroupContext grp, PendingEntriesTree oldPendingEntries) throws IgniteCheckedException {
final PageMemory pageMemory = grp.dataRegion().pageMemory();
final IgniteCacheDatabaseSharedManager db = grp.shared().database();
final Set<Integer> cacheIds = grp.cacheIds();
PendingRow row = null;
int processedEntriesCnt = 0;
int skippedEntries = 0;
// Re-acquire checkpoint lock for every next batch.
while (!Thread.currentThread().isInterrupted()) {
int cnt = 0;
db.checkpointReadLock();
try {
GridCursor<PendingRow> cursor = oldPendingEntries.find(row, null, WITHOUT_KEY);
while (cnt++ < BATCH_SIZE && cursor.next()) {
row = cursor.get();
assert row.link != 0 && row.expireTime != 0 : row;
GridCacheEntryEx entry;
// Lost cache or lost entry.
if (!cacheIds.contains(row.cacheId) || (entry = getEntry(grp, row)) == null) {
skippedEntries++;
oldPendingEntries.removex(row);
continue;
}
entry.lockEntry();
try {
if (processRow(pageMemory, grp, row))
processedEntriesCnt++;
else
skippedEntries++;
} finally {
entry.unlockEntry();
}
oldPendingEntries.removex(row);
}
if (cnt < BATCH_SIZE)
break;
} finally {
db.checkpointReadUnlock();
}
}
log.info("PendingTree upgraded: " + "[grpId=" + grp.groupId() + ", grpName=" + grp.name() + ", processedEntries=" + processedEntriesCnt + ", failedEntries=" + skippedEntries + ']');
}
Aggregations