hadoop2.0对命令调用的重构

原创,转载请注明出处 白硕 baishuo491@163.com
http://baishuo491.iteye.com/blog/1916241

2.0以后,重构为为以Command为基础的一系列类 bstract public class Command extends Configured
最核心的是run函数,里面主要的行为就是处理各种选项,展开参数,并且处理每个参数(注释原话 The default behavior is to process options, * expand arguments, and then process each argument.)
run函数里最核心的代码:
LinkedList<String> args = new LinkedList<String>(Arrays.asList(argv));
processOptions(args);
processRawArguments(args);
后面两个都是虚函数,要由子类来实现,因为不同的子类,处理的方法不一样。这个方法的注释上,给了调用过程,还是很复杂的:

<pre>
* run
* |-> {@link #processOptions(LinkedList)}
* \-> {@link #processRawArguments(LinkedList)}
* |-> {@link #expandArguments(LinkedList)} //这个和下面这个是在Command类里面实现的
* | \-> {@link #expandArgument(String)}*
* \-> {@link #processArguments(LinkedList)}
* |-> {@link #processArgument(PathData)}*
* | |-> {@link #processPathArgument(PathData)}
* | \-> {@link #processPaths(PathData, PathData...)}
* | \-> {@link #processPath(PathData)}*
* \-> {@link #processNonexistentPath(PathData)}
* </pre>


看看Command 的一个子类FsCommand , abstract public class FsCommand extends Command
里面有一个静态函数,
public static void registerCommands(CommandFactory factory) {
factory.registerCommands(CopyCommands.class);
factory.registerCommands(Count.class);
factory.registerCommands(Delete.class);
factory.registerCommands(Display.class);
。。。。。。。
如果要新建command,要这里面注册,这样就可以作为静态数据装载到内存里

public class CommandFactory extends Configured implements Configurable

里面有一个classMap 和 一个objectMap
private Map<String, Class<? extends Command>> classMap =
new HashMap<String, Class<? extends Command>>();

private Map<String, Command> objectMap =
new HashMap<String, Command>();

下面看看 CommandFactory 的函数 registerCommands
public void registerCommands(Class<?> registrarClass) {
try {
registrarClass.getMethod(
"registerCommands", CommandFactory.class
).invoke(null, this);
} catch (Exception e) {
throw new RuntimeException(StringUtils.stringifyException(e));
}
}
是registrarClass 调用自己的registerCommands命令

看一看CopyCommands 的registerCommands 命令,
public static void registerCommands(CommandFactory factory) {
factory.addClass(Merge.class, "-getmerge");
factory.addClass(Cp.class, "-cp");
factory.addClass(CopyFromLocal.class, "-copyFromLocal");
factory.addClass(CopyToLocal.class, "-copyToLocal");
factory.addClass(Get.class, "-get");
factory.addClass(Put.class, "-put");
}
原来CopyCommands 还有自己一系列的内部子类,都是静态的,在这里统一注册,如果要新建CopyCommands子类,就要在这里注册
CommandFactory 的addClass函数,可见是put到classMap里面了,名字和类调换了一下位置,字符串做主键
public void addClass(Class<? extends Command> cmdClass, String ... names) {
for (String name : names) classMap.put(name, cmdClass);
}
另外一个map objectMap,只有在FsShell的init函数里,被插入了Help() 和Usage() 两个对象

protected void init() throws IOException {
getConf().setQuietMode(true);
if (commandFactory == null) {
commandFactory = new CommandFactory(getConf());//创建一个单例的factory
commandFactory.addObject(new Help(), "-help");
commandFactory.addObject(new Usage(), "-usage");
registerCommands(commandFactory);//调用自己的registerCommands,其实是调用FsCommand的registerCommands,之前有提过。为了和DFSAdmin区分开
}
}

具体到每个命令的调用,因为都是从fshell 启动的,调用链如下:
FsShell.init() line: 83
FsShell.run(String[]) line: 241
ToolRunner.run(Configuration, Tool, String[]) line: 70
ToolRunner.run(Tool, String[]) line: 84
FsShell.main(String[]) line: 304
init之后,通过instance = commandFactory.getInstance(cmd);的到Class,cmd是解析出来的如-cat等字符串,去classMap里就可以get到对应的Class

之后,调用instance.run 执行我们最初讨论的 Command.run
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值