【转】分析Hadoop自带WordCount例子的执行过程(3)

继续向下看:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> Optionfs = OptionBuilder.withArgName( " local|namenode:port " )
.hasArg()
.withDescription(
" specifyanamenode " )
.create(
" fs " );
opts.addOption(fs);

有一个很重要的类OptionBuilder,它才完成了充实一个Option的过程,然后经过多次调用,会将多个Option都添加到opts列表中。

看一看OptionBuilder类的withArgName()方法:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /**
*ThenextOptioncreatedwillhavethespecifiedargumentvalue
*name.
*
*
@param namethenamefortheargumentvalue
*
@return theOptionBuilderinstance
*/
public static OptionBuilderwithArgName(Stringname)
{
OptionBuilder.argName
= name;
return instance;
}

上面,为一个OptionBuilder的实例指定一个参数(argName)name,实际上是返回了一个具有nameOptionBuilder实例。

然后,又调用了hasArg()方法,它也是OptionBuilder类的静态方法:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /**
*ThenextOptioncreatedwillrequireanargumentvalue.
*
*
@return theOptionBuilderinstance
*/
public static OptionBuilderhasArg()
{
OptionBuilder.numberOfArgs
= 1 ;
return instance;
}

为刚才指定参数名的那个OptionBuilder实例设置了参数的个数,因为第一次设置,当然个数为1了。

调用withDescription()方法来设定描述信息:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /**
*ThenextOptioncreatedwillhavethespecifieddescription
*
*
@param newDescriptionadescriptionoftheOption'spurpose
*
@return theOptionBuilderinstance
*/
public static OptionBuilderwithDescription(StringnewDescription)
{
OptionBuilder.description
= newDescription;
return instance;
}

比较关键的是最后一步调用,通过调用OptionBuilder类的create()方法才真正完成了一个Option的创建:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /**
*CreateanOptionusingthecurrentsettingsandwith
*thespecifiedOption<code>char</code>.
*
*
@param optthe<code>java.lang.String</code>representation
*oftheOption
*
@return theOptioninstance
*
@throws IllegalArgumentExceptionif<code>opt</code>isnot
*avalidcharacter.SeeOption.
*/
public static Optioncreate(Stringopt)
throws IllegalArgumentException
{
// createtheoption
Optionoption = new Option(opt,description);

// settheoptionproperties
option.setLongOpt(longopt);
option.setRequired(required);
option.setOptionalArg(optionalArg);
option.setArgs(numberOfArgs);
option.setType(type);
option.setValueSeparator(valuesep);
option.setArgName(argName);
option.setArgPattern(argPattern,limit);

// resettheOptionBuilderproperties
OptionBuilder.reset();
// returntheOptioninstance
return option;
}

从上面一个Option的设置,我们可以看出来,OptionBuilder类其实是一个辅助工具,用来收集与一个Option相关的信息,从而将这些信息一次全部赋予到一个新建的Option对象上,这个对象现在具有详细的信息了。

接着,通过CommandLineParser parserparse方法,可以知道public abstract class Parser implements CommandLineParser,从抽象类Parser中找到parse的实现:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> public CommandLineparse(Optionsoptions,String[]arguments,
boolean stopAtNonOption)
throws ParseException
{
return parse(options,arguments, null ,stopAtNonOption);
}

参数stopAtNonOption表明,如果解析过程中遇到的是一个空选项是否仍然继续解析。从前面parseGeneralOptions方法 中commandLine = parser.parse(opts, args, true);可知:我们传递过来一个true

