blob: ae3a0c95e82a373a8e2eac6c420860df5e609333 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.util.offheap;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.affinity.AffinityFunction;
import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.util.lang.GridCloseableIterator;
import org.apache.ignite.internal.util.lang.GridTuple;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
/**
* Tests off-heap map.
*/
public abstract class GridOffHeapPartitionedMapAbstractSelfTest extends GridCommonAbstractTest {
/** Random. */
private static final Random RAND = new Random();
/** Unsafe map. */
private GridOffHeapPartitionedMap map;
/** */
protected float load = 0.75f;
/** */
protected int initCap = 100;
/** */
protected int concurrency = 16;
/** */
protected short lruStripes = 16;
/** */
protected GridOffHeapEvictListener evictLsnr;
/** */
protected long mem = 20L * 1024 * 1024;
/** */
protected int loadCnt = 100000;
/** */
protected int parts = 17;
/**
*
*/
protected GridOffHeapPartitionedMapAbstractSelfTest() {
super(false);
}
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
//resetLog4j(Level.INFO, true, false, "");
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
if (map != null)
map.destruct();
}
/**
* @return New map.
*/
protected abstract GridOffHeapPartitionedMap newMap();
/**
* @param key Key.
* @return Hash.
*/
private int hash(Object key) {
return hash(key.hashCode());
}
/**
* @param h Hash code.
* @return Hash.
*/
private int hash(int h) {
// Apply base step of MurmurHash; see http://code.google.com/p/smhasher/
// Despite two multiplies, this is often faster than others
// with comparable bit-spread properties.
h ^= h >>> 16;
h *= 0x85ebca6b;
h ^= h >>> 13;
h *= 0xc2b2ae35;
return (h >>> 16) ^ h;
}
/**
*
* @return New Object.
*/
private String string() {
String key = "";
for (int i = 0; i < 3; i++)
key += RAND.nextLong();
return key;
}
/**
* @param len Length of byte array.
* @return Random byte array.
*/
private byte[] bytes(int len) {
byte[] b = new byte[len];
RAND.nextBytes(b);
return b;
}
/**
* @throws Exception If failed.
*/
@Test
public void testInsert() throws Exception {
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
String val = string();
map.insert(p, hash(key), key.getBytes(), val.getBytes());
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertEquals(val, new String(map.get(p, hash(key), key.getBytes())));
assertEquals(10 * p + (i + 1), map.size());
}
}
assertEquals(parts * 10, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testRehash() throws Exception {
initCap = 10;
map = newMap();
for (int p = 0; p < parts; p++) {
Map<String, String> kv = new HashMap<>(10);
for (int i = 0; i < 10; i++)
kv.put(string(), string());
for (Map.Entry<String, String> e : kv.entrySet()) {
String key = e.getKey();
String val = e.getValue();
map.insert(p, hash(key), key.getBytes(), val.getBytes());
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertEquals(val, new String(map.get(p, hash(key), key.getBytes())));
}
for (Map.Entry<String, String> e : kv.entrySet()) {
String key = e.getKey();
String val = e.getValue();
byte[] valBytes = map.get(p, hash(key), key.getBytes());
assertNotNull(valBytes);
assertEquals(val, new String(valBytes));
}
}
assertEquals(parts * 10, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testPointerAfterRehash() throws Exception {
initCap = 10;
map = newMap();
Map<String, String> kv = new HashMap<>(1000);
Map<String, Long> ptrs = new HashMap<>(1000);
for (int i = 0; i < 1000; i++)
kv.put(string(), string());
for (Map.Entry<String, String> e : kv.entrySet()) {
String key = e.getKey();
String val = e.getValue();
assertTrue(map.put(1, hash(key), key.getBytes(), val.getBytes()));
IgniteBiTuple<Long, Integer> ptr = map.valuePointer(1, hash(key), key.getBytes());
assertNotNull(ptr);
assertEquals((Integer)val.getBytes().length, ptr.get2());
assertFalse(map.put(1, hash(key), key.getBytes(), val.getBytes()));
ptrs.put(key, ptr.get1());
}
for (Map.Entry<String, String> e : kv.entrySet()) {
String key = e.getKey();
IgniteBiTuple<Long, Integer> ptr = map.valuePointer(1, hash(key), key.getBytes());
assertNotNull(ptr);
assertEquals(ptrs.get(key), ptr.get1());
}
}
/**
* @throws Exception If failed.
*/
@Test
public void testPutRandomKeys() throws Exception {
map = newMap();
AffinityFunction aff = new RendezvousAffinityFunction(parts, null);
GridByteArrayWrapper[] keys = new GridByteArrayWrapper[512];
Random rnd = new Random();
for (int i = 0; i < keys.length; i++) {
byte[] key = new byte[rnd.nextInt(64) + 1];
rnd.nextBytes(key);
keys[i] = new GridByteArrayWrapper(key);
}
for (int i = 0; i < 10000; i++) {
int idx = rnd.nextInt(keys.length);
GridByteArrayWrapper key = keys[idx];
map.put(aff.partition(key), key.hashCode(), key.array(), new byte[64]);
}
}
/**
* @throws Exception If failed.
*/
@Test
public void testGet() throws Exception {
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
String val = string();
map.insert(p, hash(key), key.getBytes(), val.getBytes());
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertEquals(val, new String(map.get(p, hash(key), key.getBytes())));
assertEquals(10 * p + (i + 1), map.size());
}
}
assertEquals(parts * 10, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testPut1() throws Exception {
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
String val = string();
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertEquals(val, new String(map.get(p, hash(key), key.getBytes())));
assertEquals(10 * p + i + 1, map.size());
}
}
assertEquals(parts * 10, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testPut2() throws Exception {
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
String val1 = string();
String val2 = string();
assertTrue(map.put(p, hash(key), key.getBytes(), val1.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertEquals(val1, new String(map.get(p, hash(key), key.getBytes())));
assertEquals(10 * p + i + 1, map.size());
assertFalse(map.put(p, hash(key), key.getBytes(), val2.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertEquals(val2, new String(map.get(p, hash(key), key.getBytes())));
assertEquals(10 * p + i + 1, map.size());
}
}
assertEquals(parts * 10, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testRemove() throws Exception {
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
String val = string();
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
assertEquals(1, map.size());
byte[] val2 = map.remove(p, hash(key), key.getBytes());
assertNotNull(val2);
assertEquals(val, new String(val2));
assertFalse(map.contains(p, hash(key), key.getBytes()));
assertNull(map.get(p, hash(key), key.getBytes()));
assertEquals(0, map.size());
}
}
assertEquals(0, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testRemovex() throws Exception {
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
String val = string();
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
assertEquals(1, map.size());
boolean rmvd = map.removex(p, hash(key), key.getBytes());
assertTrue(rmvd);
assertFalse(map.contains(p, hash(key), key.getBytes()));
assertNull(map.get(p, hash(key), key.getBytes()));
assertEquals(0, map.size());
}
}
assertEquals(0, map.size());
}
/**
* @throws Exception If failed.
*/
@Test
public void testIterator() throws Exception {
initCap = 10;
map = newMap();
final AtomicInteger rehashes = new AtomicInteger();
final AtomicInteger releases = new AtomicInteger();
map.eventListener(new GridOffHeapEventListener() {
@Override public void onEvent(GridOffHeapEvent evt) {
switch (evt) {
case REHASH:
rehashes.incrementAndGet();
break;
case RELEASE:
releases.incrementAndGet();
break;
default: // No-op.
}
}
});
int max = 1024;
Map<String, String> m = new HashMap<>(max * parts);
for (int p = 0; p < parts; p++) {
for (int i = 0; i < max; i++) {
String key = string();
String val = string();
// info("Storing [i=" + i + ", key=" + key + ", val=" + val + ']');
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
m.put(key, val);
}
}
int cnt = 0;
try (GridCloseableIterator<IgniteBiTuple<byte[], byte[]>> it = map.iterator()) {
while (it.hasNext()) {
IgniteBiTuple<byte[], byte[]> t = it.next();
String k = new String(t.get1());
String v = new String(t.get2());
// info("Entry [k=" + k + ", v=" + v + ']');
assertEquals(m.get(k), v);
cnt++;
}
}
assertEquals(map.size(), cnt);
assertEquals(max * parts, map.size());
info("Stats [size=" + map.size() + ", rehashes=" + rehashes + ", releases=" + releases + ']');
assertTrue(rehashes.get() > 0);
assertEquals(rehashes.get(), releases.get());
}
/**
* @throws Exception If failed.
*/
@Test
public void testIteratorMultithreaded() throws Exception {
initCap = 10;
map = newMap();
final AtomicInteger rehashes = new AtomicInteger();
final AtomicInteger releases = new AtomicInteger();
map.eventListener(new GridOffHeapEventListener() {
@Override public void onEvent(GridOffHeapEvent evt) {
switch (evt) {
case REHASH:
rehashes.incrementAndGet();
break;
case RELEASE:
releases.incrementAndGet();
break;
default: // No-op.
}
}
});
final int max = 1024;
final ConcurrentMap<String, String> m = new ConcurrentHashMap<>(max * parts);
final AtomicInteger part = new AtomicInteger();
multithreaded(new Callable<Object>() {
@Override public Object call() throws Exception {
int p = part.getAndIncrement();
for (int i = 0; i < max; i++) {
String key = string();
String val = string();
// info("Storing [i=" + i + ", key=" + key + ", val=" + val + ']');
String old = m.putIfAbsent(key, val);
if (old != null)
val = old;
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
}
try (GridCloseableIterator<IgniteBiTuple<byte[], byte[]>> it = map.iterator()) {
while (it.hasNext()) {
IgniteBiTuple<byte[], byte[]> t = it.next();
String k = new String(t.get1());
String v = new String(t.get2());
// info("Entry [k=" + k + ", v=" + v + ']');
assertEquals(m.get(k), v);
}
}
return null;
}
}, parts);
int cnt = 0;
try (GridCloseableIterator<IgniteBiTuple<byte[], byte[]>> it = map.iterator()) {
while (it.hasNext()) {
IgniteBiTuple<byte[], byte[]> t = it.next();
String k = new String(t.get1());
String v = new String(t.get2());
// info("Entry [k=" + k + ", v=" + v + ']');
assertEquals(m.get(k), v);
cnt++;
}
}
assertEquals(map.size(), cnt);
assertEquals(max * parts, map.size());
info("Stats [size=" + map.size() + ", rehashes=" + rehashes + ", releases=" + releases + ']');
assertTrue(rehashes.get() > 0);
assertEquals(rehashes.get(), releases.get());
}
/**
* @throws Exception If failed.
*/
@Test
public void testIteratorRemoveMultithreaded() throws Exception {
initCap = 10;
map = newMap();
final int max = 1024;
final Map<String, String> m = new ConcurrentHashMap<>(max * parts);
for (int i = 0; i < max; i++) {
String key = string();
String val = string();
m.put(key, val);
map.put(0, hash(key), key.getBytes(), val.getBytes());
}
final AtomicBoolean running = new AtomicBoolean(true);
IgniteInternalFuture<?> iterFut = multithreadedAsync(new Runnable() {
@Override public void run() {
try {
while (running.get()) {
try (GridCloseableIterator<IgniteBiTuple<byte[], byte[]>> it = map.iterator()) {
while (it.hasNext()) {
IgniteBiTuple<byte[], byte[]> tup = it.next();
String key = new String(tup.get1());
String val = new String(tup.get2());
String exp = m.get(key);
assertEquals(exp, val);
}
}
}
}
catch (IgniteCheckedException e) {
fail("Unexpected exception caught: " + e);
}
}
}, 1);
for (String key : m.keySet())
map.remove(0, hash(key), key.getBytes());
running.set(false);
iterFut.get();
map.destruct();
}
/**
* @throws Exception If failed.
*/
@Test
public void testPartitionIterator() throws Exception {
initCap = 10;
map = newMap();
final AtomicInteger rehashes = new AtomicInteger();
final AtomicInteger releases = new AtomicInteger();
map.eventListener(new GridOffHeapEventListener() {
@Override public void onEvent(GridOffHeapEvent evt) {
switch (evt) {
case REHASH:
rehashes.incrementAndGet();
break;
case RELEASE:
releases.incrementAndGet();
break;
default: // No-op.
}
}
});
int max = 1024;
for (int p = 0; p < parts; p++) {
Map<String, String> m = new HashMap<>(max);
for (int i = 0; i < max; i++) {
String key = string();
String val = string();
// info("Storing [i=" + i + ", key=" + key + ", val=" + val + ']');
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
m.put(key, val);
int cnt = 0;
try (GridCloseableIterator<IgniteBiTuple<byte[], byte[]>> it = map.iterator(p)) {
while (it.hasNext()) {
IgniteBiTuple<byte[], byte[]> t = it.next();
String k = new String(t.get1());
String v = new String(t.get2());
// info("Entry [k=" + k + ", v=" + v + ']');
assertEquals(m.get(k), v);
cnt++;
}
}
assertEquals(map.size(), p * max + cnt);
}
}
assertEquals(max * parts, map.size());
info("Stats [size=" + map.size() + ", rehashes=" + rehashes + ", releases=" + releases + ']');
assertTrue(rehashes.get() > 0);
assertEquals(rehashes.get(), releases.get());
}
/**
* @throws Exception If failed.
*/
@Test
public void testPartitionIteratorMultithreaded() throws Exception {
initCap = 10;
map = newMap();
final AtomicInteger rehashes = new AtomicInteger();
final AtomicInteger releases = new AtomicInteger();
map.eventListener(new GridOffHeapEventListener() {
@Override public void onEvent(GridOffHeapEvent evt) {
switch (evt) {
case REHASH:
rehashes.incrementAndGet();
break;
case RELEASE:
releases.incrementAndGet();
break;
default: // No-op.
}
}
});
final int max = 64;
int threads = 5;
final Map<String, String> m = new ConcurrentHashMap<>(max);
multithreaded(new Callable() {
@Override public Object call() throws Exception {
for (int p = 0; p < parts; p++) {
for (int i = 0; i < max; i++) {
String key = string();
String val = string();
// info("Storing [i=" + i + ", key=" + key + ", val=" + val + ']');
m.put(key, val);
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
try (GridCloseableIterator<IgniteBiTuple<byte[], byte[]>> it = map.iterator(p)) {
while (it.hasNext()) {
IgniteBiTuple<byte[], byte[]> t = it.next();
String k = new String(t.get1());
String v = new String(t.get2());
// info("Entry [k=" + k + ", v=" + v + ']');
assertEquals(m.get(k), v);
}
}
}
}
return null;
}
}, threads);
assertEquals(max * threads * parts, map.size());
info("Stats [size=" + map.size() + ", rehashes=" + rehashes + ", releases=" + releases + ']');
assertTrue(rehashes.get() > 0);
assertEquals(rehashes.get(), releases.get());
}
/**
*
*/
@Test
public void testInsertLoad() {
mem = 0; // Disable LRU.
loadCnt = 50000;
map = newMap();
int cnt = 0;
for (int p = 0; p < parts; p++) {
Map<String, String> m = new HashMap<>();
for (int i = 0; i < loadCnt; i++)
m.put(string(), string());
for (Map.Entry<String, String> e : m.entrySet()) {
String key = e.getKey();
String val = e.getValue();
try {
map.insert(p, hash(key), key.getBytes(), val.getBytes());
}
catch (GridOffHeapOutOfMemoryException ex) {
error("Map put failed for count: " + cnt, ex);
throw ex;
}
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
assertEquals(++cnt, map.size());
}
}
}
/**
*
*/
@Test
public void testPutLoad() {
mem = 0; // Disable LRU.
loadCnt = 50000;
map = newMap();
int cnt = 0;
for (int p = 0; p < parts; p++) {
Map<String, String> m = new HashMap<>();
for (int i = 0; i < loadCnt; i++)
m.put(string(), string());
for (Map.Entry<String, String> e : m.entrySet()) {
String key = e.getKey();
String val = e.getValue();
try {
assertTrue(map.put(p, hash(key), key.getBytes(), val.getBytes()));
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertFalse(map.put(p, hash(key), key.getBytes(), val.getBytes()));
}
catch (GridOffHeapOutOfMemoryException ex) {
error("Map put failed for count: " + cnt, ex);
throw ex;
}
assertTrue(map.contains(p, hash(key), key.getBytes()));
assertNotNull(map.get(p, hash(key), key.getBytes()));
assertEquals(new String(map.get(p, hash(key), key.getBytes())), val);
assertEquals(++cnt, map.size());
}
}
}
/**
*
*/
@Test
public void testLru1() {
lruStripes = 1;
mem = 10;
final AtomicInteger evictCnt = new AtomicInteger();
evictLsnr = new GridOffHeapEvictListener() {
@Override public void onEvict(int part, int hash, byte[] k, byte[] v) {
String key = new String(k);
info("Evicted key: " + key);
evictCnt.incrementAndGet();
}
@Override public boolean removeEvicted() {
return true;
}
};
map = newMap();
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10; i++) {
String key = string();
byte[] keyBytes = key.getBytes();
byte[] valBytes = bytes(100);
map.insert(p, hash(key), keyBytes, valBytes);
info("Evicted: " + evictCnt);
assertEquals(1, evictCnt.get());
assertEquals(0, map.size());
assertTrue(evictCnt.compareAndSet(1, 0));
}
}
}
/**
*
*/
@Test
public void testLru2() {
mem = 1000 + 64 * 16 * parts; // Add segment size.
lruStripes = 6;
concurrency = 8;
final AtomicInteger evictCnt = new AtomicInteger();
for (int p = 0; p < parts; p++) {
evictLsnr = new GridOffHeapEvictListener() {
@Override public void onEvict(int part, int hash, byte[] k, byte[] v) {
evictCnt.incrementAndGet();
}
@Override public boolean removeEvicted() {
return true;
}
};
map = newMap();
for (int i = 0; i < 10000; i++) {
String key = string();
byte[] keyBytes = key.getBytes();
byte[] valBytes = bytes(100);
map.insert(p, hash(key), keyBytes, valBytes);
}
assertTrue(evictCnt.get() > 10 * parts);
assertTrue("Invalid map free size [size=" + map.freeSize() + ", evictCnt=" + evictCnt + ']',
map.freeSize() >= 0);
}
}
/**
* @throws Exception If failed.
*/
@Test
public void testLruMultithreaded() throws Exception {
mem = 1000 + 64 * 16 * parts; // Add segment size.
lruStripes = 3;
concurrency = 8;
final AtomicInteger evictCnt = new AtomicInteger();
final AtomicInteger cnt = new AtomicInteger();
evictLsnr = new GridOffHeapEvictListener() {
@Override public void onEvict(int part, int hash, byte[] k, byte[] v) {
evictCnt.incrementAndGet();
}
@Override public boolean removeEvicted() {
return true;
}
};
map = newMap();
assertEquals(0, map.allocatedSize());
multithreaded(new Runnable() {
@Override public void run() {
for (int p = 0; p < parts; p++) {
for (int i = 0; i < 10000; i++) {
String key = string();
byte[] keyBytes = key.getBytes();
byte[] valBytes = bytes(100);
assert !map.contains(p, hash(key), keyBytes);
map.insert(p, hash(key), keyBytes, valBytes);
int n;
if ((n = cnt.incrementAndGet()) % 100000 == 0)
info("Inserted entries: " + n);
}
}
}
}, 10);
assert map.allocatedSize() <= mem;
info("Map stats [evicted=" + evictCnt + ", size=" + map.size() + ", allocated=" + map.allocatedSize() +
", freeSize=" + map.freeSize() + ']');
assertTrue("Invalid map free size [size=" + map.freeSize() + ", evictCnt=" + evictCnt + ']',
map.freeSize() >= 0);
}
/**
*
*/
@SuppressWarnings("TooBroadScope")
@Test
public void testValuePointerEvict() {
mem = 90;
final GridTuple<String> evicted = new GridTuple<>();
evictLsnr = new GridOffHeapEvictListener() {
@Override public void onEvict(int part, int hash, byte[] k, byte[] v) {
String key = new String(k);
evicted.set(key);
}
@Override public boolean removeEvicted() {
return true;
}
};
map = newMap();
final String k1 = "k1";
final String k2 = "k2";
map.put(1, k1.hashCode(), k1.getBytes(), bytes(20));
assertNull(evicted.get());
assertNotNull(map.valuePointer(1, k1.hashCode(), k1.getBytes()));
assertNull(evicted.get());
map.put(1, k2.hashCode(), k2.getBytes(), bytes(20));
assertEquals(k2, evicted.get());
evicted.set(null);
assertTrue(map.contains(1, k1.hashCode(), k1.getBytes()));
map.put(1, k1.hashCode(), k1.getBytes(), bytes(20));
assertNull(evicted.get());
map.put(1, k2.hashCode(), k2.getBytes(), bytes(20));
assertEquals(k1, evicted.get());
assertNull(map.valuePointer(1, k1.hashCode(), k1.getBytes()));
evicted.set(null);
assertNotNull(map.valuePointer(1, k2.hashCode(), k2.getBytes()));
assertNull(evicted.get());
map.put(1, k1.hashCode(), k1.getBytes(), bytes(21));
assertEquals(k1, evicted.get());
evicted.set(null);
map.put(1, k2.hashCode(), k2.getBytes(), bytes(21));
}
/**
*
*/
@SuppressWarnings("TooBroadScope")
@Test
public void testValuePointerEnableEviction() {
mem = 90;
final GridTuple<String> evicted = new GridTuple<>();
evictLsnr = new GridOffHeapEvictListener() {
@Override public void onEvict(int part, int hash, byte[] k, byte[] v) {
String key = new String(k);
evicted.set(key);
}
@Override public boolean removeEvicted() {
return true;
}
};
map = newMap();
final String k1 = "k1";
final String k2 = "k2";
map.put(1, k1.hashCode(), k1.getBytes(), bytes(20));
assertNull(evicted.get());
assertNotNull(map.valuePointer(1, k1.hashCode(), k1.getBytes()));
assertNull(evicted.get());
map.put(1, k2.hashCode(), k2.getBytes(), bytes(20));
assertEquals(k2, evicted.get());
evicted.set(null);
assertTrue(map.contains(1, k1.hashCode(), k1.getBytes()));
map.enableEviction(1, k1.hashCode(), k1.getBytes());
assertNull(evicted.get());
map.put(1, k2.hashCode(), k2.getBytes(), bytes(20));
assertEquals(k1, evicted.get());
assertNull(map.valuePointer(1, k1.hashCode(), k1.getBytes()));
evicted.set(null);
assertNotNull(map.valuePointer(1, k2.hashCode(), k2.getBytes()));
assertNull(evicted.get());
map.put(1, k1.hashCode(), k1.getBytes(), bytes(21));
assertEquals(k1, evicted.get());
evicted.set(null);
map.put(1, k2.hashCode(), k2.getBytes(), bytes(21));
}
/**
*
*/
@Test
public void testValuePointerRemove() {
map = newMap();
final String k = "k1";
map.put(1, k.hashCode(), k.getBytes(), bytes(10));
assertNotNull(map.valuePointer(1, k.hashCode(), k.getBytes()));
map.remove(1, k.hashCode(), k.getBytes());
assertNull(map.valuePointer(1, k.hashCode(), k.getBytes()));
}
}