Search in sources :

Example 1 with NewLRUClockHand

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));
    }
}
Also used : HeapLRUCapacityController(org.apache.geode.internal.cache.lru.HeapLRUCapacityController) LRUAlgorithm(org.apache.geode.internal.cache.lru.LRUAlgorithm) MemLRUCapacityController(org.apache.geode.internal.cache.lru.MemLRUCapacityController) NewLIFOClockHand(org.apache.geode.internal.cache.lru.NewLIFOClockHand) NewLRUClockHand(org.apache.geode.internal.cache.lru.NewLRUClockHand) EvictionAlgorithm(org.apache.geode.cache.EvictionAlgorithm)

Example 2 with NewLRUClockHand

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);
    }
}
Also used : NewLRUClockHand(org.apache.geode.internal.cache.lru.NewLRUClockHand)

Example 3 with NewLRUClockHand

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);
    }
}
Also used : LRUEntry(org.apache.geode.internal.cache.lru.LRUEntry) NewLRUClockHand(org.apache.geode.internal.cache.lru.NewLRUClockHand)

Example 4 with NewLRUClockHand

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);
        }
    }
}
Also used : LRUEntry(org.apache.geode.internal.cache.lru.LRUEntry) NewLRUClockHand(org.apache.geode.internal.cache.lru.NewLRUClockHand)

Example 5 with NewLRUClockHand

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());
}
Also used : CacheListenerAdapter(org.apache.geode.cache.util.CacheListenerAdapter) EntryEvent(org.apache.geode.cache.EntryEvent) Region(org.apache.geode.cache.Region) NewLRUClockHand(org.apache.geode.internal.cache.lru.NewLRUClockHand) EntryNotFoundException(org.apache.geode.cache.EntryNotFoundException) DiskAccessException(org.apache.geode.cache.DiskAccessException) Test(org.junit.Test) IntegrationTest(org.apache.geode.test.junit.categories.IntegrationTest)

Aggregations

NewLRUClockHand (org.apache.geode.internal.cache.lru.NewLRUClockHand)5 LRUEntry (org.apache.geode.internal.cache.lru.LRUEntry)2 DiskAccessException (org.apache.geode.cache.DiskAccessException)1 EntryEvent (org.apache.geode.cache.EntryEvent)1 EntryNotFoundException (org.apache.geode.cache.EntryNotFoundException)1 EvictionAlgorithm (org.apache.geode.cache.EvictionAlgorithm)1 Region (org.apache.geode.cache.Region)1 CacheListenerAdapter (org.apache.geode.cache.util.CacheListenerAdapter)1 HeapLRUCapacityController (org.apache.geode.internal.cache.lru.HeapLRUCapacityController)1 LRUAlgorithm (org.apache.geode.internal.cache.lru.LRUAlgorithm)1 MemLRUCapacityController (org.apache.geode.internal.cache.lru.MemLRUCapacityController)1 NewLIFOClockHand (org.apache.geode.internal.cache.lru.NewLIFOClockHand)1 IntegrationTest (org.apache.geode.test.junit.categories.IntegrationTest)1 Test (org.junit.Test)1