终于遇到第一块硬骨头


Hadoop没有使用java.util.Properties管理配置文件,而是自己定义了一套配置文件管理系统和自己的API。

  


  1. package org.apache.hadoop.conf;
  2.  
  3. import java.io.BufferedInputStream;
  4. import java.io.DataInput;
  5. import java.io.DataOutput;
  6. import java.io.File;
  7. import java.io.FileInputStream;
  8. import java.io.IOException;
  9. import java.io.InputStream;
  10. import java.io.InputStreamReader;
  11. import java.io.OutputStream;
  12. import java.io.Reader;
  13. import java.io.Writer;
  14. import java.net.URL;
  15. import java.util.ArrayList;
  16. import java.util.Collection;
  17. import java.util.Enumeration;
  18. import java.util.HashMap;
  19. import java.util.HashSet;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.ListIterator;
  23. import java.util.Map;
  24. import java.util.Properties;
  25. import java.util.Set;
  26. import java.util.StringTokenizer;
  27. import java.util.WeakHashMap;
  28. import java.util.concurrent.CopyOnWriteArrayList;
  29. import java.util.regex.Matcher;
  30. import java.util.regex.Pattern;
  31. //引入了IO的流类
  32. //引入了网络编程类,用来封装或获取网络资源
  33. //引入了工具包中的集合类。其中StringTokenier在hadoop中用的非常多,特别是在mapreduce编程中,经常需要这个工具类来处理数据。
  34. //它起着分词器的作用。
  35. //关于CopyOnWriteArrayList,之前没接触过,具体推荐 http://blog.csdn.net/imzoer/article/details/9751591,就是实现了线程安全
  36. //关于regex.Matcher和regex.Pattern,看regex可知就是正则类,具体用法不太一样 http://ningtukun.blog.163.com/blog/static/186541445201292984311656/
  37. import javax.xml.parsers.DocumentBuilder;
  38. import javax.xml.parsers.DocumentBuilderFactory;
  39. import javax.xml.parsers.ParserConfigurationException;
  40. import javax.xml.transform.Transformer;
  41. import javax.xml.transform.TransformerFactory;
  42. import javax.xml.transform.dom.DOMSource;
  43. import javax.xml.transform.stream.StreamResult;
  44.  
  45. import org.apache.commons.logging.Log;
  46. import org.apache.commons.logging.LogFactory;
  47. import org.apache.hadoop.fs.FileSystem;
  48. import org.apache.hadoop.fs.Path;
  49. import org.apache.hadoop.io.Writable;
  50. import org.apache.hadoop.io.WritableUtils;
  51. import org.apache.hadoop.util.StringUtils;
  52. import org.codehaus.jackson.JsonFactory;
  53. import org.codehaus.jackson.JsonGenerator;
  54. import org.w3c.dom.DOMException;
  55. import org.w3c.dom.Document;
  56. import org.w3c.dom.Element;
  57. import org.w3c.dom.Node;
  58. import org.w3c.dom.NodeList;
  59. import org.w3c.dom.Text;
  60. import org.xml.sax.SAXException;
  61.  
  62. /**
  63. * Provides access to configuration parameters.
  64. *
  65. * <h4 id="Resources">Resources</h4>
  66. *
  67. * <p>Configurations are specified by resources. A resource contains a set of
  68. * name/value pairs as XML data. Each resource is named by either a
  69. * <code>String</code> or by a {@link Path}. If named by a <code>String</code>,
  70. * then the classpath is examined for a file with that name. If named by a
  71. * <code>Path</code>, then the local filesystem is examined directly, without
  72. * referring to the classpath.
  73. *
  74. * <p>Unless explicitly turned off, Hadoop by default specifies two
  75. * resources, loaded in-order from the classpath: <ol>
  76. * <li><tt><a href="{@docRoot}/../core-default.html">core-default.xml</a>
  77. * </tt>: Read-only defaults for hadoop.</li>
  78. * <li><tt>core-site.xml</tt>: Site-specific configuration for a given hadoop
  79. * installation.</li>
  80. * </ol>
  81. * Applications may add additional resources, which are loaded
  82. * subsequent to these resources in the order they are added.
  83. *
  84. * <h4 id="FinalParams">Final Parameters</h4>
  85. *
  86. * <p>Configuration parameters may be declared <i>final</i>.
  87. * Once a resource declares a value final, no subsequently-loaded
  88. * resource can alter that value.
  89. * For example, one might define a final parameter with:
  90. * <tt><pre>
  91. * &lt;property&gt;
  92. * &lt;name&gt;dfs.client.buffer.dir&lt;/name&gt;
  93. * &lt;value&gt;/tmp/hadoop/dfs/client&lt;/value&gt;
  94. * <b>&lt;final&gt;true&lt;/final&gt;</b>
  95. * &lt;/property&gt;</pre></tt>
  96. *
  97. * Administrators typically define parameters as final in
  98. * <tt>core-site.xml</tt> for values that user applications may not alter.
  99. *
  100. * <h4 id="VariableExpansion">Variable Expansion</h4>
  101. *
  102. * <p>Value strings are first processed for <i>variable expansion</i>. The
  103. * available properties are:<ol>
  104. * <li>Other properties defined in this Configuration; and, if a name is
  105. * undefined here,</li>
  106. * <li>Properties in {@link System#getProperties()}.</li>
  107. * </ol>
  108. *
  109. * <p>For example, if a configuration resource contains the following property
  110. * definitions:
  111. * <tt><pre>
  112. * &lt;property&gt;
  113. * &lt;name&gt;basedir&lt;/name&gt;
  114. * &lt;value&gt;/user/${<i>user.name</i>}&lt;/value&gt;
  115. * &lt;/property&gt;
  116. *
  117. * &lt;property&gt;
  118. * &lt;name&gt;tempdir&lt;/name&gt;
  119. * &lt;value&gt;${<i>basedir</i>}/tmp&lt;/value&gt;
  120. * &lt;/property&gt;</pre></tt>
  121. *
  122. * When <tt>conf.get("tempdir")</tt> is called, then <tt>${<i>basedir</i>}</tt>
  123. * will be resolved to another property in this Configuration, while
  124. * <tt>${<i>user.name</i>}</tt> would then ordinarily be resolved to the value
  125. * of the System property with that name.
  126. */
  127. //一大段注释。第一句说这个类是用来提供访问配置中属性的渠道
  128. //第二段话说配置文件的构造,XML文件中键值对。
  129. //第三段话说除非主动关闭,否则hadoop会默认加载一些默认的配置文件。并且可以“重载”
  130. //第四段说了配置文件中属性标记为final会怎么样
  131. //第五段说配置文件中的属性可以用变量来表示,可以不是具体的实值。还举了个例子。
  132. public class Configuration implements Iterable<Map.Entry<String,String>>,
  133. Writable {
  134. //实现了Iterable和Writable接口。
  135. //实现Iterable接口,可以调用Iterator()方法进行迭代
  136. //关于Map.Entry类,之前不了解。就是map的一种方便的遍历工具类
  137. //实现了Writable接口。hadoop没有采用Java的序列化(具体原因不解释),而是引入了自己的序列化系统,所有的
  138. //序列化对象都要实现writable接口。以后会遇到。
  139. private static final Log LOG =
  140. LogFactory.getLog(Configuration.class);
  141. //创建了一个日志类。并做了初始化
  142. private boolean quietmode = true;
  143. //布尔变量quietmode,“安静模式”,用来确定加载配置的时候日志的某些动作,
  144. //当为true的时候则在加载解析配置文件的过程中不输出日志信息,反之......
  145. /**
  146. * List of configuration resources.
  147. */
  148. private ArrayList<Object> resources = new ArrayList<Object>();
  149. //保存了所有通过addResource()方法添加的Configuration对象的资源
  150. /**
  151. * List of configuration parameters marked <b>final</b>.
  152. */
  153. private Set<String> finalParameters = new HashSet<String>();
  154. //用来保存所有在配置文件中已经被声明为final的键–值对的键
  155. private boolean loadDefaults = true;
  156. //是否加载默认的配置资源
  157. /**
  158. * Configuration objects
  159. */
  160. private static final WeakHashMap<Configuration,Object> REGISTRY =
  161. new WeakHashMap<Configuration,Object>();
  162. //REGISTRY是一个WeakHashMap的变量,key为Configuration,value为Object,
  163. //可以看出这个对象存储了不同对象的多个配置信息,弱HashMap可以自动清除不在正常使用的键对应的条目,
  164. //发现如果这个值是null会重新加载默认的配置文件中的信息
  165. /**
  166. * List of default Resources. Resources are loaded in the order of the list
  167. * entries
  168. */
  169. private static final CopyOnWriteArrayList<String> defaultResources =
  170. new CopyOnWriteArrayList<String>();
  171. //存放的是默认的配置信息,通过方法addDefaultResource()可以添加系统的默认资源
  172. //存储配置文件的名字而不是配置文件的全路径
  173. /**
  174. * Flag to indicate if the storage of resource which updates a key needs
  175. * to be stored for each key
  176. */
  177. private boolean storeResource;
  178. //是否需要更新配置文件的标识
  179. /**
  180. * Stores the mapping of key to the resource which modifies or loads
  181. * the key most recently
  182. */
  183. private HashMap<String, String> updatingResource;
  184. //保存所有需要更新的配置文件
  185. static{
  186. //print deprecation warning if hadoop-site.xml is found in classpath
  187. ClassLoader cL = Thread.currentThread().getContextClassLoader();
  188. if (cL == null) {
  189. cL = Configuration.class.getClassLoader();
  190. }
  191. if(cL.getResource("hadoop-site.xml")!=null) {
  192. LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
  193. "Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
  194. + "mapred-site.xml and hdfs-site.xml to override properties of " +
  195. "core-default.xml, mapred-default.xml and hdfs-default.xml " +
  196. "respectively");
  197. }
  198. addDefaultResource("core-default.xml");
  199. addDefaultResource("core-site.xml");
  200. }
  201. //静态代码块。加载了两个核心配置文件,一个是默认的,一个是用户自己配置的。
  202. //如果加载了hadoop-site.xml,则发个警告信息,说它不推荐用,以及推荐用哪个
  203. private Properties properties;
  204. //Hadoop配置文件解析后的键–值对,都存放在properties中
  205. private Properties overlay;
  206. //变量overlay用于记录通过set()方式改变的配置项。也就是说,出现在overlay中的键–值对是应用设置的,
  207. //而不是通过对配置资源解析得到的
  208. private ClassLoader classLoader;
  209. {
  210. classLoader = Thread.currentThread().getContextClassLoader();
  211. if (classLoader == null) {
  212. classLoader = Configuration.class.getClassLoader();
  213. }
  214. }
  215. //定义了一个类加载器,并做了初始化。非静态代码块
  216. /** A new configuration. */
  217. public Configuration() {
  218. this(true);
  219. }
  220. //相当于空构造方法,或者说调用空构造方法的时候默认调用默认配置文件
  221. /** A new configuration where the behavior of reading from the default
  222. * resources can be turned off.
  223. *
  224. * If the parameter {@code loadDefaults} is false, the new instance
  225. * will not load resources from the default files.
  226. * @param loadDefaults specifies whether to load from the default files
  227. */
  228. public Configuration(boolean loadDefaults) {
  229. this.loadDefaults = loadDefaults;
  230. if (LOG.isDebugEnabled()) {
  231. LOG.debug(StringUtils.stringifyException(new IOException("config()")));
  232. }
  233. synchronized(Configuration.class) {
  234. REGISTRY.put(this, null);
  235. }
  236. this.storeResource = false;
  237. }
  238. //构造方法。参数是是否加载默认配置文件
  239. /**
  240. * A new configuration with the same settings and additional facility for
  241. * storage of resource to each key which loads or updates
  242. * the key most recently
  243. * @param other the configuration from which to clone settings
  244. * @param storeResource flag to indicate if the storage of resource to
  245. * each key is to be stored
  246. */
  247. private Configuration(Configuration other, boolean storeResource) {
  248. this(other);
  249. this.loadDefaults = other.loadDefaults;
  250. this.storeResource = storeResource;
  251. if (storeResource) {
  252. updatingResource = new HashMap<String, String>();
  253. }
  254. }
  255. //构造方法。加载了一个新的配置文件和现有的配置文件具有相同的一些配置并有一些新的配置
  256. /**
  257. * A new configuration with the same settings cloned from another.
  258. *
  259. * @param other the configuration from which to clone settings.
  260. */
  261. @SuppressWarnings("unchecked")
  262. public Configuration(Configuration other) {
  263. if (LOG.isDebugEnabled()) {
  264. LOG.debug(StringUtils.stringifyException
  265. (new IOException("config(config)")));
  266. }
  267.  
  268. this.resources = (ArrayList)other.resources.clone();
  269. synchronized(other) {
  270. if (other.properties != null) {
  271. this.properties = (Properties)other.properties.clone();
  272. }
  273.  
  274. if (other.overlay!=null) {
  275. this.overlay = (Properties)other.overlay.clone();
  276. }
  277. }
  278.  
  279. this.finalParameters = new HashSet<String>(other.finalParameters);
  280. synchronized(Configuration.class) {
  281. REGISTRY.put(this, null);
  282. }
  283. }
  284. //构造方法。加载了一个全新的配置文件,并克隆了其属性
  285. /**
  286. * Add a default resource. Resources are loaded in the order of the resources
  287. * added.
  288. * @param name file name. File should be present in the classpath.
  289. */
  290. public static synchronized void addDefaultResource(String name) {
  291. if(!defaultResources.contains(name)) {
  292. defaultResources.add(name);
  293. for(Configuration conf : REGISTRY.keySet()) {
  294. if(conf.loadDefaults) {
  295. conf.reloadConfiguration();
  296. }
  297. }
  298. }
  299. }
  300. //加载默认配置文件方法
  301. /**
  302. * Add a configuration resource.
  303. *
  304. * The properties of this resource will override properties of previously
  305. * added resources, unless they were marked <a href="#Final">final</a>.
  306. *
  307. * @param name resource to be added, the classpath is examined for a file
  308. * with that name.
  309. */
  310. public void addResource(String name) {
  311. addResourceObject(name);
  312. }
  313.  
  314. /**
  315. * Add a configuration resource.
  316. *
  317. * The properties of this resource will override properties of previously
  318. * added resources, unless they were marked <a href="#Final">final</a>.
  319. *
  320. * @param url url of the resource to be added, the local filesystem is
  321. * examined directly to find the resource, without referring to
  322. * the classpath.
  323. */
  324. public void addResource(URL url) {
  325. addResourceObject(url);
  326. }
  327.  
  328. /**
  329. * Add a configuration resource.
  330. *
  331. * The properties of this resource will override properties of previously
  332. * added resources, unless they were marked <a href="#Final">final</a>.
  333. *
  334. * @param file file-path of resource to be added, the local filesystem is
  335. * examined directly to find the resource, without referring to
  336. * the classpath.
  337. */
  338. public void addResource(Path file) {
  339. addResourceObject(file);
  340. }
  341.  
  342. /**
  343. * Add a configuration resource.
  344. *
  345. * The properties of this resource will override properties of previously
  346. * added resources, unless they were marked <a href="#Final">final</a>.
  347. *
  348. * @param in InputStream to deserialize the object from.
  349. */
  350. public void addResource(InputStream in) {
  351. addResourceObject(in);
  352. }
  353. //Hadoop在创建配置类的时候,考虑了三种资源:
  354. //
  355. //URL资源(网络资源,指的是一个链接);
  356. //
  357. //CLASSPATH资源(String形式);
  358. //
  359. //Hadoop文件系统中的Path资源(该资源是基于Hadoop的FileSystem的,使用斜线“/”作为分隔符,如果是绝对路径,应该以“/”开始)
  360. /**
  361. * Reload configuration from previously added resources.
  362. *
  363. * This method will clear all the configuration read from the added
  364. * resources, and final parameters. This will make the resources to
  365. * be read again before accessing the values. Values that are added
  366. * via set methods will overlay values read from the resources.
  367. */
  368. public synchronized void reloadConfiguration() {
  369. properties = null; // trigger reload
  370. finalParameters.clear(); // clear site-limits
  371. }
  372. //重新加载先前加载过的配置资源。加载前会先清空。加了线程并发关键字哦
  373. private synchronized void addResourceObject(Object resource) {
  374. resources.add(resource); // add to resources
  375. reloadConfiguration();
  376. }
  377. //注意resource是Object类型。会触发配置的重新加载
  378. private static Pattern varPat = Pattern.compile("\\$\\{[^\\}\\$\u0020]+\\}");
  379. private static int MAX_SUBST = 20;
  380.  
  381. private String substituteVars(String expr) {
  382. if (expr == null) {
  383. return null;
  384. }
  385. Matcher match = varPat.matcher("");
  386. String eval = expr;
  387. for(int s=0; s<MAX_SUBST; s++) {
  388. match.reset(eval);
  389. if (!match.find()) {
  390. return eval;
  391. }
  392. String var = match.group();
  393. var = var.substring(2, var.length()-1); // remove ${ .. }
  394. String val = null;
  395. try {
  396. val = System.getProperty(var);
  397. } catch(SecurityException se) {
  398. LOG.warn("Unexpected SecurityException in Configuration", se);
  399. }
  400. if (val == null) {
  401. val = getRaw(var);
  402. }
  403. if (val == null) {
  404. return eval; // return literal ${var}: var is unbound
  405. }
  406. // substitute
  407. eval = eval.substring(0, match.start())+val+eval.substring(match.end());
  408. }
  409. throw new IllegalStateException("Variable substitution depth too large: "
  410. + MAX_SUBST + " " + expr);
  411. }
  412. //属性扩展属性和方法。
  413. //varPat对含有环境变量的值的进行转换的正则表达式对象;
  414. //MAX_SUBST是循环次数,为了避免死循环;
  415. //当循环次数过多的时候抛异常。
  416. /**
  417. * Get the value of the <code>name</code> property, <code>null</code> if
  418. * no such property exists.
  419. *
  420. * Values are processed for <a href="#VariableExpansion">variable expansion</a>
  421. * before being returned.
  422. *
  423. * @param name the property name.
  424. * @return the value of the <code>name</code> property,
  425. * or null if no such property exists.
  426. */
  427. public String get(String name) {
  428. return substituteVars(getProps().getProperty(name));
  429. }
  430.  
  431. /**
  432. * Get the value of the <code>name</code> property, without doing
  433. * <a href="#VariableExpansion">variable expansion</a>.
  434. *
  435. * @param name the property name.
  436. * @return the value of the <code>name</code> property,
  437. * or null if no such property exists.
  438. */
  439. public String getRaw(String name) {
  440. return getProps().getProperty(name);
  441. }
  442. //两种根据名称取得属性值的方法。没有这个属性就返回NULL。
  443. //区别是第一个会进行属性扩展,第二个不会
  444. /**
  445. * Set the <code>value</code> of the <code>name</code> property.
  446. *
  447. * @param name property name.
  448. * @param value property value.
  449. */
  450. public void set(String name, String value) {
  451. getOverlay().setProperty(name, value);
  452. getProps().setProperty(name, value);
  453. }
  454.  
  455. /**
  456. * Sets a property if it is currently unset.
  457. * @param name the property name
  458. * @param value the new value
  459. */
  460. public void setIfUnset(String name, String value) {
  461. if (get(name) == null) {
  462. set(name, value);
  463. }
  464. }
  465. //两种根据名称设置值得方法。区别不解释
  466. private synchronized Properties getOverlay() {
  467. if (overlay==null){
  468. overlay=new Properties();
  469. }
  470. return overlay;
  471. }
  472.  
  473. /**
  474. * Get the value of the <code>name</code> property. If no such property
  475. * exists, then <code>defaultValue</code> is returned.
  476. *
  477. * @param name property name.
  478. * @param defaultValue default value.
  479. * @return property value, or <code>defaultValue</code> if the property
  480. * doesn't exist.
  481. */
  482. public String get(String name, String defaultValue) {
  483. return substituteVars(getProps().getProperty(name, defaultValue));
  484. }
  485.  
  486. /**
  487. * Get the value of the <code>name</code> property as an <code>int</code>.
  488. *
  489. * If no such property exists, or if the specified value is not a valid
  490. * <code>int</code>, then <code>defaultValue</code> is returned.
  491. *
  492. * @param name property name.
  493. * @param defaultValue default value.
  494. * @return property value as an <code>int</code>,
  495. * or <code>defaultValue</code>.
  496. */
  497. public int getInt(String name, int defaultValue) {
  498. String valueString = get(name);
  499. if (valueString == null)
  500. return defaultValue;
  501. try {
  502. String hexString = getHexDigits(valueString);
  503. if (hexString != null) {
  504. return Integer.parseInt(hexString, 16);
  505. }
  506. return Integer.parseInt(valueString);
  507. } catch (NumberFormatException e) {
  508. return defaultValue;
  509. }
  510. }
  511.  
  512. /**
  513. * Set the value of the <code>name</code> property to an <code>int</code>.
  514. *
  515. * @param name property name.
  516. * @param value <code>int</code> value of the property.
  517. */
  518. public void setInt(String name, int value) {
  519. set(name, Integer.toString(value));
  520. }
  521.  
  522. /**
  523. * Get the value of the <code>name</code> property as a <code>long</code>.
  524. * If no such property is specified, or if the specified value is not a valid
  525. * <code>long</code>, then <code>defaultValue</code> is returned.
  526. *
  527. * @param name property name.
  528. * @param defaultValue default value.
  529. * @return property value as a <code>long</code>,
  530. * or <code>defaultValue</code>.
  531. */
  532. public long getLong(String name, long defaultValue) {
  533. String valueString = get(name);
  534. if (valueString == null)
  535. return defaultValue;
  536. try {
  537. String hexString = getHexDigits(valueString);
  538. if (hexString != null) {
  539. return Long.parseLong(hexString, 16);
  540. }
  541. return Long.parseLong(valueString);
  542. } catch (NumberFormatException e) {
  543. return defaultValue;
  544. }
  545. }
  546.  
  547. private String getHexDigits(String value) {
  548. boolean negative = false;
  549. String str = value;
  550. String hexString = null;
  551. if (value.startsWith("-")) {
  552. negative = true;
  553. str = value.substring(1);
  554. }
  555. if (str.startsWith("0x") || str.startsWith("0X")) {
  556. hexString = str.substring(2);
  557. if (negative) {
  558. hexString = "-" + hexString;
  559. }
  560. return hexString;
  561. }
  562. return null;
  563. }
  564.  
  565. /**
  566. * Set the value of the <code>name</code> property to a <code>long</code>.
  567. *
  568. * @param name property name.
  569. * @param value <code>long</code> value of the property.
  570. */
  571. public void setLong(String name, long value) {
  572. set(name, Long.toString(value));
  573. }
  574.  
  575. /**
  576. * Get the value of the <code>name</code> property as a <code>float</code>.
  577. * If no such property is specified, or if the specified value is not a valid
  578. * <code>float</code>, then <code>defaultValue</code> is returned.
  579. *
  580. * @param name property name.
  581. * @param defaultValue default value.
  582. * @return property value as a <code>float</code>,
  583. * or <code>defaultValue</code>.
  584. */
  585. public float getFloat(String name, float defaultValue) {
  586. String valueString = get(name);
  587. if (valueString == null)
  588. return defaultValue;
  589. try {
  590. return Float.parseFloat(valueString);
  591. } catch (NumberFormatException e) {
  592. return defaultValue;
  593. }
  594. }
  595. /**
  596. * Set the value of the <code>name</code> property to a <code>float</code>.
  597. *
  598. * @param name property name.
  599. * @param value property value.
  600. */
  601. public void setFloat(String name, float value) {
  602. set(name,Float.toString(value));
  603. }
  604.  
  605. /**
  606. * Get the value of the <code>name</code> property as a <code>boolean</code>.
  607. * If no such property is specified, or if the specified value is not a valid
  608. * <code>boolean</code>, then <code>defaultValue</code> is returned.
  609. *
  610. * @param name property name.
  611. * @param defaultValue default value.
  612. * @return property value as a <code>boolean</code>,
  613. * or <code>defaultValue</code>.
  614. */
  615. public boolean getBoolean(String name, boolean defaultValue) {
  616. String valueString = get(name);
  617. if ("true".equals(valueString))
  618. return true;
  619. else if ("false".equals(valueString))
  620. return false;
  621. else return defaultValue;
  622. }
  623.  
  624. /**
  625. * Set the value of the <code>name</code> property to a <code>boolean</code>.
  626. *
  627. * @param name property name.
  628. * @param value <code>boolean</code> value of the property.
  629. */
  630. public void setBoolean(String name, boolean value) {
  631. set(name, Boolean.toString(value));
  632. }
  633.  
  634. /**
  635. * Set the given property, if it is currently unset.
  636. * @param name property name
  637. * @param value new value
  638. */
  639. public void setBooleanIfUnset(String name, boolean value) {
  640. setIfUnset(name, Boolean.toString(value));
  641. }
  642.  
  643. /**
  644. * Set the value of the <code>name</code> property to the given type. This
  645. * is equivalent to <code>set(&lt;name&gt;, value.toString())</code>.
  646. * @param name property name
  647. * @param value new value
  648. */
  649. public <T extends Enum<T>> void setEnum(String name, T value) {
  650. set(name, value.toString());
  651. }
  652.  
  653. /**
  654. * Return value matching this enumerated type.
  655. * @param name Property name
  656. * @param defaultValue Value returned if no mapping exists
  657. * @throws IllegalArgumentException If mapping is illegal for the type
  658. * provided
  659. */
  660. public <T extends Enum<T>> T getEnum(String name, T defaultValue) {
  661. final String val = get(name);
  662. return null == val
  663. ? defaultValue
  664. : Enum.valueOf(defaultValue.getDeclaringClass(), val);
  665. }
  666. //hadoop常用类型的get/set方法,其中有的做了转换。
  667. /**
  668. * A class that represents a set of positive integer ranges. It parses
  669. * strings of the form: "2-3,5,7-" where ranges are separated by comma and
  670. * the lower/upper bounds are separated by dash. Either the lower or upper
  671. * bound may be omitted meaning all values up to or over. So the string
  672. * above means 2, 3, 5, and 7, 8, 9, ...
  673. */
  674. public static class IntegerRanges {
  675. private static class Range {
  676. int start;
  677. int end;
  678. }
  679.  
  680. List<Range> ranges = new ArrayList<Range>();
  681.  
  682. public IntegerRanges() {
  683. }
  684.  
  685. public IntegerRanges(String newValue) {
  686. StringTokenizer itr = new StringTokenizer(newValue, ",");
  687. while (itr.hasMoreTokens()) {
  688. String rng = itr.nextToken().trim();
  689. String[] parts = rng.split("-", 3);
  690. if (parts.length < 1 || parts.length > 2) {
  691. throw new IllegalArgumentException("integer range badly formed: " +
  692. rng);
  693. }
  694. Range r = new Range();
  695. r.start = convertToInt(parts[0], 0);
  696. if (parts.length == 2) {
  697. r.end = convertToInt(parts[1], Integer.MAX_VALUE);
  698. } else {
  699. r.end = r.start;
  700. }
  701. if (r.start > r.end) {
  702. throw new IllegalArgumentException("IntegerRange from " + r.start +
  703. " to " + r.end + " is invalid");
  704. }
  705. ranges.add(r);
  706. }
  707. }
  708. //嵌套类。所以org.apache.hadoop.conf包中有四个类。
  709. //解释一种字符串表示的整数范围。注释中有例子。
  710. /**
  711. * Convert a string to an int treating empty strings as the default value.
  712. * @param value the string value
  713. * @param defaultValue the value for if the string is empty
  714. * @return the desired integer
  715. */
  716. private static int convertToInt(String value, int defaultValue) {
  717. String trim = value.trim();
  718. if (trim.length() == 0) {
  719. return defaultValue;
  720. }
  721. return Integer.parseInt(trim);
  722. }
  723. //字符串转整数方法。如果是空的就是用默认值
  724. /**
  725. * Is the given value in the set of ranges
  726. * @param value the value to check
  727. * @return is the value in the ranges?
  728. */
  729. public boolean isIncluded(int value) {
  730. for(Range r: ranges) {
  731. if (r.start <= value && value <= r.end) {
  732. return true;
  733. }
  734. }
  735. return false;
  736. }
  737. //不解释
  738. @Override
  739. public String toString() {
  740. StringBuffer result = new StringBuffer();
  741. boolean first = true;
  742. for(Range r: ranges) {
  743. if (first) {
  744. first = false;
  745. } else {
  746. result.append(',');
  747. }
  748. result.append(r.start);
  749. result.append('-');
  750. result.append(r.end);
  751. }
  752. return result.toString();
  753. }
  754. }
  755. //重写了toString方法
  756. /**
  757. * Parse the given attribute as a set of integer ranges
  758. * @param name the attribute name
  759. * @param defaultValue the default value if it is not set
  760. * @return a new set of ranges from the configured value
  761. */
  762. public IntegerRanges getRange(String name, String defaultValue) {
  763. return new IntegerRanges(get(name, defaultValue));
  764. }
  765.  
  766. /**
  767. * Get the comma delimited values of the <code>name</code> property as
  768. * a collection of <code>String</code>s.
  769. * If no such property is specified then empty collection is returned.
  770. * <p>
  771. * This is an optimized version of {@link #getStrings(String)}
  772. *
  773. * @param name property name.
  774. * @return property value as a collection of <code>String</code>s.
  775. */
  776. public Collection<String> getStringCollection(String name) {
  777. String valueString = get(name);
  778. return StringUtils.getStringCollection(valueString);
  779. }
  780.  
  781. /**
  782. * Get the comma delimited values of the <code>name</code> property as
  783. * an array of <code>String</code>s.
  784. * If no such property is specified then <code>null</code> is returned.
  785. *
  786. * @param name property name.
  787. * @return property value as an array of <code>String</code>s,
  788. * or <code>null</code>.
  789. */
  790. public String[] getStrings(String name) {
  791. String valueString = get(name);
  792. return StringUtils.getStrings(valueString);
  793. }
  794.  
  795. /**
  796. * Get the comma delimited values of the <code>name</code> property as
  797. * an array of <code>String</code>s.
  798. * If no such property is specified then default value is returned.
  799. *
  800. * @param name property name.
  801. * @param defaultValue The default value
  802. * @return property value as an array of <code>String</code>s,
  803. * or default value.
  804. */
  805. public String[] getStrings(String name, String... defaultValue) {
  806. String valueString = get(name);
  807. if (valueString == null) {
  808. return defaultValue;
  809. } else {
  810. return StringUtils.getStrings(valueString);
  811. }
  812. }
  813.  
  814. /**
  815. * Set the array of string values for the <code>name</code> property as
  816. * as comma delimited values.
  817. *
  818. * @param name property name.
  819. * @param values The values
  820. */
  821. public void setStrings(String name, String... values) {
  822. set(name, StringUtils.arrayToString(values));
  823. }
  824.  
  825. /**
  826. * Load a class by name.
  827. *
  828. * @param name the class name.
  829. * @return the class object.
  830. * @throws ClassNotFoundException if the class is not found.
  831. */
  832. public Class<?> getClassByName(String name) throws ClassNotFoundException {
  833. return Class.forName(name, true, classLoader);
  834. }
  835.  
  836. /**
  837. * Get the value of the <code>name</code> property
  838. * as an array of <code>Class</code>.
  839. * The value of the property specifies a list of comma separated class names.
  840. * If no such property is specified, then <code>defaultValue</code> is
  841. * returned.
  842. *
  843. * @param name the property name.
  844. * @param defaultValue default value.
  845. * @return property value as a <code>Class[]</code>,
  846. * or <code>defaultValue</code>.
  847. */
  848. public Class<?>[] getClasses(String name, Class<?> ... defaultValue) {
  849. String[] classnames = getStrings(name);
  850. if (classnames == null)
  851. return defaultValue;
  852. try {
  853. Class<?>[] classes = new Class<?>[classnames.length];
  854. for(int i = 0; i < classnames.length; i++) {
  855. classes[i] = getClassByName(classnames[i]);
  856. }
  857. return classes;
  858. } catch (ClassNotFoundException e) {
  859. throw new RuntimeException(e);
  860. }
  861. }
  862.  
  863. /**
  864. * Get the value of the <code>name</code> property as a <code>Class</code>.
  865. * If no such property is specified, then <code>defaultValue</code> is
  866. * returned.
  867. *
  868. * @param name the class name.
  869. * @param defaultValue default value.
  870. * @return property value as a <code>Class</code>,
  871. * or <code>defaultValue</code>.
  872. */
  873. public Class<?> getClass(String name, Class<?> defaultValue) {
  874. String valueString = get(name);
  875. if (valueString == null)
  876. return defaultValue;
  877. try {
  878. return getClassByName(valueString);
  879. } catch (ClassNotFoundException e) {
  880. throw new RuntimeException(e);
  881. }
  882. }
  883.  
  884. /**
  885. * Get the value of the <code>name</code> property as a <code>Class</code>
  886. * implementing the interface specified by <code>xface</code>.
  887. *
  888. * If no such property is specified, then <code>defaultValue</code> is
  889. * returned.
  890. *
  891. * An exception is thrown if the returned class does not implement the named
  892. * interface.
  893. *
  894. * @param name the class name.
  895. * @param defaultValue default value.
  896. * @param xface the interface implemented by the named class.
  897. * @return property value as a <code>Class</code>,
  898. * or <code>defaultValue</code>.
  899. */
  900. public <U> Class<? extends U> getClass(String name,
  901. Class<? extends U> defaultValue,
  902. Class<U> xface) {
  903. try {
  904. Class<?> theClass = getClass(name, defaultValue);
  905. if (theClass != null && !xface.isAssignableFrom(theClass))
  906. throw new RuntimeException(theClass+" not "+xface.getName());
  907. else if (theClass != null)
  908. return theClass.asSubclass(xface);
  909. else
  910. return null;
  911. } catch (Exception e) {
  912. throw new RuntimeException(e);
  913. }
  914. }
  915.  
  916. /**
  917. * Set the value of the <code>name</code> property to the name of a
  918. * <code>theClass</code> implementing the given interface <code>xface</code>.
  919. *
  920. * An exception is thrown if <code>theClass</code> does not implement the
  921. * interface <code>xface</code>.
  922. *
  923. * @param name property name.
  924. * @param theClass property value.
  925. * @param xface the interface implemented by the named class.
  926. */
  927. public void setClass(String name, Class<?> theClass, Class<?> xface) {
  928. if (!xface.isAssignableFrom(theClass))
  929. throw new RuntimeException(theClass+" not "+xface.getName());
  930. set(name, theClass.getName());
  931. }
  932.  
  933. /**
  934. * Get a local file under a directory named by <i>dirsProp</i> with
  935. * the given <i>path</i>. If <i>dirsProp</i> contains multiple directories,
  936. * then one is chosen based on <i>path</i>'s hash code. If the selected
  937. * directory does not exist, an attempt is made to create it.
  938. *
  939. * @param dirsProp directory in which to locate the file.
  940. * @param path file-path.
  941. * @return local file under the directory with the given path.
  942. */
  943. public Path getLocalPath(String dirsProp, String path)
  944. throws IOException {
  945. String[] dirs = getStrings(dirsProp);
  946. int hashCode = path.hashCode();
  947. FileSystem fs = FileSystem.getLocal(this);
  948. for (int i = 0; i < dirs.length; i++) { // try each local dir
  949. int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;
  950. Path file = new Path(dirs[index], path);
  951. Path dir = file.getParent();
  952. if (fs.mkdirs(dir) || fs.exists(dir)) {
  953. return file;
  954. }
  955. }
  956. LOG.warn("Could not make " + path +
  957. " in local directories from " + dirsProp);
  958. for(int i=0; i < dirs.length; i++) {
  959. int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;
  960. LOG.warn(dirsProp + "[" + index + "]=" + dirs[index]);
  961. }
  962. throw new IOException("No valid local directories in property: "+dirsProp);
  963. }
  964. //从指定路径中获取需要的本地路径。刚开始有点迷惑,注释读的迷迷糊糊,但是网上对这个方法介绍不多
  965. //后来查到它的作用时才理解了。它大部分用在taskTracker上,当任务分发时用到的,因为配置文件要拷贝
  966. //到本地,临时输出也在本地,不在HDFS上,所以就跟Local文件系统有了交集。下面的这个方法也一样。
  967. /**
  968. * Get a local file name under a directory named in <i>dirsProp</i> with
  969. * the given <i>path</i>. If <i>dirsProp</i> contains multiple directories,
  970. * then one is chosen based on <i>path</i>'s hash code. If the selected
  971. * directory does not exist, an attempt is made to create it.
  972. *
  973. * @param dirsProp directory in which to locate the file.
  974. * @param path file-path.
  975. * @return local file under the directory with the given path.
  976. */
  977. public File getFile(String dirsProp, String path)
  978. throws IOException {
  979. String[] dirs = getStrings(dirsProp);
  980. int hashCode = path.hashCode();
  981. for (int i = 0; i < dirs.length; i++) { // try each local dir
  982. int index = (hashCode+i & Integer.MAX_VALUE) % dirs.length;
  983. File file = new File(dirs[index], path);
  984. File dir = file.getParentFile();
  985. if (dir.exists() || dir.mkdirs()) {
  986. return file;
  987. }
  988. }
  989. throw new IOException("No valid local directories in property: "+dirsProp);
  990. }
  991. //跟上一个方法差不多,只不过路径变成了文件。
  992. /**
  993. * Get the {@link URL} for the named resource.
  994. *
  995. * @param name resource name.
  996. * @return the url for the named resource.
  997. */
  998. public URL getResource(String name) {
  999. return classLoader.getResource(name);
  1000. }
  1001. //根据名称获取资源URL链接
  1002. /**
  1003. * Get an input stream attached to the configuration resource with the
  1004. * given <code>name</code>.
  1005. *
  1006. * @param name configuration resource name.
  1007. * @return an input stream attached to the resource.
  1008. */
  1009. public InputStream getConfResourceAsInputStream(String name) {
  1010. try {
  1011. URL url= getResource(name);
  1012.  
  1013. if (url == null) {
  1014. LOG.info(name + " not found");
  1015. return null;
  1016. } else {
  1017. LOG.info("found resource " + name + " at " + url);
  1018. }
  1019.  
  1020. return url.openStream();
  1021. } catch (Exception e) {
  1022. return null;
  1023. }
  1024. }
  1025. //从上个方法获取的URL链接开启一个输入流。从这可以看出这两个方法都是用在配置文件上的
  1026. //看起来是废话,但是读第一个方法的时候不太确定。
  1027. /**
  1028. * Get a {@link Reader} attached to the configuration resource with the
  1029. * given <code>name</code>.
  1030. *
  1031. * @param name configuration resource name.
  1032. * @return a reader attached to the resource.
  1033. */
  1034. public Reader getConfResourceAsReader(String name) {
  1035. try {
  1036. URL url= getResource(name);
  1037.  
  1038. if (url == null) {
  1039. LOG.info(name + " not found");
  1040. return null;
  1041. } else {
  1042. LOG.info("found resource " + name + " at " + url);
  1043. }
  1044.  
  1045. return new InputStreamReader(url.openStream());
  1046. } catch (Exception e) {
  1047. return null;
  1048. }
  1049. }
  1050. //同上,做了封装
  1051. private synchronized Properties getProps() {
  1052. if (properties == null) {
  1053. properties = new Properties();
  1054. loadResources(properties, resources, quietmode);
  1055. if (overlay!= null) {
  1056. properties.putAll(overlay);
  1057. if (storeResource) {
  1058. for (Map.Entry<Object,Object> item: overlay.entrySet()) {
  1059. updatingResource.put((String) item.getKey(), "Unknown");
  1060. }
  1061. }
  1062. }
  1063. }
  1064. return properties;
  1065. }
  1066. //加载所有键值对,如果为空,则重新加载,包括已经更改过的。
  1067. //最后一个if包含的代码不是很懂,求大牛解释
  1068. /**
  1069. * Return the number of keys in the configuration.
  1070. *
  1071. * @return number of keys in the configuration.
  1072. */
  1073. public int size() {
  1074. return getProps().size();
  1075. }
  1076. //获取所有键值对的数量
  1077. /**
  1078. * Clears all keys from the configuration.
  1079. */
  1080. public void clear() {
  1081. getProps().clear();
  1082. getOverlay().clear();
  1083. }
  1084. //清空
  1085. /**
  1086. * Get an {@link Iterator} to go through the list of <code>String</code>
  1087. * key-value pairs in the configuration.
  1088. *
  1089. * @return an iterator over the entries.
  1090. */
  1091. public Iterator<Map.Entry<String, String>> iterator() {
  1092. // Get a copy of just the string to string pairs. After the old object
  1093. // methods that allow non-strings to be put into configurations are removed,
  1094. // we could replace properties with a Map<String,String> and get rid of this
  1095. // code.
  1096. Map<String,String> result = new HashMap<String,String>();
  1097. for(Map.Entry<Object,Object> item: getProps().entrySet()) {
  1098. if (item.getKey() instanceof String &&
  1099. item.getValue() instanceof String) {
  1100. result.put((String) item.getKey(), (String) item.getValue());
  1101. }
  1102. }
  1103. return result.entrySet().iterator();
  1104. }
  1105. //获取所有键值对的迭代接口
  1106. private void loadResources(Properties properties,
  1107. ArrayList resources,
  1108. boolean quiet) {
  1109. if(loadDefaults) {
  1110. for (String resource : defaultResources) {
  1111. loadResource(properties, resource, quiet);
  1112. }
  1113.  
  1114. //support the hadoop-site.xml as a deprecated case
  1115. if(getResource("hadoop-site.xml")!=null) {
  1116. loadResource(properties, "hadoop-site.xml", quiet);
  1117. }
  1118. }
  1119.  
  1120. for (Object resource : resources) {
  1121. loadResource(properties, resource, quiet);
  1122. }
  1123. }
  1124.  
  1125. private void loadResource(Properties properties, Object name, boolean quiet) {
  1126. try {
  1127. DocumentBuilderFactory docBuilderFactory
  1128. = DocumentBuilderFactory.newInstance();
  1129. //ignore all comments inside the xml file
  1130. docBuilderFactory.setIgnoringComments(true);
  1131.  
  1132. //allow includes in the xml file
  1133. docBuilderFactory.setNamespaceAware(true);
  1134. try {
  1135. docBuilderFactory.setXIncludeAware(true);
  1136. } catch (UnsupportedOperationException e) {
  1137. LOG.error("Failed to set setXIncludeAware(true) for parser "
  1138. + docBuilderFactory
  1139. + ":" + e,
  1140. e);
  1141. }
  1142. DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
  1143. Document doc = null;
  1144. Element root = null;
  1145.  
  1146. if (name instanceof URL) { // an URL resource
  1147. URL url = (URL)name;
  1148. if (url != null) {
  1149. if (!quiet) {
  1150. LOG.info("parsing " + url);
  1151. }
  1152. doc = builder.parse(url.toString());
  1153. }
  1154. } else if (name instanceof String) { // a CLASSPATH resource
  1155. URL url = getResource((String)name);
  1156. if (url != null) {
  1157. if (!quiet) {
  1158. LOG.info("parsing " + url);
  1159. }
  1160. doc = builder.parse(url.toString());
  1161. }
  1162. } else if (name instanceof Path) { // a file resource
  1163. // Can't use FileSystem API or we get an infinite loop
  1164. // since FileSystem uses Configuration API. Use java.io.File instead.
  1165. File file = new File(((Path)name).toUri().getPath())
  1166. .getAbsoluteFile();
  1167. if (file.exists()) {
  1168. if (!quiet) {
  1169. LOG.info("parsing " + file);
  1170. }
  1171. InputStream in = new BufferedInputStream(new FileInputStream(file));
  1172. try {
  1173. doc = builder.parse(in);
  1174. } finally {
  1175. in.close();
  1176. }
  1177. }
  1178. } else if (name instanceof InputStream) {
  1179. try {
  1180. doc = builder.parse((InputStream)name);
  1181. } finally {
  1182. ((InputStream)name).close();
  1183. }
  1184. } else if (name instanceof Element) {
  1185. root = (Element)name;
  1186. }
  1187.  
  1188. if (doc == null && root == null) {
  1189. if (quiet)
  1190. return;
  1191. throw new RuntimeException(name + " not found");
  1192. }
  1193.  
  1194. if (root == null) {
  1195. root = doc.getDocumentElement();
  1196. }
  1197. if (!"configuration".equals(root.getTagName()))
  1198. LOG.fatal("bad conf file: top-level element not <configuration>");
  1199. NodeList props = root.getChildNodes();
  1200. for (int i = 0; i < props.getLength(); i++) {
  1201. Node propNode = props.item(i);
  1202. if (!(propNode instanceof Element))
  1203. continue;
  1204. Element prop = (Element)propNode;
  1205. if ("configuration".equals(prop.getTagName())) {
  1206. loadResource(properties, prop, quiet);
  1207. continue;
  1208. }
  1209. if (!"property".equals(prop.getTagName()))
  1210. LOG.warn("bad conf file: element not <property>");
  1211. NodeList fields = prop.getChildNodes();
  1212. String attr = null;
  1213. String value = null;
  1214. boolean finalParameter = false;
  1215. for (int j = 0; j < fields.getLength(); j++) {
  1216. Node fieldNode = fields.item(j);
  1217. if (!(fieldNode instanceof Element))
  1218. continue;
  1219. Element field = (Element)fieldNode;
  1220. if ("name".equals(field.getTagName()) && field.hasChildNodes())
  1221. attr = ((Text)field.getFirstChild()).getData().trim();
  1222. if ("value".equals(field.getTagName()) && field.hasChildNodes())
  1223. value = ((Text)field.getFirstChild()).getData();
  1224. if ("final".equals(field.getTagName()) && field.hasChildNodes())
  1225. finalParameter = "true".equals(((Text)field.getFirstChild()).getData());
  1226. }
  1227.  
  1228. // Ignore this parameter if it has already been marked as 'final'
  1229. if (attr != null) {
  1230. if (value != null) {
  1231. if (!finalParameters.contains(attr)) {
  1232. properties.setProperty(attr, value);
  1233. if (storeResource) {
  1234. updatingResource.put(attr, name.toString());
  1235. }
  1236. } else if (!value.equals(properties.getProperty(attr))) {
  1237. LOG.warn(name+":a attempt to override final parameter: "+attr
  1238. +"; Ignoring.");
  1239. }
  1240. }
  1241. if (finalParameter) {
  1242. finalParameters.add(attr);
  1243. }
  1244. }
  1245. }
  1246.  
  1247. } catch (IOException e) {
  1248. LOG.fatal("error parsing conf file: " + e);
  1249. throw new RuntimeException(e);
  1250. } catch (DOMException e) {
  1251. LOG.fatal("error parsing conf file: " + e);
  1252. throw new RuntimeException(e);
  1253. } catch (SAXException e) {
  1254. LOG.fatal("error parsing conf file: " + e);
  1255. throw new RuntimeException(e);
  1256. } catch (ParserConfigurationException e) {
  1257. LOG.fatal("error parsing conf file: " + e);
  1258. throw new RuntimeException(e);
  1259. }
  1260. }
  1261. //从配置文件中获取所有键值对
  1262. /**
  1263. * Write out the non-default properties in this configuration to the give
  1264. * {@link OutputStream}.
  1265. *
  1266. * @param out the output stream to write to.
  1267. */
  1268. public void writeXml(OutputStream out) throws IOException {
  1269. Properties properties = getProps();
  1270. try {
  1271. Document doc =
  1272. DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
  1273. Element conf = doc.createElement("configuration");
  1274. doc.appendChild(conf);
  1275. conf.appendChild(doc.createTextNode("\n"));
  1276. for (Enumeration e = properties.keys(); e.hasMoreElements();) {
  1277. String name = (String)e.nextElement();
  1278. Object object = properties.get(name);
  1279. String value = null;
  1280. if (object instanceof String) {
  1281. value = (String) object;
  1282. }else {
  1283. continue;
  1284. }
  1285. Element propNode = doc.createElement("property");
  1286. conf.appendChild(propNode);
  1287.  
  1288. Element nameNode = doc.createElement("name");
  1289. nameNode.appendChild(doc.createTextNode(name));
  1290. propNode.appendChild(nameNode);
  1291.  
  1292. Element valueNode = doc.createElement("value");
  1293. valueNode.appendChild(doc.createTextNode(value));
  1294. propNode.appendChild(valueNode);
  1295.  
  1296. conf.appendChild(doc.createTextNode("\n"));
  1297. }
  1298.  
  1299. DOMSource source = new DOMSource(doc);
  1300. StreamResult result = new StreamResult(out);
  1301. TransformerFactory transFactory = TransformerFactory.newInstance();
  1302. Transformer transformer = transFactory.newTransformer();
  1303. transformer.transform(source, result);
  1304. } catch (Exception e) {
  1305. throw new RuntimeException(e);
  1306. }
  1307. }
  1308. //把所有非默认配置的配置按XML的形式输出到给定的输出流上
  1309. /**
  1310. * Writes out all the parameters and their properties (final and resource) to
  1311. * the given {@link Writer}
  1312. * The format of the output would be
  1313. * { "properties" : [ {key1,value1,key1.isFinal,key1.resource}, {key2,value2,
  1314. * key2.isFinal,key2.resource}... ] }
  1315. * It does not output the parameters of the configuration object which is
  1316. * loaded from an input stream.
  1317. * @param out the Writer to write to
  1318. * @throws IOException
  1319. */
  1320. public static void dumpConfiguration(Configuration conf,
  1321. Writer out) throws IOException {
  1322. Configuration config = new Configuration(conf,true);
  1323. config.reloadConfiguration();
  1324. JsonFactory dumpFactory = new JsonFactory();
  1325. JsonGenerator dumpGenerator = dumpFactory.createJsonGenerator(out);
  1326. dumpGenerator.writeStartObject();
  1327. dumpGenerator.writeFieldName("properties");
  1328. dumpGenerator.writeStartArray();
  1329. dumpGenerator.flush();
  1330. for (Map.Entry<Object,Object> item: config.getProps().entrySet()) {
  1331. dumpGenerator.writeStartObject();
  1332. dumpGenerator.writeStringField("key", (String) item.getKey());
  1333. dumpGenerator.writeStringField("value",
  1334. config.get((String) item.getKey()));
  1335. dumpGenerator.writeBooleanField("isFinal",
  1336. config.finalParameters.contains(item.getKey()));
  1337. dumpGenerator.writeStringField("resource",
  1338. config.updatingResource.get(item.getKey()));
  1339. dumpGenerator.writeEndObject();
  1340. }
  1341. dumpGenerator.writeEndArray();
  1342. dumpGenerator.writeEndObject();
  1343. dumpGenerator.flush();
  1344. }
  1345. //把所有配置属性按某种格式导出来到指定输出流上
  1346. //注释中说不包括通过输入流配置的属性,就是说只导出文件的,从几个用到的地方也只看到了文件
  1347. //这里不太确定。
  1348. /**
  1349. * Get the {@link ClassLoader} for this job.
  1350. *
  1351. * @return the correct class loader.
  1352. */
  1353. public ClassLoader getClassLoader() {
  1354. return classLoader;
  1355. }
  1356.  
  1357. /**
  1358. * Set the class loader that will be used to load the various objects.
  1359. *
  1360. * @param classLoader the new class loader.
  1361. */
  1362. public void setClassLoader(ClassLoader classLoader) {
  1363. this.classLoader = classLoader;
  1364. }
  1365.  
  1366. @Override
  1367. public String toString() {
  1368. StringBuffer sb = new StringBuffer();
  1369. sb.append("Configuration: ");
  1370. if(loadDefaults) {
  1371. toString(defaultResources, sb);
  1372. if(resources.size()>0) {
  1373. sb.append(", ");
  1374. }
  1375. }
  1376. toString(resources, sb);
  1377. return sb.toString();
  1378. }
  1379.  
  1380. private void toString(List resources, StringBuffer sb) {
  1381. ListIterator i = resources.listIterator();
  1382. while (i.hasNext()) {
  1383. if (i.nextIndex() != 0) {
  1384. sb.append(", ");
  1385. }
  1386. sb.append(i.next());
  1387. }
  1388. }
  1389.  
  1390. /**
  1391. * Set the quietness-mode.
  1392. *
  1393. * In the quiet-mode, error and informational messages might not be logged.
  1394. *
  1395. * @param quietmode <code>true</code> to set quiet-mode on, <code>false</code>
  1396. * to turn it off.
  1397. */
  1398. public synchronized void setQuietMode(boolean quietmode) {
  1399. this.quietmode = quietmode;
  1400. }
  1401.  
  1402. /** For debugging. List non-default properties to the terminal and exit. */
  1403. public static void main(String[] args) throws Exception {
  1404. new Configuration().writeXml(System.out);
  1405. }
  1406.  
  1407. @Override
  1408. public void readFields(DataInput in) throws IOException {
  1409. clear();
  1410. int size = WritableUtils.readVInt(in);
  1411. for(int i=0; i < size; ++i) {
  1412. set(org.apache.hadoop.io.Text.readString(in),
  1413. org.apache.hadoop.io.Text.readString(in));
  1414. }
  1415. }
  1416. //序列化方法。把RPC中的流序列化成“对象”,这个方法是@Override的,所以对象就是配置属性
  1417. //set前调用了clear(),这个方法是本类的方法,然后clear()方法调用了HashTable的clear()方法,把所有配置全清了
  1418. //@Override
  1419. public void write(DataOutput out) throws IOException {
  1420. Properties props = getProps();
  1421. WritableUtils.writeVInt(out, props.size());
  1422. for(Map.Entry<Object, Object> item: props.entrySet()) {
  1423. org.apache.hadoop.io.Text.writeString(out, (String) item.getKey());
  1424. org.apache.hadoop.io.Text.writeString(out, (String) item.getValue());
  1425. }
  1426. }
  1427. //序列化方法。把对象序列化为RPC的流
  1428. /**
  1429. * get keys matching the the regex
  1430. * @param regex
  1431. * @return Map<String,String> with matching keys
  1432. */
  1433. public Map<String,String> getValByRegex(String regex) {
  1434. Pattern p = Pattern.compile(regex);
  1435.  
  1436. Map<String,String> result = new HashMap<String,String>();
  1437. Matcher m;
  1438.  
  1439. for(Map.Entry<Object,Object> item: getProps().entrySet()) {
  1440. if (item.getKey() instanceof String &&
  1441. item.getValue() instanceof String) {
  1442. m = p.matcher((String)item.getKey());
  1443. if(m.find()) { // match
  1444. result.put((String) item.getKey(), (String) item.getValue());
  1445. }
  1446. }
  1447. }
  1448. return result;
  1449. }
  1450. }
  1451. //通过正则获取键值对集合

  


  


