Search in sources :

Example 1 with LRUEntry

use of org.apache.geode.internal.cache.lru.LRUEntry in project geode by apache.

the class VMCachedDeserializable method getDeserializedValue.

public Object getDeserializedValue(Region r, RegionEntry re) {
    Object v = this.value;
    if (v instanceof byte[]) {
        // org.apache.geode.internal.cache.GemFireCache.getInstance().getLogger().info("DEBUG
        // getDeserializedValue r=" + r + " re=" + re, new RuntimeException("STACK"));
        LRUEntry le = null;
        if (re != null) {
            assert r != null;
            if (re instanceof LRUEntry) {
                le = (LRUEntry) re;
            }
        }
        if (le != null) {
            if (r instanceof PartitionedRegion) {
                r = ((PartitionedRegion) r).getBucketRegion(re.getKey());
            }
            boolean callFinish = false;
            AbstractLRURegionMap lruMap = null;
            if (r != null) {
                // fix for bug 44795
                lruMap = (AbstractLRURegionMap) ((LocalRegion) r).getRegionMap();
            }
            boolean threadAlreadySynced = Thread.holdsLock(le);
            boolean isCacheListenerInvoked = re.isCacheListenerInvocationInProgress();
            synchronized (le) {
                v = this.value;
                if (!(v instanceof byte[]))
                    return v;
                v = EntryEventImpl.deserialize((byte[]) v);
                if (threadAlreadySynced && !isCacheListenerInvoked) {
                    // if the thread that called us was already synced.
                    return v;
                }
                if (!(v instanceof PdxInstance)) {
                    this.value = v;
                    if (lruMap != null) {
                        callFinish = lruMap.beginChangeValueForm(le, this, v);
                    }
                }
            }
            if (callFinish && !isCacheListenerInvoked) {
                lruMap.finishChangeValueForm();
            }
        } else {
            // we sync on this so we will only do one deserialize
            synchronized (this) {
                v = this.value;
                if (!(v instanceof byte[]))
                    return v;
                v = EntryEventImpl.deserialize((byte[]) v);
                if (!(v instanceof PdxInstance)) {
                    this.value = v;
                }
            // ObjectSizer os = null;
            // if (r != null) {
            // EvictionAttributes ea = r.getAttributes().getEvictionAttributes();
            // if (ea != null) {
            // os = ea.getObjectSizer();
            // }
            // int vSize = CachedDeserializableFactory.calcMemSize(v, os, false, false);
            // if (vSize != -1) {
            // int oldSize = this.valueSize;
            // this.valueSize = vSize;
            // if (r instanceof BucketRegion) {
            // BucketRegion br = (BucketRegion)r;
            // br.updateBucketMemoryStats(vSize - oldSize);
            // }
            // // @todo do we need to update some lru stats since the size changed?
            // }
            // // If vSize == -1 then leave valueSize as is which is the serialized size.
            }
        }
    }
    return v;
}
Also used : PdxInstance(org.apache.geode.pdx.PdxInstance) LRUEntry(org.apache.geode.internal.cache.lru.LRUEntry)

Example 2 with LRUEntry

use of org.apache.geode.internal.cache.lru.LRUEntry 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 3 with LRUEntry

use of org.apache.geode.internal.cache.lru.LRUEntry 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 4 with LRUEntry

use of org.apache.geode.internal.cache.lru.LRUEntry in project geode by apache.

the class AbstractLRURegionMap method lruUpdateCallback.

