/*
* 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.map;
import com.hazelcast.config.Config;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MapIndexConfig;
import com.hazelcast.config.MapStoreConfig;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.core.MapLoader;
import com.hazelcast.core.Member;
import com.hazelcast.query.Predicates;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
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 java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class MapIndexBackupTest extends HazelcastTestSupport {
// Issue: https://github.com/hazelcast/hazelcast/issues/6840
@Test
public void backupsShouldNotBeIndexedWhenThereIsNoMigration() {
backupsShouldNotBeIndexed(false);
}
// Issue: https://github.com/hazelcast/hazelcast/issues/6840
@Test
public void backupsShouldNotBeIndexedWhenThereIsMigration() {
backupsShouldNotBeIndexed(true);
}
private void backupsShouldNotBeIndexed(boolean migrationHappens) {
TestHazelcastInstanceFactory instanceFactory = createHazelcastInstanceFactory(2);
HazelcastInstance instance1 = createNode(instanceFactory);
if (!migrationHappens) {
createNode(instanceFactory);
}
IMap bookMap = instance1.getMap("book");
bookMap.loadAll(true);
if (migrationHappens) {
HazelcastInstance instance2 = createNode(instanceFactory);
waitAllForSafeState(instance1, instance2);
}
Set<Object> foundByPredicate = new TreeSet<Object>(
bookMap.localKeySet(
Predicates.and(
Predicates.in("author", "0", "1", "2", "3", "4", "5", "6"),
Predicates.between("year", 1990, 2000))));
Map<Member, Set<Object>> foundByPredicateByMember = new HashMap<Member, Set<Object>>();
for (Object key : foundByPredicate) {
Member owner = instance1.getPartitionService().getPartition(key).getOwner();
Set<Object> keys = foundByPredicateByMember.get(owner);
if (keys == null) {
keys = new HashSet<Object>();
foundByPredicateByMember.put(owner, keys);
}
keys.add(key);
}
assertEquals(1, foundByPredicateByMember.size());
assertTrue(foundByPredicateByMember.keySet().iterator().next().localMember());
}
private HazelcastInstance createNode(TestHazelcastInstanceFactory instanceFactory) {
Config config = getConfig();
MapConfig mapConfig = config.getMapConfig("book");
mapConfig.addMapIndexConfig(new MapIndexConfig("author", false));
mapConfig.addMapIndexConfig(new MapIndexConfig("year", true));
mapConfig.setMapStoreConfig(new MapStoreConfig().setImplementation(new BookMapLoader()));
mapConfig.setBackupCount(1);
return instanceFactory.newHazelcastInstance(config);
}
public static class Book implements Serializable {
private long id;
private String title;
private String author;
private int year;
private Book() {
}
Book(long id, String title, String author, int year) {
this.id = id;
this.title = title;
this.author = author;
this.year = year;
}
public long getId() {
return id;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getYear() {
return year;
}
}
private static class BookMapLoader implements MapLoader<Integer, Book> {
@Override
public Book load(Integer key) {
return loadAll(Collections.singleton(key)).get(key);
}
@Override
public Map<Integer, Book> loadAll(Collection<Integer> keys) {
Map<Integer, Book> map = new TreeMap<Integer, Book>();
for (int key : keys) {
map.put(key, new Book(key, String.valueOf(key), String.valueOf(key % 7), 1800 + key % 200));
}
return map;
}
@Override
public Iterable<Integer> loadAllKeys() {
List<Integer> keys = new ArrayList<Integer>(2000);
for (int i = 0; i < 2000; i++) {
keys.add(i);
}
return keys;
}
}
}