com.smartitengineering.cms.spi.lock.impl.distributed.AppTest.java Source code

Java tutorial

Introduction

Here is the source code for com.smartitengineering.cms.spi.lock.impl.distributed.AppTest.java

Source

/*
 *
 * This is a simple Content Management System (CMS)
 * Copyright (C) 2011 Imran M Yousuf (imyousuf@smartitengineering.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.smartitengineering.cms.spi.lock.impl.distributed;

import com.smartitengineering.cms.api.factory.write.Lock;
import com.smartitengineering.cms.spi.lock.Key;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.NIOServerCnxn;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class AppTest {

    public static final String ROOT_NODE = "/smart-cms";
    private static NIOServerCnxn.Factory standaloneServerFactory;
    private static final int CLIENT_PORT = 3882;
    private static final int CONNECTION_TIMEOUT = 30000;
    private final String connectString = "localhost:" + CLIENT_PORT;
    private final Key key = new Key() {

        public String getKeyStringRep() {
            return "random-key-1";
        }
    };

    @BeforeClass
    public static void startZooKeeperServer() {
        try {
            File snapDir = new File("./target/zk/");
            snapDir.mkdirs();
            ZooKeeperServer server = new ZooKeeperServer(snapDir, snapDir, 2000);
            standaloneServerFactory = new NIOServerCnxn.Factory(new InetSocketAddress(CLIENT_PORT));
            standaloneServerFactory.startup(server);
            if (!waitForServerUp(CLIENT_PORT, CONNECTION_TIMEOUT)) {
                throw new IOException("Waiting for startup of standalone server");
            }
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    @AfterClass
    public static void shutdownZooKeeperServer() {
        standaloneServerFactory.shutdown();
        if (!waitForServerDown(CLIENT_PORT, CONNECTION_TIMEOUT)) {
            throw new IllegalStateException("Waiting for shutdown of standalone server");
        }
    }

    // XXX: From o.a.zk.t.ClientBase
    public static boolean waitForServerUp(int port, long timeout) {
        long start = System.currentTimeMillis();
        while (true) {
            try {
                Socket sock = new Socket("localhost", port);
                BufferedReader reader = null;
                try {
                    OutputStream outstream = sock.getOutputStream();
                    outstream.write("stat".getBytes());
                    outstream.flush();

                    Reader isr = new InputStreamReader(sock.getInputStream());
                    reader = new BufferedReader(isr);
                    String line = reader.readLine();
                    if (line != null && line.startsWith("Zookeeper version:")) {
                        return true;
                    }
                } finally {
                    sock.close();
                    if (reader != null) {
                        reader.close();
                    }
                }
            } catch (IOException e) {
                // ignore as this is expected
            }

            if (System.currentTimeMillis() > start + timeout) {
                break;
            }
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                // ignore
            }
        }
        return false;
    }

    // XXX: From o.a.zk.t.ClientBase
    public static boolean waitForServerDown(int port, long timeout) {
        long start = System.currentTimeMillis();
        while (true) {
            try {
                Socket sock = new Socket("localhost", CLIENT_PORT);
                try {
                    OutputStream outstream = sock.getOutputStream();
                    outstream.write("stat".getBytes());
                    outstream.flush();
                } finally {
                    sock.close();
                }
            } catch (IOException e) {
                return true;
            }

            if (System.currentTimeMillis() > start + timeout) {
                break;
            }
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                // ignore
            }
        }
        return false;
    }

    @Test
    public void testInitialization() throws Exception {

        ZooKeeper zooKeeper = new ZooKeeper(connectString, CONNECTION_TIMEOUT, new Watcher() {

            public void process(WatchedEvent event) {
            }
        });
        Stat stat = zooKeeper.exists(ROOT_NODE, false);
        Assert.assertNull(stat);
        final LocalLockRegistrarImpl localLockRegistrarImpl = new LocalLockRegistrarImpl();
        localLockRegistrarImpl.initTimeoutChecking();
        ZooKeeperLockHandler handler = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl);
        stat = zooKeeper.exists(ROOT_NODE, false);
        Assert.assertNotNull(stat);
    }

    @Test
    public void testSimpleLocking() throws Exception {
        final LocalLockRegistrarImpl localLockRegistrarImpl1 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl1.initTimeoutChecking();
        ZooKeeperLockHandler handler1 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl1);
        Lock lock1 = handler1.getLock(key);
        Assert.assertNotNull(lock1);
        Assert.assertTrue(lock1.tryLock());
        Assert.assertTrue(lock1.isLockOwned());
        lock1.unlock();
        Assert.assertFalse(lock1.isLockOwned());
    }

    @Test
    public void testRepeatativeLocking() throws Exception {
        final LocalLockRegistrarImpl localLockRegistrarImpl1 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl1.initTimeoutChecking();
        ZooKeeperLockHandler handler1 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl1);
        Lock lock2 = handler1.getLock(key);
        Assert.assertNotNull(lock2);
        Assert.assertTrue(lock2.tryLock());
        Assert.assertTrue(lock2.tryLock());
        lock2.unlock();
    }

    @Test
    public void testSignleJVMLocking() throws Exception {
        final LocalLockRegistrarImpl localLockRegistrarImpl1 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl1.initTimeoutChecking();
        ZooKeeperLockHandler handler1 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl1);
        Lock lock1 = handler1.getLock(key);
        Lock lock2 = handler1.getLock(key);
        Assert.assertNotNull(lock1);
        Assert.assertNotNull(lock2);
        Assert.assertTrue(lock1.tryLock());
        Assert.assertTrue(lock1.isLockOwned());
        Assert.assertFalse(lock2.tryLock());
        lock1.unlock();
        Assert.assertFalse(lock1.isLockOwned());
        Assert.assertTrue(lock2.tryLock());
        Assert.assertTrue(lock2.tryLock());
        lock2.unlock();
        Assert.assertFalse(lock2.isLockOwned());
    }

    @Test
    public void testMultiJVMLocking() throws Exception {
        final LocalLockRegistrarImpl localLockRegistrarImpl1 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl1.initTimeoutChecking();
        ZooKeeperLockHandler handler1 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl1);
        Lock lock1 = handler1.getLock(key);
        //Simulate multi-jvm
        final LocalLockRegistrarImpl localLockRegistrarImpl2 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl2.initTimeoutChecking();
        ZooKeeperLockHandler handler2 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node2",
                CONNECTION_TIMEOUT, localLockRegistrarImpl2);
        Lock lock3 = handler2.getLock(key);
        Assert.assertTrue(lock1.tryLock());
        Assert.assertFalse(lock3.tryLock());
        Assert.assertFalse(lock3.isLockOwned());
        lock1.unlock();
        Assert.assertFalse(lock1.isLockOwned());
        Assert.assertTrue(lock3.tryLock());
        lock3.unlock();
        Assert.assertFalse(lock3.isLockOwned());
    }

    @Test
    public void testSignleJVMWaitLocking() throws Exception {
        final LocalLockRegistrarImpl localLockRegistrarImpl1 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl1.initTimeoutChecking();
        ZooKeeperLockHandler handler1 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl1);
        Lock lock1 = handler1.getLock(key);
        final Lock lock2 = handler1.getLock(key);
        Assert.assertNotNull(lock1);
        Assert.assertNotNull(lock2);
        Assert.assertTrue(lock1.tryLock());
        Assert.assertTrue(lock1.isLockOwned());
        new Thread(new Runnable() {

            public void run() {
                lock2.lock();
            }
        }).start();
        Assert.assertFalse(lock2.isLockOwned());
        Thread.sleep(1000);
        lock1.unlock();
        Assert.assertFalse(lock1.isLockOwned());
        Thread.sleep(100);
        Assert.assertTrue(lock2.isLockOwned());
        lock2.unlock();
        Assert.assertTrue(lock1.tryLock());
        new Thread(new Runnable() {

            public void run() {
                try {
                    Assert.assertFalse(lock2.tryLock(300, TimeUnit.MILLISECONDS));
                } catch (Exception ex) {
                    Assert.fail("Should not arise!");
                }
            }
        }).start();
        Assert.assertFalse(lock2.isLockOwned());
        Thread.sleep(350);
        lock1.unlock();
        Assert.assertTrue(lock1.tryLock());
        new Thread(new Runnable() {

            public void run() {
                try {
                    Assert.assertTrue(lock2.tryLock(300, TimeUnit.MILLISECONDS));
                    lock2.unlock();
                } catch (Exception ex) {
                    Assert.fail("Should not arise!");
                }
            }
        }).start();
        Assert.assertFalse(lock2.isLockOwned());
        Thread.sleep(150);
        lock1.unlock();
    }

    @Test
    public void testMultiJVMWaitLocking() throws Exception {
        final LocalLockRegistrarImpl localLockRegistrarImpl1 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl1.initTimeoutChecking();
        ZooKeeperLockHandler handler1 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node1",
                CONNECTION_TIMEOUT, localLockRegistrarImpl1);
        Lock lock1 = handler1.getLock(key);
        //Simulate multi-jvm
        final LocalLockRegistrarImpl localLockRegistrarImpl2 = new LocalLockRegistrarImpl();
        localLockRegistrarImpl2.initTimeoutChecking();
        ZooKeeperLockHandler handler2 = new ZooKeeperLockHandler(connectString, ROOT_NODE, "node2",
                CONNECTION_TIMEOUT, localLockRegistrarImpl2);
        final Lock lock3 = handler2.getLock(key);
        Assert.assertTrue(lock1.tryLock());
        new Thread(new Runnable() {

            public void run() {
                lock3.lock();
            }
        }).start();
        Assert.assertFalse(lock3.isLockOwned());
        Thread.sleep(1000);
        lock1.unlock();
        Assert.assertFalse(lock1.isLockOwned());
        Thread.sleep(100);
        Assert.assertTrue(lock3.isLockOwned());
        lock3.unlock();
        Assert.assertTrue(lock1.tryLock());
        new Thread(new Runnable() {

            public void run() {
                try {
                    Assert.assertFalse(lock3.tryLock(300, TimeUnit.MILLISECONDS));
                } catch (Exception ex) {
                    Assert.fail("Should not arise!");
                }
            }
        }).start();
        Assert.assertFalse(lock3.isLockOwned());
        Thread.sleep(350);
        lock1.unlock();
        Assert.assertTrue(lock1.tryLock());
        new Thread(new Runnable() {

            public void run() {
                try {
                    Assert.assertTrue(lock3.tryLock(300, TimeUnit.MILLISECONDS));
                    lock3.unlock();
                } catch (Exception ex) {
                    Assert.fail("Should not arise!");
                }
            }
        }).start();
        Assert.assertFalse(lock3.isLockOwned());
        Thread.sleep(150);
        lock1.unlock();
    }
}