@Override
public void lruUpdateCallback() {
    final boolean isDebugEnabled_LRU = logger.isTraceEnabled(LogMarker.LRU);
    if (getCallbackDisabled()) {
        return;
    }
    final int delta = getDelta();
    int bytesToEvict = delta;
    resetThreadLocals();
    if (isDebugEnabled_LRU && _isOwnerALocalRegion()) {
        logger.trace(LogMarker.LRU, "lruUpdateCallback; list size is: {}; actual size is: {}; map size is: {}; delta is: {}; limit is: {}; tombstone count={}", getTotalEntrySize(), this._getLruList().getExpensiveListCount(), size(), delta, getLimit(), _getOwner().getTombstoneCount());
    }
    LRUStatistics stats = _getLruList().stats();
    if (!_isOwnerALocalRegion()) {
        changeTotalEntrySize(delta);
    // instead of evicting we just quit faulting values in
    } else if (_getCCHelper().getEvictionAlgorithm().isLRUHeap()) {
        changeTotalEntrySize(delta);
        try {
            while (bytesToEvict > 0 && _getCCHelper().mustEvict(stats, _getOwner(), bytesToEvict)) {
                boolean evictFromThisRegion = true;
                if (HeapEvictor.EVICT_HIGH_ENTRY_COUNT_BUCKETS_FIRST && _getOwner() instanceof BucketRegion) {
                    long bytesEvicted = 0;
                    long totalBytesEvicted = 0;
                    List<BucketRegion> regions = ((BucketRegion) _getOwner()).getPartitionedRegion().getSortedBuckets();
                    Iterator<BucketRegion> iter = regions.iterator();
                    while (iter.hasNext()) {
                        BucketRegion region = iter.next();
                        // only primaries can trigger inline eviction fix for 41814
                        if (!region.getBucketAdvisor().isPrimary()) {
                            try {
                                bytesEvicted = ((AbstractLRURegionMap) region.entries).centralizedLruUpdateCallback();
                                if (bytesEvicted == 0) {
                                    iter.remove();
                                } else {
                                    evictFromThisRegion = false;
                                }
                                totalBytesEvicted += bytesEvicted;
                                bytesToEvict -= bytesEvicted;
                                if (bytesEvicted > bytesToEvict) {
                                    bytesToEvict = 0;
                                    break;
                                }
                                if (totalBytesEvicted > bytesToEvict) {
                                    break;
                                }
                            } catch (RegionDestroyedException rd) {
                                region.cache.getCancelCriterion().checkCancelInProgress(rd);
                            } catch (Exception e) {
                                region.cache.getCancelCriterion().checkCancelInProgress(e);
                                logger.warn(LocalizedMessage.create(LocalizedStrings.Eviction_EVICTOR_TASK_EXCEPTION, new Object[] { e.getMessage() }), e);
                            }
                        }
                    }
                }
                if (evictFromThisRegion) {
                    LRUEntry removalEntry = (LRUEntry) _getLruList().getLRUEntry();
                    if (removalEntry != null) {
                        int sizeOfValue = evictEntry(removalEntry, stats);
                        if (sizeOfValue != 0) {
                            bytesToEvict -= sizeOfValue;
                            if (isDebugEnabled_LRU) {
                                logger.trace(LogMarker.LRU, "evicted entry key={} total entry size is now: {} bytesToEvict :{}", removalEntry.getKey(), getTotalEntrySize(), bytesToEvict);
                            }
                            stats.incEvictions();
                            if (_isOwnerALocalRegion()) {
                                if (_getOwner() instanceof BucketRegion) {
                                    ((BucketRegion) _getOwner()).incEvictions(1);
                                }
                            }
                            if (isDebugEnabled_LRU) {
                                logger.trace(LogMarker.LRU, "evictions={}", stats.getEvictions());
                            }
                            _getCCHelper().afterEviction();
                        }
                    } else {
                        if (getTotalEntrySize() != 0) {
                            if (isDebugEnabled_LRU) {
                                logger.trace(LogMarker.LRU, "leaving evict loop early");
                            }
                        }
                        break;
                    }
                }
            }
        } catch (RegionClearedException e) {
            // TODO Auto-generated catch block
            if (isDebugEnabled_LRU) {
                logger.trace(LogMarker.LRU, "exception ={}", e.getCause());
            }
        }
    } else {
        try {
            // to fix bug 48285 do no evict if bytesToEvict <= 0.
            while (bytesToEvict > 0 && _getCCHelper().mustEvict(stats, _getOwner(), bytesToEvict)) {
                LRUEntry removalEntry = (LRUEntry) _getLruList().getLRUEntry();
                if (removalEntry != null) {
                    if (evictEntry(removalEntry, stats) != 0) {
                        if (isDebugEnabled_LRU) {
                            logger.trace(LogMarker.LRU, "evicted entry key(2)={} total entry size is now: {} bytesToEvict :", removalEntry.getKey(), getTotalEntrySize(), bytesToEvict);
                        }
                        stats.incEvictions();
                        if (_isOwnerALocalRegion()) {
                            if (_getOwner() instanceof BucketRegion) {
                                ((BucketRegion) _getOwner()).incEvictions(1);
                            }
                        }
                        if (isDebugEnabled_LRU) {
                            logger.trace(LogMarker.LRU, "evictions={}", stats.getEvictions());
                        }
                        _getCCHelper().afterEviction();
                    }
                } else {
                    if (getTotalEntrySize() != 0) {
                        if (isDebugEnabled_LRU) {
                            logger.trace(LogMarker.LRU, "leaving evict loop early");
                        }
                    }
                    break;
                }
            }
            changeTotalEntrySize(delta);
        } catch (RegionClearedException e) {
            // TODO Auto-generated catch block
            if (isDebugEnabled_LRU) {
                logger.debug("exception ={}", e.getCause());
            }
        }
    }
    if (isDebugEnabled_LRU) {
        logger.trace(LogMarker.LRU, "callback complete.  LRU size is now {}", _getLruList().stats().getCounter());
    }
// If in transaction context (either local or message)
// reset the tx thread local
}
Also used : RegionDestroyedException(org.apache.geode.cache.RegionDestroyedException) LRUEntry(org.apache.geode.internal.cache.lru.LRUEntry) LRUStatistics(org.apache.geode.internal.cache.lru.LRUStatistics) Iterator(java.util.Iterator) List(java.util.List) StoredObject(org.apache.geode.internal.offheap.StoredObject) RegionDestroyedException(org.apache.geode.cache.RegionDestroyedException) InternalGemFireException(org.apache.geode.InternalGemFireException)

