Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,9 @@ public IgniteInternalFuture<?> onCacheChangeRequest(

IgniteInternalFuture<?> res = cachesRegistry.update(exchActions);

for (ExchangeActions.CacheActionData d: exchActions.cacheStartRequests())
cctx.coordinators().validateCacheConfiguration(d.descriptor().cacheConfiguration());

// Affinity did not change for existing caches.
onCustomMessageNoAffinityChange(fut, exchActions);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,9 @@ public IgniteInternalFuture<?> startCachesOnLocalJoin(
IgniteInternalFuture<?> res = sharedCtx.affinity().initCachesOnLocalJoin(
locJoinCtx.cacheGroupDescriptors(), locJoinCtx.cacheDescriptors());

for (DynamicCacheDescriptor d: locJoinCtx.cacheDescriptors().values())
ctx.coordinators().validateCacheConfiguration(d.cacheConfiguration());

List<StartCacheInfo> startCacheInfos = locJoinCtx.caches().stream()
.map(cacheInfo -> new StartCacheInfo(cacheInfo.get1(), cacheInfo.get2(), exchTopVer, false))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
Expand Down Expand Up @@ -70,27 +71,33 @@ public class CachePartitionLossWithRestartsTest extends GridCommonAbstractTest {
@Parameterized.Parameter(value = 3)
public int clientIdx;

/** Possible values: true, false */
@Parameterized.Parameter(value = 4)
public boolean mvccEnabled;

/** */
@Parameterized.Parameters(name = "{0} {1} {2} {3}")
public static List<Object[]> parameters() {
ArrayList<Object[]> params = new ArrayList<>();

for (boolean persistent : new boolean[]{false, true}) {
params.add(new Object[]{-1, false, persistent, 3});
params.add(new Object[]{0, false, persistent, 3});
params.add(new Object[]{2, false, persistent, 3});
for (boolean mvcc : new boolean[]{false, true}) {
for (boolean persistent : new boolean[] {false, true}) {
params.add(new Object[] {-1, false, persistent, 3, mvcc});
params.add(new Object[] {0, false, persistent, 3, mvcc});
params.add(new Object[] {2, false, persistent, 3, mvcc});

params.add(new Object[]{-1, false, persistent, -1});
params.add(new Object[]{0, false, persistent, -1});
params.add(new Object[]{2, false, persistent, -1});
params.add(new Object[] {-1, false, persistent, -1, mvcc});
params.add(new Object[] {0, false, persistent, -1, mvcc});
params.add(new Object[] {2, false, persistent, -1, mvcc});

params.add(new Object[]{-1, true, persistent, 3});
params.add(new Object[]{0, true, persistent, 3});
params.add(new Object[]{2, true, persistent, 3});
params.add(new Object[] {-1, true, persistent, 3, mvcc});
params.add(new Object[] {0, true, persistent, 3, mvcc});
params.add(new Object[] {2, true, persistent, 3, mvcc});

params.add(new Object[]{-1, true, persistent, -1});
params.add(new Object[]{0, true, persistent, -1});
params.add(new Object[]{2, true, persistent, -1});
params.add(new Object[] {-1, true, persistent, -1, mvcc});
params.add(new Object[] {0, true, persistent, -1, mvcc});
params.add(new Object[] {2, true, persistent, -1, mvcc});
}
}

return params;
Expand Down Expand Up @@ -128,6 +135,9 @@ public static List<Object[]> parameters() {
setBackups(0).
setAffinity(new RendezvousAffinityFunction(false, PARTS_CNT));

if (mvccEnabled)
ccfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT);

if (startClientCache)
cfg.setCacheConfiguration(ccfg);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
/*
* 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.processors.cache.mvcc;

import org.apache.ignite.cluster.ClusterState;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.util.AttributeNodeFilter;
import org.junit.Test;

import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;

/**
* Tests cover cases for correct MVCC flag set for client topology.
* Client topology, in relation to a specific cache, consist of nodes that match both conditions:
* - filtered with AttributeNodeFilter for the cache;
* - don't configured with CacheConfiguration for the cache.
*/
@SuppressWarnings("unchecked")
public class CacheMvccClientTopologyTest extends GridCommonAbstractTest {
/**
* Index of node that in client topology
*/
private static final int clientModeIdx = 0;

/**
* Index of node that holds a cache
*/
private static final int cacheModeIdx = 1;

/**
* Check that by default MVCC is disabled for client topology
*/
@Test
public void testMvccDisabledByDefaultForClientTopology() throws Exception {
// when
final IgniteEx crd = startGrid(getTestIgniteInstanceName(clientModeIdx));
checkTopology(1);

// then
assertNodesMvccDisabled(crd);
}

/**
* Check that MVCC is enabled for client topology if node with MVCC cache joined
*/
@Test
public void testMvccEnabledForClientTopology() throws Exception {
// when
final IgniteEx crd = startGrid(getTestIgniteInstanceName(clientModeIdx));
final IgniteEx node = startGrid(getTestIgniteInstanceName(cacheModeIdx));

checkTopology(2);

// then
assertNodesMvccEnabled(crd, node);
}

/**
* Check that MVCC status doesn't change for client topology when MVCC cache node left
*/
@Test
public void testMvccEnabledForClientTopologyAfterCacheNodeLeft() throws Exception {
// when
final IgniteEx crd = startGrid(getTestIgniteInstanceName(clientModeIdx));
startGrid(getTestIgniteInstanceName(cacheModeIdx));

checkTopology(2);
stopGrid(cacheModeIdx);
checkTopology(1);

// then
assertNodesMvccEnabled(crd);
}

/**
* Check that MVCC status doesn't change for client topology when MVCC cache node coordinator left
*/
@Test
public void testMvccEnabledForClientTopologyStartedAfterCacheJoined() throws Exception {
// when
startGrid(getTestIgniteInstanceName(cacheModeIdx));
final IgniteEx node = startGrid(getTestIgniteInstanceName(clientModeIdx));

checkTopology(2);
stopGrid(cacheModeIdx);
checkTopology(1);

// then
assertNodesMvccEnabled(node);
}

/**
* Check that MVCC is disabled when cluster state changed to INACTIVE
*/
@Test
public void testMvccDisbledForClientTopologyAfterClusterStateChangeToInactive() throws Exception {
// when
final IgniteEx crd = startGrid(getTestIgniteInstanceName(clientModeIdx));
final IgniteEx node = startGrid(getTestIgniteInstanceName(cacheModeIdx));

checkTopology(2);
crd.cluster().state(ClusterState.INACTIVE);

// then
assertNodesMvccDisabled(crd, node);
}

/**
* Check that MVCC is disabled for client topology if cluster state is INACTIVE but cache node joined
*/
@Test
public void testMvccDisabledForClientTopologyCrdBeforeClusterStateChange() throws Exception {
// given
IgniteConfiguration crdCfg = getInactiveConfiguration(clientModeIdx);
IgniteConfiguration nodeCfg = getInactiveConfiguration(cacheModeIdx);

// when
final IgniteEx crd = startGrid(crdCfg);
final IgniteEx node = startGrid(nodeCfg);
checkTopology(2);

// then
assertNodesMvccDisabled(crd);
assertNodesMvccEnabled(node);
}

/**
* Check that MVCC is disabled for client topology if cluster state is INACTIVE but cache node joined
*/
@Test
public void testMvccDisabledForClientTopologyBeforeClusterStateChange() throws Exception {
// given
IgniteConfiguration crdCfg = getInactiveConfiguration(cacheModeIdx);
IgniteConfiguration nodeCfg = getInactiveConfiguration(clientModeIdx);

// when
final IgniteEx crd = startGrid(crdCfg);
final IgniteEx node = startGrid(nodeCfg);
checkTopology(2);

// then
assertNodesMvccEnabled(crd);
assertNodesMvccDisabled(node);
}

/**
* Check that MVCC is disabled for client topology if cluster changed state to ACTIVE
*/
@Test
public void testMvccDisabledForClientTopologyAfterClusterStateChange() throws Exception {
// given
IgniteConfiguration crdCfg = getConfiguration(getTestIgniteInstanceName(clientModeIdx))
.setClusterStateOnStart(ClusterState.INACTIVE);

// when
final IgniteEx crd = (IgniteEx) startGrid(getTestIgniteInstanceName(clientModeIdx), crdCfg);

checkTopology(1);
crd.cluster().state(ClusterState.ACTIVE);

// then
assertNodesMvccDisabled(crd);
}

/**
* Check that MVCC is enabled for client topology if cluster state changed to ACTIVE and cache node joined
*/
@Test
public void testMvccEnabledForClientTopologyAfterClusterStateChange() throws Exception {
// given
IgniteConfiguration crdCfg = getInactiveConfiguration(clientModeIdx);
IgniteConfiguration nodeCfg = getInactiveConfiguration(cacheModeIdx);

// when
final IgniteEx crd = startGrid(crdCfg);
final IgniteEx node = startGrid(nodeCfg);
checkTopology(2);

crd.cluster().state(ClusterState.ACTIVE);

// then
assertNodesMvccEnabled(crd, node);
}

/**
* Check that MVCC is enabled for client topology when cluster state changed to ACTIVE and cache node left
*/
@Test
public void testMvccEnabledForClientTopologyAfterClusterStateChangeAndNodeLeft() throws Exception {
// given
IgniteConfiguration crdCfg = getInactiveConfiguration(clientModeIdx);
IgniteConfiguration nodeCfg = getInactiveConfiguration(cacheModeIdx);

// when
final IgniteEx crd = startGrid(crdCfg);
startGrid(nodeCfg);

checkTopology(2);
crd.cluster().state(ClusterState.ACTIVE);

stopGrid(cacheModeIdx);
checkTopology(1);

// then
assertNodesMvccEnabled(crd);
}

/**
* Check that MVCC is enabled for client topology when cluster state changed to ACTIVE and new cache node joined
*/
@Test
public void testMvccEnabledForClientTopologyAfterClusterStateChangeAndCacheNodeJoined() throws Exception {
// given
IgniteConfiguration crdCfg = getInactiveConfiguration(clientModeIdx);

// when
final IgniteEx crd = startGrid(crdCfg);
crd.cluster().state(ClusterState.ACTIVE);

final IgniteEx node = startGrid(getTestIgniteInstanceName(cacheModeIdx));
checkTopology(2);

// then
assertNodesMvccEnabled(crd, node);
}

/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
super.afterTest();
stopAllGrids();
}

/**
* Configure nodes in client mode (filtered by AttributeNodeFilter, no CacheConfiguration is set)
* or in ordinary server mode.
*/
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);

if (getTestIgniteInstanceIndex(igniteInstanceName) != clientModeIdx) {
String attrName = "has_cache";
Object attrVal = Boolean.TRUE;

CacheConfiguration ccfg = defaultCacheConfiguration()
.setNearConfiguration(null)
.setNodeFilter(new AttributeNodeFilter(attrName, attrVal))
.setAtomicityMode(TRANSACTIONAL_SNAPSHOT);

return cfg
.setCacheConfiguration(ccfg)
.setUserAttributes(F.asMap(attrName, attrVal));
}

return cfg;
}

/**
* Configuration with INACTIVE state on start
*/
private IgniteConfiguration getInactiveConfiguration(int idx) throws Exception {
return getConfiguration(getTestIgniteInstanceName(idx))
.setClusterStateOnStart(ClusterState.INACTIVE);
}

/**
* Asserts if any node enables MVCC
*/
private void assertNodesMvccDisabled(IgniteEx... nodes) {
assertNodesMvccIs(false, nodes);
}

/**
* Asserts if any node doesn't enable MVCC
*/
private void assertNodesMvccEnabled(IgniteEx... nodes) {
assertNodesMvccIs(true, nodes);
}

/**
* Asserts if any node MVCC status doesn't equal expected
*/
private void assertNodesMvccIs(boolean enabled, IgniteEx... nodes) {
for (IgniteEx n: nodes)
assertEquals("Check node: " + n.name(), enabled, n.context().coordinators().mvccEnabled());
}
}
Loading