@ -11,12 +11,12 @@
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21 . txt
* If not , see < http : //www.gnu.org/licenses/>.
@ -28,9 +28,11 @@ import java.util.AbstractMap;
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Comparator ;
import java.util.HashMap ;
import java.util.HashSet ;
import java.util.Iterator ;
import java.util.Map ;
import java.util.Random ;
import java.util.Set ;
@ -47,7 +49,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
private final int mask ;
private final ARC < K , V > arc [ ] ;
/ * *
* create a concurrent ARC based on a HashARC . The type of the key elements must implement a hashing function
* @param cacheSize the number of maximum entries
@ -64,7 +66,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
m - = 1 ;
this . mask = m ;
}
/ * *
* create a concurrent ARC based on a ComparableARC
* @param cacheSize the number of maximum entries
@ -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 [ ]
* /
@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 ;
while ( m < partitions ) m = m * 2 ;
int partitionSize = cacheSize / m ;
@ -82,7 +84,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
m - = 1 ;
this . mask = m ;
}
/ * *
* put a value to the cache .
* @param s
@ -98,7 +100,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* @param s
* @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 ) ;
}
@ -109,10 +111,10 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* @param v
* @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 ) ;
}
/ * *
* put a value to the cache .
* @param s
@ -122,7 +124,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
public final V put ( final K s , final V v ) {
return this . arc [ getPartition ( s ) ] . put ( s , v ) ;
}
/ * *
* get a value from the cache .
* @param s
@ -133,18 +135,19 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
public final V get ( final Object s ) {
return this . arc [ getPartition ( s ) ] . get ( ( K ) s ) ;
}
/ * *
* check if the map contains the value
* @param value
* @return the keys that have the given value
* /
public Collection < K > getKeys ( V value ) {
ArrayList < K > keys = new ArrayList < K > ( ) ;
for ( int i = 0 ; i < this . arc . length ; i + + ) keys . addAll ( this . arc [ i ] . getKeys ( value ) ) ;
public Collection < K > getKeys ( final V value ) {
final ArrayList < K > keys = new ArrayList < K > ( ) ;
for ( final ARC < K , V > element : this . arc )
keys . addAll ( element . getKeys ( value ) ) ;
return keys ;
}
/ * *
* check if the map contains the key
* @param s
@ -155,7 +158,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
public final boolean containsKey ( final Object s ) {
return this . arc [ getPartition ( s ) ] . containsKey ( ( K ) s ) ;
}
/ * *
* remove an entry from the cache
* @param s
@ -166,13 +169,13 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
public final V remove ( final Object s ) {
return this . arc [ getPartition ( s ) ] . remove ( ( K ) s ) ;
}
/ * *
* clear the cache
* /
@Override
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
public final int size ( ) {
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 ;
}
@ -202,13 +205,13 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
* /
@Override
public Set < java . util . Map . Entry < K , V > > entrySet ( ) {
Set < Map . Entry < K , V > > m = new HashSet < Map . Entry < K , V > > ( ) ;
for ( ARC < K , V > a : this . arc ) {
for ( Map . Entry < K , V > entry : a . entrySet ( ) ) m . add ( entry ) ;
final Set < Map . Entry < K , V > > m = new HashSet < Map . Entry < K , V > > ( ) ;
for ( final ARC < K , V > a : this . arc ) {
for ( final Map . Entry < K , V > entry : a . entrySet ( ) ) m . add ( entry ) ;
}
return m ;
}
/ * *
* a hash code for this ARC
* @return a hash code
@ -217,7 +220,7 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
public int hashCode ( ) {
return this . arc . hashCode ( ) ;
}
//private static String latestObject = "";
/ * *
* return in which partition the Object belongs
@ -228,13 +231,47 @@ public final class ConcurrentARC<K, V> extends AbstractMap<K, V> implements Map<
private int getPartition ( final Object x ) {
if ( x instanceof byte [ ] ) {
int h = 0 ;
for ( byte c : ( byte [ ] ) x ) h = 31 * h + ( c & 0xFF ) ;
int p = h & mask;
for ( final byte c : ( byte [ ] ) x ) h = 31 * h + ( c & 0xFF ) ;
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;
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;
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!" ) ;
}
}