@ -28,9 +28,11 @@ import java.util.AbstractMap;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Collection ;
import java.util.Comparator ;
import java.util.Comparator ;
import java.util.HashMap ;
import java.util.HashSet ;
import java.util.HashSet ;
import java.util.Iterator ;
import java.util.Iterator ;
import java.util.Map ;
import java.util.Map ;
import java.util.Random ;
import java.util.Set ;
import java.util.Set ;
@ -72,7 +74,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* @param comparator a comparator for the key object which may be of type byte [ ]
* @param comparator a comparator for the key object which may be of type byte [ ]
* /
* /
@SuppressWarnings ( "unchecked" )
@SuppressWarnings ( "unchecked" )
public ConcurrentARC ( final int cacheSize , final int partitions , Comparator < ? super K > comparator ) {
public ConcurrentARC ( final int cacheSize , final int partitions , final Comparator < ? super K > comparator ) {
int m = 1 ;
int m = 1 ;
while ( m < partitions ) m = m * 2 ;
while ( m < partitions ) m = m * 2 ;
int partitionSize = cacheSize / m ;
int partitionSize = cacheSize / m ;
@ -98,7 +100,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* @param s
* @param s
* @param v
* @param v
* /
* /
public void insertIfAbsent ( K s , V v ) {
public void insertIfAbsent ( final K s , final V v ) {
this . arc [ getPartition ( s ) ] . insertIfAbsent ( s , v ) ;
this . arc [ getPartition ( s ) ] . insertIfAbsent ( s , v ) ;
}
}
@ -109,7 +111,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* @param v
* @param v
* @return the value before inserting the new value
* @return the value before inserting the new value
* /
* /
public V putIfAbsent ( K s , V v ) {
public V putIfAbsent ( final K s , final V v ) {
return this . arc [ getPartition ( s ) ] . putIfAbsent ( s , v ) ;
return this . arc [ getPartition ( s ) ] . putIfAbsent ( s , v ) ;
}
}
@ -139,9 +141,10 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* @param value
* @param value
* @return the keys that have the given value
* @return the keys that have the given value
* /
* /
public Collection < K > getKeys ( V value ) {
public Collection < K > getKeys ( final V value ) {
ArrayList < K > keys = new ArrayList < K > ( ) ;
final ArrayList < K > keys = new ArrayList < K > ( ) ;
for ( int i = 0 ; i < this . arc . length ; i + + ) keys . addAll ( this . arc [ i ] . getKeys ( value ) ) ;
for ( final ARC < K , V > element : this . arc )
keys . addAll ( element . getKeys ( value ) ) ;
return keys ;
return keys ;
}
}
@ -172,7 +175,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* /
* /
@Override
@Override
public final void clear ( ) {
public final void clear ( ) {
for ( ARC < K , V > a : this . arc ) a . clear ( ) ;
for ( final ARC < K , V > a : this . arc ) a . clear ( ) ;
}
}
/ * *
/ * *
@ -182,7 +185,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
@Override
@Override
public final int size ( ) {
public final int size ( ) {
int s = 0 ;
int s = 0 ;
for ( ARC < K , V > a : this . arc ) s + = a . size ( ) ;
for ( final ARC < K , V > a : this . arc ) s + = a . size ( ) ;
return s ;
return s ;
}
}
@ -202,9 +205,9 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* /
* /
@Override
@Override
public Set < java . util . Map . Entry < K , V > > entrySet ( ) {
public Set < java . util . Map . Entry < K , V > > entrySet ( ) {
Set < Map . Entry < K , V > > m = new HashSet < Map . Entry < K , V > > ( ) ;
final Set < Map . Entry < K , V > > m = new HashSet < Map . Entry < K , V > > ( ) ;
for ( ARC < K , V > a : this . arc ) {
for ( final ARC < K , V > a : this . arc ) {
for ( Map . Entry < K , V > entry : a . entrySet ( ) ) m . add ( entry ) ;
for ( final Map . Entry < K , V > entry : a . entrySet ( ) ) m . add ( entry ) ;
}
}
return m ;
return m ;
}
}
@ -228,13 +231,47 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
private int getPartition ( final Object x ) {
private int getPartition ( final Object x ) {
if ( x instanceof byte [ ] ) {
if ( x instanceof byte [ ] ) {
int h = 0 ;
int h = 0 ;
for ( byte c : ( byte [ ] ) x ) h = 31 * h + ( c & 0xFF ) ;
for ( final byte c : ( byte [ ] ) x ) h = 31 * h + ( c & 0xFF ) ;
int p = h & mask;
final int p = h & this . mask;
//String o = UTF8.String((byte[]) x); try { if (o.equals(latestObject)) throw new RuntimeException("ConcurrentARC: p = " + p + ", objectb = " + o); } catch (Exception e) { Log.logException(e); } latestObject = o;
//String o = UTF8.String((byte[]) x); try { if (o.equals(latestObject)) throw new RuntimeException("ConcurrentARC: p = " + p + ", objectb = " + o); } catch (Exception e) { Log.logException(e); } latestObject = o;
return p ;
return p ;
}
}
int p = x . hashCode ( ) & mask;
final int p = x . hashCode ( ) & this . mask;
//String o = x.toString(); try { if (o.equals(latestObject)) throw new RuntimeException("ConcurrentARC: p = " + p + ", objecto = " + o); } catch (Exception e) { Log.logException(e); } latestObject = o;
//String o = x.toString(); try { if (o.equals(latestObject)) throw new RuntimeException("ConcurrentARC: p = " + p + ", objecto = " + o); } catch (Exception e) { Log.logException(e); } latestObject = o;
return p ;
return p ;
}
}
public static void main ( final String [ ] args ) {
final Random r = new Random ( ) ;
final int testsize = 10000 ;
final ARC < String , String > a = new ConcurrentARC < String , String > ( testsize * 3 , Runtime . getRuntime ( ) . availableProcessors ( ) ) ;
final Map < String , String > b = new HashMap < String , String > ( ) ;
String key , value ;
for ( int i = 0 ; i < testsize ; i + + ) {
key = "k" + r . nextInt ( ) ;
value = "v" + r . nextInt ( ) ;
a . insertIfAbsent ( key , value ) ;
b . put ( key , value ) ;
}
// now put half of the entries AGAIN into the ARC
int h = testsize / 2 ;
for ( final Map . Entry < String , String > entry : b . entrySet ( ) ) {
a . put ( entry . getKey ( ) , entry . getValue ( ) ) ;
if ( h - - < = 0 ) break ;
}
// test correctness
for ( final Map . Entry < String , String > entry : b . entrySet ( ) ) {
if ( ! a . containsKey ( entry . getKey ( ) ) ) {
System . out . println ( "missing: " + entry . getKey ( ) ) ;
continue ;
}
if ( ! a . get ( entry . getKey ( ) ) . equals ( entry . getValue ( ) ) ) {
System . out . println ( "wrong: a = " + entry . getKey ( ) + "," + a . get ( entry . getKey ( ) ) + "; v = " + entry . getValue ( ) ) ;
}
}
System . out . println ( "finished test!" ) ;
}
}
}