GuavaOffHeapCacheBuilder { @SuppressWarnings("rawtypes") public GuavaOffHeapCache<K, V> build(final Class<V> clazz) { if ( executorService == null ) executorService = MoreExecutors.sameThreadExecutor(); if ( kryo == null ) kryo = new DecoratedKryo(); if ( memoryManager == null ) memoryManager = new UnsafeMemoryManager(); kryo.register( clazz, new FieldsSerializer( kryo, new BasicBO( clazz ) ) ); MatchingSerializer<?> serializer = new ExplicitCacheEntrySerializer( kryo ); final MutableObject<SimpleStatsCounter> statsCounter = new MutableObject<AbstractCache.SimpleStatsCounter>(); if ( recordStats ) statsCounter.set( new SimpleStatsCounter() ); OffHeapLinearProbingSet offheapSet = new OffHeapLinearProbingSet( memoryManager, capacityRestriction, null, serializer, executorService ); SpaceExpirationListener<K, ByteBuffer> evictionListener = new SpaceExpirationListener<K, ByteBuffer>( false ) { @Override public void handleNotification(final ByteBuffer entity, final K id, final Class<ByteBuffer> persistentClass, final int originalTimeToLive) { if ( statsCounter.get() != null ) statsCounter.get().recordEviction(); } }; if ( expirationListener != null ) offheapSet.setExpirationListeners( evictionListener, new SpaceExpirationListener<K, ExplicitCacheEntry<K, V>>() { @SuppressWarnings("unchecked") @Override public void handleNotification(final ExplicitCacheEntry<K, V> entity, final K id, final Class<ExplicitCacheEntry<K, V>> persistentClass, final int originalTimeToLive) { expirationListener.handleNotification( entity.getBean(), id, (Class<V>) entity.getBean().getClass(), originalTimeToLive ); } } ); else offheapSet.setExpirationListeners( evictionListener ); return new GuavaOffHeapCache<K, V>( memoryManager, offheapSet, kryo, ttl, statsCounter.get() ); }  GuavaOffHeapCacheBuilder<K, V> expireAfterWrite(final int duration,
                                                           final TimeUnit unit); GuavaOffHeapCacheBuilder<K, V> expirationListener(final SpaceExpirationListener<K, V> expirationListener); GuavaOffHeapCacheBuilder<K, V> executorService(final ExecutorService executorService); GuavaOffHeapCacheBuilder<K, V> kryo(final DecoratedKryo kryo); GuavaOffHeapCacheBuilder<K, V> recordStats(final boolean record); void setCapacityRestriction(final CapacityRestriction capacityRestriction); GuavaOffHeapCacheBuilder<K, V> memoryManager(final EffectiveMemoryManager memoryManager); @SuppressWarnings("rawtypes") GuavaOffHeapCache<K, V> build(final Class<V> clazz);  }
@Test public void trivialSunnyDayScenario1() throws ExecutionException { cache = builder.build( TestEntity1.class ); for ( int i = 0; i < 100; i++ ) { final String key = String.valueOf( System.currentTimeMillis() + i ); assertThat( cache.getIfPresent( key ), is( nullValue() ) ); cache.get( key, new Callable<TestEntity1>() { @Override public TestEntity1 call() { Uninterruptibles.sleepUninterruptibly( 10, TimeUnit.NANOSECONDS ); TestEntity1 entity = new TestEntity1(); entity.afterPropertiesSet(); entity.setUniqueIdentifier( key ); return entity; } } ); assertThat( (int) cache.size(), is( i + 1 ) ); assertThat( cache.getIfPresent( key ).getUniqueIdentifier(), is( key ) ); } assertThat( cache.stats().hitCount(), is( 100L ) ); assertThat( cache.stats().loadCount(), is( 100L ) ); assertThat( cache.stats().missCount(), is( 200L ) ); assertThat( cache.stats().averageLoadPenalty(), is( greaterThan( 0D ) ) ); }
@SuppressWarnings("unchecked") @Test public void handlesLoadingExceptionProperly() throws Exception { cache = builder.build( TestEntity1.class ); Callable<TestEntity1> loader = mock( Callable.class ); when( loader.call() ).thenThrow( new IllegalStateException( "failed to load 123 key" ) ); try { cache.get( "123", loader ); Assert.fail(); } catch ( ExecutionException e ) { assertThat( cache.stats().loadExceptionCount(), is( 1L ) ); assertThat( e.getCause().getClass().getName(), is( IllegalStateException.class.getName() ) ); } }