MapReduce的执行简单流程:用户作业执行JobClient.runJob(conf)代码会在Hadoop集群上将其启动。启动之后JobClient实例会向JobTracker获取JobId,而且客户端会将作业执行需要的作业资源复制到HDFS上,然后将作业提交给JobTracker。JobTracker在本地初始化作业,再从HDFS作业资源中获取作业输入的分割信息,根据这些信息JobTracker将作业分割成多个任务,然后分配给在于JobTracker心跳通信中请求任务的Tasktracker。TaskTracker接收到新的任务之后会先从HDFS上获取作业资源,包括作业配置信息和本作业分片输入,然后在本地启动一个JVM并执行任务。任务结束后将结果写回HDFS,并向JobTracker报告。


有些东西我说的不太明白,这里借鉴别人的

http://anyoneking.com/archives/212

http://f.dataguru.cn/thread-258563-1-1.html


原来JDK的源码包在JDK安装文件夹中,只要把src.zip解压就能用eclipse去attached source了。我这个井底蛙。


即使这样逐个看它的变量和方法,也给人一种雾里看花,不识庐山真面目的感觉。

要真正熟悉了hadoop的启动过程,过程中对配置的API调用和相关处理过程才能彻底理解这个类。

我还不够格,在网上查了也只是跟着别的思路走,期待后面自己体验和调试来融会贯通。


