@Test public void testFlushUpdatesAccessStats() throws CacheAccessException { final TestTimeSource timeSource = new TestTimeSource(); final Expiry<Object, Object> expiry = Expirations.timeToIdleExpiration(new Duration(15L, TimeUnit.MILLISECONDS)); final AbstractOffHeapStore<String, String> store = createAndInitStore(timeSource, expiry); try { final String key = "foo"; final String value = "bar"; store.put(key, value); final Store.ValueHolder<String> firstValueHolder = store.getAndFault(key); store.put(key, value); final Store.ValueHolder<String> secondValueHolder = store.getAndFault(key); timeSource.advanceTime(10); ((AbstractValueHolder) firstValueHolder) .accessed(timeSource.getTimeMillis(), expiry.getExpiryForAccess(key, value)); timeSource.advanceTime(10); ((AbstractValueHolder) secondValueHolder) .accessed(timeSource.getTimeMillis(), expiry.getExpiryForAccess(key, value)); assertThat(store.flush(key, new DelegatingValueHolder<String>(firstValueHolder)), is(false)); assertThat(store.flush(key, new DelegatingValueHolder<String>(secondValueHolder)), is(true)); timeSource.advanceTime(10); // this should NOT affect assertThat( store.getAndFault(key).lastAccessTime(TimeUnit.MILLISECONDS), is(secondValueHolder.creationTime(TimeUnit.MILLISECONDS) + 20)); } finally { destroyStore(store); } }
@Test public void testComputeIfPresentWithReplaceEqual() throws CacheAccessException { store.put(KEY, VALUE); final Store.ValueHolder<Value> computeValue = store.computeIfPresent( KEY, new BiFunction<Long, Value, Value>() { @Override public Value apply(Long aLong, Value value) { return value; } }, REPLACE_EQUAL); store.computeIfPresent( KEY, new BiFunction<Long, Value, Value>() { @Override public Value apply(Long aLong, Value value) { compareReadValues(computeValue.value(), value); return value; } }, REPLACE_EQUAL); compareValues(VALUE, computeValue.value()); }
@Test public void testComputeWithReplaceEqual() throws CacheAccessException { final Store.ValueHolder<Value> firstValue = store.compute( KEY, new BiFunction<Long, Value, Value>() { @Override public Value apply(Long aLong, Value value) { return VALUE; } }, REPLACE_EQUAL); store.compute( KEY, new BiFunction<Long, Value, Value>() { @Override public Value apply(Long aLong, Value value) { compareReadValues(value, firstValue.value()); return value; } }, REPLACE_EQUAL); compareValues(VALUE, firstValue.value()); }
@Test public void testComputeIfAbsent() throws CacheAccessException { Store.ValueHolder<Value> computedValue = store.computeIfAbsent( KEY, new Function<Long, Value>() { @Override public Value apply(Long aLong) { return VALUE; } }); Store.ValueHolder<Value> secondComputedValue = store.computeIfAbsent( KEY, new Function<Long, Value>() { @Override public Value apply(Long aLong) { fail("There should have been a mapping"); return null; } }); compareValues(VALUE, computedValue.value()); compareReadValues(computedValue.value(), secondComputedValue.value()); }
@Test public void testPutAndGet() throws CacheAccessException { store.put(KEY, VALUE); Store.ValueHolder<Value> firstStoreValue = store.get(KEY); Store.ValueHolder<Value> secondStoreValue = store.get(KEY); compareValues(VALUE, firstStoreValue.value()); compareValues(VALUE, secondStoreValue.value()); compareReadValues(firstStoreValue.value(), secondStoreValue.value()); }
@Test public void testBulkComputeFunctionGetsValuesOfEntries() throws Exception { @SuppressWarnings("rawtypes") Store.Configuration config = mock(Store.Configuration.class); when(config.getExpiry()).thenReturn(Expirations.noExpiration()); when(config.getKeyType()).thenReturn(Number.class); when(config.getValueType()).thenReturn(Number.class); Store.Configuration<Number, Number> configuration = config; OnHeapStore<Number, Number> store = new OnHeapStore<Number, Number>(configuration, SystemTimeSource.INSTANCE, false); store.put(1, 2); store.put(2, 3); store.put(3, 4); Map<Number, Store.ValueHolder<Number>> result = store.bulkCompute( Arrays.asList(1, 2, 3, 4, 5, 6), new Function< Iterable<? extends Map.Entry<? extends Number, ? extends Number>>, Iterable<? extends Map.Entry<? extends Number, ? extends Number>>>() { @Override public Iterable<? extends Map.Entry<? extends Number, ? extends Number>> apply( Iterable<? extends Map.Entry<? extends Number, ? extends Number>> entries) { Map<Number, Number> newValues = new HashMap<Number, Number>(); for (Map.Entry<? extends Number, ? extends Number> entry : entries) { final Number currentValue = entry.getValue(); if (currentValue == null) { if (entry.getKey().equals(4)) { newValues.put(entry.getKey(), null); } else { newValues.put(entry.getKey(), 0); } } else { newValues.put(entry.getKey(), currentValue.intValue() * 2); } } return newValues.entrySet(); } }); ConcurrentMap<Number, Number> check = new ConcurrentHashMap<Number, Number>(); check.put(1, 4); check.put(2, 6); check.put(3, 8); check.put(4, 0); check.put(5, 0); check.put(6, 0); assertThat(result.get(1).value(), Matchers.<Number>is(check.get(1))); assertThat(result.get(2).value(), Matchers.<Number>is(check.get(2))); assertThat(result.get(3).value(), Matchers.<Number>is(check.get(3))); assertThat(result.get(4), nullValue()); assertThat(result.get(5).value(), Matchers.<Number>is(check.get(5))); assertThat(result.get(6).value(), Matchers.<Number>is(check.get(6))); for (Number key : check.keySet()) { final Store.ValueHolder<Number> holder = store.get(key); if (holder != null) { check.remove(key, holder.value()); } } assertThat(check.size(), is(1)); assertThat(check.containsKey(4), is(true)); }
@Override public long getId() { return valueHolder.getId(); }
@Override public long hits() { return valueHolder.hits(); }
@Override public float hitRate(final long now, final TimeUnit unit) { return valueHolder.hitRate(now, unit); }
@Override public long lastAccessTime(final TimeUnit unit) { return valueHolder.lastAccessTime(unit); }
@Override public boolean isExpired(final long expirationTime, final TimeUnit unit) { return valueHolder.isExpired(expirationTime, unit); }
@Override public long expirationTime(final TimeUnit unit) { return valueHolder.expirationTime(unit); }
@Override public long creationTime(final TimeUnit unit) { return valueHolder.creationTime(unit); }
@Override public T value() { return valueHolder.value(); }
@Override public void onExpiration(final K key, final Store.ValueHolder<V> valueHolder) { eventNotificationService.onEvent(CacheEvents.expiry(key, valueHolder.value(), this.source)); }