@Override public void put(K k, V v, Metadata metadata) { boolean l1Entry = false; if (metadata instanceof L1Metadata) { metadata = ((L1Metadata) metadata).metadata(); l1Entry = true; } InternalCacheEntry<K, V> e = entries.get(k); if (trace) { log.tracef( "Creating new ICE for writing. Existing=%s, metadata=%s, new value=%s", e, metadata, toStr(v)); } final InternalCacheEntry<K, V> copy; if (l1Entry) { copy = entryFactory.createL1(k, v, metadata); } else if (e != null) { copy = entryFactory.update(e, v, metadata); } else { // this is a brand-new entry copy = entryFactory.create(k, v, metadata); } if (trace) log.tracef("Store %s in container", copy); entries.compute( copy.getKey(), (key, entry) -> { activator.onUpdate(key, entry == null); return copy; }); }
@Override protected void commitSingleEntry( CacheEntry entry, Metadata metadata, FlagAffectedCommand command, InvocationContext ctx, Flag trackFlag, boolean l1Invalidation) { // Cache flags before they're reset // TODO: Can the reset be done after notification instead? boolean created = entry.isCreated(); boolean removed = entry.isRemoved(); boolean expired; if (removed && entry instanceof MVCCEntry) { expired = ((MVCCEntry) entry).isExpired(); } else { expired = false; } InternalCacheEntry previousEntry = dataContainer.peek(entry.getKey()); Object previousValue = null; Metadata previousMetadata = null; if (previousEntry != null) { previousValue = previousEntry.getValue(); previousMetadata = previousEntry.getMetadata(); } commitManager.commit(entry, metadata, trackFlag, l1Invalidation); // Notify after events if necessary notifyCommitEntry( created, removed, expired, entry, ctx, command, previousValue, previousMetadata); }
private void assertContainerEntry( Class<? extends InternalCacheEntry> type, String expectedValue) { assert dc.containsKey("k"); InternalCacheEntry entry = dc.get("k"); assertEquals(type, entry.getClass()); assertEquals(expectedValue, entry.getValue()); }
@Override public final void store(InternalCacheEntry ed) throws CacheLoaderException { if (trace) { log.tracef("store(%s)", ed); } if (ed == null) { return; } if (ed.canExpire() && ed.isExpired(System.currentTimeMillis())) { if (containsKey(ed.getKey())) { if (trace) { log.tracef("Entry %s is expired! Removing!", ed); } remove(ed.getKey()); } else { if (trace) { log.tracef("Entry %s is expired! Not doing anything.", ed); } } return; } L keyHashCode = getLockFromKey(ed.getKey()); lockForWriting(keyHashCode); try { storeLockSafe(ed, keyHashCode); } finally { unlock(keyHashCode); } if (trace) { log.tracef("exit store(%s)", ed); } }
public void testStateTransfer() throws Exception { // Insert initial data in the cache Set<Object> keys = new HashSet<Object>(); for (int i = 0; i < NUM_KEYS; i++) { Object key = "key" + i; keys.add(key); cache(0).put(key, key); } log.trace("State transfer happens here"); // add a third node addClusterEnabledCacheManager(dccc); waitForClusterToForm(); log.trace("Checking the values from caches..."); int keysOnJoiner = 0; for (Object key : keys) { log.tracef("Checking key: %s", key); // check them directly in data container InternalCacheEntry d0 = advancedCache(0).getDataContainer().get(key); InternalCacheEntry d1 = advancedCache(1).getDataContainer().get(key); InternalCacheEntry d2 = advancedCache(2).getDataContainer().get(key); assertEquals(key, d0.getValue()); assertNull(d1); if (d2 != null) { keysOnJoiner++; } } assertTrue("The joiner should receive at least one key", keysOnJoiner > 0); }
private void testStoredEntry( InternalCacheEntry entry, Object expectedValue, long expectedLifespan, String src, Object key) { assert entry != null : src + " entry for key " + key + " should NOT be null"; assert entry.getValue().equals(expectedValue) : src + " should contain value " + expectedValue + " under key " + entry.getKey() + " but was " + entry.getValue() + ". Entry is " + entry; assert entry.getLifespan() == expectedLifespan : src + " expected lifespan for key " + key + " to be " + expectedLifespan + " but was " + entry.getLifespan() + ". Entry is " + entry; }
public boolean containsKey(Object k) { InternalCacheEntry ice = peek(k); if (ice != null && ice.canExpire() && ice.isExpired(System.currentTimeMillis())) { entries.remove(k); ice = null; } return ice != null; }
@Override public boolean containsKey(Object k) { InternalCacheEntry<K, V> ice = peek(k); if (ice != null && ice.canExpire() && ice.isExpired(timeService.wallClockTime())) { entries.remove(k); ice = null; } return ice != null; }
public void update() { // whew - expensive stuff. data.clear(); for (InternalCacheEntry ice : cache.getAdvancedCache().getDataContainer()) { if (!ice.isExpired()) data.add(ice); } cacheContentsSizeLabel.setText("Cache contains " + data.size() + " entries"); fireTableDataChanged(); }
private Map<Object, Object> getPreviousValues(Set<Object> keySet) { HashMap<Object, Object> previousValues = new HashMap<Object, Object>(); for (Object key : keySet) { InternalCacheEntry internalCacheEntry = dataContainer.get(key); Object previousValue = internalCacheEntry != null ? internalCacheEntry.getValue() : null; previousValues.put(key, previousValue); } return previousValues; }
public void compact() { for (InternalCacheEntry e : dataContainer) { if (e.getKey() instanceof MarshalledValue) { ((MarshalledValue) e.getKey()).compact(true, true); } if (e.getValue() instanceof MarshalledValue) { ((MarshalledValue) e.getValue()).compact(true, true); } } }
public void purgeExpired() { long currentTimeMillis = System.currentTimeMillis(); for (Iterator<InternalCacheEntry> purgeCandidates = entries.values().iterator(); purgeCandidates.hasNext(); ) { InternalCacheEntry e = purgeCandidates.next(); if (e.isExpired(currentTimeMillis)) { purgeCandidates.remove(); } } }
private Object remoteGet(InvocationContext ctx, Object key, GetKeyValueCommand command) throws Throwable { if (trace) log.tracef("Doing a remote get for key %s", key); InternalCacheEntry ice = dm.retrieveFromRemoteSource(key, ctx, false, command); command.setRemotelyFetchedValue(ice); if (ice != null) { return ice.getValue(); } return null; }
@Override public void notifyCacheEntriesEvicted( Collection<InternalCacheEntry<? extends K, ? extends V>> entries, InvocationContext ctx, FlagAffectedCommand command) { if (!entries.isEmpty()) { if (isNotificationAllowed(command, cacheEntriesEvictedListeners)) { EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED); Map<K, V> evictedKeysAndValues = transformCollectionToMap( entries, new InfinispanCollections.MapMakerFunction< K, V, InternalCacheEntry<? extends K, ? extends V>>() { @Override public Map.Entry<K, V> transform( final InternalCacheEntry<? extends K, ? extends V> input) { return new Map.Entry<K, V>() { @Override public K getKey() { return input.getKey(); } @Override public V getValue() { return input.getValue(); } @Override public V setValue(V value) { throw new UnsupportedOperationException(); } }; } }); e.setEntries(evictedKeysAndValues); for (CacheEntryListenerInvocation<K, V> listener : cacheEntriesEvictedListeners) listener.invoke(e); } // For backward compat if (isNotificationAllowed(command, cacheEntryEvictedListeners)) { for (InternalCacheEntry<? extends K, ? extends V> ice : entries) { EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED); e.setKey(ice.getKey()); e.setValue(ice.getValue()); boolean isLocalNodePrimaryOwner = clusteringDependentLogic.localNodeIsPrimaryOwner(ice.getKey()); for (CacheEntryListenerInvocation<K, V> listener : cacheEntryEvictedListeners) listener.invoke(e, isLocalNodePrimaryOwner); } } } }
private void commitClearCommand( DataContainer<Object, Object> dataContainer, ClearCacheEntry<Object, Object> cacheEntry, InvocationContext context, FlagAffectedCommand command) { List<InternalCacheEntry<Object, Object>> copyEntries = new ArrayList<>(dataContainer.entrySet()); cacheEntry.commit(dataContainer, null); for (InternalCacheEntry entry : copyEntries) { notifier.notifyCacheEntryRemoved( entry.getKey(), entry.getValue(), entry.getMetadata(), false, context, command); } }
public InternalCacheEntry get(Object k) { InternalCacheEntry e = peek(k); if (e != null && e.canExpire()) { long currentTimeMillis = System.currentTimeMillis(); if (e.isExpired(currentTimeMillis)) { entries.remove(k); e = null; } else { e.touch(currentTimeMillis); } } return e; }
private MVCCEntry wrapInternalCacheEntryForPut( InvocationContext ctx, Object key, InternalCacheEntry cacheEntry) { MVCCEntry mvccEntry = createWrappedEntry( key, cacheEntry.getValue(), cacheEntry.getVersion(), false, false, cacheEntry.getLifespan()); ctx.putLookedUpEntry(key, mvccEntry); return mvccEntry; }
private MVCCEntry wrapEntry(InvocationContext ctx, Object key) { CacheEntry cacheEntry = getFromContext(ctx, key); MVCCEntry mvccEntry = null; if (cacheEntry != null) { mvccEntry = wrapMvccEntryForPut(ctx, key, cacheEntry); } else { InternalCacheEntry ice = getFromContainer(key); if (ice != null) { mvccEntry = wrapInternalCacheEntryForPut(ctx, ice.getKey(), ice); } } if (mvccEntry != null) mvccEntry.copyForUpdate(container, localModeWriteSkewCheck); return mvccEntry; }
public void testExpiredData() throws InterruptedException { dc.put("k", "v", -1, 6000000); Thread.sleep(100); InternalCacheEntry entry = dc.get("k"); assert entry.getClass().equals(transienttype()); assert entry.getLastUsed() <= System.currentTimeMillis(); long entryLastUsed = entry.getLastUsed(); Thread.sleep(100); entry = dc.get("k"); assert entry.getLastUsed() > entryLastUsed; dc.put("k", "v", -1, 0); dc.purgeExpired(); dc.put("k", "v", 6000000, -1); Thread.sleep(100); assert dc.size() == 1; entry = dc.get("k"); assert entry != null : "Entry should not be null!"; assert entry.getClass().equals(mortaltype()) : "Expected " + mortaltype() + ", was " + entry.getClass().getSimpleName(); assert entry.getCreated() <= System.currentTimeMillis(); dc.put("k", "v", 0, -1); Thread.sleep(10); assert dc.get("k") == null; assert dc.size() == 0; dc.put("k", "v", 0, -1); Thread.sleep(100); assert dc.size() == 1; dc.purgeExpired(); assert dc.size() == 0; }
@Override public InternalCacheEntry<K, V> get(Object k) { InternalCacheEntry<K, V> e = entries.get(k); if (e != null && e.canExpire()) { long currentTimeMillis = timeService.wallClockTime(); if (e.isExpired(currentTimeMillis)) { expirationManager.handleInMemoryExpiration(e, currentTimeMillis); e = null; } else { e.touch(currentTimeMillis); } } return e; }
public void testEvictBeforeRead() throws CacheLoaderException, ExecutionException, InterruptedException { cache = cacheManager.getCache(); cache.put("a", "b"); assert cache.get("a").equals("b"); CacheLoader cl = TestingUtil.getCacheLoader(cache); assert cl != null; InternalCacheEntry se = cl.load("a"); assert se != null; assert se.getValue().equals("b"); // clear the cache cache.getAdvancedCache().withFlags(SKIP_CACHE_STORE).clear(); se = cl.load("a"); assert se != null; assert se.getValue().equals("b"); // now attempt a concurrent get and evict. ExecutorService e = Executors.newFixedThreadPool(1); sdi.enabled = true; log.info("test::doing the get"); // call the get Future<String> future = e.submit( new Callable<String>() { public String call() throws Exception { return (String) cache.get("a"); } }); // now run the evict. log.info("test::before the evict"); cache.evict("a"); log.info("test::after the evict"); // make sure the get call, which would have gone past the cache loader interceptor first, gets // the correct value. assert future.get().equals("b"); // disable the SlowDownInterceptor sdi.enabled = false; // and check that the key actually has been evicted assert !TestingUtil.extractComponent(cache, DataContainer.class).containsKey("a"); e.shutdownNow(); }
@Override public boolean contains(Object o) { if (!(o instanceof Map.Entry)) { return false; } @SuppressWarnings("rawtypes") Map.Entry e = (Map.Entry) o; InternalCacheEntry ice = entries.get(e.getKey()); if (ice == null) { return false; } return ice.getValue().equals(e.getValue()); }
@Override public InternalCacheEntry<K, V> remove(Object k) { final InternalCacheEntry<K, V>[] reference = new InternalCacheEntry[1]; entries.compute( (K) k, (key, entry) -> { activator.onRemove(key, entry == null); reference[0] = entry; return null; }); InternalCacheEntry<K, V> e = reference[0]; if (trace) { log.tracef("Removed %s from container", e); } return e == null || (e.canExpire() && e.isExpired(timeService.wallClockTime())) ? null : e; }
@Override public CacheEntry wrapEntryForDelta(InvocationContext ctx, Object deltaKey, Delta delta) throws InterruptedException { CacheEntry cacheEntry = getFromContext(ctx, deltaKey); DeltaAwareCacheEntry deltaAwareEntry = null; if (cacheEntry != null) { deltaAwareEntry = wrapEntryForDelta(ctx, deltaKey, cacheEntry); } else { InternalCacheEntry ice = getFromContainer(deltaKey); if (ice != null) { deltaAwareEntry = newDeltaAwareCacheEntry(ctx, deltaKey, (DeltaAware) ice.getValue()); } } if (deltaAwareEntry != null) deltaAwareEntry.appendDelta(delta); return deltaAwareEntry; }
public Object getValueAt(int rowIndex, int columnIndex) { if (data.size() > rowIndex) { InternalCacheEntry e = data.get(rowIndex); switch (columnIndex) { case 0: return e.getKey(); case 1: return e.getValue(); case 2: return e.getLifespan(); case 3: return e.getMaxIdle(); } } return "NULL!"; }
@Override public void notifyCacheEntriesEvicted( Collection<InternalCacheEntry> entries, InvocationContext ctx, FlagAffectedCommand command) { if (!entries.isEmpty()) { if (isNotificationAllowed(command, cacheEntriesEvictedListeners)) { EventImpl<Object, Object> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED); Map<Object, Object> evictedKeysAndValues = transformCollectionToMap( entries, new InfinispanCollections.MapMakerFunction<Object, Object, InternalCacheEntry>() { @Override public Map.Entry<Object, Object> transform(final InternalCacheEntry input) { return new Map.Entry<Object, Object>() { @Override public Object getKey() { return input.getKey(); } @Override public Object getValue() { return input.getValue(); } @Override public Object setValue(Object value) { throw new UnsupportedOperationException(); } }; } }); e.setEntries(evictedKeysAndValues); for (ListenerInvocation listener : cacheEntriesEvictedListeners) listener.invoke(e); } // For backward compat if (isNotificationAllowed(command, cacheEntryEvictedListeners)) { for (InternalCacheEntry ice : entries) { EventImpl<Object, Object> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED); e.setKey(ice.getKey()); e.setValue(ice.getValue()); for (ListenerInvocation listener : cacheEntryEvictedListeners) listener.invoke(e); } } } }
private Object getValue(Object key) { log.tracef("Checking key: %s", key); InternalCacheEntry d0 = advancedCache(0).getDataContainer().get(key); InternalCacheEntry d1 = advancedCache(1).getDataContainer().get(key); InternalCacheEntry d2 = advancedCache(2).getDataContainer().get(key); if (d0 == null) { assert sameValue(d1, d2); return d1.getValue(); } else if (d1 == null) { assert sameValue(d0, d2); return d0.getValue(); } else if (d2 == null) { assert sameValue(d0, d1); return d0.getValue(); } throw new RuntimeException(); }
public void put(Object k, Object v, EntryVersion version, long lifespan, long maxIdle) { InternalCacheEntry e = entries.get(k); if (e != null) { e.setValue(v); InternalCacheEntry original = e; e.setVersion(version); e = entryFactory.update(e, lifespan, maxIdle); // we have the same instance. So we need to reincarnate. if (original == e) { e.reincarnate(); } } else { // this is a brand-new entry e = entryFactory.create(k, v, version, lifespan, maxIdle); } entries.put(k, e); }
public void testContainerIteration() { dc.put("k1", "v", 6000000, -1); dc.put("k2", "v", -1, -1); dc.put("k3", "v", -1, 6000000); dc.put("k4", "v", 6000000, 6000000); Set expected = new HashSet(); expected.add("k1"); expected.add("k2"); expected.add("k3"); expected.add("k4"); for (InternalCacheEntry ice : dc) { assert expected.remove(ice.getKey()); } assert expected.isEmpty() : "Did not see keys " + expected + " in iterator!"; }
public void testGetsFromMultipleSrcs() throws Exception { assert cs.load("k1") == null; assert cs.load("k2") == null; assert cs.load("k3") == null; assert cs.load("k4") == null; // k1 is on store1 store1.store(InternalEntryFactory.create("k1", "v1")); assertEquals(cs.loadAll().size(), 1); // k2 is on store2 store2.store(InternalEntryFactory.create("k2", "v2")); assertEquals(cs.loadAll().size(), 2); // k3 is on both store1.store(InternalEntryFactory.create("k3", "v3")); assertEquals(cs.loadAll().size(), 3); store2.store(InternalEntryFactory.create("k3", "v3")); assertEquals(cs.loadAll().size(), 3); // k4 is on neither assert cs.load("k1").getValue().equals("v1"); assert cs.load("k2").getValue().equals("v2"); assert cs.load("k3").getValue().equals("v3"); assert cs.load("k4") == null; Set<InternalCacheEntry> all = cs.loadAll(); assertEquals(all.size(), 3); Set<Object> expectedKeys = new HashSet<Object>(); expectedKeys.add("k1"); expectedKeys.add("k2"); expectedKeys.add("k3"); for (InternalCacheEntry a : all) assert expectedKeys.remove(a.getKey()); assert expectedKeys.isEmpty(); cs.remove("k3"); assert !store1.containsKey("k3"); assert !store2.containsKey("k3"); }