/*
* Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved.
*
* Licensed 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 com.hazelcast.impl;
import com.hazelcast.config.Config;
import com.hazelcast.core.*;
import com.hazelcast.impl.base.CallState;
import com.hazelcast.impl.base.DistributedLock;
import com.hazelcast.impl.base.ScheduledAction;
import com.hazelcast.nio.Data;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static com.hazelcast.nio.IOUtil.toData;
import static com.hazelcast.nio.IOUtil.toObject;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
@RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class)
public class CMapTest extends TestUtil {
@BeforeClass
public static void init() throws Exception {
System.setProperty(GroupProperties.PROP_WAIT_SECONDS_BEFORE_JOIN, "1");
System.setProperty(GroupProperties.PROP_VERSION_CHECK_ENABLED, "false");
Hazelcast.shutdownAll();
}
@After
public void cleanup() throws Exception {
Hazelcast.shutdownAll();
}
@Test
@Ignore
public void testCallState() throws Exception {
Config config = new Config();
final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config);
final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config);
final Node node1 = getNode(h1);
final Node node2 = getNode(h2);
Thread.sleep(100);
final CountDownLatch latch = new CountDownLatch(1);
final IMap imap1 = h1.getMap("default");
new Thread(new Runnable() {
public void run() {
imap1.lock("1");
latch.countDown();
}
}).start();
latch.await();
// final IMap imap2 = h2.getMap("default");
final AtomicInteger threadId = new AtomicInteger();
new Thread(new Runnable() {
public void run() {
ThreadContext.get().setCurrentFactory(node1.factory);
threadId.set(ThreadContext.get().getThreadId());
imap1.put("1", "value1");
}
}).start();
Thread.sleep(1000);
System.out.println(node1.getThisAddress() + " thread " + threadId.get());
CallState callState1 = node1.getSystemLogService().getCallState(node1.getThisAddress(), threadId.get());
if (callState1 != null) {
for (Object callStateLog : callState1.getLogs()) {
System.out.println(callStateLog);
}
}
CallState callState2 = node2.getSystemLogService().getCallState(node1.getThisAddress(), threadId.get());
System.out.println("========================");
if (callState2 != null) {
for (Object callStateLog : callState2.getLogs()) {
System.out.println(callStateLog);
}
}
}
@Test
public void testMigrationOfTTLAndLock() throws Exception {
Config config = new Config();
final HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config);
final HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config);
ConcurrentMapManager cmm1 = getConcurrentMapManager(h1);
ConcurrentMapManager cmm2 = getConcurrentMapManager(h2);
final IMap imap1 = h1.getMap("default");
final IMap imap2 = h2.getMap("default");
final Data dKey = toData("1");
assertTrue(migrateKey("1", h1, h1, 0));
assertTrue(migrateKey("1", h1, h2, 1));
imap1.put("1", "value1", 60, TimeUnit.SECONDS);
imap1.lock("1");
Future put2 = imap2.putAsync("1", "value2");
imap2.addEntryListener(new EntryAdapter() {
@Override
public void entryUpdated(EntryEvent entryEvent) {
System.out.println(entryEvent);
}
}, "1", true);
if (put2 == null) fail();
Thread.sleep(1000);
CMap cmap1 = getCMap(h1, "default");
CMap cmap2 = getCMap(h2, "default");
Record record1 = cmap1.getRecord(dKey);
assertEquals(1, record1.getScheduledActionCount());
for (ScheduledAction scheduledAction : record1.getScheduledActions()) {
assertTrue(scheduledAction.isValid());
}
assertNotNull(record1.getListeners());
assertEquals(1, record1.getListeners().size());
DistributedLock lock = cmap1.getRecord(dKey).getLock();
assertTrue(cmm1.thisAddress.equals(lock.getLockAddress()));
assertTrue(lock.getLockThreadId() != -1);
assertEquals(1, lock.getLockCount());
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(0, cmap2.getMapIndexService().getOwnedRecords().size());
assertEquals(1, cmap1.getMapIndexService().getOwnedRecords().size());
assertTrue(migrateKey("1", h1, h2, 0));
assertTrue(migrateKey("1", h1, h1, 1));
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(0, cmap1.getMapIndexService().getOwnedRecords().size());
assertEquals(1, cmap2.getMapIndexService().getOwnedRecords().size());
assertTrue(cmap1.getRecord(dKey).getRemainingTTL() < 60000);
assertTrue(cmap2.getRecord(dKey).getRemainingTTL() < 60000);
Record record2 = cmap2.getRecord(dKey);
lock = record2.getLock();
assertTrue(cmm1.thisAddress.equals(lock.getLockAddress()));
assertTrue(lock.getLockThreadId() != -1);
assertEquals(1, lock.getLockCount());
lock = cmap1.getRecord(dKey).getLock();
assertTrue(cmm1.thisAddress.equals(lock.getLockAddress()));
assertTrue(lock.getLockThreadId() != -1);
assertEquals(1, lock.getLockCount());
imap1.unlock("1");
put2.get(10, TimeUnit.SECONDS);
assertEquals("value2", imap1.get("1"));
assertEquals("value2", imap2.get("1"));
assertNotNull(record2.getListeners());
assertEquals(1, record2.getListeners().size());
}
@Test
public void testPutWithTwoMember() throws Exception {
Config config = new Config();
HazelcastInstance h1 = Hazelcast.newHazelcastInstance(config);
HazelcastInstance h2 = Hazelcast.newHazelcastInstance(config);
assertEquals(2, h1.getCluster().getMembers().size());
assertEquals(2, h2.getCluster().getMembers().size());
IMap imap1 = h1.getMap("default");
IMap imap2 = h2.getMap("default");
assertEquals(0, imap1.size());
assertEquals(0, imap2.size());
CMap cmap1 = getCMap(h1, "default");
CMap cmap2 = getCMap(h2, "default");
assertNotNull(cmap1);
assertNotNull(cmap2);
Object key = "1";
Object value = "value";
Data dKey = toData(key);
Data dValue = toData(value);
imap1.put(key, value, 5, TimeUnit.SECONDS);
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(1, cmap1.getMapIndexService().getOwnedRecords().size() + cmap2.getMapIndexService().getOwnedRecords().size());
Record record1 = cmap1.getRecord(dKey);
Record record2 = cmap2.getRecord(dKey);
long now = System.currentTimeMillis();
long millisLeft1 = record1.getExpirationTime() - now;
long millisLeft2 = record2.getExpirationTime() - now;
assertTrue(millisLeft1 <= 5000 && millisLeft1 > 0);
assertTrue(millisLeft2 <= 5000 && millisLeft2 > 0);
assertTrue(record1.isActive());
assertTrue(record2.isActive());
assertEquals(1, record1.valueCount());
assertEquals(1, record2.valueCount());
assertEquals(dValue, record1.getValueData());
assertEquals(dValue, record2.getValueData());
imap1.set("2", "value2", 5, TimeUnit.SECONDS);
assertEquals("value2", imap1.get("2"));
assertEquals("value2", imap2.get("2"));
Thread.sleep(6000);
assertNull(imap1.get("2"));
assertNull(imap2.get("2"));
now = System.currentTimeMillis();
assertFalse(record1.isValid(now));
assertFalse(record2.isValid(now));
Thread.sleep(23000);
assertEquals(0, cmap1.getMapIndexService().getOwnedRecords().size());
assertEquals(0, cmap2.getMapIndexService().getOwnedRecords().size());
assertEquals(0, cmap1.mapRecords.size());
assertEquals(0, cmap2.mapRecords.size());
imap1.put(key, value, 10, TimeUnit.SECONDS);
assertTrue(migrateKey(key, h1, h1, 0));
assertTrue(migrateKey(key, h1, h2, 1));
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(1, cmap1.getMapIndexService().getOwnedRecords().size() + cmap2.getMapIndexService().getOwnedRecords().size());
record1 = cmap1.getRecord(dKey);
record2 = cmap2.getRecord(dKey);
now = System.currentTimeMillis();
millisLeft1 = record1.getExpirationTime() - now;
millisLeft2 = record2.getExpirationTime() - now;
assertTrue(millisLeft1 <= 11000 && millisLeft1 > 0);
assertTrue(millisLeft2 <= 11000 && millisLeft2 > 0);
assertTrue(record1.isActive());
assertTrue(record2.isActive());
assertTrue(record1.isValid(now));
assertTrue(record2.isValid(now));
assertEquals(1, record1.valueCount());
assertEquals(1, record2.valueCount());
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(1, cmap1.getMapIndexService().getOwnedRecords().size() + cmap2.getMapIndexService().getOwnedRecords().size());
assertTrue(migrateKey(key, h1, h2, 0));
assertTrue(migrateKey(key, h1, h1, 1));
cmap1.startCleanup(true);
cmap2.startCleanup(true);
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(1, cmap2.getMapIndexService().getOwnedRecords().size());
assertEquals(0, cmap1.getMapIndexService().getOwnedRecords().size());
now = System.currentTimeMillis();
millisLeft1 = record1.getExpirationTime() - now;
millisLeft2 = record2.getExpirationTime() - now;
assertTrue(millisLeft1 <= 10000 && millisLeft1 > 0);
assertTrue(millisLeft2 <= 10000 && millisLeft2 > 0);
assertTrue(record1.isActive());
assertTrue(record2.isActive());
assertTrue(record1.isValid(now));
assertTrue(record2.isValid(now));
assertEquals(1, record1.valueCount());
assertEquals(1, record2.valueCount());
Thread.sleep(11000);
now = System.currentTimeMillis();
assertFalse(record1.isValid(now));
assertFalse(record2.isValid(now));
Thread.sleep(20000);
assertEquals(0, cmap1.mapRecords.size());
assertEquals(0, cmap2.mapRecords.size());
assertEquals(0, cmap1.getMapIndexService().getOwnedRecords().size());
assertEquals(0, cmap2.getMapIndexService().getOwnedRecords().size());
imap1.put("1", "value1");
record1 = cmap1.getRecord(dKey);
record2 = cmap2.getRecord(dKey);
assertEquals(1, cmap1.mapRecords.size());
assertEquals(1, cmap2.mapRecords.size());
assertEquals(0, cmap1.getMapIndexService().getOwnedRecords().size());
assertEquals(1, cmap2.getMapIndexService().getOwnedRecords().size());
now = System.currentTimeMillis();
assertEquals(Long.MAX_VALUE, record1.getExpirationTime());
assertEquals(Long.MAX_VALUE, record2.getExpirationTime());
assertTrue(record1.isActive());
assertTrue(record2.isActive());
assertTrue(record1.isValid(now));
assertTrue(record2.isValid(now));
assertEquals(1, record1.valueCount());
assertEquals(1, record2.valueCount());
imap1.remove("1");
assertEquals(0, cmap1.getMapIndexService().getOwnedRecords().size());
assertEquals(0, cmap2.getMapIndexService().getOwnedRecords().size());
Thread.sleep(20000);
assertEquals(0, cmap1.mapRecords.size());
assertEquals(0, cmap2.mapRecords.size());
assertEquals(0, cmap1.mapIndexService.size());
assertEquals(0, cmap2.mapIndexService.size());
}
@Test
public void testTTL() throws Exception {
Config config = new Config();
FactoryImpl mockFactory = mock(FactoryImpl.class);
// we mocked the node
// do not forget to shutdown the connectionManager
// so that server socket can be released.
Node node = new Node(mockFactory, config);
node.serviceThread = Thread.currentThread();
CMap cmap = new CMap(node.concurrentMapManager, "c:myMap");
Object key = "1";
Object value = "istanbul";
Data dKey = toData(key);
Data dValue = toData(value);
Request reqPut = newPutRequest(dKey, dValue);
reqPut.ttl = 3000;
cmap.put(reqPut);
assertTrue(cmap.mapRecords.containsKey(toData(key)));
Data actualValue = cmap.get(newGetRequest(dKey));
assertThat(toObject(actualValue), equalTo(value));
assertEquals(1, cmap.mapRecords.size());
Record record = cmap.getRecord(dKey);
assertNotNull(record);
assertTrue(record.isActive());
assertTrue(record.isValid());
assertEquals(1, cmap.size());
assertNotNull(cmap.get(newGetRequest(dKey)));
assertEquals(dValue, cmap.get(newGetRequest(dKey)));
assertTrue(record.getRemainingTTL() > 1000);
Thread.sleep(1000);
assertTrue(record.getRemainingTTL() < 2100);
cmap.put(newPutRequest(dKey, dValue));
assertTrue(record.getRemainingTTL() > 2001);
assertTrue(record.isActive());
assertTrue(record.isValid());
Thread.sleep(1000);
assertTrue(record.getRemainingTTL() < 2100);
cmap.put(newPutRequest(dKey, dValue));
assertTrue(record.getRemainingTTL() > 2001);
assertTrue(record.isActive());
assertTrue(record.isValid());
Thread.sleep(5000);
assertEquals(0, cmap.size());
assertTrue(cmap.evict(newEvictRequest(dKey)));
assertTrue(cmap.shouldPurgeRecord(record, System.currentTimeMillis() + 10000));
cmap.removeAndPurgeRecord(record);
assertEquals(0, cmap.mapRecords.size());
assertEquals(0, cmap.size());
assertEquals(0, cmap.mapIndexService.size());
node.connectionManager.shutdown();
}
@Test
public void testPut() throws Exception {
Config config = new Config();
FactoryImpl mockFactory = mock(FactoryImpl.class);
// we mocked the node
// do not forget to shutdown the connectionManager
// so that server socket can be released.
Node node = new Node(mockFactory, config);
node.serviceThread = Thread.currentThread();
CMap cmap = new CMap(node.concurrentMapManager, "c:myMap");
Object key = "1";
Object value = "istanbul";
Data dKey = toData(key);
Data dValue = toData(value);
cmap.put(newPutRequest(dKey, dValue));
assertTrue(cmap.mapRecords.containsKey(toData(key)));
Data actualValue = cmap.get(newGetRequest(dKey));
assertThat(toObject(actualValue), equalTo(value));
assertEquals(1, cmap.mapRecords.size());
Record record = cmap.getRecord(dKey);
assertNotNull(record);
assertTrue(record.isActive());
assertTrue(record.isValid());
assertEquals(1, cmap.size());
cmap.remove(newRemoveRequest(dKey));
assertTrue(System.currentTimeMillis() - record.getRemoveTime() < 100);
assertEquals(1, cmap.mapRecords.size());
record = cmap.getRecord(dKey);
assertNotNull(record);
assertFalse(record.isActive());
assertFalse(record.isValid());
assertEquals(0, cmap.size());
cmap.put(newPutRequest(dKey, dValue, 1000));
assertEquals(0, record.getRemoveTime());
assertTrue(cmap.mapRecords.containsKey(toData(key)));
Thread.sleep(1500);
assertEquals(0, cmap.size());
assertFalse(cmap.contains(newContainsRequest(dKey, null)));
node.connectionManager.shutdown();
}
}