com.alibaba.napoli.metamorphosis.client.consumer.storage.ZkOffsetStorage.java Source code

Java tutorial

Introduction

Here is the source code for com.alibaba.napoli.metamorphosis.client.consumer.storage.ZkOffsetStorage.java

Source

/*
 * (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.alibaba.napoli.metamorphosis.client.consumer.storage;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

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

import com.alibaba.napoli.metamorphosis.client.ZkClientChangedListener;
import com.alibaba.napoli.metamorphosis.client.consumer.TopicPartitionRegInfo;
import com.alibaba.napoli.metamorphosis.cluster.Partition;
import com.alibaba.napoli.metamorphosis.utils.MetaZookeeper;
import com.alibaba.napoli.metamorphosis.utils.MetaZookeeper.ZKGroupTopicDirs;
import com.alibaba.napoli.metamorphosis.utils.ZkUtils;

/**
 * zkoffset
 * 
 * @author boyan
 * @Date 2011-4-28
 * 
 */
public class ZkOffsetStorage implements OffsetStorage, ZkClientChangedListener {
    private volatile ZkClient zkClient;
    private final MetaZookeeper metaZookeeper;

    @Override
    public void onZkClientChanged(final ZkClient newClient) {
        log.info("Update ZkOffsetStorage's zkClient...");
        this.zkClient = newClient;
    }

    public ZkOffsetStorage(final MetaZookeeper metaZookeeper, final ZkClient zkClient) {
        super();
        this.metaZookeeper = metaZookeeper;
        this.zkClient = zkClient;
    }

    static final Log log = LogFactory.getLog(ZkOffsetStorage.class);

    @Override
    public void commitOffset(final String group, final Collection<TopicPartitionRegInfo> infoList) {
        if (this.zkClient == null || infoList == null || infoList.isEmpty()) {
            return;
        }
        List<TopicPartitionRegInfo> shouldDeleteList = new ArrayList<TopicPartitionRegInfo>();

        for (final TopicPartitionRegInfo info : infoList) {
            final String topic = info.getTopic();
            final ZKGroupTopicDirs topicDirs = this.metaZookeeper.new ZKGroupTopicDirs(topic, group);
            long newOffset = -1;
            long msgId = -1;
            // ???msgIdoffset
            synchronized (info) {
                // ??
                if (!info.isModified()) {
                    continue;
                }
                newOffset = info.getOffset().get();
                msgId = info.getMessageId();
                // false
                info.setModified(false);
            }
            try {

                if (!ZkUtils.pathExists(this.zkClient,
                        topicDirs.consumerOffsetDir + "/" + info.getPartition().toString())) {
                    Partition partition = info.getPartition();
                    int brokerId = partition.getBrokerId();
                    String brokerTopicPath = this.metaZookeeper.brokerTopicsPathOf(topic, brokerId, -1);
                    if (!ZkUtils.pathExists(this.zkClient, brokerTopicPath)) {
                        shouldDeleteList.add(info);
                        continue;
                    }
                }
                // zk?msgId-offset
                // ?offset1.4msgId-offset,??
                ZkUtils.updatePersistentPath(this.zkClient,
                        topicDirs.consumerOffsetDir + "/" + info.getPartition().toString(),
                        msgId + "-" + newOffset);
            } catch (final Throwable t) {
                log.error("exception during commitOffsets", t);
            }
            if (log.isDebugEnabled()) {
                log.debug("Committed offset " + newOffset + " for topic " + info.getTopic());
            }

        }
        if (shouldDeleteList.size() > 0) {
            for (TopicPartitionRegInfo deleteInfo : shouldDeleteList) {
                log.warn(deleteInfo.getTopic() + " remove form borked[" + deleteInfo.getPartition().getBrokerId()
                        + "]");
            }
            infoList.remove(shouldDeleteList);
        }
    }

    @Override
    public TopicPartitionRegInfo load(final String topic, final String group, final Partition partition) {
        final ZKGroupTopicDirs topicDirs = this.metaZookeeper.new ZKGroupTopicDirs(topic, group);
        final String znode = topicDirs.consumerOffsetDir + "/" + partition.toString();
        final String offsetString = ZkUtils.readDataMaybeNull(this.zkClient, znode);
        if (offsetString == null) {
            return null;
        } else {
            // ?
            final int index = offsetString.lastIndexOf("-");
            if (index > 0) {
                // 1.4
                final long msgId = Long.parseLong(offsetString.substring(0, index));
                final long offset = Long.parseLong(offsetString.substring(index + 1));
                return new TopicPartitionRegInfo(topic, partition, offset, msgId);
            } else {
                // ?
                final long offset = Long.parseLong(offsetString);
                return new TopicPartitionRegInfo(topic, partition, offset);
            }
        }
    }

    @Override
    public void close() {
        // do nothing
    }

    @Override
    public void initOffset(final String topic, final String group, final Partition partition, final long offset) {
        // do nothing
    }

}