LocalRegion region = _getOwner(); if (action.isLocalDestroy()) { int size = entry.getEntrySize(); if (region.evictDestroy(entry)) { stats.incDestroys(); int change = 0; synchronized (entry) { if (entry.isInUseByTransaction()) { entry.unsetEvicted(); if (logger.isTraceEnabled(LogMarker.LRU_VERBOSE)) { logger.trace(LogMarker.LRU_VERBOSE, "No eviction of transactional entry for key={}", entry.getKey()); Token entryVal = entry.getValueAsToken(); if (entryVal == null) { if (logger.isTraceEnabled(LogMarker.LRU_VERBOSE)) { logger.trace(LogMarker.LRU_VERBOSE, "no need to evict already evicted key={}", entry.getKey()); entry.getKey()); entry.setEvicted(); change = DiskEntry.Helper.overflowToDisk((DiskEntry) entry, region, getEvictionController()); logger.trace(LogMarker.LRU_VERBOSE, "no need to evict token for key={} because moving its value to disk resulted in a net change of {} bytes.", entry.getKey(), change);
@Override public boolean confirmEvictionDestroy(RegionEntry regionEntry) { // We assume here that a LRURegionMap contains LRUEntries EvictableEntry lruRe = (EvictableEntry) regionEntry; if (lruRe.isInUseByTransaction() || lruRe.isDestroyed()) { lruRe.unsetEvicted(); return false; } else { return true; } }
@Override public void lruEntryUpdate(RegionEntry re) { final EvictableEntry e = (EvictableEntry) re; setDelta(e.updateEntrySize(getEvictionController())); if (logger.isDebugEnabled()) { logger.debug("lruEntryUpdate for key={} size={}", re.getKey(), e.getEntrySize()); if (!possibleClear || this._getOwner().basicGetEntry(re.getKey()) == re) { if (e instanceof DiskEntry) { if (!e.isEvicted()) { lruList.appendEntry(e); e.resetRefCount(lruList); if (!e.isEvicted()) { lruList.appendEntry(e);
@Override public void lruEntryDestroy(RegionEntry regionEntry) { final EvictableEntry e = (EvictableEntry) regionEntry; if (logger.isTraceEnabled(LogMarker.LRU_VERBOSE)) { logger.trace(LogMarker.LRU_VERBOSE, "lruEntryDestroy for key={}; list size is: {}; actual size is: {}; map size is: {}; entry size: {}; in lru clock: {}", regionEntry.getKey(), getTotalEntrySize(), this.getEvictionList().size(), size(), e.getEntrySize(), !e.isEvicted()); } getEvictionList().destroyEntry(e); changeTotalEntrySize(-1 * e.getEntrySize());// subtract the size. Token vTok = regionEntry.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(getEvictionController()); } }
/** * Called by DiskEntry.Helper.faultInValue */ @Override public void lruEntryFaultIn(EvictableEntry e) { if (logger.isDebugEnabled()) { logger.debug("lruEntryFaultIn for key={} size={}", e.getKey(), e.getEntrySize()); } EvictionList lruList = getEvictionList(); 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); } }
@Test public void evictDestroyWithExistingTombstoneInUseByTransactionInTokenModeDoesNothing() throws RegionClearedException { CustomEntryConcurrentHashMap<String, EvictableEntry> map = mock(CustomEntryConcurrentHashMap.class); EvictableEntry entry = mock(EvictableEntry.class); when(entry.isInUseByTransaction()).thenReturn(true); when(entry.getValue()).thenReturn(Token.TOMBSTONE); when(map.get(KEY)).thenReturn(entry); final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map); final EntryEventImpl event = createEventForDestroy(arm._getOwner()); final Object expectedOldValue = null; final boolean inTokenMode = true; final boolean duringRI = false; final boolean evict = true; assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, expectedOldValue, false)) .isFalse(); verify(entry, never()).destroy(any(), any(), anyBoolean(), anyBoolean(), any(), anyBoolean(), anyBoolean()); verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean()); verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), any()); }
@Test public void destroyWithConcurrentChangeFromTombstoneToValidRetriesAndDoesDestroy() throws RegionClearedException { CustomEntryConcurrentHashMap<Object, EvictableEntry> map = mock(CustomEntryConcurrentHashMap.class); EvictableEntry entry = mock(EvictableEntry.class); when(entry.getValue()).thenReturn("value"); when(entry.isTombstone()).thenReturn(true).thenReturn(false); when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), anyBoolean(), anyBoolean())) .thenReturn(true); when(map.get(KEY)).thenReturn(entry); final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map); final EntryEventImpl event = createEventForDestroy(arm._getOwner()); final Object expectedOldValue = null; final boolean inTokenMode = false; final boolean duringRI = false; final boolean evict = false; assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, expectedOldValue, false)) .isTrue(); verify(entry, times(1)).destroy(eq(arm._getOwner()), eq(event), eq(false), anyBoolean(), eq(expectedOldValue), anyBoolean(), anyBoolean()); boolean invokeCallbacks = true; verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), eq(inTokenMode), eq(false), eq(duringRI), eq(invokeCallbacks)); verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), eq(inTokenMode), eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue)); }
@Override public void lruEntryCreate(RegionEntry re) { EvictableEntry e = (EvictableEntry) re; if (logger.isTraceEnabled(LogMarker.LRU_VERBOSE)) { logger.trace(LogMarker.LRU_VERBOSE, "lruEntryCreate for key={}; list size is: {}; actual size is: {}; map size is: {}; entry size: {}; in lru clock: {}", re.getKey(), getTotalEntrySize(), this.getEvictionList().size(), size(), e.getEntrySize(), !e.isEvicted()); } e.unsetEvicted(); EvictionList lruList = getEvictionList(); DiskRegion disk = _getOwner().getDiskRegion(); boolean possibleClear = disk != null && disk.didClearCountChange(); if (!possibleClear || this._getOwner().basicGetEntry(re.getKey()) == re) { lruList.appendEntry(e); lruEntryUpdate(e); } }
@Test public void destroyWithConcurrentChangeFromNullToValidRetriesAndDoesDestroy() throws RegionClearedException { CustomEntryConcurrentHashMap<Object, EvictableEntry> map = mock(CustomEntryConcurrentHashMap.class); EvictableEntry entry = mock(EvictableEntry.class); when(entry.getValue()).thenReturn("value"); when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), anyBoolean(), anyBoolean())) .thenReturn(true); when(map.get(KEY)).thenReturn(null).thenReturn(entry); when(map.putIfAbsent(eq(KEY), any())).thenReturn(entry); final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map); final EntryEventImpl event = createEventForDestroy(arm._getOwner()); final Object expectedOldValue = null; final boolean inTokenMode = false; final boolean duringRI = false; final boolean evict = false; assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, expectedOldValue, false)) .isTrue(); verify(entry, times(1)).destroy(eq(arm._getOwner()), eq(event), eq(false), anyBoolean(), eq(expectedOldValue), anyBoolean(), anyBoolean()); boolean invokeCallbacks = true; verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), eq(inTokenMode), eq(false), eq(duringRI), eq(invokeCallbacks)); verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), eq(inTokenMode), eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue)); }
@Test public void evictDestroyWithConcurrentChangeFromNullToInUseByTransactionInTokenModeDoesNothing() throws RegionClearedException { CustomEntryConcurrentHashMap<Object, EvictableEntry> map = mock(CustomEntryConcurrentHashMap.class); EvictableEntry entry = mock(EvictableEntry.class); when(entry.isInUseByTransaction()).thenReturn(true); when(map.get(KEY)).thenReturn(null); when(map.putIfAbsent(eq(KEY), any())).thenReturn(entry); final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map); final EntryEventImpl event = createEventForDestroy(arm._getOwner()); final Object expectedOldValue = null; final boolean inTokenMode = true; final boolean duringRI = false; final boolean evict = true; assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, expectedOldValue, false)) .isFalse(); verify(entry, never()).destroy(any(), any(), anyBoolean(), anyBoolean(), any(), anyBoolean(), anyBoolean()); verify(arm._getOwner(), never()).basicDestroyPart2(any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean()); verify(arm._getOwner(), never()).basicDestroyPart3(any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), any()); }
Object curVal = le.getValue(); // OFFHEAP: _getValue ok if (curVal != cd) { if (cd instanceof StoredObject) { le.updateEntrySize(getEvictionController(), new CachedDeserializableValueWrapper(v)); if (delta != 0) { result = true;
@Test public void destroyInTokenModeWithConcurrentChangeFromNullToRemovePhase2RetriesAndDoesDestroy() throws RegionClearedException { CustomEntryConcurrentHashMap<Object, EvictableEntry> map = mock(CustomEntryConcurrentHashMap.class); EvictableEntry entry = mock(EvictableEntry.class); when(entry.isRemovedPhase2()).thenReturn(true); when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), anyBoolean(), anyBoolean())) .thenReturn(true); when(map.get(KEY)).thenReturn(null); when(map.putIfAbsent(eq(KEY), any())).thenReturn(entry).thenReturn(null); final TestableVMLRURegionMap arm = new TestableVMLRURegionMap(true, map); final EntryEventImpl event = createEventForDestroy(arm._getOwner()); final Object expectedOldValue = null; final boolean inTokenMode = true; final boolean duringRI = false; final boolean evict = false; assertThat(arm.destroy(event, inTokenMode, duringRI, false, evict, expectedOldValue, false)) .isTrue(); verify(map).remove(eq(KEY), eq(entry)); verify(map, times(2)).putIfAbsent(eq(KEY), any()); verify(entry, never()).destroy(eq(arm._getOwner()), eq(event), eq(false), anyBoolean(), eq(expectedOldValue), anyBoolean(), anyBoolean()); boolean invokeCallbacks = true; verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), eq(inTokenMode), eq(false), eq(duringRI), eq(invokeCallbacks)); verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), eq(inTokenMode), eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue)); }
/** * @return true if the evict destroy was done; false if it was not needed */ boolean evictDestroy(EvictableEntry entry) { checkReadiness(); @Released final EntryEventImpl event = generateEvictDestroyEvent(entry.getKey()); try { return mapDestroy(event, false, // cacheWrite true, // isEviction null); // expectedOldValue } catch (CacheWriterException error) { throw new Error( "Cache Writer should not have been called for evictDestroy", error); } catch (TimeoutException anotherError) { throw new Error( "No distributed lock should have been attempted for evictDestroy", anotherError); } catch (EntryNotFoundException yetAnotherError) { throw new Error( "EntryNotFoundException should be masked for evictDestroy", yetAnotherError); } finally { event.release(); } }
boolean evicted = ((EvictableEntry) entry).isEvicted(); if (evicted) { if (!dr.isBackup()) {
@Test public void startScanIfEvictableEntryIsRecentlyUsed() throws Exception { List<EvictionNode> nodes = new ArrayList<>(); LRUListWithAsyncSorting lruEvictionList = new LRUListWithAsyncSorting(controller, executor, 1); IntStream.range(0, 11).forEach(i -> { EvictionNode node = new LRUTestEntry(i); nodes.add(node); lruEvictionList.appendEntry(node); node.setRecentlyUsed(mock(RegionEntryContext.class)); }); assertThat(lruEvictionList.getEvictableEntry().isRecentlyUsed()).isTrue(); verify(executor).submit(any(Runnable.class)); }
@Test public void destroyWithEmptyRegionInTokenModeWithRegionClearedExceptionDoesDestroy() throws Exception { CustomEntryConcurrentHashMap<String, EvictableEntry> map = mock(CustomEntryConcurrentHashMap.class); EvictableEntry entry = mock(EvictableEntry.class); when(entry.destroy(any(), any(), anyBoolean(), anyBoolean(), any(), anyBoolean(), anyBoolean())) .thenThrow(RegionClearedException.class); when(map.get(KEY)).thenReturn(null); RegionEntryFactory factory = mock(RegionEntryFactory.class); when(factory.createEntry(any(), any(), any())).thenReturn(entry); final TestableAbstractRegionMap arm = new TestableAbstractRegionMap(false, map, factory); final EntryEventImpl event = createEventForDestroy(arm._getOwner()); final Object expectedOldValue = null; final boolean inTokenMode = true; final boolean duringRI = false; assertThat(arm.destroy(event, inTokenMode, duringRI, false, false, expectedOldValue, false)) .isTrue(); boolean invokeCallbacks = true; verify(arm._getOwner(), times(1)).basicDestroyPart2(any(), eq(event), eq(inTokenMode), eq(true), eq(duringRI), eq(invokeCallbacks)); verify(arm._getOwner(), times(1)).basicDestroyPart3(any(), eq(event), eq(inTokenMode), eq(duringRI), eq(invokeCallbacks), eq(expectedOldValue)); }
@Override boolean evictDestroy(EvictableEntry entry) { boolean evictDestroyWasDone = super.evictDestroy(entry); if (evictDestroyWasDone) { if (this.scope.isGlobal()) { try { getLockService().freeResources(entry.getKey()); } catch (LockServiceDestroyedException ignore) { } } } return evictDestroyWasDone; }
&& ((EvictableEntry) entry).isEvicted()) {
logger.trace(LogMarker.LRU_VERBOSE, "evicted entry key={} total entry size is now: {} bytesToEvict :{}", removalEntry.getKey(), getTotalEntrySize(), bytesToEvict); logger.trace(LogMarker.LRU_VERBOSE, "evicted entry key(2)={} total entry size is now: {} bytesToEvict: {}", removalEntry.getKey(), getTotalEntrySize(), bytesToEvict);