再次调用Parser类的重载成员方法parse(),如下所示,解析过程非常详细:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /**
*Parsetheargumentsaccordingtothespecifiedoptionsand
*properties.
*
*
@param optionsthespecifiedOptions
*
@param argumentsthecommandlinearguments
*
@param propertiescommandlineoptionname-valuepairs
*
@param stopAtNonOptionstopparsingtheargumentswhenthefirst
*nonoptionisencountered.
*
*
@return thelistofatomicoptionandvaluetokens
*
*
@throws ParseExceptionifthereareanyproblemsencountered
*whileparsingthecommandlinetokens.
*/
public CommandLineparse(Optionsoptions,String[]arguments,
Propertiesproperties,
boolean stopAtNonOption)
throws ParseException
{
// initialisemembers
this .options = options;
requiredOptions
= options.getRequiredOptions();
cmd
= new CommandLine();
boolean eatTheRest = false ;
if (arguments == null )
{
arguments
= new String[ 0 ];
}
ListtokenList
= Arrays.asList(flatten( this .options,
arguments,
stopAtNonOption));
ListIteratoriterator
= tokenList.listIterator();
// processeachflattenedtoken
while (iterator.hasNext())
{
Stringt
= (String)iterator.next();
// thevalueisthedouble-dash
if ( " -- " .equals(t))
{
eatTheRest
= true ;
}
// thevalueisasingledash
else if ( " - " .equals(t))
{
if (stopAtNonOption)
{
eatTheRest
= true ;
}
else
{
cmd.addArg(t);
}
}
// thevalueisanoption
else if (t.startsWith( " - " ))
{
if (stopAtNonOption && ! options.hasOption(t))
{
eatTheRest
= true ;
cmd.addArg(t);
}
else
{
processOption(t,iterator);
}
}
// thevalueisanargument
else
{
cmd.addArg(t);
if (stopAtNonOption)
{
eatTheRest
= true ;
}
}
// eattheremainingtokens
if (eatTheRest)
{
while (iterator.hasNext())
{
Stringstr
= (String)iterator.next();
// ensureonlyonedouble-dashisadded
if ( ! " -- " .equals(str))
{
cmd.addArg(str);
}
}
}
}
processProperties(properties);
checkRequiredOptions();
return cmd;
}

解析之后,返回CommandLine类的实例,从而GenericOptionsParser类的成员变量commandLine获取到了一个引用。commandLineGenericOptionsParser类的一个私有成员变量。

