/* This file is part of VoltDB.
* Copyright (C) 2008-2014 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.voltdb.iv2;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import org.apache.zookeeper_voltpatches.ZooDefs.Ids;
import org.apache.zookeeper_voltpatches.CreateMode;
import org.apache.zookeeper_voltpatches.ZooKeeper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.voltcore.zk.ZKTestBase;
import com.google_voltpatches.common.collect.ImmutableMap;
public class TestLeaderCache extends ZKTestBase {
private final int NUM_AGREEMENT_SITES = 8;
public static class TestCallback extends LeaderCache.Callback
{
volatile ImmutableMap<Integer, Long> m_cache = null;
public void run(ImmutableMap<Integer, Long> cache)
{
m_cache = cache;
}
}
@Before
public void setUp() throws Exception
{
setUpZK(NUM_AGREEMENT_SITES);
}
@After
public void tearDown() throws Exception
{
tearDownZK();
}
void configure(String root, ZooKeeper zk) throws Exception
{
Long aa = 12345678L;
Long bb = 87654321L;
Long cc = 11223344L;
zk.create(root, new byte[]{}, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(root + "/0", aa.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(root + "/1", bb.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(root + "/2", cc.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
@Test
public void testInitialCache() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache01", zk);
LeaderCache dut = new LeaderCache(zk, "/cache01");
dut.start(true);
Map<Integer, Long> cache = dut.pointInTimeCache();
assertEquals("3 items cached.", 3, cache.size());
assertEquals(12345678L, dut.get(0).longValue());
assertEquals(87654321L, dut.get(1).longValue());
assertEquals(11223344L, dut.get(2).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testInitialCacheWithCallback() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache01", zk);
TestCallback cb = new TestCallback();
LeaderCache dut = new LeaderCache(zk, "/cache01", cb);
dut.start(true);
assertEquals("3 items cached.", 3, cb.m_cache.size());
assertEquals(12345678, cb.m_cache.get(0).longValue());
assertEquals(87654321, cb.m_cache.get(1).longValue());
assertEquals(11223344, cb.m_cache.get(2).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testModifyChild() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache03", zk);
LeaderCache dut = new LeaderCache(zk, "/cache03");
dut.start(true);
Map<Integer, Long> cache = dut.pointInTimeCache();
assertEquals("3 items cached.", 3, cache.size());
assertEquals(12345678, dut.get(0).longValue());
zk.setData("/cache03/0", Long.toString(23456789).getBytes(), -1);
while(true) {
if (dut.get(0) == 23456789) {
break;
}
}
assertEquals("3 items cached.", 3, cache.size());
assertEquals(23456789L, dut.get(0).longValue());
assertEquals(87654321L, dut.get(1).longValue());
assertEquals(11223344L, dut.get(2).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testModifyChildWithCallback() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache03", zk);
TestCallback cb = new TestCallback();
LeaderCache dut = new LeaderCache(zk, "/cache03", cb);
dut.start(true);
Map<Integer, Long> cache = cb.m_cache;
assertEquals("3 items cached.", 3, cache.size());
assertEquals(12345678, cache.get(0).longValue());
dut.put(0, 23456789);
while(true) {
cache = cb.m_cache;
if (cache.get(0) == 23456789) {
break;
}
}
cache = cb.m_cache;
assertEquals("3 items cached.", 3, cache.size());
assertEquals(23456789, cache.get(0).longValue());
assertEquals(87654321, cache.get(1).longValue());
assertEquals(11223344, cache.get(2).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testDeleteChild() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache02", zk);
LeaderCache dut = new LeaderCache(zk, "/cache02");
dut.start(true);
Map<Integer, Long> cache = dut.pointInTimeCache();
assertEquals("3 items cached.", 3, cache.size());
zk.delete("/cache02/1", -1);
while(true) {
cache = dut.pointInTimeCache();
if (cache.size() == 3) {
Thread.sleep(1);
}
else {
break;
}
}
assertEquals("Item removed", 2, cache.size());
assertEquals(null, cache.get(1));
assertEquals(12345678, cache.get(0).longValue());
assertEquals(11223344, cache.get(2).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testDeleteChildWithCallback() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache02", zk);
TestCallback cb = new TestCallback();
LeaderCache dut = new LeaderCache(zk, "/cache02", cb);
dut.start(true);
Map<Integer, Long> cache = cb.m_cache;
assertEquals("3 items cached.", 3, cache.size());
zk.delete("/cache02/1", -1);
while(true) {
cache = cb.m_cache;
if (cache.size() == 3) {
Thread.sleep(1);
}
else {
break;
}
}
assertEquals("Item removed", 2, cache.size());
assertEquals(null, cache.get(1));
assertEquals(12345678, cache.get(0).longValue());
assertEquals(11223344, cache.get(2).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testAddChildWithPut() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache04", zk);
LeaderCache dut = new LeaderCache(zk, "/cache04");
dut.start(true);
Map<Integer, Long> cache = dut.pointInTimeCache();
dut.put(3, 88776655);
while(true) {
cache = dut.pointInTimeCache();
if (cache.size() == 3) {
Thread.sleep(1);
}
else {
break;
}
}
assertEquals("Item added", 4, cache.size());
assertEquals(12345678, cache.get(0).longValue());
assertEquals(87654321, cache.get(1).longValue());
assertEquals(11223344, cache.get(2).longValue());
assertEquals(88776655, cache.get(3).longValue());
// modify the new child and make sure it has a watch set.
dut.put(3, 99887766);
while(true) {
cache = dut.pointInTimeCache();
if (cache.get(3) == 99887766) {
break;
}
}
assertEquals("Items accounted for.", 4, cache.size());
assertEquals(99887766L, cache.get(3).longValue());
dut.shutdown();
zk.close();
}
@Test
public void testAddChildWithPutWithCallback() throws Exception
{
ZooKeeper zk = getClient(0);
configure("/cache04", zk);
TestCallback cb = new TestCallback();
LeaderCache dut = new LeaderCache(zk, "/cache04", cb);
dut.start(true);
Map<Integer, Long> cache = cb.m_cache;
dut.put(3, 88776655);
while(true) {
cache = cb.m_cache;
if (cache.size() == 3) {
Thread.sleep(1);
}
else {
break;
}
}
assertEquals("Item added", 4, cache.size());
assertEquals(12345678, cache.get(0).longValue());
assertEquals(87654321, cache.get(1).longValue());
assertEquals(11223344, cache.get(2).longValue());
assertEquals(88776655, cache.get(3).longValue());
// modify the new child and make sure it has a watch set.
dut.put(3, 99887766);
while(true) {
cache = cb.m_cache;
if (cache.get(3) == 99887766) {
break;
}
}
assertEquals("Items accounted for.", 4, cache.size());
assertEquals(99887766, cache.get(3).longValue());
dut.shutdown();
zk.close();
}
}