org.apache.hadoop.conf-Configuration的更多相关文章

  1. org.apache.hadoop.conf.Configuration无法引用 解决方法

    我用的是Hadoop-common 2.6.4jar,可是明明包里面有这个类却引用不了,然后我看了下包里面是一个抽象类......................................... ...

  2. 加载hive-jdbc driver时报错:java.lang.NoClassDefFoundError: org/apache/hadoop/conf/Configuration

    这是因为缺少一个hadoop-common包,引入即可: <dependency> <groupId>org.apache.hadoop</groupId> < ...

  3. hadoop 出现FATAL conf.Configuration: error parsing conf file,异常

    FATAL conf.Configuration: error parsing conf file: com.sun.org.apache.xerces.internal.impl.io.Malfor ...

  4. ERROR [org.apache.hadoop.security.UserGroupInformation] - PriviledgedActionExcep

    换了个环境,出现此异常 016-10-18 23:54:01,334 WARN [org.apache.hadoop.util.NativeCodeLoader] - Unable to load n ...

  5. 使用eclipse的快捷键自动生成的map或者reduce函数的参数中:“org.apache.hadoop.mapreduce.Reducer.Context context”

    今天在测试mapreduce的程序时,就是简单的去重,对照课本上的程序和自己的程序,唯一不同的就是“org.apache.hadoop.mapreduce.Reducer.Context contex ...

  6. 用java运行Hadoop程序报错:org.apache.hadoop.fs.LocalFileSystem cannot be cast to org.apache.

    用java运行Hadoop例程报错:org.apache.hadoop.fs.LocalFileSystem cannot be cast to org.apache.所写代码如下: package ...

  7. 报错org.apache.hadoop.mapreduce.lib.input.FileSplit cannot be cast to org.apache.hadoop.mapred.FileSplit

    报错 java.lang.Exception: java.lang.ClassCastException: org.apache.hadoop.mapreduce.lib.input.FileSpli ...

  8. org.apache.hadoop.hbase.MasterNotRunningException解决策略

    执行HBase时常会遇到个错误,我就有这种经历. ERROR: org.apache.hadoop.hbase.MasterNotRunningException: Retried 7 times 检 ...

  9. 访问HDFS报错:org.apache.hadoop.security.AccessControlException: Permission denied

    import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apac ...

  10. ERROR [org.apache.hadoop.util.Shell] - Failed to locate the winutils binary in the hadoop binary path

    错误日志如下: -- ::, DEBUG [org.apache.hadoop.metrics2.lib.MutableMetricsFactory] - field org.apache.hadoo ...

