com.talis.platform.sequencing.zookeeper.ZooKeeperProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.talis.platform.sequencing.zookeeper.ZooKeeperProvider.java

Source

/*
 *    Copyright 2010 Talis Systems Ltd
 * 
 *    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 com.talis.platform.sequencing.zookeeper;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Provider;

public class ZooKeeperProvider implements Provider<ZooKeeper>, Watcher {

    static final Logger LOG = LoggerFactory.getLogger(ZooKeeperProvider.class);

    public static final String DEFAULT_SERVER_LIST_LOCATION = "/zkservers";
    public static final String SERVER_LIST_LOCATION_PROPERTY = "com.talis.platform.sequencing.zookeeper.servers";

    public static final int DEFAULT_SESSION_TIMEOUT = 10 * 1000;
    public static final String SESSION_TIMEOUT_PROPERTY = "com.talis.platform.sequencing.zookeeper.session.timeout";

    public static final int DEFAULT_CONNECTION_TIMEOUT = 10 * 1000;
    public static final String CONNECTION_TIMEOUT_PROPERTY = "com.talis.platform.sequencing.zookeeper.connection.timeout";

    private String ensembleList;
    private volatile ZooKeeper zookeeper;
    private boolean connected = false;

    @Override
    public void process(WatchedEvent event) {
        switch (event.getType()) {
        case None:
            processNoneTypeEvent(event.getState());
        default:
            // do nothing
        }
    }

    private void processNoneTypeEvent(Event.KeeperState state) {
        switch (state) {
        case SyncConnected:
            LOG.info("Received connected event, notifying waiting thread " + "(there should only be one)");
            synchronized (this) {
                connected = true;
                notify();
            }
            break;
        case Expired:
            LOG.info("Session expired event, disposing of client instance");
            reset();
            break;
        default:
            // do nothing
        }
    }

    @Override
    public ZooKeeper get() {
        if (null == zookeeper) {
            LOG.info("No ZooKeeper instance cached");
            synchronized (this) {
                if (null == zookeeper) {
                    try {
                        zookeeper = newKeeperInstance();
                        LOG.info("Waiting for connection to zookeeper server");
                        waitForConnection();
                    } catch (IOException e) {
                        LOG.error("Unable to create ZooKeeper instance", e);
                        throw new ZooKeeperInitialisationException(
                                "Unable to provide client for sequence generation", e);
                    }
                }
            }
        } else {
            LOG.info("Returning cached ZooKeeper instance");
        }
        return zookeeper;
    }

    private void waitForConnection() throws ZooKeeperInitialisationException {
        long connectionTimeout = Long.getLong(CONNECTION_TIMEOUT_PROPERTY, DEFAULT_CONNECTION_TIMEOUT);
        synchronized (this) {
            try {
                wait(connectionTimeout);
            } catch (InterruptedException e) {
                LOG.info("Interrupted while waiting for connection");
            }

            if (!connected) {
                zookeeper = null;
                throw new ZooKeeperInitialisationException("Connection timed out or interrupted");
            }
        }
    }

    public String getEnsembleList() throws IOException {
        if (null == ensembleList) {
            ensembleList = readEnsembleList();
        }
        return ensembleList;
    }

    public synchronized void reset() {
        ensembleList = null;
        zookeeper = null;
    }

    private String readEnsembleList() throws IOException {
        InputStream ensembleListStream = this.getClass().getResourceAsStream(DEFAULT_SERVER_LIST_LOCATION);
        String theFilename = System.getProperty(SERVER_LIST_LOCATION_PROPERTY);
        if (null == theFilename) {
            if (LOG.isInfoEnabled()) {
                LOG.info("No server list specified in system " + "property using default");
            }
        } else {
            if (LOG.isInfoEnabled()) {
                LOG.info(String.format("Initialising server list from file %s", theFilename));
            }
            ensembleListStream = FileUtils.openInputStream(new File(theFilename));
        }

        String list = ((String) IOUtils.readLines(ensembleListStream).get(0)).trim();
        if (LOG.isInfoEnabled()) {
            LOG.info(String.format("Read ensemble list => %s", list));
        }
        return list;
    }

    private ZooKeeper newKeeperInstance() throws IOException {
        int sessionTimeout = Integer.getInteger(SESSION_TIMEOUT_PROPERTY, DEFAULT_SESSION_TIMEOUT);

        if (LOG.isInfoEnabled()) {
            LOG.info(String.format("Creating new ZooKeeper instance. Servers: %s | Session Timeout: %s",
                    getEnsembleList(), sessionTimeout));
        }
        connected = false;
        ZooKeeper keeper = new ZooKeeper(getEnsembleList(), sessionTimeout, this);

        if (LOG.isInfoEnabled()) {
            LOG.info("Created ZooKeeper instance");
        }
        return keeper;
    }
}