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;
}
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);
}
}
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);
}
}
}
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
}
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");
// }
}
Aggregations