看一下CommandLine类的实现:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> package org.apache.commons.cli;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
*Representslistofargumentsparsedagainst
*a{
@link Options}descriptor.
*
*Itallowsqueryingofaboolean{
@link #hasOption(Stringopt)},
*inadditiontoretrievingthe{
@link #getOptionValue(Stringopt)}
*foroptionsrequiringarguments.
*/
public class CommandLine{
// 不能识别的options/arguments
private Listargs = new LinkedList();
/** theprocessedoptions */
private Mapoptions = new HashMap();
/** theoptionnamemap */
private Mapnames = new HashMap();
/** Mapofuniqueoptionsforeasetogetcompletelistofoptions */
private MaphashcodeMap = new HashMap();
/** theprocessedoptions */
private Option[]optionsArray;
// 创建一个命令行CommandLine的实例。
CommandLine()
{
// nothingtodo
}
// 从options这个HashMap中查看,判断是否opt已经被设置了
public boolean hasOption(Stringopt)
{
return options.containsKey(opt);
}
// 调用hasOption()方法,从options这个HashMap中查看,判断是否opt已经被设置了
public boolean hasOption( char opt)
{
return hasOption(String.valueOf(opt));
}
// 根据Stringopt返回Option的Object类型
public ObjectgetOptionObject(Stringopt)
{
Stringres
= getOptionValue(opt);
if ( ! options.containsKey(opt))
{
return null ;
}
Objecttype
= ((Option)options.get(opt)).getType();
return (res == null ) ? null :TypeHandler.createValue(res,type);
}
// 根据charopt返回Option的Object类型
public ObjectgetOptionObject( char opt)
{
return getOptionObject(String.valueOf(opt));
}
// 根据指定的Stringopt获取Option的值
public StringgetOptionValue(Stringopt)
{
String[]values
= getOptionValues(opt);
return (values == null ) ? null :values[ 0 ];
}
// 根据指定的charopt获取Option的值
public StringgetOptionValue( char opt)
{
return getOptionValue(String.valueOf(opt));
}
/**
*Retrievesthearrayofvalues,ifany,ofanoption.
*
*
@param optstringnameoftheoption
*
@return Valuesoftheargumentifoptionisset,andhasanargument,
*otherwisenull.
*/
public String[]getOptionValues(Stringopt)
{
opt
= Util.stripLeadingHyphens(opt);
Stringkey
= opt;
if (names.containsKey(opt))
{
key
= (String)names.get(opt);
}
if (options.containsKey(key))
{
return ((Option)options.get(key)).getValues();
}
return null ;
}
// 根据指定的Stringopt,返回Option的值的一个数组
public String[]getOptionValues( char opt)
{
return getOptionValues(String.valueOf(opt));
}
// 根据指定的Stringopt和StringdefaultValue获取Option的值
public StringgetOptionValue(Stringopt,StringdefaultValue)
{
Stringanswer
= getOptionValue(opt);
return (answer != null ) ? answer:defaultValue;
}
// 根据指定的charopt和StringdefaultValue获取Option的值
public StringgetOptionValue( char opt,StringdefaultValue)
{
return getOptionValue(String.valueOf(opt),defaultValue);
}
// 返回不能够解析的Option和参数的一个数组
public String[]getArgs()
{
String[]answer
= new String[args.size()];
args.toArray(answer);
return answer;
}
// 返回不能够解析的Option和参数的一个列表
public ListgetArgList()
{
return args;
}
/**
*jkeyes
*-commentedoutuntilitisimplementedproperly
*<p>Dumpstate,suitablefordebugging.</p>
*
*
@return Stringifiedformofthisobject
*/
public StringtoString(){
StringBufferbuf
= new StringBuffer();

buf.append(
" [CommandLine:[options: " );
buf.append(options.toString());
buf.append(
" ][args: " );
buf.append(args.toString());
buf.append(
" ]] " );

return buf.toString();
}
/**
*Addleft-overunrecognizedoption/argument.
*
*
@param argtheunrecognisedoption/argument.
*/
void addArg(Stringarg)
{
args.add(arg);
}
// 向CommandLine中添加一个Option,其中Option的值(可能多个)被存储
void addOption(Optionopt)
{
hashcodeMap.put(
new Integer(opt.hashCode()),opt);
Stringkey
= opt.getKey();
if (key == null )
{
key
= opt.getLongOpt();
}
else
{
names.put(opt.getLongOpt(),key);
}
options.put(key,opt);
}
// 返回CommandLine的Option成员表的一个迭代器
public Iteratoriterator()
{
return hashcodeMap.values().iterator();
}
// 返回处理过的Option的对象数组
public Option[]getOptions()
{
Collectionprocessed
= options.values();

// reinitialisearray
optionsArray = new Option[processed.size()];
// returnthearray
return (Option[])processed.toArray(optionsArray);
}
}

一个CommandLine中包含一个重要的HashMap,里面存储的是键值对,即(key, opt),通过它可以非常方便地设置和访问。

接着在parseGeneralOptions方法中调用processGeneralOptions()方法,进行处理:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> processGeneralOptions(conf,commandLine);

processGeneralOptions的处理过程如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> /**
*Modifyconfigurationaccordinguser-specifiedgenericoptions
*
@param confConfigurationtobemodified
*
@param lineUser-specifiedgenericoptions
*/
private void processGeneralOptions(Configurationconf,
CommandLineline){
if (line.hasOption( " fs " )){
conf.set(
" fs.default.name " ,line.getOptionValue( " fs " ));
}
if (line.hasOption( " jt " )){
conf.set(
" mapred.job.tracker " ,line.getOptionValue( " jt " ));
}
if (line.hasOption( " conf " )){
conf.addResource(
new Path(line.getOptionValue( " conf " )));
}
if (line.hasOption( ' D ' )){
String[]property
= line.getOptionValues( ' D ' );
for ( int i = 0 ;i < property.length - 1 ;i = i + 2 ){
if (property[i] != null )
conf.set(property[i],property[i
+ 1 ]);
}
}
}

传进去一个CommandLine实例,通过CommanLine的信息,来设置Configuration conf对象。设置Configuration conf对象的目的是:为HadoopTool工作而设置的,比如WordCount这个工具,在运行开始时需要获取到Hadoop的配置信息的,这个 就需要从这里设置的Configuration conf对象来获取。

上面这个processGeneralOptions()方法,是根据CommanLine的对象,获取到所有参数值的一个数组,并返回。

到此位置,前面都是为了初始化一个GenericOptionsParser parser解析器所做的工作:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> GenericOptionsParserparser = new GenericOptionsParser(conf,args);

进而,可以使用 GenericOptionsParser类的实例parser 来获取Hadoop的通用参数了:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> // gettheargsw/ogenerichadoopargs
String[]toolArgs = parser.getRemainingArgs();

已经具备了运行Hadoop工具的条件了,可以启动了:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> return tool.run(toolArgs);

可以根据返回的状态码检查工具运行情况。

上面Tool tool就是我们实例化的WordCount对象,这时候才进入到WordCount实现中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值