/*
* 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 });
}
}