com.navercorp.nbasearc.confmaster.server.ZooKeeperHolder.java Source code

Java tutorial

Introduction

Here is the source code for com.navercorp.nbasearc.confmaster.server.ZooKeeperHolder.java

Source

/*
 * Copyright 2015 Naver Corp.
 * 
 * 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.navercorp.nbasearc.confmaster.server;

import static org.apache.zookeeper.ZooDefs.OpCode.*;
import static com.navercorp.nbasearc.confmaster.server.lock.LockType.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.Op;
import org.apache.zookeeper.OpResult;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooKeeper.States;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.codehaus.jackson.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Repository;

import com.navercorp.nbasearc.confmaster.ConfMasterException.MgmtZooKeeperException;
import com.navercorp.nbasearc.confmaster.ThreadLocalVariableHolder;
import com.navercorp.nbasearc.confmaster.config.Config;
import com.navercorp.nbasearc.confmaster.logger.Logger;

@Repository("zooKeeperHolder")
public class ZooKeeperHolder {

    private ZooKeeper zk = null;

    private final MemoryObjectMapper mapper = new MemoryObjectMapper();

    public ZooKeeper getZooKeeper() {
        return zk;
    }

    @Value("${confmaster.zookeeper.address}")
    private String ipPort;

    @Autowired
    private Config config;

    @Autowired
    private ApplicationContext context;

    public void initialize() throws MgmtZooKeeperException {
        Logger.info("Connect to zookeeper. address: {}", getIpPort());

        final int sessionTimeout = 10000;

        try {
            WatchEventHandler sync = new WatchEventHandler(context);
            zk = new ZooKeeper(getIpPort(), sessionTimeout, sync);
            if (!sync.awaitConnection(sessionTimeout)) {
                zk.close();
                String msg = "Connect to ZooKeeper failed, connection time out. address:" + getIpPort()
                        + ", timeout: " + sessionTimeout;
                Logger.error(msg);
                throw new MgmtZooKeeperException(msg);
            }
        } catch (InterruptedException e) {
            Logger.error("Connect to ZooKeeper fail. address: {}, timeout: {}", getIpPort(), sessionTimeout, e);
            throw new MgmtZooKeeperException(e);
        } catch (IOException e) {
            Logger.error("Connect to ZooKeeper fail. address: {}, timeout: {}", getIpPort(), sessionTimeout, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public void release() {
        if (null != zk) {
            try {
                zk.close();
            } catch (InterruptedException e) {
                Logger.error("Close ZooKeeper handle error.", e);
            }
            zk = null;
        }
    }

    public <T> Op createReflectMemoryIntoZkOperation(String path, T data, final int version) {
        return Op.setData(path, mapper.writeValueAsBytes(data), version);
    }

    public <T> Stat reflectMemoryIntoZk(String path, T dataObject) throws MgmtZooKeeperException {
        try {
            final byte[] data = mapper.writeValueAsBytes(dataObject);
            ThreadLocalVariableHolder.checkPermission(path, WRITE);
            return zk.setData(path, data, -1);
        } catch (KeeperException e) {
            Logger.error("Set data from memory into ZooKeeper fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Set data from memory into ZooKeeper fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T getData(String path, Stat stat, Watcher watcher, TypeReference<T> typeRef)
            throws MgmtZooKeeperException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, READ);
            final byte[] data = zk.getData(path, watcher, stat);
            return (T) mapper.readValue(data, typeRef);
        } catch (KeeperException e) {
            Logger.error("Get data from ZooKeeper fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Get data from ZooKeeper fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public void handleResultsOfMulti(List<OpResult> results) {
        if (null == results) {
            Logger.error("Multi operations of ZooKeeper result is null.");
            return;
        }

        for (OpResult result : results) {
            switch (result.getType()) {
            case ZooDefs.OpCode.create:
                OpResult.CreateResult rc = (OpResult.CreateResult) result;
                Logger.debug("CreateResult. {}, path: {}", rc, rc.getPath());
                break;

            case ZooDefs.OpCode.delete:
                OpResult.DeleteResult rd = (OpResult.DeleteResult) result;
                Logger.debug("DeleteResult. {} ", rd);
                break;

            case ZooDefs.OpCode.setData:
                OpResult.SetDataResult rsd = (OpResult.SetDataResult) result;
                Logger.debug("DeleteResult. " + rsd.toString());
                break;

            case ZooDefs.OpCode.error:
                OpResult.ErrorResult rer = (OpResult.ErrorResult) result;
                Logger.debug("DeleteResult. {}, error: {}", rer, rer.getErr());
                break;
            }
            Logger.debug(result.toString());
        }
    }

    String create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
            throws MgmtZooKeeperException, NodeExistsException {
        String createdPath = null;
        try {
            ThreadLocalVariableHolder.checkPermission(path, WRITE);
            createdPath = zk.create(path, data, acl, createMode);
        } catch (KeeperException.NodeExistsException e) {
            // Do not logging this exception. error handling depends on a caller.
            throw e;
        } catch (KeeperException e) {
            Logger.error("Create znode fail. path: {}, data: {}", path, data, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Create znode fail. path: {}, data: {}", path, data, e);
            throw new MgmtZooKeeperException(e);
        }

        return createdPath;
    }

    public String createPersistentZNode(String path, byte data[])
            throws MgmtZooKeeperException, NodeExistsException {
        return this.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }

    public String createPersistentZNode(String path) throws MgmtZooKeeperException, NodeExistsException {
        final byte[] ZERO_BYTE = new byte[1];
        return this.create(path, ZERO_BYTE, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }

    public String createEphemeralZNode(String path, byte data[])
            throws MgmtZooKeeperException, NodeExistsException {
        return this.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    }

    public String createEphemeralZNode(String path) throws MgmtZooKeeperException, NodeExistsException {
        final byte[] ZERO_BYTE = new byte[1];
        return this.create(path, ZERO_BYTE, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    }

    public void registerChangedEventWatcher(final String path, final Watcher watcher)
            throws MgmtZooKeeperException {
        try {
            zk.exists(path, watcher);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Register changed event watcher fail. path: {}", path, e);
            // ignore
        } catch (KeeperException e) {
            Logger.error("Register changed event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Register changed event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public void registerChangedEventWatcher(final String path) throws MgmtZooKeeperException {
        try {
            zk.exists(path, true);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Register changed event watcher fail. path: {}", path, e);
            // ignore
        } catch (KeeperException e) {
            Logger.error("Register changed event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Register changed event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public void registerChildEventWatcher(final String path) throws MgmtZooKeeperException {
        try {
            zk.getChildren(path, true);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Register child event watcher fail. path: {}", path, e);
            // ignore
        } catch (KeeperException e) {
            Logger.error("Register child event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Register child event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public void registerChildEventWatcher(final String path, final Watcher watcher) throws MgmtZooKeeperException {
        try {
            zk.getChildren(path, watcher);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Register child event watcher fail. path: {}", path, e);
            // ignore
        } catch (KeeperException e) {
            Logger.error("Register child event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Register child event watcher fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public Stat setData(final String path, final byte[] data, final int version) throws MgmtZooKeeperException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, WRITE);
            return zk.setData(path, data, version);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Set znode fail. path: {}, data: {}", path, data, e);
            throw new MgmtZooKeeperException(e);
        } catch (KeeperException e) {
            Logger.error("Set znode fail. path: {}, data: {}", path, data, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Set znode fail. path: {}, data: {}", path, data, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public byte[] getData(final String path, Stat stat, Watcher watcher)
            throws MgmtZooKeeperException, NoNodeException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, READ);
            return zk.getData(path, watcher, stat);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Get data fail. path: {}", path, e);
            throw e;
        } catch (KeeperException e) {
            Logger.error("Get data fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Get data fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public byte[] getData(final String path, Stat stat, boolean watch)
            throws MgmtZooKeeperException, NoNodeException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, READ);
            return zk.getData(path, watch, stat);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Get data fail. path: {}", path, e);
            throw e;
        } catch (KeeperException e) {
            Logger.error("Get data fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Get data fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public byte[] getData(final String path, Stat stat) throws MgmtZooKeeperException, NoNodeException {
        return getData(path, stat, null);
    }

    public void deleteZNode(final String path, final int version) throws MgmtZooKeeperException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, WRITE);
            zk.delete(path, version);
        } catch (KeeperException.NoNodeException e) {
            Logger.warn("Delete znode fail. path: {}", path, e);
            // ignore
        } catch (KeeperException.NotEmptyException e) {
            Logger.error("Delete znode fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (KeeperException e) {
            Logger.error("Delete znode fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Delete znode fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public void deleteChildren(String path) throws MgmtZooKeeperException {
        List<String> children = getChildren(path);

        for (String childName : children) {
            StringBuilder childPath = new StringBuilder(path);
            childPath.append("/").append(childName);
            deleteZNode(childPath.toString(), -1);
        }
    }

    public void deleteAllZNodeRecursive() throws MgmtZooKeeperException {
        List<String> tree = listSubTreeBFS("/");
        for (int i = tree.size() - 1; i >= 0; --i) {
            deleteZNode(tree.get(i), -1);
        }
    }

    public void deleteZNodeRecursive(final String path) throws MgmtZooKeeperException {
        List<String> tree = listSubTreeBFS(path);
        for (int i = tree.size() - 1; i >= 0; --i) {
            deleteZNode(tree.get(i), -1);
        }
    }

    private List<String> listSubTreeBFS(final String pathRoot) throws MgmtZooKeeperException {
        if (pathRoot.equals("/zookeeper")) {
            return new ArrayList<String>();
        }

        Deque<String> queue = new LinkedList<String>();
        List<String> tree = new ArrayList<String>();
        queue.add(pathRoot);
        tree.add(pathRoot);
        while (true) {
            String node = queue.pollFirst();
            if (node == null) {
                break;
            }

            List<String> children = getChildren(node);
            for (final String child : children) {
                final String childPath = (node.equals("/") ? node : node + "/") + child;
                if (childPath.equals("/zookeeper")) {
                    continue;
                }
                queue.add(childPath);
                tree.add(childPath);
            }
        }

        if (!tree.isEmpty() && tree.get(0).equals("/")) {
            tree.remove(0);
        }

        return tree;
    }

    public List<String> getChildren(final String path) throws MgmtZooKeeperException {
        return getChildren(path, null);
    }

    public List<String> getChildren(final String path, final boolean watch) throws MgmtZooKeeperException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, READ);
            return zk.getChildren(path, watch);
        } catch (KeeperException e) {
            Logger.error("Get children of znode fail. path: {} ", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Get children of znode fail. path: {} ", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public List<String> getChildren(final String path, final Watcher watcher) throws MgmtZooKeeperException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, READ);
            return zk.getChildren(path, watcher);
        } catch (KeeperException e) {
            Logger.error("Get children of znode fail. path: {} ", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Get children of znode fail. path: {} ", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public int getNumberOfChildren(final String path) throws MgmtZooKeeperException {
        List<String> children = getChildren(path, null);
        return children.size();
    }

    public boolean isExists(final String path) throws MgmtZooKeeperException {
        try {
            ThreadLocalVariableHolder.checkPermission(path, READ);
            return (zk.exists(path, true) != null);
        } catch (KeeperException e) {
            Logger.error("Check znode fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Check znode fail. path: {}", path, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public List<OpResult> multi(Iterable<Op> ops) throws MgmtZooKeeperException {
        try {
            for (Op op : ops) {
                if (op.getType() == create || op.getType() == delete || op.getType() == setData) {
                    ThreadLocalVariableHolder.checkPermission(op.getPath(), WRITE);
                } else if (op.getType() == getData || op.getType() == exists || op.getType() == getChildren) {
                    ThreadLocalVariableHolder.checkPermission(op.getPath(), READ);
                }
            }
            return zk.multi(ops);
        } catch (KeeperException e) {
            Logger.error("Multi operation fail. {}, {}", e.getPath(), ops, e);
            throw new MgmtZooKeeperException(e);
        } catch (InterruptedException e) {
            Logger.error("Multi operation fail. {}", ops, e);
            throw new MgmtZooKeeperException(e);
        }
    }

    public String getIpPort() {
        return ipPort;
    }

    public void setIpPort(String ipPort) {
        this.ipPort = ipPort;
    }

    public States getStates() {
        return zk.getState();
    }

}