随机推荐

  1. linux 从命令行自动识别文件并将其打开的命令

    若是shell是 zsh,则可: 使用 alias -s 定义后缀别名 (zsh) % alias -s pl=perl % script.pl perl script.pl % alias -s p ...

  2. TransactionScope事务对多个数据库的操作

    .Net 2.0引入了轻量级事务管理器(Lighweight Transaction Manager),即System.Transactions.TransactionManager. 轻量级事务管理 ...

  3. Hadoop学习笔记(2)

    Hadoop学习笔记(2) ——解读Hello World 上一章中,我们把hadoop下载.安装.运行起来,最后还执行了一个Hello world程序,看到了结果.现在我们就来解读一下这个Hello ...

  4. UVALive 7077 - Little Zu Chongzhi's Triangles(暴力)

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  5. hdu 1155 Bungee Jumping

    http://acm.hdu.edu.cn/showproblem.php?pid=1155 Bungee Jumping Time Limit: 2000/1000 MS (Java/Others) ...

  6. CodeForces 711A Bus to Udayland (水题)

    题意:给定一个n*4的矩阵,然后O表示空座位,X表示已经有人了,问你是不能找到一对相邻的座位,都是空的,并且前两个是一对,后两个是一对. 析:直接暴力找就行. 代码如下: #pragma commen ...

  7. thinkPHP 无法create,无法插入数据,提示非法数据对象

    4.thinkPHP 无法create,提示非法数据对象解决方法:不要create+add,而用 data[]= '';+add$m_r_fa_account = D('R_fa_account'); ...

  8. .net 学习资源(转)

      名称:快速入门地址:http://chs.gotdotnet.com/quickstart/描述:本站点是微软.NET技术的快速入门网站,我们不必再安装.NET Framework中的快速入门示例 ...

  9. js判断滚动方向

     //页面滚动监听事件     window.onscroll = function (e) {                scrollFunc();         $("#t&quo ...

  10. Linux编译安装RTL8192CU芯片驱动,使用TP_LINK wn823n无线网卡

    前几天给自己的台式电脑安装了Window 7+CentOS 6.4 Linux双系统,发现在Windows 7下面可以正常使用TP_LINK wn823n无线网卡来连接无线网络,但是在Linux下面, ...