Package com.taobao.metamorphosis.utils

Source Code of com.taobao.metamorphosis.utils.MetaZookeeper$ZKGroupTopicDirs

/*
* (C) 2007-2012 Alibaba Group Holding Limited.
*
* 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.
* Authors:
*   wuhua <wq163@163.com> , boyan <killme2008@gmail.com>
*/
package com.taobao.metamorphosis.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.I0Itec.zkclient.ZkClient;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.taobao.metamorphosis.cluster.Broker;
import com.taobao.metamorphosis.cluster.Cluster;
import com.taobao.metamorphosis.cluster.Partition;
import com.taobao.metamorphosis.cluster.json.TopicBroker;


/**
* Meta��zookeeper�����ĸ�����
*
* @author boyan(boyan@taobao.com)
* @date 2011-12-15
*
*/
public class MetaZookeeper {

    static{
        if(Thread.getDefaultUncaughtExceptionHandler()==null){
            Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    logger.warn("Thread terminated with exception: "+ t.getName(),e);
                }
            });
        }
    }

    private volatile ZkClient zkClient;

    private static Log logger = LogFactory.getLog(MetaZookeeper.class);
    public final String metaRoot;
    public final String consumersPath;
    public final String brokerIdsPath;
    @Deprecated
    public final String brokerTopicsPath;
    // added by dennis,sinace 1.4.3
    public final String brokerTopicsPubPath;
    public final String brokerTopicsSubPath;


    public ZkClient getZkClient() {
        return this.zkClient;
    }


    public void setZkClient(final ZkClient zkClient) {
        this.zkClient = zkClient;
    }


    public MetaZookeeper(final ZkClient zkClient, final String root) {
        this.zkClient = zkClient;
        this.metaRoot = this.normalize(root);
        this.consumersPath = this.metaRoot + "/consumers";
        this.brokerIdsPath = this.metaRoot + "/brokers/ids";
        this.brokerTopicsPath = this.metaRoot + "/brokers/topics";
        this.brokerTopicsPubPath = this.metaRoot + "/brokers/topics-pub";
        this.brokerTopicsSubPath = this.metaRoot + "/brokers/topics-sub";
    }


    private String normalize(final String root) {
        if (root.startsWith("/")) {
            return this.removeLastSlash(root);
        }
        else {
            return "/" + this.removeLastSlash(root);
        }
    }


    private String removeLastSlash(final String root) {
        if (root.endsWith("/")) {
            return root.substring(0, root.lastIndexOf("/"));
        }
        else {
            return root;
        }
    }

    public class ZKGroupDirs {
        public ZKGroupDirs(final String group) {
            this.consumerGroupDir = this.consumerDir + "/" + group;
            this.consumerRegistryDir = this.consumerGroupDir + "/ids";
        }

        public String consumerDir = MetaZookeeper.this.consumersPath;
        public String consumerGroupDir;
        public String consumerRegistryDir;
    }

    public class ZKGroupTopicDirs extends ZKGroupDirs {
        public ZKGroupTopicDirs(final String topic, final String group) {
            super(group);
            this.consumerOffsetDir = this.consumerGroupDir + "/offsets/" + topic;
            this.consumerOwnerDir = this.consumerGroupDir + "/owners/" + topic;
        }

        public String consumerOffsetDir;
        public String consumerOwnerDir;
    }


    /**
     * ����broker��Ⱥ,����slave��master
     *
     * @param zkClient
     * @return
     */
    public Cluster getCluster() {
        final Cluster cluster = new Cluster();
        final List<String> nodes = ZkUtils.getChildren(this.zkClient, this.brokerIdsPath);
        for (final String node : nodes) {
            // String brokerZKString = readData(zkClient, brokerIdsPath + "/" +
            // node);
            final int brokerId = Integer.parseInt(node);
            final Set<Broker> brokers = this.getBrokersById(brokerId);
            if (brokers != null && !brokers.isEmpty()) {
                cluster.addBroker(brokerId, brokers);
            }
        }
        return cluster;
    }


    /**
     * ��zk��ѯһ��id�µ�brokers,����master��һ������slave
     * */
    public Set<Broker> getBrokersById(final int brokerId) {
        final Set<Broker> set = new HashSet<Broker>();
        final Broker masterBroker = this.getMasterBrokerById(brokerId);
        final Set<Broker> slaveBrokers = this.getSlaveBrokersById(brokerId);
        if (masterBroker != null) {
            set.add(masterBroker);
        }
        if (slaveBrokers != null && !slaveBrokers.isEmpty()) {
            set.addAll(slaveBrokers);
        }
        return set;
    }


    /**
     * ��zk��ѯmaster broker,�������򷵻�null
     * */
    public Broker getMasterBrokerById(final int brokerId) {
        final String brokersString = ZkUtils.readDataMaybeNull(this.zkClient, this.brokerIdsPathOf(brokerId, -1));
        if (StringUtils.isNotBlank(brokersString)) {
            return new Broker(brokerId, brokersString);
        }
        return null;
    }


    /**
     * ��zk��ѯslave broker,�������򷵻�null
     * */
    private Set<Broker> getSlaveBrokersById(final int brokerId) {
        final Set<Broker> ret = new HashSet<Broker>();
        final List<String> brokers = ZkUtils.getChildren(this.zkClient, this.brokerIdsPath + "/" + brokerId);
        if (brokers == null) {
            return ret;
        }
        for (final String broker : brokers) {
            if (broker.startsWith("slave")) {
                int slaveId = -1;
                try {
                    slaveId = Integer.parseInt(broker.substring(5));
                    if (slaveId < 0) {
                        logger.warn("skip invalid slave path:" + broker);
                        continue;
                    }
                }
                catch (final Exception e) {
                    logger.warn("skip invalid slave path:" + broker);
                    continue;
                }
                final String brokerData =
                        ZkUtils.readDataMaybeNull(this.zkClient, this.brokerIdsPath + "/" + brokerId + "/" + broker);
                if (StringUtils.isNotBlank(brokerData)) {
                    ret.add(new Broker(brokerId, brokerData + "?slaveId=" + slaveId));
                }
            }
        }
        return ret;
    }


    /**
     * ���ط�����ָ����topic������master brokers
     * */
    public Map<Integer, String> getMasterBrokersByTopic(final String topic) {
        final Map<Integer, String> ret = new TreeMap<Integer, String>();
        final List<String> brokerIds = ZkUtils.getChildren(this.zkClient, this.brokerTopicsPubPath + "/" + topic);
        if (brokerIds == null) {
            return ret;
        }
        for (final String brokerIdStr : brokerIds) {
            if (!brokerIdStr.endsWith("-m")) {
                continue;
            }
            final int brokerId = Integer.parseInt(StringUtils.split(brokerIdStr, "-")[0]);
            final Broker broker = this.getMasterBrokerById(brokerId);
            if (broker != null) {
                ret.put(brokerId, broker.getZKString());
            }
        }
        return ret;

    }


    /**
     * ����master��topic��partitionӳ���map
     *
     * @param zkClient
     * @param topics
     * @return
     */
    public Map<String, List<Partition>> getPartitionsForTopicsFromMaster(final Collection<String> topics) {
        final Map<String, List<Partition>> ret = new HashMap<String, List<Partition>>();
        for (final String topic : topics) {
            List<Partition> partList = null;
            final List<String> brokers = ZkUtils.getChildren(this.zkClient, this.brokerTopicsPubPath + "/" + topic);
            for (final String broker : brokers) {
                final String[] brokerStrs = StringUtils.split(broker, "-");
                if (this.isMaster(brokerStrs)) {
                    String path = this.brokerTopicsPubPath + "/" + topic + "/" + broker;
                    String brokerData = ZkUtils.readData(this.zkClient, path);
                    try {
                        final TopicBroker topicBroker = TopicBroker.parse(brokerData);
                        if (topicBroker == null) {
                            logger.warn("Null broker data for path:" + path);
                            continue;
                        }
                        for (int part = 0; part < topicBroker.getNumParts(); part++) {
                            if (partList == null) {
                                partList = new ArrayList<Partition>();
                            }
                            final Partition partition = new Partition(Integer.parseInt(brokerStrs[0]), part);
                            if (!partList.contains(partition)) {
                                partList.add(partition);
                            }
                        }
                    }
                    catch (Exception e) {
                        logger.error("A serious error occurred,could not parse broker data at path=" + path
                            + ",and broker data is:" + brokerData, e);
                    }
                }
            }
            if (partList != null) {
                Collections.sort(partList);
                ret.put(topic, partList);
            }
        }
        return ret;
    }


    private boolean isMaster(final String[] brokerStrs) {
        return brokerStrs != null && brokerStrs.length == 2 && brokerStrs[1].equals("m");
    }


    /**
     * ����һ��broker����������topics
     *
     * */
    public Set<String> getTopicsByBrokerIdFromMaster(final int brokerId) {
        final Set<String> set = new HashSet<String>();
        final List<String> allTopics = ZkUtils.getChildren(this.zkClient, this.brokerTopicsSubPath);
        for (final String topic : allTopics) {
            final List<String> brokers = ZkUtils.getChildren(this.zkClient, this.brokerTopicsSubPath + "/" + topic);
            if (brokers != null && brokers.size() > 0) {
                for (final String broker : brokers) {
                    if ((String.valueOf(brokerId) + "-m").equals(broker)) {
                        set.add(topic);
                    }
                }
            }
        }
        return set;
    }


    /**
     * ����һ��master �µ�topic��partitionӳ���map
     *
     * @param zkClient
     * @param topics
     * @return
     */
    public Map<String, List<Partition>> getPartitionsForSubTopicsFromMaster(final Collection<String> topics,
        final int brokerId) {
        final Map<String, List<Partition>> ret = new HashMap<String, List<Partition>>();
        if (topics != null) {
            for (final String topic : topics) {
                List<Partition> partList = null;
                final String dataString =
                        ZkUtils.readDataMaybeNull(this.zkClient, this.brokerTopicsPathOf(topic, false, brokerId, -1));
                if (StringUtils.isBlank(dataString)) {
                    continue;
                }
                try {
                    final TopicBroker topicBroker = TopicBroker.parse(dataString);
                    if (topicBroker == null) {
                        continue;
                    }
                    for (int part = 0; part < topicBroker.getNumParts(); part++) {
                        if (partList == null) {
                            partList = new ArrayList<Partition>();
                        }
                        partList.add(new Partition(brokerId, part));
                    }
                    if (partList != null) {
                        Collections.sort(partList);
                        ret.put(topic, partList);
                    }
                }
                catch (Exception e) {
                    throw new IllegalStateException("Parse data to TopicBroker failed,data is:" + dataString, e);
                }
            }
        }
        return ret;
    }


    /**
     * ����һ��master�µ�topic��partitionӳ���map
     *
     * @param zkClient
     * @param topics
     * @return
     */
    public Map<String, List<String>> getPartitionStringsForSubTopicsFromMaster(final Collection<String> topics,
        final int brokerId) {
        final Map<String, List<String>> ret = new HashMap<String, List<String>>();
        final Map<String, List<Partition>> tmp = this.getPartitionsForSubTopicsFromMaster(topics, brokerId);
        if (tmp != null && !tmp.isEmpty()) {
            for (final Map.Entry<String, List<Partition>> each : tmp.entrySet()) {
                final String topic = each.getKey();
                List<String> list = ret.get(topic);
                if (list == null) {
                    list = new ArrayList<String>();
                }
                for (final Partition partition : each.getValue()) {
                    list.add(partition.getBrokerId() + "-" + partition.getPartition());
                }
                if (list != null) {
                    Collections.sort(list);
                    ret.put(topic, list);
                }
            }
        }
        return ret;
    }


    /**
     * ����topic��partitionӳ���map. ����master��slave������partitions
     *
     * @param zkClient
     * @param topics
     * @return
     */
    public Map<String, List<String>> getPartitionStringsForSubTopics(final Collection<String> topics) {
        final Map<String, List<String>> ret = new HashMap<String, List<String>>();
        for (final String topic : topics) {
            List<String> partList = null;
            final List<String> brokers = ZkUtils.getChildren(this.zkClient, this.brokerTopicsSubPath + "/" + topic);
            for (final String broker : brokers) {
                final String[] tmp = StringUtils.split(broker, "-");
                if (tmp != null && tmp.length == 2) {
                    String path = this.brokerTopicsSubPath + "/" + topic + "/" + broker;
                    String brokerData = ZkUtils.readData(this.zkClient, path);
                    try {
                        final TopicBroker topicBroker = TopicBroker.parse(brokerData);
                        if (topicBroker == null) {
                            logger.warn("Null broker data for path:" + path);
                            continue;
                        }
                        for (int part = 0; part < topicBroker.getNumParts(); part++) {
                            if (partList == null) {
                                partList = new ArrayList<String>();
                            }

                            final String partitionString = tmp[0] + "-" + part;
                            if (!partList.contains(partitionString)) {
                                partList.add(partitionString);
                            }
                        }
                    }
                    catch (Exception e) {
                        logger.error("A serious error occurred,could not parse broker data at path=" + path
                            + ",and broker data is:" + brokerData, e);
                    }
                }
                else {
                    logger.warn("skip invalid topics path:" + broker);
                }
            }
            if (partList != null) {
                Collections.sort(partList);
                ret.put(topic, partList);
            }
        }
        return ret;
    }


    /**
     * brokerId ��zk��ע���path
     *
     * @param brokerId
     * @param slaveId
     *            slave���, С��0��ʾmaster
     *
     * */
    public String brokerIdsPathOf(final int brokerId, final int slaveId) {
        return this.brokerIdsPath + "/" + brokerId + (slaveId >= 0 ? "/slave" + slaveId : "/master");
    }


    /**
     * Master config file checksum path
     *
     * @param brokerId
     * @return
     */
    public String masterConfigChecksum(final int brokerId) {
        return this.brokerIdsPath + "/" + brokerId + "/master_config_checksum";
    }


    /**
     * topic ��zk��ע���path
     *
     * @param topic
     * @param brokerId
     * @param slaveId
     *            slave���, С��0��ʾmaster
     * */
    @Deprecated
    public String brokerTopicsPathOf(final String topic, final int brokerId, final int slaveId) {
        return this.brokerTopicsPath + "/" + topic + "/" + brokerId + (slaveId >= 0 ? "-s" + slaveId : "-m");
    }


    /**
     *
     * Returns topic path in zk
     *
     * @since 1.4.3
     * @param topic
     * @param brokerId
     * @param slaveId
     *            slave���, С��0��ʾmaster
     * */
    public String brokerTopicsPathOf(final String topic, boolean publish, final int brokerId, final int slaveId) {
        String parent = publish ? this.brokerTopicsPubPath : this.brokerTopicsSubPath;
        return parent + "/" + topic + "/" + brokerId + (slaveId >= 0 ? "-s" + slaveId : "-m");
    }

}
TOP

Related Classes of com.taobao.metamorphosis.utils.MetaZookeeper$ZKGroupTopicDirs

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.