Example 5 with LRUEntry

use of org.apache.geode.internal.cache.lru.LRUEntry in project geode by apache.

the class AbstractLRURegionMap method lruEntryDestroy.

@Override
protected void lruEntryDestroy(RegionEntry re) {
    final LRUEntry e = (LRUEntry) re;
    if (logger.isTraceEnabled(LogMarker.LRU)) {
        logger.trace(LogMarker.LRU, "lruEntryDestroy 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());
    }
    // if (this.lruCreatedKey == re.getKey()) {
    // String method = Thread.currentThread().getStackTrace()[5].getMethodName();
    // }
    // boolean wasEvicted = e.testEvicted();
    /* boolean removed = */
    _getLruList().unlinkEntry(e);
    // if (removed || wasEvicted) { // evicted entries have already been removed from the list
    // subtract the size.
    changeTotalEntrySize(-1 * e.getEntrySize());
    Token vTok = re.getValueAsToken();
    if (vTok == Token.DESTROYED || vTok == Token.TOMBSTONE) {
        // OFFHEAP noop TODO: use
        // re.isDestroyedOrTombstone
        // if in token mode we need to recalculate the size of the entry since it's
        // staying in the map and may be resurrected
        e.updateEntrySize(_getCCHelper());
    }
// } else if (debug) {
// debugLogging("entry not removed from LRU list");
// }
}
Also used : LRUEntry(org.apache.geode.internal.cache.lru.LRUEntry)

Aggregations

LRUEntry (org.apache.geode.internal.cache.lru.LRUEntry)7 LRUStatistics (org.apache.geode.internal.cache.lru.LRUStatistics)2 NewLRUClockHand (org.apache.geode.internal.cache.lru.NewLRUClockHand)2 StoredObject (org.apache.geode.internal.offheap.StoredObject)2 Iterator (java.util.Iterator)1 List (java.util.List)1 InternalGemFireException (org.apache.geode.InternalGemFireException)1 DiskAccessException (org.apache.geode.cache.DiskAccessException)1 RegionDestroyedException (org.apache.geode.cache.RegionDestroyedException)1 PdxInstance (org.apache.geode.pdx.PdxInstance)1