private CascadingCache<Object, Object> getDirectMappedCache( int capacity, CacheEvictionCallback cacheEvictionCallback ) { CascadingCache<Object, Object> map = new DirectMappedCache<Object, Object>(); map.setCacheEvictionCallback( cacheEvictionCallback ); map.setCapacity( capacity ); map.initialize(); return map; }
@Test public void testMaxCapacity() { TestCacheEvictionCallBack callBack = new TestCacheEvictionCallBack(); CascadingCache<Object, Object> cache = getDirectMappedCache( 10, callBack ); for( int i = 0; i < cache.getCapacity() + 10; i++ ) cache.put( i, i ); assertEquals( cache.getCapacity(), cache.size() ); assertEquals( 10, callBack.evictionCounter ); }
@Test public void testDirectMappedCache() { CascadingCache<Object, Object> cache = getDirectMappedCache( 10, CacheEvictionCallback.NULL ); assertNotNull( cache ); assertEquals( 0, cache.size() ); String key = "abc"; String value = "def"; cache.put( key, value ); assertEquals( 1, cache.size() ); assertTrue( cache.containsKey( key ) ); assertTrue( cache.containsValue( value ) ); assertSame( value, cache.get( key ) ); Set<Object> keys = cache.keySet(); assertEquals( 1, keys.size() ); assertTrue( keys.contains( key ) ); Collection<Object> values = cache.values(); assertTrue( values.contains( value ) ); cache.clear(); assertEquals( 0, cache.size() ); assertFalse( cache.containsKey( key ) ); assertFalse( cache.containsValue( value ) ); }
@Test public void testDirectMappedCacheEviction() { TestCacheEvictionCallBack callBack = new TestCacheEvictionCallBack(); CascadingCache<Object, Object> cache = getDirectMappedCache( 10, callBack ); Collider key = new Collider( "key" ); String value = "value"; cache.put( key, value ); assertEquals( 1, cache.size() ); assertEquals( 0, callBack.evictionCounter ); Collider secondKey = new Collider( "anotherKey" ); cache.put( secondKey, value ); assertEquals( 1, cache.size() ); assertEquals( 1, callBack.evictionCounter ); assertTrue( cache.containsKey( secondKey ) ); assertTrue( cache.containsValue( value ) ); assertSame( value, cache.get( secondKey ) ); assertTrue( callBack.evictedEntries.get( 0 ).getKey().equals( key ) ); assertTrue( callBack.evictedEntries.get( 0 ).getValue().equals( value ) ); }
@Override public void operate( FlowProcess flowProcess, FunctionCall<CompositeFunction.Context> functionCall ) { TupleEntry arguments = functionCall.getArguments(); Tuple key = TupleHasher.wrapTuple( this.tupleHasher, arguments.selectTupleCopy( groupingFields ) ); Context context = functionCall.getContext(); Tuple[] functorContext = context.lru.get( key ); if( functorContext == null ) { functorContext = new Tuple[ functors.length ]; context.lru.put( key, functorContext ); flowProcess.increment( Cache.Num_Keys_Missed, 1 ); } else { flowProcess.increment( Cache.Num_Keys_Hit, 1 ); } for( int i = 0; i < functors.length; i++ ) { TupleViews.reset( context.arguments[ i ].getTuple(), arguments.getTuple() ); functorContext[ i ] = functors[ i ].aggregate( flowProcess, context.arguments[ i ], functorContext[ i ] ); } }
@Override public boolean isRemove( FlowProcess flowProcess, FilterCall<CascadingCache<Tuple, Object>> filterCall ) { // we assume its more painful to create lots of tuple copies vs comparisons Tuple args = TupleHasher.wrapTuple( tupleHasher, filterCall.getArguments().getTuple() ); switch( include ) { case ALL: break; case NO_NULLS: if( Tuples.frequency( args, null ) == args.size() ) return true; break; } if( filterCall.getContext().containsKey( args ) ) { flowProcess.increment( Cache.Num_Keys_Hit, 1 ); return true; } // only do the copy here filterCall.getContext().put( TupleHasher.wrapTuple( tupleHasher, filterCall.getArguments().getTupleCopy() ), NULL_VALUE ); flowProcess.increment( Cache.Num_Keys_Missed, 1 ); return false; }
@Test(expected = IllegalArgumentException.class) public void testNullValue() { CascadingCache<Object, Object> cache = getDirectMappedCache( 10, CacheEvictionCallback.NULL ); cache.put( "a", null ); }
@Test(expected = IllegalArgumentException.class) public void testContainsKeyNull() { CascadingCache<Object, Object> cache = getDirectMappedCache( 10, CacheEvictionCallback.NULL ); cache.containsKey( null ); }
@Test(expected = IllegalArgumentException.class) public void testContainsValueNull() { CascadingCache<Object, Object> cache = getDirectMappedCache( 10, CacheEvictionCallback.NULL ); cache.containsValue( null ); }
@Test(expected = IllegalArgumentException.class) public void testNullKey() { CascadingCache<Object, Object> cache = getDirectMappedCache( 10, CacheEvictionCallback.NULL ); cache.put( null, "a" ); }
@Override public void prepare( final FlowProcess flowProcess, OperationCall<CascadingCache<Tuple, Object>> operationCall ) { CacheEvictionCallback callback = new CacheEvictionCallback() { @Override public void evict( Map.Entry entry ) { flowProcess.increment( Cache.Num_Keys_Flushed, 1 ); } }; FactoryLoader loader = FactoryLoader.getInstance(); BaseCacheFactory cacheFactory = loader.loadFactoryFrom( flowProcess, UniqueProps.UNIQUE_CACHE_FACTORY, UniqueProps.DEFAULT_CACHE_FACTORY_CLASS ); if( cacheFactory == null ) throw new CascadingException( "unable to load cache factory, please check your '" + UniqueProps.UNIQUE_CACHE_FACTORY + "' setting." ); CascadingCache cache = cacheFactory.create( flowProcess ); cache.setCacheEvictionCallback( callback ); Integer cacheCapacity = capacity; if( capacity == 0 ) { cacheCapacity = flowProcess.getIntegerProperty( UniqueProps.UNIQUE_CACHE_CAPACITY ); if( cacheCapacity == null ) cacheCapacity = UniqueProps.UNIQUE_DEFAULT_CAPACITY; } cache.setCapacity( cacheCapacity.intValue() ); cache.initialize(); operationCall.setContext( cache ); }
cache.setCacheEvictionCallback( new AggregateByEviction() ); cacheCapacity = AggregateByProps.AGGREGATE_BY_DEFAULT_CAPACITY; cache.setCapacity( cacheCapacity.intValue() ); cache.initialize();