/* * Copyright 2008-2009 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.scheduled; import static voldemort.TestUtils.bytesEqual; import java.util.Arrays; import java.util.Date; import java.util.List; import junit.framework.TestCase; import voldemort.ServerTestUtils; import voldemort.TestUtils; import voldemort.cluster.Cluster; import voldemort.cluster.Node; import voldemort.cluster.failuredetector.NoopFailureDetector; import voldemort.server.StoreRepository; import voldemort.server.VoldemortConfig; import voldemort.server.scheduler.slop.BlockingSlopPusherJob; import voldemort.server.storage.ScanPermitWrapper; import voldemort.store.FailingStore; import voldemort.store.memory.InMemoryStorageEngine; import voldemort.store.metadata.MetadataStore; import voldemort.store.slop.Slop; import voldemort.store.slop.Slop.Operation; import voldemort.store.slop.SlopStorageEngine; import voldemort.utils.ByteArray; import voldemort.utils.Props; import voldemort.versioning.Versioned; import com.google.common.collect.Lists; public class BlockingSlopPusherTest extends TestCase { private final static String STORE_NAME = "test0"; private BlockingSlopPusherJob pusher; private StoreRepository repo; @Override protected void setUp() throws Exception { Cluster cluster = makeCluster(3); repo = new StoreRepository(); repo.setSlopStore(new SlopStorageEngine(new InMemoryStorageEngine<ByteArray, byte[], byte[]>("slop"), cluster)); repo.addNodeStore(0, new InMemoryStorageEngine<ByteArray, byte[], byte[]>(STORE_NAME)); repo.addNodeStore(1, new InMemoryStorageEngine<ByteArray, byte[], byte[]>(STORE_NAME)); repo.addNodeStore(2, new FailingStore<ByteArray, byte[], byte[]>(STORE_NAME)); MetadataStore metadataStore = ServerTestUtils.createMetadataStore(cluster, ServerTestUtils.getStoreDefs(1)); Props props = new Props(); props.put("node.id", 0); props.put("voldemort.home", "/"); pusher = new BlockingSlopPusherJob(repo, metadataStore, new NoopFailureDetector(), new VoldemortConfig(props), new ScanPermitWrapper(1)); } private Cluster makeCluster(int numNodes) { List<Node> nodes = Lists.newArrayList(); for(int i = 0; i < numNodes; i++) nodes.add(new Node(i, Integer.toString(i), 1234, 1235, 1236, Arrays.asList(i))); return new Cluster("cluster", nodes); } private Versioned<Slop> randomSlop(String name, int nodeId) { return Versioned.value(new Slop(name, Operation.PUT, TestUtils.randomBytes(10), TestUtils.randomBytes(10), nodeId, new Date())); } private void pushSlop(Versioned<Slop>... slops) { // put all the slop in the slop store for(Versioned<Slop> s: slops) repo.getSlopStore().asSlopStore().put(s.getValue().makeKey(), s, null); // run the pusher pusher.run(); } private void checkPush(Versioned<Slop>[] delivered, Versioned<Slop>[] undelivered) { // now all the delivered slop should be gone and the various stores // should have // those items for(Versioned<Slop> vs: delivered) { // check that all the slops are in the stores // and no new slops have appeared // and the SloppyStore is now empty Slop slop = vs.getValue(); assertEquals("Slop remains.", 0, repo.getSlopStore().get(slop.makeKey(), null).size()); assertTrue(bytesEqual(slop.getValue(), repo.getNodeStore(STORE_NAME, slop.getNodeId()) .get(slop.getKey(), null) .get(0) .getValue())); } // check that all undelivered slop is undelivered for(Versioned<Slop> vs: undelivered) { Slop slop = vs.getValue(); assertEquals("Slop is gone!", 1, repo.getSlopStore().get(slop.makeKey(), null).size()); } } public void testPushNoSlop() { pusher.run(); } @SuppressWarnings("unchecked") public void testPushSomeSlop() { Versioned<Slop>[] values = new Versioned[] { randomSlop(STORE_NAME, 0), randomSlop(STORE_NAME, 1), randomSlop(STORE_NAME, 0) }; pushSlop(values); checkPush(values, new Versioned[] {}); } @SuppressWarnings("unchecked") public void testSlopWithFailingStore() { Versioned<Slop> good1 = randomSlop(STORE_NAME, 0); Versioned<Slop> good2 = randomSlop(STORE_NAME, 1); Versioned<Slop> bad = randomSlop(STORE_NAME, 2); pushSlop(good1, bad, good2); checkPush(new Versioned[] { good1, good2 }, new Versioned[] { bad }); } }