/* * Copyright (c) 2008-2017, Hazelcast, Inc. 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.cache.impl; import com.hazelcast.cache.CacheFromDifferentNodesTest; import com.hazelcast.cache.CacheTestSupport; import com.hazelcast.cache.HazelcastCacheManager; import com.hazelcast.config.CacheConfig; import com.hazelcast.config.Config; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.instance.Node; import com.hazelcast.instance.TestUtil; import com.hazelcast.internal.partition.InternalPartitionService; import com.hazelcast.nio.serialization.DataSerializableFactory; import com.hazelcast.nio.serialization.IdentifiedDataSerializable; import com.hazelcast.spi.impl.AbstractNamedOperation; import com.hazelcast.spi.impl.NodeEngineImpl; import com.hazelcast.spi.impl.operationservice.InternalOperationService; import com.hazelcast.test.HazelcastParallelClassRunner; import com.hazelcast.test.TestHazelcastInstanceFactory; import com.hazelcast.test.annotation.ParallelTest; import com.hazelcast.test.annotation.QuickTest; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import javax.cache.Cache; import javax.cache.configuration.FactoryBuilder; import javax.cache.configuration.MutableCacheEntryListenerConfiguration; import java.util.concurrent.Future; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @RunWith(HazelcastParallelClassRunner.class) @Category({QuickTest.class, ParallelTest.class}) public class InternalCacheRecordStoreTest extends CacheTestSupport { private TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(2); @Override protected void onSetup() { } @Override protected void onTearDown() { factory.shutdownAll(); } @Override protected HazelcastInstance getHazelcastInstance() { return factory.newHazelcastInstance(createConfig()); } @Override protected Config createConfig() { Config config = super.createConfig(); config.getSerializationConfig().addDataSerializableFactory(InternalCacheRecordStoreTestFactory.F_ID, new InternalCacheRecordStoreTestFactory()); return config; } /** * Test for issue: https://github.com/hazelcast/hazelcast/issues/6618 */ @Test public void batchEventMapShouldBeCleanedAfterRemoveAll() { String cacheName = randomString(); CacheConfig<Integer, String> config = createCacheConfig(); CacheFromDifferentNodesTest.SimpleEntryListener<Integer, String> listener = new CacheFromDifferentNodesTest.SimpleEntryListener<Integer, String>(); MutableCacheEntryListenerConfiguration<Integer, String> listenerConfiguration = new MutableCacheEntryListenerConfiguration<Integer, String>( FactoryBuilder.factoryOf(listener), null, true, true); config.addCacheEntryListenerConfiguration(listenerConfiguration); Cache<Integer, String> cache = cacheManager.createCache(cacheName, config); assertNotNull(cache); Integer key = 1; String value = "value"; cache.put(key, value); HazelcastInstance instance = ((HazelcastCacheManager) cacheManager).getHazelcastInstance(); int partitionId = instance.getPartitionService().getPartition(key).getPartitionId(); cache.removeAll(); Node node = getNode(instance); assertNotNull(node); ICacheService cacheService = node.getNodeEngine().getService(ICacheService.SERVICE_NAME); AbstractCacheRecordStore recordStore = (AbstractCacheRecordStore) cacheService .getRecordStore("/hz/" + cacheName, partitionId); assertEquals(0, recordStore.batchEvent.size()); } /** * Test for issue: https://github.com/hazelcast/hazelcast/issues/6983 */ @Test public void ownerStateShouldBeUpdatedAfterMigration() throws Exception { HazelcastCacheManager hzCacheManager = (HazelcastCacheManager) cacheManager; HazelcastInstance instance1 = hzCacheManager.getHazelcastInstance(); Node node1 = TestUtil.getNode(instance1); NodeEngineImpl nodeEngine1 = node1.getNodeEngine(); InternalPartitionService partitionService1 = nodeEngine1.getPartitionService(); int partitionCount = partitionService1.getPartitionCount(); String cacheName = randomName(); CacheConfig cacheConfig = new CacheConfig().setName(cacheName); Cache<String, String> cache = cacheManager.createCache(cacheName, cacheConfig); String fullCacheName = hzCacheManager.getCacheNameWithPrefix(cacheName); for (int i = 0; i < partitionCount; i++) { String key = generateKeyForPartition(instance1, i); cache.put(key, "Value"); } for (int i = 0; i < partitionCount; i++) { verifyPrimaryState(node1, fullCacheName, i, true); } HazelcastInstance instance2 = getHazelcastInstance(); Node node2 = TestUtil.getNode(instance2); warmUpPartitions(instance1, instance2); waitAllForSafeState(instance1, instance2); for (int i = 0; i < partitionCount; i++) { boolean ownedByNode1 = partitionService1.isPartitionOwner(i); if (ownedByNode1) { verifyPrimaryState(node1, fullCacheName, i, true); verifyPrimaryState(node2, fullCacheName, i, false); } else { verifyPrimaryState(node1, fullCacheName, i, false); verifyPrimaryState(node2, fullCacheName, i, true); } } } private void verifyPrimaryState(Node node, String fullCacheName, int partitionId, boolean expectedState) throws Exception { NodeEngineImpl nodeEngine = node.getNodeEngine(); InternalOperationService operationService = nodeEngine.getOperationService(); Future<Boolean> isPrimaryOnNode = operationService.invokeOnTarget( ICacheService.SERVICE_NAME, createCacheOwnerStateGetterOperation(fullCacheName, partitionId), node.getThisAddress()); assertEquals(expectedState, isPrimaryOnNode.get()); } private CachePrimaryStateGetterOperation createCacheOwnerStateGetterOperation(String fullCacheName, int partitionId) { CachePrimaryStateGetterOperation operation = new CachePrimaryStateGetterOperation(fullCacheName); operation.setPartitionId(partitionId); operation.setValidateTarget(false); return operation; } static class CachePrimaryStateGetterOperation extends AbstractNamedOperation { private boolean isPrimary; private CachePrimaryStateGetterOperation() { } private CachePrimaryStateGetterOperation(String cacheName) { super(cacheName); } @Override public void run() throws Exception { ICacheService cacheService = getService(); AbstractCacheRecordStore cacheRecordStore = (AbstractCacheRecordStore) cacheService.getRecordStore(name, getPartitionId()); isPrimary = cacheRecordStore.primary; } @Override public Object getResponse() { return isPrimary; } @Override public String getServiceName() { return ICacheService.SERVICE_NAME; } @Override public int getFactoryId() { return InternalCacheRecordStoreTestFactory.F_ID; } @Override public int getId() { return InternalCacheRecordStoreTestFactory.INTERNAL_CACHE_PRIMARY_STATE_GETTER; } } static class InternalCacheRecordStoreTestFactory implements DataSerializableFactory { static final int F_ID = 1; static final int INTERNAL_CACHE_PRIMARY_STATE_GETTER = 0; @Override public IdentifiedDataSerializable create(int typeId) { if (typeId == INTERNAL_CACHE_PRIMARY_STATE_GETTER) { return new CachePrimaryStateGetterOperation(); } else { throw new UnsupportedOperationException("Could not create instance of type id " + typeId); } } } }