/*
* (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.tools.shell;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.lang.StringUtils;
import com.taobao.metamorphosis.cluster.Partition;
import com.taobao.metamorphosis.tools.monitor.InitException;
import com.taobao.metamorphosis.tools.query.OffsetQueryDO;
import com.taobao.metamorphosis.tools.query.OffsetQueryDO.QueryType;
import com.taobao.metamorphosis.tools.query.Query;
import com.taobao.metamorphosis.tools.utils.CommandLineUtils;
/**
* <pre>
* usage:
* CopyOffsetInZk -topic xxtopic -src 1 -target 2 -start 5 -end 10
* CopyOffsetInZk -topic xxtopic -src 1 -target 2 -start 5 -end 10 -targetStart 2
* </pre>
*
* @author ��
* @since 2011-8-24 ����10:19:30
*/
public class CopyOffsetInZk extends ShellTool {
private final Query query;
private final ZkManager zkManager;
public static void main(String[] args) throws Exception {
new CopyOffsetInZk(System.out).doMain(args);
System.exit(0);
}
CopyOffsetInZk(PrintStream out) throws InitException {
super(out);
this.query = new Query();
this.query.init("zk.properties", null);
this.zkManager = new ZkManager(this.query);
}
public CopyOffsetInZk(String configFile, PrintWriter out) throws InitException {
super(out);
this.query = new Query();
this.query.init(configFile, null);
this.zkManager = new ZkManager(query);
}
@Override
public void doMain(String[] args) throws Exception {
CommandLine commandLine = this.getCommandLine(args);
String topic = commandLine.getOptionValue("topic");
int src = Integer.parseInt(commandLine.getOptionValue("src"));
int target = Integer.parseInt(commandLine.getOptionValue("target"));
int start = Integer.parseInt(commandLine.getOptionValue("start"));
int end = Integer.parseInt(commandLine.getOptionValue("end"));
int targetStart = Integer.parseInt(commandLine.getOptionValue("targetStart", "0"));
this.checkArg(topic, src, target, start, end);
List<String> groups = this.query.getConsumerGroups(QueryType.zk);
Map<Partition, Partition> srcTargetPartitionMap =
this.getSrcTargetPartitionMap(this.getSourcePartitions(src, start, end), target, targetStart);
for (String group : groups) {
for (Map.Entry<Partition, Partition> entry : srcTargetPartitionMap.entrySet()) {
Partition oldPartition = entry.getKey();
Partition newPartition = entry.getValue();
String srcOffset = this.query.queryOffset(new OffsetQueryDO(topic, group, oldPartition.toString(), "zk"));
if (!StringUtils.isBlank(srcOffset)) {
if (!StringUtils.isBlank(this.query.queryOffset(new OffsetQueryDO(topic, group, newPartition.toString(), "zk")))) {
this.println("topic=" + topic + ",group=" + group + ",partition[" + newPartition
+ "] offset �Ѿ�����");
continue;
}
this.zkManager.setOffset(topic, group, newPartition, srcOffset);
this.println("copy offset successed for topic[" + topic + "], group=" + group + ", " + oldPartition
+ "-->" + newPartition + ", offset=" + srcOffset);
}
else {
this.println("topic=" + topic + ",group=" + group + ",partition[" + oldPartition
+ "] offset �����ڻ��ѯ����");
}
}
}
}
//
// private Map<String, String> getOffsetPathMap(String group, String topic,
// Map<Partition, Partition> srcTargetPartitionMap) {
//
// Map<String, String> map = new LinkedHashMap<String, String>();
//
// for (Map.Entry<Partition, Partition> entry :
// srcTargetPartitionMap.entrySet()) {
// map.put(Query.getOffsetPath(group, topic, entry.getKey()),
// Query.getOffsetPath(group, topic, entry.getValue()));
// }
// return map;
// }
private List<Partition> getSourcePartitions(int brokerId, int startPartitionNo, int endPartitionNo) {
List<Partition> list = new LinkedList<Partition>();
for (int i = startPartitionNo; i <= endPartitionNo; i++) {
list.add(new Partition(brokerId, i));
}
return list;
}
private Map<Partition, Partition> getSrcTargetPartitionMap(List<Partition> srcPartitions, int target, int start) {
Map<Partition, Partition> map = new TreeMap<Partition, Partition>();
for (int i = 0; i < srcPartitions.size(); i++) {
map.put(srcPartitions.get(i), new Partition(target, i + start));
}
return map;
}
private CommandLine getCommandLine(String[] args) {
Option topicOption = new Option("topic", true, "topic");
topicOption.setRequired(true);
Option fromOption = new Option("src", true, "source broker id");
fromOption.setRequired(true);
Option toOption = new Option("target", true, "target broker id");
toOption.setRequired(true);
Option startOption = new Option("start", true, "start partition number");
startOption.setRequired(true);
Option endOption = new Option("end", true, "end partition number");
endOption.setRequired(true);
Option targetStartOption = new Option("targetStart", true, "Ŀ���������ʼ���");
return CommandLineUtils.parseCmdLine(args, new Options().addOption(topicOption).addOption(fromOption)
.addOption(toOption).addOption(startOption).addOption(endOption).addOption(targetStartOption));
}
private void checkArg(String topic, int src, int target, int start, int end) {
if (StringUtils.isBlank(topic)) {
throw new IllegalArgumentException("topic is blank");
}
if (src < 0 || target < 0) {
throw new IllegalArgumentException("src and target must not less than 0");
}
if (src == target) {
throw new IllegalArgumentException("src equals target");
}
if (start > end) {
throw new IllegalArgumentException("start less then end");
}
}
Query getQuery() {
return this.query;
}
}