package water.util;
import water.AutoBuffer;
import water.Freezable;
import water.H2O;
import water.Iced;
import water.nbhm.NonBlockingHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
/** Iced / Freezable NonBlockingHashMap. Delegates to a NonBlockingHashMap for
* all its operations. Inspired by water.parser.Categorical.
*/
public class IcedHashMap<K, V> extends IcedHashMapBase<K,V> implements ConcurrentMap<K, V> {
transient NonBlockingHashMap<K,V> _map;
public IcedHashMap() { init(); }
@Override protected Map<K, V> map() { return _map; }
@Override protected Map<K, V> init() { return _map = new NonBlockingHashMap<>(); }
public V putIfAbsent(K key, V value) { return _map.putIfAbsent(key, value); }
public boolean remove(Object key, Object value) { return _map.remove(key, value); }
public boolean replace(K key, V oldValue, V newValue) { return _map.replace(key, oldValue, newValue); }
public V replace(K key, V value) { return _map.replace(key, value); }
public K getk(K key) { return _map.getk(key); }
// Map-writing optimized for NBHM
@Override protected void writeMap(AutoBuffer ab, int mode) {
// For faster K/V store walking get the NBHM raw backing array,
// and walk it directly.
Object[] kvs = _map.raw_array();
// Start the walk at slot 2, because slots 0,1 hold meta-data
// In the raw backing array, Keys and Values alternate in slots
// Ignore tombstones and Primes and null's
switch( mode ) {
case 1: // <String,String>
for( int i=2; i<kvs.length; i += 2 )
if( kvs[i] instanceof String && kvs[i+1] instanceof String )
ab.putStr((String)kvs[i]).putStr((String)kvs[i+1]);
break;
case 2: // <String,Freezable>
for( int i=2; i<kvs.length; i += 2 )
if( kvs[i] instanceof String && kvs[i+1] instanceof Iced )
ab.putStr((String)kvs[i]).put ((Freezable)kvs[i+1]);
break;
case 3: // <Freezable,String>
for( int i=2; i<kvs.length; i += 2 )
if( kvs[i] instanceof Iced && kvs[i+1] instanceof String )
ab.put ((Freezable )kvs[i]).putStr((String)kvs[i+1]);
break;
case 4: // <Freezable,Freezable>
for( int i=2; i<kvs.length; i += 2 )
if( kvs[i] instanceof Freezable && kvs[i+1] instanceof Freezable )
ab.put ((Freezable )kvs[i]).put ((Freezable )kvs[i+1]);
break;
case 5: // <String,Freezable[]>
for( int i=2;i<kvs.length; i+=2 )
if( kvs[i] instanceof String && kvs[i+1] instanceof Freezable[] ) {
Freezable[] vals = (Freezable[])kvs[i+1];
ab.putStr((String)kvs[i]).put4(vals.length); // key len vals
for(Freezable v: vals) ab.put(v);
}
break;
case 6: // <Freezable,Freezable[]>
for( int i=2;i<kvs.length; i+=2 )
if( kvs[i] instanceof Freezable && kvs[i+1] instanceof Freezable[] ) {
Freezable[] vals = (Freezable[])kvs[i+1];
ab.put((Freezable)kvs[i]).put4(vals.length); // key len vals
for(Freezable v: vals) ab.put(v);
}
break;
default: throw H2O.fail();
}
}
}