/* * Copyright 2008-2012 LinkedIn, Inc * * 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 voldemort.store.bdb; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Set; import org.apache.commons.io.FileDeleteStrategy; import org.junit.After; import org.junit.Before; import org.junit.Test; import voldemort.TestUtils; import voldemort.routing.RoutingStrategy; import voldemort.server.VoldemortConfig; import voldemort.store.PartitionListIterator; import voldemort.store.StoreDefinition; import voldemort.utils.ByteArray; import voldemort.utils.Props; import voldemort.versioning.Versioned; /** * Tests the PartitionListIterator used in pidscan based rebalancing * */ public class BdbPartitionListIteratorTest { private File bdbMasterDir; private BdbStorageConfiguration bdbStorage; private BdbStorageEngine store; private RoutingStrategy strategy; private HashMap<Integer, Set<String>> partitionEntries; @Before public void setUp() throws Exception { bdbMasterDir = TestUtils.createTempDir(); FileDeleteStrategy.FORCE.delete(bdbMasterDir); // lets use all the default values. Props props = new Props(); props.put("node.id", 1); props.put("voldemort.home", "test/common/voldemort/config"); VoldemortConfig voldemortConfig = new VoldemortConfig(props); voldemortConfig.setBdbCacheSize(10 * 1024 * 1024); voldemortConfig.setBdbOneEnvPerStore(true); voldemortConfig.setBdbDataDirectory(bdbMasterDir.toURI().getPath()); voldemortConfig.setBdbPrefixKeysWithPartitionId(true); bdbStorage = new BdbStorageConfiguration(voldemortConfig); StoreDefinition defA = TestUtils.makeStoreDefinition("storeA"); store = (BdbStorageEngine) bdbStorage.getStore(defA, (strategy = TestUtils.makeSingleNodeRoutingStrategy())); // load some data for non odd partitions, and note down how much data we // have for each partition. partitionEntries = new HashMap<Integer, Set<String>>(); int numEntries = 0; while(numEntries++ < 10000) { String key = "entry_" + numEntries; int p = strategy.getMasterPartition(key.getBytes()); // omit odd partitions if(p % 2 == 1) continue; if(!partitionEntries.containsKey(p)) partitionEntries.put(p, new HashSet<String>()); store.put(new ByteArray(key.getBytes()), new Versioned<byte[]>(key.getBytes()), null); partitionEntries.get(p).add(key); } } @After public void tearDown() throws Exception { store.close(); bdbStorage.close(); FileDeleteStrategy.FORCE.delete(bdbMasterDir); } @Test public void testEmptyPartitionList() { PartitionListIterator plistItr = new PartitionListIterator(store, new ArrayList<Integer>()); assertEquals("Empty list cannot have a next element", false, plistItr.hasNext()); try { plistItr.next(); fail("Should have thrown an exception for next()"); } catch(NoSuchElementException ne) { } finally { plistItr.close(); } } @Test public void testEmptyPartition() { PartitionListIterator plistItr = new PartitionListIterator(store, Arrays.asList(1)); assertEquals("No data loaded for odd partitions, so hasNext() should be false", false, plistItr.hasNext()); try { plistItr.next(); fail("Should have thrown an exception for next()"); } catch(NoSuchElementException ne) { } finally { plistItr.close(); } } @Test public void testSingletonPartitionList() { PartitionListIterator plistItr = new PartitionListIterator(store, Arrays.asList(4)); Set<String> pentries = new HashSet<String>(); while(plistItr.hasNext()) { pentries.add(new String(plistItr.next().getFirst().get())); } plistItr.close(); assertEquals(partitionEntries.get(4), pentries); } @Test public void testPartitionListWithEmptyPartitions() { PartitionListIterator plistItr = new PartitionListIterator(store, Arrays.asList(2, 3, 4, 5, 6)); HashMap<Integer, Set<String>> retrievedPartitionEntries = new HashMap<Integer, Set<String>>(); while(plistItr.hasNext()) { String key = new String(plistItr.next().getFirst().get()); int p = strategy.getMasterPartition(key.getBytes()); if(!retrievedPartitionEntries.containsKey(p)) retrievedPartitionEntries.put(p, new HashSet<String>()); retrievedPartitionEntries.get(p).add(key); } plistItr.close(); // should only have retrieved entries for even partitions assertEquals(3, retrievedPartitionEntries.size()); for(Integer p: Arrays.asList(2, 3, 4, 5, 6)) { if(p % 2 == 0) { assertEquals(partitionEntries.get(p), retrievedPartitionEntries.get(p)); } else { assertEquals(false, retrievedPartitionEntries.containsKey(p)); } } } }