use of org.apache.geode.internal.cache.lru.NewLRUClockHand in project geode by apache.
the class AbstractLRURegionMap method initialize.
protected void initialize(Object owner, Attributes attr, InternalRegionArguments internalRegionArgs) {
super.initialize(owner, attr, internalRegionArgs, true);
EvictionAlgorithm ea;
LRUAlgorithm ec;
if (owner instanceof LocalRegion) {
ea = ((LocalRegion) owner).getEvictionAttributes().getAlgorithm();
ec = ((LocalRegion) owner).getEvictionController();
} else if (owner instanceof PlaceHolderDiskRegion) {
PlaceHolderDiskRegion phdr = (PlaceHolderDiskRegion) owner;
ea = phdr.getActualLruAlgorithm();
ec = phdr.getEvictionAttributes().createEvictionController(null, phdr.getOffHeap());
} else {
throw new IllegalStateException("expected LocalRegion or PlaceHolderDiskRegion");
}
this.evictionController = ec;
if (ea.isLRUMemory()) {
((MemLRUCapacityController) ec).setEntryOverHead(getEntryOverHead());
}
if (ea.isLRUHeap()) {
((HeapLRUCapacityController) ec).setEntryOverHead(getEntryOverHead());
}
_setCCHelper(getHelper(ec));
/*
* modification for LIFO Logic incubation
*
*/
if (ea == EvictionAlgorithm.LIFO_ENTRY || ea == EvictionAlgorithm.LIFO_MEMORY) {
_setLruList(new NewLIFOClockHand(owner, _getCCHelper(), internalRegionArgs));
} else {
_setLruList(new NewLRUClockHand(owner, _getCCHelper(), internalRegionArgs));
}
}
use of org.apache.geode.internal.cache.lru.NewLRUClockHand in project geode by apache.
the class AbstractLRURegionMap method lruEntryFaultIn.
/**
* Called by DiskEntry.Helper.faultInValue
*/
@Override
public void lruEntryFaultIn(LRUEntry e) {
if (logger.isDebugEnabled()) {
logger.debug("lruEntryFaultIn for key={} size={}", e.getKey(), e.getEntrySize());
}
NewLRUClockHand lruList = _getLruList();
if (_isOwnerALocalRegion()) {
DiskRegion disk = _getOwner().getDiskRegion();
boolean possibleClear = disk != null && disk.didClearCountChange();
if (!possibleClear || this._getOwner().basicGetEntry(e.getKey()) == e) {
lruEntryUpdate(e);
e.unsetEvicted();
lruList.appendEntry(e);
}
} else {
lruEntryUpdate(e);
lruList.appendEntry(e);
}
}
use of org.apache.geode.internal.cache.lru.NewLRUClockHand in project geode by apache.
the class AbstractLRURegionMap method lruEntryCreate.
/*
* Asif : Motivation: An entry which is no longer existing in the system due to clear operation,
* should not be present the LRUList being used by the region.
*
* Case1 : An entry has been written to disk & on its return code path, it invokes lruCreate or
* lruUpdate. Before starting the operation of writing to disk, the HTree reference is set in the
* threadlocal. A clear operation changes the Htree reference in a write lock. Thus if the htree
* reference has not changed till this point, it would mean either the entry is still valid or a
* clear operation is in progress but has not changed the Htree Reference . Since we store the
* LRUList in a local variable, it implies that if clear occurs , it will go in the stale list &
* if not it goes in the right list. Both ways we are safe.
*
* Case 2: The Htree reference has changed ( implying a clear conflic with put) but the entry is
* valid. This is possible as we first set the Htree Ref in thread local. Now before the update
* operation has acquired the entry , clear happens. As a result the update operation has become
* create. Since the clear changes the Htree Ref & the LRUList in a write lock & hence by the time
* the original update operation acquires the read lock, the LRUList has already been changed by
* clear. Now in the update operation's return path the List which it stores in local variable is
* bound to be the new List. Since our code checks if the entry reference exists in the region in
* case of conflict & if yes, we append the entry to the List. It is guaranteed to be added to the
* new List.
*
* Also it is necessary that when we clear the region, first the concurrent map of the region
* containing entries needs to be cleared. The Htree Reference should be reset after that. And
* then we should be resetting the LRUList. Previously the Htree reference was being set before
* clearing the Map. This caused Bug 37606. If the order of clear operation on disk region is (
* incorrect ) 1) map.clear 2) Resetting the LRUList 3) Changing the Htree ref Then following bug
* can occur., During entry operation on its return path, invokes lruUpdate/lruCreate. By that
* time the clear proceeds & it has reset the LRUList & cleared the entries. But as the Htree ref
* has not changed, we would take the locally available LRUList ( which may be the new List) &
* append the entry to the List.
*
*
*
*/
@Override
protected void lruEntryCreate(RegionEntry re) {
LRUEntry e = (LRUEntry) re;
// Assert.assertFalse(e._getValue() instanceof DiskEntry.RecoveredEntry)
if (logger.isTraceEnabled(LogMarker.LRU)) {
logger.trace(LogMarker.LRU, "lruEntryCreate for key={}; list size is: {}; actual size is: {}; map size is: {}; entry size: {}; in lru clock: {}", re.getKey(), getTotalEntrySize(), this._getLruList().getExpensiveListCount(), size(), e.getEntrySize(), !e.testEvicted());
}
// this.lruCreatedKey = re.getKey(); // [ bruce ] for DEBUGGING only
e.unsetEvicted();
NewLRUClockHand lruList = _getLruList();
DiskRegion disk = _getOwner().getDiskRegion();
boolean possibleClear = disk != null && disk.didClearCountChange();
if (!possibleClear || this._getOwner().basicGetEntry(re.getKey()) == re) {
lruList.appendEntry(e);
lruEntryUpdate(e);
}
}
use of org.apache.geode.internal.cache.lru.NewLRUClockHand in project geode by apache.
the class AbstractLRURegionMap method lruEntryUpdate.
@Override
protected void lruEntryUpdate(RegionEntry re) {
final LRUEntry e = (LRUEntry) re;
setDelta(e.updateEntrySize(_getCCHelper()));
if (logger.isDebugEnabled()) {
logger.debug("lruEntryUpdate for key={} size={}", re.getKey(), e.getEntrySize());
}
NewLRUClockHand lruList = _getLruList();
if (_isOwnerALocalRegion()) {
DiskRegion disk = _getOwner().getDiskRegion();
boolean possibleClear = disk != null && disk.didClearCountChange();
if (!possibleClear || this._getOwner().basicGetEntry(re.getKey()) == re) {
if (e instanceof DiskEntry) {
if (!e.testEvicted()) {
lruList.appendEntry(e);
}
}
// Why reset the refcount? All the txs that currently reference
// this region entry still do but they will now fail with conflicts.
// But they also have logic in them to dec the refcount.
// I think we did the resetRefCount thinking it was safe
// to drop it back to zero since the RE was modified and give
// us a chance to evict it. But if the txs that are going to fail
// with a conflict still do refCountDecs then after the reset any
// new txs that inc the refcount may have their count decd by one of
// the old txs allowing the entry to be evicted and causing a tx conflict.
// TODO: this should now be safe but why the odd condition for this block
// and why call lruList.appendEntry twice (once above and once in resetRefCount.
// Also lruEntryUpdate only happens on an lru. Do we need to call reset for the non-lru
// (expiration) case?
e.resetRefCount(lruList);
}
} else {
// No need to call resetRefCount since tx are not yet possible.
if (!e.testEvicted()) {
lruList.appendEntry(e);
}
}
}
use of org.apache.geode.internal.cache.lru.NewLRUClockHand in project geode by apache.
the class DiskRegionJUnitTest method testClearInteractionWithLRUList_Bug37605.
/**
* If an entry which has just been written on the disk, sees clear just before updating the
* LRULiist, then that deleted entry should not go into the LRUList
*/
@Test
public void testClearInteractionWithLRUList_Bug37605() throws Exception {
DiskRegionProperties props = new DiskRegionProperties();
props.setOverflow(true);
props.setOverFlowCapacity(1);
props.setDiskDirs(dirs);
props.setRegionName("IGNORE_EXCEPTION_testClearInteractionWithLRUList_Bug37605");
final Region region = DiskRegionHelperFactory.getSyncOverFlowAndPersistRegion(cache, props);
final Thread th = new Thread(new Runnable() {
public void run() {
region.clear();
}
});
region.getAttributesMutator().setCacheListener(new CacheListenerAdapter() {
public void afterCreate(EntryEvent event) {
th.start();
}
});
region.create("key1", "value1");
try {
cache.getLogger().info("waiting for clear to finish");
ThreadUtils.join(th, 30 * 1000);
} catch (Exception ie) {
DiskRegionJUnitTest.this.exceptionOccurred = true;
DiskRegionJUnitTest.this.failureCause = ie.toString();
}
assertFalse(this.failureCause, this.exceptionOccurred);
NewLRUClockHand lruList = ((VMLRURegionMap) ((LocalRegion) region).entries)._getLruList();
assertEquals(region.size(), 0);
lruList.audit();
assertNull("The LRU List should have been empty instead it contained a cleared entry", lruList.getLRUEntry());
}
Aggregations