From cfb96367814acb7f815498559a79836dfce14328 Mon Sep 17 00:00:00 2001 From: Owen O'Malley Date: Fri, 19 Jun 2009 23:39:51 +0000 Subject: [PATCH] HADOOP-4687. Pulling trunk docs to branch git-svn-id: https://svn.apache.org/repos/asf/hadoop/core/branches/HADOOP-4687/core@786720 13f79535-47bb-0310-9956-ffa450edef68 --- src/docs/changes/ChangesFancyStyle.css | 170 + src/docs/changes/ChangesSimpleStyle.css | 49 + src/docs/changes/changes2html.pl | 282 ++ src/docs/cn/changes/ChangesFancyStyle.css | 170 + src/docs/cn/changes/ChangesSimpleStyle.css | 49 + src/docs/cn/changes/changes2html.pl | 282 ++ src/docs/cn/forrest.properties | 109 + src/docs/cn/src/documentation/README.txt | 7 + .../classes/CatalogManager.properties | 40 + src/docs/cn/src/documentation/conf/cli.xconf | 327 ++ .../content/xdocs/cluster_setup.xml | 386 ++ .../content/xdocs/commands_manual.xml | 596 ++++ .../documentation/content/xdocs/distcp.xml | 294 ++ .../content/xdocs/hadoop_archives.xml | 69 + .../content/xdocs/hdfs_design.xml | 376 ++ .../content/xdocs/hdfs_permissions_guide.xml | 193 + .../content/xdocs/hdfs_quota_admin_guide.xml | 72 + .../content/xdocs/hdfs_shell.xml | 477 +++ .../content/xdocs/hdfs_user_guide.xml | 513 +++ .../src/documentation/content/xdocs/hod.xml | 46 + .../content/xdocs/hod_admin_guide.xml | 237 ++ .../content/xdocs/hod_config_guide.xml | 158 + .../content/xdocs/hod_user_guide.xml | 559 +++ .../src/documentation/content/xdocs/index.xml | 46 + .../content/xdocs/mapred_tutorial.xml | 2466 +++++++++++++ .../content/xdocs/native_libraries.xml | 230 ++ .../content/xdocs/quickstart.xml | 252 ++ .../src/documentation/content/xdocs/site.xml | 249 ++ .../documentation/content/xdocs/streaming.xml | 618 ++++ .../src/documentation/content/xdocs/tabs.xml | 37 + .../resources/images/architecture.gif | Bin 0 -> 15461 bytes .../resources/images/core-logo.gif | Bin 0 -> 6665 bytes .../resources/images/favicon.ico | Bin 0 -> 766 bytes .../resources/images/hadoop-logo-big.jpg | Bin 0 -> 127869 bytes .../resources/images/hadoop-logo.jpg | Bin 0 -> 9443 bytes .../resources/images/hdfsarchitecture.gif | Bin 0 -> 17653 bytes .../resources/images/hdfsarchitecture.odg | Bin 0 -> 41298 bytes .../resources/images/hdfsarchitecture.png | Bin 0 -> 40571 bytes .../resources/images/hdfsdatanodes.gif | Bin 0 -> 16060 bytes .../resources/images/hdfsdatanodes.odg | Bin 0 -> 37296 bytes .../resources/images/hdfsdatanodes.png | Bin 0 -> 30012 bytes src/docs/cn/src/documentation/skinconf.xml | 346 ++ .../skins/common/css/forrest.css.xslt | 78 + .../skins/common/images/README.txt | 1 + .../documentation/skins/common/images/add.jpg | Bin 0 -> 1142 bytes .../images/built-with-forrest-button.png | Bin 0 -> 1936 bytes .../common/images/corner-imports.svg.xslt | 92 + .../skins/common/images/dc.svg.xslt | 28 + .../skins/common/images/external-link.gif | Bin 0 -> 71 bytes .../documentation/skins/common/images/fix.jpg | Bin 0 -> 932 bytes .../common/images/forrest-credit-logo.png | Bin 0 -> 4633 bytes .../skins/common/images/hack.jpg | Bin 0 -> 743 bytes .../skins/common/images/pdfdoc.gif | Bin 0 -> 457 bytes .../skins/common/images/poddoc.png | Bin 0 -> 856 bytes .../skins/common/images/poddoc.svg.xslt | 55 + .../skins/common/images/printer.gif | Bin 0 -> 438 bytes .../skins/common/images/rc.svg.xslt | 27 + .../skins/common/images/remove.jpg | Bin 0 -> 1251 bytes .../documentation/skins/common/images/rss.png | Bin 0 -> 360 bytes .../skins/common/images/spacer.gif | Bin 0 -> 43 bytes .../skins/common/images/txtdoc.png | Bin 0 -> 784 bytes .../skins/common/images/txtdoc.svg.xslt | 55 + .../skins/common/images/update.jpg | Bin 0 -> 990 bytes .../skins/common/images/valid-html401.png | Bin 0 -> 2948 bytes .../skins/common/images/vcss.png | Bin 0 -> 1134 bytes .../skins/common/images/xmldoc.gif | Bin 0 -> 647 bytes .../common/scripts/breadcrumbs-optimized.js | 90 + .../skins/common/scripts/breadcrumbs.js | 237 ++ .../skins/common/scripts/fontsize.js | 166 + .../skins/common/scripts/getBlank.js | 40 + .../skins/common/scripts/getMenu.js | 45 + .../skins/common/scripts/menu.js | 48 + .../skins/common/scripts/prototype.js | 1257 +++++++ .../documentation/skins/common/skinconf.xsl | 238 ++ .../common/translations/CommonMessages_de.xml | 23 + .../translations/CommonMessages_en_US.xml | 23 + .../common/translations/CommonMessages_es.xml | 23 + .../common/translations/CommonMessages_fr.xml | 23 + .../skins/common/xslt/fo/d2fo.xml | 1015 ++++++ .../skins/common/xslt/fo/document-to-fo.xsl | 1025 ++++++ .../skins/common/xslt/fo/footerinfo.xsl | 70 + .../skins/common/xslt/fo/pdfoutline.xsl | 45 + .../skins/common/xslt/html/book-to-menu.xsl | 139 + .../common/xslt/html/document-to-html.xsl | 374 ++ .../skins/common/xslt/html/dotdots.xsl | 73 + .../skins/common/xslt/html/pathutils.xsl | 231 ++ .../skins/common/xslt/html/renderlogo.xsl | 67 + .../skins/common/xslt/html/site-to-xhtml.xsl | 388 ++ .../skins/common/xslt/html/split.xsl | 124 + .../common/xslt/html/strip_namespaces.xsl | 39 + .../skins/common/xslt/html/tab-to-menu.xsl | 195 + .../skins/common/xslt/html/tabutils.xsl | 98 + .../skins/common/xslt/svg/document-to-svg.xsl | 45 + .../documentation/skins/pelt/css/basic.css | 166 + .../documentation/skins/pelt/css/print.css | 54 + .../skins/pelt/css/profile.css.xslt | 182 + .../documentation/skins/pelt/css/screen.css | 587 +++ .../skins/pelt/images/chapter.gif | Bin 0 -> 49 bytes .../skins/pelt/images/chapter_open.gif | Bin 0 -> 49 bytes .../skins/pelt/images/current.gif | Bin 0 -> 54 bytes .../documentation/skins/pelt/images/error.png | Bin 0 -> 1709 bytes .../skins/pelt/images/header_white_line.gif | Bin 0 -> 37 bytes .../documentation/skins/pelt/images/info.png | Bin 0 -> 1320 bytes .../skins/pelt/images/instruction_arrow.png | Bin 0 -> 285 bytes .../documentation/skins/pelt/images/label.gif | Bin 0 -> 54 bytes .../documentation/skins/pelt/images/page.gif | Bin 0 -> 79 bytes .../skins/pelt/images/pdfdoc.gif | Bin 0 -> 1008 bytes .../skins/pelt/images/printer.gif | Bin 0 -> 603 bytes .../skins/pelt/images/success.png | Bin 0 -> 1291 bytes .../skins/pelt/images/warning.png | Bin 0 -> 1215 bytes .../skins/pelt/images/xmldoc.gif | Bin 0 -> 992 bytes .../cn/src/documentation/skins/pelt/note.txt | 50 + .../src/documentation/skins/pelt/skinconf.xsl | 137 + .../skins/pelt/xslt/fo/document-to-fo.xsl | 22 + .../skins/pelt/xslt/html/book-to-menu.xsl | 53 + .../skins/pelt/xslt/html/document-to-html.xsl | 154 + .../skins/pelt/xslt/html/site-to-xhtml.xsl | 809 +++++ .../skins/pelt/xslt/html/tab-to-menu.xsl | 66 + src/docs/cn/status.xml | 75 + src/docs/cn/uming.ttc | Bin 0 -> 21053592 bytes src/docs/cn/uming.xml | 1 + src/docs/forrest.properties | 109 + src/docs/releasenotes.html | 1 + src/docs/src/documentation/README.txt | 7 + .../classes/CatalogManager.properties | 40 + src/docs/src/documentation/conf/cli.xconf | 327 ++ .../content/xdocs/SLG_user_guide.xml | 193 + .../content/xdocs/capacity_scheduler.xml | 356 ++ .../content/xdocs/cluster_setup.xml | 891 +++++ .../content/xdocs/commands_manual.xml | 699 ++++ .../documentation/content/xdocs/distcp.xml | 352 ++ .../content/xdocs/fair_scheduler.xml | 371 ++ .../content/xdocs/hadoop_archives.xml | 80 + .../content/xdocs/hdfs_design.xml | 368 ++ .../content/xdocs/hdfs_imageviewer.xml | 359 ++ .../content/xdocs/hdfs_permissions_guide.xml | 192 + .../content/xdocs/hdfs_quota_admin_guide.xml | 110 + .../content/xdocs/hdfs_shell.xml | 465 +++ .../content/xdocs/hdfs_user_guide.xml | 633 ++++ .../content/xdocs/hod_admin_guide.xml | 412 +++ .../content/xdocs/hod_config_guide.xml | 344 ++ .../content/xdocs/hod_user_guide.xml | 561 +++ .../src/documentation/content/xdocs/index.xml | 37 + .../documentation/content/xdocs/libhdfs.xml | 97 + .../content/xdocs/mapred_tutorial.xml | 3133 +++++++++++++++++ .../content/xdocs/native_libraries.xml | 212 ++ .../content/xdocs/quickstart.xml | 296 ++ .../content/xdocs/service_level_auth.xml | 234 ++ .../src/documentation/content/xdocs/site.xml | 283 ++ .../documentation/content/xdocs/streaming.xml | 670 ++++ .../src/documentation/content/xdocs/tabs.xml | 37 + .../documentation/content/xdocs/vaidya.xml | 172 + .../resources/images/architecture.gif | Bin 0 -> 15461 bytes .../resources/images/core-logo.gif | Bin 0 -> 6665 bytes .../resources/images/favicon.ico | Bin 0 -> 766 bytes .../resources/images/hadoop-logo-big.jpg | Bin 0 -> 127869 bytes .../resources/images/hadoop-logo.jpg | Bin 0 -> 9443 bytes .../resources/images/hdfsarchitecture.gif | Bin 0 -> 17653 bytes .../resources/images/hdfsarchitecture.odg | Bin 0 -> 41298 bytes .../resources/images/hdfsarchitecture.png | Bin 0 -> 40571 bytes .../resources/images/hdfsdatanodes.gif | Bin 0 -> 16060 bytes .../resources/images/hdfsdatanodes.odg | Bin 0 -> 37296 bytes .../resources/images/hdfsdatanodes.png | Bin 0 -> 30012 bytes src/docs/src/documentation/skinconf.xml | 366 ++ src/docs/status.xml | 75 + 165 files changed, 31020 insertions(+) create mode 100644 src/docs/changes/ChangesFancyStyle.css create mode 100644 src/docs/changes/ChangesSimpleStyle.css create mode 100755 src/docs/changes/changes2html.pl create mode 100644 src/docs/cn/changes/ChangesFancyStyle.css create mode 100644 src/docs/cn/changes/ChangesSimpleStyle.css create mode 100644 src/docs/cn/changes/changes2html.pl create mode 100644 src/docs/cn/forrest.properties create mode 100644 src/docs/cn/src/documentation/README.txt create mode 100644 src/docs/cn/src/documentation/classes/CatalogManager.properties create mode 100644 src/docs/cn/src/documentation/conf/cli.xconf create mode 100644 src/docs/cn/src/documentation/content/xdocs/cluster_setup.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/commands_manual.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/distcp.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hadoop_archives.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hdfs_design.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hdfs_permissions_guide.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hdfs_quota_admin_guide.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hdfs_shell.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hdfs_user_guide.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hod.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hod_admin_guide.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hod_config_guide.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/hod_user_guide.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/index.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/mapred_tutorial.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/native_libraries.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/quickstart.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/site.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/streaming.xml create mode 100644 src/docs/cn/src/documentation/content/xdocs/tabs.xml create mode 100644 src/docs/cn/src/documentation/resources/images/architecture.gif create mode 100644 src/docs/cn/src/documentation/resources/images/core-logo.gif create mode 100644 src/docs/cn/src/documentation/resources/images/favicon.ico create mode 100644 src/docs/cn/src/documentation/resources/images/hadoop-logo-big.jpg create mode 100644 src/docs/cn/src/documentation/resources/images/hadoop-logo.jpg create mode 100644 src/docs/cn/src/documentation/resources/images/hdfsarchitecture.gif create mode 100644 src/docs/cn/src/documentation/resources/images/hdfsarchitecture.odg create mode 100644 src/docs/cn/src/documentation/resources/images/hdfsarchitecture.png create mode 100644 src/docs/cn/src/documentation/resources/images/hdfsdatanodes.gif create mode 100644 src/docs/cn/src/documentation/resources/images/hdfsdatanodes.odg create mode 100644 src/docs/cn/src/documentation/resources/images/hdfsdatanodes.png create mode 100644 src/docs/cn/src/documentation/skinconf.xml create mode 100644 src/docs/cn/src/documentation/skins/common/css/forrest.css.xslt create mode 100644 src/docs/cn/src/documentation/skins/common/images/README.txt create mode 100644 src/docs/cn/src/documentation/skins/common/images/add.jpg create mode 100644 src/docs/cn/src/documentation/skins/common/images/built-with-forrest-button.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/corner-imports.svg.xslt create mode 100644 src/docs/cn/src/documentation/skins/common/images/dc.svg.xslt create mode 100644 src/docs/cn/src/documentation/skins/common/images/external-link.gif create mode 100644 src/docs/cn/src/documentation/skins/common/images/fix.jpg create mode 100644 src/docs/cn/src/documentation/skins/common/images/forrest-credit-logo.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/hack.jpg create mode 100644 src/docs/cn/src/documentation/skins/common/images/pdfdoc.gif create mode 100644 src/docs/cn/src/documentation/skins/common/images/poddoc.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/poddoc.svg.xslt create mode 100644 src/docs/cn/src/documentation/skins/common/images/printer.gif create mode 100644 src/docs/cn/src/documentation/skins/common/images/rc.svg.xslt create mode 100644 src/docs/cn/src/documentation/skins/common/images/remove.jpg create mode 100644 src/docs/cn/src/documentation/skins/common/images/rss.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/spacer.gif create mode 100644 src/docs/cn/src/documentation/skins/common/images/txtdoc.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/txtdoc.svg.xslt create mode 100644 src/docs/cn/src/documentation/skins/common/images/update.jpg create mode 100644 src/docs/cn/src/documentation/skins/common/images/valid-html401.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/vcss.png create mode 100644 src/docs/cn/src/documentation/skins/common/images/xmldoc.gif create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs-optimized.js create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs.js create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/fontsize.js create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/getBlank.js create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/getMenu.js create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/menu.js create mode 100644 src/docs/cn/src/documentation/skins/common/scripts/prototype.js create mode 100644 src/docs/cn/src/documentation/skins/common/skinconf.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/translations/CommonMessages_de.xml create mode 100644 src/docs/cn/src/documentation/skins/common/translations/CommonMessages_en_US.xml create mode 100644 src/docs/cn/src/documentation/skins/common/translations/CommonMessages_es.xml create mode 100644 src/docs/cn/src/documentation/skins/common/translations/CommonMessages_fr.xml create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/fo/d2fo.xml create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/fo/document-to-fo.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/fo/footerinfo.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/fo/pdfoutline.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/book-to-menu.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/document-to-html.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/dotdots.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/pathutils.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/renderlogo.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/site-to-xhtml.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/split.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/strip_namespaces.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/tab-to-menu.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/html/tabutils.xsl create mode 100644 src/docs/cn/src/documentation/skins/common/xslt/svg/document-to-svg.xsl create mode 100644 src/docs/cn/src/documentation/skins/pelt/css/basic.css create mode 100644 src/docs/cn/src/documentation/skins/pelt/css/print.css create mode 100644 src/docs/cn/src/documentation/skins/pelt/css/profile.css.xslt create mode 100644 src/docs/cn/src/documentation/skins/pelt/css/screen.css create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/chapter.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/chapter_open.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/current.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/error.png create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/header_white_line.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/info.png create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/instruction_arrow.png create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/label.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/page.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/pdfdoc.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/printer.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/success.png create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/warning.png create mode 100644 src/docs/cn/src/documentation/skins/pelt/images/xmldoc.gif create mode 100644 src/docs/cn/src/documentation/skins/pelt/note.txt create mode 100644 src/docs/cn/src/documentation/skins/pelt/skinconf.xsl create mode 100644 src/docs/cn/src/documentation/skins/pelt/xslt/fo/document-to-fo.xsl create mode 100644 src/docs/cn/src/documentation/skins/pelt/xslt/html/book-to-menu.xsl create mode 100644 src/docs/cn/src/documentation/skins/pelt/xslt/html/document-to-html.xsl create mode 100644 src/docs/cn/src/documentation/skins/pelt/xslt/html/site-to-xhtml.xsl create mode 100644 src/docs/cn/src/documentation/skins/pelt/xslt/html/tab-to-menu.xsl create mode 100644 src/docs/cn/status.xml create mode 100644 src/docs/cn/uming.ttc create mode 100644 src/docs/cn/uming.xml create mode 100644 src/docs/forrest.properties create mode 100644 src/docs/releasenotes.html create mode 100644 src/docs/src/documentation/README.txt create mode 100644 src/docs/src/documentation/classes/CatalogManager.properties create mode 100644 src/docs/src/documentation/conf/cli.xconf create mode 100644 src/docs/src/documentation/content/xdocs/SLG_user_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/capacity_scheduler.xml create mode 100644 src/docs/src/documentation/content/xdocs/cluster_setup.xml create mode 100644 src/docs/src/documentation/content/xdocs/commands_manual.xml create mode 100644 src/docs/src/documentation/content/xdocs/distcp.xml create mode 100644 src/docs/src/documentation/content/xdocs/fair_scheduler.xml create mode 100644 src/docs/src/documentation/content/xdocs/hadoop_archives.xml create mode 100644 src/docs/src/documentation/content/xdocs/hdfs_design.xml create mode 100644 src/docs/src/documentation/content/xdocs/hdfs_imageviewer.xml create mode 100644 src/docs/src/documentation/content/xdocs/hdfs_permissions_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/hdfs_quota_admin_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/hdfs_shell.xml create mode 100644 src/docs/src/documentation/content/xdocs/hdfs_user_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/hod_admin_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/hod_config_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/hod_user_guide.xml create mode 100644 src/docs/src/documentation/content/xdocs/index.xml create mode 100644 src/docs/src/documentation/content/xdocs/libhdfs.xml create mode 100644 src/docs/src/documentation/content/xdocs/mapred_tutorial.xml create mode 100644 src/docs/src/documentation/content/xdocs/native_libraries.xml create mode 100644 src/docs/src/documentation/content/xdocs/quickstart.xml create mode 100644 src/docs/src/documentation/content/xdocs/service_level_auth.xml create mode 100644 src/docs/src/documentation/content/xdocs/site.xml create mode 100644 src/docs/src/documentation/content/xdocs/streaming.xml create mode 100644 src/docs/src/documentation/content/xdocs/tabs.xml create mode 100644 src/docs/src/documentation/content/xdocs/vaidya.xml create mode 100644 src/docs/src/documentation/resources/images/architecture.gif create mode 100644 src/docs/src/documentation/resources/images/core-logo.gif create mode 100644 src/docs/src/documentation/resources/images/favicon.ico create mode 100644 src/docs/src/documentation/resources/images/hadoop-logo-big.jpg create mode 100644 src/docs/src/documentation/resources/images/hadoop-logo.jpg create mode 100644 src/docs/src/documentation/resources/images/hdfsarchitecture.gif create mode 100644 src/docs/src/documentation/resources/images/hdfsarchitecture.odg create mode 100644 src/docs/src/documentation/resources/images/hdfsarchitecture.png create mode 100644 src/docs/src/documentation/resources/images/hdfsdatanodes.gif create mode 100644 src/docs/src/documentation/resources/images/hdfsdatanodes.odg create mode 100644 src/docs/src/documentation/resources/images/hdfsdatanodes.png create mode 100644 src/docs/src/documentation/skinconf.xml create mode 100644 src/docs/status.xml diff --git a/src/docs/changes/ChangesFancyStyle.css b/src/docs/changes/ChangesFancyStyle.css new file mode 100644 index 00000000000..5eef2412b6a --- /dev/null +++ b/src/docs/changes/ChangesFancyStyle.css @@ -0,0 +1,170 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * General + */ + +img { border: 0; } + +#content table { + border: 0; + width: 100%; +} +/*Hack to get IE to render the table at 100%*/ +* html #content table { margin-left: -3px; } + +#content th, +#content td { + margin: 0; + padding: 0; + vertical-align: top; +} + +.clearboth { + clear: both; +} + +.note, .warning, .fixme { + border: solid black 1px; + margin: 1em 3em; +} + +.note .label { + background: #369; + color: white; + font-weight: bold; + padding: 5px 10px; +} +.note .content { + background: #F0F0FF; + color: black; + line-height: 120%; + font-size: 90%; + padding: 5px 10px; +} +.warning .label { + background: #C00; + color: white; + font-weight: bold; + padding: 5px 10px; +} +.warning .content { + background: #FFF0F0; + color: black; + line-height: 120%; + font-size: 90%; + padding: 5px 10px; +} +.fixme .label { + background: #C6C600; + color: black; + font-weight: bold; + padding: 5px 10px; +} +.fixme .content { + padding: 5px 10px; +} + +/** + * Typography + */ + +body { + font-family: verdana, "Trebuchet MS", arial, helvetica, sans-serif; + font-size: 100%; +} + +#content { + font-family: Georgia, Palatino, Times, serif; + font-size: 95%; +} +#tabs { + font-size: 70%; +} +#menu { + font-size: 80%; +} +#footer { + font-size: 70%; +} + +h1, h2, h3, h4, h5, h6 { + font-family: "Trebuchet MS", verdana, arial, helvetica, sans-serif; + font-weight: bold; + margin-top: 1em; + margin-bottom: .5em; +} + +h1 { + margin-top: 0; + margin-bottom: 1em; + font-size: 1.4em; + background-color: 73CAFF +} +#content h1 { + font-size: 160%; + margin-bottom: .5em; +} +#menu h1 { + margin: 0; + padding: 10px; + background: #336699; + color: white; +} +h2 { + font-size: 120%; + background-color: 73CAFF +} +h3 { font-size: 100%; } +h4 { font-size: 90%; } +h5 { font-size: 80%; } +h6 { font-size: 75%; } + +p { + line-height: 120%; + text-align: left; + margin-top: .5em; + margin-bottom: 1em; +} + +#content li, +#content th, +#content td, +#content li ul, +#content li ol{ + margin-top: .5em; + margin-bottom: .5em; +} + + +#content li li, +#minitoc-area li{ + margin-top: 0em; + margin-bottom: 0em; +} + +#content .attribution { + text-align: right; + font-style: italic; + font-size: 85%; + margin-top: 1em; +} + +.codefrag { + font-family: "Courier New", Courier, monospace; + font-size: 110%; +} diff --git a/src/docs/changes/ChangesSimpleStyle.css b/src/docs/changes/ChangesSimpleStyle.css new file mode 100644 index 00000000000..407d0f1cf6d --- /dev/null +++ b/src/docs/changes/ChangesSimpleStyle.css @@ -0,0 +1,49 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ + +body { + font-family: Courier New, monospace; + font-size: 10pt; +} + +h1 { + font-family: Courier New, monospace; + font-size: 10pt; +} + +h2 { + font-family: Courier New, monospace; + font-size: 10pt; +} + +h3 { + font-family: Courier New, monospace; + font-size: 10pt; +} + +a:link { + color: blue; +} + +a:visited { + color: purple; +} + +li { + margin-top: 1em; + margin-bottom: 1em; +} diff --git a/src/docs/changes/changes2html.pl b/src/docs/changes/changes2html.pl new file mode 100755 index 00000000000..67e1826e116 --- /dev/null +++ b/src/docs/changes/changes2html.pl @@ -0,0 +1,282 @@ +#!/usr/bin/perl +# +# Transforms Lucene Java's CHANGES.txt into Changes.html +# +# Input is on STDIN, output is to STDOUT +# +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +use strict; +use warnings; + +my $jira_url_prefix = 'http://issues.apache.org/jira/browse/'; +my $title = undef; +my $release = undef; +my $sections = undef; +my $items = undef; +my $first_relid = undef; +my $second_relid = undef; +my @releases = (); + +my @lines = <>; # Get all input at once + +# +# Parse input and build hierarchical release structure in @releases +# +for (my $line_num = 0 ; $line_num <= $#lines ; ++$line_num) { + $_ = $lines[$line_num]; + next unless (/\S/); # Skip blank lines + + unless ($title) { + if (/\S/) { + s/^\s+//; # Trim leading whitespace + s/\s+$//; # Trim trailing whitespace + } + $title = $_; + next; + } + + if (/^(Release)|(Trunk)/) { # Release headings + $release = $_; + $sections = []; + push @releases, [ $release, $sections ]; + ($first_relid = lc($release)) =~ s/\s+/_/g if ($#releases == 0); + ($second_relid = lc($release)) =~ s/\s+/_/g if ($#releases == 1); + $items = undef; + next; + } + + # Section heading: 2 leading spaces, words all capitalized + if (/^ ([A-Z]+)\s*/) { + my $heading = $_; + $items = []; + push @$sections, [ $heading, $items ]; + next; + } + + # Handle earlier releases without sections - create a headless section + unless ($items) { + $items = []; + push @$sections, [ undef, $items ]; + } + + my $type; + if (@$items) { # A list item has been encountered in this section before + $type = $items->[0]; # 0th position of items array is list type + } else { + $type = get_list_type($_); + push @$items, $type; + } + + if ($type eq 'numbered') { # The modern items list style + # List item boundary is another numbered item or an unindented line + my $line; + my $item = $_; + $item =~ s/^(\s{0,2}\d+\.\s*)//; # Trim the leading item number + my $leading_ws_width = length($1); + $item =~ s/\s+$//; # Trim trailing whitespace + $item .= "\n"; + + while ($line_num < $#lines + and ($line = $lines[++$line_num]) !~ /^(?:\s{0,2}\d+\.\s*\S|\S)/) { + $line =~ s/^\s{$leading_ws_width}//; # Trim leading whitespace + $line =~ s/\s+$//; # Trim trailing whitespace + $item .= "$line\n"; + } + $item =~ s/\n+\Z/\n/; # Trim trailing blank lines + push @$items, $item; + --$line_num unless ($line_num == $#lines); + } elsif ($type eq 'paragraph') { # List item boundary is a blank line + my $line; + my $item = $_; + $item =~ s/^(\s+)//; + my $leading_ws_width = defined($1) ? length($1) : 0; + $item =~ s/\s+$//; # Trim trailing whitespace + $item .= "\n"; + + while ($line_num < $#lines and ($line = $lines[++$line_num]) =~ /\S/) { + $line =~ s/^\s{$leading_ws_width}//; # Trim leading whitespace + $line =~ s/\s+$//; # Trim trailing whitespace + $item .= "$line\n"; + } + push @$items, $item; + --$line_num unless ($line_num == $#lines); + } else { # $type is one of the bulleted types + # List item boundary is another bullet or a blank line + my $line; + my $item = $_; + $item =~ s/^(\s*$type\s*)//; # Trim the leading bullet + my $leading_ws_width = length($1); + $item =~ s/\s+$//; # Trim trailing whitespace + $item .= "\n"; + + while ($line_num < $#lines + and ($line = $lines[++$line_num]) !~ /^\s*(?:$type|\Z)/) { + $line =~ s/^\s{$leading_ws_width}//; # Trim leading whitespace + $line =~ s/\s+$//; # Trim trailing whitespace + $item .= "$line\n"; + } + push @$items, $item; + --$line_num unless ($line_num == $#lines); + } +} + +# +# Print HTML-ified version to STDOUT +# +print<<"__HTML_HEADER__"; + + + + $title + + + + + + + +Hadoop +

$title

+ +__HTML_HEADER__ + +my $heading; +my $relcnt = 0; +my $header = 'h2'; +for my $rel (@releases) { + if (++$relcnt == 3) { + $header = 'h3'; + print "

"; + print "Older Releases"; + print "

\n"; + print "\n" if ($relcnt > 3); +print "\n\n"; + + +# +# Subroutine: get_list_type +# +# Takes one parameter: +# +# - The first line of a sub-section/point +# +# Returns one scalar: +# +# - The list type: 'numbered'; or one of the bulleted types '-', or '.' or +# 'paragraph'. +# +sub get_list_type { + my $first_list_item_line = shift; + my $type = 'paragraph'; # Default to paragraph type + + if ($first_list_item_line =~ /^\s{0,2}\d+\.\s+\S+/) { + $type = 'numbered'; + } elsif ($first_list_item_line =~ /^\s*([-.])\s+\S+/) { + $type = $1; + } + return $type; +} + +1; diff --git a/src/docs/cn/changes/ChangesFancyStyle.css b/src/docs/cn/changes/ChangesFancyStyle.css new file mode 100644 index 00000000000..5eef2412b6a --- /dev/null +++ b/src/docs/cn/changes/ChangesFancyStyle.css @@ -0,0 +1,170 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * General + */ + +img { border: 0; } + +#content table { + border: 0; + width: 100%; +} +/*Hack to get IE to render the table at 100%*/ +* html #content table { margin-left: -3px; } + +#content th, +#content td { + margin: 0; + padding: 0; + vertical-align: top; +} + +.clearboth { + clear: both; +} + +.note, .warning, .fixme { + border: solid black 1px; + margin: 1em 3em; +} + +.note .label { + background: #369; + color: white; + font-weight: bold; + padding: 5px 10px; +} +.note .content { + background: #F0F0FF; + color: black; + line-height: 120%; + font-size: 90%; + padding: 5px 10px; +} +.warning .label { + background: #C00; + color: white; + font-weight: bold; + padding: 5px 10px; +} +.warning .content { + background: #FFF0F0; + color: black; + line-height: 120%; + font-size: 90%; + padding: 5px 10px; +} +.fixme .label { + background: #C6C600; + color: black; + font-weight: bold; + padding: 5px 10px; +} +.fixme .content { + padding: 5px 10px; +} + +/** + * Typography + */ + +body { + font-family: verdana, "Trebuchet MS", arial, helvetica, sans-serif; + font-size: 100%; +} + +#content { + font-family: Georgia, Palatino, Times, serif; + font-size: 95%; +} +#tabs { + font-size: 70%; +} +#menu { + font-size: 80%; +} +#footer { + font-size: 70%; +} + +h1, h2, h3, h4, h5, h6 { + font-family: "Trebuchet MS", verdana, arial, helvetica, sans-serif; + font-weight: bold; + margin-top: 1em; + margin-bottom: .5em; +} + +h1 { + margin-top: 0; + margin-bottom: 1em; + font-size: 1.4em; + background-color: 73CAFF +} +#content h1 { + font-size: 160%; + margin-bottom: .5em; +} +#menu h1 { + margin: 0; + padding: 10px; + background: #336699; + color: white; +} +h2 { + font-size: 120%; + background-color: 73CAFF +} +h3 { font-size: 100%; } +h4 { font-size: 90%; } +h5 { font-size: 80%; } +h6 { font-size: 75%; } + +p { + line-height: 120%; + text-align: left; + margin-top: .5em; + margin-bottom: 1em; +} + +#content li, +#content th, +#content td, +#content li ul, +#content li ol{ + margin-top: .5em; + margin-bottom: .5em; +} + + +#content li li, +#minitoc-area li{ + margin-top: 0em; + margin-bottom: 0em; +} + +#content .attribution { + text-align: right; + font-style: italic; + font-size: 85%; + margin-top: 1em; +} + +.codefrag { + font-family: "Courier New", Courier, monospace; + font-size: 110%; +} diff --git a/src/docs/cn/changes/ChangesSimpleStyle.css b/src/docs/cn/changes/ChangesSimpleStyle.css new file mode 100644 index 00000000000..407d0f1cf6d --- /dev/null +++ b/src/docs/cn/changes/ChangesSimpleStyle.css @@ -0,0 +1,49 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ + +body { + font-family: Courier New, monospace; + font-size: 10pt; +} + +h1 { + font-family: Courier New, monospace; + font-size: 10pt; +} + +h2 { + font-family: Courier New, monospace; + font-size: 10pt; +} + +h3 { + font-family: Courier New, monospace; + font-size: 10pt; +} + +a:link { + color: blue; +} + +a:visited { + color: purple; +} + +li { + margin-top: 1em; + margin-bottom: 1em; +} diff --git a/src/docs/cn/changes/changes2html.pl b/src/docs/cn/changes/changes2html.pl new file mode 100644 index 00000000000..67e1826e116 --- /dev/null +++ b/src/docs/cn/changes/changes2html.pl @@ -0,0 +1,282 @@ +#!/usr/bin/perl +# +# Transforms Lucene Java's CHANGES.txt into Changes.html +# +# Input is on STDIN, output is to STDOUT +# +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +use strict; +use warnings; + +my $jira_url_prefix = 'http://issues.apache.org/jira/browse/'; +my $title = undef; +my $release = undef; +my $sections = undef; +my $items = undef; +my $first_relid = undef; +my $second_relid = undef; +my @releases = (); + +my @lines = <>; # Get all input at once + +# +# Parse input and build hierarchical release structure in @releases +# +for (my $line_num = 0 ; $line_num <= $#lines ; ++$line_num) { + $_ = $lines[$line_num]; + next unless (/\S/); # Skip blank lines + + unless ($title) { + if (/\S/) { + s/^\s+//; # Trim leading whitespace + s/\s+$//; # Trim trailing whitespace + } + $title = $_; + next; + } + + if (/^(Release)|(Trunk)/) { # Release headings + $release = $_; + $sections = []; + push @releases, [ $release, $sections ]; + ($first_relid = lc($release)) =~ s/\s+/_/g if ($#releases == 0); + ($second_relid = lc($release)) =~ s/\s+/_/g if ($#releases == 1); + $items = undef; + next; + } + + # Section heading: 2 leading spaces, words all capitalized + if (/^ ([A-Z]+)\s*/) { + my $heading = $_; + $items = []; + push @$sections, [ $heading, $items ]; + next; + } + + # Handle earlier releases without sections - create a headless section + unless ($items) { + $items = []; + push @$sections, [ undef, $items ]; + } + + my $type; + if (@$items) { # A list item has been encountered in this section before + $type = $items->[0]; # 0th position of items array is list type + } else { + $type = get_list_type($_); + push @$items, $type; + } + + if ($type eq 'numbered') { # The modern items list style + # List item boundary is another numbered item or an unindented line + my $line; + my $item = $_; + $item =~ s/^(\s{0,2}\d+\.\s*)//; # Trim the leading item number + my $leading_ws_width = length($1); + $item =~ s/\s+$//; # Trim trailing whitespace + $item .= "\n"; + + while ($line_num < $#lines + and ($line = $lines[++$line_num]) !~ /^(?:\s{0,2}\d+\.\s*\S|\S)/) { + $line =~ s/^\s{$leading_ws_width}//; # Trim leading whitespace + $line =~ s/\s+$//; # Trim trailing whitespace + $item .= "$line\n"; + } + $item =~ s/\n+\Z/\n/; # Trim trailing blank lines + push @$items, $item; + --$line_num unless ($line_num == $#lines); + } elsif ($type eq 'paragraph') { # List item boundary is a blank line + my $line; + my $item = $_; + $item =~ s/^(\s+)//; + my $leading_ws_width = defined($1) ? length($1) : 0; + $item =~ s/\s+$//; # Trim trailing whitespace + $item .= "\n"; + + while ($line_num < $#lines and ($line = $lines[++$line_num]) =~ /\S/) { + $line =~ s/^\s{$leading_ws_width}//; # Trim leading whitespace + $line =~ s/\s+$//; # Trim trailing whitespace + $item .= "$line\n"; + } + push @$items, $item; + --$line_num unless ($line_num == $#lines); + } else { # $type is one of the bulleted types + # List item boundary is another bullet or a blank line + my $line; + my $item = $_; + $item =~ s/^(\s*$type\s*)//; # Trim the leading bullet + my $leading_ws_width = length($1); + $item =~ s/\s+$//; # Trim trailing whitespace + $item .= "\n"; + + while ($line_num < $#lines + and ($line = $lines[++$line_num]) !~ /^\s*(?:$type|\Z)/) { + $line =~ s/^\s{$leading_ws_width}//; # Trim leading whitespace + $line =~ s/\s+$//; # Trim trailing whitespace + $item .= "$line\n"; + } + push @$items, $item; + --$line_num unless ($line_num == $#lines); + } +} + +# +# Print HTML-ified version to STDOUT +# +print<<"__HTML_HEADER__"; + + + + $title + + + + + + + +Hadoop +

$title

+ +__HTML_HEADER__ + +my $heading; +my $relcnt = 0; +my $header = 'h2'; +for my $rel (@releases) { + if (++$relcnt == 3) { + $header = 'h3'; + print "

"; + print "Older Releases"; + print "

\n"; + print "\n" if ($relcnt > 3); +print "\n\n"; + + +# +# Subroutine: get_list_type +# +# Takes one parameter: +# +# - The first line of a sub-section/point +# +# Returns one scalar: +# +# - The list type: 'numbered'; or one of the bulleted types '-', or '.' or +# 'paragraph'. +# +sub get_list_type { + my $first_list_item_line = shift; + my $type = 'paragraph'; # Default to paragraph type + + if ($first_list_item_line =~ /^\s{0,2}\d+\.\s+\S+/) { + $type = 'numbered'; + } elsif ($first_list_item_line =~ /^\s*([-.])\s+\S+/) { + $type = $1; + } + return $type; +} + +1; diff --git a/src/docs/cn/forrest.properties b/src/docs/cn/forrest.properties new file mode 100644 index 00000000000..0bfc7f8b4d8 --- /dev/null +++ b/src/docs/cn/forrest.properties @@ -0,0 +1,109 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +############## +# Properties used by forrest.build.xml for building the website +# These are the defaults, un-comment them if you need to change them. +############## + +# Prints out a summary of Forrest settings for this project +#forrest.echo=true + +# Project name (used to name .war file) +#project.name=my-project + +# Specifies name of Forrest skin to use +#project.skin=tigris +#project.skin=pelt + +# comma separated list, file:// is supported +#forrest.skins.descriptors=http://forrest.apache.org/skins/skins.xml,file:///c:/myskins/skins.xml + +############## +# behavioural properties +#project.menu-scheme=tab_attributes +#project.menu-scheme=directories + +############## +# layout properties + +# Properties that can be set to override the default locations +# +# Parent properties must be set. This usually means uncommenting +# project.content-dir if any other property using it is uncommented + +#project.status=status.xml +#project.content-dir=src/documentation +#project.raw-content-dir=${project.content-dir}/content +#project.conf-dir=${project.content-dir}/conf +#project.sitemap-dir=${project.content-dir} +#project.xdocs-dir=${project.content-dir}/content/xdocs +#project.resources-dir=${project.content-dir}/resources +#project.stylesheets-dir=${project.resources-dir}/stylesheets +#project.images-dir=${project.resources-dir}/images +#project.schema-dir=${project.resources-dir}/schema +#project.skins-dir=${project.content-dir}/skins +#project.skinconf=${project.content-dir}/skinconf.xml +#project.lib-dir=${project.content-dir}/lib +#project.classes-dir=${project.content-dir}/classes +#project.translations-dir=${project.content-dir}/translations + +############## +# validation properties + +# This set of properties determine if validation is performed +# Values are inherited unless overridden. +# e.g. if forrest.validate=false then all others are false unless set to true. +#forrest.validate=true +#forrest.validate.xdocs=${forrest.validate} +#forrest.validate.skinconf=${forrest.validate} +#forrest.validate.sitemap=${forrest.validate} +#forrest.validate.stylesheets=${forrest.validate} +#forrest.validate.skins=${forrest.validate} +#forrest.validate.skins.stylesheets=${forrest.validate.skins} + +# *.failonerror=(true|false) - stop when an XML file is invalid +#forrest.validate.failonerror=true + +# *.excludes=(pattern) - comma-separated list of path patterns to not validate +# e.g. +#forrest.validate.xdocs.excludes=samples/subdir/**, samples/faq.xml +#forrest.validate.xdocs.excludes= + + +############## +# General Forrest properties + +# The URL to start crawling from +#project.start-uri=linkmap.html +# Set logging level for messages printed to the console +# (DEBUG, INFO, WARN, ERROR, FATAL_ERROR) +#project.debuglevel=ERROR +# Max memory to allocate to Java +forrest.maxmemory=512m +# Any other arguments to pass to the JVM. For example, to run on an X-less +# server, set to -Djava.awt.headless=true +#forrest.jvmargs= +# The bugtracking URL - the issue number will be appended +#project.bugtracking-url=http://issues.apache.org/bugzilla/show_bug.cgi?id= +#project.bugtracking-url=http://issues.apache.org/jira/browse/ +# The issues list as rss +#project.issues-rss-url= +#I18n Property only works for the "forrest run" target. +#project.i18n=true +project.configfile=${project.home}/src/documentation/conf/cli.xconf + diff --git a/src/docs/cn/src/documentation/README.txt b/src/docs/cn/src/documentation/README.txt new file mode 100644 index 00000000000..9bc261b2f15 --- /dev/null +++ b/src/docs/cn/src/documentation/README.txt @@ -0,0 +1,7 @@ +This is the base documentation directory. + +skinconf.xml # This file customizes Forrest for your project. In it, you + # tell forrest the project name, logo, copyright info, etc + +sitemap.xmap # Optional. This sitemap is consulted before all core sitemaps. + # See http://forrest.apache.org/docs/project-sitemap.html diff --git a/src/docs/cn/src/documentation/classes/CatalogManager.properties b/src/docs/cn/src/documentation/classes/CatalogManager.properties new file mode 100644 index 00000000000..b9cb5848fbf --- /dev/null +++ b/src/docs/cn/src/documentation/classes/CatalogManager.properties @@ -0,0 +1,40 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +#======================================================================= +# CatalogManager.properties +# +# This is the default properties file for Apache Forrest. +# This facilitates local configuration of application-specific catalogs. +# +# See the Apache Forrest documentation: +# http://forrest.apache.org/docs/your-project.html +# http://forrest.apache.org/docs/validation.html + +# verbosity ... level of messages for status/debug +# See forrest/src/core/context/WEB-INF/cocoon.xconf + +# catalogs ... list of additional catalogs to load +# (Note that Apache Forrest will automatically load its own default catalog +# from src/core/context/resources/schema/catalog.xcat) +# use full pathnames +# pathname separator is always semi-colon (;) regardless of operating system +# directory separator is always slash (/) regardless of operating system +# +#catalogs=/home/me/forrest/my-site/src/documentation/resources/schema/catalog.xcat +catalogs= + diff --git a/src/docs/cn/src/documentation/conf/cli.xconf b/src/docs/cn/src/documentation/conf/cli.xconf new file mode 100644 index 00000000000..5c6e245688c --- /dev/null +++ b/src/docs/cn/src/documentation/conf/cli.xconf @@ -0,0 +1,327 @@ + + + + + + + + . + WEB-INF/cocoon.xconf + ../tmp/cocoon-work + ../site + + + + + + + + + + + + + + + index.html + + + + + + + */* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/content/xdocs/cluster_setup.xml b/src/docs/cn/src/documentation/content/xdocs/cluster_setup.xml new file mode 100644 index 00000000000..0bf6c0e15ee --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/cluster_setup.xml @@ -0,0 +1,386 @@ + + + + + + + +
+ Hadoop集群æ­å»º +
+ + + +
+ 目的 + +

本文æ述了如何安装ã€é…置和管ç†æœ‰å®žé™…æ„义的Hadoop集群,其规模å¯ä»Žå‡ ä¸ªèŠ‚点的å°é›†ç¾¤åˆ°å‡ åƒä¸ªèŠ‚点的超大集群。

+ +

如果你希望在å•æœºä¸Šå®‰è£…Hadoop玩玩,从这里能找到相关细节。

+
+ +
+ 先决æ¡ä»¶ + +
    +
  1. + ç¡®ä¿åœ¨ä½ é›†ç¾¤ä¸­çš„æ¯ä¸ªèŠ‚点上都安装了所有必需软件。 +
  2. +
  3. + 获å–Hadoop软件包。 +
  4. +
+
+ +
+ 安装 + +

安装Hadoop集群通常è¦å°†å®‰è£…软件解压到集群内的所有机器上。

+ +

通常,集群里的一å°æœºå™¨è¢«æŒ‡å®šä¸º + NameNode,å¦ä¸€å°ä¸åŒçš„机器被指定为JobTracker。这些机器是masters。余下的机器å³ä½œä¸ºDataNode也作为TaskTracker。这些机器是slaves。

+ +

我们用HADOOP_HOME指代安装的根路径。通常,集群里的所有机器的HADOOP_HOME路径相åŒã€‚

+
+ +
+ é…ç½® + +

接下æ¥çš„几节æ述了如何é…ç½®Hadoop集群。

+ +
+ é…置文件 + +

对Hadoopçš„é…置通过conf/目录下的两个é‡è¦é…置文件完æˆï¼š

+
    +
  1. + hadoop-default.xml - åªè¯»çš„默认é…置。 +
  2. +
  3. + hadoop-site.xml - 集群特有的é…置。 +
  4. +
+ +

è¦äº†è§£æ›´å¤šå…³äºŽè¿™äº›é…置文件如何影å“Hadoop框架的细节,请看这里。

+ +

此外,通过设置conf/hadoop-env.sh中的å˜é‡ä¸ºé›†ç¾¤ç‰¹æœ‰çš„值,你å¯ä»¥å¯¹bin/目录下的Hadoop脚本进行控制。

+
+ +
+ 集群é…ç½® + +

è¦é…ç½®Hadoop集群,你需è¦è®¾ç½®Hadoop守护进程的è¿è¡ŒçŽ¯å¢ƒå’ŒHadoop守护进程的è¿è¡Œå‚数。

+ +

Hadoop守护进程指NameNode/DataNode + 和JobTracker/TaskTracker。

+ +
+ é…ç½®Hadoop守护进程的è¿è¡ŒçŽ¯å¢ƒ + +

管ç†å‘˜å¯åœ¨conf/hadoop-env.sh脚本内对Hadoop守护进程的è¿è¡ŒçŽ¯å¢ƒåšç‰¹åˆ«æŒ‡å®šã€‚

+

至少,你得设定JAVA_HOME使之在æ¯ä¸€è¿œç«¯èŠ‚点上都被正确设置。

+

管ç†å‘˜å¯ä»¥é€šè¿‡é…置选项HADOOP_*_OPTSæ¥åˆ†åˆ«é…ç½®å„个守护进程。 + 下表是å¯ä»¥é…置的选项。 +

+ + + + + + + + +
守护进程é…置选项
NameNodeHADOOP_NAMENODE_OPTS
DataNodeHADOOP_DATANODE_OPTS
SecondaryNamenodeHADOOP_SECONDARYNAMENODE_OPTS
JobTrackerHADOOP_JOBTRACKER_OPTS
TaskTrackerHADOOP_TASKTRACKER_OPTS
+ +

例如,é…ç½®Namenodeæ—¶,为了使其能够并行回收垃圾(parallelGC), + è¦æŠŠä¸‹é¢çš„代ç åŠ å…¥åˆ°hadoop-env.sh : +
+ export HADOOP_NAMENODE_OPTS="-XX:+UseParallelGC ${HADOOP_NAMENODE_OPTS}" +

+

其它å¯å®šåˆ¶çš„常用å‚数还包括:

+
    +
  • + HADOOP_LOG_DIR - 守护进程日志文件的存放目录。如果ä¸å­˜åœ¨ä¼šè¢«è‡ªåŠ¨åˆ›å»ºã€‚ +
  • +
  • + HADOOP_HEAPSIZE - 最大å¯ç”¨çš„堆大å°ï¼Œå•ä½ä¸ºMB。比如,1000MB。 + 这个å‚数用于设置hadoop守护进程的堆大å°ã€‚缺çœå¤§å°æ˜¯1000MB。 +
  • +
+
+ +
+ é…ç½®Hadoop守护进程的è¿è¡Œå‚æ•° + +

这部分涉åŠHadoop集群的é‡è¦å‚数,这些å‚数在conf/hadoop-site.xml中指定。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
å‚æ•°å–值备注
fs.default.nameNameNodeçš„URI。hdfs://主机å/
mapred.job.trackerJobTracker的主机(或者IP)和端å£ã€‚主机:端å£ã€‚
dfs.name.dir + NameNodeæŒä¹…存储å字空间åŠäº‹åŠ¡æ—¥å¿—的本地文件系统路径。当这个值是一个逗å·åˆ†å‰²çš„目录列表时,nametableæ•°æ®å°†ä¼šè¢«å¤åˆ¶åˆ°æ‰€æœ‰ç›®å½•ä¸­åšå†—余备份。 +
dfs.data.dir + DataNode存放å—æ•°æ®çš„本地文件系统路径,逗å·åˆ†å‰²çš„列表。 + + 当这个值是逗å·åˆ†å‰²çš„目录列表时,数æ®å°†è¢«å­˜å‚¨åœ¨æ‰€æœ‰ç›®å½•ä¸‹ï¼Œé€šå¸¸åˆ†å¸ƒåœ¨ä¸åŒè®¾å¤‡ä¸Šã€‚ +
mapred.system.dirMap/Reduce框架存储系统文件的HDFS路径。比如/hadoop/mapred/system/。 + 这个路径是默认文件系统(HDFS)下的路径, 须从æœåŠ¡å™¨å’Œå®¢æˆ·ç«¯ä¸Šå‡å¯è®¿é—®ã€‚ +
mapred.local.dir本地文件系统下逗å·åˆ†å‰²çš„路径列表,Map/Reduce临时数æ®å­˜æ”¾çš„地方。 + 多路径有助于利用ç£ç›˜i/o。
mapred.tasktracker.{map|reduce}.tasks.maximumæŸä¸€TaskTracker上å¯è¿è¡Œçš„最大Map/Reduce任务数,这些任务将åŒæ—¶å„自è¿è¡Œã€‚ + + 默认为2(2个mapå’Œ2个reduce),å¯ä¾æ®ç¡¬ä»¶æƒ…况更改。 +
dfs.hosts/dfs.hosts.exclude许å¯/æ‹’ç»DataNode列表。 + 如有必è¦ï¼Œç”¨è¿™ä¸ªæ–‡ä»¶æŽ§åˆ¶è®¸å¯çš„datanode列表。 +
mapred.hosts/mapred.hosts.exclude许å¯/æ‹’ç»TaskTracker列表。 + 如有必è¦ï¼Œç”¨è¿™ä¸ªæ–‡ä»¶æŽ§åˆ¶è®¸å¯çš„TaskTracker列表。 +
+ +

通常,上述å‚数被标记为 + + final 以确ä¿å®ƒä»¬ä¸è¢«ç”¨æˆ·åº”用更改。 +

+ +
+ 现实世界的集群é…ç½® + +

这节罗列在大规模集群上è¿è¡Œsort基准测试(benchmark)时使用到的一些éžç¼ºçœé…置。

+ +
    +
  • +

    è¿è¡Œsort900的一些éžç¼ºçœé…置值,sort900å³åœ¨900个节点的集群上对9TBçš„æ•°æ®è¿›è¡ŒæŽ’åºï¼š

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    å‚æ•°å–值备注
    dfs.block.size134217728针对大文件系统,HDFSçš„å—大å°å–128MB。
    dfs.namenode.handler.count40 + å¯åŠ¨æ›´å¤šçš„NameNodeæœåŠ¡çº¿ç¨‹åŽ»å¤„ç†æ¥è‡ªå¤§é‡DataNodeçš„RPC请求。 +
    mapred.reduce.parallel.copies20 + reduceå¯åŠ¨æ›´å¤šçš„并行拷è´å™¨ä»¥èŽ·å–大é‡map的输出。 +
    mapred.child.java.opts-Xmx512M + 为map/reduceå­è™šæ‹Ÿæœºä½¿ç”¨æ›´å¤§çš„堆。 +
    fs.inmemory.size.mb200 + 为reduce阶段åˆå¹¶map输出所需的内存文件系统分é…更多的内存。 +
    io.sort.factor100文件排åºæ—¶æ›´å¤šçš„æµå°†åŒæ—¶è¢«å½’并。
    io.sort.mb200æ高排åºæ—¶çš„内存上é™ã€‚
    io.file.buffer.size131072SequenceFile中用到的读/写缓存大å°ã€‚
    +
  • +
  • +

    è¿è¡Œsort1400å’Œsort2000时需è¦æ›´æ–°çš„é…置,å³åœ¨1400个节点上对14TBçš„æ•°æ®è¿›è¡ŒæŽ’åºå’Œåœ¨2000个节点上对20TBçš„æ•°æ®è¿›è¡ŒæŽ’åºï¼š

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    å‚æ•°å–值备注
    mapred.job.tracker.handler.count60 + å¯ç”¨æ›´å¤šçš„JobTrackeræœåŠ¡çº¿ç¨‹åŽ»å¤„ç†æ¥è‡ªå¤§é‡TaskTrackerçš„RPC请求。 +
    mapred.reduce.parallel.copies50
    tasktracker.http.threads50 + 为TaskTrackerçš„HttpæœåŠ¡å¯ç”¨æ›´å¤šçš„工作线程。reduce通过HttpæœåŠ¡èŽ·å–map的中间输出。 +
    mapred.child.java.opts-Xmx1024M使用更大的堆用于maps/reducesçš„å­è™šæ‹Ÿæœº
    +
  • +
+
+ +
+ +
+ Slaves + +

通常,你选择集群中的一å°æœºå™¨ä½œä¸ºNameNode,å¦å¤–一å°ä¸åŒçš„机器作为JobTracker。余下的机器å³ä½œä¸ºDataNodeåˆä½œä¸ºTaskTracker,这些被称之为slaves。

+ +

在conf/slaves文件中列出所有slave的主机å或者IP地å€ï¼Œä¸€è¡Œä¸€ä¸ªã€‚

+
+ +
+ 日志 + +

Hadoop使用Apache log4jæ¥è®°å½•æ—¥å¿—,它由Apache Commons Logging框架æ¥å®žçŽ°ã€‚编辑conf/log4j.properties文件å¯ä»¥æ”¹å˜Hadoop守护进程的日志é…置(日志格å¼ç­‰ï¼‰ã€‚

+ +
+ 历å²æ—¥å¿— + +

作业的历å²æ–‡ä»¶é›†ä¸­å­˜æ”¾åœ¨hadoop.job.history.location,这个也å¯ä»¥æ˜¯åœ¨åˆ†å¸ƒå¼æ–‡ä»¶ç³»ç»Ÿä¸‹çš„路径,其默认值为${HADOOP_LOG_DIR}/history。jobtrackerçš„web UI上有历å²æ—¥å¿—çš„web UI链接。

+ +

历å²æ–‡ä»¶åœ¨ç”¨æˆ·æŒ‡å®šçš„目录hadoop.job.history.user.location也会记录一份,这个é…置的缺çœå€¼ä¸ºä½œä¸šçš„输出目录。这些文件被存放在指定路径下的“_logs/history/â€ç›®å½•ä¸­ã€‚因此,默认情况下日志文件会在“mapred.output.dir/_logs/history/â€ä¸‹ã€‚如果将hadoop.job.history.user.location指定为值none,系统将ä¸å†è®°å½•æ­¤æ—¥å¿—。

+ +

用户å¯ä½¿ç”¨ä»¥ä¸‹å‘½ä»¤åœ¨æŒ‡å®šè·¯å¾„下查看历å²æ—¥å¿—汇总
+ $ bin/hadoop job -history output-dir
+ è¿™æ¡å‘½ä»¤ä¼šæ˜¾ç¤ºä½œä¸šçš„细节信æ¯ï¼Œå¤±è´¥å’Œç»ˆæ­¢çš„任务细节。
+ 关于作业的更多细节,比如æˆåŠŸçš„任务,以åŠå¯¹æ¯ä¸ªä»»åŠ¡çš„所åšçš„å°è¯•æ¬¡æ•°ç­‰å¯ä»¥ç”¨ä¸‹é¢çš„命令查看
+ $ bin/hadoop job -history all output-dir

+
+
+
+ +

一但全部必è¦çš„é…置完æˆï¼Œå°†è¿™äº›æ–‡ä»¶åˆ†å‘到所有机器的HADOOP_CONF_DIR路径下,通常是${HADOOP_HOME}/conf。

+
+ +
+ Hadoop的机架感知 +

HDFS和Map/Reduce的组件是能够感知机架的。

+

NameNodeå’ŒJobTracker通过调用管ç†å‘˜é…置模å—中的APIresolveæ¥èŽ·å–集群里æ¯ä¸ªslave的机架id。该APIå°†slaveçš„DNSå称(或者IP地å€ï¼‰è½¬æ¢æˆæœºæž¶id。使用哪个模å—是通过é…置项topology.node.switch.mapping.implæ¥æŒ‡å®šçš„。模å—的默认实现会调用topology.script.file.nameé…置项指定的一个的脚本/命令。 如果topology.script.file.name未被设置,对于所有传入的IP地å€ï¼Œæ¨¡å—会返回/default-rack作为机架id。在Map/Reduce部分还有一个é¢å¤–çš„é…置项mapred.cache.task.levels,该å‚数决定cache的级数(在网络拓扑中)。例如,如果默认值是2,会建立两级的cacheï¼ ä¸€çº§é’ˆå¯¹ä¸»æœºï¼ˆä¸»æœº -> 任务的映射)å¦ä¸€çº§é’ˆå¯¹æœºæž¶ï¼ˆæœºæž¶ -> 任务的映射)。 +

+
+ +
+ å¯åŠ¨Hadoop + +

å¯åŠ¨Hadoop集群需è¦å¯åŠ¨HDFS集群和Map/Reduce集群。

+ +

+ æ ¼å¼åŒ–一个新的分布å¼æ–‡ä»¶ç³»ç»Ÿï¼š
+ $ bin/hadoop namenode -format +

+ +

+ 在分é…çš„NameNode上,è¿è¡Œä¸‹é¢çš„命令å¯åŠ¨HDFS:
+ $ bin/start-dfs.sh +

+

bin/start-dfs.sh脚本会å‚ç…§NameNode上${HADOOP_CONF_DIR}/slaves文件的内容,在所有列出的slave上å¯åŠ¨DataNode守护进程。

+

+ 在分é…çš„JobTracker上,è¿è¡Œä¸‹é¢çš„命令å¯åŠ¨Map/Reduce:
+ $ bin/start-mapred.sh +

+

bin/start-mapred.sh脚本会å‚ç…§JobTracker上${HADOOP_CONF_DIR}/slaves文件的内容,在所有列出的slave上å¯åŠ¨TaskTracker守护进程。

+
+ +
+ åœæ­¢Hadoop + +

+ 在分é…çš„NameNode上,执行下é¢çš„命令åœæ­¢HDFS:
+ $ bin/stop-dfs.sh +

+

bin/stop-dfs.sh脚本会å‚ç…§NameNode上${HADOOP_CONF_DIR}/slaves文件的内容,在所有列出的slave上åœæ­¢DataNode守护进程。

+

+ 在分é…çš„JobTracker上,è¿è¡Œä¸‹é¢çš„命令åœæ­¢Map/Reduce:
+ $ bin/stop-mapred.sh
+

+

bin/stop-mapred.sh脚本会å‚ç…§JobTracker上${HADOOP_CONF_DIR}/slaves文件的内容,在所有列出的slave上åœæ­¢TaskTracker守护进程。

+
+ + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/commands_manual.xml b/src/docs/cn/src/documentation/content/xdocs/commands_manual.xml new file mode 100644 index 00000000000..f461beac212 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/commands_manual.xml @@ -0,0 +1,596 @@ + + + + + +
+ 命令手册 +
+ + +
+ 概述 +

+ 所有的hadoop命令å‡ç”±bin/hadoop脚本引å‘。ä¸æŒ‡å®šå‚æ•°è¿è¡Œhadoop脚本会打å°æ‰€æœ‰å‘½ä»¤çš„æ述。 +

+

+ 用法:hadoop [--config confdir] [COMMAND] [GENERIC_OPTIONS] [COMMAND_OPTIONS] +

+

+ Hadoop有一个选项解æžæ¡†æž¶ç”¨äºŽè§£æžä¸€èˆ¬çš„选项和è¿è¡Œç±»ã€‚ +

+ + + + + + + + + + + + + + + +
命令选项 æè¿°
--config confdir覆盖缺çœé…置目录。缺çœæ˜¯${HADOOP_HOME}/conf。
GENERIC_OPTIONS多个命令都支æŒçš„通用选项。
COMMAND
命令选项S
å„ç§å„样的命令和它们的选项会在下é¢æ到。这些命令被分为 + 用户命令 + 管ç†å‘½ä»¤ä¸¤ç»„。
+
+ 常规选项 +

+ 下é¢çš„选项被 + dfsadmin, + fs, fsckå’Œ + job支æŒã€‚ + 应用程åºè¦å®žçŽ° + Toolæ¥æ”¯æŒ + + 常规选项。 +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GENERIC_OPTION æè¿°
-conf <configuration file>指定应用程åºçš„é…置文件。
-D <property=value>为指定property指定值value。
-fs <local|namenode:port>指定namenode。
-jt <local|jobtracker:port>指定job tracker。åªé€‚用于job。
-files <逗å·åˆ†éš”的文件列表>指定è¦æ‹·è´åˆ°map reduce集群的文件的逗å·åˆ†éš”的列表。 + åªé€‚用于job。
-libjars <逗å·åˆ†éš”çš„jar列表>指定è¦åŒ…å«åˆ°classpath中的jar文件的逗å·åˆ†éš”的列表。 + åªé€‚用于job。
-archives <逗å·åˆ†éš”çš„archive列表>指定è¦è¢«è§£åŽ‹åˆ°è®¡ç®—节点上的档案文件的逗å·åˆ†å‰²çš„列表。 + åªé€‚用于job。
+
+
+ +
+ 用户命令 +

hadoop集群用户的常用命令。

+
+ archive +

+ 创建一个hadoop档案文件。å‚考 Hadoop Archives. +

+

+ 用法:hadoop archive -archiveName NAME <src>* <dest> +

+ + + + + + + + + + + + + + +
命令选项 æè¿°
-archiveName NAMEè¦åˆ›å»ºçš„档案的å字。
src文件系统的路径å,和通常å«æ­£åˆ™è¡¨è¾¾çš„一样。
destä¿å­˜æ¡£æ¡ˆæ–‡ä»¶çš„目标目录。
+
+ +
+ distcp +

+ 递归地拷è´æ–‡ä»¶æˆ–目录。å‚考DistCp指å—以获å–等多信æ¯ã€‚ +

+

+ 用法:hadoop distcp <srcurl> <desturl> +

+ + + + + + + + + + + +
命令选项 æè¿°
srcurlæºUrl
desturl目标Url
+
+ +
+ fs +

+ 用法:hadoop fs [GENERIC_OPTIONS] + [COMMAND_OPTIONS] +

+

+ è¿è¡Œä¸€ä¸ªå¸¸è§„的文件系统客户端。 +

+

+ å„ç§å‘½ä»¤é€‰é¡¹å¯ä»¥å‚考HDFS Shell指å—。 +

+
+ +
+ fsck +

+ è¿è¡ŒHDFS文件系统检查工具。å‚考Fsck了解更多。 +

+

用法:hadoop fsck [GENERIC_OPTIONS] + <path> [-move | -delete | -openforwrite] [-files [-blocks + [-locations | -racks]]]

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
命令选项 æè¿°
<path>检查的起始目录。
-move移动å—æŸæ–‡ä»¶åˆ°/lost+found
-delete删除å—æŸæ–‡ä»¶ã€‚
-openforwrite打å°å‡ºå†™æ‰“开的文件。
-files打å°å‡ºæ­£è¢«æ£€æŸ¥çš„文件。
-blocks打å°å‡ºå—ä¿¡æ¯æŠ¥å‘Šã€‚
-locations打å°å‡ºæ¯ä¸ªå—çš„ä½ç½®ä¿¡æ¯ã€‚
-racks打å°å‡ºdata-node的网络拓扑结构。
+
+ +
+ jar +

+ è¿è¡Œjar文件。用户å¯ä»¥æŠŠä»–们的Map Reduce代ç æ†ç»‘到jar文件中,使用这个命令执行。 +

+

+ 用法:hadoop jar <jar> [mainClass] args... +

+

+ streaming作业是通过这个命令执行的。å‚考Streaming examples中的例å­ã€‚ +

+

+ Word count例å­ä¹Ÿæ˜¯é€šè¿‡jar命令è¿è¡Œçš„。å‚考Wordcount example。 +

+
+ +
+ job +

+ 用于和Map Reduce作业交互和命令。 +

+

+ 用法:hadoop job [GENERIC_OPTIONS] + [-submit <job-file>] | [-status <job-id>] | + [-counter <job-id> <group-name> <counter-name>] | [-kill <job-id>] | + [-events <job-id> <from-event-#> <#-of-events>] | [-history [all] <jobOutputDir>] | + [-list [all]] | [-kill-task <task-id>] | [-fail-task <task-id>] +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
命令选项 æè¿°
-submit <job-file>æ交作业
-status <job-id>打å°mapå’Œreduce完æˆç™¾åˆ†æ¯”和所有计数器。
-counter <job-id> <group-name> <counter-name>打å°è®¡æ•°å™¨çš„值。
-kill <job-id>æ€æ­»æŒ‡å®šä½œä¸šã€‚
-events <job-id> <from-event-#> <#-of-events>打å°ç»™å®šèŒƒå›´å†…jobtracker接收到的事件细节。
-history [all] <jobOutputDir>-history <jobOutputDir> 打å°ä½œä¸šçš„细节ã€å¤±è´¥åŠè¢«æ€æ­»åŽŸå› çš„细节。更多的关于一个作业的细节比如æˆåŠŸçš„任务,åšè¿‡çš„任务å°è¯•ç­‰ä¿¡æ¯å¯ä»¥é€šè¿‡æŒ‡å®š[all]选项查看。 +
-list [all]-list all显示所有作业。-liståªæ˜¾ç¤ºå°†è¦å®Œæˆçš„作业。
-kill-task <task-id>æ€æ­»ä»»åŠ¡ã€‚被æ€æ­»çš„任务ä¸ä¼šä¸åˆ©äºŽå¤±è´¥å°è¯•ã€‚
-fail-task <task-id>使任务失败。被失败的任务会对失败å°è¯•ä¸åˆ©ã€‚
+
+ +
+ pipes +

+ è¿è¡Œpipes作业。 +

+

+ 用法:hadoop pipes [-conf <path>] [-jobconf <key=value>, <key=value>, ...] + [-input <path>] [-output <path>] [-jar <jar file>] [-inputformat <class>] + [-map <class>] [-partitioner <class>] [-reduce <class>] [-writer <class>] + [-program <executable>] [-reduces <num>] +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
命令选项 æè¿°
-conf <path>作业的é…ç½®
-jobconf <key=value>, <key=value>, ...增加/覆盖作业的é…置项
-input <path>输入目录
-output <path>输出目录
-jar <jar file>Jar文件å
-inputformat <class>InputFormatç±»
-map <class>Java Mapç±»
-partitioner <class>Java Partitioner
-reduce <class>Java Reduceç±»
-writer <class>Java RecordWriter
-program <executable>å¯æ‰§è¡Œç¨‹åºçš„URI
-reduces <num>reduce个数
+
+ +
+ version +

+ 打å°ç‰ˆæœ¬ä¿¡æ¯ã€‚ +

+

+ 用法:hadoop version +

+
+ +
+ CLASSNAME +

+ hadoop脚本å¯ç”¨äºŽè°ƒè°ƒç”¨ä»»ä½•ç±»ã€‚ +

+

+ 用法:hadoop CLASSNAME +

+

+ è¿è¡Œå字为CLASSNAME的类。 +

+
+ +
+ +
+ 管ç†å‘½ä»¤ +

hadoop集群管ç†å‘˜å¸¸ç”¨çš„命令。

+
+ balancer +

+ è¿è¡Œé›†ç¾¤å¹³è¡¡å·¥å…·ã€‚管ç†å‘˜å¯ä»¥ç®€å•çš„按Ctrl-Cæ¥åœæ­¢å¹³è¡¡è¿‡ç¨‹ã€‚å‚考Rebalancer了解更多。 +

+

+ 用法:hadoop balancer [-threshold <threshold>] +

+ + + + + + + +
命令选项 æè¿°
-threshold <threshold>ç£ç›˜å®¹é‡çš„百分比。这会覆盖缺çœçš„阀值。
+
+ +
+ daemonlog +

+ 获å–或设置æ¯ä¸ªå®ˆæŠ¤è¿›ç¨‹çš„日志级别。 +

+

+ 用法:hadoop daemonlog -getlevel <host:port> <name>
+ 用法:hadoop daemonlog -setlevel <host:port> <name> <level> +

+ + + + + + + + + + + +
命令选项 æè¿°
-getlevel <host:port> <name>打å°è¿è¡Œåœ¨<host:port>的守护进程的日志级别。这个命令内部会连接http://<host:port>/logLevel?log=<name>
-setlevel <host:port> <name> <level>设置è¿è¡Œåœ¨<host:port>的守护进程的日志级别。这个命令内部会连接http://<host:port>/logLevel?log=<name>
+
+ +
+ datanode +

+ è¿è¡Œä¸€ä¸ªHDFSçš„datanode。 +

+

+ 用法:hadoop datanode [-rollback] +

+ + + + + + + +
命令选项 æè¿°
-rollbackå°†datanode回滚到å‰ä¸€ä¸ªç‰ˆæœ¬ã€‚这需è¦åœ¨åœæ­¢datanode,分å‘è€çš„hadoop版本之åŽä½¿ç”¨ã€‚ +
+
+ +
+ dfsadmin +

+ è¿è¡Œä¸€ä¸ªHDFSçš„dfsadmin客户端。 +

+

+ 用法:hadoop dfsadmin [GENERIC_OPTIONS] [-report] [-safemode enter | leave | get | wait] [-refreshNodes] + [-finalizeUpgrade] [-upgradeProgress status | details | force] [-metasave filename] + [-setQuota <quota> <dirname>...<dirname>] [-clrQuota <dirname>...<dirname>] + [-help [cmd]] +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
命令选项 æè¿°
-report报告文件系统的基本信æ¯å’Œç»Ÿè®¡ä¿¡æ¯ã€‚
-safemode enter | leave | get | wait安全模å¼ç»´æŠ¤å‘½ä»¤ã€‚安全模å¼æ˜¯Namenode的一个状æ€ï¼Œè¿™ç§çŠ¶æ€ä¸‹ï¼ŒNamenode
+ 1. ä¸æŽ¥å—对å字空间的更改(åªè¯»)
+ 2. ä¸å¤åˆ¶æˆ–删除å—
+ Namenode会在å¯åŠ¨æ—¶è‡ªåŠ¨è¿›å…¥å®‰å…¨æ¨¡å¼ï¼Œå½“é…置的å—最å°ç™¾åˆ†æ¯”数满足最å°çš„副本数æ¡ä»¶æ—¶ï¼Œä¼šè‡ªåŠ¨ç¦»å¼€å®‰å…¨æ¨¡å¼ã€‚安全模å¼å¯ä»¥æ‰‹åŠ¨è¿›å…¥ï¼Œä½†æ˜¯è¿™æ ·çš„è¯ä¹Ÿå¿…须手动关闭安全模å¼ã€‚ +
-refreshNodesé‡æ–°è¯»å–hostså’Œexclude文件,更新å…许连到Namenode的或那些需è¦é€€å‡ºæˆ–入编的Datanode的集åˆã€‚ +
-finalizeUpgrade终结HDFSçš„å‡çº§æ“作。Datanode删除å‰ä¸€ä¸ªç‰ˆæœ¬çš„工作目录,之åŽNamenode也这样åšã€‚这个æ“作完结整个å‡çº§è¿‡ç¨‹ã€‚ +
-upgradeProgress status | details | force请求当å‰ç³»ç»Ÿçš„å‡çº§çŠ¶æ€ï¼ŒçŠ¶æ€çš„细节,或者强制å‡çº§æ“作进行。 +
-metasave filenameä¿å­˜Namenode的主è¦æ•°æ®ç»“构到hadoop.log.dir属性指定的目录下的<filename>文件。对于下é¢çš„æ¯ä¸€é¡¹ï¼Œ<filename>中都会一行内容与之对应
+ 1. Namenode收到的Datanode的心跳信å·
+ 2. 等待被å¤åˆ¶çš„å—
+ 3. 正在被å¤åˆ¶çš„å—
+ 4. 等待被删除的å—
-setQuota <quota> <dirname>...<dirname>为æ¯ä¸ªç›®å½• <dirname>设定é…é¢<quota>。目录é…é¢æ˜¯ä¸€ä¸ªé•¿æ•´åž‹æ•´æ•°ï¼Œå¼ºåˆ¶é™å®šäº†ç›®å½•æ ‘下的å字个数。
+ 命令会在这个目录上工作良好,以下情况会报错:
+ 1. Nä¸æ˜¯ä¸€ä¸ªæ­£æ•´æ•°ï¼Œæˆ–者
+ 2. 用户ä¸æ˜¯ç®¡ç†å‘˜ï¼Œæˆ–者
+ 3. 这个目录ä¸å­˜åœ¨æˆ–是文件,或者
+ 4. 目录会马上超出新设定的é…é¢ã€‚
-clrQuota <dirname>...<dirname>为æ¯ä¸€ä¸ªç›®å½•<dirname>清除é…é¢è®¾å®šã€‚
+ 命令会在这个目录上工作良好,以下情况会报错:
+ 1. 这个目录ä¸å­˜åœ¨æˆ–是文件,或者
+ 2. 用户ä¸æ˜¯ç®¡ç†å‘˜ã€‚
+ 如果目录原æ¥æ²¡æœ‰é…é¢ä¸ä¼šæŠ¥é”™ã€‚
-help [cmd]显示给定命令的帮助信æ¯ï¼Œå¦‚果没有给定命令,则显示所有命令的帮助信æ¯ã€‚
+
+ +
+ jobtracker +

+ è¿è¡ŒMapReduce job Tracker节点。 +

+

+ 用法:hadoop jobtracker +

+
+ +
+ namenode +

+ è¿è¡Œnamenode。有关å‡çº§ï¼Œå›žæ»šï¼Œå‡çº§ç»ˆç»“的更多信æ¯è¯·å‚考å‡çº§å’Œå›žæ»šã€‚ +

+

+ 用法:hadoop namenode [-format] | [-upgrade] | [-rollback] | [-finalize] | [-importCheckpoint] +

+ + + + + + + + + + + + + + + + + + + + + + + +
命令选项 æè¿°
-formatæ ¼å¼åŒ–namenode。它å¯åŠ¨namenode,格å¼åŒ–namenode,之åŽå…³é—­namenode。
-upgrade分å‘新版本的hadoopåŽï¼Œnamenode应以upgrade选项å¯åŠ¨ã€‚
-rollbackå°†namenode回滚到å‰ä¸€ç‰ˆæœ¬ã€‚这个选项è¦åœ¨åœæ­¢é›†ç¾¤ï¼Œåˆ†å‘è€çš„hadoop版本åŽä½¿ç”¨ã€‚ +
-finalizefinalize会删除文件系统的å‰ä¸€çŠ¶æ€ã€‚最近的å‡çº§ä¼šè¢«æŒä¹…化,rollback选项将å†ä¸å¯ç”¨ï¼Œå‡çº§ç»ˆç»“æ“作之åŽï¼Œå®ƒä¼šåœæŽ‰namenode。
-importCheckpoint从检查点目录装载镜åƒå¹¶ä¿å­˜åˆ°å½“å‰æ£€æŸ¥ç‚¹ç›®å½•ï¼Œæ£€æŸ¥ç‚¹ç›®å½•ç”±fs.checkpoint.dir指定。 +
+
+ +
+ secondarynamenode +

+ è¿è¡ŒHDFSçš„secondary namenode。å‚考Secondary Namenode了解更多。 +

+

+ 用法:hadoop secondarynamenode [-checkpoint [force]] | [-geteditsize] +

+ + + + + + + + + + + +
命令选项 æè¿°
-checkpoint [force]如果EditLogçš„å¤§å° >= fs.checkpoint.size,å¯åŠ¨Secondary namenode的检查点过程。 + 如果使用了-force,将ä¸è€ƒè™‘EditLog的大å°ã€‚
-geteditsize打å°EditLog大å°ã€‚
+
+ +
+ tasktracker +

+ è¿è¡ŒMapReduceçš„task Tracker节点。 +

+

+ 用法:hadoop tasktracker +

+
+ +
+ + + + + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/distcp.xml b/src/docs/cn/src/documentation/content/xdocs/distcp.xml new file mode 100644 index 00000000000..3fda68dc46b --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/distcp.xml @@ -0,0 +1,294 @@ + + + + + + + +
+ DistCp +
+ + + +
+ 概述 + +

DistCp(分布å¼æ‹·è´ï¼‰æ˜¯ç”¨äºŽå¤§è§„模集群内部和集群之间拷è´çš„工具。 + 它使用Map/Reduce实现文件分å‘,错误处ç†å’Œæ¢å¤ï¼Œä»¥åŠæŠ¥å‘Šç”Ÿæˆã€‚ + 它把文件和目录的列表作为map任务的输入,æ¯ä¸ªä»»åŠ¡ä¼šå®Œæˆæºåˆ—表中部分文件的拷è´ã€‚ + 由于使用了Map/Reduce方法,这个工具在语义和执行上都会有特殊的地方。 + 这篇文档会为常用DistCpæ“作æ供指å—并é˜è¿°å®ƒçš„工作模型。 +

+ +
+ +
+ 使用方法 + +
+ 基本使用方法 +

DistCp最常用在集群之间的拷è´ï¼š

+

bash$ hadoop distcp hdfs://nn1:8020/foo/bar \
+           +           + hdfs://nn2:8020/bar/foo

+ +

è¿™æ¡å‘½ä»¤ä¼šæŠŠnn1集群的/foo/bar目录下的所有文件或目录å展开并存储到一个临时文件中,这些文件内容的拷è´å·¥ä½œè¢«åˆ†é…给多个map任务, + 然åŽæ¯ä¸ªTaskTracker分别执行从nn1到nn2çš„æ‹·è´æ“作。注æ„DistCp使用ç»å¯¹è·¯å¾„进行æ“作。 +

+ +

命令行中å¯ä»¥æŒ‡å®šå¤šä¸ªæºç›®å½•ï¼š

+

bash$ hadoop distcp hdfs://nn1:8020/foo/a \
+           +           + hdfs://nn1:8020/foo/b \
+           +           + hdfs://nn2:8020/bar/foo

+ +

或者使用-f选项,从文件里获得多个æºï¼š
+ bash$ hadoop distcp -f hdfs://nn1:8020/srclist \
+            +            +  hdfs://nn2:8020/bar/foo

+ +

其中srclist 的内容是
+     hdfs://nn1:8020/foo/a
+     hdfs://nn1:8020/foo/b

+ +

当从多个æºæ‹·è´æ—¶ï¼Œå¦‚果两个æºå†²çªï¼ŒDistCp会åœæ­¢æ‹·è´å¹¶æ示出错信æ¯ï¼Œ + 如果在目的ä½ç½®å‘生冲çªï¼Œä¼šæ ¹æ®é€‰é¡¹è®¾ç½®è§£å†³ã€‚ + 默认情况会跳过已ç»å­˜åœ¨çš„目标文件(比如ä¸ç”¨æºæ–‡ä»¶åšæ›¿æ¢æ“作)。æ¯æ¬¡æ“作结æŸæ—¶ + 都会报告跳过的文件数目,但是如果æŸäº›æ‹·è´æ“作失败了,但在之åŽçš„å°è¯•æˆåŠŸäº†ï¼Œ + 那么报告的信æ¯å¯èƒ½ä¸å¤Ÿç²¾ç¡®ï¼ˆè¯·å‚考附录)。 +

+ +

æ¯ä¸ªTaskTracker必须都能够与æºç«¯å’Œç›®çš„端文件系统进行访问和交互。 + 对于HDFSæ¥è¯´ï¼Œæºå’Œç›®çš„端è¦è¿è¡Œç›¸åŒç‰ˆæœ¬çš„å议或者使用å‘下兼容的å议。 + (请å‚考ä¸åŒç‰ˆæœ¬é—´çš„æ‹·è´ ï¼‰ã€‚ +

+ +

æ‹·è´å®ŒæˆåŽï¼Œå»ºè®®ç”Ÿæˆæºç«¯å’Œç›®çš„端文件的列表,并交å‰æ£€æŸ¥ï¼Œæ¥ç¡®è®¤æ‹·è´çœŸæ­£æˆåŠŸã€‚ + 因为DistCp使用Map/Reduce和文件系统API进行æ“作,所以这三者或它们之间有任何问题 + 都会影å“æ‹·è´æ“作。一些Distcp命令的æˆåŠŸæ‰§è¡Œå¯ä»¥é€šè¿‡å†æ¬¡æ‰§è¡Œå¸¦-updateå‚数的该命令æ¥å®Œæˆï¼Œ + 但用户在如此æ“作之å‰åº”该对该命令的语法很熟悉。 +

+ +

值得注æ„的是,当å¦ä¸€ä¸ªå®¢æˆ·ç«¯åŒæ—¶åœ¨å‘æºæ–‡ä»¶å†™å…¥æ—¶ï¼Œæ‹·è´å¾ˆæœ‰å¯èƒ½ä¼šå¤±è´¥ã€‚ + å°è¯•è¦†ç›–HDFS上正在被写入的文件的æ“作也会失败。 + 如果一个æºæ–‡ä»¶åœ¨æ‹·è´ä¹‹å‰è¢«ç§»åŠ¨æˆ–删除了,拷è´å¤±è´¥åŒæ—¶è¾“出异常 + FileNotFoundException。

+ +
+ +
+ 选项 + +
+ 选项索引 + + + + + + + + + + + + + + + + + + + + + + + + + +
标识 æè¿° 备注
-p[rbugp]Preserve
+   r: replication number
+   b: block size
+   u: user
+   g: group
+   p: permission
修改次数ä¸ä¼šè¢«ä¿ç•™ã€‚并且当指定 + -update 时,更新的状æ€ä¸ä¼š + 被åŒæ­¥ï¼Œé™¤éžæ–‡ä»¶å¤§å°ä¸åŒï¼ˆæ¯”如文件被é‡æ–°åˆ›å»ºï¼‰ã€‚ +
-i忽略失败就åƒåœ¨ 附录中æ到的,这个选项会比默认情况æ供关于拷è´çš„更精确的统计, åŒæ—¶å®ƒè¿˜å°†ä¿ç•™å¤±è´¥æ‹·è´æ“作的日志,这些日志信æ¯å¯ä»¥ç”¨äºŽè°ƒè¯•ã€‚最åŽï¼Œå¦‚果一个map失败了,但并没完æˆæ‰€æœ‰åˆ†å—任务的å°è¯•ï¼Œè¿™ä¸ä¼šå¯¼è‡´æ•´ä¸ªä½œä¸šçš„失败。 +
-log <logdir>记录日志到 <logdir>DistCp为æ¯ä¸ªæ–‡ä»¶çš„æ¯æ¬¡å°è¯•æ‹·è´æ“作都记录日志,并把日志作为map的输出。 + 如果一个map失败了,当é‡æ–°æ‰§è¡Œæ—¶è¿™ä¸ªæ—¥å¿—ä¸ä¼šè¢«ä¿ç•™ã€‚ +
-m <num_maps>åŒæ—¶æ‹·è´çš„最大数目指定了拷è´æ•°æ®æ—¶map的数目。请注æ„并ä¸æ˜¯map数越多åžåé‡è¶Šå¤§ã€‚ +
-overwrite覆盖目标如果一个map失败并且没有使用-i选项,ä¸ä»…仅那些拷è´å¤±è´¥çš„文件,这个分å—任务中的所有文件都会被é‡æ–°æ‹·è´ã€‚ + å°±åƒä¸‹é¢æ到的,它会改å˜ç”Ÿæˆç›®æ ‡è·¯å¾„的语义,所以 + 用户è¦å°å¿ƒä½¿ç”¨è¿™ä¸ªé€‰é¡¹ã€‚ +
-update如果æºå’Œç›®æ ‡çš„大å°ä¸ä¸€æ ·åˆ™è¿›è¡Œè¦†ç›–åƒä¹‹å‰æ到的,这ä¸æ˜¯"åŒæ­¥"æ“作。 + 执行覆盖的唯一标准是æºæ–‡ä»¶å’Œç›®æ ‡æ–‡ä»¶å¤§å°æ˜¯å¦ç›¸åŒï¼›å¦‚æžœä¸åŒï¼Œåˆ™æºæ–‡ä»¶æ›¿æ¢ç›®æ ‡æ–‡ä»¶ã€‚ + åƒ ä¸‹é¢æ到的,它也改å˜ç”Ÿæˆç›®æ ‡è·¯å¾„的语义, + 用户使用è¦å°å¿ƒã€‚ +
-f <urilist_uri>使用<urilist_uri> 作为æºæ–‡ä»¶åˆ—表这等价于把所有文件å列在命令行中。 + urilist_uri 列表应该是完整åˆæ³•çš„URI。 +
+ +
+ +
+ 更新和覆盖 + +

这里给出一些 -updateå’Œ -overwrite的例å­ã€‚ + 考虑一个从/foo/a å’Œ + /foo/b 到 /bar/fooçš„æ‹·è´ï¼Œæºè·¯å¾„包括: +

+ +

    hdfs://nn1:8020/foo/a
+     hdfs://nn1:8020/foo/a/aa
+     hdfs://nn1:8020/foo/a/ab
+     hdfs://nn1:8020/foo/b
+     hdfs://nn1:8020/foo/b/ba
+     hdfs://nn1:8020/foo/b/ab

+ +

如果没设置-update或 -overwrite选项, + 那么两个æºéƒ½ä¼šæ˜ å°„到目标端的 + /bar/foo/ab。 + 如果设置了这两个选项,æ¯ä¸ªæºç›®å½•çš„内容都会和目标目录的 + 内容 åšæ¯”较。DistCp碰到这类冲çªçš„情况会终止æ“作并退出。

+ +

默认情况下,/bar/foo/a å’Œ + /bar/foo/b 目录都会被创建,所以并ä¸ä¼šæœ‰å†²çªã€‚

+ +

现在考虑一个使用-updateåˆæ³•çš„æ“作:
+ distcp -update hdfs://nn1:8020/foo/a \
+         +        + hdfs://nn1:8020/foo/b \
+         +        + hdfs://nn2:8020/bar

+ +

其中æºè·¯å¾„/大å°:

+ +

    hdfs://nn1:8020/foo/a
+     hdfs://nn1:8020/foo/a/aa 32
+     hdfs://nn1:8020/foo/a/ab 32
+     hdfs://nn1:8020/foo/b
+     hdfs://nn1:8020/foo/b/ba 64
+     hdfs://nn1:8020/foo/b/bb 32

+ +

和目的路径/大å°:

+ +

    hdfs://nn2:8020/bar
+     hdfs://nn2:8020/bar/aa 32
+     hdfs://nn2:8020/bar/ba 32
+     hdfs://nn2:8020/bar/bb 64

+ +

会产生:

+ +

    hdfs://nn2:8020/bar
+     hdfs://nn2:8020/bar/aa 32
+     hdfs://nn2:8020/bar/ab 32
+     hdfs://nn2:8020/bar/ba 64
+     hdfs://nn2:8020/bar/bb 32

+ +

åªæœ‰nn2çš„aa文件没有被覆盖。如果指定了 + -overwrite选项,所有文件都会被覆盖。 +

+ +
+ +
+ +
+ +
+ 附录 + +
+ Mapæ•°ç›® + +

DistCp会å°è¯•ç€å‡åˆ†éœ€è¦æ‹·è´çš„内容,这样æ¯ä¸ªmapæ‹·è´å·®ä¸å¤šç›¸ç­‰å¤§å°çš„内容。 + 但因为文件是最å°çš„æ‹·è´ç²’度,所以é…置增加åŒæ—¶æ‹·è´ï¼ˆå¦‚map)的数目ä¸ä¸€å®šä¼šå¢žåŠ å®žé™…åŒæ—¶æ‹·è´çš„数目以åŠæ€»åžåé‡ã€‚ +

+ +

如果没使用-m选项,DistCp会å°è¯•åœ¨è°ƒåº¦å·¥ä½œæ—¶æŒ‡å®šmapçš„æ•°ç›® + 为 min (total_bytes / bytes.per.map, 20 * num_task_trackers), + 其中bytes.per.map默认是256MB。

+ +

建议对于长时间è¿è¡Œæˆ–定期è¿è¡Œçš„作业,根æ®æºå’Œç›®æ ‡é›†ç¾¤å¤§å°ã€æ‹·è´æ•°é‡å¤§å°ä»¥åŠå¸¦å®½è°ƒæ•´map的数目。 +

+ +
+ +
+ ä¸åŒHDFSç‰ˆæœ¬é—´çš„æ‹·è´ + +

对于ä¸åŒHadoop版本间的拷è´ï¼Œç”¨æˆ·åº”该使用HftpFileSystem。 + 这是一个åªè¯»æ–‡ä»¶ç³»ç»Ÿï¼Œæ‰€ä»¥DistCpå¿…é¡»è¿è¡Œåœ¨ç›®æ ‡ç«¯é›†ç¾¤ä¸Šï¼ˆæ›´ç¡®åˆ‡çš„说是在能够写入目标集群的TaskTracker上)。 + æºçš„æ ¼å¼æ˜¯ + hftp://<dfs.http.address>/<path> + (默认情况dfs.http.address是 + <namenode>:50070)。

+ +
+ +
+ Map/Reduce和副效应 + +

åƒå‰é¢æ到的,mapæ‹·è´è¾“入文件失败时,会带æ¥ä¸€äº›å‰¯æ•ˆåº”。 +

+ +
    + +
  • 除éžä½¿ç”¨äº†-i,任务产生的日志会被新的å°è¯•æ›¿æ¢æŽ‰ã€‚ +
  • + +
  • 除éžä½¿ç”¨äº†-overwrite,文件被之å‰çš„mapæˆåŠŸæ‹·è´åŽå½“åˆä¸€æ¬¡æ‰§è¡Œæ‹·è´æ—¶ä¼šè¢«æ ‡è®°ä¸º + "被忽略"。
  • + +
  • 如果map失败了mapred.map.max.attempts次,剩下的map任务会被终止(除éžä½¿ç”¨äº†-i)。 +
  • + +
  • 如果mapred.speculative.execution被设置为 + finalå’Œtrue,则拷è´çš„结果是未定义的。
  • + +
+ +
+ + + +
+ + + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hadoop_archives.xml b/src/docs/cn/src/documentation/content/xdocs/hadoop_archives.xml new file mode 100644 index 00000000000..8a610f65a7f --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hadoop_archives.xml @@ -0,0 +1,69 @@ + + + + +
+ Hadoop Archives +
+ +
+ 什么是Hadoop archives? +

+ Hadoop archives是特殊的档案格å¼ã€‚一个Hadoop archive对应一个文件系统目录。 + Hadoop archive的扩展å是*.har。Hadoop archive包å«å…ƒæ•°æ®ï¼ˆå½¢å¼æ˜¯_indexå’Œ_masterindx)和数æ®ï¼ˆpart-*)文件。_index文件包å«äº†æ¡£æ¡ˆä¸­çš„文件的文件åå’Œä½ç½®ä¿¡æ¯ã€‚ +

+
+
+ 如何创建archive? +

+ 用法: hadoop archive -archiveName name <src>* <dest> +

+

+ ç”±-archiveName选项指定你è¦åˆ›å»ºçš„archiveçš„å字。比如foo.har。archiveçš„å字的扩展å应该是*.har。输入是文件系统的路径å,路径åçš„æ ¼å¼å’Œå¹³æ—¶çš„表达方å¼ä¸€æ ·ã€‚创建的archive会ä¿å­˜åˆ°ç›®æ ‡ç›®å½•ä¸‹ã€‚注æ„创建archives是一个Map/Reduce job。你应该在map reduce集群上è¿è¡Œè¿™ä¸ªå‘½ä»¤ã€‚下é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š +

+

+ hadoop archive -archiveName foo.har /user/hadoop/dir1 /user/hadoop/dir2 /user/zoo/ +

+ 在上é¢çš„例å­ä¸­ï¼Œ + /user/hadoop/dir1 å’Œ /user/hadoop/dir2 会被归档到这个文件系统目录下 + -- /user/zoo/foo.har。当创建archive时,æºæ–‡ä»¶ä¸ä¼šè¢«æ›´æ”¹æˆ–删除。 +

+
+
+ 如何查看archives中的文件? +

+ archive作为文件系统层暴露给外界。所以所有的fs shell命令都能在archive上è¿è¡Œï¼Œä½†æ˜¯è¦ä½¿ç”¨ä¸åŒçš„URI。 + å¦å¤–,archive是ä¸å¯æ”¹å˜çš„。所以é‡å‘½å,删除和创建都会返回错误。Hadoop Archives çš„URI是 +

har://scheme-hostname:port/archivepath/fileinarchive

+ 如果没æä¾›scheme-hostname,它会使用默认的文件系统。这ç§æƒ…况下URI是这ç§å½¢å¼ +

+ har:///archivepath/fileinarchive

+

+ 这是一个archive的例å­ã€‚archive的输入是/dir。这个dir目录包å«æ–‡ä»¶filea,fileb。 + 把/dir归档到/user/hadoop/foo.bar的命令是 +

+

hadoop archive -archiveName foo.har /dir /user/hadoop +

+ 获得创建的archive中的文件列表,使用命令 +

+

hadoop dfs -lsr har:///user/hadoop/foo.har

+

查看archive中的filea文件的命令- +

hadoop dfs -cat har:///user/hadoop/foo.har/dir/filea

+
+ +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hdfs_design.xml b/src/docs/cn/src/documentation/content/xdocs/hdfs_design.xml new file mode 100644 index 00000000000..86f0697792c --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hdfs_design.xml @@ -0,0 +1,376 @@ + + + + + + + + +
+ + Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿï¼šæž¶æž„和设计 + + + + +
+ + +
+ 引言 +

+ Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿ(HDFS)被设计æˆé€‚åˆè¿è¡Œåœ¨é€šç”¨ç¡¬ä»¶(commodity hardware)上的分布å¼æ–‡ä»¶ç³»ç»Ÿã€‚它和现有的分布å¼æ–‡ä»¶ç³»ç»Ÿæœ‰å¾ˆå¤šå…±åŒç‚¹ã€‚但åŒæ—¶ï¼Œå®ƒå’Œå…¶ä»–的分布å¼æ–‡ä»¶ç³»ç»Ÿçš„区别也是很明显的。HDFS是一个高度容错性的系统,适åˆéƒ¨ç½²åœ¨å»‰ä»·çš„机器上。HDFS能æ供高åžåé‡çš„æ•°æ®è®¿é—®ï¼Œéžå¸¸é€‚åˆå¤§è§„模数æ®é›†ä¸Šçš„应用。HDFS放宽了一部分POSIX约æŸï¼Œæ¥å®žçŽ°æµå¼è¯»å–文件系统数æ®çš„目的。HDFS在最开始是作为Apache Nutchæœç´¢å¼•æ“Žé¡¹ç›®çš„基础架构而开å‘的。HDFS是Apache Hadoop Core项目的一部分。这个项目的地å€æ˜¯http://hadoop.apache.org/core/。 +

+
+ +
+ å‰æ和设计目标 + +
+ 硬件错误 +

+ 硬件错误是常æ€è€Œä¸æ˜¯å¼‚常。HDFSå¯èƒ½ç”±æˆç™¾ä¸Šåƒçš„æœåŠ¡å™¨æ‰€æž„æˆï¼Œæ¯ä¸ªæœåŠ¡å™¨ä¸Šå­˜å‚¨ç€æ–‡ä»¶ç³»ç»Ÿçš„部分数æ®ã€‚我们é¢å¯¹çš„现实是构æˆç³»ç»Ÿçš„组件数目是巨大的,而且任一组件都有å¯èƒ½å¤±æ•ˆï¼Œè¿™æ„味ç€æ€»æ˜¯æœ‰ä¸€éƒ¨åˆ†HDFS的组件是ä¸å·¥ä½œçš„。因此错误检测和快速ã€è‡ªåŠ¨çš„æ¢å¤æ˜¯HDFS最核心的架构目标。 +

+
+
+ æµå¼æ•°æ®è®¿é—® +

+è¿è¡Œåœ¨HDFS上的应用和普通的应用ä¸åŒï¼Œéœ€è¦æµå¼è®¿é—®å®ƒä»¬çš„æ•°æ®é›†ã€‚HDFS的设计中更多的考虑到了数æ®æ‰¹å¤„ç†ï¼Œè€Œä¸æ˜¯ç”¨æˆ·äº¤äº’处ç†ã€‚比之数æ®è®¿é—®çš„低延迟问题,更关键的在于数æ®è®¿é—®çš„高åžåé‡ã€‚POSIX标准设置的很多硬性约æŸå¯¹HDFS应用系统ä¸æ˜¯å¿…需的。为了æ高数æ®çš„åžåé‡ï¼Œåœ¨ä¸€äº›å…³é”®æ–¹é¢å¯¹POSIX的语义åšäº†ä¸€äº›ä¿®æ”¹ã€‚ +

+
+ +
+ 大规模数æ®é›† +

+ è¿è¡Œåœ¨HDFS上的应用具有很大的数æ®é›†ã€‚HDFS上的一个典型文件大å°ä¸€èˆ¬éƒ½åœ¨G字节至T字节。因此,HDFS被调节以支æŒå¤§æ–‡ä»¶å­˜å‚¨ã€‚它应该能æ供整体上高的数æ®ä¼ è¾“带宽,能在一个集群里扩展到数百个节点。一个å•ä¸€çš„HDFS实例应该能支撑数以åƒä¸‡è®¡çš„文件。 +

+
+ + +
+ 简å•çš„一致性模型 + +

+ HDFS应用需è¦ä¸€ä¸ªâ€œä¸€æ¬¡å†™å…¥å¤šæ¬¡è¯»å–â€çš„文件访问模型。一个文件ç»è¿‡åˆ›å»ºã€å†™å…¥å’Œå…³é—­ä¹‹åŽå°±ä¸éœ€è¦æ”¹å˜ã€‚这一å‡è®¾ç®€åŒ–了数æ®ä¸€è‡´æ€§é—®é¢˜ï¼Œå¹¶ä¸”使高åžåé‡çš„æ•°æ®è®¿é—®æˆä¸ºå¯èƒ½ã€‚Map/Reduce应用或者网络爬虫应用都éžå¸¸é€‚åˆè¿™ä¸ªæ¨¡åž‹ã€‚ç›®å‰è¿˜æœ‰è®¡åˆ’在将æ¥æ‰©å……这个模型,使之支æŒæ–‡ä»¶çš„附加写æ“作。 +

+ +
+ + +
+ “移动计算比移动数æ®æ›´åˆ’ç®—” +

+ 一个应用请求的计算,离它æ“作的数æ®è¶Šè¿‘就越高效,在数æ®è¾¾åˆ°æµ·é‡çº§åˆ«çš„时候更是如此。因为这样就能é™ä½Žç½‘络阻塞的影å“,æ高系统数æ®çš„åžåé‡ã€‚将计算移动到数æ®é™„近,比之将数æ®ç§»åŠ¨åˆ°åº”用所在显然更好。HDFS为应用æ供了将它们自己移动到数æ®é™„近的接å£ã€‚ +

+
+ + +
+ 异构软硬件平å°é—´çš„å¯ç§»æ¤æ€§ +

+ HDFS在设计的时候就考虑到平å°çš„å¯ç§»æ¤æ€§ã€‚è¿™ç§ç‰¹æ€§æ–¹ä¾¿äº†HDFS作为大规模数æ®åº”用平å°çš„推广。 +

+
+
+ + +
+ Namenode 和 Datanode + +

+ HDFS采用master/slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组æˆã€‚Namenode是一个中心æœåŠ¡å™¨ï¼Œè´Ÿè´£ç®¡ç†æ–‡ä»¶ç³»ç»Ÿçš„å字空间(namespace)以åŠå®¢æˆ·ç«¯å¯¹æ–‡ä»¶çš„访问。集群中的Datanode一般是一个节点一个,负责管ç†å®ƒæ‰€åœ¨èŠ‚点上的存储。HDFS暴露了文件系统的å字空间,用户能够以文件的形å¼åœ¨ä¸Šé¢å­˜å‚¨æ•°æ®ã€‚从内部看,一个文件其实被分æˆä¸€ä¸ªæˆ–多个数æ®å—,这些å—存储在一组Datanode上。Namenode执行文件系统的å字空间æ“作,比如打开ã€å…³é—­ã€é‡å‘½å文件或目录。它也负责确定数æ®å—到具体Datanode节点的映射。Datanode负责处ç†æ–‡ä»¶ç³»ç»Ÿå®¢æˆ·ç«¯çš„读写请求。在Namenode的统一调度下进行数æ®å—的创建ã€åˆ é™¤å’Œå¤åˆ¶ã€‚ +

+ +
+

+ Namenodeå’ŒDatanode被设计æˆå¯ä»¥åœ¨æ™®é€šçš„商用机器上è¿è¡Œã€‚这些机器一般è¿è¡Œç€GNU/Linuxæ“作系统(OS)。HDFS采用Java语言开å‘,因此任何支æŒJava的机器都å¯ä»¥éƒ¨ç½²Namenode或Datanode。由于采用了å¯ç§»æ¤æ€§æžå¼ºçš„Java语言,使得HDFSå¯ä»¥éƒ¨ç½²åˆ°å¤šç§ç±»åž‹çš„机器上。一个典型的部署场景是一å°æœºå™¨ä¸Šåªè¿è¡Œä¸€ä¸ªNamenode实例,而集群中的其它机器分别è¿è¡Œä¸€ä¸ªDatanode实例。这ç§æž¶æž„并ä¸æŽ’斥在一å°æœºå™¨ä¸Šè¿è¡Œå¤šä¸ªDatanode,åªä¸è¿‡è¿™æ ·çš„情况比较少è§ã€‚ +

+

+ 集群中å•ä¸€Namenode的结构大大简化了系统的架构。Namenode是所有HDFS元数æ®çš„仲è£è€…和管ç†è€…,这样,用户数æ®æ°¸è¿œä¸ä¼šæµè¿‡Namenode。 +

+
+ +
+ 文件系统的å字空间 (namespace) +

+ HDFS支æŒä¼ ç»Ÿçš„层次型文件组织结构。用户或者应用程åºå¯ä»¥åˆ›å»ºç›®å½•ï¼Œç„¶åŽå°†æ–‡ä»¶ä¿å­˜åœ¨è¿™äº›ç›®å½•é‡Œã€‚文件系统å字空间的层次结构和大多数现有的文件系统类似:用户å¯ä»¥åˆ›å»ºã€åˆ é™¤ã€ç§»åŠ¨æˆ–é‡å‘½å文件。当å‰ï¼ŒHDFSä¸æ”¯æŒç”¨æˆ·ç£ç›˜é…é¢å’Œè®¿é—®æƒé™æŽ§åˆ¶ï¼Œä¹Ÿä¸æ”¯æŒç¡¬é“¾æŽ¥å’Œè½¯é“¾æŽ¥ã€‚但是HDFS架构并ä¸å¦¨ç¢å®žçŽ°è¿™äº›ç‰¹æ€§ã€‚ +

+

+ Namenode负责维护文件系统的å字空间,任何对文件系统å字空间或属性的修改都将被Namenode记录下æ¥ã€‚应用程åºå¯ä»¥è®¾ç½®HDFSä¿å­˜çš„文件的副本数目。文件副本的数目称为文件的副本系数,这个信æ¯ä¹Ÿæ˜¯ç”±Namenodeä¿å­˜çš„。 +

+
+ +
+ æ•°æ®å¤åˆ¶ +

+ HDFS被设计æˆèƒ½å¤Ÿåœ¨ä¸€ä¸ªå¤§é›†ç¾¤ä¸­è·¨æœºå™¨å¯é åœ°å­˜å‚¨è¶…大文件。它将æ¯ä¸ªæ–‡ä»¶å­˜å‚¨æˆä¸€ç³»åˆ—çš„æ•°æ®å—,除了最åŽä¸€ä¸ªï¼Œæ‰€æœ‰çš„æ•°æ®å—都是åŒæ ·å¤§å°çš„。为了容错,文件的所有数æ®å—都会有副本。æ¯ä¸ªæ–‡ä»¶çš„æ•°æ®å—大å°å’Œå‰¯æœ¬ç³»æ•°éƒ½æ˜¯å¯é…置的。应用程åºå¯ä»¥æŒ‡å®šæŸä¸ªæ–‡ä»¶çš„副本数目。副本系数å¯ä»¥åœ¨æ–‡ä»¶åˆ›å»ºçš„时候指定,也å¯ä»¥åœ¨ä¹‹åŽæ”¹å˜ã€‚HDFS中的文件都是一次性写入的,并且严格è¦æ±‚在任何时候åªèƒ½æœ‰ä¸€ä¸ªå†™å…¥è€…。 +

+

+ Namenodeå…¨æƒç®¡ç†æ•°æ®å—çš„å¤åˆ¶ï¼Œå®ƒå‘¨æœŸæ€§åœ°ä»Žé›†ç¾¤ä¸­çš„æ¯ä¸ªDatanode接收心跳信å·å’Œå—状æ€æŠ¥å‘Š(Blockreport)。接收到心跳信å·æ„味ç€è¯¥Datanode节点工作正常。å—状æ€æŠ¥å‘ŠåŒ…å«äº†ä¸€ä¸ªè¯¥Datanode上所有数æ®å—的列表。 +

+
+ +
+ 副本存放: 最最开始的一步 +

+ 副本的存放是HDFSå¯é æ€§å’Œæ€§èƒ½çš„关键。优化的副本存放策略是HDFS区分于其他大部分分布å¼æ–‡ä»¶ç³»ç»Ÿçš„é‡è¦ç‰¹æ€§ã€‚è¿™ç§ç‰¹æ€§éœ€è¦åšå¤§é‡çš„调优,并需è¦ç»éªŒçš„积累。HDFS采用一ç§ç§°ä¸ºæœºæž¶æ„ŸçŸ¥(rack-aware)çš„ç­–ç•¥æ¥æ”¹è¿›æ•°æ®çš„å¯é æ€§ã€å¯ç”¨æ€§å’Œç½‘络带宽的利用率。目å‰å®žçŽ°çš„副本存放策略åªæ˜¯åœ¨è¿™ä¸ªæ–¹å‘上的第一步。实现这个策略的短期目标是验è¯å®ƒåœ¨ç”Ÿäº§çŽ¯å¢ƒä¸‹çš„有效性,观察它的行为,为实现更先进的策略打下测试和研究的基础。 +

+

+ 大型HDFS实例一般è¿è¡Œåœ¨è·¨è¶Šå¤šä¸ªæœºæž¶çš„计算机组æˆçš„集群上,ä¸åŒæœºæž¶ä¸Šçš„两å°æœºå™¨ä¹‹é—´çš„通讯需è¦ç»è¿‡äº¤æ¢æœºã€‚在大多数情况下,åŒä¸€ä¸ªæœºæž¶å†…的两å°æœºå™¨é—´çš„带宽会比ä¸åŒæœºæž¶çš„两å°æœºå™¨é—´çš„带宽大。 +

+

+ 通过一个机架感知的过程,Namenodeå¯ä»¥ç¡®å®šæ¯ä¸ªDatanode所属的机架id。一个简å•ä½†æ²¡æœ‰ä¼˜åŒ–的策略就是将副本存放在ä¸åŒçš„机架上。这样å¯ä»¥æœ‰æ•ˆé˜²æ­¢å½“整个机架失效时数æ®çš„丢失,并且å…许读数æ®çš„时候充分利用多个机架的带宽。这ç§ç­–略设置å¯ä»¥å°†å‰¯æœ¬å‡åŒ€åˆ†å¸ƒåœ¨é›†ç¾¤ä¸­ï¼Œæœ‰åˆ©äºŽå½“组件失效情况下的负载å‡è¡¡ã€‚但是,因为这ç§ç­–略的一个写æ“作需è¦ä¼ è¾“æ•°æ®å—到多个机架,这增加了写的代价。 +

+

+ 在大多数情况下,副本系数是3,HDFS的存放策略是将一个副本存放在本地机架的节点上,一个副本放在åŒä¸€æœºæž¶çš„å¦ä¸€ä¸ªèŠ‚点上,最åŽä¸€ä¸ªå‰¯æœ¬æ”¾åœ¨ä¸åŒæœºæž¶çš„节点上。这ç§ç­–ç•¥å‡å°‘了机架间的数æ®ä¼ è¾“,这就æ高了写æ“作的效率。机架的错误远远比节点的错误少,所以这个策略ä¸ä¼šå½±å“到数æ®çš„å¯é æ€§å’Œå¯ç”¨æ€§ã€‚于此åŒæ—¶ï¼Œå› ä¸ºæ•°æ®å—åªæ”¾åœ¨ä¸¤ä¸ªï¼ˆä¸æ˜¯ä¸‰ä¸ªï¼‰ä¸åŒçš„机架上,所以此策略å‡å°‘了读å–æ•°æ®æ—¶éœ€è¦çš„网络传输总带宽。在这ç§ç­–略下,副本并ä¸æ˜¯å‡åŒ€åˆ†å¸ƒåœ¨ä¸åŒçš„机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,其他副本å‡åŒ€åˆ†å¸ƒåœ¨å‰©ä¸‹çš„机架中,这一策略在ä¸æŸå®³æ•°æ®å¯é æ€§å’Œè¯»å–性能的情况下改进了写的性能。 +

+

+ 当å‰ï¼Œè¿™é‡Œä»‹ç»çš„默认副本存放策略正在开å‘的过程中。 +

+
+ +
+ 副本选择 +

+ 为了é™ä½Žæ•´ä½“的带宽消耗和读å–延时,HDFS会尽é‡è®©è¯»å–程åºè¯»å–离它最近的副本。如果在读å–程åºçš„åŒä¸€ä¸ªæœºæž¶ä¸Šæœ‰ä¸€ä¸ªå‰¯æœ¬ï¼Œé‚£ä¹ˆå°±è¯»å–该副本。如果一个HDFS集群跨越多个数æ®ä¸­å¿ƒï¼Œé‚£ä¹ˆå®¢æˆ·ç«¯ä¹Ÿå°†é¦–先读本地数æ®ä¸­å¿ƒçš„副本。 +

+
+ +
+ å®‰å…¨æ¨¡å¼ +

+ Namenodeå¯åŠ¨åŽä¼šè¿›å…¥ä¸€ä¸ªç§°ä¸ºå®‰å…¨æ¨¡å¼çš„特殊状æ€ã€‚处于安全模å¼çš„Namenode是ä¸ä¼šè¿›è¡Œæ•°æ®å—çš„å¤åˆ¶çš„。Namenode从所有的 Datanode接收心跳信å·å’Œå—状æ€æŠ¥å‘Šã€‚å—状æ€æŠ¥å‘ŠåŒ…括了æŸä¸ªDatanode所有的数æ®å—列表。æ¯ä¸ªæ•°æ®å—都有一个指定的最å°å‰¯æœ¬æ•°ã€‚当Namenode检测确认æŸä¸ªæ•°æ®å—的副本数目达到这个最å°å€¼ï¼Œé‚£ä¹ˆè¯¥æ•°æ®å—就会被认为是副本安全(safely replicated)的;在一定百分比(这个å‚æ•°å¯é…置)的数æ®å—被Namenode检测确认是安全之åŽï¼ˆåŠ ä¸Šä¸€ä¸ªé¢å¤–çš„30秒等待时间),Namenode将退出安全模å¼çŠ¶æ€ã€‚接下æ¥å®ƒä¼šç¡®å®šè¿˜æœ‰å“ªäº›æ•°æ®å—的副本没有达到指定数目,并将这些数æ®å—å¤åˆ¶åˆ°å…¶ä»–Datanode上。 +

+
+ +
+ +
+ 文件系统元数æ®çš„æŒä¹…化 +

+ Namenode上ä¿å­˜ç€HDFSçš„å字空间。对于任何对文件系统元数æ®äº§ç”Ÿä¿®æ”¹çš„æ“作,Namenode都会使用一ç§ç§°ä¸ºEditLog的事务日志记录下æ¥ã€‚例如,在HDFS中创建一个文件,Namenode就会在Editlog中æ’入一æ¡è®°å½•æ¥è¡¨ç¤ºï¼›åŒæ ·åœ°ï¼Œä¿®æ”¹æ–‡ä»¶çš„副本系数也将往Editlogæ’入一æ¡è®°å½•ã€‚Namenode在本地æ“作系统的文件系统中存储这个Editlog。整个文件系统的å字空间,包括数æ®å—到文件的映射ã€æ–‡ä»¶çš„属性等,都存储在一个称为FsImage的文件中,这个文件也是放在Namenode所在的本地文件系统上。 +

+

+ Namenode在内存中ä¿å­˜ç€æ•´ä¸ªæ–‡ä»¶ç³»ç»Ÿçš„å字空间和文件数æ®å—映射(Blockmap)的映åƒã€‚这个关键的元数æ®ç»“构设计得很紧凑,因而一个有4G内存的Namenode足够支撑大é‡çš„文件和目录。当Namenodeå¯åŠ¨æ—¶ï¼Œå®ƒä»Žç¡¬ç›˜ä¸­è¯»å–Editlogå’ŒFsImage,将所有Editlog中的事务作用在内存中的FsImage上,并将这个新版本的FsImage从内存中ä¿å­˜åˆ°æœ¬åœ°ç£ç›˜ä¸Šï¼Œç„¶åŽåˆ é™¤æ—§çš„Editlog,因为这个旧的Editlog的事务都已ç»ä½œç”¨åœ¨FsImage上了。这个过程称为一个检查点(checkpoint)。在当å‰å®žçŽ°ä¸­ï¼Œæ£€æŸ¥ç‚¹åªå‘生在Namenodeå¯åŠ¨æ—¶ï¼Œåœ¨ä¸ä¹…çš„å°†æ¥å°†å®žçŽ°æ”¯æŒå‘¨æœŸæ€§çš„检查点。 +

+

+ Datanodeå°†HDFSæ•°æ®ä»¥æ–‡ä»¶çš„å½¢å¼å­˜å‚¨åœ¨æœ¬åœ°çš„文件系统中,它并ä¸çŸ¥é“有关HDFS文件的信æ¯ã€‚它把æ¯ä¸ªHDFSæ•°æ®å—存储在本地文件系统的一个å•ç‹¬çš„文件中。Datanode并ä¸åœ¨åŒä¸€ä¸ªç›®å½•åˆ›å»ºæ‰€æœ‰çš„文件,实际上,它用试探的方法æ¥ç¡®å®šæ¯ä¸ªç›®å½•çš„最佳文件数目,并且在适当的时候创建å­ç›®å½•ã€‚在åŒä¸€ä¸ªç›®å½•ä¸­åˆ›å»ºæ‰€æœ‰çš„本地文件并ä¸æ˜¯æœ€ä¼˜çš„选择,这是因为本地文件系统å¯èƒ½æ— æ³•é«˜æ•ˆåœ°åœ¨å•ä¸ªç›®å½•ä¸­æ”¯æŒå¤§é‡çš„文件。当一个Datanodeå¯åŠ¨æ—¶ï¼Œå®ƒä¼šæ‰«æ本地文件系统,产生一个这些本地文件对应的所有HDFSæ•°æ®å—的列表,然åŽä½œä¸ºæŠ¥å‘Šå‘é€åˆ°Namenode,这个报告就是å—状æ€æŠ¥å‘Šã€‚ +

+
+ +
+ 通讯åè®® +

+ 所有的HDFS通讯å议都是建立在TCP/IPå议之上。客户端通过一个å¯é…置的TCP端å£è¿žæŽ¥åˆ°Namenode,通过ClientProtocolå议与Namenode交互。而Datanode使用DatanodeProtocolå议与Namenode交互。一个远程过程调用(RPC)模型被抽象出æ¥å°è£…ClientProtocolå’ŒDatanodeprotocolå议。在设计上,Namenodeä¸ä¼šä¸»åŠ¨å‘èµ·RPC,而是å“应æ¥è‡ªå®¢æˆ·ç«¯æˆ– Datanode çš„RPC请求。 +

+
+ +
+ å¥å£®æ€§ +

+ HDFS的主è¦ç›®æ ‡å°±æ˜¯å³ä½¿åœ¨å‡ºé”™çš„情况下也è¦ä¿è¯æ•°æ®å­˜å‚¨çš„å¯é æ€§ã€‚常è§çš„三ç§å‡ºé”™æƒ…况是:Namenode出错, Datanode出错和网络割裂(network partitions)。 +

+ +
+ ç£ç›˜æ•°æ®é”™è¯¯ï¼Œå¿ƒè·³æ£€æµ‹å’Œé‡æ–°å¤åˆ¶ +

+ æ¯ä¸ªDatanode节点周期性地å‘Namenodeå‘é€å¿ƒè·³ä¿¡å·ã€‚网络割裂å¯èƒ½å¯¼è‡´ä¸€éƒ¨åˆ†Datanodeè·ŸNamenode失去è”系。Namenode通过心跳信å·çš„缺失æ¥æ£€æµ‹è¿™ä¸€æƒ…况,并将这些近期ä¸å†å‘é€å¿ƒè·³ä¿¡å·Datanode标记为宕机,ä¸ä¼šå†å°†æ–°çš„IO请求å‘给它们。任何存储在宕机Datanode上的数æ®å°†ä¸å†æœ‰æ•ˆã€‚Datanode的宕机å¯èƒ½ä¼šå¼•èµ·ä¸€äº›æ•°æ®å—的副本系数低于指定值,Namenodeä¸æ–­åœ°æ£€æµ‹è¿™äº›éœ€è¦å¤åˆ¶çš„æ•°æ®å—,一旦å‘现就å¯åŠ¨å¤åˆ¶æ“作。在下列情况下,å¯èƒ½éœ€è¦é‡æ–°å¤åˆ¶ï¼šæŸä¸ªDatanode节点失效,æŸä¸ªå‰¯æœ¬é­åˆ°æŸå,Datanode上的硬盘错误,或者文件的副本系数增大。 +

+
+ +
+ 集群å‡è¡¡ +

+ HDFS的架构支æŒæ•°æ®å‡è¡¡ç­–略。如果æŸä¸ªDatanode节点上的空闲空间低于特定的临界点,按照å‡è¡¡ç­–略系统就会自动地将数æ®ä»Žè¿™ä¸ªDatanode移动到其他空闲的Datanode。当对æŸä¸ªæ–‡ä»¶çš„请求çªç„¶å¢žåŠ ï¼Œé‚£ä¹ˆä¹Ÿå¯èƒ½å¯åŠ¨ä¸€ä¸ªè®¡åˆ’创建该文件新的副本,并且åŒæ—¶é‡æ–°å¹³è¡¡é›†ç¾¤ä¸­çš„其他数æ®ã€‚这些å‡è¡¡ç­–略目å‰è¿˜æ²¡æœ‰å®žçŽ°ã€‚ +

+
+ +
+ æ•°æ®å®Œæ•´æ€§ +

+ + 从æŸä¸ªDatanode获å–çš„æ•°æ®å—有å¯èƒ½æ˜¯æŸå的,æŸåå¯èƒ½æ˜¯ç”±Datanode的存储设备错误ã€ç½‘络错误或者软件bug造æˆçš„。HDFS客户端软件实现了对HDFS文件内容的校验和(checksum)检查。当客户端创建一个新的HDFS文件,会计算这个文件æ¯ä¸ªæ•°æ®å—的校验和,并将校验和作为一个å•ç‹¬çš„éšè—文件ä¿å­˜åœ¨åŒä¸€ä¸ªHDFSå字空间下。当客户端获å–文件内容åŽï¼Œå®ƒä¼šæ£€éªŒä»ŽDatanode获å–çš„æ•°æ®è·Ÿç›¸åº”的校验和文件中的校验和是å¦åŒ¹é…,如果ä¸åŒ¹é…,客户端å¯ä»¥é€‰æ‹©ä»Žå…¶ä»–Datanode获å–该数æ®å—的副本。 +

+
+
+ 元数æ®ç£ç›˜é”™è¯¯ +

+ FsImageå’ŒEditlog是HDFS的核心数æ®ç»“构。如果这些文件æŸå了,整个HDFS实例都将失效。因而,Namenodeå¯ä»¥é…ç½®æˆæ”¯æŒç»´æŠ¤å¤šä¸ªFsImageå’ŒEditlog的副本。任何对FsImage或者Editlog的修改,都将åŒæ­¥åˆ°å®ƒä»¬çš„副本上。这ç§å¤šå‰¯æœ¬çš„åŒæ­¥æ“作å¯èƒ½ä¼šé™ä½ŽNamenodeæ¯ç§’处ç†çš„å字空间事务数é‡ã€‚然而这个代价是å¯ä»¥æŽ¥å—的,因为å³ä½¿HDFS的应用是数æ®å¯†é›†çš„,它们也éžå…ƒæ•°æ®å¯†é›†çš„。当Namenodeé‡å¯çš„时候,它会选å–最近的完整的FsImageå’ŒEditlogæ¥ä½¿ç”¨ã€‚ +

+

+ Namenode是HDFS集群中的å•ç‚¹æ•…éšœ(single point of failure)所在。如果Namenode机器故障,是需è¦æ‰‹å·¥å¹²é¢„的。目å‰ï¼Œè‡ªåŠ¨é‡å¯æˆ–在å¦ä¸€å°æœºå™¨ä¸ŠåšNamenode故障转移的功能还没实现。 +

+
+ +
+ å¿«ç…§ +

+ 快照支æŒæŸä¸€ç‰¹å®šæ—¶åˆ»çš„æ•°æ®çš„å¤åˆ¶å¤‡ä»½ã€‚利用快照,å¯ä»¥è®©HDFS在数æ®æŸåæ—¶æ¢å¤åˆ°è¿‡åŽ»ä¸€ä¸ªå·²çŸ¥æ­£ç¡®çš„时间点。HDFSç›®å‰è¿˜ä¸æ”¯æŒå¿«ç…§åŠŸèƒ½ï¼Œä½†è®¡åˆ’在将æ¥çš„版本进行支æŒã€‚ +

+
+
+
+ + æ•°æ®ç»„织 + +
+ æ•°æ®å— +

+ HDFS被设计æˆæ”¯æŒå¤§æ–‡ä»¶ï¼Œé€‚用HDFS的是那些需è¦å¤„ç†å¤§è§„模的数æ®é›†çš„应用。这些应用都是åªå†™å…¥æ•°æ®ä¸€æ¬¡ï¼Œä½†å´è¯»å–一次或多次,并且读å–速度应能满足æµå¼è¯»å–的需è¦ã€‚HDFS支æŒæ–‡ä»¶çš„“一次写入多次读å–â€è¯­ä¹‰ã€‚一个典型的数æ®å—大å°æ˜¯64MB。因而,HDFS中的文件总是按照64M被切分æˆä¸åŒçš„å—,æ¯ä¸ªå—å°½å¯èƒ½åœ°å­˜å‚¨äºŽä¸åŒçš„Datanode中。 +

+
+ +
+ + Staging +

+ 客户端创建文件的请求其实并没有立å³å‘é€ç»™Namenode,事实上,在刚开始阶段HDFS客户端会先将文件数æ®ç¼“存到本地的一个临时文件。应用程åºçš„写æ“作被é€æ˜Žåœ°é‡å®šå‘到这个临时文件。当这个临时文件累积的数æ®é‡è¶…过一个数æ®å—的大å°ï¼Œå®¢æˆ·ç«¯æ‰ä¼šè”ç³»Namenode。Namenode将文件åæ’入文件系统的层次结构中,并且分é…一个数æ®å—给它。然åŽè¿”回Datanode的标识符和目标数æ®å—给客户端。接ç€å®¢æˆ·ç«¯å°†è¿™å—æ•°æ®ä»Žæœ¬åœ°ä¸´æ—¶æ–‡ä»¶ä¸Šä¼ åˆ°æŒ‡å®šçš„Datanode上。当文件关闭时,在临时文件中剩余的没有上传的数æ®ä¹Ÿä¼šä¼ è¾“到指定的Datanode上。然åŽå®¢æˆ·ç«¯å‘Šè¯‰Namenode文件已ç»å…³é—­ã€‚此时Namenodeæ‰å°†æ–‡ä»¶åˆ›å»ºæ“作æ交到日志里进行存储。如果Namenode在文件关闭å‰å®•æœºäº†ï¼Œåˆ™è¯¥æ–‡ä»¶å°†ä¸¢å¤±ã€‚ +

+

+ 上述方法是对在HDFS上è¿è¡Œçš„目标应用进行认真考虑åŽå¾—到的结果。这些应用需è¦è¿›è¡Œæ–‡ä»¶çš„æµå¼å†™å…¥ã€‚如果ä¸é‡‡ç”¨å®¢æˆ·ç«¯ç¼“存,由于网络速度和网络堵塞会对åžä¼°é‡é€ æˆæ¯”较大的影å“。这ç§æ–¹æ³•å¹¶ä¸æ˜¯æ²¡æœ‰å…ˆä¾‹çš„,早期的文件系统,比如AFS,就用客户端缓存æ¥æ高性能。为了达到更高的数æ®ä¸Šä¼ æ•ˆçŽ‡ï¼Œå·²ç»æ”¾æ¾äº†POSIX标准的è¦æ±‚。 +

+
+ +
+ æµæ°´çº¿å¤åˆ¶ +

+ 当客户端å‘HDFS文件写入数æ®çš„时候,一开始是写到本地临时文件中。å‡è®¾è¯¥æ–‡ä»¶çš„副本系数设置为3,当本地临时文件累积到一个数æ®å—的大å°æ—¶ï¼Œå®¢æˆ·ç«¯ä¼šä»ŽNamenode获å–一个Datanode列表用于存放副本。然åŽå®¢æˆ·ç«¯å¼€å§‹å‘第一个Datanode传输数æ®ï¼Œç¬¬ä¸€ä¸ªDatanode一å°éƒ¨åˆ†ä¸€å°éƒ¨åˆ†(4 KB)地接收数æ®ï¼Œå°†æ¯ä¸€éƒ¨åˆ†å†™å…¥æœ¬åœ°ä»“库,并åŒæ—¶ä¼ è¾“该部分到列表中第二个Datanode节点。第二个Datanode也是这样,一å°éƒ¨åˆ†ä¸€å°éƒ¨åˆ†åœ°æŽ¥æ”¶æ•°æ®ï¼Œå†™å…¥æœ¬åœ°ä»“库,并åŒæ—¶ä¼ ç»™ç¬¬ä¸‰ä¸ªDatanode。最åŽï¼Œç¬¬ä¸‰ä¸ªDatanode接收数æ®å¹¶å­˜å‚¨åœ¨æœ¬åœ°ã€‚因此,Datanode能æµæ°´çº¿å¼åœ°ä»Žå‰ä¸€ä¸ªèŠ‚点接收数æ®ï¼Œå¹¶åœ¨åŒæ—¶è½¬å‘给下一个节点,数æ®ä»¥æµæ°´çº¿çš„æ–¹å¼ä»Žå‰ä¸€ä¸ªDatanodeå¤åˆ¶åˆ°ä¸‹ä¸€ä¸ªã€‚ +

+
+ +
+ +
+ + å¯è®¿é—®æ€§ + +

+ HDFS给应用æ供了多ç§è®¿é—®æ–¹å¼ã€‚用户å¯ä»¥é€šè¿‡Java API接å£è®¿é—®ï¼Œä¹Ÿå¯ä»¥é€šè¿‡C语言的å°è£…API访问,还å¯ä»¥é€šè¿‡æµè§ˆå™¨çš„æ–¹å¼è®¿é—®HDFS中的文件。通过WebDAVå议访问的方å¼æ­£åœ¨å¼€å‘中。 +

+ +
+ DFSShell +

+ HDFS以文件和目录的形å¼ç»„织用户数æ®ã€‚它æ供了一个命令行的接å£(DFSShell)让用户与HDFS中的数æ®è¿›è¡Œäº¤äº’。命令的语法和用户熟悉的其他shell(例如 bash, csh)工具类似。下é¢æ˜¯ä¸€äº›åŠ¨ä½œ/命令的示例: +

+ + + + + + + + + + + + + +
动作 命令
创建一个å为 /foodir 的目录 bin/hadoop dfs -mkdir /foodir
创建一个å为 /foodir 的目录 bin/hadoop dfs -mkdir /foodir
查看å为 /foodir/myfile.txt 的文件内容 bin/hadoop dfs -cat /foodir/myfile.txt
+

+ DFSShell å¯ä»¥ç”¨åœ¨é‚£äº›é€šè¿‡è„šæœ¬è¯­è¨€å’Œæ–‡ä»¶ç³»ç»Ÿè¿›è¡Œäº¤äº’的应用程åºä¸Šã€‚ +

+
+ +
+ DFSAdmin +

+ DFSAdmin 命令用æ¥ç®¡ç†HDFS集群。这些命令åªæœ‰HDSF的管ç†å‘˜æ‰èƒ½ä½¿ç”¨ã€‚下é¢æ˜¯ä¸€äº›åŠ¨ä½œ/命令的示例: +

+ + + + + + + + + + + + + +
动作 命令
å°†é›†ç¾¤ç½®äºŽå®‰å…¨æ¨¡å¼ bin/hadoop dfsadmin -safemode enter
显示Datanode列表 bin/hadoop dfsadmin -report
使Datanode节点 datanodename退役 bin/hadoop dfsadmin -decommission datanodename
+
+ +
+ æµè§ˆå™¨æŽ¥å£ +

+ 一个典型的HDFS安装会在一个å¯é…置的TCP端å£å¼€å¯ä¸€ä¸ªWebæœåŠ¡å™¨ç”¨äºŽæš´éœ²HDFSçš„å字空间。用户å¯ä»¥ç”¨æµè§ˆå™¨æ¥æµè§ˆHDFSçš„å字空间和查看文件的内容。 +

+
+ +
+ +
+ 存储空间回收 + +
+ 文件的删除和æ¢å¤ +

+ 当用户或应用程åºåˆ é™¤æŸä¸ªæ–‡ä»¶æ—¶ï¼Œè¿™ä¸ªæ–‡ä»¶å¹¶æ²¡æœ‰ç«‹åˆ»ä»ŽHDFS中删除。实际上,HDFS会将这个文件é‡å‘½å转移到/trash目录。åªè¦æ–‡ä»¶è¿˜åœ¨/trash目录中,该文件就å¯ä»¥è¢«è¿…速地æ¢å¤ã€‚文件在/trash中ä¿å­˜çš„时间是å¯é…置的,当超过这个时间时,Namenode就会将该文件从å字空间中删除。删除文件会使得该文件相关的数æ®å—被释放。注æ„,从用户删除文件到HDFS空闲空间的增加之间会有一定时间的延迟。

+

+åªè¦è¢«åˆ é™¤çš„文件还在/trash目录中,用户就å¯ä»¥æ¢å¤è¿™ä¸ªæ–‡ä»¶ã€‚如果用户想æ¢å¤è¢«åˆ é™¤çš„文件,他/她å¯ä»¥æµè§ˆ/trash目录找回该文件。/trash目录仅仅ä¿å­˜è¢«åˆ é™¤æ–‡ä»¶çš„最åŽå‰¯æœ¬ã€‚/trash目录与其他的目录没有什么区别,除了一点:在该目录上HDFS会应用一个特殊策略æ¥è‡ªåŠ¨åˆ é™¤æ–‡ä»¶ã€‚ç›®å‰çš„默认策略是删除/trash中ä¿ç•™æ—¶é—´è¶…过6å°æ—¶çš„文件。将æ¥ï¼Œè¿™ä¸ªç­–ç•¥å¯ä»¥é€šè¿‡ä¸€ä¸ªè¢«è‰¯å¥½å®šä¹‰çš„接å£é…置。 +

+
+ +
+ å‡å°‘副本系数 +

+ 当一个文件的副本系数被å‡å°åŽï¼ŒNamenode会选择过剩的副本删除。下次心跳检测时会将该信æ¯ä¼ é€’ç»™Datanode。Datanodeé‚å³ç§»é™¤ç›¸åº”çš„æ•°æ®å—,集群中的空闲空间加大。åŒæ ·ï¼Œåœ¨è°ƒç”¨setReplication API结æŸå’Œé›†ç¾¤ä¸­ç©ºé—²ç©ºé—´å¢žåŠ é—´ä¼šæœ‰ä¸€å®šçš„延迟。

+
+
+ + +
+ å‚考资料 +

+ HDFS Java API: + + http://hadoop.apache.org/core/docs/current/api/ + +

+

+ HDFS æºä»£ç : + + http://hadoop.apache.org/core/version_control.html + +

+
+ + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hdfs_permissions_guide.xml b/src/docs/cn/src/documentation/content/xdocs/hdfs_permissions_guide.xml new file mode 100644 index 00000000000..54f0a1f7bfd --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hdfs_permissions_guide.xml @@ -0,0 +1,193 @@ + + + + + + + + +
+ + HDFSæƒé™ç®¡ç†ç”¨æˆ·æŒ‡å— + +
+ + +
概述 +

+ Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿå®žçŽ°äº†ä¸€ä¸ªå’ŒPOSIX系统类似的文件和目录的æƒé™æ¨¡åž‹ã€‚æ¯ä¸ªæ–‡ä»¶å’Œç›®å½•æœ‰ä¸€ä¸ªæ‰€æœ‰è€…(owner)和一个组(group)。文件或目录对其所有者ã€åŒç»„的其他用户以åŠæ‰€æœ‰å…¶ä»–用户分别有ç€ä¸åŒçš„æƒé™ã€‚对文件而言,当读å–这个文件时需è¦æœ‰ræƒé™ï¼Œå½“写入或者追加到文件时需è¦æœ‰wæƒé™ã€‚对目录而言,当列出目录内容时需è¦å…·æœ‰ræƒé™ï¼Œå½“新建或删除å­æ–‡ä»¶æˆ–å­ç›®å½•æ—¶éœ€è¦æœ‰wæƒé™ï¼Œå½“访问目录的å­èŠ‚点时需è¦æœ‰xæƒé™ã€‚ä¸åŒäºŽPOSIX模型,HDFSæƒé™æ¨¡åž‹ä¸­çš„文件没有sticky,setuid或setgidä½ï¼Œå› ä¸ºè¿™é‡Œæ²¡æœ‰å¯æ‰§è¡Œæ–‡ä»¶çš„概念。为了简å•èµ·è§ï¼Œè¿™é‡Œä¹Ÿæ²¡æœ‰ç›®å½•çš„sticky,setuid或setgidä½ã€‚总的æ¥è¯´ï¼Œæ–‡ä»¶æˆ–目录的æƒé™å°±æ˜¯å®ƒçš„模å¼ï¼ˆmode)。HDFS采用了Unix表示和显示模å¼çš„习惯,包括使用八进制数æ¥è¡¨ç¤ºæƒé™ã€‚当新建一个文件或目录,它的所有者å³å®¢æˆ·è¿›ç¨‹çš„用户,它的所属组是父目录的组(BSD的规定)。 +

+

+ æ¯ä¸ªè®¿é—®HDFS的用户进程的标识分为两个部分,分别是用户å和组å列表。æ¯æ¬¡ç”¨æˆ·è¿›ç¨‹è®¿é—®ä¸€ä¸ªæ–‡ä»¶æˆ–目录foo,HDFS都è¦å¯¹å…¶è¿›è¡Œæƒé™æ£€æŸ¥ï¼Œ +

+
    +
  • + 如果用户å³foo的所有者,则检查所有者的访问æƒé™ï¼› +
  • +
  • + 如果fooå…³è”的组在组å列表中出现,则检查组用户的访问æƒé™ï¼› +
  • +
  • + å¦åˆ™æ£€æŸ¥foo其他用户的访问æƒé™ã€‚ +
  • +
+ +

+ 如果æƒé™æ£€æŸ¥å¤±è´¥ï¼Œåˆ™å®¢æˆ·çš„æ“作会失败。 +

+
+ +
用户身份 +

+在这个版本的Hadoop中,客户端用户身份是通过宿主æ“作系统给出。对类Unix系统æ¥è¯´ï¼Œ +

+
    +
  • + 用户å等于`whoami`ï¼› +
  • +
  • + 组列表等于`bash -c groups`。 +
  • +
+ +

+å°†æ¥ä¼šå¢žåŠ å…¶ä»–çš„æ–¹å¼æ¥ç¡®å®šç”¨æˆ·èº«ä»½ï¼ˆæ¯”如Kerberosã€LDAP等)。期待用上文中æ到的第一ç§æ–¹å¼æ¥é˜²æ­¢ä¸€ä¸ªç”¨æˆ·å‡å†’å¦ä¸€ä¸ªç”¨æˆ·æ˜¯ä¸çŽ°å®žçš„。这ç§ç”¨æˆ·èº«ä»½è¯†åˆ«æœºåˆ¶ç»“åˆæƒé™æ¨¡åž‹å…许一个å作团体以一ç§æœ‰ç»„织的形å¼å…±äº«æ–‡ä»¶ç³»ç»Ÿä¸­çš„资æºã€‚ +

+

+ä¸ç®¡æ€Žæ ·ï¼Œç”¨æˆ·èº«ä»½æœºåˆ¶å¯¹HDFS本身æ¥è¯´åªæ˜¯å¤–部特性。HDFS并ä¸æ供创建用户身份ã€åˆ›å»ºç»„或处ç†ç”¨æˆ·å‡­è¯ç­‰åŠŸèƒ½ã€‚ +

+
+ +
ç†è§£ç³»ç»Ÿçš„实现 +

+ æ¯æ¬¡æ–‡ä»¶æˆ–目录æ“作都传递完整的路径åç»™name node,æ¯ä¸€ä¸ªæ“作都会对此路径åšæƒé™æ£€æŸ¥ã€‚客户框架会éšå¼åœ°å°†ç”¨æˆ·èº«ä»½å’Œä¸Žname node的连接关è”èµ·æ¥ï¼Œä»Žè€Œå‡å°‘改å˜çŽ°æœ‰å®¢æˆ·ç«¯API的需求。ç»å¸¸ä¼šæœ‰è¿™ç§æƒ…况,当对一个文件的æŸä¸€æ“作æˆåŠŸåŽï¼Œä¹‹åŽåŒæ ·çš„æ“作å´ä¼šå¤±è´¥ï¼Œè¿™æ˜¯å› ä¸ºæ–‡ä»¶æˆ–路径上的æŸäº›ç›®å½•å·²ç»ä¸å¤å­˜åœ¨äº†ã€‚比如,客户端首先开始读一个文件,它å‘name nodeå‘出一个请求以获å–文件第一个数æ®å—çš„ä½ç½®ã€‚但接下去的获å–其他数æ®å—的第二个请求å¯èƒ½ä¼šå¤±è´¥ã€‚å¦ä¸€æ–¹é¢ï¼Œåˆ é™¤ä¸€ä¸ªæ–‡ä»¶å¹¶ä¸ä¼šæ’¤é”€å®¢æˆ·ç«¯å·²ç»èŽ·å¾—的对文件数æ®å—的访问æƒé™ã€‚而æƒé™ç®¡ç†èƒ½ä½¿å¾—客户端对一个文件的访问许å¯åœ¨ä¸¤æ¬¡è¯·æ±‚之间被收回。é‡å¤ä¸€ä¸‹ï¼Œæƒé™çš„改å˜å¹¶ä¸ä¼šæ’¤é”€å½“å‰å®¢æˆ·ç«¯å¯¹æ–‡ä»¶æ•°æ®å—的访问许å¯ã€‚ +

+

+map-reduce框架通过传递字符串æ¥æŒ‡æ´¾ç”¨æˆ·èº«ä»½ï¼Œæ²¡æœ‰åšå…¶ä»–特别的安全方é¢çš„考虑。文件或目录的所有者和组属性是以字符串的形å¼ä¿å­˜ï¼Œè€Œä¸æ˜¯åƒä¼ ç»Ÿçš„Unixæ–¹å¼è½¬æ¢ä¸ºç”¨æˆ·å’Œç»„çš„æ•°å­—ID。 +

+

+这个å‘行版本的æƒé™ç®¡ç†ç‰¹æ€§å¹¶ä¸éœ€è¦æ”¹å˜data node的任何行为。Data node上的数æ®å—上并没有任何Hadoop所有者或æƒé™ç­‰å…³è”属性。 +

+
+ +
文件系统APIå˜æ›´ +

+ 如果æƒé™æ£€æŸ¥å¤±è´¥ï¼Œæ‰€æœ‰ä½¿ç”¨ä¸€ä¸ªè·¯å¾„å‚数的方法都å¯èƒ½æŠ›å‡ºAccessControlException异常。 +

+

新增方法:

+
    +
  • + public FSDataOutputStream create(Path f, FsPermission permission, boolean overwrite, int bufferSize, short replication, long blockSize, Progressable progress) throws IOExceptionï¼› +
  • +
  • + public boolean mkdirs(Path f, FsPermission permission) throws IOExceptionï¼› +
  • +
  • + public void setPermission(Path p, FsPermission permission) throws IOExceptionï¼› +
  • +
  • + public void setOwner(Path p, String username, String groupname) throws IOExceptionï¼› +
  • +
  • + public FileStatus getFileStatus(Path f) throws IOExceptionï¼› 也会返回路径关è”的所有者ã€ç»„和模å¼å±žæ€§ã€‚ +
  • + +
+

+新建文件或目录的模å¼å—é…ç½®å‚æ•°umask的约æŸã€‚当使用之å‰çš„ create(path, …) 方法(没有指定æƒé™å‚数)时,新文件的模å¼æ˜¯666 & ^umask。当使用新的 create(path, permission, …) 方法(指定了æƒé™å‚æ•°P)时,新文件的模å¼æ˜¯P & ^umask & 666。当使用先å‰çš„ mkdirs(path) 方法(没有指定 æƒé™å‚数)新建一个目录时,新目录的模å¼æ˜¯777 & ^umask。当使用新的 mkdirs(path, permission ) 方法(指定了æƒé™å‚æ•°P)新建一个目录时,新目录的模å¼æ˜¯P & ^umask & 777。 +

+
+ + +
Shell命令å˜æ›´ +

新增æ“作:

+
+
chmod [-R] mode file …
+
+ åªæœ‰æ–‡ä»¶çš„所有者或者超级用户æ‰æœ‰æƒé™æ”¹å˜æ–‡ä»¶æ¨¡å¼ã€‚ +
+
chgrp [-R] group file …
+
+ 使用chgrp命令的用户必须属于特定的组且是文件的所有者,或者用户是超级用户。 +
+
chown [-R] [owner][:[group]] file …
+
+ 文件的所有者的åªèƒ½è¢«è¶…级用户更改。 +
+
ls file …
+
lsr file …
+
+ 输出格å¼åšäº†è°ƒæ•´ä»¥æ˜¾ç¤ºæ‰€æœ‰è€…ã€ç»„和模å¼ã€‚ +
+
+ + +
超级用户 +

+超级用户å³è¿è¡Œname node进程的用户。宽泛的讲,如果你å¯åŠ¨äº†name node,你就是超级用户。超级用户干任何事情,因为超级用户能够通过所有的æƒé™æ£€æŸ¥ã€‚没有永久记å·ä¿ç•™è°è¿‡åŽ»æ˜¯è¶…级用户;当name node开始è¿è¡Œæ—¶ï¼Œè¿›ç¨‹è‡ªåŠ¨åˆ¤æ–­è°çŽ°åœ¨æ˜¯è¶…级用户。HDFS的超级用户ä¸ä¸€å®šéžå¾—是name node主机上的超级用户,也ä¸éœ€è¦æ‰€æœ‰çš„集群的超级用户都是一个。åŒæ ·çš„,在个人工作站上è¿è¡ŒHDFS的实验者,ä¸éœ€ä»»ä½•é…置就已方便的æˆä¸ºäº†ä»–的部署实例的超级用户。 +

+

+ å¦å¤–,管ç†å‘˜å¯ä»¥ç”¨é…ç½®å‚数指定一组特定的用户,如果åšäº†è®¾å®šï¼Œè¿™ä¸ªç»„çš„æˆå‘˜ä¹Ÿä¼šæ˜¯è¶…级用户。 +

+
+ +
WebæœåŠ¡å™¨ +

+WebæœåŠ¡å™¨çš„身份是一个å¯é…ç½®å‚数。Name node并没有真实用户的概念,但是WebæœåŠ¡å™¨è¡¨çŽ°åœ°å°±åƒå®ƒå…·æœ‰ç®¡ç†å‘˜é€‰å®šçš„用户的身份(用户å和组)一样。除éžè¿™ä¸ªé€‰å®šçš„身份是超级用户,å¦åˆ™ä¼šæœ‰å字空间中的一部分对WebæœåŠ¡å™¨æ¥è¯´ä¸å¯è§ã€‚ +

+
+ +
在线å‡çº§ +

+如果集群在0.15版本的数æ®é›†ï¼ˆfsimage)上å¯åŠ¨ï¼Œæ‰€æœ‰çš„文件和目录都有所有者O,组G,和模å¼M,这里 O å’Œ G 分别是超级用户的用户标识和组å,M是一个é…ç½®å‚数。

+
+ +
é…ç½®å‚æ•° +
+
dfs.permissions = true
+
+ 如果是 true,则打开å‰æ–‡æ‰€è¿°çš„æƒé™ç³»ç»Ÿã€‚如果是 false,æƒé™æ£€æŸ¥ 就是关闭的,但是其他的行为没有改å˜ã€‚这个é…ç½®å‚数的改å˜å¹¶ä¸æ”¹å˜æ–‡ä»¶æˆ–目录的模å¼ã€æ‰€æœ‰è€…和组等信æ¯ã€‚ +

+

+ ä¸ç®¡æƒé™æ¨¡å¼æ˜¯å¼€è¿˜æ˜¯å…³ï¼Œchmod,chgrp å’Œ chown 总是 会检查æƒé™ã€‚这些命令åªæœ‰åœ¨æƒé™æ£€æŸ¥èƒŒæ™¯ä¸‹æ‰æœ‰ç”¨ï¼Œæ‰€ä»¥ä¸ä¼šæœ‰å…¼å®¹æ€§é—®é¢˜ã€‚这样,这就能让管ç†å‘˜åœ¨æ‰“开常规的æƒé™æ£€æŸ¥ä¹‹å‰å¯ä»¥å¯é åœ°è®¾ç½®æ–‡ä»¶çš„所有者和æƒé™ã€‚ +
+
dfs.web.ugi = webuser,webgroup
+
+ WebæœåŠ¡å™¨ä½¿ç”¨çš„用户å。如果将这个å‚数设置为超级用户的å称,则所有Web客户就å¯ä»¥çœ‹åˆ°æ‰€æœ‰çš„ä¿¡æ¯ã€‚如果将这个å‚数设置为一个ä¸ä½¿ç”¨çš„用户,则Web客户就åªèƒ½è®¿é—®åˆ°â€œotherâ€æƒé™å¯è®¿é—®çš„资æºäº†ã€‚é¢å¤–的组å¯ä»¥åŠ åœ¨åŽé¢ï¼Œå½¢æˆä¸€ä¸ªç”¨é€—å·åˆ†éš”的列表。 +
+
dfs.permissions.supergroup = supergroup
+
+ 超级用户的组å。 +
+
dfs.upgrade.permission = 777
+
+ å‡çº§æ—¶çš„åˆå§‹æ¨¡å¼ã€‚文件永ä¸ä¼šè¢«è®¾ç½®xæƒé™ã€‚在é…置文件中,å¯ä»¥ä½¿ç”¨å进制数51110。 +
+
dfs.umask = 022
+
+ umaskå‚数在创建文件和目录时使用。在é…置文件中,å¯ä»¥ä½¿ç”¨å进制数1810。 +
+
+
+ + + +
+ + diff --git a/src/docs/cn/src/documentation/content/xdocs/hdfs_quota_admin_guide.xml b/src/docs/cn/src/documentation/content/xdocs/hdfs_quota_admin_guide.xml new file mode 100644 index 00000000000..014f513d310 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hdfs_quota_admin_guide.xml @@ -0,0 +1,72 @@ + + + + + + + + +
+ + å字空间é…é¢ç®¡ç†æŒ‡å— + +
+ + +

+ Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿ(HDFS)å…许管ç†å‘˜ä¸ºæ¯ä¸ªç›®å½•è®¾ç½®é…é¢ã€‚ + 新建立的目录没有é…é¢ã€‚ + 最大的é…é¢æ˜¯Long.Max_Value。é…é¢ä¸º1å¯ä»¥å¼ºåˆ¶ç›®å½•ä¿æŒä¸ºç©ºã€‚ +

+ +

+ 目录é…é¢æ˜¯å¯¹ç›®å½•æ ‘上该目录下的åå­—æ•°é‡åšç¡¬æ€§é™åˆ¶ã€‚如果创建文件或目录时超过了é…é¢ï¼Œè¯¥æ“作会失败。é‡å‘½åä¸ä¼šæ”¹å˜è¯¥ç›®å½•çš„é…é¢ï¼›å¦‚æžœé‡å‘½åæ“作会导致è¿åé…é¢é™åˆ¶ï¼Œè¯¥æ“作将会失败。如果å°è¯•è®¾ç½®ä¸€ä¸ªé…é¢è€ŒçŽ°æœ‰æ–‡ä»¶æ•°é‡å·²ç»è¶…出了这个新é…é¢ï¼Œåˆ™è®¾ç½®å¤±è´¥ã€‚ +

+ +

+ é…é¢å’Œfsimageä¿æŒä¸€è‡´ã€‚当å¯åŠ¨æ—¶ï¼Œå¦‚æžœfsimageè¿å了æŸä¸ªé…é¢é™åˆ¶ï¼ˆä¹Ÿè®¸fsimage被å·å·æ”¹å˜äº†ï¼‰ï¼Œåˆ™å¯åŠ¨å¤±è´¥å¹¶ç”Ÿæˆé”™è¯¯æŠ¥å‘Šã€‚设置或删除一个é…é¢ä¼šåˆ›å»ºç›¸åº”的日志记录。 +

+ +

+ 下é¢çš„新命令或新选项是用于支æŒé…é¢çš„。 + å‰ä¸¤ä¸ªæ˜¯ç®¡ç†å‘˜å‘½ä»¤ã€‚ +

+ + + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hdfs_shell.xml b/src/docs/cn/src/documentation/content/xdocs/hdfs_shell.xml new file mode 100644 index 00000000000..029936ea721 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hdfs_shell.xml @@ -0,0 +1,477 @@ + + + + +
+ Hadoop Shell命令 +
+ + +
+ FS Shell +

+ 调用文件系统(FS)Shell命令应使用 + bin/hadoop fs <args>çš„å½¢å¼ã€‚ + 所有的的FS shell命令使用URI路径作为å‚数。URIæ ¼å¼æ˜¯scheme://authority/path。对HDFS文件系统,scheme是hdfs,对本地文件系统,scheme是file。其中schemeå’Œauthorityå‚数都是å¯é€‰çš„,如果未加指定,就会使用é…置中指定的默认scheme。一个HDFS文件或目录比如/parent/childå¯ä»¥è¡¨ç¤ºæˆhdfs://namenode:namenodeport/parent/child,或者更简å•çš„/parent/child(å‡è®¾ä½ é…置文件中的默认值是namenode:namenodeport)。大多数FS Shell命令的行为和对应的Unix Shell命令类似,ä¸åŒä¹‹å¤„会在下é¢ä»‹ç»å„命令使用详情时指出。出错信æ¯ä¼šè¾“出到stderr,其他信æ¯è¾“出到stdout。 +

+
+ cat +

+ 使用方法:hadoop fs -cat URI [URI …] +

+ +

+ 将路径指定文件的内容输出到stdout。 +

+ +

示例:

+
    +
  • + hadoop fs -cat hdfs://host1:port1/file1 hdfs://host2:port2/file2 + +
  • +
  • + hadoop fs -cat file:///file3 /user/hadoop/file4 +
  • +
+

返回值:
+ + æˆåŠŸè¿”回0,失败返回-1。

+
+
+ chgrp +

+ 使用方法:hadoop fs -chgrp [-R] GROUP URI [URI …] + Change group association of files. With -R, make the change recursively through the directory structure. The user must be the owner of files, or else a super-user. Additional information is in the Permissions User Guide. +--> +

+

+ 改å˜æ–‡ä»¶æ‰€å±žçš„组。使用-R将使改å˜åœ¨ç›®å½•ç»“构下递归进行。命令的使用者必须是文件的所有者或者超级用户。更多的信æ¯è¯·å‚è§HDFSæƒé™ç”¨æˆ·æŒ‡å—。 +

+
+
+ chmod +

+ 使用方法:hadoop fs -chmod [-R] <MODE[,MODE]... | OCTALMODE> URI [URI …] +

+

+ 改å˜æ–‡ä»¶çš„æƒé™ã€‚使用-R将使改å˜åœ¨ç›®å½•ç»“构下递归进行。命令的使用者必须是文件的所有者或者超级用户。更多的信æ¯è¯·å‚è§HDFSæƒé™ç”¨æˆ·æŒ‡å—。 +

+
+
+ chown +

+ 使用方法:hadoop fs -chown [-R] [OWNER][:[GROUP]] URI [URI ] +

+

+ 改å˜æ–‡ä»¶çš„拥有者。使用-R将使改å˜åœ¨ç›®å½•ç»“构下递归进行。命令的使用者必须是超级用户。更多的信æ¯è¯·å‚è§HDFSæƒé™ç”¨æˆ·æŒ‡å—。 +

+
+
+ copyFromLocal +

+ 使用方法:hadoop fs -copyFromLocal <localsrc> URI +

+

除了é™å®šæºè·¯å¾„是一个本地文件外,和put命令相似。

+
+
+ copyToLocal +

+ 使用方法:hadoop fs -copyToLocal [-ignorecrc] [-crc] URI <localdst> +

+

除了é™å®šç›®æ ‡è·¯å¾„是一个本地文件外,和get命令类似。

+
+
+ cp +

+ 使用方法:hadoop fs -cp URI [URI …] <dest> +

+

+ 将文件从æºè·¯å¾„å¤åˆ¶åˆ°ç›®æ ‡è·¯å¾„。这个命令å…许有多个æºè·¯å¾„,此时目标路径必须是一个目录。 +
+ 示例:

+
    +
  • + hadoop fs -cp /user/hadoop/file1 /user/hadoop/file2 +
  • +
  • + hadoop fs -cp /user/hadoop/file1 /user/hadoop/file2 /user/hadoop/dir +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ du +

+ 使用方法:hadoop fs -du URI [URI …] +

+

+ 显示目录中所有文件的大å°ï¼Œæˆ–者当åªæŒ‡å®šä¸€ä¸ªæ–‡ä»¶æ—¶ï¼Œæ˜¾ç¤ºæ­¤æ–‡ä»¶çš„大å°ã€‚
+ 示例:
hadoop fs -du /user/hadoop/dir1 /user/hadoop/file1 hdfs://host:port/user/hadoop/dir1
+ 返回值:
æˆåŠŸè¿”回0,失败返回-1。

+
+
+ dus +

+ 使用方法:hadoop fs -dus <args> +

+

+ 显示文件的大å°ã€‚ +

+
+
+ expunge +

+ 使用方法:hadoop fs -expunge +

+

清空回收站。请å‚考HDFS设计文档以获å–更多关于回收站特性的信æ¯ã€‚ +

+
+
+ get +

+ 使用方法:hadoop fs -get [-ignorecrc] [-crc] <src> <localdst> +
+

+

+ å¤åˆ¶æ–‡ä»¶åˆ°æœ¬åœ°æ–‡ä»¶ç³»ç»Ÿã€‚å¯ç”¨-ignorecrc选项å¤åˆ¶CRC校验失败的文件。使用-crc选项å¤åˆ¶æ–‡ä»¶ä»¥åŠCRCä¿¡æ¯ã€‚ +

+

示例:

+
    +
  • + hadoop fs -get /user/hadoop/file localfile +
  • +
  • + hadoop fs -get hdfs://host:port/user/hadoop/file localfile +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ getmerge +

+ 使用方法:hadoop fs -getmerge <src> <localdst> [addnl] +

+

+ 接å—一个æºç›®å½•å’Œä¸€ä¸ªç›®æ ‡æ–‡ä»¶ä½œä¸ºè¾“入,并且将æºç›®å½•ä¸­æ‰€æœ‰çš„文件连接æˆæœ¬åœ°ç›®æ ‡æ–‡ä»¶ã€‚addnl是å¯é€‰çš„,用于指定在æ¯ä¸ªæ–‡ä»¶ç»“尾添加一个æ¢è¡Œç¬¦ã€‚ +

+
+
+ ls +

+ 使用方法:hadoop fs -ls <args> +

+

如果是文件,则按照如下格å¼è¿”回文件信æ¯ï¼š
文件å <副本数> æ–‡ä»¶å¤§å° ä¿®æ”¹æ—¥æœŸ 修改时间 æƒé™ 用户ID 组ID
+ 如果是目录,则返回它直接å­æ–‡ä»¶çš„一个列表,就åƒåœ¨Unix中一样。目录返回列表的信æ¯å¦‚下:
目录å <dir> 修改日期 修改时间 æƒé™ 用户ID 组ID
+ 示例:
hadoop fs -ls /user/hadoop/file1 /user/hadoop/file2 hdfs://host:port/user/hadoop/dir1 /nonexistentfile
+ 返回值:
æˆåŠŸè¿”回0,失败返回-1。

+
+
+ lsr +

使用方法:hadoop fs -lsr <args>
+ ls命令的递归版本。类似于Unix中的ls -R。 +

+
+
+ mkdir +

+ 使用方法:hadoop fs -mkdir <paths> +
+

+

接å—路径指定的uri作为å‚数,创建这些目录。其行为类似于Unixçš„mkdir -p,它会创建路径中的å„级父目录。

+

示例:

+
    +
  • + hadoop fs -mkdir /user/hadoop/dir1 /user/hadoop/dir2 +
  • +
  • + hadoop fs -mkdir hdfs://host1:port1/user/hadoop/dir hdfs://host2:port2/user/hadoop/dir + +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ movefromLocal +

+ 使用方法:dfs -moveFromLocal <src> <dst> +

+

输出一个â€not implemented“信æ¯ã€‚ +

+
+
+ mv +

+ 使用方法:hadoop fs -mv URI [URI …] <dest> +

+

+ 将文件从æºè·¯å¾„移动到目标路径。这个命令å…许有多个æºè·¯å¾„,此时目标路径必须是一个目录。ä¸å…许在ä¸åŒçš„文件系统间移动文件。 +
+ 示例: +

+
    +
  • + hadoop fs -mv /user/hadoop/file1 /user/hadoop/file2 +
  • +
  • + hadoop fs -mv hdfs://host:port/file1 hdfs://host:port/file2 hdfs://host:port/file3 hdfs://host:port/dir1 +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ put +

+ 使用方法:hadoop fs -put <localsrc> ... <dst> +

+

从本地文件系统中å¤åˆ¶å•ä¸ªæˆ–多个æºè·¯å¾„到目标文件系统。也支æŒä»Žæ ‡å‡†è¾“入中读å–输入写入目标文件系统。
+

+
    +
  • + hadoop fs -put localfile /user/hadoop/hadoopfile +
  • +
  • + hadoop fs -put localfile1 localfile2 /user/hadoop/hadoopdir +
  • +
  • + hadoop fs -put localfile hdfs://host:port/hadoop/hadoopfile +
  • +
  • hadoop fs -put - hdfs://host:port/hadoop/hadoopfile
    从标准输入中读å–输入。
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ rm +

+ 使用方法:hadoop fs -rm URI [URI …] +

+

+ 删除指定的文件。åªåˆ é™¤éžç©ºç›®å½•å’Œæ–‡ä»¶ã€‚请å‚考rmr命令了解递归删除。
+ 示例: +

+
    +
  • + hadoop fs -rm hdfs://host:port/file /user/hadoop/emptydir +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ rmr +

+ 使用方法:hadoop fs -rmr URI [URI …] +

+

delete的递归版本。
+ 示例: +

+
    +
  • + hadoop fs -rmr /user/hadoop/dir +
  • +
  • + hadoop fs -rmr hdfs://host:port/user/hadoop/dir +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ setrep +

+ 使用方法:hadoop fs -setrep [-R] <path> +

+

+ 改å˜ä¸€ä¸ªæ–‡ä»¶çš„副本系数。-R选项用于递归改å˜ç›®å½•ä¸‹æ‰€æœ‰æ–‡ä»¶çš„副本系数。 +

+

示例:

+
    +
  • + hadoop fs -setrep -w 3 -R /user/hadoop/dir1 +
  • +
+

返回值:

+

+ æˆåŠŸè¿”回0,失败返回-1。 +

+
+
+ stat +

+ 使用方法:hadoop fs -stat URI [URI …] +

+

+ 返回指定路径的统计信æ¯ã€‚ +

+

示例:

+
    +
  • + hadoop fs -stat path +
  • +
+

返回值:
+ æˆåŠŸè¿”回0,失败返回-1。

+
+
+ tail +

+ 使用方法:hadoop fs -tail [-f] URI +

+

+ 将文件尾部1K字节的内容输出到stdout。支æŒ-f选项,行为和Unix中一致。 +

+

示例:

+
    +
  • + hadoop fs -tail pathname +
  • +
+

返回值:
+ æˆåŠŸè¿”回0,失败返回-1。

+
+
+ test +

+ 使用方法:hadoop fs -test -[ezd] URI +

+

+ 选项:
+ -e 检查文件是å¦å­˜åœ¨ã€‚如果存在则返回0。
+ -z 检查文件是å¦æ˜¯0字节。如果是则返回0。
+ -d 如果路径是个目录,则返回1,å¦åˆ™è¿”回0。

+

示例:

+
    +
  • + hadoop fs -test -e filename +
  • +
+
+
+ text +

+ 使用方法:hadoop fs -text <src> +
+

+

+ å°†æºæ–‡ä»¶è¾“出为文本格å¼ã€‚å…许的格å¼æ˜¯zipå’ŒTextRecordInputStream。 +

+
+
+ touchz +

+ 使用方法:hadoop fs -touchz URI [URI …] +
+

+

+ 创建一个0字节的空文件。 +

+

示例:

+
    +
  • + hadoop -touchz pathname +
  • +
+

返回值:
+ æˆåŠŸè¿”回0,失败返回-1。

+ +
+
+ +
+ + diff --git a/src/docs/cn/src/documentation/content/xdocs/hdfs_user_guide.xml b/src/docs/cn/src/documentation/content/xdocs/hdfs_user_guide.xml new file mode 100644 index 00000000000..40a43c997ac --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hdfs_user_guide.xml @@ -0,0 +1,513 @@ + + + + + + + + + +
+ + Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿä½¿ç”¨æŒ‡å— + +
+ + +
目的 +

+ 本文档的目标是为Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿï¼ˆHDFS)的用户æ供一个学习的起点,这里的HDFSæ—¢å¯ä»¥ä½œä¸ºHadoop集群的一部分,也å¯ä»¥ä½œä¸ºä¸€ä¸ªç‹¬ç«‹çš„分布å¼æ–‡ä»¶ç³»ç»Ÿã€‚虽然HDFS在很多环境下被设计æˆæ˜¯å¯æ­£ç¡®å·¥ä½œçš„,但是了解HDFS的工作原ç†å¯¹åœ¨ç‰¹å®šé›†ç¾¤ä¸Šæ”¹è¿›HDFSçš„è¿è¡Œæ€§èƒ½å’Œé”™è¯¯è¯Šæ–­éƒ½æœ‰æžå¤§çš„帮助。 +

+
+ + + +
概述 +

+HDFS是Hadoop应用用到的一个最主è¦çš„分布å¼å­˜å‚¨ç³»ç»Ÿã€‚一个HDFS集群主è¦ç”±ä¸€ä¸ªNameNode和很多个Datanode组æˆï¼šNamenode管ç†æ–‡ä»¶ç³»ç»Ÿçš„元数æ®ï¼Œè€ŒDatanode存储了实际的数æ®ã€‚HDFS的体系结构在这里有详细的æ述。本文档主è¦å…³æ³¨ç”¨æˆ·ä»¥åŠç®¡ç†å‘˜æ€Žæ ·å’ŒHDFS进行交互。HDFS架构设计中的图解æ述了Namenodeã€Datanode和客户端之间的基本的交互æ“作。基本上,客户端è”ç³»Namenode以获å–文件的元数æ®æˆ–修饰属性,而真正的文件I/Oæ“作是直接和Datanode进行交互的。 +

+

+ 下é¢åˆ—出了一些多数用户都比较感兴趣的é‡è¦ç‰¹æ€§ã€‚ +

+
    +
  • + + Hadoop(包括HDFS)éžå¸¸é€‚åˆåœ¨å•†ç”¨ç¡¬ä»¶ï¼ˆcommodity hardware)上åšåˆ†å¸ƒå¼å­˜å‚¨å’Œè®¡ç®—,因为它ä¸ä»…具有容错性和å¯æ‰©å±•æ€§ï¼Œè€Œä¸”éžå¸¸æ˜“于扩展。Map-Reduce框架以其在大型分布å¼ç³»ç»Ÿåº”用上的简å•æ€§å’Œå¯ç”¨æ€§è€Œè‘—称,这个框架已ç»è¢«é›†æˆè¿›Hadoop中。 +
  • +
  • + HDFSçš„å¯é…置性æžé«˜ï¼ŒåŒæ—¶ï¼Œå®ƒçš„默认é…置能够满足很多的安装环境。多数情况下,这些å‚æ•°åªåœ¨éžå¸¸å¤§è§„模的集群环境下æ‰éœ€è¦è°ƒæ•´ã€‚ +
  • + +
  • + 用Java语言开å‘,支æŒæ‰€æœ‰çš„主æµå¹³å°ã€‚ +
  • +
  • + 支æŒç±»Shell命令,å¯ç›´æŽ¥å’ŒHDFS进行交互。 +
  • +
  • + NameNodeå’ŒDataNode有内置的WebæœåŠ¡å™¨ï¼Œæ–¹ä¾¿ç”¨æˆ·æ£€æŸ¥é›†ç¾¤çš„当å‰çŠ¶æ€ã€‚ +
  • + +
  • + 新特性和改进会定期加入HDFS的实现中。下é¢åˆ—出的是HDFS中常用特性的一部分: +
      +
    • + 文件æƒé™å’ŒæŽˆæƒã€‚ +
    • +
    • + 机架感知(Rack awareness):在调度任务和分é…存储空间时考虑节点的物ç†ä½ç½®ã€‚ +
    • +
    • + 安全模å¼ï¼šä¸€ç§ç»´æŠ¤éœ€è¦çš„管ç†æ¨¡å¼ã€‚ +
    • +
    • + fsck:一个诊断文件系统å¥åº·çŠ¶å†µçš„工具,能够å‘现丢失的文件或数æ®å—。 +
    • +
    • + Rebalancer:当datanode之间数æ®ä¸å‡è¡¡æ—¶ï¼Œå¹³è¡¡é›†ç¾¤ä¸Šçš„æ•°æ®è´Ÿè½½ã€‚ +
    • +
    • + å‡çº§å’Œå›žæ»šï¼šåœ¨è½¯ä»¶æ›´æ–°åŽæœ‰å¼‚常å‘生的情形下,能够回滚到HDFSå‡çº§ä¹‹å‰çš„状æ€ã€‚ +
    • +
    • + Secondary Namenode:对文件系统å字空间执行周期性的检查点,将Namenode上HDFS改动日志文件的大å°æŽ§åˆ¶åœ¨æŸä¸ªç‰¹å®šçš„é™åº¦ä¸‹ã€‚ +
    • +
    +
  • +
+ +
先决æ¡ä»¶ +

+ 下é¢çš„文档æ述了如何安装和æ­å»ºHadoop集群: +

+ +

+ 文档余下部分å‡è®¾ç”¨æˆ·å·²ç»å®‰è£…并è¿è¡Œäº†è‡³å°‘包å«ä¸€ä¸ªDatanode节点的HDFS。就本文目的æ¥è¯´ï¼ŒNamenodeå’ŒDatanodeå¯ä»¥è¿è¡Œåœ¨åŒä¸€ä¸ªç‰©ç†ä¸»æœºä¸Šã€‚ +

+ +
WebæŽ¥å£ + +

+ NameNodeå’ŒDataNodeå„自å¯åŠ¨äº†ä¸€ä¸ªå†…置的WebæœåŠ¡å™¨ï¼Œæ˜¾ç¤ºäº†é›†ç¾¤å½“å‰çš„基本状æ€å’Œä¿¡æ¯ã€‚在默认é…置下NameNode的首页地å€æ˜¯http://namenode-name:50070/。这个页é¢åˆ—出了集群里的所有DataNode和集群的基本状æ€ã€‚这个Web接å£ä¹Ÿå¯ä»¥ç”¨æ¥æµè§ˆæ•´ä¸ªæ–‡ä»¶ç³»ç»Ÿï¼ˆä½¿ç”¨NameNode首页上的"Browse the file system"链接)。 +

+ + +
Shell命令 +

Hadoop包括一系列的类shell的命令,å¯ç›´æŽ¥å’ŒHDFS以åŠå…¶ä»–Hadoop支æŒçš„文件系统进行交互。bin/hadoop fs -help 命令列出所有Hadoop Shell支æŒçš„命令。而 bin/hadoop fs -help command-name 命令能显示关于æŸä¸ªå‘½ä»¤çš„详细信æ¯ã€‚这些命令支æŒå¤§å¤šæ•°æ™®é€šæ–‡ä»¶ç³»ç»Ÿçš„æ“作,比如å¤åˆ¶æ–‡ä»¶ã€æ”¹å˜æ–‡ä»¶æƒé™ç­‰ã€‚它还支æŒä¸€äº›HDFS特有的æ“作,比如改å˜æ–‡ä»¶å‰¯æœ¬æ•°ç›®ã€‚ +

+ +
DFSAdmin命令 +

+ 'bin/hadoop dfsadmin' 命令支æŒä¸€äº›å’ŒHDFS管ç†ç›¸å…³çš„æ“作。bin/hadoop dfsadmin -help 命令能列出所有当å‰æ”¯æŒçš„命令。比如: +

+
    +
  • + + -report:报告HDFS的基本统计信æ¯ã€‚有些信æ¯ä¹Ÿå¯ä»¥åœ¨NameNode WebæœåŠ¡é¦–页看到。 + +
  • +
  • + -safemode:虽然通常并ä¸éœ€è¦ï¼Œä½†æ˜¯ç®¡ç†å‘˜çš„ç¡®å¯ä»¥æ‰‹åŠ¨è®©NameNode进入或离开安全模å¼ã€‚ +
  • +
  • + -finalizeUpgrade:删除上一次å‡çº§æ—¶åˆ¶ä½œçš„集群备份。 +
  • +
+
+ +
Secondary NameNode +

NameNode将对文件系统的改动追加ä¿å­˜åˆ°æœ¬åœ°æ–‡ä»¶ç³»ç»Ÿä¸Šçš„一个日志文件(edits)。当一个NameNodeå¯åŠ¨æ—¶ï¼Œå®ƒé¦–先从一个映åƒæ–‡ä»¶ï¼ˆfsimage)中读å–HDFS的状æ€ï¼ŒæŽ¥ç€åº”用日志文件中的editsæ“作。然åŽå®ƒå°†æ–°çš„HDFS状æ€å†™å…¥ï¼ˆfsimage)中,并使用一个空的edits文件开始正常æ“作。因为NameNodeåªæœ‰åœ¨å¯åŠ¨é˜¶æ®µæ‰åˆå¹¶fsimageå’Œedits,所以久而久之日志文件å¯èƒ½ä¼šå˜å¾—éžå¸¸åºžå¤§ï¼Œç‰¹åˆ«æ˜¯å¯¹å¤§åž‹çš„集群。日志文件太大的å¦ä¸€ä¸ªå‰¯ä½œç”¨æ˜¯ä¸‹ä¸€æ¬¡NameNodeå¯åŠ¨ä¼šèŠ±å¾ˆé•¿æ—¶é—´ã€‚ +

+

+ Secondary NameNode定期åˆå¹¶fsimageå’Œedits日志,将edits日志文件大å°æŽ§åˆ¶åœ¨ä¸€ä¸ªé™åº¦ä¸‹ã€‚因为内存需求和NameNode在一个数é‡çº§ä¸Šï¼Œæ‰€ä»¥é€šå¸¸secondary NameNodeå’ŒNameNodeè¿è¡Œåœ¨ä¸åŒçš„机器上。Secondary NameNode通过bin/start-dfs.sh在conf/masters中指定的节点上å¯åŠ¨ã€‚ +

+ + +

+Secondary NameNode的检查点进程å¯åŠ¨ï¼Œæ˜¯ç”±ä¸¤ä¸ªé…ç½®å‚数控制的: +

+
    +
  • + fs.checkpoint.period,指定连续两次检查点的最大时间间隔, + 默认值是1å°æ—¶ã€‚ +
  • +
  • + fs.checkpoint.size定义了edits日志文件的最大值,一旦超过这个值会导致强制执行检查点(å³ä½¿æ²¡åˆ°æ£€æŸ¥ç‚¹çš„最大时间间隔)。默认值是64MB。 +
  • +
+

+ Secondary NameNodeä¿å­˜æœ€æ–°æ£€æŸ¥ç‚¹çš„目录与NameNode的目录结构相åŒã€‚ + 所以NameNodeå¯ä»¥åœ¨éœ€è¦çš„时候读å–Secondary NameNode上的检查点镜åƒã€‚ +

+

+ 如果NameNode上除了最新的检查点以外,所有的其他的历å²é•œåƒå’Œedits文件都丢失了, + NameNodeå¯ä»¥å¼•å…¥è¿™ä¸ªæœ€æ–°çš„检查点。以下æ“作å¯ä»¥å®žçŽ°è¿™ä¸ªåŠŸèƒ½ï¼š +

+
    +
  • + 在é…ç½®å‚æ•°dfs.name.dir指定的ä½ç½®å»ºç«‹ä¸€ä¸ªç©ºæ–‡ä»¶å¤¹ï¼› +
  • +
  • + 把检查点目录的ä½ç½®èµ‹å€¼ç»™é…ç½®å‚æ•°fs.checkpoint.dirï¼› +
  • +
  • + å¯åŠ¨NameNode,并加上-importCheckpoint。 +
  • +
+

+ NameNode会从fs.checkpoint.dir目录读å–检查点, + 并把它ä¿å­˜åœ¨dfs.name.dir目录下。 + 如果dfs.name.dir目录下有åˆæ³•çš„é•œåƒæ–‡ä»¶ï¼ŒNameNode会å¯åŠ¨å¤±è´¥ã€‚ + NameNode会检查fs.checkpoint.dir目录下镜åƒæ–‡ä»¶çš„一致性,但是ä¸ä¼šåŽ»æ”¹åŠ¨å®ƒã€‚ +

+

+ 命令的使用方法请å‚考secondarynamenode 命令. +

+ + + + +
Rebalancer + +

+ HDFSçš„æ•°æ®ä¹Ÿè®¸å¹¶ä¸æ˜¯éžå¸¸å‡åŒ€çš„分布在å„个DataNode中。一个常è§çš„原因是在现有的集群上ç»å¸¸ä¼šå¢žæ·»æ–°çš„DataNode节点。当新增一个数æ®å—(一个文件的数æ®è¢«ä¿å­˜åœ¨ä¸€ç³»åˆ—çš„å—中)时,NameNode在选择DataNode接收这个数æ®å—之å‰ï¼Œä¼šè€ƒè™‘到很多因素。其中的一些考虑的是: +

+ +
    +
  • + 将数æ®å—的一个副本放在正在写这个数æ®å—的节点上。 +
  • +
  • + å°½é‡å°†æ•°æ®å—çš„ä¸åŒå‰¯æœ¬åˆ†å¸ƒåœ¨ä¸åŒçš„机架上,这样集群å¯åœ¨å®Œå…¨å¤±åŽ»æŸä¸€æœºæž¶çš„情况下还能存活。 +
  • +
  • + 一个副本通常被放置在和写文件的节点åŒä¸€æœºæž¶çš„æŸä¸ªèŠ‚点上,这样å¯ä»¥å‡å°‘跨越机架的网络I/O。 +
  • +
  • + å°½é‡å‡åŒ€åœ°å°†HDFSæ•°æ®åˆ†å¸ƒåœ¨é›†ç¾¤çš„DataNode中。 +
  • +
+

+由于上述多ç§è€ƒè™‘需è¦å–èˆï¼Œæ•°æ®å¯èƒ½å¹¶ä¸ä¼šå‡åŒ€åˆ†å¸ƒåœ¨DataNode中。HDFS为管ç†å‘˜æ供了一个工具,用于分æžæ•°æ®å—分布和é‡æ–°å¹³è¡¡DataNode上的数æ®åˆ†å¸ƒã€‚HADOOP-1652的附件中的一个PDF是一个简è¦çš„rebalancer管ç†å‘˜æŒ‡å—。 +

+ +

+ 使用方法请å‚考balancer 命令. +

+ +
机架感知(Rack awareness) +

+ 通常,大型Hadoop集群是以机架的形å¼æ¥ç»„织的,åŒä¸€ä¸ªæœºæž¶ä¸Šä¸åŒèŠ‚点间的网络状况比ä¸åŒæœºæž¶ä¹‹é—´çš„更为ç†æƒ³ã€‚å¦å¤–,NameNode设法将数æ®å—副本ä¿å­˜åœ¨ä¸åŒçš„机架上以æ高容错性。Hadoopå…许集群的管ç†å‘˜é€šè¿‡é…ç½®dfs.network.scriptå‚æ•°æ¥ç¡®å®šèŠ‚点所处的机架。当这个脚本é…置完毕,æ¯ä¸ªèŠ‚点都会è¿è¡Œè¿™ä¸ªè„šæœ¬æ¥èŽ·å–它的机架ID。默认的安装å‡å®šæ‰€æœ‰çš„节点属于åŒä¸€ä¸ªæœºæž¶ã€‚这个特性åŠå…¶é…ç½®å‚数在HADOOP-692所附的PDF上有更详细的æ述。 +

+ +
å®‰å…¨æ¨¡å¼ +

+ NameNodeå¯åŠ¨æ—¶ä¼šä»Žfsimageå’Œedits日志文件中装载文件系统的状æ€ä¿¡æ¯ï¼ŒæŽ¥ç€å®ƒç­‰å¾…å„个DataNodeå‘它报告它们å„自的数æ®å—状æ€ï¼Œè¿™æ ·ï¼ŒNameNodeå°±ä¸ä¼šè¿‡æ—©åœ°å¼€å§‹å¤åˆ¶æ•°æ®å—,å³ä½¿åœ¨å‰¯æœ¬å……足的情况下。这个阶段,NameNode处于安全模å¼ä¸‹ã€‚NameNode的安全模å¼æœ¬è´¨ä¸Šæ˜¯HDFS集群的一ç§åªè¯»æ¨¡å¼ï¼Œæ­¤æ—¶é›†ç¾¤ä¸å…许任何对文件系统或者数æ®å—修改的æ“作。通常NameNode会在开始阶段自动地退出安全模å¼ã€‚如果需è¦ï¼Œä½ ä¹Ÿå¯ä»¥é€šè¿‡'bin/hadoop dfsadmin -safemode'命令显å¼åœ°å°†HDFS置于安全模å¼ã€‚NameNode首页会显示当å‰æ˜¯å¦å¤„于安全模å¼ã€‚关于安全模å¼çš„更多介ç»å’Œé…置信æ¯è¯·å‚考JavaDoc:setSafeMode()。 +

+ +
fsck +

+ HDFS支æŒfsck命令æ¥æ£€æŸ¥ç³»ç»Ÿä¸­çš„å„ç§ä¸ä¸€è‡´çŠ¶å†µã€‚这个命令被设计æ¥æŠ¥å‘Šå„ç§æ–‡ä»¶å­˜åœ¨çš„问题,比如文件缺少数æ®å—或者副本数目ä¸å¤Ÿã€‚ä¸åŒäºŽåœ¨æœ¬åœ°æ–‡ä»¶ç³»ç»Ÿä¸Šä¼ ç»Ÿçš„fsck工具,这个命令并ä¸ä¼šä¿®æ­£å®ƒæ£€æµ‹åˆ°çš„错误。一般æ¥è¯´ï¼ŒNameNode会自动修正大多数å¯æ¢å¤çš„错误。HDFSçš„fsckä¸æ˜¯ä¸€ä¸ªHadoop shell命令。它通过'bin/hadoop fsck'执行。 + +命令的使用方法请å‚考fsck命令 +fsckå¯ç”¨æ¥æ£€æŸ¥æ•´ä¸ªæ–‡ä»¶ç³»ç»Ÿï¼Œä¹Ÿå¯ä»¥åªæ£€æŸ¥éƒ¨åˆ†æ–‡ä»¶ã€‚ + +

+ +
å‡çº§å’Œå›žæ»š +

当在一个已有集群上å‡çº§Hadoop时,åƒå…¶ä»–的软件å‡çº§ä¸€æ ·ï¼Œå¯èƒ½ä¼šæœ‰æ–°çš„bug或一些会影å“到现有应用的éžå…¼å®¹æ€§å˜æ›´å‡ºçŽ°ã€‚在任何有实际æ„义的HDSF系统上,丢失数æ®æ˜¯ä¸è¢«å…许的,更ä¸ç”¨è¯´é‡æ–°æ­å»ºå¯åŠ¨HDFS了。HDFSå…许管ç†å‘˜é€€å›žåˆ°ä¹‹å‰çš„Hadoop版本,并将集群的状æ€å›žæ»šåˆ°å‡çº§ä¹‹å‰ã€‚更多关于HDFSå‡çº§çš„细节在å‡çº§wiki上å¯ä»¥æ‰¾åˆ°ã€‚HDFS在一个时间å¯ä»¥æœ‰ä¸€ä¸ªè¿™æ ·çš„备份。在å‡çº§ä¹‹å‰ï¼Œç®¡ç†å‘˜éœ€è¦ç”¨bin/hadoop dfsadmin -finalizeUpgrade(å‡çº§ç»ˆç»“æ“作)命令删除存在的备份文件。下é¢ç®€å•ä»‹ç»ä¸€ä¸‹ä¸€èˆ¬çš„å‡çº§è¿‡ç¨‹ï¼š +

+
    +
  • å‡çº§ Hadoop 软件之å‰ï¼Œè¯·æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨ä¸€ä¸ªå¤‡ä»½ï¼Œå¦‚果存在,å¯æ‰§è¡Œå‡çº§ç»ˆç»“æ“作删除这个备份。通过dfsadmin -upgradeProgress status命令能够知é“是å¦éœ€è¦å¯¹ä¸€ä¸ªé›†ç¾¤æ‰§è¡Œå‡çº§ç»ˆç»“æ“作。
  • +
  • åœæ­¢é›†ç¾¤å¹¶éƒ¨ç½²æ–°ç‰ˆæœ¬çš„Hadoop。
  • +
  • 使用-upgrade选项è¿è¡Œæ–°çš„版本(bin/start-dfs.sh -upgrade)。 +
  • +
  • 在大多数情况下,集群都能够正常è¿è¡Œã€‚一旦我们认为新的HDFSè¿è¡Œæ­£å¸¸ï¼ˆä¹Ÿè®¸ç»è¿‡å‡ å¤©çš„æ“作之åŽï¼‰ï¼Œå°±å¯ä»¥å¯¹ä¹‹æ‰§è¡Œå‡çº§ç»ˆç»“æ“作。注æ„,在对一个集群执行å‡çº§ç»ˆç»“æ“作之å‰ï¼Œåˆ é™¤é‚£äº›å‡çº§å‰å°±å·²ç»å­˜åœ¨çš„文件并ä¸ä¼šçœŸæ­£åœ°é‡Šæ”¾DataNodes上的ç£ç›˜ç©ºé—´ã€‚
  • +
  • 如果需è¦é€€å›žåˆ°è€ç‰ˆæœ¬ï¼Œ +
      +
    • åœæ­¢é›†ç¾¤å¹¶ä¸”部署è€ç‰ˆæœ¬çš„Hadoop。
    • +
    • 用回滚选项å¯åŠ¨é›†ç¾¤ï¼ˆbin/start-dfs.h -rollback)。
    • +
    +
  • +
+ +
文件æƒé™å’Œå®‰å…¨æ€§ +

+ 这里的文件æƒé™å’Œå…¶ä»–常è§å¹³å°å¦‚Linux的文件æƒé™ç±»ä¼¼ã€‚ç›®å‰ï¼Œå®‰å…¨æ€§ä»…é™äºŽç®€å•çš„文件æƒé™ã€‚å¯åŠ¨NameNode的用户被视为HDFS的超级用户。HDFS以åŽçš„版本将会支æŒç½‘络验è¯å议(比如Kerberos)æ¥å¯¹ç”¨æˆ·èº«ä»½è¿›è¡ŒéªŒè¯å’Œå¯¹æ•°æ®è¿›è¡ŒåŠ å¯†ä¼ è¾“。具体的细节请å‚考æƒé™ä½¿ç”¨ç®¡ç†æŒ‡å—。 +

+ +
å¯æ‰©å±•æ€§ +

+ 现在,Hadoopå·²ç»è¿è¡Œåœ¨ä¸Šåƒä¸ªèŠ‚点的集群上。Powered By Hadoop页é¢åˆ—出了一些已将Hadoop部署在他们的大型集群上的组织。HDFS集群åªæœ‰ä¸€ä¸ªNameNode节点。目å‰ï¼ŒNameNode上å¯ç”¨å†…存大å°æ˜¯ä¸€ä¸ªä¸»è¦çš„扩展é™åˆ¶ã€‚在超大型的集群中,增大HDFS存储文件的平å‡å¤§å°èƒ½å¤Ÿå¢žå¤§é›†ç¾¤çš„规模,而ä¸éœ€è¦å¢žåŠ NameNode的内存。默认é…置也许并ä¸é€‚åˆè¶…大规模的集群。Hadoop FAQ页é¢åˆ—举了针对大型Hadoop集群的é…置改进。

+ +
相关文档 +

+ 这个用户手册给用户æ供了一个学习和使用HDSF文件系统的起点。本文档会ä¸æ–­åœ°è¿›è¡Œæ”¹è¿›ï¼ŒåŒæ—¶ï¼Œç”¨æˆ·ä¹Ÿå¯ä»¥å‚考更多的Hadoopå’ŒHDFS文档。下é¢çš„列表是用户继续学习的起点: +

+
    +
  • + Hadoop官方主页:所有Hadoop相关的起始页。 +
  • +
  • + Hadoop Wiki:Hadoop Wiki文档首页。这个指å—是Hadoop代ç æ ‘中的一部分,与此ä¸åŒï¼ŒHadoop Wiki是由Hadoop社区定期编辑的。 +
  • +
  • Hadoop Wiki上的FAQ。 +
  • +
  • Hadoop JavaDoc API。
  • +
  • Hadoop用户邮件列表:core-user[at]hadoop.apache.org。
  • +
  • 查看conf/hadoop-default.xml文件。这里包括了大多数é…ç½®å‚数的简è¦æ述。
  • +
  • + 命令手册:命令使用说明。 +
  • + + +
+
+ + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hod.xml b/src/docs/cn/src/documentation/content/xdocs/hod.xml new file mode 100644 index 00000000000..dcdd92315da --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hod.xml @@ -0,0 +1,46 @@ + + + + + + + + +
+ + Hadoop On Demand + +
+ + +
+ 简介 +

Hadoop On Demand(HOD)是一个能在大型物ç†é›†ç¾¤ä¸Šä¾›åº”虚拟hadoop集群的系统。它使用Torque资æºç®¡ç†å™¨åˆ†é…节点。它å¯ä»¥åœ¨åˆ†é…的节点上å¯åŠ¨Hadoop Map/Reduceå’ŒHDFS的守护进程。它会自动为Hadoop守护进程和客户端生æˆåˆé€‚çš„é…置文件(hadoop-site.xml)。HOD还å¯ä»¥å°†Hadoop分å‘到它分é…出æ¥çš„虚拟Hadoop集群的节点上。简而言之,HOD使管ç†å‘˜å’Œç”¨æˆ·è½»æ¾åœ°å¿«é€Ÿæ­å»ºå’Œä½¿ç”¨hadoop。它也是Hadoopå¼€å‘人员和测试人员éžå¸¸æœ‰ç”¨çš„一个工具,他们å¯ä»¥ä½¿ç”¨HOD共享一个物ç†é›†ç¾¤æ¥æµ‹è¯•å„自的Hadoop版本。

+
+
+ 文档 +

读一é下é¢çš„文档,你会在使用HODæ–¹é¢äº†è§£æ›´å¤š

+
    +
  • HOD管ç†æŒ‡å— : 此指å—概述了HOD的体系结构,Torque资æºç®¡ç†å™¨åŠå…¶ä»–å„ç§æ”¯æŒå·¥å…·ï¼Œä¹Ÿä¼šå‘Šè¯‰ä½ å¦‚何安装,é…置和è¿è¡ŒHOD。
  • +
  • HODé…ç½®æŒ‡å— : 此指å—讨论HODçš„é…置段,会告诉你如何使用那些最é‡è¦å’Œæœ€å¸¸ç”¨çš„é…置项。
  • +
  • HODç”¨æˆ·æŒ‡å— : 此指å—会告诉你如何开始使用HOD,它的å„ç§åŠŸèƒ½ç‰¹æ€§ï¼Œå‘½ä»¤è¡Œé€‰é¡¹ï¼Œä¹Ÿä¼šç»™ä½ ä¸€äº›æ•…障解决方é¢çš„详细帮助。
  • +
+
+ +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hod_admin_guide.xml b/src/docs/cn/src/documentation/content/xdocs/hod_admin_guide.xml new file mode 100644 index 00000000000..6d1a0d3d8da --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hod_admin_guide.xml @@ -0,0 +1,237 @@ + + + + + + + + +
+ + Hadoop On Demand + +
+ + +
+概述 +

Hadoop On Demand (HOD)是一个能在一个共享集群上供应和管ç†ç›¸äº’独立的Hadoop Map/Reduceå’ŒHadoop分布å¼æ–‡ä»¶ç³»ç»Ÿï¼ˆHDFS)实例的系统。它能让管ç†å‘˜å’Œç”¨æˆ·è½»æ¾åœ°å¿«é€Ÿæ­å»ºå’Œä½¿ç”¨hadoop。HOD对Hadoopçš„å¼€å‘人员和测试人员也éžå¸¸æœ‰ç”¨ï¼Œä»–们å¯ä»¥é€šè¿‡HOD共享一个物ç†é›†ç¾¤æ¥æµ‹è¯•å„自ä¸åŒçš„Hadoop版本。

+

HODä¾èµ–资æºç®¡ç†å™¨(RM)æ¥åˆ†é…节点,这些节点被用æ¥åœ¨ä¹‹ä¸Šè¿è¡Œhadoop实例。目å‰ï¼ŒHOD采用的是Torque资æºç®¡ç†å™¨ã€‚ +

+

+基本的HOD系统架构包å«çš„下列组件:

+
    +
  • 一个资æºç®¡ç†å™¨ï¼ˆå¯èƒ½åŒæ—¶é™„带一个调度程åºï¼‰
  • +
  • å„ç§HOD的组件
  • +
  • Hadoop Map/Reduceå’ŒHDFS守护进程
  • +
+ +

+通过与以上组件交互,HOD在给定的集群上供应和维护Hadoop Map/Reduce实例,或者HDFS实例。集群中的节点å¯çœ‹ä½œç”±ä¸¤ç»„节点构æˆï¼š

+
    +
  • æ交节点(Submit nodes):用户通过HOD客户端在这些节点上申请集群,之åŽé€šè¿‡Hadoop客户端æ交Hadoop作业。
  • +
  • 计算节点(Compute nodes):利用资æºç®¡ç†å™¨ï¼ŒHOD组件在这些节点上è¿è¡Œä»¥ä¾›åº”Hadoop守护进程。之åŽï¼ŒHadoop作业在这些节点上è¿è¡Œã€‚
  • +
+ +

+下é¢æ˜¯å¯¹ç”³è¯·é›†ç¾¤åŠåœ¨ä¹‹ä¸Šè¿è¡Œä½œä¸šæ‰€éœ€æ“作步骤的简è¦æ述。 +

+
    +
  • 用户在æ交节点上用HOD客户端分é…所需数目节点的集群,在上é¢ä¾›åº”Hadoop。
  • +
  • HOD客户端利用资æºç®¡ç†å™¨æŽ¥å£ï¼ˆåœ¨Torque中是qsub)æ交一个被称为RingMasterçš„HOD进程作为一个资æºç®¡ç†å™¨ä½œä¸šï¼Œç”³è¯·ç†æƒ³æ•°ç›®çš„节点。这个作业被æ交到资æºç®¡ç†å™¨çš„中央æœåŠ¡å™¨ä¸Šï¼ˆåœ¨Torque中å«pbs_server)。
  • +
  • 在计算节点上,资æºç®¡ç†å™¨çš„从(slave)守护程åº(Torque中的pbs_moms)接å—并处ç†ä¸­å¤®æœåŠ¡å™¨(Torque中的pbs_server)分é…的作业。RingMaster进程在其中一个计算节点(Torque中的mother superior)上开始è¿è¡Œã€‚
  • +
  • 之åŽï¼ŒRingmaster通过资æºç®¡ç†å™¨çš„å¦å¤–一个接å£(在Torque中是pbsdsh)在所有分é…到的计算节点上è¿è¡Œç¬¬äºŒä¸ªHOD组件HodRing,å³åˆ†å¸ƒå¼ä»»åŠ¡ã€‚
  • +
  • HodRingåˆå§‹åŒ–之åŽä¼šä¸ŽRingMaster通信获å–Hadoop指令,并éµç…§æ‰§è¡Œã€‚一旦Hadoop的命令开始å¯åŠ¨ï¼Œå®ƒä»¬ä¼šå‘RingMaster登记,æ供关于守护进程的信æ¯ã€‚
  • +
  • Hadoop实例所需的é…置文件全部由HOD自己生æˆï¼Œæœ‰ä¸€äº›æ¥è‡ªäºŽç”¨æˆ·åœ¨é…置文件设置的选项。
  • +
  • HOD客户端ä¿æŒå’ŒRingMaster的通信,找出JobTrackerå’ŒHDFS守护进程的ä½ç½®æ‰€åœ¨ã€‚
  • +
+

之åŽçš„文档会讲述如何在一个物ç†é›†ç¾¤çš„节点上安装HOD。

+
+ +
+先决æ¡ä»¶ +

è¦ä½¿ç”¨HOD,你的系统应包å«ä¸‹åˆ—的硬件和软件

+

æ“作系统: HODç›®å‰åœ¨RHEL4上测试通过。
+节点:HOD至少需è¦3个由资æºç®¡ç†å™¨é…置的节点。

+ +

软件

+

在使用HOD之å‰ï¼Œä»¥ä¸‹ç»„件必须被安装到所有节点上:

+
    +
  • Torque:资æºç®¡ç†å™¨
  • +
  • Python:HODè¦æ±‚Python 2.5.1
  • +
+ +

下列组件是å¯é€‰çš„,你å¯ä»¥å®‰è£…以获å–HOD更好的功能:

+
    +
  • Twisted Python:这个å¯ä»¥ç”¨æ¥æå‡HODçš„å¯æ‰©å±•æ€§ã€‚如果检测到这个模å—已安装,HOD就用它,å¦åˆ™å°±ä½¿ç”¨é»˜è®¤çš„模å—。
  • + +
  • Hadoop:HOD能自动将Hadoop分å‘到集群的所有节点上。ä¸è¿‡ï¼Œå¦‚æžœHadoop在所有节点上已ç»å¯ç”¨ï¼ŒHOD也å¯ä»¥ä½¿ç”¨å·²ç»å®‰è£…好的Hadoop。HODç›®å‰æ”¯æŒHadoop 0.15和其åŽç»­ç‰ˆæœ¬ã€‚
  • +
+ +

注释: HODçš„é…置需è¦ä»¥ä¸Šè¿™äº›ç»„件的安装ä½ç½®åœ¨é›†ç¾¤æ‰€æœ‰èŠ‚点上ä¿æŒä¸€è‡´ã€‚如果在æ交节点上的安装ä½ç½®ä¹Ÿç›¸åŒï¼Œé…置起æ¥ä¼šæ›´ç®€å•ã€‚

+
+ +
+资æºç®¡ç†å™¨ +

ç›®å‰ï¼ŒHOD使用Torque资æºç®¡ç†å™¨æ¥åˆ†é…节点和æ交作业。Torque是一个开æºçš„资æºç®¡ç†å™¨ï¼Œæ¥è‡ªäºŽCluster Resources,是一个社区基于PBS项目努力的结晶。它æ供对批处ç†ä½œä¸šå’Œåˆ†æ•£çš„计算节点(Compute nodes)的控制。你å¯ä»¥è‡ªç”±åœ°ä»Žæ­¤å¤„下载Torque。

+

所有torque相关的文档å¯ä»¥åœ¨è¿™å„¿çš„TORQUE Resource Manager一节找到。在这里å¯ä»¥çœ‹åˆ°wiki文档。如果想订阅TORQUE的邮件列表或查看问题存档,访问这里。

+ +

使用带Torque的HOD:

+
    +
  • 安装Torque组件:在一个节点上(head node)安装pbs_server,所有计算节点上安装pbs_mom,所有计算节点和æ交节点上安装PBS客户端。至少åšæœ€åŸºæœ¬çš„é…置,使Torque系统跑起æ¥ï¼Œä¹Ÿå°±æ˜¯ï¼Œä½¿pbs_server能知é“该和哪些机器通è¯ã€‚查看这里å¯ä»¥äº†è§£åŸºæœ¬é…置。è¦äº†è§£é«˜çº§é…置,请查看这里。
  • +
  • 在pbs_server上创建一个作业æ交队列。队列的åå­—å’ŒHODçš„é…ç½®å‚æ•°resource-manager.queue相åŒã€‚Hod客户端利用此队列æ交RingMaster进程作为Torque作业。
  • +
  • 在集群的所有节点上指定一个cluster name作为property。这å¯ä»¥ç”¨qmgr命令åšåˆ°ã€‚比如:qmgr -c "set node node properties=cluster-name"。集群åå­—å’ŒHODçš„é…ç½®å‚æ•°hod.cluster是相åŒçš„。
  • +
  • ç¡®ä¿ä½œä¸šå¯ä»¥æ交到节点上去。这å¯ä»¥é€šè¿‡ä½¿ç”¨qsub命令åšåˆ°ã€‚比如:echo "sleep 30" | qsub -l nodes=3
  • +
+
+ +
+安装HOD + +

现在资æºç®¡ç†å™¨å·²ç»å®‰è£…好了,我们接ç€ä¸‹è½½å¹¶å®‰è£…HOD。

+
    +
  • 如果你想从Hadoop tar包中获å–HOD,它在'contrib'下的'hod'的根目录下。
  • +
  • 如果你从编译æºç ï¼Œå¯ä»¥åœ¨Hadoop根目录下的è¿è¡Œant tar, 生æˆHadoop tar包。然åŽä»ŽèŽ·å–HOD,å‚照上é¢ã€‚
  • +
  • 把这个目录下的所有文件分å‘到集群的所有节点上。注æ„文件拷è´çš„ä½ç½®åº”在所有节点上ä¿æŒä¸€è‡´ã€‚
  • +
  • 注æ„,编译hadoop时会创建HOD,åŒæ—¶ä¼šæ­£ç¡®åœ°è®¾ç½®æ‰€æœ‰HOD必须的脚本文件的æƒé™ã€‚
  • +
+
+ +
+é…ç½®HOD + +

安装HODåŽä½ å°±å¯ä»¥é…置它。为了è¿è¡ŒHOD需è¦åšçš„最å°é…置会在下é¢è®²è¿°ï¼Œæ›´å¤šé«˜çº§çš„é…置会在HODé…置指å—里é¢è®²è§£ã€‚

+
+ 最å°é…ç½® +

为è¿è¡ŒHOD,以下的最å°é…置是必须è¦åšçš„:

+
    +
  • 在你想è¦è¿è¡Œhod的节点上,编辑<install dir>/conf目录下的hodrc文件。这个文件包å«äº†è¿è¡Œhod所必需的最少é‡çš„设置。
  • +
  • +

    为这个é…置文件中的定义的å˜é‡æŒ‡å®šé€‚åˆä½ çŽ¯å¢ƒçš„值。注æ„,有些å˜é‡åœ¨æ–‡ä»¶ä¸­å‡ºçŽ°äº†ä¸æ­¢ä¸€æ¬¡ã€‚

    + +
      +
    • ${JAVA_HOME}:Hadoopçš„Java的安装ä½ç½®ã€‚Hadoop支æŒSun JDK 1.5.xåŠä»¥ä¸Šç‰ˆæœ¬ã€‚
    • +
    • ${CLUSTER_NAME}:集群å称,由'node property'指定,在资æºç®¡ç†å™¨é…置中曾æ到过。
    • +
    • ${HADOOP_HOME}:Hadoop在计算节点和æ交节点上的安装ä½ç½®ã€‚
    • +
    • ${RM_QUEUE}:在资æºç®¡ç†å™¨é…置中设置的作业æ交队列。
    • +
    • ${RM_HOME}:资æºç®¡ç†å™¨åœ¨è®¡ç®—节点和æ交节点的安装ä½ç½®ã€‚
    • +
    +
  • + +
  • +

    以下环境å˜é‡å¯èƒ½éœ€è¦è®¾ç½®ï¼Œå–决于你的系统环境。在你è¿è¡ŒHOD客户端的地方这些å˜é‡å¿…须被定义,也必须在HODé…置文件中通过设定resource_manager.env-vars的值指定。多个å˜é‡å¯æŒ‡å®šä¸ºç”¨é€—å·åˆ†éš”çš„key=value对组æˆçš„列表。

    +
      +
    • HOD_PYTHON_HOME:如果python安装在计算节点或æ交节点的éžé»˜è®¤ä½ç½®ï¼Œé‚£ä¹ˆè¿™ä¸ªå€¼å¿…须设定为pythonçš„å¯æ‰§è¡Œæ–‡ä»¶çš„实际ä½ç½®ã€‚
    • +
    +
  • +
+
+ +
+ 高级é…ç½® +

ä½ å¯ä»¥æ£€æŸ¥å’Œä¿®æ”¹å…¶å®ƒé…置选项æ¥æ»¡è¶³ä½ çš„特定需è¦ã€‚关于HODé…置的更多信æ¯ï¼Œè¯·å‚考é…置指å—。

+
+
+
+ è¿è¡ŒHOD +

当HODé…置好åŽï¼Œä½ å°±å¯ä»¥è¿è¡Œå®ƒäº†ã€‚更多信æ¯è¯·å‚考HOD用户指å—。

+
+ +
+ 支æŒå·¥å…·å’Œå®žç”¨ç¨‹åº +

此节æ述一些å¯ç”¨äºŽç®¡ç†HOD部署的支æŒå·¥å…·å’Œåº”用程åºã€‚

+
+ logcondense.py - 管ç†æ—¥å¿—文件 +

在HOD用户指å—有æ到,HODå¯é…ç½®æˆå°†Hadoop日志上传到一个é…置好的é™æ€HDFS上。éšç€æ—¶é—´å¢žåŠ ï¼Œæ—¥å¿—æ•°é‡ä¼šä¸æ–­å¢žé•¿ã€‚logcondense.pyå¯ä»¥å¸®åŠ©ç®¡ç†å‘˜æ¸…ç†ä¸Šä¼ åˆ°HDFS的日志文件。

+
+ è¿è¡Œlogcondense.py +

logcondense.py在hod_install_location/support文件夹下。你å¯ä»¥ä½¿ç”¨python去è¿è¡Œå®ƒï¼Œæ¯”如python logcondense.py,或者授以执行æƒé™ï¼Œç›´æŽ¥è¿è¡Œlogcondense.py。如果å¯ç”¨äº†æƒé™ï¼Œlogcondense.py需è¦è¢«æœ‰è¶³å¤Ÿæƒé™ï¼Œèƒ½åˆ é™¤HDFS上上传目录下日志文件的用户è¿è¡Œã€‚比如,在é…置指å—中æåŠè¿‡ï¼Œç”¨æˆ·å¯ä»¥é…置将日志放在HDFS上的其主目录下。在这ç§æƒ…况下,你需è¦å…·æœ‰è¶…级用户æƒé™ï¼Œæ‰èƒ½è¿è¡Œlogcondense.py删除所有用户主目录下的日志文件。

+
+
+ logcondense.py的命令行选项 +

logcondense.py支æŒä»¥ä¸‹å‘½ä»¤è¡Œé€‰é¡¹

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
短选项长选项å«ä¹‰ä¾‹å­
-p--packagehadoop脚本的全路径。Hadoop的版本必须和è¿è¡ŒHDFS的版本一致。/usr/bin/hadoop
-d--days删除超过指定天数的日志文件7
-c--configHadoopé…置目录的路径,hadoop-site.xml存在于此目录中。hadoop-site.xml中须指明待删除日志存放的HDFSçš„NameNode。/home/foo/hadoop/conf
-l--logs一个HDFS路径,须和log-destination-uri指定的是åŒä¸€ä¸ªHDFS路径,ä¸å¸¦hdfs:// URI串,这点在é…置指å—中æ到过。/user
-n--dynamicdfs如果为true,logcondense.py除è¦åˆ é™¤Map/Reduce日志之外还需删除HDFS日志。å¦åˆ™ï¼Œå®ƒåªåˆ é™¤Map/Reduce日志,这也是ä¸æŒ‡å®šè¿™ä¸ªé€‰é¡¹æ—¶çš„默认行为。这个选项对下é¢çš„情况éžå¸¸æœ‰ç”¨ï¼šä¸€ä¸ªåŠ¨æ€çš„HDFSç”±HOD供应,一个é™æ€çš„HDFS用æ¥æ”¶é›†æ—¥å¿—文件 - 也许这是测试集群中一个éžå¸¸æ™®é的使用场景。false
+

比如,å‡å¦‚è¦åˆ é™¤æ‰€æœ‰7天之å‰çš„日志文件,hadoop-site.xml存放在~/hadoop-conf下,hadoop安装于~/hadoop-0.17.0,你å¯ä»¥è¿™æ ·ï¼š

+

python logcondense.py -p ~/hadoop-0.17.0/bin/hadoop -d 7 -c ~/hadoop-conf -l /user

+
+
+
+ checklimits.sh - 监视资æºé™åˆ¶ +

checklimits.sh是一个针对Torque/Maui环境的HOD工具(Maui集群调度器 是一个用于集群和超级计算机的开æºä½œä¸šè°ƒåº¦å™¨ï¼Œæ¥è‡ªclusterresourcces)。当新æ交的作业è¿å或超过用户在Maui调度器里设置的é™åˆ¶æ—¶ï¼Œchecklimits.sh脚本更新torqueçš„comment字段。它使用qstat在torqueçš„job-list中åšä¸€æ¬¡é历确定作业是在队列中还是已完æˆï¼Œè¿è¡ŒMaui工具checkjob检查æ¯ä¸€ä¸ªä½œä¸šæ˜¯å¦è¿å用户é™åˆ¶è®¾å®šï¼Œä¹‹åŽè¿è¡Œtorqueçš„qalter工具更新作业的'comment'的属性。当å‰ï¼Œå®ƒæŠŠé‚£äº›è¿åé™åˆ¶çš„作业的comment的值更新为User-limits exceeded. Requested:([0-9]*) Used:([0-9]*) MaxLimit:([0-9]*)。之åŽï¼ŒHODæ ¹æ®è¿™ä¸ªæ³¨é‡Šå†…容åšå‡ºç›¸åº”处ç†ã€‚ +

+ +
+ è¿è¡Œchecklimits.sh +

checklimits.shå¯ä»¥åœ¨hod_install_location/support目录下下找到。在具有得执行æƒé™åŽï¼Œè¿™ä¸ªshell脚本å¯ä»¥ç›´æŽ¥é€šè¿‡sh checklimits.sh 或者./checklimits.shè¿è¡Œã€‚这个工具è¿è¡Œçš„机器上应有Torqueå’ŒMaui的二进制è¿è¡Œæ–‡ä»¶ï¼Œå¹¶ä¸”这些文件è¦åœ¨è¿™ä¸ªshell脚本进程的路径中。为了更新ä¸åŒç”¨æˆ·ä½œä¸šçš„comment值,这个工具必须以torque的管ç†å‘˜æƒé™è¿è¡Œã€‚这个工具必须按照一定时间间隔é‡å¤è¿è¡Œï¼Œæ¥ä¿è¯æ›´æ–°job的约æŸæ¡ä»¶ï¼Œæ¯”如å¯ä»¥é€šè¿‡cron。请注æ„,这个脚本中用到的资æºç®¡ç†å™¨å’Œè°ƒåº¦å™¨å‘½ä»¤è¿è¡Œä»£ä»·å¯èƒ½ä¼šæ¯”价大,所以最好ä¸è¦åœ¨æ²¡æœ‰sleeping的紧凑循环中è¿è¡Œã€‚ +

+
+
+ +
+ verify-account - 用于核实用户æ交作业所使用的å¸å·çš„脚本 +

生产系统一般使用å¸å·ç³»ç»Ÿæ¥å¯¹ä½¿ç”¨å…±äº«èµ„æºçš„用户收费。HOD支æŒä¸€ä¸ªå«resource_manager.pbs-accountçš„å‚数,用户å¯ä»¥é€šè¿‡è¿™ä¸ªå‚æ•°æ¥æŒ‡å®šæ交作业时使用的å¸å·ã€‚核实这个å¸æˆ·åœ¨å¸å·ç®¡ç†ç³»ç»Ÿä¸­çš„有效性是有必è¦çš„。脚本hod-install-dir/bin/verify-accountæ供了一ç§æœºåˆ¶è®©ç”¨æˆ·æ’入自定义脚本æ¥å®žçŽ°è¿™ä¸ªæ ¸å®žè¿‡ç¨‹ã€‚

+
+ 在HOD中集æˆverify-account +

在分é…集群之å‰ï¼ŒHODè¿è¡Œverify-account脚本,将resource_manager.pbs-account的值作为å‚数传递给用户自定义脚本æ¥å®Œæˆç”¨æˆ·çš„确认。系统还å¯ä»¥é€šè¿‡è¿™ç§æ–¹å¼æ¥å–代它本身的å¸å·ç³»ç»Ÿã€‚若该用户脚本中的返回值éž0,就会导致HOD分é…集群失败。并且在å‘生错误时,HOD还会将脚本中产生的错误信æ¯æ‰“å°å‡ºæ¥ã€‚通过这ç§æ–¹å¼ï¼Œä»»ä½•æ述性的错误信æ¯éƒ½å¯ä»¥ä»Žç”¨æˆ·è„šæœ¬ä¸­è¿”回给用户。 +

+

在HOD中自带的默认脚本是ä¸åšä»»ä½•çš„用户核实,并返回0。

+

如果HOD没有找到上é¢æ到的verify-account脚本,HOD就会认为该用户核实的功能被关闭,然åŽç»§ç»­è‡ªå·±ä»¥åŽçš„分é…工作。

+
+
+ +
+ +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hod_config_guide.xml b/src/docs/cn/src/documentation/content/xdocs/hod_config_guide.xml new file mode 100644 index 00000000000..31ddc84e076 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hod_config_guide.xml @@ -0,0 +1,158 @@ + + + + + + + +
+ + Hadoop On Demand:é…ç½®æŒ‡å— + +
+ + +
+ 1. 简介 +

+ 这个文档讲述了一些最é‡è¦å’Œå¸¸ç”¨çš„Hadoop On Demand(HOD)的é…置项。 + 这些é…置项å¯é€šè¿‡ä¸¤ç§æ–¹å¼æŒ‡å®šï¼šINI风格的é…置文件,通过--section.option[=value]æ ¼å¼æŒ‡å®šçš„HOD shell的命令行选项。如果两个地方都指定了åŒä¸€ä¸ªé€‰é¡¹ï¼Œå‘½ä»¤è¡Œä¸­çš„值覆盖é…置文件中的值。 +

+

+ ä½ å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤èŽ·å¾—所有é…置项的简è¦æ述: +

+
$ hod --verbose-help
+ +
+
+ 2. 段 +

HODé…置文件分æˆä»¥ä¸‹å‡ ä¸ªé…置段:

+
    +
  • hod: HOD客户端的é…置项
  • +
  • resource_manager: 指定è¦ä½¿ç”¨çš„资æºç®¡ç†å™¨çš„é…置项,以åŠä½¿ç”¨è¯¥èµ„æºç®¡ç†å™¨æ—¶éœ€è¦çš„一些其他å‚数。
  • +
  • ringmaster: RingMaster进程的é…置项
  • +
  • hodring: HodRing进程的é…置项
  • +
  • gridservice-mapred: Map/Reduce守护进程的é…置项
  • +
  • gridservice-hdfs: HDFS守护进程的é…置项
  • +
+
+
+ 3. HODé…置项 +

+ 接下æ¥çš„一节会先æ述大部分HODé…置段中通用的一些é…置项,å†æè¿°å„é…置段特有的é…置项。 +

+ +
+ 3.1 一般的é…置项 + +

æŸäº›é…置项会在HODé…置中的多个段定义。在一个段中定义的é…置项,会被该段所适用的所有进程使用。这些é…置项æ„义相åŒï¼Œä½†åœ¨ä¸åŒçš„段中å¯ä»¥æœ‰ä¸åŒçš„å–值。

+ +
    +
  • temp-dir: HOD进程使用的临时目录。请确ä¿è¿è¡Œhod的用户有æƒé™åœ¨è¿™ä¸ªæŒ‡å®šçš„目录下创建å­ç›®å½•ã€‚如果想在æ¯æ¬¡åˆ†é…的时候都使用ä¸åŒçš„临时目录,å¯ä»¥ä½¿ç”¨çŽ¯å¢ƒå˜é‡ï¼Œèµ„æºç®¡ç†å™¨ä¼šè®©è¿™äº›çŽ¯å¢ƒå˜é‡å¯¹HOD进程å¯ç”¨ã€‚例如,在Torque设置的时候,使--ringmaster.temp-dir=/tmp/hod- temp-dir.$PBS_JOBID会让ringmaster在æ¯ä¸€æ¬¡ç”³è¯·æ—¶ä½¿ç”¨ä¸åŒçš„临时目录;Troque会在ringmasterå¯åŠ¨å‰å±•å¼€è¿™ä¸ªçŽ¯å¢ƒå˜é‡ã€‚ +
  • +
  • debug:数值类型,å–值范围是1-4。4会产生最多的logä¿¡æ¯ã€‚
  • +
  • log-dir:日志文件的存放目录。缺çœå€¼æ˜¯<install-location>/logs/。temp-dirå˜é‡çš„é™åˆ¶å’Œæ³¨æ„事项在这里åŒæ ·ä½¿ç”¨ã€‚ +
  • +
  • xrs-port-range:端å£èŒƒå›´ï¼Œä¼šåœ¨è¿™ä¹‹ä¸­æŒ‘选一个å¯ç”¨ç«¯å£ç”¨äºŽè¿è¡ŒXML-RPCæœåŠ¡ã€‚
  • +
  • http-port-range:端å£èŒƒå›´ï¼Œä¼šåœ¨è¿™ä¹‹ä¸­æŒ‘选一个å¯ç”¨ç«¯å£ç”¨äºŽè¿è¡ŒHTTPæœåŠ¡ã€‚
  • +
  • java-home:给Hadoop使用的Javaçš„ä½ç½®ã€‚
  • +
  • syslog-address:syslog守护进程è¦ç»‘定的地å€ã€‚æ ¼å¼ä¸ºhost:port。如果é…置了这个选项,HOD日志信æ¯ä¼šè¢«è®°å½•åˆ°è¿™ä¸ªä½ç½®çš„syslog。
  • +
+
+ +
+ 3.2 hodçš„é…置项 +
    +
  • cluster:集群的æ述性å称。对于Torque,这个值被指定为集群中所有节点的'Node property'。HOD使用这个值计算å¯ç”¨èŠ‚点的个数。
  • +
  • client-params:逗å·åˆ†å‰²çš„hadoopé…ç½®å‚数列表,其中的æ¯ä¸€é¡¹éƒ½æ˜¯ä¸€ä¸ªkey-value对。在æ交节点上会æ®æ­¤äº§ç”Ÿä¸€ä¸ªhadoop-site.xml,用于è¿è¡ŒMap/Reduce作业。
  • + +
  • job-feasibility-attr: 正则表达å¼ï¼Œç”¨äºŽæŒ‡å®šæ˜¯å¦å’Œå¦‚何检查作业的å¯è¡Œæ€§ ï¼ èµ„æºç®¡ç†å™¨é™åˆ¶æˆ–调度é™åˆ¶ã€‚ç›®å‰æ˜¯é€šè¿‡torque作业的'comment'属性实现的,缺çœæƒ…况下没有开å¯è¿™ä¸ªåŠŸèƒ½ã€‚设置了这个é…置项åŽï¼ŒHOD会使用它æ¥ç¡®å®šå“ªäº›ç§ç±»çš„é™åˆ¶æ˜¯å¯ç”¨çš„,以åŠè¯·æ±‚超出é™åˆ¶æˆ–者累积超出é™åˆ¶æ—¶æ˜¯å›žæ”¶æœºç¾¤è¿˜æ˜¯ç•™åœ¨æŽ’队状æ€ã€‚torque comment属性å¯ä»¥è¢«æŸä¸ªå¤–部机制周期性地更新。比如,comment属性被hod/support目录下的checklimits.sh更新,这样设置job-feasibility-attr的值等于TORQUE_USER_LIMITS_COMMENT_FIELD, "User-limits exceeded. Requested:([0-9]*) Used:([0-9]*) MaxLimit:([0-9]*)"会使HOD产生相应的行为。
  • +
+
+ +
+ 3.3 resouce_managerçš„é…置项 + +
    +
  • queue:资æºç®¡ç†å™¨ä¸­é…置的队列å,作业会被æ交到这里。
  • + +
  • batch-home:个安装目录,其下的'bin'中有资æºç®¡ç†å™¨çš„å¯æ‰§è¡Œæ–‡ä»¶ã€‚
  • +
  • env-vars:逗å·åˆ†éš”çš„key-value对的列表,形å¼æ˜¯key=value,它会被传递给è¿è¡Œåœ¨è®¡ç®—节点的作业。例如,如果ptyhon没有安装在常规ä½ç½®ï¼Œç”¨æˆ·å¯ä»¥é€šè¿‡è®¾ç½®çŽ¯å¢ƒå˜é‡'HOD_PYTHON_HOME'指定pythonå¯æ‰§è¡Œæ–‡ä»¶çš„路径。之åŽï¼Œåœ¨è®¡ç®—节点è¿è¡Œçš„HOD的进程就å¯ä»¥ä½¿ç”¨è¿™ä¸ªå˜é‡äº†ã€‚
  • +
+
+ +
+ 3.4 ringmasterçš„é…置项 +
    +
  • work-dirs:这是一个由逗å·åˆ†éš”的路径列表,这些路径将作为HOD产生和传递给Hadoop,用于存放DFSå’ŒMap/Reduceæ•°æ®çš„目录的根目录。例如,这是DFSæ•°æ®å—存放的路径。一般情况下,有多少å—ç£ç›˜å°±æŒ‡å®šå¤šå°‘路径,以确ä¿æ‰€æœ‰çš„ç£ç›˜éƒ½è¢«åˆ©ç”¨åˆ°ã€‚temp-dirå˜é‡çš„é™åˆ¶å’Œæ³¨æ„事项在这儿åŒæ ·é€‚用。
  • +
  • max-master-failures:hadoop主守护进å¯åŠ¨å‰å¯ä»¥å¤±è´¥çš„次数,超出这个次数åŽï¼ŒHOD会让这次集群分é…失败。在HOD集群中,有时候由于æŸäº›é—®é¢˜ï¼Œæ¯”如机器没安装java,没有安装Hadoop,或者Hadoop版本错误等,会存在一个或几个“åâ€èŠ‚点。当这个é…置项被设为正整数时,åªæœ‰å½“hadoop matser(JobTracker或者NameNode)在上述的å节点上,由于上é¢æ到的ç§ç§åŽŸå› å¯åŠ¨å¤±è´¥çš„次数超过设定的值时,RingMasteræ‰ä¼šæŠŠé”™è¯¯è¿”回给客户端。如果å°è¯•å¯åŠ¨çš„次数没有超过设定值,当下一个HodRing请求è¿è¡Œä¸€ä¸ªå‘½ä»¤æ—¶ï¼ŒåŒä¸€ä¸ªhadoop master会指定给这个HodRing。这样,å³ä½¿é›†ç¾¤ä¸­å­˜åœ¨ä¸€äº›å的节点,HOD也会尽全力使这次分é…æˆåŠŸã€‚ +
  • + +
+
+
+ 3.5 gridservice-hdfsçš„é…置项 +
    +
  • external:如果被置为false,HOD必须在通过allocate命令分é…的节点上自己创建HDFS集群。注æ„,在这ç§æƒ…况下,如果集群被回收,HDFS集群会åœæ­¢ï¼Œæ‰€æœ‰æ•°æ®ä¼šä¸¢å¤±ã€‚如果被置为true,它会å°è¯•é“¾æŽ¥å¤–部的已é…置的HDFS系统。通常,因为在作业è¿è¡Œä¹‹å‰ä½œä¸šçš„输入需è¦è¢«æ”¾ç½®åœ¨HDFS上,并且作业的输出需è¦æŒä¹…ä¿ç•™ï¼Œåœ¨ç”Ÿäº§çŽ¯å¢ƒä¸­ä¸€ä¸ªå†…部的HDFS集群æ„义ä¸å¤§ã€‚
  • + +
  • host:外部é…置好的NameNode的主机å。
  • + +
  • fs_port:NameNode RPCæœåŠ¡ç»‘定的端å£ã€‚
  • + +
  • info_port:NameNode web UIæœåŠ¡ç»‘定的端å£ã€‚
  • + +
  • pkgs:安装目录,其下有bin/hadoopå¯æ‰§è¡Œæ–‡ä»¶ã€‚å¯ç”¨æ¥ä½¿ç”¨é›†ç¾¤ä¸Šé¢„先安装的Hadoop版本。
  • + +
  • server-params:一个逗å·åˆ†å‰²çš„hadoopé…ç½®å‚数列表,æ¯ä¸€é¡¹ä¸ºkey-value对形å¼ã€‚这些将用于产生被NameNodeå’ŒDataNode使用到的hadoop-site.xml文件。
  • + +
  • final-server-params:除会被标记为final外和上é¢ç›¸åŒã€‚
  • +
+
+ +
+ 3.6 gridservice-mapredçš„é…置项 + +
    +
  • external:如果被置为false,HOD必须在通过allocate命令分é…的节点上自己创建Map/Reduce集群。如果被置为true,它会å°è¯•é“¾æŽ¥å¤–部的已é…置的Map/Reduce系统。
  • +
  • host:外部é…置好的JobTracker的主机å。
  • + +
  • tracker_port:JobTracker RPCæœåŠ¡ç»‘定的端å£ã€‚
  • + +
  • info_port:JobTracker web UIæœåŠ¡ç»‘定的端å£ã€‚
  • + +
  • pkgs:安装目录,其下有bin/hadoopå¯æ‰§è¡Œæ–‡ä»¶ã€‚
  • + +
  • server-params:一个逗å·åˆ†å‰²çš„hadoopé…ç½®å‚数列表,æ¯ä¸€é¡¹ä¸ºkey-value对形å¼ã€‚这些将用于产生被JobTrackerå’ŒTaskTracker使用到的hadoop-site.xml文件。
  • +
  • final-server-params:除会被标记为final外和上é¢ç›¸åŒã€‚
  • +
+
+ +
+ 3.7 hodringçš„é…置项 + +
    +
  • mapred-system-dir-root:DFS上的目录,HOD会在这个目录下创建å­ç›®å½•å¹¶æŠŠå…¨è·¯å¾„作为å‚æ•°'mapred.system.dir'的值传递给Hadoop守护进程。全路径的格å¼ä¸ºvalue-of-this-option/userid/mapredsystem/cluster-id。注æ„,如果HDFSå¯ç”¨äº†æƒé™ï¼Œè¿™é‡ŒæŒ‡å®šçš„路径下应å…许所有用户创建å­ç›®å½•ã€‚设置此é…置项的值为/user会使HOD使用用户的home目录æ¥äº§ç”Ÿmapred.system.dir的值。
  • +
  • log-destination-uri:一个URL,能å映一个外部的é™æ€çš„DFS或者集群节点上的本地文件系统上的路径。当集群被回收时,HOD会把Hadoop日志上传到这个路径。è¦æŒ‡å®šDFS路径,使用'hdfs://path'æ ¼å¼ã€‚è¦æŒ‡å®šä¸€ä¸ªé›†ç¾¤èŠ‚点上的本地文件系统路径,使用'file://path'æ ¼å¼ã€‚当HOD回收集群时,作为HOD的清除过程的一部分,hadoop日志会被删除。è¦åšåˆ°æŒä¹…储这些日志,你å¯ä»¥ä½¿ç”¨è¿™ä¸ªé…置项。路径的格å¼ä¼šæ˜¯values-of-this-option/userid/hod-logs/cluster-id。注æ„,应该ä¿è¯æ‰€æœ‰çš„用户能在这里指定的目录下创建å­ç›®å½•ã€‚把这个值设为hdfs://user会使这些日志被转移到用户在DFS上的home目录下。
  • +
  • pkgs:安装目录,其下有bin/hadoopå¯æ‰§è¡Œæ–‡ä»¶ã€‚如果给log-destination-uri指定了一个HDFS URL,HOD上传日志时会用到这个é…置项。注æ„,当用户使用了和外部é™æ€HDFSä¸åŒç‰ˆæœ¬çš„tarball时,这个é…置项会派上用场。
  • + +
+
+
+ +
diff --git a/src/docs/cn/src/documentation/content/xdocs/hod_user_guide.xml b/src/docs/cn/src/documentation/content/xdocs/hod_user_guide.xml new file mode 100644 index 00000000000..0137536c1a0 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/hod_user_guide.xml @@ -0,0 +1,559 @@ + + + + + +
+ + Hadoop On Demandç”¨æˆ·æŒ‡å— + +
+ + +
+ 简介 +

Hadoop On Demand (HOD)是一个能在大规模物ç†é›†ç¾¤ä¸Šä¾›åº”虚拟Hadoop集群的系统。它使用Torque资æºç®¡ç†å™¨è¿›è¡ŒèŠ‚点分é…。在所分é…的节点上,它能å¯åŠ¨Hadoop Map/Reduce以åŠHDFS守护进程。它能自动为Hadoop守护进程åŠå®¢æˆ·ç«¯ç”Ÿæˆåˆé€‚çš„é…置文件(Hadoop-site.xml)。HOD还能够将Hadoop分å‘到它分é…的虚拟集群节点上。总之,HOD方便管ç†è€…和用户快速安装与使用Hadoop。它也是需è¦åœ¨åŒä¸€ç‰©ç†é›†ç¾¤ä¸Šæµ‹è¯•å„自版本的Hadoopå¼€å‘者和测试者的实用工具。

+

HOD支æŒHadoop 0.15åŠå…¶åŽç»­ç‰ˆæœ¬ã€‚

+

åŽé¢çš„文档包括一个快速入门指å—能让你快速上手HOD,一个所有HOD特性的详细手册,命令行选项,一些已知问题和故障排除的信æ¯ã€‚

+
+
+ HOD使用入门 + +

在这部分,我们将会é€æ­¥éª¤åœ°ä»‹ç»ä½¿ç”¨HOD涉åŠåˆ°çš„最基本的æ“作。在开始éµå¾ªè¿™äº›æ­¥éª¤ä¹‹å‰ï¼Œæˆ‘们å‡å®šHODåŠå…¶ä¾èµ–的软硬件å‡å·²è¢«æ­£ç¡®å®‰è£…å’Œé…置。这步通常由集群的系统管ç†å‘˜è´Ÿè´£ã€‚

+

HOD的用户界é¢æ˜¯ä¸€ä¸ªå‘½ä»¤è¡Œå·¥å…·ï¼Œå«åšhod。它被一个通常由系统管ç†å‘˜ä¸ºç”¨æˆ·è®¾ç½®å¥½çš„é…置文件所驱动。用户在使用hod的时候å¯ä»¥è¦†ç›–这个é…置,文档的åŽé¢ä¼šç”±ä»‹ç»ã€‚使用hod时有如下两ç§æ–¹å¼å¯ä»¥æŒ‡å®šé…置文件:

+
    +
  • 在命令行中指定,使用 -c 选项。例如hod <operation> <required-args> -c path-to-the-configuration-file [ohter-options]
  • +
  • 在è¿è¡Œhod的地方设置环境å˜é‡HOD_CONF_DIR。这个å˜é‡åº”指å‘指å‘一个本地目录,其中有å为hodrc的文件。这与Hadoop中的HADOOP_CONF_DIR与hadoop-site.xml文件是类似的。如果命令行中未指定é…置文件,hod会查找HOD_CONF_DIR环境å˜é‡æŒ‡å®šç›®å½•ä¸‹çš„hodrc文件。
  • +
+

下é¢çš„例å­ä¸­ï¼Œæˆ‘们将ä¸ä¼šæ˜Žç¡®æŒ‡å‡ºè¿™ä¸ªé…置选项,å‡å®šå…¶å·²æ­£ç¡®æŒ‡å®šã€‚

+
一个典型HODä¼šè¯ +

一个典型HOD会è¯è‡³å°‘包括三个步骤:分é…,执行Hadoop作业,回收。为此,执行如下步骤。

+

创建一个集群目录

+

集群目录是本地文件系统上的一个目录,hod会为它分é…的集群产生对应的Hadoopé…ç½®hadoop-site.xml,放在这个目录下。这个目录å¯ä»¥æŒ‰ä¸‹æ–‡æ‰€è¿°æ–¹å¼ä¼ é€’ç»™hodæ“作。如果这个目录ä¸å­˜åœ¨ï¼ŒHOD会自动创建这个目录。一但分é…好了集群,用户å¯é€šè¿‡Hadoop --config选项指定集群目录,在之上è¿è¡ŒHadoop作业。

+ +

allocateæ“作

+

allocateæ“作用æ¥åˆ†é…一组节点并在之上安装和æä¾›Hadoop。它的语法如下。注æ„它è¦æ±‚指定å‚数集群目录(-d, --hod.clusterdir)和节点个数(-n, --hod.nodecount):

+ + + + + + +
$ hod allocate -d cluster_dir -n number_of_nodes [OPTIONS]
+

如果命令æˆåŠŸæ‰§è¡Œï¼Œcluster_dir/hadoop-site.xml会被生æˆï¼Œæ–‡ä»¶ä¸­åŒ…å«äº†åˆ†é…出的集群的信æ¯ã€‚它也会打å°å‡ºå…³äºŽHadoopçš„web UIçš„ä¿¡æ¯ã€‚

+

试è¿è¡Œè¿™ä¸ªå‘½ä»¤ä¼šäº§ç”Ÿå¦‚下输出。注æ„在这个例å­ä¸­é›†ç¾¤ç›®å½•æ˜¯~/hod-clusters/test,我们è¦åˆ†é…5个节点:

+ + + + +
$ hod allocate -d ~/hod-clusters/test -n 5
+ INFO - HDFS UI on http://foo1.bar.com:53422
+ INFO - Mapred UI on http://foo2.bar.com:55380
+ +

在分é…的集群上执行Hadoop作业

+

现在,å¯ä»¥ç”¨ä¸€èˆ¬çš„æ–¹å¼åœ¨åˆ†é…的集群上执行Hadoop作业了。这是å‡å®šåƒJAVA_HOME,指å‘Hadoop安装的路径已被正确地设置了:

+ + + + + + +
$ hadoop --config cluster_dir hadoop_command hadoop_command_args
+

或者

+ + + + + + +
$ export HADOOP_CONF_DIR=cluster_dir
+ $ hadoop hadoop_command hadoop_command_args
+

继续我们的例å­ï¼Œä¸‹é¢çš„命令会在分é…的集群上è¿è¡Œwordcount的例å­ï¼š

+
$ hadoop --config ~/hod-clusters/test jar /path/to/hadoop/hadoop-examples.jar wordcount /path/to/input /path/to/output
+

或者

+ + + +
$ export HADOOP_CONF_DIR=~/hod-clusters/test
+ $ hadoop jar /path/to/hadoop/hadoop-examples.jar wordcount /path/to/input /path/to/output
+

deallocateæ“作

+

deallocateæ“作用æ¥å›žæ”¶åˆ†é…到的集群。当完æˆé›†ç¾¤ä½¿ç”¨ä¹‹åŽï¼Œå¿…须执行回收æ“作使这些节点å¯ä»¥ä¸ºå…¶ä»–用户所用。deallocateæ“作的语法如下。注æ„它需è¦é›†ç¾¤ç›®å½•ï¼ˆ-d, --hod.clusterdir)作为å‚数:

+ + + + + + +
$ hod deallocate -d cluster_dir
+

继续我们的例å­ï¼Œå¦‚下命令会回收集群:

+
$ hod deallocate -d ~/hod-clusters/test
+

如你所è§ï¼ŒHODå…许用户分é…一个集群,éšæ„的使用它æ¥è¿è¡ŒHadoop作业。例如,通过从多个shell中å¯åŠ¨ä½¿ç”¨åŒä¸€ä¸ªé…置的hadoop,用户å¯ä»¥åšåˆ°åœ¨åŒä¸€ä¸ªé›†ç¾¤ä¸Šå¹¶å‘è¿è¡Œå¤šä¸ªä½œä¸šã€‚

+
+
使用HODè¿è¡ŒHadoop脚本 +

HODçš„scriptæ“作能将集群的分é…,使用和回收组织在一起。这对那些想è¿è¡ŒHadoop作业脚本,期望HOD能在脚本结æŸåŽè‡ªåŠ¨å®Œæˆæ¸…ç†æ“作的用户特别管用。用hod执行Hadoop脚本,需è¦è¿™ä¹ˆåšï¼š

+

创建脚本文件

+

这是一个普通的shell脚本,通常里é¢ä¼šåŒ…å«hadoop命令,如:

+ +
$ hadoop jar jar_file options
+

当然,用户å¯ä»¥å‘脚本中添加任何有效的命令。HOD会在执行这个脚本时自动地设置HADOOP_CONF_DIR指å‘分é…的集群。用户ä¸å¿…对此担心。ä¸è¿‡ï¼Œåƒåˆ†é…æ“作时一样,用户需è¦æŒ‡å®šä¸€ä¸ªé›†ç¾¤ç›®å½•ã€‚

+

è¿è¡Œè„šæœ¬

+

脚本æ“作的语法如下。注æ„它需è¦é›†ç¾¤ç›®å½•ï¼ˆ-d, --hod.clusterdir),节点个数(-n, --hod.nodecount)以åŠè„šæœ¬æ–‡ä»¶ï¼ˆ-s, --hod.script)作为å‚数:

+ + + + + + +
$ hod script -d cluster_directory -n number_of_nodes -s script_file
+

注æ„一但脚本执行完毕,HOD就会回收集群,这æ„味ç€è„šæœ¬å¿…é¡»è¦åšåˆ°ç­‰hadoop作业完æˆåŽè„šæœ¬æ‰ç»“æŸã€‚用户写脚本时必须注æ„这点。

+
+
+
+ HOD的功能 +
供应与管ç†Hadoop集群 +

HOD主è¦åŠŸèƒ½æ˜¯ä¾›åº”Hadoopçš„Map/Reduceå’ŒHDFS集群。这些在è§å…¥é—¨ä¸€èŠ‚å·²ç»åšè¿‡æ述。 此外,è¦æ˜¯è¿˜æœ‰èŠ‚点å¯ç”¨ï¼Œå¹¶ä¸”组织上也批准,一个用户å¯ä»¥åœ¨åŒä¸€æ—¶é—´å†…使用HOD分é…多个Map/Reduce集群。对于分é…到的ä¸åŒé›†ç¾¤ï¼Œç”¨æˆ·éœ€è¦ä¸ºä¸Šé¢æ到的cluster_dirå‚数指定ä¸åŒçš„路径。HODæä¾›listå’Œinfoæ“作å¯ä»¥ç®¡ç†å¤šä¸ªé›†ç¾¤ã€‚

+

listæ“作

+

listæ“作能列举到目å‰ä¸ºæ­¢ç”¨æˆ·æ‰€åˆ›å»ºçš„所有集群。存放hadoop-site.xml的集群目录,与JobTrackerå’Œï¼æˆ–HDFS的连接åŠçŠ¶æ€ä¹Ÿä¼šè¢«æ˜¾ç¤ºå‡ºæ¥ã€‚listæ“作的使用语法如下:

+ + + + + + +
$ hod list
+

infoæ“作

+

infoæ“作会显示指定集群相关的信æ¯ã€‚这些信æ¯åŒ…括Torque作业id,HOD Ringmaster进程,Hadoopçš„JobTrackerå’ŒNameNode守护进程等é‡è¦å®ˆæŠ¤è¿›ç¨‹çš„ä½ç½®ã€‚infoæ“作的语法如下。注æ„它需è¦é›†ç¾¤ç›®å½•ï¼ˆ-d, --hod.clusterdir)作为å‚数:

+ + + + + + +
$ hod info -d cluster_dir
+

cluster_dir应为å‰é¢allocateæ“作中指定的有效集群目录。

+
+
使用tarball分å‘Hadoop +

供应Hadoop时,HODå¯ä»¥ä½¿ç”¨é›†ç¾¤èŠ‚点上已ç»å®‰è£…好的Hadoop,也å¯ä»¥å°†hadoopçš„tarball作为供应æ“作的一部分在节点上进行分å‘和安装。如果使用tarball选项,就ä¸å¿…éžå¾—使用预装的Hadoop了,也ä¸è¦æ±‚集群节点上必须有一个预装的版本。这对开å‘ï¼QE环境下在一个共享集群上测试ä¸åŒç‰ˆæœ¬hadoopçš„å¼€å‘者尤其有用。

+

è¦ä½¿ç”¨é¢„装的Hadoop,你必须在hodrc中的gridservice-hdfs部分和gridservice-mapred部分指定pkgs选项。它必须指å‘集群中所有节点上Hadoop的安装路径。

+

指定Tarball的语法如下:

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes -t hadoop_tarball_location
+

例如,下é¢çš„命令根æ®tarball~/share/hadoop.tar.gz分é…Hadoop:

+
$ hod allocate -d ~/hadoop-cluster -n 10 -t ~/share/hadoop.tar.gz
+

类似地,使用hod脚本的语法如下:

+ + + + +
$ hod script -d cluster_directory -s scritp_file -n number_of_nodes -t hadoop_tarball_location
+

上é¢è¯­æ³•ä¸­æŒ‡å®šçš„hadoop_tarball_location应指å‘从所有计算节点都å¯ä»¥è®¿é—®çš„共享文件系统的路径。当å‰ï¼ŒHODåªæ”¯æŒæŒ‚载的NFS。

+

注æ„:

+
    +
  • 为了获得更好分å‘性能,建议Hadoop tarballåªåŒ…å«åº“与二进制文件,ä¸åŒ…å«æºä»£ç æˆ–文档。
  • +
  • 当你希望在用tarballæ–¹å¼åˆ†é…的集群上执行作业,你必须使用兼容的Hadoop版本æ交你的作业。最好的方å¼æ˜¯è§£åŽ‹ï¼Œä½¿ç”¨Tarball中的版本。
  • +
  • 你需è¦ç¡®ä¿åœ¨tar分å‘包的conf目录下没有Hadoopé…置文件hadoop-env.shå’Œhadoop-site.xml。如果这些文件存在并包å«é”™è¯¯çš„值,集群分é…å¯èƒ½ä¼šå¤±è´¥ã€‚ +
  • +
+
+
使用外部HDFS +

在典型的由HODæ供的Hadoop集群中,HDFSå·²ç»è¢«é™æ€åœ°ï¼ˆæœªä½¿ç”¨HOD)设置好。这能使数æ®åœ¨HODæ供的集群被回收åŽè¿˜å¯ä»¥æŒä¹…ä¿å­˜åœ¨HDFS中。为使用é™æ€é…置的HDFS,你的hodrc必须指å‘一个外部HDFS。具体就是,在hodrcçš„gridservice-hdfs部分将下é¢é€‰é¡¹è®¾ç½®ä¸ºæ­£ç¡®çš„值:

+
external = true
host = HDFS NameNode主机å
fs_port = HDFS NameNode端å£
info_port = HDFS NameNode web UI的端å£
+

注æ„:你也å¯ä»¥ä»Žå‘½ä»¤è¡Œå¼€å¯è¿™ä¸ªé€‰é¡¹ã€‚å³ï¼Œä½ è¿™æ ·åŽ»ä½¿ç”¨ä¸€ä¸ªé™æ€HDFS:
+

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes --gridservice-hdfs.external
+

如果需è¦ï¼ŒHODå³å¯ä»¥ä¾›åº”HDFS集群也å¯ä»¥ä¾›åº”Map/Reduce的集群HOD。这需è¦è®¾ç½®hodrc中的gridservice-hdfs部分的下列选项:

+
external = false
+
+
é…ç½®Hadoop的选项 +

HODæ供一个éžå¸¸æ–¹ä¾¿çš„机制能é…置它æ供的Hadoop守护进程和它在客户端生æˆçš„hadoop-site.xml。通过在HODé…置文件中指定é…ç½®å‚数,或在分é…集群时在命令行指定都å¯åšåˆ°è¿™ç‚¹ã€‚

+

é…ç½®Hadoop守护进程

+

è¦é…ç½®Hadoop守护进程,你å¯ä»¥è¿™ä¹ˆåšï¼š

+

对于Map/Reduce,指定gridservice-mapred部分的server-params项的指为一个以逗å·åˆ†å‰²çš„key-value对列表。åŒé…置动æ€HDFS集群一样,设置gridservice-hdfs部分的server-params项。如果这些å‚数应被标记æˆfinal,将这些å‚数包å«åˆ°ç›¸åº”部分的final-server-params项中。

+

例如:

+ +
server-params = mapred.reduce.parallel.copies=20,io.sort.factor=100,io.sort.mb=128,io.file.buffer.size=131072
final-server-params = mapred.child.java.opts=-Xmx512m,dfs.block.size=134217728,fs.inmemory.size.mb=128
+

è¦ä»Žå‘½ä»¤è¡ŒæŒ‡å®šé€‰é¡¹ï¼Œä½ å¯ä»¥ç”¨å¦‚下语法:

+

é…ç½®Map/Reduce守护进程:

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes -Mmapred.reduce.parallel.copies=20 -Mio.sort.factor=100
+

在上述例å­ä¸­ï¼Œmapred.reduce.parallel.copieså‚æ•°å’Œio.sort.factorå‚数将会被添加到server-params中,如果已ç»åœ¨server-params中存在,则它们会被覆盖。è¦å°†è¿™äº›å‚数指定æˆfinal类型,你å¯ä»¥ï¼š

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes -Fmapred.reduce.parallel.copies=20 -Fio.sort.factor=100
+

ä¸è¿‡ï¼Œåº”注æ„finalå‚数无法被命令行改写的,åªæœ‰åœ¨æœªæŒ‡å®šçš„情形æ‰èƒ½è¿½åŠ ã€‚

+

é…置动æ€ä¾›åº”çš„HDFS守护进程的选项与此相似。用-H替æ¢-M以,用-S替æ¢-Få³å¯ã€‚

+

é…ç½®Hadoop的作业æ交(客户端)程åº

+

如上所述,当allocateæ“作æˆåŠŸåŽï¼Œcluster_dir/hadoop-site.xml将会生æˆï¼Œå…¶ä¸­ä¼šåŒ…å«åˆ†é…的集群的JobTrackerå’ŒNameNodeçš„ä¿¡æ¯ã€‚这个é…置用于å‘集群æ交作业。HODæ供选项å¯å°†å…¶å®ƒçš„hadoopé…ç½®å‚数添加到该文件,其语法如下:

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes -Cmapred.userlog.limit.kb=200 -Cmapred.child.java.opts=-Xmx512m
+

上例中,mapred.userlog.limit.kb和mapred.child.java.opts会被添加到hod产生的hadoop-site.xml中。

+
+
查看Hadoop的Web-UI +

HODçš„allocateæ“作会打å°å‡ºJobTrackerå’ŒNameNodeçš„Web UIçš„URL。例如:

+
$ hod allocate -d ~/hadoop-cluster -n 10 -c ~/hod-conf-dir/hodrc
+ INFO - HDFS UI on http://host242.foo.com:55391
+ INFO - Mapred UI on http://host521.foo.com:54874 +
+

上é¢æ到的infoæ“作å¯ä»¥ç»™ä½ åŒæ ·çš„ä¿¡æ¯ã€‚

+
+
收集和查看Hadoop日志 +

è¦èŽ·å–在æŸäº›åˆ†é…节点上è¿è¡Œçš„守护进程的Hadoop日志:

+
    +
  • 登录感兴趣的节点。如果你想查看JobTracker或者NameNode的日志,listå’Œinfoæ“作能告诉你这些进程在那些节点上è¿è¡Œã€‚
  • +
  • 获å–感兴趣的守护进程的进程信æ¯ï¼ˆä¾‹å¦‚,ps ux | grep TaskTracker)
  • +
  • 在这些进程信æ¯ä¸­ï¼ŒæŸ¥æ‰¾å˜é‡-Dhadoop.log.dir的值。通常是hodé…置文件里hodring.temp-dir目录的一个å­ç›®å½• 。
  • +
  • 切æ¢åˆ°hadoop.log.dir目录以查看守护进程日志和用户日志。
  • +
+

HOD也æ供了一个机制,能让你在集群回收åŽå°†æ—¥å¿—收集存放到文件系统,或者一个在外部é…置的HDFS中。这样的è¯ï¼Œåœ¨ä½œä¸šå®Œæˆï¼ŒèŠ‚点回收åŽä½ è¿˜å¯ä»¥çœ‹è¿™äº›æ—¥å¿—。è¦åšåˆ°è¿™ç‚¹ï¼Œåƒä¸‹é¢ä¸€æ ·ä¸ºlog-destination-uri指定一个URI:

+ + +
log-destination-uri= hdfs://host123:45678/user/hod/logs或者
log-destination-uri= file://path/to/store/log/files
+

在上é¢æŒ‡å®šçš„的根目录中,HOD会创建路径user_name/torque_jobid,把作业涉åŠåˆ°çš„æ¯ä¸ªèŠ‚点上的日志文件gzip压缩,存放在里é¢ã€‚

+

注æ„è¦åœ¨HDFS上存储这些文件,你得将hodring.pkgs项é…置为和刚æ‰æ到的HDFS兼容的版本。å¦åˆ™ï¼ŒHOD会å°è¯•ä½¿ç”¨å®ƒä¾›åº”Hadoop集群时用到的Hadoop版本。

+
+
闲置集群的自动回收 +

HOD会自动回收在一段时间内没有è¿è¡ŒHadoop作业的集群。æ¯æ¬¡çš„HOD分é…会带有一个监控设施ä¸åœåœ°æ£€æŸ¥Hadoop作业的执行。如果侦测到在一定时间内没Hadoop作业在执行,它就回收这个集群,释放那些未被有效利用的节点。

+

注æ„:当集群被回收时,集群目录没有被自动清空。用户须通过一个正å¼çš„deallcocateæ“作清ç†å®ƒã€‚

+
+
指定é¢å¤–的作业属性 +

HODå…许用户为一个Torque作业指定一个时钟时间和一个å称(或者标题)。

+

时钟时间是对Torque作业有效时间的一个估计。这个时间过期åŽï¼ŒTorque将自动删除这个作业,释放其节点。指定这个时钟时间还能帮助作业调度程åºæ›´å¥½çš„安排作业,æ高对集群资æºçš„使用率。

+

指定时钟时间的语法如下:

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes -l time_in_seconds
+

Torque作业的å称或标题能给用户以å‹å¥½çš„作业标识。æ¯æ¬¡å±•ç¤ºTorque作业的属性的时候,这个字符串就会出现,包括qstat命令。

+

指定å称或标题的语法如下:

+ + + + +
$ hod allocate -d cluster_dir -n number_of_nodes -N name_of_job
+

注æ„:由于底层Torque资æºç®¡ç†å™¨çš„é™åˆ¶ï¼Œä¸ä»¥å­—æ¯å¼€å¤´æˆ–者包å«ç©ºæ ¼çš„å字将导致作业失败。失败信æ¯ä¼šè¡¨æ˜Žé—®é¢˜å­˜åœ¨äºŽæŒ‡å®šçš„作业å称中。

+
+
æ•èŽ·HOD在Torqueä¸­çš„é€€å‡ºç  +

HOD退出ç å‡ºçŽ°åœ¨Torqueçš„exit_status字段中。这有助于使用者和系统管ç†å‘˜åŒºåˆ†æˆåŠŸçš„HOD执行和失败的HOD执行。如果分é…æˆåŠŸä¸”所有Hadoop作业在所分é…的集群上正确的执行,退出ç ä¸º0。如果分é…失败或者部分hadoop作业在分é…集群上è¿è¡Œå¤±è´¥ï¼Œé€€å‡ºç éž0。下表列出了å¯èƒ½å‡ºçŽ°çš„退出ç ã€‚注æ„:åªæœ‰æ‰€ä½¿ç”¨çš„Hadoop版本是0.16或以上时,Hadoop作业状æ€æ‰å¯ä»¥è¢«æ•èŽ·ã€‚

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
退出ç å«ä¹‰
6 Ringmaster故障
7 DFS故障
8 Job tracker故障
10 集群死亡
12 集群已分é…
13 HDFS死亡
14 Mapred死亡
16 集群中所有的Map/Reduce作业失败。查看hadoop日志了解更多细节。
17 集群中部分的Map/Reduce作业失败。查看hadoop日志了解更多细节。
+
+
+ 命令行 +

HOD命令行的通用的语法如下:
+ hod <operation> [ARGS] [OPTIONS]
+ å…许的æ“作有‘allocate’,‘deallocate’,‘info’,‘list’,‘script’以åŠâ€˜help’。è¦èŽ·å–æŸç‰¹å®šæ“作的帮助你å¯ä»¥æ‰§è¡Œï¼šhod help <operation>。è¦æŸ¥çœ‹å¯èƒ½çš„æ“作你å¯ä»¥æ‰§è¡Œhod help options。

+

allocate
+ 用法:hod allocate -d cluster_dir -n number_of_nodes [OPTIONS]
+ 分é…一个指定节点数目的集群,把分é…ä¿¡æ¯å­˜æ”¾åœ¨cluster_dir方便åŽç»­hadoop命令使用。注æ„cluster_dir必须在è¿è¡Œè¯¥å‘½ä»¤å‰å·²ç»å­˜åœ¨ã€‚

+

list
+ 用法:hod list [OPTIONS]
+ 列举出用户分é…的所有集群。æ供的信æ¯åŒ…括集群对应的的Torque作业标识,存储分é…ä¿¡æ¯çš„集群目录,Map/Reduce守护进程是å¦å­˜æ´»ã€‚

+

info
+ 用法:hod info -d cluster_dir [OPTIONS]
+ 列举集群分é…ä¿¡æ¯å­˜æ”¾äºŽæŸæŒ‡å®šé›†ç¾¤ç›®å½•çš„集群信æ¯ã€‚

+

deallocate
+ 用法:hod deallocate -d cluster_dir [OPTIONS]
+ 回收集群分é…ä¿¡æ¯å­˜æ”¾äºŽæŸæŒ‡å®šé›†ç¾¤ç›®å½•çš„集群。

+

script
+ 用法:hod script -s script_file -d cluster_directory -n number_of_node [OPTIONS]
+ 用HODscriptæ“作执行一个hadoop脚本。在给定数目的节点上æä¾›Hadoop,在æ交的节点执行这个脚本,并在脚本执行结æŸåŽå›žæ”¶é›†ç¾¤ã€‚

+

help
+ 用法:hod help [operation | 'options']
+ 未指定å‚数时,hod help给出用法以åŠåŸºæœ¬é€‰é¡¹ï¼Œç­‰åŒäºŽhod --help (è§ä¸‹æ–‡ï¼‰ã€‚当指定å‚数‘options’时,显示hod的基本选项。当指定operation时,它会显示出该特定operation的用法和相应的æ述。例如,希望了解allocateæ“作,你å¯ä»¥æ‰§è¡Œhod help allocate

+

除上é¢çš„æ“作外,HOD还能接å—下列命令行选项。

+

--help
+ 打å°å‡ºç”¨æ³•å’ŒåŸºæœ¬é€‰é¡¹çš„帮助信æ¯ã€‚

+

--verbose-help
+ hodrc文件中所有的é…置项å‡å¯é€šè¿‡å‘½ä»¤è¡Œä¼ é€’,使用语法--section_name.option_name[=vlaue]。这ç§æ–¹å¼ä¸‹ï¼Œå‘½ä»¤è¡Œä¼ é€’çš„å‚数会覆盖hodrc中的é…置项。verbose-help命令会列出hodrc文件中全部å¯ç”¨é¡¹ã€‚这也是一个了解é…置选项å«ä¹‰çš„好方法。

+

下一部分有多数é‡è¦çš„hodé…置项的æ述。对于基本选项,你å¯ä»¥é€šè¿‡hod help options了解,对于所有的hodé…置中的å¯èƒ½é€‰é¡¹ï¼Œä½ å¯ä»¥å‚看hod --verbose-help的输出。了解所有选项的æ述,请å‚看é…置指å—。

+
+
HODé…置选项 +

如上所述,HODçš„é…置是通过系统管ç†å‘˜è®¾ç½®é…置文件完æˆã€‚这是一个INI风格的é…置文件,文件分æˆå¤šä¸ªæ®µï¼Œæ¯ä¸ªæ®µåŒ…å«ä¸€äº›é…置项。这些段分别和HOD的进程:client,ringmaster,hodring,mapreduce或hdfs相关。æ¯ä¸€ä¸ªé…置项有选项å和值构æˆã€‚

+

有两ç§æ–¹å¼å¯è®©ç”¨æˆ·è¦†ç›–默认é…置文件里的设定:

+
    +
  • 在æ¯æ¡å‘½ä»¤å‰ï¼Œç”¨æˆ·å¯ä»¥å‘HODæ供自己的é…置文件,使用-c选项。
  • +
  • 用户å¯ä»¥åœ¨å‘½ä»¤è¡ŒæŒ‡å®šHODçš„é…置选项覆盖正使用的é…置文件中æ供的值。
  • +
+

这一节介ç»ä¸€äº›æœ€å¸¸ç”¨çš„é…置项。为了指定方便,这些常用选项通常会有一个短选项å。所有其它选项å¯èƒ½ç”¨éšåŽä»‹ç»çš„长选项指定。

+

-c config_file
+ æä¾›è¦ä½¿ç”¨çš„é…置文件。å¯ä¸Žå…¶ä»–任何的HOD选项一起使用。此外,å¯å®šä¹‰HOD_CONF_DIR环境å˜é‡ä¸ºä¸€ä¸ªåŒ…å«hodrc文件的目录,é¿å…æ¯æ¡HOD命令都è¦æŒ‡å®šé…置文件。

+

-d cluster_dir
+ 大多数hodæ“作都è¦æ±‚这个选项。如此处æ述的,集群目录是在本地文件系统上的一个目录,hod将它分é…集群的相应Hadoopé…置产生在这个目录里,å³hadoop-site.xml。使用-d或者--hod.clusterdir将这个å‚数传递给hodæ“作,如果目录ä¸å­˜åœ¨ï¼ŒHOD会自动创建该目录。集群分é…好åŽï¼Œç”¨æˆ·å¯åœ¨è¿™ä¸ªé›†ç¾¤ä¸Šï¼Œé€šè¿‡æŒ‡å®šhadoop--config为集群目录æ¥æ‰§è¡ŒHadoop作业。

+

-n number_of_nodes
+ hod allocationæ“作和scriptæ“作è¦æ±‚这个选项。表示è¦åˆ†é…的节点数。

+

-s script-file
+ 脚本æ“作时需è¦ï¼Œç”¨äºŽæŒ‡å®šè¦æ‰§è¡Œçš„脚本文件。

+

-b 1|2|3|4
+ å¯ç”¨ç»™å®šçš„调试级别。能与其他HOD选项一起使用。级别4最为详尽。

+

-t hadoop_tarball
+ 从指定tar.gz文件æä¾›Hadoop分å‘。此选项值åªé€‚用于allocateæ“作。为获得更好的分å‘性能,强烈推è创建Hadoop tarballå‰åˆ é™¤å…¶ä¸­çš„æºä»£ç æˆ–文档。

+

-N job-name
+ 内部使用的资æºç®¡ç†ä½œä¸šå。比如,对于Torque作为资æºç®¡ç†å™¨çš„情况,会被解释æˆqsub -N选项,使用qstat命令时å¯ä»¥çœ‹åˆ°è¿™ä¸ªä½œä¸šå。

+

-l wall-clock-time
+ 用户希望在分é…的集群作业的时间总é‡ã€‚它被传递给HOD底层的资æºç®¡ç†å™¨ï¼Œç”¨äºŽæ›´æœ‰æ•ˆåœ°è°ƒåº¦å’Œåˆ©ç”¨é›†ç¾¤ã€‚注æ„对于Torque的情形,这个时间到期åŽï¼Œé›†ç¾¤ä¼šåœ¨è¢«è‡ªåŠ¨å›žæ”¶ã€‚

+

-j java-home
+ JAVA_HOME环境å˜é‡é‡ŒæŒ‡å®šçš„路径。在scriptæ“作中使用。HODå°†JAVA_HOME环境å˜é‡è®¾ç½®ä¸ºè¿™ä¸ªå€¼ï¼Œå¹¶åœ¨æ­¤çŽ¯å¢ƒä¸‹å¯åŠ¨ç”¨æˆ·è„šæœ¬ã€‚

+

-A account-string
+ 传递给åŽå°èµ„æºç®¡ç†å™¨çš„核计信æ¯ã€‚

+

-Q queue-name
+ 接å—作业æ交的åŽå°èµ„æºç®¡ç†å™¨ä¸­é˜Ÿåˆ—çš„å称。

+

-Mkey1=value1 -Mkey2=value2
+ 为供应的Map/Reduce守护进程(JobTracker以åŠTaskTracker)æä¾›é…ç½®å‚数。在集群节点上,会根æ®è¿™äº›å€¼äº§ç”Ÿä¸€ä¸ªhadoop-site.xml。
+ 注æ„:值中的下列字符:空格,逗å·ï¼Œç­‰å·ï¼Œåˆ†å·éœ€è¦ä½¿ç”¨â€˜\’转义, 且放置在引å·ä¸­ã€‚你也å¯ä»¥ä½¿ç”¨â€˜\’æ¥è½¬ä¹‰â€˜\’。

+

-Hkey1=value1 -Hkey2=value2
+ 为供应的HDFS守护进程(NameNode以åŠDataNode)æä¾›é…ç½®å‚数。在集群节点上,会根æ®è¿™äº›å€¼äº§ç”Ÿä¸€ä¸ªhadoop-site.xml。
+ 注æ„:值中的下列字符:空格,逗å·ï¼Œç­‰å·ï¼Œåˆ†å·éœ€è¦ä½¿ç”¨â€˜\’转义, 且放置在引å·ä¸­ã€‚你也å¯ä»¥ä½¿ç”¨â€˜\’æ¥è½¬ä¹‰â€˜\’。

+

-Ckey1=value1 -Ckey2=value2
+ 为æ交作业的客户端æä¾›é…ç½®å‚数。在æ交节点上,会根æ®è¿™äº›å€¼äº§ç”Ÿä¸€ä¸ªhadoop-site.xml。
+ 注æ„:å‚数值å¯ä»¥ä½¿ç”¨ä»¥ä¸‹ç¬¦å·ï¼šç©ºæ ¼ï¼Œé€—å·ï¼Œç­‰å·ï¼Œéœ€è¦â€˜\’åšè½¬ä¹‰ç¬¦çš„分å·ï¼Œä¸Šè¿°ç¬¦å·è¦ç”¨å¼•å·è¿›è¡Œåˆ†å‰²ã€‚你也å¯ä»¥ä½¿ç”¨â€˜\’转义‘\’。

+

--section-name.option-name=value
+ 这是用长格å¼æä¾›é…置选项的方法。比如,你å¯ä»¥--hod.script-wait-time=20

+
+
+
+ 故障排除 +

下节列出了一些用户使用HODæ—¶å¯èƒ½ç¢°åˆ°çš„多å‘错误的æ¡ä»¶ä»¥åŠè§£å†³é—®é¢˜çš„方法

+
分é…æ“作时<code>hod</code>挂起 +

å¯èƒ½åŽŸå› ï¼šHOD或Hadoop的一个组件å¯åŠ¨å¤±è´¥ã€‚è¿™ç§æƒ…况下,hod命令会在一段时间(通常是2-3分钟)åŽè¿”回,退出ç æ˜¯é”™è¯¯ä»£ç éƒ¨åˆ†å®šä¹‰çš„错误ç 7或8。å‚考该部分以获得更多细节。

+

å¯èƒ½åŽŸå› ï¼šä½¿ç”¨tarball模å¼ç”³è¯·äº†å¤§è§„模的集群。有时由于网络负载,或者是分é…节点上的负载,tarball分å‘过程å¯èƒ½ä¼šæ…¢çš„比较明显,需è¦å‡ åˆ†é’Ÿæ‰èƒ½å“应。等待命令完æˆã€‚还å¯ä»¥æ£€æŸ¥ä¸€ä¸‹tarball,看是å¦ä¸å«Hadoopæºç æˆ–文档。

+

å¯èƒ½åŽŸå› ï¼šTorque相关的问题。如果原因与Torque相关,hod命令5分钟内是ä¸ä¼šè¿”回的。在调试模å¼ä¸‹è¿è¡Œhod你会å‘现qstat命令被é‡å¤æ‰§è¡Œã€‚在å¦ä¸€ä¸ªshell中执行qstat命令你会å‘现作业处于Q(排队)状æ€ã€‚这通常说明Torque出现了问题。å¯èƒ½åŽŸå› æœ‰ä¸ªåˆ«èŠ‚点宕机,或者增加了新节点但Torqueä¸çŸ¥ã€‚通常,需è¦ç³»ç»Ÿç®¡ç†å‘˜å¸®åŠ©è§£å†³æ­¤é—®é¢˜ã€‚

+
+
回收æ“作时<code>hod</code>挂起 +

å¯èƒ½åŽŸå› ï¼šTorque相关的问题,通常是Torque server上的负载较大,或者是分é…的集群éžå¸¸å¤§ã€‚一般æ¥è¯´ï¼Œä½ å”¯ä¸€èƒ½åšçš„是等待命令执行完æˆã€‚

+
+
<code>hod</code>失败时的错误代ç å’Œé”™è¯¯ä¿¡æ¯ +

如果hod命令的退出ç ä¸æ˜¯0,å‚考下é¢çš„退出代ç è¡¨ç¡®å®šæ­¤æƒ…况å‘生的原因和相应的调试方法。

+

错误代ç 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
错误代ç å«ä¹‰å¯èƒ½åŽŸå› åŠè¡¥æ•‘方法
1 é…置错误 hodrc中的å‚数错误,或者其他与HODé…置相关的错误。此类情况下,错误信æ¯å·²ç»è¶³å¤Ÿå¸®ä½ å‘现和解决问题。
2 无效æ“作执行hod help查看有效的æ“作列表。
3 无效æ“作å‚数执行hod help operation查看特定æ“作的用法。
4 调度失败 1. 请求分é…了过多的资æºã€‚执行checknodes cluster_name查看是å¦æœ‰è¶³å¤Ÿå¤šçš„å¯ç”¨èŠ‚点。
+ 2. 请求的资æºè¶…出了资æºç®¡ç†å™¨çš„é™åˆ¶ã€‚
+ 3. Torqueé…置错误,Torqueå¯æ‰§è¡Œæ–‡ä»¶è·¯å¾„é…置错误,或者其它Torque相关问题。è”系系统管ç†å‘˜ã€‚
5 执行作业失败 1. Torque作业被外部删除。执行Torque qstat命令查看是å¦æœ‰ä½œä¸šå¤„于R(è¿è¡Œï¼‰çŠ¶æ€ã€‚如果没有,å°è¯•é‡æ–°è¿è¡ŒHOD。
+ 2. Torque的问题诸如æœåŠ¡å™¨æš‚时性宕机,或者无å“应。è”系系统管ç†å‘˜ã€‚
+ 3. 系统管ç†å‘˜å¯èƒ½é…置了å¸å·æ ¸å®žï¼Œå¹¶ä¸”一个éžæ³•çš„å¸å·è¢«æŒ‡å®šã€‚请è”系系统管ç†å‘˜ã€‚
6 Ringmasteræ•…éšœ HOD会打å°ä¿¡æ¯"Cluster could not be allocated because of the following errors on the ringmaster host <hostname>"。实际的错误信æ¯å¯èƒ½æŒ‡ç¤ºä¸‹åˆ—情形中的一ç§ï¼š
+ 1. è¿è¡Œringmaster的节点é…ç½®ä¸åˆæ³•ï¼Œé”™è¯¯ä¿¡æ¯ä¸­çš„hostname会指明具体的机器。
+ 2. ringmaster段的é…置无效,
+ 3. gridservice-mapred或者gridservice-hdfs段中pkgs项的é…置无效,
+ 4. 无效的hadoop tarball,或者tarball中conf目录下存在无效的é…置文件,
+ 5. Hadoop中的MapReduce与外部HDFS版本ä¸åŒ¹é…。
+ Torque qstat命令很å¯èƒ½ä¼šæ˜¾ç¤ºä¸€ä¸ªå‡ºäºŽC(Completed,已完æˆ)状æ€çš„作业。
+ ä½ å¯ä»¥ç™»å½•åˆ°HOD失败信æ¯ä¸­ç»™å‡ºçš„ringmaster主机,根æ®é”™è¯¯ä¿¡æ¯çš„æ示解决问题。如果错误信æ¯æ²¡æœ‰ç»™å‡ºå®Œæ•´çš„ä¿¡æ¯ï¼Œringmaster日志也å¯èƒ½å¸®åŠ©æ‰¾åˆ°é—®é¢˜çš„æ ¹æºã€‚å‚考下é¢å®šä½Ringmaster日志一节了解更多信æ¯ã€‚
7 DFSæ•…éšœ 当HOD由于DFS故障(或者Job tracker失败,错误ç 8,下文有介ç»ï¼‰åˆ†é…失败时,它会打å°é”™è¯¯ä¿¡æ¯ "Hodring at <hostname> failed with following errors:",并给出真正的错误信æ¯ï¼Œè¿™ä¸ªä¿¡æ¯å¯èƒ½è¡¨æ˜Žä¸‹åˆ—情形中的一ç§ï¼š
+ 1. å¯åŠ¨Hadoop集群时出现问题。通常错误信æ¯ä¼šè¡¨æ˜Žä¹‹å‰æ到的主机出现错误的真正原因。你也è¦æ£€æŸ¥HODé…置中文件中Hadoop相关的é…置。按上é¢æ”¶é›†å’ŒæŸ¥çœ‹Hadoop日志一节中介ç»çš„方法查看Hadoop的日志。
+ 2. è¿è¡Œhodring的节点上的é…置无效,错误信æ¯ä¸­çš„hostname会指明机器
+ 3. hodrc中hodring段的é…置无效。ssh到错误信æ¯ä¸­æ到的节点,在hdring日志中grepERROR或CRITICAL。å‚考下é¢å®šä½Hodring日志部分获å–更多信æ¯ã€‚
+ 4. 指定了无效的tarball,å¯èƒ½æœªæ­£ç¡®æ‰“包。
+ 5. 无法与外部é…置的HDFS通信。
+ 当DFS或Job tracker出现故障时,你å¯ä»¥ç™»å½•åˆ°HOD失败信æ¯ä¸­æ到的主机上,进行debug。解决问题的时候,你也应通过查看ringmaster日志中的其它日志信æ¯ï¼Œæ¥æ£€æŸ¥å…¶ä»–机器是å¦åœ¨å¯åŠ¨jobtracker/namenode时也出现了问题,而ä¸åªæ˜¯æ£€æŸ¥é”™è¯¯ä¿¡æ¯ä¸­æ到的主机。其他机器也å¯èƒ½å‘生问题是因为HOD会按照é…置项ringmaster.max-master-failures的设置在多个机器上连续å°è¯•å’Œå¯åŠ¨hadoop守护进程。更多关于ringmaster日志的信æ¯è¯·å‚考下文定ä½Ringmaster日志。 +
8 Job tracker故障与DFS故障情形中的原因类似。
10 集群死亡1. 集群因为较长时间空闲被自动回收。
+ 2. 集群因系统管ç†å‘˜æˆ–者用户指定的时钟时间到期被自动回收。
+ 3. 无法与æˆåŠŸåˆ†é…çš„JobTracker以åŠHDFSçš„NameNode通信。回收集群,é‡æ–°åˆ†é…。
12 集群已分é…指定的集群目录是已被用于先å‰çš„分é…æ“作,且尚未回收。指定å¦å¤–一个目录,或者先回收先å‰åˆ†é…的。
13 HDFS死亡无法与HDFSçš„NameNode通信。HDFSçš„NameNodeåœæŽ‰äº†ã€‚
14 Mapred死亡 1. 集群因为长时间闲置被自动回收。
+ 2. 集群因系统管ç†å‘˜æˆ–用户指定的时钟时间到期被自动回收。
+ 3. 无法与Map/Reduce的JobTracker通信。JobTracker节点宕机。
+
15 集群未分é…一个需è¦å·²åˆ†é…集群的æ“作被指以一个没有状æ€ä¿¡æ¯çš„集群目录。
ä»»æ„éž0退出代ç HOD脚本错误如果使用了hod的脚本选项,很å¯èƒ½è¿™ä¸ªé€€å‡ºä»£ç æ˜¯è„šæœ¬çš„退出å—。ä¸å¹¸çš„是,这å¯èƒ½ä¼šä¸Žhod自己的退出ç å†²çªã€‚为帮助用户区分两者,如果脚本返回了一个退出ç ï¼Œhod将此退出ç å†™åˆ°äº†é›†ç¾¤ç›®å½•ä¸‹çš„script.exitcode文件。你å¯ä»¥cat这个文件以确定脚本的退出ç ã€‚如果文件ä¸å­˜åœ¨ï¼Œåˆ™é€€å‡ºä»£ç æ˜¯hod命令的退出ç ã€‚
+
+ +
Hadoop DFSClient警告NotReplicatedYetExceptionä¿¡æ¯ +

有时,当你申请到一个HOD集群åŽé©¬ä¸Šå°è¯•ä¸Šä¼ æ–‡ä»¶åˆ°HDFS时,DFSClient会警告NotReplicatedYetExceptionã€‚é€šå¸¸ä¼šæœ‰ä¸€ä¸ªè¿™æ ·çš„ä¿¡æ¯ -

WARN +hdfs.DFSClient: NotReplicatedYetException sleeping <filename> retries +left 3
08/01/25 16:31:40 INFO hdfs.DFSClient: +org.apache.hadoop.ipc.RemoteException: java.io.IOException: File +<filename> could only be replicated to 0 nodes, instead of +1

当你å‘一个DataNodes正在和NameNodeè”络的集群上传文件的时候,这ç§çŽ°è±¡å°±ä¼šå‘生。在上传新文件到HDFS之å‰å¤šç­‰å¾…一段时间就å¯ä»¥è§£å†³è¿™ä¸ªé—®é¢˜ï¼Œå› ä¸ºè¿™ä½¿å¾—足够多的DataNodeå¯åŠ¨å¹¶ä¸”è”络上了NameNode。

+
+ + +
æˆåŠŸåˆ†é…的集群上无法è¿è¡ŒHadoop作业 +

这一情景通常å‘生在这ç§æƒ…形:一个集群已ç»åˆ†é…,并且一段时间内处于ä¸æ´»è·ƒçŠ¶æ€ï¼Œä¹‹åŽhadoop作业试图在这个集群上è¿è¡Œã€‚Hadoop作业会失败,产生如下异常信æ¯ï¼š

+
08/01/25 16:31:40 INFO ipc.Client: Retrying connect to server: foo.bar.com/1.1.1.1:53567. Already tried 1 time(s).
+

å¯èƒ½åŽŸå› ï¼šç›¸å½“长的时间内无hadoop作业è¿è¡Œï¼Œé›†ç¾¤ä¼šå¦‚闲置集群的自动回收一节介ç»çš„那样被自动回收。回收该集群,然åŽé‡æ–°åˆ†é…。

+

å¯èƒ½åŽŸå› ï¼šä»Žåˆ†é…开始算起,Torque管ç†å‘˜æŒ‡å®šçš„或指定é¢å¤–的作业属性一节中定义的-l选项指定的时间上é™è¿‡æœŸã€‚è¿™ç§æƒ…况下集群å¯èƒ½å·²è¢«é‡Šæ”¾ã€‚回收集群,然åŽé‡æ–°åˆ†é…。

+

å¯èƒ½åŽŸå› ï¼šæ交作业使用的hadoop版本和供应集群的Hadoop版本(通常通过tarball选项)ä¸åŒ¹é…。确ä¿ä½¿ç”¨çš„兼容的版本。

+

å¯èƒ½åŽŸå› ï¼š æ交jobçš„hadoop客户端与æ供的hadoop(通常通过tarball选项)版本ä¸å…¼å®¹ã€‚ ç¡®ä¿æ‰€ä½¿ç”¨hadoop软件版本兼容。

+

å¯èƒ½åŽŸå› ï¼š 你使用了-M or -H中的一个指定Hadoopé…置,其中有未正确转义的字符比如空格或逗å·ã€‚å‚考HODé…置选项一节以了解如何正确指定这些选项。

+
+
我的Hadoop作业被中止了 +

å¯èƒ½åŽŸå› ï¼šä»Žåˆ†é…开始算起,Torque管ç†å‘˜æŒ‡å®šçš„或指定é¢å¤–的作业属性一节中定义的-l选项指定的时间上é™è¿‡æœŸã€‚è¿™ç§æƒ…况下集群å¯èƒ½å·²è¢«é‡Šæ”¾ã€‚回收集群,然åŽé‡æ–°åˆ†é…,这次è¦åˆ¶å®šä¸€ä¸ªå¤§ç‚¹å„¿çš„时钟时间。

+

å¯èƒ½åŽŸå› ï¼š JobTracker节点出现问题。å‚考收集和查看Hadoop日志一节以获å–更多信æ¯ã€‚

+
+
Hadoop作业失败并返回消æ¯ï¼šâ€˜Job tracker still initializing’ +

å¯èƒ½åŽŸå› ï¼šhadoop作业是作为HOD脚本的一部分è¿è¡Œçš„,它在JobTracker完全就绪å‰å¼€å§‹äº†æ‰§è¡Œã€‚分é…集群时为é…置选--hod.script-wait-time设定一个大点儿的值。通常å–120是å¯ä»¥å·¥ä½œçš„,尽管通常没必è¦è¿™ä¹ˆå¤§ã€‚

+
+
Torque的退出代ç æ²¡æœ‰åŒ…å«HODçš„ +

å¯èƒ½åŽŸå› ï¼šæ­¤åŠŸèƒ½éœ€è¦Hadoop 0.16。所用的Hadoop版本ä¸æ»¡è¶³è¿™ä¸ªæ¡ä»¶ã€‚请使用åˆé€‚çš„Hadoop版本。

+

å¯èƒ½åŽŸå› ï¼šæ²¡æœ‰ä½¿ç”¨hod命令回收集群;例如直接使用qdel。当使用这ç§æ–¹å¼å›žæ”¶é›†ç¾¤æ—¶ï¼ŒHOD进程被信å·ä¸­æ­¢ã€‚这会导致退出ç æ˜¯åŸºäºŽsignal number的,而ä¸æ˜¯ç¨‹åºçš„退出ç ã€‚

+
+
Hadoop日志未被上传到DFS +

å¯èƒ½åŽŸå› ï¼šä¸Šä¼ æ—¥å¿—的使用的hadoop与外部的HDFS版本ä¸å…¼å®¹ã€‚ç¡®ä¿hodring.pkgs选项指定了正确的版本。

+
+
定ä½Ringmaster日志 +

éµå¾ªä»¥ä¸‹æ­¥éª¤å®šä½ringmaster日志:

+
    +
  • 用-b选项在调试模å¼æ‰§è¡Œhod。这会打å°å‡ºå½“å‰è¿è¡Œçš„Torque作业的标识。
  • +
  • 执行qstat -f torque_job_id,在输出中查找exec_hostå‚数的值。列表中的第一个主机就是ringmaster节点。
  • +
  • 登陆该节点。
  • +
  • ringmaster日志的ä½ç½®ç”±hodrc中的ringmaster.log-dir项指定。日志文件的å字会是username.torque_job_id/ringmaster-main.log。
  • +
  • 如果你没有获å–到足够的信æ¯ï¼Œä½ å¯ä»¥å°†ringmaster的调试级别设为4。这å¯é€šè¿‡å‘hod命令行传递--ringmaster.debug 4åšåˆ°ã€‚
  • +
+
+
定ä½Hodring日志 +

éµå¾ªä»¥ä¸‹æ­¥éª¤å®šä½hodring日志:

+
    +
  • 用-b选项在调试模å¼ä¸‹è¿è¡Œhod。这将打å°å½“å‰è¿è¡Œçš„Torque作业的标识。
  • +
  • 执行qstat -f torque_job_id,查看输出中exec_hostå‚数的值。列表中的的所有节点上都有一个hodring。
  • +
  • 登陆到任何一个节点。
  • +
  • hodring日志的ä½ç½®ç”±hodrc中的hodring.log-dir项指定。日志文件的å字会是username.torque_job_id/hodring-main.log。
  • +
  • 如果你没有获得足够的信æ¯ï¼Œä½ æˆ–许想将hodring的调试等级更改为4。这å¯ä»¥å‘hod命令行传递--hodring.debug 4 æ¥åšåˆ°ã€‚
  • +
+
+
+ +
diff --git a/src/docs/cn/src/documentation/content/xdocs/index.xml b/src/docs/cn/src/documentation/content/xdocs/index.xml new file mode 100644 index 00000000000..de63185b52f --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/index.xml @@ -0,0 +1,46 @@ + + + + + + + +
+ Hadoop文档 +
+ + +

+ 下é¢çš„文档是一些概念介ç»å’Œæ“作教程,å¯å¸®åŠ©ä½ å¼€å§‹ä½¿ç”¨Hadoop。如果é‡åˆ°äº†é—®é¢˜ï¼Œä½ å¯ä»¥å‘邮件列表求助或者æµè§ˆä¸€ä¸‹å­˜æ¡£é‚®ä»¶ã€‚ +

+ +

+

+ + + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/mapred_tutorial.xml b/src/docs/cn/src/documentation/content/xdocs/mapred_tutorial.xml new file mode 100644 index 00000000000..d842f4d93a8 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/mapred_tutorial.xml @@ -0,0 +1,2466 @@ + + + + + + +
+ Hadoop Map/Reduce教程 +
+ + + +
+ 目的 + +

这篇教程从用户的角度出å‘,全é¢åœ°ä»‹ç»äº†Hadoop Map/Reduce框架的å„个方é¢ã€‚

+
+ +
+ 先决æ¡ä»¶ + +

请先确认Hadoop被正确安装ã€é…置和正常è¿è¡Œä¸­ã€‚更多信æ¯è§ï¼š

+ +
+ +
+ 概述 + +

Hadoop Map/Reduce是一个使用简易的软件框架,基于它写出æ¥çš„应用程åºèƒ½å¤Ÿè¿è¡Œåœ¨ç”±ä¸Šåƒä¸ªå•†ç”¨æœºå™¨ç»„æˆçš„大型集群上,并以一ç§å¯é å®¹é”™çš„æ–¹å¼å¹¶è¡Œå¤„ç†ä¸ŠT级别的数æ®é›†ã€‚

+ +

一个Map/Reduce 作业(job) 通常会把输入的数æ®é›†åˆ‡åˆ†ä¸ºè‹¥å¹²ç‹¬ç«‹çš„æ•°æ®å—,由 + map任务(task)以完全并行的方å¼å¤„ç†å®ƒä»¬ã€‚框架会对map的输出先进行排åºï¼Œ + 然åŽæŠŠç»“果输入给reduce任务。通常作业的输入和输出都会被存储在文件系统中。 + 整个框架负责任务的调度和监控,以åŠé‡æ–°æ‰§è¡Œå·²ç»å¤±è´¥çš„任务。

+ +

通常,Map/Reduce框架和分布å¼æ–‡ä»¶ç³»ç»Ÿæ˜¯è¿è¡Œåœ¨ä¸€ç»„相åŒçš„节点上的,也就是说,计算节点和存储节点通常在一起。这ç§é…ç½®å…许框架在那些已ç»å­˜å¥½æ•°æ®çš„节点上高效地调度任务,这å¯ä»¥ä½¿æ•´ä¸ªé›†ç¾¤çš„网络带宽被éžå¸¸é«˜æ•ˆåœ°åˆ©ç”¨ã€‚

+ +

Map/Reduce框架由一个å•ç‹¬çš„master JobTracker å’Œæ¯ä¸ªé›†ç¾¤èŠ‚点一个slave TaskTrackerå…±åŒç»„æˆã€‚master负责调度构æˆä¸€ä¸ªä½œä¸šçš„所有任务,这些任务分布在ä¸åŒçš„slave上,master监控它们的执行,é‡æ–°æ‰§è¡Œå·²ç»å¤±è´¥çš„任务。而slave仅负责执行由master指派的任务。

+ +

应用程åºè‡³å°‘应该指明输入/输出的ä½ç½®ï¼ˆè·¯å¾„),并通过实现åˆé€‚的接å£æˆ–抽象类æä¾›mapå’Œreduce函数。å†åŠ ä¸Šå…¶ä»–作业的å‚数,就构æˆäº†ä½œä¸šé…置(job configuration)。然åŽï¼ŒHadoopçš„ job clientæ交作业(jar包/å¯æ‰§è¡Œç¨‹åºç­‰ï¼‰å’Œé…置信æ¯ç»™JobTracker,åŽè€…负责分å‘这些软件和é…置信æ¯ç»™slaveã€è°ƒåº¦ä»»åŠ¡å¹¶ç›‘控它们的执行,åŒæ—¶æ供状æ€å’Œè¯Šæ–­ä¿¡æ¯ç»™job-client。

+ +

虽然Hadoop框架是用JavaTM实现的,但Map/Reduce应用程åºåˆ™ä¸ä¸€å®šè¦ç”¨ + Javaæ¥å†™ 。

+
    +
  • + + Hadoop Streaming是一ç§è¿è¡Œä½œä¸šçš„实用工具,它å…许用户创建和è¿è¡Œä»»ä½•å¯æ‰§è¡Œç¨‹åº + (例如:Shell工具)æ¥åšä¸ºmapperå’Œreducer。 +
  • +
  • + + Hadoop Pipes是一个与SWIG兼容的C++ API + (没有基于JNITM技术),它也å¯ç”¨äºŽå®žçŽ°Map/Reduce应用程åºã€‚ +
  • +
+
+ +
+ 输入与输出 + +

Map/Reduce框架è¿è½¬åœ¨<key, value> 键值对上,也就是说, + 框架把作业的输入看为是一组<key, value> 键值对,åŒæ ·ä¹Ÿäº§å‡ºä¸€ç»„ + <key, value> 键值对åšä¸ºä½œä¸šçš„输出,这两组键值对的类型å¯èƒ½ä¸åŒã€‚

+ +

框架需è¦å¯¹keyå’Œvalueçš„ç±»(classes)进行åºåˆ—化æ“作, + 因此,这些类需è¦å®žçŽ° Writable接å£ã€‚ + å¦å¤–,为了方便框架执行排åºæ“作,key类必须实现 + + WritableComparable接å£ã€‚ +

+ +

一个Map/Reduce 作业的输入和输出类型如下所示:

+

+ (input) <k1, v1> + -> + map + -> + <k2, v2> + -> + combine + -> + <k2, v2> + -> + reduce + -> + <k3, v3> (output) +

+
+ +
+ 例å­ï¼šWordCount v1.0 + +

在深入细节之å‰ï¼Œè®©æˆ‘们先看一个Map/Reduce的应用示例,以便对它们的工作方å¼æœ‰ä¸€ä¸ªåˆæ­¥çš„认识。

+

WordCount是一个简å•çš„应用,它å¯ä»¥è®¡ç®—出指定数æ®é›†ä¸­æ¯ä¸€ä¸ªå•è¯å‡ºçŽ°çš„次数。

+

这个应用适用于 + å•æœºæ¨¡å¼ï¼Œ + 伪分布å¼æ¨¡å¼ 或 + 完全分布å¼æ¨¡å¼ + 三ç§Hadoop安装方å¼ã€‚

+ +
+ æºä»£ç  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
WordCount.java
1. + package org.myorg; +
2.
3. + import java.io.IOException; +
4. + import java.util.*; +
5.
6. + import org.apache.hadoop.fs.Path; +
7. + import org.apache.hadoop.conf.*; +
8. + import org.apache.hadoop.io.*; +
9. + import org.apache.hadoop.mapred.*; +
10. + import org.apache.hadoop.util.*; +
11.
12. + public class WordCount { +
13.
14. +    + + public static class Map extends MapReduceBase + implements Mapper<LongWritable, Text, Text, IntWritable> { + +
15. +      + + private final static IntWritable one = new IntWritable(1); + +
16. +      + private Text word = new Text(); +
17.
18. +      + + public void map(LongWritable key, Text value, + OutputCollector<Text, IntWritable> output, + Reporter reporter) throws IOException { + +
19. +        + String line = value.toString(); +
20. +        + StringTokenizer tokenizer = new StringTokenizer(line); +
21. +        + while (tokenizer.hasMoreTokens()) { +
22. +          + word.set(tokenizer.nextToken()); +
23. +          + output.collect(word, one); +
24. +        + } +
25. +      + } +
26. +    + } +
27.
28. +    + + public static class Reduce extends MapReduceBase implements + Reducer<Text, IntWritable, Text, IntWritable> { + +
29. +      + + public void reduce(Text key, Iterator<IntWritable> values, + OutputCollector<Text, IntWritable> output, + Reporter reporter) throws IOException { + +
30. +        + int sum = 0; +
31. +        + while (values.hasNext()) { +
32. +          + sum += values.next().get(); +
33. +        + } +
34. +        + output.collect(key, new IntWritable(sum)); +
35. +      + } +
36. +    + } +
37.
38. +    + + public static void main(String[] args) throws Exception { + +
39. +      + + JobConf conf = new JobConf(WordCount.class); + +
40. +      + conf.setJobName("wordcount"); +
41.
42. +      + conf.setOutputKeyClass(Text.class); +
43. +      + conf.setOutputValueClass(IntWritable.class); +
44.
45. +      + conf.setMapperClass(Map.class); +
46. +      + conf.setCombinerClass(Reduce.class); +
47. +      + conf.setReducerClass(Reduce.class); +
48.
49. +      + conf.setInputFormat(TextInputFormat.class); +
50. +      + conf.setOutputFormat(TextOutputFormat.class); +
51.
52. +      + FileInputFormat.setInputPaths(conf, new Path(args[0])); +
53. +      + FileOutputFormat.setOutputPath(conf, new Path(args[1])); +
54.
55. +      + JobClient.runJob(conf); +
57. +    + } +
58. + } +
59.
+
+ +
+ 用法 + +

å‡è®¾çŽ¯å¢ƒå˜é‡HADOOP_HOME对应安装时的根目录,HADOOP_VERSION对应Hadoop的当å‰å®‰è£…版本,编译WordCount.javaæ¥åˆ›å»ºjar包,å¯å¦‚下æ“作:

+

+ $ mkdir wordcount_classes
+ + $ javac -classpath ${HADOOP_HOME}/hadoop-${HADOOP_VERSION}-core.jar + -d wordcount_classes WordCount.java +
+ $ jar -cvf /usr/joe/wordcount.jar -C wordcount_classes/ . +

+ +

å‡è®¾ï¼š

+
    +
  • + /usr/joe/wordcount/input - 是HDFS中的输入路径 +
  • +
  • + /usr/joe/wordcount/output - 是HDFS中的输出路径 +
  • +
+ +

用示例文本文件åšä¸ºè¾“入:

+

+ $ bin/hadoop dfs -ls /usr/joe/wordcount/input/
+ /usr/joe/wordcount/input/file01
+ /usr/joe/wordcount/input/file02
+
+ $ bin/hadoop dfs -cat /usr/joe/wordcount/input/file01
+ Hello World Bye World
+
+ $ bin/hadoop dfs -cat /usr/joe/wordcount/input/file02
+ Hello Hadoop Goodbye Hadoop +

+ +

è¿è¡Œåº”用程åºï¼š

+

+ + $ bin/hadoop jar /usr/joe/wordcount.jar org.myorg.WordCount + /usr/joe/wordcount/input /usr/joe/wordcount/output + +

+ +

输出是:

+

+ + $ bin/hadoop dfs -cat /usr/joe/wordcount/output/part-00000 + +
+ Bye 1
+ Goodbye 1
+ Hadoop 2
+ Hello 2
+ World 2
+

+

应用程åºèƒ½å¤Ÿä½¿ç”¨-files选项æ¥æŒ‡å®šä¸€ä¸ªç”±é€—å·åˆ†éš”的路径列表,这些路径是task的当å‰å·¥ä½œç›®å½•ã€‚使用选项-libjarså¯ä»¥å‘mapå’Œreduceçš„classpath中添加jar包。使用-archives选项程åºå¯ä»¥ä¼ é€’档案文件åšä¸ºå‚数,这些档案文件会被解压并且在task的当å‰å·¥ä½œç›®å½•ä¸‹ä¼šåˆ›å»ºä¸€ä¸ªæŒ‡å‘解压生æˆçš„目录的符å·é“¾æŽ¥ï¼ˆä»¥åŽ‹ç¼©åŒ…çš„å字命å)。 + 有关命令行选项的更多细节请å‚考 + Commands manual。

+ +

使用-libjarså’Œ-filesè¿è¡Œwordcount例å­ï¼š
+ hadoop jar hadoop-examples.jar wordcount -files cachefile.txt + -libjars mylib.jar input output +

+ +
+ +
+ 解释 + +

WordCount应用程åºéžå¸¸ç›´æˆªäº†å½“。

+ +

Mapper(14-26è¡Œ)中的map方法(18-25è¡Œ)通过指定的 + TextInputFormat(49è¡Œ)一次处ç†ä¸€è¡Œã€‚然åŽï¼Œå®ƒé€šè¿‡StringTokenizer + 以空格为分隔符将一行切分为若干tokens,之åŽï¼Œè¾“出< <word>, 1> + å½¢å¼çš„键值对。

+ +

+ 对于示例中的第一个输入,map输出是:
+ < Hello, 1>
+ < World, 1>
+ < Bye, 1>
+ < World, 1>
+

+ +

+ 第二个输入,map输出是:
+ < Hello, 1>
+ < Hadoop, 1>
+ < Goodbye, 1>
+ < Hadoop, 1>
+

+ +

关于组æˆä¸€ä¸ªæŒ‡å®šä½œä¸šçš„map数目的确定,以åŠå¦‚何以更精细的方å¼åŽ»æŽ§åˆ¶è¿™äº›map,我们将在教程的åŽç»­éƒ¨åˆ†å­¦ä¹ åˆ°æ›´å¤šçš„内容。

+ +

WordCount还指定了一个combiner (46è¡Œ)。因此,æ¯æ¬¡mapè¿è¡Œä¹‹åŽï¼Œä¼šå¯¹è¾“出按照key进行排åºï¼Œç„¶åŽæŠŠè¾“出传递给本地的combiner(按照作业的é…置与Reducer一样),进行本地èšåˆã€‚

+ +

+ 第一个map的输出是:
+ < Bye, 1>
+ < Hello, 1>
+ < World, 2>
+

+ +

+ 第二个map的输出是:
+ < Goodbye, 1>
+ < Hadoop, 2>
+ < Hello, 1>
+

+ +

Reducer(28-36è¡Œ)中的reduce方法(29-35è¡Œ) + 仅是将æ¯ä¸ªkey(本例中就是å•è¯ï¼‰å‡ºçŽ°çš„次数求和。 +

+ +

+ 因此这个作业的输出就是:
+ < Bye, 1>
+ < Goodbye, 1>
+ < Hadoop, 2>
+ < Hello, 2>
+ < World, 2>
+

+ +

代ç ä¸­çš„run方法中指定了作业的几个方é¢ï¼Œ + 例如:通过命令行传递过æ¥çš„输入/输出路径ã€key/value的类型ã€è¾“å…¥/输出的格å¼ç­‰ç­‰JobConf中的é…置信æ¯ã€‚éšåŽç¨‹åºè°ƒç”¨äº†JobClient.runJob(55è¡Œ)æ¥æ交作业并且监控它的执行。

+ +

我们将在本教程的åŽç»­éƒ¨åˆ†å­¦ä¹ æ›´å¤šçš„关于JobConf, JobClient, + Tool和其他接å£åŠç±»(class)。

+
+
+ +
+ Map/Reduce - ç”¨æˆ·ç•Œé¢ + +

这部分文档为用户将会é¢ä¸´çš„Map/Reduce框架中的å„个环节æ供了适当的细节。这应该会帮助用户更细粒度地去实现ã€é…置和调优作业。然而,请注æ„æ¯ä¸ªç±»/接å£çš„javadoc文档æ供最全é¢çš„文档;本文åªæ˜¯æƒ³èµ·åˆ°æŒ‡å—的作用。 +

+ +

我们会先看看Mapperå’ŒReducer接å£ã€‚应用程åºé€šå¸¸ä¼šé€šè¿‡æä¾›mapå’Œreduce方法æ¥å®žçŽ°å®ƒä»¬ã€‚ +

+ +

然åŽï¼Œæˆ‘们会讨论其他的核心接å£ï¼Œå…¶ä¸­åŒ…括: + JobConf,JobClient,Partitioner, + OutputCollector,Reporter, + InputFormat,OutputFormat等等。

+ +

最åŽï¼Œæˆ‘们将通过讨论框架中一些有用的功能点(例如:DistributedCache, + IsolationRunner等等)æ¥æ”¶å°¾ã€‚

+ +
+ 核心功能æè¿° + +

应用程åºé€šå¸¸ä¼šé€šè¿‡æä¾›mapå’Œreduceæ¥å®žçŽ° + Mapperå’ŒReducer接å£ï¼Œå®ƒä»¬ç»„æˆä½œä¸šçš„核心。

+ +
+ Mapper + +

+ Mapper将输入键值对(key/value pair)映射到一组中间格å¼çš„键值对集åˆã€‚

+ +

Map是一类将输入记录集转æ¢ä¸ºä¸­é—´æ ¼å¼è®°å½•é›†çš„独立任务。 + è¿™ç§è½¬æ¢çš„中间格å¼è®°å½•é›†ä¸éœ€è¦ä¸Žè¾“入记录集的类型一致。一个给定的输入键值对å¯ä»¥æ˜ å°„æˆ0个或多个输出键值对。

+ +

Hadoop Map/Reduce框架为æ¯ä¸€ä¸ªInputSplit产生一个map任务,而æ¯ä¸ªInputSplit是由该作业的InputFormat产生的。

+ +

概括地说,对Mapper的实现者需è¦é‡å†™ + + JobConfigurable.configure(JobConf)方法,这个方法需è¦ä¼ é€’一个JobConfå‚数,目的是完æˆMapperçš„åˆå§‹åŒ–工作。然åŽï¼Œæ¡†æž¶ä¸ºè¿™ä¸ªä»»åŠ¡çš„InputSplit中æ¯ä¸ªé”®å€¼å¯¹è°ƒç”¨ä¸€æ¬¡ + + map(WritableComparable, Writable, OutputCollector, Reporter)æ“作。应用程åºå¯ä»¥é€šè¿‡é‡å†™Closeable.close()方法æ¥æ‰§è¡Œç›¸åº”的清ç†å·¥ä½œã€‚

+ +

输出键值对ä¸éœ€è¦ä¸Žè¾“入键值对的类型一致。一个给定的输入键值对å¯ä»¥æ˜ å°„æˆ0个或多个输出键值对。通过调用 + OutputCollector.collect(WritableComparable,Writable)å¯ä»¥æ”¶é›†è¾“出的键值对。

+ +

应用程åºå¯ä»¥ä½¿ç”¨Reporter报告进度,设定应用级别的状æ€æ¶ˆæ¯ï¼Œæ›´æ–°Counters(计数器),或者仅是表明自己è¿è¡Œæ­£å¸¸ã€‚

+ +

框架éšåŽä¼šæŠŠä¸Žä¸€ä¸ªç‰¹å®škeyå…³è”的所有中间过程的值(value)分æˆç»„,然åŽæŠŠå®ƒä»¬ä¼ ç»™Reducer以产出最终的结果。用户å¯ä»¥é€šè¿‡ + + JobConf.setOutputKeyComparatorClass(Class)æ¥æŒ‡å®šå…·ä½“负责分组的 + Comparator。

+ +

Mapper的输出被排åºåŽï¼Œå°±è¢«åˆ’分给æ¯ä¸ªReducer。分å—的总数目和一个作业的reduce任务的数目是一样的。用户å¯ä»¥é€šè¿‡å®žçŽ°è‡ªå®šä¹‰çš„ Partitioneræ¥æŽ§åˆ¶å“ªä¸ªkey被分é…给哪个 Reducer。

+ +

用户å¯é€‰æ‹©é€šè¿‡ + JobConf.setCombinerClass(Class)指定一个combiner,它负责对中间过程的输出进行本地的èšé›†ï¼Œè¿™ä¼šæœ‰åŠ©äºŽé™ä½Žä»ŽMapper到 + Reduceræ•°æ®ä¼ è¾“é‡ã€‚ +

+

这些被排好åºçš„中间过程的输出结果ä¿å­˜çš„æ ¼å¼æ˜¯(key-len, key, value-len, value),应用程åºå¯ä»¥é€šè¿‡JobConf控制对这些中间结果是å¦è¿›è¡ŒåŽ‹ç¼©ä»¥åŠæ€Žä¹ˆåŽ‹ç¼©ï¼Œä½¿ç”¨å“ªç§ + CompressionCodec。 +

+ +
+ 需è¦å¤šå°‘个Map? + +

Map的数目通常是由输入数æ®çš„大å°å†³å®šçš„,一般就是所有输入文件的总å—(block)数。

+ +

Map正常的并行规模大致是æ¯ä¸ªèŠ‚点(node)大约10到100个map,对于CPU + 消耗较å°çš„map任务å¯ä»¥è®¾åˆ°300个左å³ã€‚由于æ¯ä¸ªä»»åŠ¡åˆå§‹åŒ–需è¦ä¸€å®šçš„时间,因此,比较åˆç†çš„情况是map执行的时间至少超过1分钟。

+ +

这样,如果你输入10TBçš„æ•°æ®ï¼Œæ¯ä¸ªå—(block)的大å°æ˜¯128MB,你将需è¦å¤§çº¦82,000个mapæ¥å®Œæˆä»»åŠ¡ï¼Œé™¤éžä½¿ç”¨ + + setNumMapTasks(int)(注æ„:这里仅仅是对框架进行了一个æ示(hint),实际决定因素è§è¿™é‡Œï¼‰å°†è¿™ä¸ªæ•°å€¼è®¾ç½®å¾—更高。

+
+
+ +
+ Reducer + +

+ Reducer将与一个keyå…³è”的一组中间数值集归约(reduce)为一个更å°çš„数值集。

+ +

用户å¯ä»¥é€šè¿‡ + JobConf.setNumReduceTasks(int)设定一个作业中reduce任务的数目。

+ +

概括地说,对Reducer的实现者需è¦é‡å†™ + + JobConfigurable.configure(JobConf)方法,这个方法需è¦ä¼ é€’一个JobConfå‚数,目的是完æˆReducerçš„åˆå§‹åŒ–工作。然åŽï¼Œæ¡†æž¶ä¸ºæˆç»„的输入数æ®ä¸­çš„æ¯ä¸ª<key, (list of values)>对调用一次 + + reduce(WritableComparable, Iterator, OutputCollector, Reporter)方法。之åŽï¼Œåº”用程åºå¯ä»¥é€šè¿‡é‡å†™Closeable.close()æ¥æ‰§è¡Œç›¸åº”的清ç†å·¥ä½œã€‚

+ +

Reducer有3个主è¦é˜¶æ®µï¼šshuffleã€sortå’Œreduce。 +

+ +
+ Shuffle + +

Reducer的输入就是Mapperå·²ç»æŽ’好åºçš„输出。在这个阶段,框架通过HTTP为æ¯ä¸ªReducer获得所有Mapper输出中与之相关的分å—。

+
+ +
+ Sort + +

这个阶段,框架将按照key的值对Reducer的输入进行分组 + (因为ä¸åŒmapper的输出中å¯èƒ½ä¼šæœ‰ç›¸åŒçš„key)。

+ +

Shuffleå’ŒSort两个阶段是åŒæ—¶è¿›è¡Œçš„ï¼›map的输出也是一边被å–回一边被åˆå¹¶çš„。

+ +
+ Secondary Sort + +

如果需è¦ä¸­é—´è¿‡ç¨‹å¯¹key的分组规则和reduceå‰å¯¹key的分组规则ä¸åŒï¼Œé‚£ä¹ˆå¯ä»¥é€šè¿‡ + JobConf.setOutputValueGroupingComparator(Class)æ¥æŒ‡å®šä¸€ä¸ªComparator。å†åŠ ä¸Š + + JobConf.setOutputKeyComparatorClass(Class)å¯ç”¨äºŽæŽ§åˆ¶ä¸­é—´è¿‡ç¨‹çš„key如何被分组,所以结åˆä¸¤è€…å¯ä»¥å®žçŽ°æŒ‰å€¼çš„二次排åºã€‚ +

+
+
+ +
+ Reduce + +

在这个阶段,框架为已分组的输入数æ®ä¸­çš„æ¯ä¸ª + <key, (list of values)>对调用一次 + + reduce(WritableComparable, Iterator, OutputCollector, Reporter)方法。

+ +

Reduce任务的输出通常是通过调用 + + OutputCollector.collect(WritableComparable, Writable)写入 + + 文件系统的。

+ +

应用程åºå¯ä»¥ä½¿ç”¨Reporter报告进度,设定应用程åºçº§åˆ«çš„状æ€æ¶ˆæ¯ï¼Œæ›´æ–°Counters(计数器),或者仅是表明自己è¿è¡Œæ­£å¸¸ã€‚

+ +

Reducer的输出是没有排åºçš„。

+
+ +
+ 需è¦å¤šå°‘个Reduce? + +

Reduce的数目建议是0.95或1.75乘以 + (<no. of nodes> * + mapred.tasktracker.reduce.tasks.maximum)。 +

+ +

用0.95,所有reduceå¯ä»¥åœ¨maps一完æˆæ—¶å°±ç«‹åˆ»å¯åŠ¨ï¼Œå¼€å§‹ä¼ è¾“map的输出结果。用1.75,速度快的节点å¯ä»¥åœ¨å®Œæˆç¬¬ä¸€è½®reduce任务åŽï¼Œå¯ä»¥å¼€å§‹ç¬¬äºŒè½®ï¼Œè¿™æ ·å¯ä»¥å¾—到比较好的负载å‡è¡¡çš„效果。

+ +

增加reduce的数目会增加整个框架的开销,但å¯ä»¥æ”¹å–„è´Ÿè½½å‡è¡¡ï¼Œé™ä½Žç”±äºŽæ‰§è¡Œå¤±è´¥å¸¦æ¥çš„è´Ÿé¢å½±å“。

+ +

上述比例因å­æ¯”整体数目ç¨å°ä¸€äº›æ˜¯ä¸ºäº†ç»™æ¡†æž¶ä¸­çš„推测性任务(speculative-tasks) + 或失败的任务预留一些reduce的资æºã€‚

+
+ +
+ æ— Reducer + +

如果没有归约è¦è¿›è¡Œï¼Œé‚£ä¹ˆè®¾ç½®reduce任务的数目为零是åˆæ³•çš„。

+ +

è¿™ç§æƒ…况下,map任务的输出会直接被写入由 + + setOutputPath(Path)指定的输出路径。框架在把它们写入FileSystem之å‰æ²¡æœ‰å¯¹å®ƒä»¬è¿›è¡ŒæŽ’åºã€‚ +

+
+
+ +
+ Partitioner + +

+ Partitioner用于划分键值空间(key space)。

+ +

Partitioner负责控制map输出结果key的分割。Key(或者一个keyå­é›†ï¼‰è¢«ç”¨äºŽäº§ç”Ÿåˆ†åŒºï¼Œé€šå¸¸ä½¿ç”¨çš„是Hash函数。分区的数目与一个作业的reduce任务的数目是一样的。因此,它控制将中间过程的key(也就是这æ¡è®°å½•ï¼‰åº”该å‘é€ç»™m个reduce任务中的哪一个æ¥è¿›è¡Œreduceæ“作。 +

+ +

+ HashPartitioner是默认的 Partitioner。

+
+ +
+ Reporter + +

+ Reporter是用于Map/Reduce应用程åºæŠ¥å‘Šè¿›åº¦ï¼Œè®¾å®šåº”用级别的状æ€æ¶ˆæ¯ï¼Œ + æ›´æ–°Counters(计数器)的机制。

+ +

Mapperå’ŒReducer的实现å¯ä»¥åˆ©ç”¨Reporter + æ¥æŠ¥å‘Šè¿›åº¦ï¼Œæˆ–者仅是表明自己è¿è¡Œæ­£å¸¸ã€‚在那ç§åº”用程åºéœ€è¦èŠ±å¾ˆé•¿æ—¶é—´å¤„ç†ä¸ªåˆ«é”®å€¼å¯¹çš„场景中,这ç§æœºåˆ¶æ˜¯å¾ˆå…³é”®çš„,因为框架å¯èƒ½ä¼šä»¥ä¸ºè¿™ä¸ªä»»åŠ¡è¶…时了,从而将它强行æ€æ­»ã€‚å¦ä¸€ä¸ªé¿å…è¿™ç§æƒ…况å‘生的方å¼æ˜¯ï¼Œå°†é…ç½®å‚æ•°mapred.task.timeout设置为一个足够高的值(或者干脆设置为零,则没有超时é™åˆ¶äº†ï¼‰ã€‚ +

+ +

应用程åºå¯ä»¥ç”¨Reporteræ¥æ›´æ–°Counter(计数器)。 +

+
+ +
+ OutputCollector + +

+ OutputCollector是一个Map/Reduce框架æ供的用于收集 + Mapper或Reducer输出数æ®çš„通用机制 + (包括中间输出结果和作业的输出结果)。

+
+ +

Hadoop Map/Reduce框架附带了一个包å«è®¸å¤šå®žç”¨åž‹çš„mapperã€reducerå’Œpartitioner + 的类库。

+
+ +
+ 作业é…ç½® + +

+ JobConf代表一个Map/Reduce作业的é…置。

+ +

JobConf是用户å‘Hadoop框架æ述一个Map/Reduce作业如何执行的主è¦æŽ¥å£ã€‚框架会按照JobConfæè¿°çš„ä¿¡æ¯å¿ å®žåœ°åŽ»å°è¯•å®Œæˆè¿™ä¸ªä½œä¸šï¼Œç„¶è€Œï¼š

+
    +
  • + 一些å‚æ•°å¯èƒ½ä¼šè¢«ç®¡ç†è€…标记为 + final,这æ„味它们ä¸èƒ½è¢«æ›´æ”¹ã€‚ +
  • +
  • + 一些作业的å‚æ•°å¯ä»¥è¢«ç›´æˆªäº†å½“地进行设置(例如: + + setNumReduceTasks(int)),而å¦ä¸€äº›å‚数则与框架或者作业的其他å‚数之间微妙地相互影å“,并且设置起æ¥æ¯”较å¤æ‚(例如: + setNumMapTasks(int))。 +
  • +
+ +

通常,JobConf会指明Mapperã€Combiner(如果有的è¯)〠+ Partitionerã€Reducerã€InputFormatå’Œ + OutputFormat的具体实现。JobConf还能指定一组输入文件 + (setInputPaths(JobConf, Path...) + /addInputPath(JobConf, Path)) + å’Œ(setInputPaths(JobConf, String) + /addInputPaths(JobConf, String)) + 以åŠè¾“出文件应该写在哪儿 + (setOutputPath(Path))。

+ +

JobConfå¯é€‰æ‹©åœ°å¯¹ä½œä¸šè®¾ç½®ä¸€äº›é«˜çº§é€‰é¡¹ï¼Œä¾‹å¦‚:设置Comparatorï¼› + 放到DistributedCache上的文件;中间结果或者作业输出结果是å¦éœ€è¦åŽ‹ç¼©ä»¥åŠæ€Žä¹ˆåŽ‹ç¼©ï¼› + 利用用户æ供的脚本(setMapDebugScript(String)/setReduceDebugScript(String)) + 进行调试;作业是å¦å…许预防性(speculative)任务的执行 + (setMapSpeculativeExecution(boolean))/(setReduceSpeculativeExecution(boolean)) + ï¼›æ¯ä¸ªä»»åŠ¡æœ€å¤§çš„å°è¯•æ¬¡æ•° + (setMaxMapAttempts(int)/setMaxReduceAttempts(int)) + ;一个作业能容å¿çš„任务失败的百分比 + (setMaxMapTaskFailuresPercent(int)/setMaxReduceTaskFailuresPercent(int)) + ;等等。

+ +

当然,用户能使用 + set(String, String)/get(String, String) + æ¥è®¾ç½®æˆ–者å–得应用程åºéœ€è¦çš„ä»»æ„å‚数。然而,DistributedCache的使用是é¢å‘大规模åªè¯»æ•°æ®çš„。

+
+ +
+ 任务的执行和环境 + +

TaskTracker是在一个å•ç‹¬çš„jvm上以å­è¿›ç¨‹çš„å½¢å¼æ‰§è¡Œ + Mapper/Reducer任务(Task)的。 +

+ +

å­ä»»åŠ¡ä¼šç»§æ‰¿çˆ¶TaskTracker的环境。用户å¯ä»¥é€šè¿‡JobConf中的 + mapred.child.java.optsé…ç½®å‚æ•°æ¥è®¾å®šå­jvm上的附加选项,例如: + 通过-Djava.library.path=<> 将一个éžæ ‡å‡†è·¯å¾„设为è¿è¡Œæ—¶çš„链接用以æœç´¢å…±äº«åº“,等等。如果mapred.child.java.opts包å«ä¸€ä¸ªç¬¦å·@taskid@, + 它会被替æ¢æˆmap/reduceçš„taskid的值。

+ +

下é¢æ˜¯ä¸€ä¸ªåŒ…å«å¤šä¸ªå‚数和替æ¢çš„例å­ï¼Œå…¶ä¸­åŒ…括:记录jvm GC日志; + JVM JMX代ç†ç¨‹åºä»¥æ— å¯†ç çš„æ–¹å¼å¯åŠ¨ï¼Œè¿™æ ·å®ƒå°±èƒ½è¿žæŽ¥åˆ°jconsole上,从而å¯ä»¥æŸ¥çœ‹å­è¿›ç¨‹çš„内存和线程,得到线程的dump;还把å­jvm的最大堆尺寸设置为512MB, + 并为å­jvmçš„java.library.path添加了一个附加路径。

+ +

+ <property>
+   <name>mapred.child.java.opts</name>
+   <value>
+      + -Xmx512M -Djava.library.path=/home/mycompany/lib + -verbose:gc -Xloggc:/tmp/@taskid@.gc
+      + -Dcom.sun.management.jmxremote.authenticate=false + -Dcom.sun.management.jmxremote.ssl=false
+   </value>
+ </property> +

+

用户或管ç†å‘˜ä¹Ÿå¯ä»¥ä½¿ç”¨mapred.child.ulimit设定è¿è¡Œçš„å­ä»»åŠ¡çš„最大虚拟内存。mapred.child.ulimit的值以(KB)为å•ä½ï¼Œå¹¶ä¸”必须大于或等于-Xmxå‚æ•°ä¼ ç»™JavaVM的值,å¦åˆ™VM会无法å¯åŠ¨ã€‚

+

注æ„:mapred.child.java.optsåªç”¨äºŽè®¾ç½®task trackerå¯åŠ¨çš„å­ä»»åŠ¡ã€‚为守护进程设置内存选项请查看 + + cluster_setup.html

+

${mapred.local.dir}/taskTracker/是task tracker的本地目录, + 用于创建本地缓存和job。它å¯ä»¥æŒ‡å®šå¤šä¸ªç›®å½•ï¼ˆè·¨è¶Šå¤šä¸ªç£ç›˜ï¼‰ï¼Œæ–‡ä»¶ä¼šåŠéšæœºçš„ä¿å­˜åˆ°æœ¬åœ°è·¯å¾„下的æŸä¸ªç›®å½•ã€‚当jobå¯åŠ¨æ—¶ï¼Œtask trackeræ ¹æ®é…置文档创建本地job目录,目录结构如以下所示:

+
    +
  • ${mapred.local.dir}/taskTracker/archive/ :分布å¼ç¼“存。这个目录ä¿å­˜æœ¬åœ°çš„分布å¼ç¼“存。因此本地分布å¼ç¼“存是在所有taskå’Œjob间共享的。
  • +
  • ${mapred.local.dir}/taskTracker/jobcache/$jobid/ : + 本地job目录。 +
      +
    • ${mapred.local.dir}/taskTracker/jobcache/$jobid/work/: + job指定的共享目录。å„个任务å¯ä»¥ä½¿ç”¨è¿™ä¸ªç©ºé—´åšä¸ºæš‚存空间,用于它们之间共享文件。这个目录通过job.local.dir å‚数暴露给用户。这个路径å¯ä»¥é€šè¿‡API + JobConf.getJobLocalDir()æ¥è®¿é—®ã€‚它也å¯ä»¥è¢«åšä¸ºç³»ç»Ÿå±žæ€§èŽ·å¾—。因此,用户(比如è¿è¡Œstreaming)å¯ä»¥è°ƒç”¨System.getProperty("job.local.dir")获得该目录。 +
    • +
    • ${mapred.local.dir}/taskTracker/jobcache/$jobid/jars/: + 存放jar包的路径,用于存放作业的jar文件和展开的jar。job.jar是应用程åºçš„jar文件,它会被自动分å‘到å„å°æœºå™¨ï¼Œåœ¨taskå¯åŠ¨å‰ä¼šè¢«è‡ªåŠ¨å±•å¼€ã€‚使用api + + JobConf.getJar() 函数å¯ä»¥å¾—到job.jarçš„ä½ç½®ã€‚使用JobConf.getJar().getParent()å¯ä»¥è®¿é—®å­˜æ”¾å±•å¼€çš„jar包的目录。 +
    • +
    • ${mapred.local.dir}/taskTracker/jobcache/$jobid/job.xml: + 一个job.xml文件,本地的通用的作业é…置文件。 +
    • +
    • ${mapred.local.dir}/taskTracker/jobcache/$jobid/$taskid: + æ¯ä¸ªä»»åŠ¡æœ‰ä¸€ä¸ªç›®å½•task-id,它里é¢æœ‰å¦‚下的目录结构: +
        +
      • ${mapred.local.dir}/taskTracker/jobcache/$jobid/$taskid/job.xml: + 一个job.xml文件,本地化的任务作业é…置文件。任务本地化是指为该task设定特定的属性值。这些值会在下é¢å…·ä½“说明。 +
      • +
      • ${mapred.local.dir}/taskTracker/jobcache/$jobid/$taskid/output + 一个存放中间过程的输出文件的目录。它ä¿å­˜äº†ç”±framwork产生的临时map reduceæ•°æ®ï¼Œæ¯”如map的输出文件等。
      • +
      • ${mapred.local.dir}/taskTracker/jobcache/$jobid/$taskid/work: + task的当å‰å·¥ä½œç›®å½•ã€‚
      • +
      • ${mapred.local.dir}/taskTracker/jobcache/$jobid/$taskid/work/tmp: + task的临时目录。(用户å¯ä»¥è®¾å®šå±žæ€§mapred.child.tmp + æ¥ä¸ºmapå’Œreduce task设定临时目录。缺çœå€¼æ˜¯./tmp。如果这个值ä¸æ˜¯ç»å¯¹è·¯å¾„, + 它会把task的工作路径加到该路径å‰é¢ä½œä¸ºtask的临时文件路径。如果这个值是ç»å¯¹è·¯å¾„则直接使用这个值。 + 如果指定的目录ä¸å­˜åœ¨ï¼Œä¼šè‡ªåŠ¨åˆ›å»ºè¯¥ç›®å½•ã€‚之åŽï¼ŒæŒ‰ç…§é€‰é¡¹ + -Djava.io.tmpdir='临时文件的ç»å¯¹è·¯å¾„'执行javaå­ä»»åŠ¡ã€‚ + pipeså’Œstreaming的临时文件路径是通过环境å˜é‡TMPDIR='the absolute path of the tmp dir'设定的)。 + 如果mapred.child.tmp有./tmp值,这个目录会被创建。
      • +
      +
    • +
    +
  • +
+

下é¢çš„属性是为æ¯ä¸ªtask执行时使用的本地å‚数,它们ä¿å­˜åœ¨æœ¬åœ°åŒ–的任务作业é…置文件里:

+ + + + + + + + + + + + + + + + + + + + + + + +
å称类型æè¿°
mapred.job.idStringjob id
mapred.jarStringjob目录下job.jarçš„ä½ç½®
job.local.dir Stringjob指定的共享存储空间
mapred.tip.id String task id
mapred.task.id String taskå°è¯•id
mapred.task.is.map boolean 是å¦æ˜¯map task
mapred.task.partition int task在job中的id
map.input.file String map读å–的文件å
map.input.start long map输入的数æ®å—的起始ä½ç½®å移
map.input.length long map输入的数æ®å—的字节数
mapred.work.output.dir String task临时输出目录
+

task的标准输出和错误输出æµä¼šè¢«è¯»åˆ°TaskTracker中,并且记录到 + ${HADOOP_LOG_DIR}/userlogs

+

DistributedCache + å¯ç”¨äºŽmap或reduce task中分å‘jar包和本地库。å­jvm总是把 + 当å‰å·¥ä½œç›®å½• 加到 + java.library.path å’Œ LD_LIBRARY_PATH。 + 因此,å¯ä»¥é€šè¿‡ + + System.loadLibrary或 + + System.load装载缓存的库。有关使用分布å¼ç¼“存加载共享库的细节请å‚考 + + native_libraries.html

+
+ +
+ 作业的æ交与监控 + +

+ JobClient是用户æ交的作业与JobTracker交互的主è¦æŽ¥å£ã€‚ +

+ +

JobClient æä¾›æ交作业,追踪进程,访问å­ä»»åŠ¡çš„日志记录,获得Map/Reduce集群状æ€ä¿¡æ¯ç­‰åŠŸèƒ½ã€‚ +

+ +

作业æ交过程包括:

+
    +
  1. 检查作业输入输出样å¼ç»†èŠ‚
  2. +
  3. 为作业计算InputSplit值。
  4. +
  5. + 如果需è¦çš„è¯ï¼Œä¸ºä½œä¸šçš„DistributedCache建立必须的统计信æ¯ã€‚ +
  6. +
  7. + æ‹·è´ä½œä¸šçš„jar包和é…置文件到FileSystem上的Map/Reduce系统目录下。 +
  8. +
  9. + æ交作业到JobTracker并且监控它的状æ€ã€‚ +
  10. +
+

作业的历å²æ–‡ä»¶è®°å½•åˆ°æŒ‡å®šç›®å½•çš„"_logs/history/"å­ç›®å½•ä¸‹ã€‚这个指定目录由hadoop.job.history.user.location设定,默认是作业输出的目录。因此默认情况下,文件会存放在mapred.output.dir/_logs/history目录下。用户å¯ä»¥è®¾ç½®hadoop.job.history.user.location为noneæ¥åœæ­¢æ—¥å¿—记录。 +

+ +

用户使用下é¢çš„命令å¯ä»¥çœ‹åˆ°åœ¨æŒ‡å®šç›®å½•ä¸‹çš„历å²æ—¥å¿—记录的摘è¦ã€‚ +
+ $ bin/hadoop job -history output-dir
+ 这个命令会打å°å‡ºä½œä¸šçš„细节,以åŠå¤±è´¥çš„和被æ€æ­»çš„任务细节。
+ è¦æŸ¥çœ‹æœ‰å…³ä½œä¸šçš„更多细节例如æˆåŠŸçš„任务ã€æ¯ä¸ªä»»åŠ¡å°è¯•çš„次数(task attempt)等,å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„命令 +
+ $ bin/hadoop job -history all output-dir

+ +

用户å¯ä»¥ä½¿ç”¨ + OutputLogFilter + 从输出目录列表中筛选日志文件。

+ +

一般情况,用户利用JobConf创建应用程åºå¹¶é…置作业属性, + 然åŽç”¨ + JobClient æ交作业并监视它的进程。

+ +
+ 作业的控制 + +

有时候,用一个å•ç‹¬çš„Map/Reduce作业并ä¸èƒ½å®Œæˆä¸€ä¸ªå¤æ‚的任务,用户也许è¦é“¾æŽ¥å¤šä¸ªMap/Reduce作业æ‰è¡Œã€‚这是容易实现的,因为作业通常输出到分布å¼æ–‡ä»¶ç³»ç»Ÿä¸Šçš„,所以å¯ä»¥æŠŠè¿™ä¸ªä½œä¸šçš„输出作为下一个作业的输入实现串è”。 +

+ +

然而,这也æ„味ç€ï¼Œç¡®ä¿æ¯ä¸€ä½œä¸šå®Œæˆ(æˆåŠŸæˆ–失败)的责任就直接è½åœ¨äº†å®¢æˆ·èº«ä¸Šã€‚在这ç§æƒ…况下,å¯ä»¥ç”¨çš„控制作业的选项有: +

+
    +
  • + + runJob(JobConf):æ交作业,仅当作业完æˆæ—¶è¿”回。 +
  • +
  • + + submitJob(JobConf):åªæ交作业,之åŽéœ€è¦ä½ è½®è¯¢å®ƒè¿”回的 + + RunningJobå¥æŸ„的状æ€ï¼Œå¹¶æ ¹æ®æƒ…况调度。 +
  • +
  • + + JobConf.setJobEndNotificationURI(String):设置一个作业完æˆé€šçŸ¥ï¼Œå¯é¿å…轮询。 + +
  • +
+
+
+ +
+ 作业的输入 + +

+ InputFormat 为Map/Reduce作业æ述输入的细节规范。 +

+ +

Map/Reduce框架根æ®ä½œä¸šçš„InputFormatæ¥ï¼š +

+
    +
  1. 检查作业输入的有效性。
  2. +
  3. + 把输入文件切分æˆå¤šä¸ªé€»è¾‘InputSplit实例, + 并把æ¯ä¸€å®žä¾‹åˆ†åˆ«åˆ†å‘给一个 + Mapper。 +
  4. +
  5. + æä¾›RecordReader的实现,这个RecordReader从逻辑InputSplit中获得输入记录, + 这些记录将由Mapper处ç†ã€‚ +
  6. +
+ +

基于文件的InputFormat实现(通常是 + + FileInputFormatçš„å­ç±»ï¼‰ + 默认行为是按照输入文件的字节大å°ï¼ŒæŠŠè¾“入数æ®åˆ‡åˆ†æˆé€»è¾‘分å—(logical + InputSplit )。 + 其中输入文件所在的FileSystemçš„æ•°æ®å—尺寸是分å—大å°çš„上é™ã€‚下é™å¯ä»¥è®¾ç½®mapred.min.split.size + 的值。

+ +

考虑到边界情况,对于很多应用程åºæ¥è¯´ï¼Œå¾ˆæ˜Žæ˜¾æŒ‰ç…§æ–‡ä»¶å¤§å°è¿›è¡Œé€»è¾‘分割是ä¸èƒ½æ»¡è¶³éœ€æ±‚的。 + 在这ç§æƒ…况下,应用程åºéœ€è¦å®žçŽ°ä¸€ä¸ªRecordReaderæ¥å¤„ç†è®°å½•çš„边界并为æ¯ä¸ªä»»åŠ¡æ供一个逻辑分å—çš„é¢å‘记录的视图。 +

+ +

+ TextInputFormat 是默认的InputFormat。

+ +

如果一个作业的Inputformat是TextInputFormat, + 并且框架检测到输入文件的åŽç¼€æ˜¯.gzå’Œ.lzo,就会使用对应的CompressionCodec自动解压缩这些文件。 + 但是需è¦æ³¨æ„,上述带åŽç¼€çš„压缩文件ä¸ä¼šè¢«åˆ‡åˆ†ï¼Œå¹¶ä¸”整个压缩文件会分给一个mapperæ¥å¤„ç†ã€‚ +

+ +
+ InputSplit + +

+ InputSplit 是一个å•ç‹¬çš„Mapperè¦å¤„ç†çš„æ•°æ®å—。

+ +

一般的InputSplit 是字节样å¼è¾“入,然åŽç”±RecordReader处ç†å¹¶è½¬åŒ–æˆè®°å½•æ ·å¼ã€‚ +

+ +

+ FileSplit 是默认的InputSplit。 它把 + map.input.file 设定为输入文件的路径,输入文件是逻辑分å—文件。 +

+
+ +
+ RecordReader + +

+ RecordReader 从InputSlit读入<key, value>对。 +

+ +

一般的,RecordReader 把由InputSplit + æ供的字节样å¼çš„输入文件,转化æˆç”±Mapper处ç†çš„记录样å¼çš„文件。 + å› æ­¤RecordReader负责处ç†è®°å½•çš„边界情况和把数æ®è¡¨ç¤ºæˆkeys/values对形å¼ã€‚ +

+
+
+ +
+ 作业的输出 + +

+ OutputFormat æè¿°Map/Reduce作业的输出样å¼ã€‚ +

+ +

Map/Reduce框架根æ®ä½œä¸šçš„OutputFormatæ¥ï¼š +

+
    +
  1. + 检验作业的输出,例如检查输出路径是å¦å·²ç»å­˜åœ¨ã€‚ +
  2. +
  3. + æ供一个RecordWriter的实现,用æ¥è¾“出作业结果。 + 输出文件ä¿å­˜åœ¨FileSystem上。 +
  4. +
+ +

TextOutputFormat是默认的 + OutputFormat。

+ +
+ 任务的Side-Effect File + +

在一些应用程åºä¸­ï¼Œå­ä»»åŠ¡éœ€è¦äº§ç”Ÿä¸€äº›side-file,这些文件与作业实际输出结果的文件ä¸åŒã€‚ +

+ +

在这ç§æƒ…况下,åŒä¸€ä¸ªMapper或者Reducer的两个实例(比如预防性任务)åŒæ—¶æ‰“开或者写 + FileSystem上的åŒä¸€æ–‡ä»¶å°±ä¼šäº§ç”Ÿå†²çªã€‚因此应用程åºåœ¨å†™æ–‡ä»¶çš„时候需è¦ä¸ºæ¯æ¬¡ä»»åŠ¡å°è¯•ï¼ˆä¸ä»…仅是æ¯æ¬¡ä»»åŠ¡ï¼Œæ¯ä¸ªä»»åŠ¡å¯ä»¥å°è¯•æ‰§è¡Œå¾ˆå¤šæ¬¡ï¼‰é€‰å–一个独一无二的文件å(使用attemptid,例如task_200709221812_0001_m_000000_0)。 +

+ +

为了é¿å…冲çªï¼ŒMap/Reduce框架为æ¯æ¬¡å°è¯•æ‰§è¡Œä»»åŠ¡éƒ½å»ºç«‹å’Œç»´æŠ¤ä¸€ä¸ªç‰¹æ®Šçš„ + ${mapred.output.dir}/_temporary/_${taskid}å­ç›®å½•ï¼Œè¿™ä¸ªç›®å½•ä½äºŽæœ¬æ¬¡å°è¯•æ‰§è¡Œä»»åŠ¡è¾“出结果所在的FileSystem上,å¯ä»¥é€šè¿‡ + ${mapred.work.output.dir}æ¥è®¿é—®è¿™ä¸ªå­ç›®å½•ã€‚ + 对于æˆåŠŸå®Œæˆçš„任务å°è¯•ï¼Œåªæœ‰${mapred.output.dir}/_temporary/_${taskid}下的文件会移动到${mapred.output.dir}。当然,框架会丢弃那些失败的任务å°è¯•çš„å­ç›®å½•ã€‚è¿™ç§å¤„ç†è¿‡ç¨‹å¯¹äºŽåº”用程åºæ¥è¯´æ˜¯å®Œå…¨é€æ˜Žçš„。

+ +

在任务执行期间,应用程åºåœ¨å†™æ–‡ä»¶æ—¶å¯ä»¥åˆ©ç”¨è¿™ä¸ªç‰¹æ€§ï¼Œæ¯”如 + 通过 + FileOutputFormat.getWorkOutputPath()获得${mapred.work.output.dir}目录, + 并在其下创建任æ„任务执行时所需的side-file,框架在任务å°è¯•æˆåŠŸæ—¶ä¼šé©¬ä¸Šç§»åŠ¨è¿™äº›æ–‡ä»¶ï¼Œå› æ­¤ä¸éœ€è¦åœ¨ç¨‹åºå†…为æ¯æ¬¡ä»»åŠ¡å°è¯•é€‰å–一个独一无二的å字。 +

+ +

注æ„:在æ¯æ¬¡ä»»åŠ¡å°è¯•æ‰§è¡ŒæœŸé—´ï¼Œ${mapred.work.output.dir} 的值实际上是 + ${mapred.output.dir}/_temporary/_{$taskid},这个值是Map/Reduce框架创建的。 + 所以使用这个特性的方法是,在 + FileOutputFormat.getWorkOutputPath() + 路径下创建side-fileå³å¯ã€‚ +

+ +

对于åªä½¿ç”¨mapä¸ä½¿ç”¨reduce的作业,这个结论也æˆç«‹ã€‚è¿™ç§æƒ…况下,map的输出结果直接生æˆåˆ°HDFS上。 +

+
+ +
+ RecordWriter + +

+ RecordWriter 生æˆ<key, value> + 对到输出文件。

+ +

RecordWriter的实现把作业的输出结果写到 + FileSystem。

+
+
+ +
+ 其他有用的特性 + +
+ Counters + +

Counters 是多个由Map/Reduce框架或者应用程åºå®šä¹‰çš„全局计数器。 + æ¯ä¸€ä¸ªCounterå¯ä»¥æ˜¯ä»»ä½•ä¸€ç§ + Enum类型。åŒä¸€ç‰¹å®šEnum类型的Counterå¯ä»¥æ±‡é›†åˆ°ä¸€ä¸ªç»„,其类型为Counters.Group。

+ +

应用程åºå¯ä»¥å®šä¹‰ä»»æ„(Enum类型)çš„Counters并且å¯ä»¥é€šè¿‡ map 或者 + reduce方法中的 + + Reporter.incrCounter(Enum, long)或者 + + Reporter.incrCounter(String, String, long) + 更新。之åŽæ¡†æž¶ä¼šæ±‡æ€»è¿™äº›å…¨å±€counters。 +

+
+ +
+ DistributedCache + +

+ DistributedCache å¯å°†å…·ä½“应用相关的ã€å¤§å°ºå¯¸çš„ã€åªè¯»çš„文件有效地分布放置。 +

+ +

DistributedCache 是Map/Reduce框架æ供的功能,能够缓存应用程åºæ‰€éœ€çš„文件 + (包括文本,档案文件,jar文件等)。 +

+

应用程åºåœ¨JobConf中通过url(hdfs://)指定需è¦è¢«ç¼“存的文件。 + DistributedCacheå‡å®šç”±hdfs://æ ¼å¼url指定的文件已ç»åœ¨ + FileSystem上了。

+ +

Map-Redcue框架在作业所有任务执行之å‰ä¼šæŠŠå¿…è¦çš„文件拷è´åˆ°slave节点上。 + 它è¿è¡Œé«˜æ•ˆæ˜¯å› ä¸ºæ¯ä¸ªä½œä¸šçš„文件åªæ‹·è´ä¸€æ¬¡å¹¶ä¸”为那些没有文档的slave节点缓存文档。 +

+ +

DistributedCache æ ¹æ®ç¼“存文档修改的时间戳进行追踪。 + 在作业执行期间,当å‰åº”用程åºæˆ–者外部程åºä¸èƒ½ä¿®æ”¹ç¼“存文件。 +

+ +

distributedCacheå¯ä»¥åˆ†å‘简å•çš„åªè¯»æ•°æ®æˆ–文本文件,也å¯ä»¥åˆ†å‘å¤æ‚类型的文件例如归档文件和jar文件。归档文件(zip,tar,tgzå’Œtar.gz文件)在slave节点上会被解档(un-archived)。 + 这些文件å¯ä»¥è®¾ç½®æ‰§è¡Œæƒé™ã€‚

+

用户å¯ä»¥é€šè¿‡è®¾ç½®mapred.cache.{files|archives}æ¥åˆ†å‘文件。 + 如果è¦åˆ†å‘多个文件,å¯ä»¥ä½¿ç”¨é€—å·åˆ†éš”文件所在路径。也å¯ä»¥åˆ©ç”¨APIæ¥è®¾ç½®è¯¥å±žæ€§ï¼š + + DistributedCache.addCacheFile(URI,conf)/ + + DistributedCache.addCacheArchive(URI,conf) and + + DistributedCache.setCacheFiles(URIs,conf)/ + + DistributedCache.setCacheArchives(URIs,conf) + 其中URIçš„å½¢å¼æ˜¯ + hdfs://host:port/absolute-path#link-name + 在Streaming程åºä¸­ï¼Œå¯ä»¥é€šè¿‡å‘½ä»¤è¡Œé€‰é¡¹ + -cacheFile/-cacheArchive + 分å‘文件。

+

+ 用户å¯ä»¥é€šè¿‡ + DistributedCache.createSymlink(Configuration)方法让DistributedCache + 在当å‰å·¥ä½œç›®å½•ä¸‹åˆ›å»ºåˆ°ç¼“存文件的符å·é“¾æŽ¥ã€‚ + 或者通过设置é…置文件属性mapred.create.symlink为yes。 + 分布å¼ç¼“存会截å–URI的片段作为链接的å字。 + 例如,URI是 hdfs://namenode:port/lib.so.1#lib.so, + 则在task当å‰å·¥ä½œç›®å½•ä¼šæœ‰å为lib.so的链接, + 它会链接分布å¼ç¼“存中的lib.so.1。 +

+ +

DistributedCacheå¯åœ¨map/reduce任务中作为 + 一ç§åŸºç¡€è½¯ä»¶åˆ†å‘机制使用。它å¯ä»¥è¢«ç”¨äºŽåˆ†å‘jar包和本地库(native libraries)。 + + DistributedCache.addArchiveToClassPath(Path, Configuration)å’Œ + + DistributedCache.addFileToClassPath(Path, Configuration) API能够被用于 + 缓存文件和jar包,并把它们加入å­jvmçš„classpath。也å¯ä»¥é€šè¿‡è®¾ç½®é…置文档里的属性 + mapred.job.classpath.{files|archives}达到相åŒçš„效果。缓存文件å¯ç”¨äºŽåˆ†å‘和装载本地库。 +

+
+ +
+ Tool + +

Tool + 接å£æ”¯æŒå¤„ç†å¸¸ç”¨çš„Hadoop命令行选项。 +

+ +

Tool 是Map/Reduce工具或应用的标准。应用程åºåº”åªå¤„ç†å…¶å®šåˆ¶å‚数, + è¦æŠŠæ ‡å‡†å‘½ä»¤è¡Œé€‰é¡¹é€šè¿‡ + ToolRunner.run(Tool, String[]) + 委托给 + + GenericOptionsParser处ç†ã€‚ +

+ +

+ Hadoop命令行的常用选项有:
+ + -conf <configuration file> + +
+ + -D <property=value> + +
+ + -fs <local|namenode:port> + +
+ + -jt <local|jobtracker:port> + +

+
+ +
+ IsolationRunner + +

+ IsolationRunner 是帮助调试Map/Reduce程åºçš„工具。

+ +

使用IsolationRunner的方法是,首先设置 + keep.failed.task.files属性为true + (åŒæ—¶å‚考keep.task.files.pattern)。

+ +

+ 然åŽï¼Œç™»å½•åˆ°ä»»åŠ¡è¿è¡Œå¤±è´¥çš„节点上,进入 + TaskTracker的本地路径è¿è¡Œ + IsolationRunner:
+ $ cd <local path>/taskTracker/${taskid}/work
+ + $ bin/hadoop org.apache.hadoop.mapred.IsolationRunner ../job.xml + +

+ +

IsolationRunner会把失败的任务放在å•ç‹¬çš„一个能够调试的jvm上è¿è¡Œï¼Œå¹¶ä¸”采用和之å‰å®Œå…¨ä¸€æ ·çš„输入数æ®ã€‚ +

+
+ +
+ Profiling +

Profiling是一个工具,它使用内置的java profiler工具进行分æžèŽ·å¾—(2-3个)map或reduce样例è¿è¡Œåˆ†æžæŠ¥å‘Šã€‚

+

用户å¯ä»¥é€šè¿‡è®¾ç½®å±žæ€§mapred.task.profile指定系统是å¦é‡‡é›†profilerä¿¡æ¯ã€‚ + 利用api + JobConf.setProfileEnabled(boolean)å¯ä»¥ä¿®æ”¹å±žæ€§å€¼ã€‚如果设为true, + 则开å¯profiling功能。profilerä¿¡æ¯ä¿å­˜åœ¨ç”¨æˆ·æ—¥å¿—目录下。缺çœæƒ…况,profiling功能是关闭的。

+

如果用户设定使用profiling功能,å¯ä»¥ä½¿ç”¨é…置文档里的属性 + mapred.task.profile.{maps|reduces} + 设置è¦profile map/reduce task的范围。设置该属性值的api是 + + JobConf.setProfileTaskRange(boolean,String)。 + 范围的缺çœå€¼æ˜¯0-2。

+

用户å¯ä»¥é€šè¿‡è®¾å®šé…置文档里的属性mapred.task.profile.params + æ¥æŒ‡å®šprofileré…ç½®å‚数。修改属性è¦ä½¿ç”¨api + + JobConf.setProfileParams(String)。当è¿è¡Œtask时,如果字符串包å«%s。 + 它会被替æ¢æˆprofileing的输出文件å。这些å‚数会在命令行里传递到å­JVM中。缺çœçš„profiling + å‚数是 + -agentlib:hprof=cpu=samples,heap=sites,force=n,thread=y,verbose=n,file=%s。 +

+
+ +
+ 调试 +

Map/Reduce框架能够è¿è¡Œç”¨æˆ·æ供的用于调试的脚本程åºã€‚ + 当map/reduce任务失败时,用户å¯ä»¥é€šè¿‡è¿è¡Œè„šæœ¬åœ¨ä»»åŠ¡æ—¥å¿—(例如任务的标准输出ã€æ ‡å‡†é”™è¯¯ã€ç³»ç»Ÿæ—¥å¿—以åŠä½œä¸šé…置文件)上åšåŽç»­å¤„ç†å·¥ä½œã€‚用户æ供的调试脚本程åºçš„标准输出和标准错误会输出为诊断文件。如果需è¦çš„è¯è¿™äº›è¾“出结果也å¯ä»¥æ‰“å°åœ¨ç”¨æˆ·ç•Œé¢ä¸Šã€‚

+ +

在接下æ¥çš„章节,我们讨论如何与作业一起æ交调试脚本。为了æ交调试脚本, + 首先è¦æŠŠè¿™ä¸ªè„šæœ¬åˆ†å‘出去,而且还è¦åœ¨é…置文件里设置。 +

+
+ 如何分å‘脚本文件: +

用户è¦ç”¨ + DistributedCache + 机制æ¥åˆ†å‘和链接脚本文件

+
+
+ 如何æ交脚本: +

一个快速æ交调试脚本的方法是分别为需è¦è°ƒè¯•çš„map任务和reduce任务设置 + "mapred.map.task.debug.script" å’Œ "mapred.reduce.task.debug.script" + 属性的值。这些属性也å¯ä»¥é€šè¿‡ + + JobConf.setMapDebugScript(String) å’Œ + + JobConf.setReduceDebugScript(String) APIæ¥è®¾ç½®ã€‚对于streaming, + å¯ä»¥åˆ†åˆ«ä¸ºéœ€è¦è°ƒè¯•çš„map任务和reduce任务使用命令行选项-mapdebug å’Œ -reducedegugæ¥æ交调试脚本。 +

+ +

脚本的å‚数是任务的标准输出ã€æ ‡å‡†é”™è¯¯ã€ç³»ç»Ÿæ—¥å¿—以åŠä½œä¸šé…置文件。在è¿è¡Œmap/reduce失败的节点上è¿è¡Œè°ƒè¯•å‘½ä»¤æ˜¯ï¼š +
+ $script $stdout $stderr $syslog $jobconf

+ +

Pipes 程åºæ ¹æ®ç¬¬äº”个å‚数获得c++程åºå。 + 因此调试pipes程åºçš„命令是
+ $script $stdout $stderr $syslog $jobconf $program +

+
+ +
+ 默认行为 +

对于pipes,默认的脚本会用gdb处ç†core dump, + æ‰“å° stack trace并且给出正在è¿è¡Œçº¿ç¨‹çš„ä¿¡æ¯ã€‚

+
+
+ +
+ JobControl + +

+ JobControl是一个工具,它å°è£…了一组Map/Reduce作业以åŠä»–们之间的ä¾èµ–关系。 +

+
+ +
+ æ•°æ®åŽ‹ç¼© + +

Hadoop Map/Reduce框架为应用程åºçš„写入文件æ“作æ供压缩工具,这些工具å¯ä»¥ä¸ºmap输出的中间数æ®å’Œä½œä¸šæœ€ç»ˆè¾“出数æ®ï¼ˆä¾‹å¦‚reduce的输出)æ供支æŒã€‚它还附带了一些 + + CompressionCodec的实现,比如实现了 + zlibå’Œlzo压缩算法。 + HadoopåŒæ ·æ”¯æŒgzip文件格å¼ã€‚ +

+ +

考虑到性能问题(zlib)以åŠJava类库的缺失(lzo)等因素,Hadoop也为上述压缩解压算法æ供本地库的实现。更多的细节请å‚考 + 这里。

+ +
+ 中间输出 + +

应用程åºå¯ä»¥é€šè¿‡ + + JobConf.setCompressMapOutput(boolean)api控制map输出的中间结果,并且å¯ä»¥é€šè¿‡ + + JobConf.setMapOutputCompressorClass(Class)api指定 + CompressionCodec。 +

+
+ +
+ 作业输出 +

应用程åºå¯ä»¥é€šè¿‡ + + FileOutputFormat.setCompressOutput(JobConf, boolean) + api控制输出是å¦éœ€è¦åŽ‹ç¼©å¹¶ä¸”å¯ä»¥ä½¿ç”¨ + + FileOutputFormat.setOutputCompressorClass(JobConf, Class)api指定CompressionCodec。

+ +

如果作业输出è¦ä¿å­˜æˆ + + SequenceFileOutputFormatæ ¼å¼ï¼Œéœ€è¦ä½¿ç”¨ + + SequenceFileOutputFormat.setOutputCompressionType(JobConf, + SequenceFile.CompressionType)api,æ¥è®¾å®š + SequenceFile.CompressionType (i.e. RECORD / + BLOCK - 默认是RECORD)。 +

+
+
+ +
+
+ +
+ 例å­ï¼šWordCount v2.0 + +

这里是一个更全é¢çš„WordCount例å­ï¼Œå®ƒä½¿ç”¨äº†æˆ‘们已ç»è®¨è®ºè¿‡çš„很多Map/Reduce框架æ供的功能。 +

+ +

è¿è¡Œè¿™ä¸ªä¾‹å­éœ€è¦HDFSçš„æŸäº›åŠŸèƒ½ï¼Œç‰¹åˆ«æ˜¯ + DistributedCache相关功能。因此这个例å­åªèƒ½è¿è¡Œåœ¨ + ä¼ªåˆ†å¸ƒå¼ æˆ–è€… + 完全分布å¼æ¨¡å¼çš„ + Hadoop上。

+ +
+ æºä»£ç  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
WordCount.java
1. + package org.myorg; +
2.
3. + import java.io.*; +
4. + import java.util.*; +
5.
6. + import org.apache.hadoop.fs.Path; +
7. + import org.apache.hadoop.filecache.DistributedCache; +
8. + import org.apache.hadoop.conf.*; +
9. + import org.apache.hadoop.io.*; +
10. + import org.apache.hadoop.mapred.*; +
11. + import org.apache.hadoop.util.*; +
12.
13. + public class WordCount extends Configured implements Tool { +
14.
15. +    + + public static class Map extends MapReduceBase + implements Mapper<LongWritable, Text, Text, IntWritable> { + +
16.
17. +      + + static enum Counters { INPUT_WORDS } + +
18.
19. +      + + private final static IntWritable one = new IntWritable(1); + +
20. +      + private Text word = new Text(); +
21.
22. +      + private boolean caseSensitive = true; +
23. +      + private Set<String> patternsToSkip = new HashSet<String>(); +
24.
25. +      + private long numRecords = 0; +
26. +      + private String inputFile; +
27.
28. +      + public void configure(JobConf job) { +
29. +        + + caseSensitive = job.getBoolean("wordcount.case.sensitive", true); + +
30. +        + inputFile = job.get("map.input.file"); +
31.
32. +        + if (job.getBoolean("wordcount.skip.patterns", false)) { +
33. +          + Path[] patternsFiles = new Path[0]; +
34. +          + try { +
35. +            + + patternsFiles = DistributedCache.getLocalCacheFiles(job); + +
36. +          + } catch (IOException ioe) { +
37. +            + + System.err.println("Caught exception while getting cached files: " + + StringUtils.stringifyException(ioe)); + +
38. +          + } +
39. +          + for (Path patternsFile : patternsFiles) { +
40. +            + parseSkipFile(patternsFile); +
41. +          + } +
42. +        + } +
43. +      + } +
44.
45. +      + private void parseSkipFile(Path patternsFile) { +
46. +        + try { +
47. +          + + BufferedReader fis = + new BufferedReader(new FileReader(patternsFile.toString())); + +
48. +          + String pattern = null; +
49. +          + while ((pattern = fis.readLine()) != null) { +
50. +            + patternsToSkip.add(pattern); +
51. +          + } +
52. +        + } catch (IOException ioe) { +
53. +          + + System.err.println("Caught exception while parsing the cached file '" + + patternsFile + "' : " + + StringUtils.stringifyException(ioe)); + + +
54. +        + } +
55. +      + } +
56.
57. +      + + public void map(LongWritable key, Text value, + OutputCollector<Text, IntWritable> output, + Reporter reporter) throws IOException { + +
58. +        + + String line = + (caseSensitive) ? value.toString() : + value.toString().toLowerCase(); + +
59.
60. +        + for (String pattern : patternsToSkip) { +
61. +          + line = line.replaceAll(pattern, ""); +
62. +        + } +
63.
64. +        + StringTokenizer tokenizer = new StringTokenizer(line); +
65. +        + while (tokenizer.hasMoreTokens()) { +
66. +          + word.set(tokenizer.nextToken()); +
67. +          + output.collect(word, one); +
68. +          + reporter.incrCounter(Counters.INPUT_WORDS, 1); +
69. +        + } +
70.
71. +        + if ((++numRecords % 100) == 0) { +
72. +          + + reporter.setStatus("Finished processing " + numRecords + + " records " + "from the input file: " + + inputFile); + +
73. +        + } +
74. +      + } +
75. +    + } +
76.
77. +    + + public static class Reduce extends MapReduceBase implements + Reducer<Text, IntWritable, Text, IntWritable> { + +
78. +      + + public void reduce(Text key, Iterator<IntWritable> values, + OutputCollector<Text, IntWritable> output, + Reporter reporter) throws IOException { + +
79. +        + int sum = 0; +
80. +        + while (values.hasNext()) { +
81. +          + sum += values.next().get(); +
82. +        + } +
83. +        + output.collect(key, new IntWritable(sum)); +
84. +      + } +
85. +    + } +
86.
87. +    + public int run(String[] args) throws Exception { +
88. +      + + JobConf conf = new JobConf(getConf(), WordCount.class); + +
89. +      + conf.setJobName("wordcount"); +
90.
91. +      + conf.setOutputKeyClass(Text.class); +
92. +      + conf.setOutputValueClass(IntWritable.class); +
93.
94. +      + conf.setMapperClass(Map.class); +
95. +      + conf.setCombinerClass(Reduce.class); +
96. +      + conf.setReducerClass(Reduce.class); +
97.
98. +      + conf.setInputFormat(TextInputFormat.class); +
99. +      + conf.setOutputFormat(TextOutputFormat.class); +
100.
101. +      + + List<String> other_args = new ArrayList<String>(); + +
102. +      + for (int i=0; i < args.length; ++i) { +
103. +        + if ("-skip".equals(args[i])) { +
104. +          + + DistributedCache.addCacheFile(new Path(args[++i]).toUri(), conf); + +
105. +          + + conf.setBoolean("wordcount.skip.patterns", true); + +
106. +        + } else { +
107. +          + other_args.add(args[i]); +
108. +        + } +
109. +      + } +
110.
111. +      + FileInputFormat.setInputPaths(conf, new Path(other_args.get(0))); +
112. +      + FileOutputFormat.setOutputPath(conf, new Path(other_args.get(1))); +
113.
114. +      + JobClient.runJob(conf); +
115. +      + return 0; +
116. +    + } +
117.
118. +    + + public static void main(String[] args) throws Exception { + +
119. +      + + int res = ToolRunner.run(new Configuration(), new WordCount(), + args); + +
120. +      + System.exit(res); +
121. +    + } +
122. + } +
123.
+
+ +
+ è¿è¡Œæ ·ä¾‹ + +

输入样例:

+

+ $ bin/hadoop dfs -ls /usr/joe/wordcount/input/
+ /usr/joe/wordcount/input/file01
+ /usr/joe/wordcount/input/file02
+
+ $ bin/hadoop dfs -cat /usr/joe/wordcount/input/file01
+ Hello World, Bye World!
+
+ $ bin/hadoop dfs -cat /usr/joe/wordcount/input/file02
+ Hello Hadoop, Goodbye to hadoop. +

+ +

è¿è¡Œç¨‹åºï¼š

+

+ + $ bin/hadoop jar /usr/joe/wordcount.jar org.myorg.WordCount + /usr/joe/wordcount/input /usr/joe/wordcount/output + +

+ +

输出:

+

+ + $ bin/hadoop dfs -cat /usr/joe/wordcount/output/part-00000 + +
+ Bye 1
+ Goodbye 1
+ Hadoop, 1
+ Hello 2
+ World! 1
+ World, 1
+ hadoop. 1
+ to 1
+

+ +

注æ„此时的输入与第一个版本的ä¸åŒï¼Œè¾“出的结果也有ä¸åŒã€‚ +

+ +

现在通过DistributedCacheæ’入一个模å¼æ–‡ä»¶ï¼Œæ–‡ä»¶ä¸­ä¿å­˜äº†è¦è¢«å¿½ç•¥çš„å•è¯æ¨¡å¼ã€‚ +

+ +

+ $ hadoop dfs -cat /user/joe/wordcount/patterns.txt
+ \.
+ \,
+ \!
+ to
+

+ +

å†è¿è¡Œä¸€æ¬¡ï¼Œè¿™æ¬¡ä½¿ç”¨æ›´å¤šçš„选项:

+

+ + $ bin/hadoop jar /usr/joe/wordcount.jar org.myorg.WordCount + -Dwordcount.case.sensitive=true /usr/joe/wordcount/input + /usr/joe/wordcount/output -skip /user/joe/wordcount/patterns.txt + +

+ +

应该得到这样的输出:

+

+ + $ bin/hadoop dfs -cat /usr/joe/wordcount/output/part-00000 + +
+ Bye 1
+ Goodbye 1
+ Hadoop 1
+ Hello 2
+ World 2
+ hadoop 1
+

+ +

å†è¿è¡Œä¸€æ¬¡ï¼Œè¿™ä¸€æ¬¡å…³é—­å¤§å°å†™æ•æ„Ÿæ€§ï¼ˆcase-sensitivity):

+

+ + $ bin/hadoop jar /usr/joe/wordcount.jar org.myorg.WordCount + -Dwordcount.case.sensitive=false /usr/joe/wordcount/input + /usr/joe/wordcount/output -skip /user/joe/wordcount/patterns.txt + +

+ +

输出:

+

+ + $ bin/hadoop dfs -cat /usr/joe/wordcount/output/part-00000 + +
+ bye 1
+ goodbye 1
+ hadoop 2
+ hello 2
+ world 2
+

+
+ +
+ 程åºè¦ç‚¹ + +

+ 通过使用一些Map/Reduce框架æ供的功能,WordCount的第二个版本在原始版本基础上有了如下的改进: +

+
    +
  • + 展示了应用程åºå¦‚何在Mapper (å’ŒReducer)中通过configure方法 + 修改é…ç½®å‚æ•°(28-43è¡Œ)。 +
  • +
  • + 展示了作业如何使用DistributedCache æ¥åˆ†å‘åªè¯»æ•°æ®ã€‚ + 这里å…许用户指定å•è¯çš„模å¼ï¼Œåœ¨è®¡æ•°æ—¶å¿½ç•¥é‚£äº›ç¬¦åˆæ¨¡å¼çš„å•è¯(104è¡Œ)。 +
  • +
  • + 展示Tool接å£å’ŒGenericOptionsParser处ç†Hadoop命令行选项的功能 + (87-116, 119è¡Œ)。 +
  • +
  • + 展示了应用程åºå¦‚何使用Counters(68è¡Œ),如何通过传递给map(和reduce) + 方法的Reporter实例æ¥è®¾ç½®åº”用程åºçš„状æ€ä¿¡æ¯(72è¡Œ)。 +
  • +
+ +
+
+ +

+ Java和JNI是Sun Microsystems, Inc.在美国和其它国家的注册商标。 +

+ + + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/native_libraries.xml b/src/docs/cn/src/documentation/content/xdocs/native_libraries.xml new file mode 100644 index 00000000000..091cffc3e92 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/native_libraries.xml @@ -0,0 +1,230 @@ + + + + + + + +
+ Hadoop本地库 +
+ + + +
+ 目的 + +

+ 鉴于性能问题以åŠæŸäº›Java类库的缺失,对于æŸäº›ç»„件,Hadoopæ供了自己的本地实现。 + 这些组件ä¿å­˜åœ¨Hadoop的一个独立的动æ€é“¾æŽ¥çš„库里。这个库在*nixå¹³å°ä¸Šå«libhadoop.so. 本文主è¦ä»‹ç»æœ¬åœ°åº“的使用方法以åŠå¦‚何构建本地库。 +

+
+ +
+ 组件 + +

Hadoop现在已ç»æœ‰ä»¥ä¸‹ + + compression codecs本地组件:

+ + +

在以上组件中,lzoå’Œgzip压缩编解ç å™¨å¿…须使用hadoop本地库æ‰èƒ½è¿è¡Œã€‚ +

+
+ +
+ 使用方法 + +

hadoop本地库的用法很简å•ï¼š

+ +
    +
  • + 看一下 + 支æŒçš„å¹³å°. +
  • +
  • + 下载 预构建的32ä½i386架构的Linux本地hadoop库(å¯ä»¥åœ¨hadoopå‘行版的lib/native目录下找到)或者自己 + 构建 这些库。 +
  • +
  • + ç¡®ä¿ä½ çš„å¹³å°å·²ç»å®‰è£…了zlib-1.2以上版本或者lzo2.0以上版本的软件包或者两者å‡å·²å®‰è£…(根æ®ä½ çš„需è¦ï¼‰ã€‚ +
  • +
+ +

bin/hadoop 脚本通过系统属性 + -Djava.library.path=<path>æ¥ç¡®è®¤hadoop本地库是å¦åŒ…å«åœ¨åº“路径里。

+ +

检查hadoop日志文件å¯ä»¥æŸ¥çœ‹hadoop库是å¦æ­£å¸¸ï¼Œæ­£å¸¸æƒ…况下会看到:

+ +

+ + DEBUG util.NativeCodeLoader - Trying to load the custom-built + native-hadoop library... +
+ + INFO util.NativeCodeLoader - Loaded the native-hadoop library + +

+ +

如果出错,会看到:

+

+ + INFO util.NativeCodeLoader - Unable to load native-hadoop library for + your platform... using builtin-java classes where applicable + +

+
+ +
+ 支æŒçš„å¹³å° + +

Hadoop本地库åªæ”¯æŒ*nixå¹³å°ï¼Œå·²ç»å¹¿æ³›ä½¿ç”¨åœ¨GNU/Linuxå¹³å°ä¸Šï¼Œä½†æ˜¯ä¸æ”¯æŒ + Cygwin + å’Œ Mac OS X。 +

+ +

å·²ç»æµ‹è¯•è¿‡çš„GNU/Linuxå‘行版本:

+ + +

在上述平å°ä¸Šï¼Œ32/64ä½Hadoop本地库分别能和32/64ä½çš„jvm一起正常è¿è¡Œã€‚ +

+
+ +
+ 构建Hadoop本地库 + +

Hadoop本地库使用 + ANSI C 编写,使用GNU autotools工具链 (autoconf, autoheader, automake, autoscan, libtool)构建。也就是说构建hadoop库的平å°éœ€è¦æœ‰æ ‡å‡†C的编译器和GNU autotools工具链。请å‚看 + 支æŒçš„å¹³å°ã€‚

+ +

你的目标平å°ä¸Šå¯èƒ½ä¼šéœ€è¦çš„软件包: +

+
    +
  • + C 编译器 (e.g. GNU C Compiler) +
  • +
  • + GNU Autools 工具链: + autoconf, + automake, + libtool +
  • +
  • + zlibå¼€å‘包 (stable version >= 1.2.0) +
  • +
  • + lzoå¼€å‘包 (stable version >= 2.0) +
  • +
+ +

如果已ç»æ»¡è¶³äº†ä¸Šè¿°å…ˆå†³æ¡ä»¶ï¼Œå¯ä»¥ä½¿ç”¨build.xml + 文件,并把其中的compile.native置为 + true,这样就å¯ä»¥ç”Ÿæˆhadoop本地库:

+ +

$ ant -Dcompile.native=true <target>

+ +

因为ä¸æ˜¯æ‰€æœ‰ç”¨æˆ·éƒ½éœ€è¦Hadoop本地库,所以默认情况下hadoopä¸ç”Ÿæˆè¯¥åº“。 +

+ +

ä½ å¯ä»¥åœ¨ä¸‹é¢çš„路径查看新生æˆçš„hadoop本地库:

+ +

$ build/native/<platform>/lib

+ +

其中<platform>æ˜¯ä¸‹åˆ—ç³»ç»Ÿå±žæ€§çš„ç»„åˆ + ${os.name}-${os.arch}-${sun.arch.data.model};例如 + Linux-i386-32。

+ +
+ æ³¨æ„ + +
    +
  • + 在生æˆhadoop本地库的目标平å°ä¸Šå¿…é¡» 安装了zlibå’Œlzoå¼€å‘包;但是如果你åªå¸Œæœ›ä½¿ç”¨å…¶ä¸­ä¸€ä¸ªçš„è¯ï¼Œåœ¨éƒ¨ç½²æ—¶ï¼Œå®‰è£…其中任何一个都是足够的。 +
  • +
  • + 在目标平å°ä¸Šç”Ÿæˆä»¥åŠéƒ¨ç½²hadoop本地库时,都需è¦æ ¹æ®32/64ä½jvm选å–对应的32/64ä½zlib/lzo软件包。 +
  • +
+
+
+ +
+ 使用DistributedCache 加载本地库 +

用户å¯ä»¥é€šè¿‡ + DistributedCache + 加载本地共享库,并分å‘和建立库文件的符å·é“¾æŽ¥ã€‚ +

+ +

这个例å­æ述了如何分å‘库文件并在从map/reduce任务中装载库文件。 +

+
    +
  1. 首先拷è´åº“文件到HDFS。
    + bin/hadoop fs -copyFromLocal mylib.so.1 /libraries/mylib.so.1 +
  2. +
  3. å¯åŠ¨ä½œä¸šæ—¶åŒ…å«ä»¥ä¸‹ä»£ç ï¼š
    + DistributedCache.createSymlink(conf);
    + DistributedCache.addCacheFile("hdfs://host:port/libraries/mylib.so.1#mylib.so", conf); + +
  4. +
  5. map/reduce任务中包å«ä»¥ä¸‹ä»£ç ï¼š
    + System.loadLibrary("mylib.so"); +
  6. +
+
+ + +
+ diff --git a/src/docs/cn/src/documentation/content/xdocs/quickstart.xml b/src/docs/cn/src/documentation/content/xdocs/quickstart.xml new file mode 100644 index 00000000000..e13395563ef --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/quickstart.xml @@ -0,0 +1,252 @@ + + + + + + +
+ Hadoop快速入门 +
+ + + +
+ 目的 +

这篇文档的目的是帮助你快速完æˆå•æœºä¸Šçš„Hadoop安装与使用以便你对Hadoop分布å¼æ–‡ä»¶ç³»ç»Ÿ(HDFS)å’ŒMap-Reduce框架有所体会,比如在HDFS上è¿è¡Œç¤ºä¾‹ç¨‹åºæˆ–简å•ä½œä¸šç­‰ã€‚

+
+
+ 先决æ¡ä»¶ + +
+ 支æŒå¹³å° + +
    +
  • + GNU/Linux是产å“å¼€å‘å’Œè¿è¡Œçš„å¹³å°ã€‚ + Hadoop已在有2000个节点的GNU/Linux主机组æˆçš„集群系统上得到验è¯ã€‚ +
  • +
  • + Win32å¹³å°æ˜¯ä½œä¸ºå¼€å‘å¹³å°æ”¯æŒçš„。由于分布å¼æ“作尚未在Win32å¹³å°ä¸Šå……分测试,所以还ä¸ä½œä¸ºä¸€ä¸ªç”Ÿäº§å¹³å°è¢«æ”¯æŒã€‚ +
  • +
+
+ +
+ 所需软件 +

Linux和Windows所需软件包括:

+
    +
  1. + JavaTM1.5.x,必须安装,建议选择Sunå…¬å¸å‘行的Java版本。 +
  2. +
  3. + ssh 必须安装并且ä¿è¯ sshd一直è¿è¡Œï¼Œä»¥ä¾¿ç”¨Hadoop + 脚本管ç†è¿œç«¯Hadoop守护进程。 +
  4. +
+

Windows下的附加软件需求

+
    +
  1. + Cygwin - æ供上述软件之外的shell支æŒã€‚ +
  2. +
+
+ +
+ 安装软件 + +

如果你的集群尚未安装所需软件,你得首先安装它们。

+ +

以Ubuntu Linux为例:

+

+ $ sudo apt-get install ssh
+ $ sudo apt-get install rsync +

+ +

在Windowså¹³å°ä¸Šï¼Œå¦‚果安装cygwin时未安装全部所需软件,则需å¯åŠ¨cyqwin安装管ç†å™¨å®‰è£…如下软件包:

+
    +
  • openssh - Net ç±»
  • +
+
+ +
+ +
+ 下载 + +

+ 为了获å–Hadoopçš„å‘行版,从Apacheçš„æŸä¸ªé•œåƒæœåŠ¡å™¨ä¸Šä¸‹è½½æœ€è¿‘çš„ + 稳定å‘行版。

+
+ +
+ è¿è¡ŒHadoop集群的准备工作 +

+ 解压所下载的Hadoopå‘行版。编辑 + conf/hadoop-env.sh文件,至少需è¦å°†JAVA_HOME设置为Java安装根路径。 +

+ +

+ å°è¯•å¦‚下命令:
+ $ bin/hadoop
+ 将会显示hadoop 脚本的使用文档。 +

+ +

现在你å¯ä»¥ç”¨ä»¥ä¸‹ä¸‰ç§æ”¯æŒçš„模å¼ä¸­çš„一ç§å¯åŠ¨Hadoop集群: +

+
    +
  • å•æœºæ¨¡å¼
  • +
  • 伪分布å¼æ¨¡å¼
  • +
  • 完全分布å¼æ¨¡å¼
  • +
+
+ +
+ å•æœºæ¨¡å¼çš„æ“作方法 + +

默认情况下,Hadoop被é…ç½®æˆä»¥éžåˆ†å¸ƒå¼æ¨¡å¼è¿è¡Œçš„一个独立Java进程。这对调试éžå¸¸æœ‰å¸®åŠ©ã€‚

+ +

+ 下é¢çš„实例将已解压的 conf 目录拷è´ä½œä¸ºè¾“入,查找并显示匹é…给定正则表达å¼çš„æ¡ç›®ã€‚输出写入到指定的output目录。 +
+ $ mkdir input
+ $ cp conf/*.xml input
+ + $ bin/hadoop jar hadoop-*-examples.jar grep input output 'dfs[a-z.]+' +
+ $ cat output/* +

+
+ +
+ 伪分布å¼æ¨¡å¼çš„æ“作方法 + +

Hadoopå¯ä»¥åœ¨å•èŠ‚点上以所谓的伪分布å¼æ¨¡å¼è¿è¡Œï¼Œæ­¤æ—¶æ¯ä¸€ä¸ªHadoop守护进程都作为一个独立的Java进程è¿è¡Œã€‚

+ +
+ é…ç½® +

使用如下的 conf/hadoop-site.xml:

+ + + + + + + + + + + + + + + + + + + +
<configuration>
  <property>
    <name>fs.default.name</name>
    <value>localhost:9000</value>
  </property>
  <property>
    <name>mapred.job.tracker</name>
    <value>localhost:9001</value>
  </property>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
</configuration>
+
+ +
+ å…密ç <em>ssh</em>设置 + +

+ 现在确认能å¦ä¸è¾“å…¥å£ä»¤å°±ç”¨ssh登录localhost:
+ $ ssh localhost +

+ +

+ 如果ä¸è¾“å…¥å£ä»¤å°±æ— æ³•ç”¨ssh登陆localhost,执行下é¢çš„命令:
+ $ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
+ $ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys +

+
+ +
+ 执行 + +

+ æ ¼å¼åŒ–一个新的分布å¼æ–‡ä»¶ç³»ç»Ÿï¼š
+ $ bin/hadoop namenode -format +

+ +

+ å¯åŠ¨Hadoop守护进程:
+ $ bin/start-all.sh +

+ +

Hadoop守护进程的日志写入到 + ${HADOOP_LOG_DIR} 目录 (默认是 + ${HADOOP_HOME}/logs).

+ +

æµè§ˆNameNodeå’ŒJobTracker的网络接å£ï¼Œå®ƒä»¬çš„地å€é»˜è®¤ä¸ºï¼š

+ + +

+ 将输入文件拷è´åˆ°åˆ†å¸ƒå¼æ–‡ä»¶ç³»ç»Ÿï¼š
+ $ bin/hadoop fs -put conf input +

+ +

+ è¿è¡Œå‘行版æ供的示例程åºï¼š
+ + $ bin/hadoop jar hadoop-*-examples.jar grep input output 'dfs[a-z.]+' + +

+ +

查看输出文件:

+

+ 将输出文件从分布å¼æ–‡ä»¶ç³»ç»Ÿæ‹·è´åˆ°æœ¬åœ°æ–‡ä»¶ç³»ç»ŸæŸ¥çœ‹ï¼š
+ $ bin/hadoop fs -get output output
+ $ cat output/* +

+

或者

+

+ 在分布å¼æ–‡ä»¶ç³»ç»Ÿä¸ŠæŸ¥çœ‹è¾“出文件:
+ $ bin/hadoop fs -cat output/* +

+ +

+ 完æˆå…¨éƒ¨æ“作åŽï¼Œåœæ­¢å®ˆæŠ¤è¿›ç¨‹ï¼š
+ $ bin/stop-all.sh +

+
+
+ +
+ 完全分布å¼æ¨¡å¼çš„æ“作方法 + +

关于æ­å»ºå®Œå…¨åˆ†å¸ƒå¼æ¨¡å¼çš„,有实际æ„义的集群的资料å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚

+
+ +

+ Java与JNI是Sun Microsystems, Inc.在美国以åŠå…¶ä»–国家地区的商标或注册商标。 +

+ + + +
diff --git a/src/docs/cn/src/documentation/content/xdocs/site.xml b/src/docs/cn/src/documentation/content/xdocs/site.xml new file mode 100644 index 00000000000..329186df68d --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/site.xml @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/content/xdocs/streaming.xml b/src/docs/cn/src/documentation/content/xdocs/streaming.xml new file mode 100644 index 00000000000..221205e13f1 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/streaming.xml @@ -0,0 +1,618 @@ + + + + + + + +
+Hadoop Streaming +Content-Type +text/html; +utf-8 +
+ +
+Hadoop Streaming +

+Hadoop streaming是Hadoop的一个工具, + 它帮助用户创建和è¿è¡Œä¸€ç±»ç‰¹æ®Šçš„map/reduce作业, + 这些特殊的map/reduce作业是由一些å¯æ‰§è¡Œæ–‡ä»¶æˆ–脚本文件充当mapper或者reducer。例如: +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper /bin/cat \ + -reducer /bin/wc + +
+ +
+Streamingå·¥ä½œåŽŸç† +

+在上é¢çš„例å­é‡Œï¼Œmapperå’Œreducer都是å¯æ‰§è¡Œæ–‡ä»¶ï¼Œå®ƒä»¬ä»Žæ ‡å‡†è¾“入读入数æ®ï¼ˆä¸€è¡Œä¸€è¡Œè¯»ï¼‰ï¼Œ +并把计算结果å‘给标准输出。Streaming工具会创建一个Map/Reduce作业, +并把它å‘é€ç»™åˆé€‚的集群,åŒæ—¶ç›‘视这个作业的整个执行过程。 +

+如果一个å¯æ‰§è¡Œæ–‡ä»¶è¢«ç”¨äºŽmapper,则在mapperåˆå§‹åŒ–时, +æ¯ä¸€ä¸ªmapper任务会把这个å¯æ‰§è¡Œæ–‡ä»¶ä½œä¸ºä¸€ä¸ªå•ç‹¬çš„进程å¯åŠ¨ã€‚ +mapper任务è¿è¡Œæ—¶ï¼Œå®ƒæŠŠè¾“入切分æˆè¡Œå¹¶æŠŠæ¯ä¸€è¡Œæ供给å¯æ‰§è¡Œæ–‡ä»¶è¿›ç¨‹çš„标准输入。 +åŒæ—¶ï¼Œmapper收集å¯æ‰§è¡Œæ–‡ä»¶è¿›ç¨‹æ ‡å‡†è¾“出的内容,并把收到的æ¯ä¸€è¡Œå†…容转化æˆkey/value对,作为mapper的输出。 +默认情况下,一行中第一个tab之å‰çš„部分作为key,之åŽçš„(ä¸åŒ…括tab)作为value。 +如果没有tab,整行作为key值,value值为null。ä¸è¿‡ï¼Œè¿™å¯ä»¥å®šåˆ¶ï¼Œåœ¨ä¸‹æ–‡ä¸­å°†ä¼šè®¨è®ºå¦‚何自定义keyå’Œvalue的切分方å¼ã€‚ +

+

如果一个å¯æ‰§è¡Œæ–‡ä»¶è¢«ç”¨äºŽreducer,æ¯ä¸ªreducer任务会把这个å¯æ‰§è¡Œæ–‡ä»¶ä½œä¸ºä¸€ä¸ªå•ç‹¬çš„进程å¯åŠ¨ã€‚ +Reducer任务è¿è¡Œæ—¶ï¼Œå®ƒæŠŠè¾“入切分æˆè¡Œå¹¶æŠŠæ¯ä¸€è¡Œæ供给å¯æ‰§è¡Œæ–‡ä»¶è¿›ç¨‹çš„标准输入。 +åŒæ—¶ï¼Œreducer收集å¯æ‰§è¡Œæ–‡ä»¶è¿›ç¨‹æ ‡å‡†è¾“出的内容,并把æ¯ä¸€è¡Œå†…容转化æˆkey/value对,作为reducer的输出。 +默认情况下,一行中第一个tab之å‰çš„部分作为key,之åŽçš„(ä¸åŒ…括tab)作为value。在下文中将会讨论如何自定义keyå’Œvalue的切分方å¼ã€‚ +

+这是Map/Reduce框架和streaming mapper/reducer之间的基本通信å议。 +

+用户也å¯ä»¥ä½¿ç”¨java类作为mapper或者reducer。上é¢çš„例å­ä¸Žè¿™é‡Œçš„代ç ç­‰ä»·ï¼š +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper org.apache.hadoop.mapred.lib.IdentityMapper \ + -reducer /bin/wc + +

用户å¯ä»¥è®¾å®šstream.non.zero.exit.is.failure +true 或false æ¥è¡¨æ˜Žstreaming task的返回值éžé›¶æ—¶æ˜¯ +Failure +还是Success。默认情况,streaming task返回éžé›¶æ—¶è¡¨ç¤ºå¤±è´¥ã€‚ +

+
+ +
+将文件打包到æ交的作业中 +

+任何å¯æ‰§è¡Œæ–‡ä»¶éƒ½å¯ä»¥è¢«æŒ‡å®šä¸ºmapper/reducer。这些å¯æ‰§è¡Œæ–‡ä»¶ä¸éœ€è¦äº‹å…ˆå­˜æ”¾åœ¨é›†ç¾¤ä¸Šï¼› +如果在集群上还没有,则需è¦ç”¨-file选项让framework把å¯æ‰§è¡Œæ–‡ä»¶ä½œä¸ºä½œä¸šçš„一部分,一起打包æ交。例如: +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper myPythonScript.py \ + -reducer /bin/wc \ + -file myPythonScript.py + +

+上é¢çš„例å­æ述了一个用户把å¯æ‰§è¡Œpython文件作为mapper。 +其中的选项“-file myPythonScirpt.pyâ€ä½¿å¯æ‰§è¡Œpython文件作为作业æ交的一部分被上传到集群的机器上。 +

+

+除了å¯æ‰§è¡Œæ–‡ä»¶å¤–,其他mapper或reducer需è¦ç”¨åˆ°çš„辅助文件(比如字典,é…置文件等)也å¯ä»¥ç”¨è¿™ç§æ–¹å¼æ‰“包上传。例如: +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper myPythonScript.py \ + -reducer /bin/wc \ + -file myPythonScript.py \ + -file myDictionary.txt + +
+ +
+Streaming选项与用法 + +
+åªä½¿ç”¨Mapper的作业 +

+有时åªéœ€è¦map函数处ç†è¾“入数æ®ã€‚这时åªéœ€æŠŠmapred.reduce.tasks设置为零,Map/reduce框架就ä¸ä¼šåˆ›å»ºreducer任务,mapper任务的输出就是整个作业的最终输出。 +

+为了åšåˆ°å‘下兼容,Hadoop Streaming也支æŒâ€œ-reduce Noneâ€é€‰é¡¹ï¼Œå®ƒä¸Žâ€œ-jobconf mapred.reduce.tasks=0â€ç­‰ä»·ã€‚ +

+
+ +
+为作业指定其他æ’件 +

+和其他普通的Map/Reduce作业一样,用户å¯ä»¥ä¸ºstreaming作业指定其他æ’件: +

+ + -inputformat JavaClassName + -outputformat JavaClassName + -partitioner JavaClassName + -combiner JavaClassName + +

用于处ç†è¾“入格å¼çš„ç±»è¦èƒ½è¿”回Text类型的key/value对。如果ä¸æŒ‡å®šè¾“入格å¼ï¼Œåˆ™é»˜è®¤ä¼šä½¿ç”¨TextInputFormat。 +因为TextInputFormat得到的key值是LongWritable类型的(其实key值并ä¸æ˜¯è¾“入文件中的内容,而是valueå移é‡ï¼‰ï¼Œ +所以key会被丢弃,åªæŠŠvalue用管é“æ–¹å¼å‘ç»™mapper。 +

+用户æ供的定义输出格å¼çš„类需è¦èƒ½å¤Ÿå¤„ç†Text类型的key/value对。如果ä¸æŒ‡å®šè¾“出格å¼ï¼Œåˆ™é»˜è®¤ä¼šä½¿ç”¨TextOutputFormat类。 +

+
+ +
+Hadoop Streaming中的大文件和档案 + +

任务使用-cacheFileå’Œ-cacheArchive选项在集群中分å‘文件和档案,选项的å‚数是用户已上传至HDFS的文件或档案的URI。这些文件和档案在ä¸åŒçš„作业间缓存。用户å¯ä»¥é€šè¿‡fs.default.name.configé…ç½®å‚数的值得到文件所在的hostå’Œfs_port。 +

+

+这个是使用-cacheFile选项的例å­ï¼š +

+ +-cacheFile hdfs://host:fs_port/user/testfile.txt#testlink + +

在上é¢çš„例å­é‡Œï¼Œurl中#åŽé¢çš„部分是建立在任务当å‰å·¥ä½œç›®å½•ä¸‹çš„符å·é“¾æŽ¥çš„å字。这里的任务的当å‰å·¥ä½œç›®å½•ä¸‹æœ‰ä¸€ä¸ªâ€œtestlinkâ€ç¬¦å·é“¾æŽ¥ï¼Œå®ƒæŒ‡å‘testfile.txt文件在本地的拷è´ã€‚如果有多个文件,选项å¯ä»¥å†™æˆï¼š +

+ +-cacheFile hdfs://host:fs_port/user/testfile1.txt#testlink1 -cacheFile hdfs://host:fs_port/user/testfile2.txt#testlink2 + +

+-cacheArchive选项用于把jar文件拷è´åˆ°ä»»åŠ¡å½“å‰å·¥ä½œç›®å½•å¹¶è‡ªåŠ¨æŠŠjar文件解压缩。例如: +

+ +-cacheArchive hdfs://host:fs_port/user/testfile.jar#testlink3 + +

+在上é¢çš„例å­ä¸­ï¼Œtestlink3是当å‰å·¥ä½œç›®å½•ä¸‹çš„符å·é“¾æŽ¥ï¼Œå®ƒæŒ‡å‘testfile.jar解压åŽçš„目录。 +

+

+下é¢æ˜¯ä½¿ç”¨-cacheArchive选项的å¦ä¸€ä¸ªä¾‹å­ã€‚其中,input.txt文件有两行内容,分别是两个文件的å字:testlink/cache.txtå’Œtestlink/cache2.txt。“testlinkâ€æ˜¯æŒ‡å‘档案目录(jar文件解压åŽçš„目录)的符å·é“¾æŽ¥ï¼Œè¿™ä¸ªç›®å½•ä¸‹æœ‰â€œcache.txtâ€å’Œâ€œcache2.txtâ€ä¸¤ä¸ªæ–‡ä»¶ã€‚ +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input "/user/me/samples/cachefile/input.txt" \ + -mapper "xargs cat" \ + -reducer "cat" \ + -output "/user/me/samples/cachefile/out" \ + -cacheArchive 'hdfs://hadoop-nn1.example.com/user/me/samples/cachefile/cachedir.jar#testlink' \ + -jobconf mapred.map.tasks=1 \ + -jobconf mapred.reduce.tasks=1 \ + -jobconf mapred.job.name="Experiment" + +$ ls test_jar/ +cache.txt cache2.txt + +$ jar cvf cachedir.jar -C test_jar/ . +added manifest +adding: cache.txt(in = 30) (out= 29)(deflated 3%) +adding: cache2.txt(in = 37) (out= 35)(deflated 5%) + +$ hadoop dfs -put cachedir.jar samples/cachefile + +$ hadoop dfs -cat /user/me/samples/cachefile/input.txt +testlink/cache.txt +testlink/cache2.txt + +$ cat test_jar/cache.txt +This is just the cache string + +$ cat test_jar/cache2.txt +This is just the second cache string + +$ hadoop dfs -ls /user/me/samples/cachefile/out +Found 1 items +/user/me/samples/cachefile/out/part-00000 <r 3> 69 + +$ hadoop dfs -cat /user/me/samples/cachefile/out/part-00000 +This is just the cache string +This is just the second cache string + + +
+ +
+为作业指定附加é…ç½®å‚æ•° +

+用户å¯ä»¥ä½¿ç”¨â€œ-jobconf <n>=<v>â€å¢žåŠ ä¸€äº›é…ç½®å˜é‡ã€‚例如: +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper org.apache.hadoop.mapred.lib.IdentityMapper\ + -reducer /bin/wc \ + -jobconf mapred.reduce.tasks=2 + +

+上é¢çš„例å­ä¸­ï¼Œ-jobconf mapred.reduce.tasks=2表明用两个reducer完æˆä½œä¸šã€‚ +

+

+关于jobconfå‚数的更多细节å¯ä»¥å‚考:hadoop-default.html

+
+ +
+其他选项 +

+Streaming 作业的其他选项如下表: +

+ + + + + + + + + + + + + +
选项å¯é€‰/å¿…é¡»æè¿°
-cluster name å¯é€‰ 在本地Hadoop集群与一个或多个远程集群间切æ¢
-dfs host:port or local å¯é€‰ 覆盖作业的HDFSé…ç½®
-jt host:port or local å¯é€‰ 覆盖作业的JobTrackeré…ç½®
-additionalconfspec specfile å¯é€‰ 用一个类似于hadoop-site.xmlçš„XML文件ä¿å­˜æ‰€æœ‰é…置,从而ä¸éœ€è¦ç”¨å¤šä¸ª"-jobconf name=value"类型的选项å•ç‹¬ä¸ºæ¯ä¸ªé…ç½®å˜é‡èµ‹å€¼
-cmdenv name=value å¯é€‰ 传递环境å˜é‡ç»™streaming命令
-cacheFile fileNameURI å¯é€‰ 指定一个上传到HDFS的文件
-cacheArchive fileNameURI å¯é€‰ 指定一个上传到HDFSçš„jar文件,这个jar文件会被自动解压缩到当å‰å·¥ä½œç›®å½•ä¸‹
-inputreader JavaClassName å¯é€‰ 为了å‘下兼容:指定一个record reader类(而ä¸æ˜¯input format类)
-verbose å¯é€‰ 详细输出
+

+使用-cluster <name>实现“本地â€Hadoop和一个或多个远程Hadoop集群间切æ¢ã€‚默认情况下,使用hadoop-default.xmlå’Œhadoop-site.xml;当使用-cluster <name>选项时,会使用$HADOOP_HOME/conf/hadoop-<name>.xml。 +

+

+下é¢çš„选项改å˜temp目录: +

+ + -jobconf dfs.data.dir=/tmp + +

+下é¢çš„选项指定其他本地temp目录: +

+ + -jobconf mapred.local.dir=/tmp/local + -jobconf mapred.system.dir=/tmp/system + -jobconf mapred.temp.dir=/tmp/temp + +

+更多有关jobconf的细节请å‚考:http://wiki.apache.org/hadoop/JobConfFile +

+在streaming命令中设置环境å˜é‡ï¼š +

+ +-cmdenv EXAMPLE_DIR=/home/example/dictionaries/ + +
+
+ +
+å…¶ä»–ä¾‹å­ + +
+使用自定义的方法切分行æ¥å½¢æˆKey/Value对 +

+之å‰å·²ç»æ到,当Map/Reduce框架从mapper的标准输入读å–一行时,它把这一行切分为key/value对。 +在默认情况下,æ¯è¡Œç¬¬ä¸€ä¸ªtab符之å‰çš„部分作为key,之åŽçš„部分作为value(ä¸åŒ…括tab符)。 +

+

+但是,用户å¯ä»¥è‡ªå®šä¹‰ï¼Œå¯ä»¥æŒ‡å®šåˆ†éš”符是其他字符而ä¸æ˜¯é»˜è®¤çš„tab符,或者指定在第n(n>=1)个分割符处分割而ä¸æ˜¯é»˜è®¤çš„第一个。例如: +

+ + +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper org.apache.hadoop.mapred.lib.IdentityMapper \ + -reducer org.apache.hadoop.mapred.lib.IdentityReducer \ + -jobconf stream.map.output.field.separator=. \ + -jobconf stream.num.map.output.key.fields=4 + +

+在上é¢çš„例å­ï¼Œâ€œ-jobconf stream.map.output.field.separator=.â€æŒ‡å®šâ€œ.â€ä½œä¸ºmap输出内容的分隔符,并且从在第四个“.â€ä¹‹å‰çš„部分作为key,之åŽçš„部分作为value(ä¸åŒ…括这第四个“.â€ï¼‰ã€‚ +如果一行中的“.â€å°‘于四个,则整行的内容作为key,value设为空的Text对象(就åƒè¿™æ ·åˆ›å»ºäº†ä¸€ä¸ªText:new Text(""))。 +

+åŒæ ·ï¼Œç”¨æˆ·å¯ä»¥ä½¿ç”¨â€œ-jobconf stream.reduce.output.field.separator=SEPâ€å’Œâ€œ-jobconf stream.num.reduce.output.fields=NUMâ€æ¥æŒ‡å®šreduce输出的行中,第几个分隔符处分割keyå’Œvalue。 +

+
+ + +
+一个实用的Partitionerç±»<!--A Useful Partitioner Class--> (二次排åºï¼Œ-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner 选项) +

+Hadoop有一个工具类org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner, +它在应用程åºä¸­å¾ˆæœ‰ç”¨ã€‚Map/reduce框架用这个类切分map的输出, +切分是基于key值的å‰ç¼€ï¼Œè€Œä¸æ˜¯æ•´ä¸ªkey。例如: +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper org.apache.hadoop.mapred.lib.IdentityMapper \ + -reducer org.apache.hadoop.mapred.lib.IdentityReducer \ + -partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \ + -jobconf stream.map.output.field.separator=. \ + -jobconf stream.num.map.output.key.fields=4 \ + -jobconf map.output.key.field.separator=. \ + -jobconf num.key.fields.for.partition=2 \ + -jobconf mapred.reduce.tasks=12 + +

+其中,-jobconf stream.map.output.field.separator=. å’Œ-jobconf stream.num.map.output.key.fields=4是å‰æ–‡ä¸­çš„例å­ã€‚Streaming用这两个å˜é‡æ¥å¾—到mapperçš„key/value对。 +

+上é¢çš„Map/Reduce 作业中map输出的key一般是由“.â€åˆ†å‰²æˆçš„å››å—。但是因为使用了 +-jobconf num.key.fields.for.partition=2 +选项,所以Map/Reduce框架使用keyçš„å‰ä¸¤å—æ¥åˆ‡åˆ†map的输出。其中, +-jobconf map.output.key.field.separator=. +指定了这次切分使用的key的分隔符。这样å¯ä»¥ä¿è¯åœ¨æ‰€æœ‰key/value对中, +key值å‰ä¸¤ä¸ªå—值相åŒçš„所有key被分到一组,分é…给一个reducer。 +

+è¿™ç§é«˜æ•ˆçš„方法等价于指定å‰ä¸¤å—作为主键,åŽä¸¤å—作为副键。 +主键用于切分å—,主键和副键的组åˆç”¨äºŽæŽ’åºã€‚一个简å•çš„示例如下: +

+

+Map的输出(key)

+11.12.1.2 +11.14.2.3 +11.11.4.1 +11.12.1.1 +11.14.2.2 + + +

+切分给3个reducer(å‰ä¸¤å—的值用于切分)

+11.11.4.1 +----------- +11.12.1.2 +11.12.1.1 +----------- +11.14.2.3 +11.14.2.2 + +

+在æ¯ä¸ªåˆ‡åˆ†åŽçš„组内排åºï¼ˆå››ä¸ªå—的值都用于排åºï¼‰ +

+11.11.4.1 +----------- +11.12.1.1 +11.12.1.2 +----------- +11.14.2.2 +11.14.2.3 + +
+ +
+ HadoopèšåˆåŠŸèƒ½åŒ…的使用(-reduce aggregate 选项) +

+Hadoop有一个工具包“Aggregateâ€ï¼ˆ +https://svn.apache.org/repos/asf/hadoop/core/trunk/src/java/org/apache/hadoop/mapred/lib/aggregate)。 +“Aggregateâ€æ供一个特殊的reducer类和一个特殊的combiner类, +并且有一系列的“èšåˆå™¨â€ï¼ˆâ€œaggregatorâ€ï¼‰ï¼ˆä¾‹å¦‚“sumâ€ï¼Œâ€œmaxâ€ï¼Œâ€œminâ€ç­‰ï¼‰ç”¨äºŽèšåˆä¸€ç»„valueçš„åºåˆ—。 +用户å¯ä»¥ä½¿ç”¨Aggregate定义一个mapperæ’件类, +这个类用于为mapper输入的æ¯ä¸ªkey/value对产生“å¯èšåˆé¡¹â€ã€‚ +combiner/reducer利用适当的èšåˆå™¨èšåˆè¿™äº›å¯èšåˆé¡¹ã€‚ +

+è¦ä½¿ç”¨Aggregate,åªéœ€æŒ‡å®šâ€œ-reducer aggregateâ€ï¼š

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper myAggregatorForKeyCount.py \ + -reducer aggregate \ + -file myAggregatorForKeyCount.py \ + -jobconf mapred.reduce.tasks=12 + +

+python程åºmyAggregatorForKeyCount.py例å­ï¼š +

+ +#!/usr/bin/python + +import sys; + +def generateLongCountToken(id): + return "LongValueSum:" + id + "\t" + "1" + +def main(argv): + line = sys.stdin.readline(); + try: + while line: + line = line[:-1]; + fields = line.split("\t"); + print generateLongCountToken(fields[0]); + line = sys.stdin.readline(); + except "end of file": + return None +if __name__ == "__main__": + main(sys.argv) + +
+ +
+字段的选å–(类似于unix中的 'cut' 命令) +

+Hadoop的工具类org.apache.hadoop.mapred.lib.FieldSelectionMapReduce帮助用户高效处ç†æ–‡æœ¬æ•°æ®ï¼Œ +å°±åƒunix中的“cutâ€å·¥å…·ã€‚工具类中的map函数把输入的key/value对看作字段的列表。 +用户å¯ä»¥æŒ‡å®šå­—段的分隔符(默认是tab), +å¯ä»¥é€‰æ‹©å­—段列表中任æ„一段(由列表中一个或多个字段组æˆï¼‰ä½œä¸ºmap输出的key或者value。 +åŒæ ·ï¼Œå·¥å…·ç±»ä¸­çš„reduce函数也把输入的key/value对看作字段的列表,用户å¯ä»¥é€‰å–ä»»æ„一段作为reduce输出的key或value。例如: +

+ +$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input myInputDirs \ + -output myOutputDir \ + -mapper org.apache.hadoop.mapred.lib.FieldSelectionMapReduce\ + -reducer org.apache.hadoop.mapred.lib.FieldSelectionMapReduce\ + -partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \ + -jobconf map.output.key.field.separa=. \ + -jobconf num.key.fields.for.partition=2 \ + -jobconf mapred.data.field.separator=. \ + -jobconf map.output.key.value.fields.spec=6,5,1-3:0- \ + -jobconf reduce.output.key.value.fields.spec=0-2:5- \ + -jobconf mapred.reduce.tasks=12 + +

+选项“-jobconf map.output.key.value.fields.spec=6,5,1-3:0-â€æŒ‡å®šäº†å¦‚何为map的输出选å–keyå’Œvalue。Key选å–规则和value选å–规则由“:â€åˆ†å‰²ã€‚ +在这个例å­ä¸­ï¼Œmap输出的key由字段6,5,1,2å’Œ3组æˆã€‚输出的value由所有字段组æˆï¼ˆâ€œ0-â€æŒ‡å­—段0以åŠä¹‹åŽæ‰€æœ‰å­—段)。 +

+

+选项“-jobconf reduce.output.key.value.fields.spec=0-2:0-â€ï¼ˆè¯‘者注:此处应为â€0-2:5-“)指定如何为reduce的输出选å–value。 +本例中,reduce的输出的key将包å«å­—段0,1,2(对应于原始的字段6,5,1)。 +reduce输出的value将包å«èµ·è‡ªå­—段5的所有字段(对应于所有的原始字段)。 +

+
+
+ +
+常è§é—®é¢˜ + +
+我该怎样使用Hadoop Streamingè¿è¡Œä¸€ç»„独立(相关)的任务呢? +

+多数情况下,你ä¸éœ€è¦Map Reduce的全部功能, +而åªéœ€è¦è¿è¡ŒåŒä¸€ç¨‹åºçš„多个实例,或者使用ä¸åŒæ•°æ®ï¼Œæˆ–者在相åŒæ•°æ®ä¸Šä½¿ç”¨ä¸åŒçš„å‚数。 +ä½ å¯ä»¥é€šè¿‡Hadoop Streamingæ¥å®žçŽ°ã€‚

+ +
+ +
+如何处ç†å¤šä¸ªæ–‡ä»¶ï¼Œå…¶ä¸­æ¯ä¸ªæ–‡ä»¶ä¸€ä¸ªmap? +

+例如这样一个问题,在集群上压缩(zipping)一些文件,你å¯ä»¥ä½¿ç”¨ä»¥ä¸‹å‡ ç§æ–¹æ³•ï¼š

    +
  1. 使用Hadoop Streaming和用户编写的mapper脚本程åºï¼š
      +
    • 生æˆä¸€ä¸ªæ–‡ä»¶ï¼Œæ–‡ä»¶ä¸­åŒ…å«æ‰€æœ‰è¦åŽ‹ç¼©çš„文件在HDFS上的完整路径。æ¯ä¸ªmap 任务获得一个路径å作为输入。
    • +
    • 创建一个mapper脚本程åºï¼Œå®žçŽ°å¦‚下功能:获得文件å,把该文件拷è´åˆ°æœ¬åœ°ï¼ŒåŽ‹ç¼©è¯¥æ–‡ä»¶å¹¶æŠŠå®ƒå‘到期望的输出目录。
    • +
  2. +
  3. 使用现有的Hadoop框架:
      +
    • 在main函数中添加如下命令: + + FileOutputFormat.setCompressOutput(conf, true); + FileOutputFormat.setOutputCompressorClass(conf, org.apache.hadoop.io.compress.GzipCodec.class); + conf.setOutputFormat(NonSplitableTextInputFormat.class); + conf.setNumReduceTasks(0); +
    • +
    • 编写map函数: + + + public void map(WritableComparable key, Writable value, + OutputCollector output, + Reporter reporter) throws IOException { + output.collect((Text)value, null); + } +
    • +
    • 注æ„输出的文件å和原文件åä¸åŒ
    • +
  4. +
+
+ +
+应该使用多少个reducer? +

+请å‚考Hadoop Wiki:Reducer +

+
+ +
+ +如果在Shell脚本里设置一个别å,并放在-mapper之åŽï¼ŒStreaming会正常è¿è¡Œå—? +例如,alias cl='cut -fl',-mapper "cl"会è¿è¡Œæ­£å¸¸å—? + +

+脚本里无法使用别å,但是å…许å˜é‡æ›¿æ¢ï¼Œä¾‹å¦‚: +

+ +$ hadoop dfs -cat samples/student_marks +alice 50 +bruce 70 +charlie 80 +dan 75 + +$ c2='cut -f2'; $HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \ + -input /user/me/samples/student_marks + -mapper \"$c2\" -reducer 'cat' + -output /user/me/samples/student_out + -jobconf mapred.job.name='Experiment' + +$ hadoop dfs -ls samples/student_out +Found 1 items/user/me/samples/student_out/part-00000 <r 3> 16 + +$ hadoop dfs -cat samples/student_out/part-00000 +50 +70 +75 +80 + +
+ +
+ +我å¯ä»¥ä½¿ç”¨UNIX pipeså—?例如 –mapper "cut –fl | set s/foo/bar/g"管用么? + +

+现在ä¸æ”¯æŒï¼Œè€Œä¸”会给出错误信æ¯â€œjava.io.IOException: Broken pipeâ€ã€‚这或许是一个bug,需è¦è¿›ä¸€æ­¥ç ”究。 +

+
+ +
+在streaming作业中用-file选项è¿è¡Œä¸€ä¸ª<strong>分布å¼çš„超大å¯æ‰§è¡Œæ–‡ä»¶ï¼ˆä¾‹å¦‚,3.6G)</strong>时, +我得到了一个错误信æ¯â€œNo space left on deviceâ€ã€‚如何解决? + +

+é…ç½®å˜é‡stream.tmpdir指定了一个目录,在这个目录下è¦è¿›è¡Œæ‰“jar包的æ“作。stream.tmpdir的默认值是/tmp,你需è¦å°†è¿™ä¸ªå€¼è®¾ç½®ä¸ºä¸€ä¸ªæœ‰æ›´å¤§ç©ºé—´çš„目录: +

+ +-jobconf stream.tmpdir=/export/bigspace/... + +
+ +
+如何设置多个输入目录? +

+å¯ä»¥ä½¿ç”¨å¤šä¸ª-input选项设置多个输入目录: +

+ hadoop jar hadoop-streaming.jar -input '/user/foo/dir1' -input '/user/foo/dir2' + +
+ +
+如何生æˆgzipæ ¼å¼çš„输出文件? +

+除了纯文本格å¼çš„输出,你还å¯ä»¥ç”Ÿæˆgzip文件格å¼çš„输出,你åªéœ€è®¾ç½®streaming作业中的选项‘-jobconf mapred.output.compress=true -jobconf mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCode’。 +

+
+ +
+Streaming中如何自定义input/output format? +

+至少在Hadoop 0.14版本以å‰ï¼Œä¸æ”¯æŒå¤šä¸ªjar文件。所以当指定自定义的类时,你è¦æŠŠä»–们和原有的streaming jar打包在一起,并用这个自定义的jar包替æ¢é»˜è®¤çš„hadoop streaming jar包。 +

+
+ +
+Streaming如何解æžXML文档? +

+ä½ å¯ä»¥ä½¿ç”¨StreamXmlRecordReaderæ¥è§£æžXML文档。 +

+ +hadoop jar hadoop-streaming.jar -inputreader "StreamXmlRecord,begin=BEGIN_STRING,end=END_STRING" ..... (rest of the command) + +

+Map任务会把BEGIN_STRINGå’ŒEND_STRING之间的部分看作一æ¡è®°å½•ã€‚ +

+
+ +
+在streaming应用程åºä¸­å¦‚何更新计数器? +

+streaming进程能够使用stderrå‘出计数器信æ¯ã€‚ +reporter:counter:<group>,<counter>,<amount> +应该被å‘é€åˆ°stderræ¥æ›´æ–°è®¡æ•°å™¨ã€‚ +

+
+
+如何更新streaming应用程åºçš„状æ€ï¼Ÿ +

+streaming进程能够使用stderrå‘出状æ€ä¿¡æ¯ã€‚ +reporter:status:<message> è¦è¢«å‘é€åˆ°stderræ¥è®¾ç½®çŠ¶æ€ã€‚ +

+
+ +
+ +
diff --git a/src/docs/cn/src/documentation/content/xdocs/tabs.xml b/src/docs/cn/src/documentation/content/xdocs/tabs.xml new file mode 100644 index 00000000000..83e53efc072 --- /dev/null +++ b/src/docs/cn/src/documentation/content/xdocs/tabs.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/resources/images/architecture.gif b/src/docs/cn/src/documentation/resources/images/architecture.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d84a23b07a3f326f8b2a3eb912192048d15733c GIT binary patch literal 15461 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 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/favicon.ico b/src/docs/cn/src/documentation/resources/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..161bcf7841cb95d326d9729fb0000941cef010d2 GIT binary patch literal 766 zcmcIiyKVw85Znt$i7TjRC~{@~0Yy+;gB1ES`4%kk0ioT3FQGA2+AEUc3QLrfNHkYO z+061d+ZUu%tZ%$Kp7HuDnJB}^^FC?p?uZ7+Pe2Y#fQ-7Bi7d41VIe}X_LMNAB^)TsBsHWP6w-$U*}emq-5YDhJteeZ$Sa@ literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/hadoop-logo-big.jpg b/src/docs/cn/src/documentation/resources/images/hadoop-logo-big.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c6996cdcb0ed8b4115aab112b8a411f25f165f6 GIT binary patch literal 127869 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%0D9RC&~b8uzf}P}V$4?^SL3jy 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 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/hadoop-logo.jpg b/src/docs/cn/src/documentation/resources/images/hadoop-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..809525d9f158f6163c7692b5e317153ae68bf23f GIT binary patch literal 9443 zcmbVxWmFv9vUU$H!6AX*7GMY@L4yZLuwVlTGLYad8Qcj3LIS}DcOBeaLvRR?;4rwm zyMB}Rob#S@@1O79yLHfSiDX8@`P$Wf;~i05zl zbD#x)@y}-yP-8pF5*6_;uYZk_#&(7#465dKj&=^_b{`l7xt{_&PoD}1KjjtX;bB1a z&-jI(3IPCm8t5OV2)6lRBay)+ejE|3xo=r&XIgcneFCWhzCm>v0 z+-8J|gFk*OJAGr`Dtd?V6vn5D{E zDImZ1S$GZY{c!Q_KcJ*~$ohzlode9rFCh3_NLX6tM0!~(E;BD=pTf}oH{N{~z6I8UKhXX{ z_CEvW_kTk6H?V)>ngZ^jgHW4?P69{(CwbSh4!nH?MYUDNbyv?KckJAy&#lP~t zIfs~$AFDq7t%p>xLL?;?Di}p-qL)CXc}iH02g@Xw!$Qr1+dU`|lx&$B!+P{H zYwP_BJrwqpw|oa!vAMDad;+miVui8y0EVV2g=+z=B zRp!A0-4ekr#u?cHoXD1L-W{78Z|p5U#%71eElMpDLnZipJhr9`

$=|}3K>raVyd0jn4a}r)A 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 cFa54ek;oIKkbLkl^m_THMn6 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 VCSzQ#bsV@bu6RFQOict3{XfPQuL=MF literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/hdfsdatanodes.odg b/src/docs/cn/src/documentation/resources/images/hdfsdatanodes.odg new file mode 100644 index 0000000000000000000000000000000000000000..e5d922757192f9928961e2458b0fa8d968d9133c GIT binary patch literal 37296 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 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/hdfsdatanodes.png b/src/docs/cn/src/documentation/resources/images/hdfsdatanodes.png new file mode 100644 index 0000000000000000000000000000000000000000..40ea2ec9d1cc164fba4f1ce3d254e46a5ca66361 GIT binary patch literal 30012 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 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skinconf.xml b/src/docs/cn/src/documentation/skinconf.xml new file mode 100644 index 00000000000..e40b8a09156 --- /dev/null +++ b/src/docs/cn/src/documentation/skinconf.xml @@ -0,0 +1,346 @@ + + + + + + + + + + + + true + + false + + true + + true + + + true + + + true + + + true + + + false + + + true + + + Hadoop + Scalable Computing Platform + http://hadoop.apache.org/core/ + images/core-logo.gif + + + Hadoop + Apache Hadoop + http://hadoop.apache.org/ + images/hadoop-logo.jpg + + + + + + + images/favicon.ico + + + 2009 + The Apache Software Foundation. + http://www.apache.org/licenses/ + + + + + + + + + + + + + + + + + + + p.quote { + margin-left: 2em; + padding: .5em; + background-color: #f0f0f0; + font-family: monospace; + } + + + + + + + + + + + + + + + + + + + + + + + + + 1in + 1in + 1.25in + 1in + + + + false + + + false + + + + + + Built with Apache Forrest + http://forrest.apache.org/ + images/built-with-forrest-button.png + 88 + 31 + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/css/forrest.css.xslt b/src/docs/cn/src/documentation/skins/common/css/forrest.css.xslt new file mode 100644 index 00000000000..fbfa020f60f --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/css/forrest.css.xslt @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + +/* ==================== aural ============================ */ + +@media aural { + h1, h2, h3, h4, h5, h6 { voice-family: paul, male; stress: 20; richness: 90 } + h1 { pitch: x-low; pitch-range: 90 } + h2 { pitch: x-low; pitch-range: 80 } + h3 { pitch: low; pitch-range: 70 } + h4 { pitch: medium; pitch-range: 60 } + h5 { pitch: medium; pitch-range: 50 } + h6 { pitch: medium; pitch-range: 40 } + li, dt, dd { pitch: medium; richness: 60 } + dt { stress: 80 } + pre, code, tt { pitch: medium; pitch-range: 0; stress: 0; richness: 80 } + em { pitch: medium; pitch-range: 60; stress: 60; richness: 50 } + strong { pitch: medium; pitch-range: 60; stress: 90; richness: 90 } + dfn { pitch: high; pitch-range: 60; stress: 60 } + s, strike { richness: 0 } + i { pitch: medium; pitch-range: 60; stress: 60; richness: 50 } + b { pitch: medium; pitch-range: 60; stress: 90; richness: 90 } + u { richness: 0 } + + :link { voice-family: harry, male } + :visited { voice-family: betty, female } + :active { voice-family: betty, female; pitch-range: 80; pitch: x-high } +} + + +a.external { + padding: 0 20px 0px 0px; + display:inline; + background-repeat: no-repeat; + background-position: center right; + background-image: url(images/external-link.gif); +} + + +/* extra-css */ + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/images/README.txt b/src/docs/cn/src/documentation/skins/common/images/README.txt new file mode 100644 index 00000000000..e0932f4a46d --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/images/README.txt @@ -0,0 +1 @@ +The images in this directory are used if the current skin lacks them. diff --git a/src/docs/cn/src/documentation/skins/common/images/add.jpg b/src/docs/cn/src/documentation/skins/common/images/add.jpg new file mode 100644 index 0000000000000000000000000000000000000000..06831eeb3ddf196c72e23557e0ed23ab5eebef14 GIT binary patch literal 1142 zcmex=8LQWSUGXZw=a9;-CH1opy?hi@Re9OjXnTmIP&sRNi|KfA6jNG!RuT!@9YtHw( z9erp2Zq<%rjVqhBF6#`j(Nz7-sP^lFKTm1Gh0D`qPDac0FaMRdT;F`zq?kW-W@pz% ze5s1wt~F!ht0dJ-6Wtq2zbVbV=fB~?vunDX+mkr&9obTxINM8acHwgGD`nz_>c8~X z#64k4<|uMwTb-nlGND71x8e8h0CS_Z??Mj^qF+we3cIj#)xArPJbFc z1J^&EzSnzGz5a8z`w3oY3k27{($?ztW&09(=ivnpp{KI7WqXY09TH4GKIhxFx{~WE za;gV-Un(Aaa&M}6?~U3j!7KUi>iU;l*gowzla$PHmbcrJ<^Kv-hZ^4yNZ?w%@WRrg z9hKMiif_BPt>>(?=HJZAb?S+a3uMc;RsFTId)L4BO>y9_%h9vu@!Dqx|QqvyOz9SIJ(F^=e;T^m(oCzw|lXRk=EsYqq%^ zT`d)L>*v{G>#v@6=iH9&5}xL?Y5R3H&Bwh9=Y-v2RZ~9aIrWlLlqS2Jh$?@c!KtzFq_@~|twFFteiZSS44jqO(VSv>5s zSk$Z3r4sR|%QU3V;-b@%!bJ@$Iu>ZHYFM=ZnC>fE$}45(-kf`P=H0v9*1LrwXLhOr z(Tqu+Dw97yVxO<^>3%?xVY_#66#K#toTr`}oRP~sdOKTC=ER@XAKDdr{M$Kf7M%Ki l%F17_Xw@h6ZS#V!{>|Nxc>kE literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/built-with-forrest-button.png b/src/docs/cn/src/documentation/skins/common/images/built-with-forrest-button.png new file mode 100644 index 0000000000000000000000000000000000000000..4a787abe4dc7831124c5a3105d328309d671654e GIT binary patch literal 1936 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@@!3-or#C}}@QVJ!m5hWp+B{``KPNkVSB?{%4 zB^e5i1&PTSsS0lSMMbH_C5p!XSU`qIg48;emSp4?F%*}imZj$9IV6Hr>g5-upPn-{ z7N|%Aq{unHpt2}4J)?vn1ZWJ@wBY=-lJdkNkg=tCDTyVS`FXqD1Vn&(#K3xrQo&*h zA(^?U42FjK2B!K3Mr$wBh5%Ktmw5WRvR~q672y_j(|Vu{6yhxKh%9Dc;Q9c)(aAfd*^e>N}8ml8GDLnbh$Vh8yg>#P$;PF zC>QelbcQQ9twO^-_C801qj=2GblKSS!fj&e!5;2=cvDr4f*v|q3raa`n#2k(0Hfotk0b1J=Zc zVix-wb&f*FNxFAB>YkC+NOHE=$eo>CQlF6FW+Y*C$UweP(%~&@q>7f$#X#{A z;Q~QbwWpj0XSnm#bgimu&2m(IKJ4T((08AzspZ9!kdUPob@ zhUPNf9CfQG1}XglS^Z_=`jsLf7uek{k1Lkt=SCSE_Dw?nen%L4B7i^>@v~C&d=nR^FdJVP^0Cp33}tc?Gq$O(FfPpv_~AIPICFic;5W(Z>PHY@&p}`TbikKkV444Jk93Se-mtf*V{`vIwng zXu9Mqxh&@_YxVKtE1Q|E&EFj=C=gTZUe?$exv?(b$cHuUKkhedO?dx=U+Qq@<*v^rKUcg+uGXdSD-c1$LjDs$D3&%&n#_h{2#BhC!i@(`b;D9TORRq zdb5xI_xrb_^#0kXwa*@ycsr?PYU?avxGJe9GyUl7*!OiS zyFPrgF>;P=eC379dw#zycy~ibF5adl<@V%<|Ac&Q-%p5$abw8I1(|q!`K$Bs-$Ufi zn-NYN)w4{zw?yhbQXIC#@eD+l6OwziP6C9qB=6m^)Bp&s4|Xb_eY#M_>}{ahob-+F#617?*~$q0=_@T*^V)U2LV1m;&(&(TU%TRD_D(n) zkt5*A;KlgCw)x%rA4f%Q=dtWM=lnF0i|2Y{YvH!Kii;L@-PURI*lQP0-t8T_&{^nm zamG&RnUcY0o~~6qWBy(4eNK5~Ox(I2w%NP3-I + + + + + + + + + + + + + + + 0 + + + + + + fill:; + + + fill:; + + + stroke:; + + + + + + + + + 1 + -1 + + + + + 1 + -1 + + + + + 0 + - + + + + + + 0 + - + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/images/dc.svg.xslt b/src/docs/cn/src/documentation/skins/common/images/dc.svg.xslt new file mode 100644 index 00000000000..f900f2f9549 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/images/dc.svg.xslt @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/images/external-link.gif b/src/docs/cn/src/documentation/skins/common/images/external-link.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff2f7b2a0edcd149b45744fdcb0868e37143710c GIT binary patch literal 71 zcmZ?wbhEHbS8S}jHOdM}x%?#1T_hvOu zeqG%@%jEJ)+xMGqi`DhzUb?T@b*jm~qG)$k_0mNz)~?<@;qdjdiH;j0rN7>4^_4qo z5-gGTX~~LRHZje`Th!*x4E(t!-8@p`oW=c$!sDW9hig{2?%n3H_Ac9RW(;~SGaDvl^$sR zZR`Db@iJktYp>+@>&*J_Eg|S|(C5`M9bCDOPH*r!#U1(W>Vy8^PaL*AzXds>biWub zU(}P4yZpmzwcBDjUipzl)5pyRig`_Ko=%m`=yb8WdNtOQMQ9B(lQYBN8_GW% zl>aEmrT<`n&A8Xgjs3p^3-J_ z$4wvPo_u@Yw2tX2 z)6Bh-Dkn2LQ71ZDWEM_BQC5`^W#0}m1r{TqnvEkUNvx)vOBQNLKSx_zUW0yfZFz^x z0A_X|Dce6W##tA*KTW(aB2H0ZacpC_p&)@;J%w>A=HS-f2v{~6LwbXcCMrtAEF6kN zLA0@}h!JD$#0WdJZVFEKDLFfuv(i|+sc03mcmSaefwW^{L9 za%BKbVPkS{ZDnL>VIW3na%FdKa%*!SG%hgeCMR_O01x3wL_t(|oZVWDU)splMs`OQ zF>OMz+v&ElrD1S{7fDG2+fmrWtqNK}kyvE6Rz?uHgui=_2mzi0Bnw~B7vyZcUm z)i9GY&pcEgkAKi6rRXNC?Q2Fp(oU85^8fzvfarWw7}9(=Yj zo<(#H@dZNBB^Mze0<{Ofe;2JII!wbLts^H*GgKGm^VxZ@q$vpx$_ia0=|}BB9xnzN z|DY)}g4Q0ql;x_1y-nk!~Rd9nDviibl2<<5+nCV~ieB z8gv0w_zW$z?Hn)G8nmDgA%&;?&@UpsJyu$YHE0eA9KvHxno~M!`s~0msnFMHmkRqzyKm`hZo6eS0}G!~F4(zC?Ea8`M;|0$c&6#XNalv! zn+SjZa1ZZmsK84jImobk8fX-^J|AL(iZuMbDXMoFhFv}K=E3oz&$iRpmZG;doe9xR zAgw|ot$;LAObpu9@681d47*k?rBFN}O|fxaA>cpDQ;fF}72A z2B{1oom3&HcpGRl?DF%J1p4cxZQ4c32j`PNVrnE$8>05$`#_UiPGS^7qV@0)e)&jt za%1iZR<113p;VWhj(>|R;?yB{(Y5T{oxNw49r&izwri%~H>xN)JH+m}FZf{9QNwl> z_~DdN(h0U>;RETWX^&SDD24tH>a(MhUmRcdjpsQBc+M)1*tlYTI8yzHSXR>T>mAc? zhfuM^7@@!Y!~TzdAiP$EMgw>_YF43np(%ltl+e|1hjqv9oj3W<+2fVTabFv*LWzO^i+1IBQKT3o2;>Qw zt4R;8?4K@Ou_4yBv+Hd{Qx&4`x}JY$UAm}(H95V;KbbQ zPYuR`bF#*%CIgZMS1@IyQ+}L2aL$6EC4^)$1?)IVYRUQF?q1+orr0R)wp79?!}_e{Y_ii{bD=t{`Ce%gn<|V*1yDd$}+xN#IDPe(*)I;-IE+x~|J-Uk$ti z2YCa}gCmpm(=FbLK-x(v#j3drPs=|6_p})0d2rG`aG&VSx~YeRxi3oGXDk37DOc!IdT$FM+1G6MPJjF)87`8g4o;SAL8gIlK4z zdmHXVw%DBsVP}g}P(l}v+!`^DbfLv;a!!CISSOiQ5GSWH%tuXYku8zB(EA;@iN$jt zc4XZVSheBKWR-LYBKU|ZrA2265-=;@YbStOSn{+~FN=5XD*(5b)i4oaO0diV^JPl+H$gHzj-(k{U)&JBw_IqL=CGFu}c#qlB6s`NwTS>@V%nbNkZU$ z^yuDDk{!4--{8lwBlnZM{p=i7{N@86bEc}s8pK@Oa2{KUnNEsfcdkQWkk;aZ>Ix)7L zHz50K9lHm0E?{wRY5t_GPZuN{-Eeq@q_Nb$sNgcHz*|e92jHMxa#-C49Q_x={Xc3W zlH2+Ac9(HGZ8*8RzxI9&wR89WE!NMs)`pV%=J%OTJ6&;Q=U3?X_7)?}Ewy3fp8soR z=F>Mg%py~c>pwxqmZDe@_#e}Tk=y>|{>;x0;Y?F3Ilc@m{4u+L&#<1z9XdKYn>vB! z@f?NHe?!_s$T2_EKOCHY0WOvti_kG~{>6CN-bLX|(*&6?Ta%>b|9+|+LM}O0FP@gS zfQu=|(wnD|VkCO6pInHO)oRt}D;ceSTmKGiklf*P{o&qe{T*<5W605WZ+3leBD(71 z`JT);B*@NixY3Xdy(+izdN;AD3zZuyevsUod-d%HyXCjOM$(ky*wgy<=Ro<`*D$`^ z>D(y@L?v7@-;m#uCO0)sbjEI~i9vE(PxIe>j%1Gy8b!H04nD@IVLdJ0k@7%-xyhBe9vVUr`Ap8R4Lyq8FGHxPi$TY-px-2H(`i#?w^pFmO(u5{}5z%DL z$rCP3Xj0x7Lhh+49mr9vR}^&p#C>gs1LSYyqwl97udw0@;dQ^Sz=Gq+Eii=9Y|mZ&3U7 zlVi5Z`E|!ZzPt+LOgWzCw;hXt@r}cNav_~itM4tZ!osI8IUGGh@Gur~COI)2_h;~V zVXn5X<0I#)gu_b-&nDMQRZCJ@cfs+pY!?1d?Fl+?FBwt#1|g-N+|qG0@M7=abvC## zZpv{Z8~ET@j6??m3Xo%Ss;L*;U}1$Yb~+4D1r^8EGt585^X)gbeH~2>yCIiiDR5I9 zbb2PpB{#k z<=1PDxt03HM%I$!#_ZbO=Luuy`tvUw6-#Y$u#sMy9BVMRlAIv4)IzW9(3uM!yMn>j zh)iFP9OyE-l6`_3ST<+u@DDekT1%g-7E`Ip|4e;K(Z-bi4e=5WZniX7g1wlB$n z5DD|BOE^q<+WP)FQq~=ZE$W+%;{in&%U&bM#EJmhR$89-2-u5|s&!0E?WtrymrrH(D z&alT}rEU!hJ+r{Oid@=-AFxzUX6)v07%_4H4=7!wmb*`&^q(R}Ct^zu-@FIw)0AT@ zUP~rp^R@nH8RE<{%Z7Hl2uK9U6Am&cD@dH+b1KzEuD>Hqh%J(A5+|OIA3qv>X&q-^ zRYTPw;O=x*YPBN|9{bO~|NZEfm!qHOgXG+?Sh|?xYs=qfEjjv1`}@g#ejvT`xX41h z+9jHFlXOB3?=56_qZgq~nJoCb$qjTM52VcC60*Y1V~aCLzE!_}+007LU`Cc@Q@H|8 z6f!_ zI}l=O{&|09*-R)su1fWN$#xD(7o3zgzGNqxFJE3Kfxh64Gn0f&wIfHEvB(d;Nx*-r zrt}cTJxouMYuwRu%RmR7g)ywmG|s-Zxp$BC1Kxxjtza3rl|~Y$#kLzqQTxDc16D(( z>6yH51~e-2V7vIc0&~h@(eT^N0sfcm@-IR#yCHJ?r?e}-<@smsnc4meb>C3;7yIZB P00000NkvXXu0mjfVyU~g literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/hack.jpg b/src/docs/cn/src/documentation/skins/common/images/hack.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f38d50fe4e87cb4ede05ce4b6f124460b77f2a0f GIT binary patch literal 743 zcmex=i3*BJ!6k`h{6D}T z$iX1OAi~Tj$iO7X$SlbC{|JKw10w@7BLfm(XJ%pJ0LrKcFfc&?GgOv|nURH6kWENf zkwJ-FL|MfMs7f5@Q$`g1tjr8-KnXQL1_q#~fqGzOGcpM(GO!prCNi@M1qv57PW)i> z{}uxePyv%5vmk>#!z=Hw)gfzchs_dwb)6~u-lc{J9p#OZ6SG*{l#7i&yEVyNe`52m z?8<(|$z{?4i%i3(tlGKv6RT2AO_XoH_ze@T4q^E^|1Do4E?duNoY48XDn;^jy+5zl z+XU5E*B@I8^sa2*)?&wgVr`M0ezaz8!s?*grt`V(_w>!37OKV~GNofv@IAJ)s`t@z z^FlA$8!_%?Z7SXJL&p2U66xZ5uJx0j=v`Qu{B@(m?4Vh@_!qo9xtn^QNZp*i{dALZZD-PQj)&8J`hMPbAhvS`-8>JA6F4^r=zKIWe^-BH${BtgXXyz|z4k0IlcQSn1w>fm t4@cY%T^+SFHFVX2^CbaS}9ZZyUVQ>#nGL-7*pWflJ-z4MzO#pq+?lJ%X literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/pdfdoc.gif b/src/docs/cn/src/documentation/skins/common/images/pdfdoc.gif new file mode 100644 index 0000000000000000000000000000000000000000..00dee28aad446d961c01450fae86a39f71506c40 GIT binary patch literal 457 zcmZ?wbhEHbRA5kGXklO|E-Y?oYx)2G`~Uy{=ggZE6d3gP@7FJ1zMMOM?)md;|Neb5 zG%)=2>(l%9@1H+^e(d%3QEFmIYKlU6W=V!Z zNJgrHyQgmegW^vXMlJ?<1|6VrK&L1$FtGl6px)<@FfXI3FXuO-lg{}=3HMzd?lO3L zx#dpZ)!#>X+9eqkW%l(1I5n-57OUryPc+E=w4h68?FNn6<<|>(K4x18^eZg5rKQDV z@3BU);Ba$^U{iBTYg?00eqp0fAGlb2V`vgV!7II9RxpeOA6%*z! z3|=zZZ0U+wy{kFbDhu{6-#B;oyajyQm3B_wwP9ud)!}=UVM1;xs>^9?e~YDa&(ms`M23tynMtd zBjq3o`n}ocQSKm@lYj+NTmZ@xk6H+e9Xb+?eFj m6JT-u?3~D87X}uGW-eJT5e-Wr)=65ir?#xT#IMM}U=08!4(Bld literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/poddoc.png b/src/docs/cn/src/documentation/skins/common/images/poddoc.png new file mode 100644 index 0000000000000000000000000000000000000000..a393df7372349f6df300eacf8d62987dba6f85aa GIT binary patch literal 856 zcmV-e1E>6nP)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00004XF*Lt006syVXTxM00006 zVoOIv0RI600RN!9r;`8x010qNS#tmY4#WTe4#WYKD-Ig~00O*8L_t(|+QpVTNE|^J z$A2fM1T`LdK8|#PiddK?TFD{e3)I2~C^izoQX5IcN=2)r5d^`Af`y%hg(!sB1jJZ~ zhhQQ2xbuN2jD|xCJ-y4!uDkAD*4y(U^S#%Bffg1Pd~Ubu+KBq}=IwO^pm2rcF!(l?9kaD>;J^+QI_c}?CwAUL!v{63b zMSwIAqZURm`P~-C@AoSl%Ul|ean#u3@mK?mz^4>(UJ5^_rrx+pOJh1dEH4pbk^qc| zxl{Vd?dDxqS8R>E@IiO~%8JU*q-C#{P-mxZ#<)zE2x%c6UoZ>}L4H2$?ZMa>l$5Az zCnqp40PXEiQ={%(Ux)d5xVqAT?1CXlpEWmw&j&3nP+JR&i!e6_d3i883OPBDoD7?r z(Ax`*jr!5wmzQj8Y$$vp9wq^w1`@Agd>pp7p{ECymW1(_Rc*9OkB?zu0%m5QzFt52 zIwONp5k!(jWwFu7;ZU_IFNgDUI6PF>PfsBw#e8aa7qYWWK9VNW%oiI-Qd5&^mWvCx zzE;=L)BgraO_f<|84UJ5lBVnKhSgPATT?+LwYI{+f%#Nf8EkDmS@Y~Q(i21YCNmR; zhoPb2F}ErzV0IP?3QYMH3+f~e}F{5Y&DV_64k;u-pUk+1@tdkX!Dz!8_URaM9J0C iRWA_nQh{&$5BdZ3oY`MtoEnh;0000 + + + + + + + + + + + + + + + + + + + + + + + POD + + + diff --git a/src/docs/cn/src/documentation/skins/common/images/printer.gif b/src/docs/cn/src/documentation/skins/common/images/printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..5021187b064c981bfa6688696d7144557468aaeb GIT binary patch literal 438 zcmZ?wbhEHbRA7*0IP#z2KM*i5+`E78+VyMa&YwHSV0i5Kv8~&-E?u^C&b&EOrcG&S zYbh=)PM*h*oS4i2RBAAXfq~(`fdfF27@+u*g^__lh(QOW7-S~{>;DBReJP%LD^{+1 zWwb0OW|y(&kV>k zoOo=K^QXOuJ0Hm{NahgWnfSbCS&!m_J#TnkY(62tR9SRN+sgHj0JFEIS?oy@Hx34C E05v70Bme*a literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/rc.svg.xslt b/src/docs/cn/src/documentation/skins/common/images/rc.svg.xslt new file mode 100644 index 00000000000..d8924fec1b4 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/images/rc.svg.xslt @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/images/remove.jpg b/src/docs/cn/src/documentation/skins/common/images/remove.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c9b9efa8fe95d823706ee9a211f34a0eb6f010a GIT binary patch literal 1251 zcmex=TL z>B-E7X2&P~a4`6jwh^=64%N$KvYWpfx`zxWxwdqUOnSC!Nz1SzY(ekLziD#x^ zN5c#+_UIeyY-pcs;P~|OA~k0Xi4!{~wTsAVnY=KnKKB0f`iUPuesXv@{Yci~8^Yz; ze$Gr6yrcD=n6CQspW#+>&)4KPoVTPS*P1y_xgl9G>4Qerv-iJzj6I!?I`hUW=Uv;# zHL>yT)$${4S$`XkoKG^9y{xuxQw?uJf!VPYKQ*7-)s9v(dui5j;p*Lw-?h_ZE}fNP znwi!fr^&uU)A`}8>{ko!=Ix#T_|WcYS)p$px382xAu?rN%}Uqp&Q)t>SDty!{&wjU zF$1}Yb2`GEzRw9aTyRJxLO(N-d%~h~3;r!CocN-C`qZPZEBp0d?V0X;_S@7qkG}EW zu$cJqO5oK~FE(#jvTvWQ_qU8sn~sKLX5RGeejKvAxN5rQtVLh$3bizMgenJ$X;1#o zkZV6ctbo!DryG5`U%cNA- z37SIO>Jn2uPEOf&tRRquW%=UskTnw*lL4j4_oQFx5`5PDln65ExUE?CQL56{W=O6>4%t1lHGeC6k3=o{392#=l uSM0X)>rLCYt$Mw3&7xT=7q(o#=zPoVy6suxF44RH-vj{rcK4+K literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/rss.png b/src/docs/cn/src/documentation/skins/common/images/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..f0796ac886201eb43b7a15113e2deb1b32fa9a09 GIT binary patch literal 360 zcmV-u0hj)XP)1pTfh($;sL0vc}u{{{FPIw4gub**+Xunj;hMg-Rk@N{o&!^ z{r&#_{{B{et%#+@{r~@)vdh1}zle=^0GR*(m;g35HkdZcHkixXHq)$8FWQhbW?9;ba!ELWdKKV zVQ^?^V?%Flc4cyOWpXuLNbUdt06|GaK~#90Vz9#p80;8u1CXpOE?Whx%fLW2AK{k88_xIu00030{{sMfLr(Xb|5zme0000004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00004XF*Lt006O$eEU(800001 zb5ch_0Itp)=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#0007K zNklQ>j$aI!>~6BuS6Q;~j%&nubQBVJyz=J&@KuRzjD; zcW(vZmNxJrKpeyxg%ynaLZD)?XsFw9aUiSZ8VZG+fzrUYH*7w2ey^>)m&eCl6R*)C z%=R)sowX&(lcM0`^0IqGG2rt<`VS6F^(fg`42{LbhhyyM=(-V3aWNTYXHDf22mq(2 z!0IZnumH@>0oT`${)-DBowfmq$k1#2*6To_01OTSmzTiN5im0YjEwi0pxkefcYS?`FcOI) za+39RU|;~)-#0-7IU)dleBQ_~Gz2yi2!}nB!COS^Uf}Q$n3@725l=O*b0CUlauQfs zG1<4Y;LWU?LD?PHl9k7t-wA_?`Mj}fOG*Fq!Zx#ulu6&o$RJ{P>DS%_VhWrCUF3V*)!aYF% O0000 + + + + + + + + + + + + + + + + + + + + + + + TXT + + + diff --git a/src/docs/cn/src/documentation/skins/common/images/update.jpg b/src/docs/cn/src/documentation/skins/common/images/update.jpg new file mode 100644 index 0000000000000000000000000000000000000000..beb9207336f508e1e60b2154a6292705a7317c03 GIT binary patch literal 990 zcmex=`WXCjGV$EqLPXcGp+%Z zNis4pF{2v5&dkcj0+dn`WB}@CL6QbCSy&m^1clgvCWsmRzs0}<)XOBuEXZKbu&nmZ zUEkd+zBN|q$1Ixqrz7BO-I}$>PfA|TKK6C0m9FK+cPkQQjN+DUeXu4u@MF*FfGpz| z8`AsaC+fJb;VhfwY3f*Z%PzR)$hD1?A!ldYs+8Y+P^~-c^*$2O#Z#!G>X}ouT=R2Pc+d@(I!`-o_U*_tEEUB#I-?h1ST9V+k zI{VU>v(|fR-Q8VoVYScfxqV08!yC;RNj^=v(@svZJL)?1=<1$Hzg3pkD(!u`W^Jmq zq~WGkfvK;05)NDre`1gmxMs`dZA!UZ7oHRysABC~;c?pY)vx`JQzm!&aUF{m4Rhs5 zdK>CJP0VJAle6=@^)ogG9&Fz#nj>qy%3IC8JJ*rb?aa5nealbC$aFi_cy83=n6g=U z_lkGjUv!q|+;`>nIhuN9+BOx>^4qS5`wNVpC^$^b3Q2I~6Fng)S{-w=EHJ+_>pw&4 z>sqT;#+&Tg{b{Q$r0 zcjPwoN^N?+#M#1Z;pwWy3EJV(Ic&E?RC2Z^U(MN|Em16H;~rq;EcQAajAv$N9{om-s!5r##+I#Y}qkqPB1#0`7CuktZhxU=!4ohn_gbm zlDj{ppYNW{A@7V3(=UI13-HQKP`M&)Y;@vdl5X=hrHIwv9t##XtHe!Kcxhr7`+BO# gv;PeKu`GXNFaKw_))oI_o&UPMIeaoE+5c|>0A~eb6#xJL literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/valid-html401.png b/src/docs/cn/src/documentation/skins/common/images/valid-html401.png new file mode 100644 index 0000000000000000000000000000000000000000..3855210c6c3c85c56f90221b3247fa664374b6bf GIT binary patch literal 2948 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 IbxsLQ074N#oB#j- literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/images/xmldoc.gif b/src/docs/cn/src/documentation/skins/common/images/xmldoc.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca1224f61f15032439564542f57d501d5cf54b6b GIT binary patch literal 647 zcmZ?wbhEHbRA5kGSjxaqTv*)F*7E=V_y7O@&zUzTC@|>n->+Z3d^vai-0|ZF9zVYQ z{P{IYOY?vKz7-Ya$;!$Y8W{HVb;`&{7Z&FJ`t|Ak`}fbEKR#i|247#_j*iy(^XL2f`-g-Cb#}G_!ROC!X3d(lYSofmyLM$|Wf>bApFMka%a-L* zQc~&Z>1WUGOHYrVHLK6p*WK7yUrI`1`;P4m4Gmzo0iA~(DgG06E=o--Nlj5G&n(GM z2+2rQaQE~LU{L(Y!pOy7&!7Wz4bZC!3=C}l4$S|+&LPo%;z{9&93j>VD?$ubL~*h% z7dCiX#u=eI`E{=pUl5a$PF%zb6qC`S(^p(YuHP2qAU6MIRkj>f>{N6`=TlY zg@g-5;zY$b#1k0Gd@Fd_1o;JnBmzX4X3R>MmmJH**B&dnb>{4K&J}TzK`Xay-|4hF zxNF6#12Yfhr3P=EAtqLG`bdD(7HJvT8QhmA1aeAq%1H}K^F5PaC9iPt633NFMI|0V zP8mTNWtpw=vKQ|@sO@%o)X1zM!=myee4)#3*7uJbImH*w&)mJh={Qfpwa=1j zVwTNZcQ%=v(oYdH=*`%;faTK4`K!#1cCBRM78i@#&|o-umG7p==q(e{4!ZJ4Y9G*& zjTW2LC0Vlj;Eaz=Y+G0D-^An-&HRE((lAEl>eee7<{f$w3cZS(-v%(g6DyBCDE9Jt eDx<)PxU;*qW?#L+bz+|H?rm>xIyW&eSOWkroh0x8 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs-optimized.js b/src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs-optimized.js new file mode 100644 index 00000000000..507612af872 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs-optimized.js @@ -0,0 +1,90 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +var PREPREND_CRUMBS=new Array(); +var link1="@skinconfig.trail.link1.name@"; +var link2="@skinconfig.trail.link2.name@"; +var link3="@skinconfig.trail.link3.name@"; +if(!(link1=="")&&!link1.indexOf( "@" ) == 0){ + PREPREND_CRUMBS.push( new Array( link1, @skinconfig.trail.link1.href@ ) ); } +if(!(link2=="")&&!link2.indexOf( "@" ) == 0){ + PREPREND_CRUMBS.push( new Array( link2, @skinconfig.trail.link2.href@ ) ); } +if(!(link3=="")&&!link3.indexOf( "@" ) == 0){ + PREPREND_CRUMBS.push( new Array( link3, @skinconfig.trail.link3.href@ ) ); } +var DISPLAY_SEPARATOR=" > "; +var DISPLAY_PREPREND=" > "; +var DISPLAY_POSTPREND=":"; +var CSS_CLASS_CRUMB="breadcrumb"; +var CSS_CLASS_TRAIL="breadcrumbTrail"; +var CSS_CLASS_SEPARATOR="crumbSeparator"; +var FILE_EXTENSIONS=new Array( ".html", ".htm", ".jsp", ".php", ".php3", ".php4" ); +var PATH_SEPARATOR="/"; + +function sc(s) { + var l=s.toLowerCase(); + return l.substr(0,1).toUpperCase()+l.substr(1); +} +function getdirs() { + var t=document.location.pathname.split(PATH_SEPARATOR); + var lc=t[t.length-1]; + for(var i=0;i < FILE_EXTENSIONS.length;i++) + { + if(lc.indexOf(FILE_EXTENSIONS[i])) + return t.slice(1,t.length-1); } + return t.slice(1,t.length); +} +function getcrumbs( d ) +{ + var pre = "/"; + var post = "/"; + var c = new Array(); + if( d != null ) + { + for(var i=0;i < d.length;i++) { + pre+=d[i]+postfix; + c.push(new Array(d[i],pre)); } + } + if(PREPREND_CRUMBS.length > 0 ) + return PREPREND_CRUMBS.concat( c ); + return c; +} +function gettrail( c ) +{ + var h=DISPLAY_PREPREND; + for(var i=0;i < c.length;i++) + { + h+=''+sc(c[i][0])+''; + if(i!=(c.length-1)) + h+=DISPLAY_SEPARATOR; } + return h+DISPLAY_POSTPREND; +} + +function gettrailXHTML( c ) +{ + var h=''+DISPLAY_PREPREND; + for(var i=0;i < c.length;i++) + { + h+=''+sc(c[i][0])+''; + if(i!=(c.length-1)) + h+=''+DISPLAY_SEPARATOR+''; } + return h+DISPLAY_POSTPREND+''; +} + +if(document.location.href.toLowerCase().indexOf("http://")==-1) + document.write(gettrail(getcrumbs())); +else + document.write(gettrail(getcrumbs(getdirs()))); + diff --git a/src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs.js b/src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs.js new file mode 100644 index 00000000000..aea80ec045b --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/breadcrumbs.js @@ -0,0 +1,237 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * This script, when included in a html file, builds a neat breadcrumb trail + * based on its url. That is, if it doesn't contains bugs (I'm relatively + * sure it does). + * + * Typical usage: + * + */ + +/** + * IE 5 on Mac doesn't know Array.push. + * + * Implement it - courtesy to fritz. + */ +var abc = new Array(); +if (!abc.push) { + Array.prototype.push = function(what){this[this.length]=what} +} + +/* ======================================================================== + CONSTANTS + ======================================================================== */ + +/** + * Two-dimensional array containing extra crumbs to place at the front of + * the trail. Specify first the name of the crumb, then the URI that belongs + * to it. You'll need to modify this for every domain or subdomain where + * you use this script (you can leave it as an empty array if you wish) + */ +var PREPREND_CRUMBS = new Array(); + +var link1 = "@skinconfig.trail.link1.name@"; +var link2 = "@skinconfig.trail.link2.name@"; +var link3 = "@skinconfig.trail.link3.name@"; + +var href1 = "@skinconfig.trail.link1.href@"; +var href2 = "@skinconfig.trail.link2.href@"; +var href3 = "@skinconfig.trail.link3.href@"; + + if(!(link1=="")&&!link1.indexOf( "@" ) == 0){ + PREPREND_CRUMBS.push( new Array( link1, href1 ) ); + } + if(!(link2=="")&&!link2.indexOf( "@" ) == 0){ + PREPREND_CRUMBS.push( new Array( link2, href2 ) ); + } + if(!(link3=="")&&!link3.indexOf( "@" ) == 0){ + PREPREND_CRUMBS.push( new Array( link3, href3 ) ); + } + +/** + * String to include between crumbs: + */ +var DISPLAY_SEPARATOR = " > "; +/** + * String to include at the beginning of the trail + */ +var DISPLAY_PREPREND = " > "; +/** + * String to include at the end of the trail + */ +var DISPLAY_POSTPREND = ""; + +/** + * CSS Class to use for a single crumb: + */ +var CSS_CLASS_CRUMB = "breadcrumb"; + +/** + * CSS Class to use for the complete trail: + */ +var CSS_CLASS_TRAIL = "breadcrumbTrail"; + +/** + * CSS Class to use for crumb separator: + */ +var CSS_CLASS_SEPARATOR = "crumbSeparator"; + +/** + * Array of strings containing common file extensions. We use this to + * determine what part of the url to ignore (if it contains one of the + * string specified here, we ignore it). + */ +var FILE_EXTENSIONS = new Array( ".html", ".htm", ".jsp", ".php", ".php3", ".php4" ); + +/** + * String that separates parts of the breadcrumb trail from each other. + * When this is no longer a slash, I'm sure I'll be old and grey. + */ +var PATH_SEPARATOR = "/"; + +/* ======================================================================== + UTILITY FUNCTIONS + ======================================================================== */ +/** + * Capitalize first letter of the provided string and return the modified + * string. + */ +function sentenceCase( string ) +{ return string; + //var lower = string.toLowerCase(); + //return lower.substr(0,1).toUpperCase() + lower.substr(1); +} + +/** + * Returns an array containing the names of all the directories in the + * current document URL + */ +function getDirectoriesInURL() +{ + var trail = document.location.pathname.split( PATH_SEPARATOR ); + + // check whether last section is a file or a directory + var lastcrumb = trail[trail.length-1]; + for( var i = 0; i < FILE_EXTENSIONS.length; i++ ) + { + if( lastcrumb.indexOf( FILE_EXTENSIONS[i] ) ) + { + // it is, remove it and send results + return trail.slice( 1, trail.length-1 ); + } + } + + // it's not; send the trail unmodified + return trail.slice( 1, trail.length ); +} + +/* ======================================================================== + BREADCRUMB FUNCTIONALITY + ======================================================================== */ +/** + * Return a two-dimensional array describing the breadcrumbs based on the + * array of directories passed in. + */ +function getBreadcrumbs( dirs ) +{ + var prefix = "/"; + var postfix = "/"; + + // the array we will return + var crumbs = new Array(); + + if( dirs != null ) + { + for( var i = 0; i < dirs.length; i++ ) + { + prefix += dirs[i] + postfix; + crumbs.push( new Array( dirs[i], prefix ) ); + } + } + + // preprend the PREPREND_CRUMBS + if(PREPREND_CRUMBS.length > 0 ) + { + return PREPREND_CRUMBS.concat( crumbs ); + } + + return crumbs; +} + +/** + * Return a string containing a simple text breadcrumb trail based on the + * two-dimensional array passed in. + */ +function getCrumbTrail( crumbs ) +{ + var xhtml = DISPLAY_PREPREND; + + for( var i = 0; i < crumbs.length; i++ ) + { + xhtml += ''; + xhtml += unescape( crumbs[i][0] ) + ''; + if( i != (crumbs.length-1) ) + { + xhtml += DISPLAY_SEPARATOR; + } + } + + xhtml += DISPLAY_POSTPREND; + + return xhtml; +} + +/** + * Return a string containing an XHTML breadcrumb trail based on the + * two-dimensional array passed in. + */ +function getCrumbTrailXHTML( crumbs ) +{ + var xhtml = ''; + xhtml += DISPLAY_PREPREND; + + for( var i = 0; i < crumbs.length; i++ ) + { + xhtml += ''; + xhtml += unescape( crumbs[i][0] ) + ''; + if( i != (crumbs.length-1) ) + { + xhtml += '' + DISPLAY_SEPARATOR + ''; + } + } + + xhtml += DISPLAY_POSTPREND; + xhtml += ''; + + return xhtml; +} + +/* ======================================================================== + PRINT BREADCRUMB TRAIL + ======================================================================== */ + +// check if we're local; if so, only print the PREPREND_CRUMBS +if( document.location.href.toLowerCase().indexOf( "http://" ) == -1 ) +{ + document.write( getCrumbTrail( getBreadcrumbs() ) ); +} +else +{ + document.write( getCrumbTrail( getBreadcrumbs( getDirectoriesInURL() ) ) ); +} + diff --git a/src/docs/cn/src/documentation/skins/common/scripts/fontsize.js b/src/docs/cn/src/documentation/skins/common/scripts/fontsize.js new file mode 100644 index 00000000000..11722bfc52f --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/fontsize.js @@ -0,0 +1,166 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +function init() +{ //embedded in the doc + //ndeSetTextSize(); +} + +function checkBrowser(){ + if (!document.getElementsByTagName){ + return true; + } + else{ + return false; + } +} + + +function ndeSetTextSize(chgsize,rs) +{ + var startSize; + var newSize; + + if (!checkBrowser) + { + return; + } + + startSize = parseInt(ndeGetDocTextSize()); + + if (!startSize) + { + startSize = 16; + } + + switch (chgsize) + { + case 'incr': + newSize = startSize + 2; + break; + + case 'decr': + newSize = startSize - 2; + break; + + case 'reset': + if (rs) {newSize = rs;} else {newSize = 16;} + break; + + default: + try{ + newSize = parseInt(ndeReadCookie("nde-textsize")); + } + catch(e){ + alert(e); + } + + if (!newSize || newSize == 'NaN') + { + newSize = startSize; + } + break; + + } + + if (newSize < 10) + { + newSize = 10; + } + + newSize += 'px'; + + document.getElementsByTagName('html')[0].style.fontSize = newSize; + document.getElementsByTagName('body')[0].style.fontSize = newSize; + + ndeCreateCookie("nde-textsize", newSize, 365); +} + +function ndeGetDocTextSize() +{ + if (!checkBrowser) + { + return 0; + } + + var size = 0; + var body = document.getElementsByTagName('body')[0]; + + if (body.style && body.style.fontSize) + { + size = body.style.fontSize; + } + else if (typeof(getComputedStyle) != 'undefined') + { + size = getComputedStyle(body,'').getPropertyValue('font-size'); + } + else if (body.currentStyle) + { + size = body.currentStyle.fontSize; + } + + //fix IE bug + if( isNaN(size)){ + if(size.substring(size.length-1)=="%"){ + return + } + + } + + return size; + +} + + + +function ndeCreateCookie(name,value,days) +{ + var cookie = name + "=" + value + ";"; + + if (days) + { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + cookie += " expires=" + date.toGMTString() + ";"; + } + cookie += " path=/"; + + document.cookie = cookie; + +} + +function ndeReadCookie(name) +{ + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + + + for(var i = 0; i < ca.length; i++) + { + var c = ca[i]; + while (c.charAt(0) == ' ') + { + c = c.substring(1, c.length); + } + + ctest = c.substring(0,name.length); + + if(ctest == name){ + return c.substring(nameEQ.length,c.length); + } + } + return null; +} diff --git a/src/docs/cn/src/documentation/skins/common/scripts/getBlank.js b/src/docs/cn/src/documentation/skins/common/scripts/getBlank.js new file mode 100644 index 00000000000..d9978c0b3e6 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/getBlank.js @@ -0,0 +1,40 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * getBlank script - when included in a html file and called from a form text field, will set the value of this field to "" + * if the text value is still the standard value. + * getPrompt script - when included in a html file and called from a form text field, will set the value of this field to the prompt + * if the text value is empty. + * + * Typical usage: + * + * + */ + diff --git a/src/docs/cn/src/documentation/skins/common/scripts/getMenu.js b/src/docs/cn/src/documentation/skins/common/scripts/getMenu.js new file mode 100644 index 00000000000..b17aad61858 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/getMenu.js @@ -0,0 +1,45 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * This script, when included in a html file, can be used to make collapsible menus + * + * Typical usage: + * + */ + +if (document.getElementById){ + document.write('') +} + + +function SwitchMenu(obj, thePath) +{ +var open = 'url("'+thePath + 'images/chapter_open.gif")'; +var close = 'url("'+thePath + 'images/chapter.gif")'; + if(document.getElementById) { + var el = document.getElementById(obj); + var title = document.getElementById(obj+'Title'); + + if(el.style.display != "block"){ + title.style.backgroundImage = open; + el.style.display = "block"; + }else{ + title.style.backgroundImage = close; + el.style.display = "none"; + } + }// end - if(document.getElementById) +}//end - function SwitchMenu(obj) diff --git a/src/docs/cn/src/documentation/skins/common/scripts/menu.js b/src/docs/cn/src/documentation/skins/common/scripts/menu.js new file mode 100644 index 00000000000..06ea471dc57 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/menu.js @@ -0,0 +1,48 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * This script, when included in a html file, can be used to make collapsible menus + * + * Typical usage: + * + */ + +if (document.getElementById){ + document.write('') +} + +function SwitchMenu(obj) +{ + if(document.getElementById) { + var el = document.getElementById(obj); + var title = document.getElementById(obj+'Title'); + + if(obj.indexOf("_selected_")==0&&el.style.display == ""){ + el.style.display = "block"; + title.className = "pagegroupselected"; + } + + if(el.style.display != "block"){ + el.style.display = "block"; + title.className = "pagegroupopen"; + } + else{ + el.style.display = "none"; + title.className = "pagegroup"; + } + }// end - if(document.getElementById) +}//end - function SwitchMenu(obj) diff --git a/src/docs/cn/src/documentation/skins/common/scripts/prototype.js b/src/docs/cn/src/documentation/skins/common/scripts/prototype.js new file mode 100644 index 00000000000..ed7d920cb5f --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/scripts/prototype.js @@ -0,0 +1,1257 @@ +/* Prototype JavaScript framework, version 1.4.0_pre4 + * (c) 2005 Sam Stephenson + * + * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff + * against the source tree, available from the Prototype darcs repository. + * + * Prototype is freely distributable under the terms of an MIT-style license. + * + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.4.0_pre4', + + emptyFunction: function() {}, + K: function(x) {return x} +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (property in source) { + destination[property] = source[property]; + } + return destination; +} + +Function.prototype.bind = function(object) { + var __method = this; + return function() { + return __method.apply(object, arguments); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this; + return function(event) { + return __method.call(object, event || window.event); + } +} + +Number.prototype.toColorPart = function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; +} + +var Try = { + these: function() { + var returnValue; + + for (var i = 0; i < arguments.length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(); + } finally { + this.currentlyExecuting = false; + } + } + } +} + +/*--------------------------------------------------------------------------*/ + +function $() { + var elements = new Array(); + + for (var i = 0; i < arguments.length; i++) { + var element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + + if (arguments.length == 1) + return element; + + elements.push(element); + } + + return elements; +} + +if (!Array.prototype.push) { + Array.prototype.push = function() { + var startLength = this.length; + for (var i = 0; i < arguments.length; i++) + this[startLength + i] = arguments[i]; + return this.length; + } +} + +if (!Function.prototype.apply) { + // Based on code from http://www.youngpup.net/ + Function.prototype.apply = function(object, parameters) { + var parameterStrings = new Array(); + if (!object) object = window; + if (!parameters) parameters = new Array(); + + for (var i = 0; i < parameters.length; i++) + parameterStrings[i] = 'parameters[' + i + ']'; + + object.__apply__ = this; + var result = eval('object.__apply__(' + + parameterStrings.join(', ') + ')'); + object.__apply__ = null; + + return result; + } +} + +Object.extend(String.prototype, { + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0].nodeValue; + }, + + parseQuery: function() { + var str = this; + if (str.substring(0,1) == '?') { + str = this.substring(1); + } + var result = {}; + var pairs = str.split('&'); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split('='); + result[pair[0]] = pair[1]; + } + return result; + } +}); + + +var _break = new Object(); +var _continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != _continue) throw e; + } + }); + } catch (e) { + if (e != _break) throw e; + } + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + if (!(result &= (iterator || Prototype.K)(value, index))) + throw _break; + }); + return result; + }, + + any: function(iterator) { + var result = true; + this.each(function(value, index) { + if (result &= (iterator || Prototype.K)(value, index)) + throw _break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function (iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw _break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw _break; + } + }); + return found; + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.collect(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value >= (result || value)) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value <= (result || value)) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.collect(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.collect(Prototype.K); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + iterator(value = collections.pluck(index)); + return value; + }); + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); + +$A = Array.from = function(iterable) { + var results = []; + for (var i = 0; i < iterable.length; i++) + results.push(iterable[i]); + return results; +} + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0; i < this.length; i++) + iterator(this[i]); + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + } +}); + +Object.extend(Array.prototype, Enumerable); + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')}, + function() {return new XMLHttpRequest()} + ) || false; + } +} + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + parameters: '' + } + Object.extend(this.options, options || {}); + }, + + responseIsSuccess: function() { + return this.transport.status == undefined + || this.transport.status == 0 + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + responseIsFailure: function() { + return !this.responseIsSuccess(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + var parameters = this.options.parameters || ''; + if (parameters.length > 0) parameters += '&_='; + + try { + if (this.options.method == 'get') + url += '?' + parameters; + + this.transport.open(this.options.method, url, + this.options.asynchronous); + + if (this.options.asynchronous) { + this.transport.onreadystatechange = this.onStateChange.bind(this); + setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); + } + + this.setRequestHeaders(); + + var body = this.options.postBody ? this.options.postBody : parameters; + this.transport.send(this.options.method == 'post' ? body : null); + + } catch (e) { + } + }, + + setRequestHeaders: function() { + var requestHeaders = + ['X-Requested-With', 'XMLHttpRequest', + 'X-Prototype-Version', Prototype.Version]; + + if (this.options.method == 'post') { + requestHeaders.push('Content-type', + 'application/x-www-form-urlencoded'); + + /* Force "Connection: close" for Mozilla browsers to work around + * a bug where XMLHttpReqeuest sends an incorrect Content-length + * header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType) + requestHeaders.push('Connection', 'close'); + } + + if (this.options.requestHeaders) + requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); + + for (var i = 0; i < requestHeaders.length; i += 2) + this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState != 1) + this.respondToReadyState(this.transport.readyState); + }, + + respondToReadyState: function(readyState) { + var event = Ajax.Request.Events[readyState]; + + if (event == 'Complete') + (this.options['on' + this.transport.status] + || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(this.transport); + + (this.options['on' + event] || Prototype.emptyFunction)(this.transport); + + /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ + if (event == 'Complete') + this.transport.onreadystatechange = Prototype.emptyFunction; + } +}); + +Ajax.Updater = Class.create(); +Ajax.Updater.ScriptFragment = '(?:)((\n|.)*?)(?:<\/script>)'; + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.containers = { + success: container.success ? $(container.success) : $(container), + failure: container.failure ? $(container.failure) : + (container.success ? null : $(container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function() { + this.updateContent(); + onComplete(this.transport); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.responseIsSuccess() ? + this.containers.success : this.containers.failure; + + var match = new RegExp(Ajax.Updater.ScriptFragment, 'img'); + var response = this.transport.responseText.replace(match, ''); + var scripts = this.transport.responseText.match(match); + + if (receiver) { + if (this.options.insertion) { + new this.options.insertion(receiver, response); + } else { + receiver.innerHTML = response; + } + } + + if (this.responseIsSuccess()) { + if (this.onComplete) + setTimeout((function() {this.onComplete( + this.transport)}).bind(this), 10); + } + + if (this.options.evalScripts && scripts) { + match = new RegExp(Ajax.Updater.ScriptFragment, 'im'); + setTimeout((function() { + for (var i = 0; i < scripts.length; i++) + eval(scripts[i].match(match)[1]); + }).bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = 1; + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Ajax.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + +document.getElementsByClassName = function(className) { + var children = document.getElementsByTagName('*') || document.all; + var elements = new Array(); + + for (var i = 0; i < children.length; i++) { + var child = children[i]; + var classNames = child.className.split(' '); + for (var j = 0; j < classNames.length; j++) { + if (classNames[j] == className) { + elements.push(child); + break; + } + } + } + + return elements; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) { + var Element = new Object(); +} + +Object.extend(Element, { + toggle: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = + (element.style.display == 'none' ? '' : 'none'); + } + }, + + hide: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = 'none'; + } + }, + + show: function() { + for (var i = 0; i < arguments.length; i++) { + var element = $(arguments[i]); + element.style.display = ''; + } + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + }, + + getHeight: function(element) { + element = $(element); + return element.offsetHeight; + }, + + hasClassName: function(element, className) { + element = $(element); + if (!element) + return; + var a = element.className.split(' '); + for (var i = 0; i < a.length; i++) { + if (a[i] == className) + return true; + } + return false; + }, + + addClassName: function(element, className) { + element = $(element); + Element.removeClassName(element, className); + element.className += ' ' + className; + }, + + removeClassName: function(element, className) { + element = $(element); + if (!element) + return; + var newClassName = ''; + var a = element.className.split(' '); + for (var i = 0; i < a.length; i++) { + if (a[i] != className) { + if (i > 0) + newClassName += ' '; + newClassName += a[i]; + } + } + element.className = newClassName; + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + var element = $(element); + for (var i = 0; i < element.childNodes.length; i++) { + var node = element.childNodes[i]; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + Element.remove(node); + } + } +}); + +var Toggle = new Object(); +Toggle.display = Element.toggle; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content; + + if (this.adjacency && this.element.insertAdjacentHTML) { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.fragment = this.range.createContextualFragment(this.content); + this.insertContent(); + } + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function() { + this.element.parentNode.insertBefore(this.fragment, this.element); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function() { + this.element.insertBefore(this.fragment, this.element.firstChild); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function() { + this.element.appendChild(this.fragment); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function() { + this.element.parentNode.insertBefore(this.fragment, + this.element.nextSibling); + } +}); + +var Field = { + clear: function() { + for (var i = 0; i < arguments.length; i++) + $(arguments[i]).value = ''; + }, + + focus: function(element) { + $(element).focus(); + }, + + present: function() { + for (var i = 0; i < arguments.length; i++) + if ($(arguments[i]).value == '') return false; + return true; + }, + + select: function(element) { + $(element).select(); + }, + + activate: function(element) { + $(element).focus(); + $(element).select(); + } +} + +/*--------------------------------------------------------------------------*/ + +var Form = { + serialize: function(form) { + var elements = Form.getElements($(form)); + var queryComponents = new Array(); + + for (var i = 0; i < elements.length; i++) { + var queryComponent = Form.Element.serialize(elements[i]); + if (queryComponent) + queryComponents.push(queryComponent); + } + + return queryComponents.join('&'); + }, + + getElements: function(form) { + var form = $(form); + var elements = new Array(); + + for (tagName in Form.Element.Serializers) { + var tagElements = form.getElementsByTagName(tagName); + for (var j = 0; j < tagElements.length; j++) + elements.push(tagElements[j]); + } + return elements; + }, + + getInputs: function(form, typeName, name) { + var form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) + return inputs; + + var matchingInputs = new Array(); + for (var i = 0; i < inputs.length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || + (name && input.name != name)) + continue; + matchingInputs.push(input); + } + + return matchingInputs; + }, + + disable: function(form) { + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element.blur(); + element.disabled = 'true'; + } + }, + + enable: function(form) { + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + element.disabled = ''; + } + }, + + focusFirstElement: function(form) { + var form = $(form); + var elements = Form.getElements(form); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + if (element.type != 'hidden' && !element.disabled) { + Field.activate(element); + break; + } + } + }, + + reset: function(form) { + $(form).reset(); + } +} + +Form.Element = { + serialize: function(element) { + var element = $(element); + var method = element.tagName.toLowerCase(); + var parameter = Form.Element.Serializers[method](element); + + if (parameter) + return encodeURIComponent(parameter[0]) + '=' + + encodeURIComponent(parameter[1]); + }, + + getValue: function(element) { + var element = $(element); + var method = element.tagName.toLowerCase(); + var parameter = Form.Element.Serializers[method](element); + + if (parameter) + return parameter[1]; + } +} + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'submit': + case 'hidden': + case 'password': + case 'text': + return Form.Element.Serializers.textarea(element); + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + } + return false; + }, + + inputSelector: function(element) { + if (element.checked) + return [element.name, element.value]; + }, + + textarea: function(element) { + return [element.name, element.value]; + }, + + select: function(element) { + var value = ''; + if (element.type == 'select-one') { + var index = element.selectedIndex; + if (index >= 0) + value = element.options[index].value || element.options[index].text; + } else { + value = new Array(); + for (var i = 0; i < element.length; i++) { + var opt = element.options[i]; + if (opt.selected) + value.push(opt.value || opt.text); + } + } + return [element.name, value]; + } +} + +/*--------------------------------------------------------------------------*/ + +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + var elements = Form.getElements(this.element); + for (var i = 0; i < elements.length; i++) + this.registerCallback(elements[i]); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + element.target = this; + element.prev_onclick = element.onclick || Prototype.emptyFunction; + element.onclick = function() { + this.prev_onclick(); + this.target.onElementEvent(); + } + break; + case 'password': + case 'text': + case 'textarea': + case 'select-one': + case 'select-multiple': + element.target = this; + element.prev_onchange = element.onchange || Prototype.emptyFunction; + element.onchange = function() { + this.prev_onchange(); + this.target.onElementEvent(); + } + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + + +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + + element: function(event) { + return event.target || event.srcElement; + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0; i < Event.observers.length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + var element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + ((/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + || element.attachEvent)) + name = 'keydown'; + + this._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + var element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + ((/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + || element.detachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + element.detachEvent('on' + name, observer); + } + } +}); + +/* prevent memory leaks in IE */ +Event.observe(window, 'unload', Event.unloadCache, false); + +var Position = { + + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + clone: function(source, target) { + source = $(source); + target = $(target); + target.style.position = 'absolute'; + var offsets = this.cumulativeOffset(source); + target.style.top = offsets[1] + 'px'; + target.style.left = offsets[0] + 'px'; + target.style.width = source.offsetWidth + 'px'; + target.style.height = source.offsetHeight + 'px'; + } +} diff --git a/src/docs/cn/src/documentation/skins/common/skinconf.xsl b/src/docs/cn/src/documentation/skins/common/skinconf.xsl new file mode 100644 index 00000000000..5d1132086f1 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/skinconf.xsl @@ -0,0 +1,238 @@ + + + + + + + true + + + true + + + true + + + true + + + true + + + false + + + false + + + true + + + .at. + + + true + + + + + + + + + + + + + + + Page 1 + + + + + true + + + + + + + + + + Built with Apache Forrest + http://forrest.apache.org/ + images/built-with-forrest-button.png + 88 + 31 + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_de.xml b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_de.xml new file mode 100644 index 00000000000..bc461196e64 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_de.xml @@ -0,0 +1,23 @@ + + + + Schriftgrösse: + Zuletzt veröffentlicht: + Suche: + Suche auf der Seite mit + diff --git a/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_en_US.xml b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_en_US.xml new file mode 100644 index 00000000000..88dfe143118 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_en_US.xml @@ -0,0 +1,23 @@ + + + + Font size: + Last Published: + Search + Search site with + diff --git a/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_es.xml b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_es.xml new file mode 100644 index 00000000000..63be6712b30 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_es.xml @@ -0,0 +1,23 @@ + + + + Tamaño del texto: + Fecha de publicación: + Buscar + Buscar en + diff --git a/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_fr.xml b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_fr.xml new file mode 100644 index 00000000000..622569a4ffa --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/translations/CommonMessages_fr.xml @@ -0,0 +1,23 @@ + + + + Taille : + Dernière publication : + Rechercher + Rechercher sur le site avec + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/fo/d2fo.xml b/src/docs/cn/src/documentation/skins/common/xslt/fo/d2fo.xml new file mode 100644 index 00000000000..7b7a5fe9bfd --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/fo/d2fo.xml @@ -0,0 +1,1015 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 841mm + 594mm + 420mm + 297mm + 210mm + 148mm + 7.25in + 8.5in + 11in + 8.5in + 8.5in + 8.5in + 11in + 8.5in + + + + + 1189mm + 841mm + 594mm + 420mm + 297mm + 210mm + 10.5in + 13in + 17in + 14in + 10.83in + 17in + 11in + + + + + + + + + + 1189mm + 841mm + 594mm + 420mm + 297mm + 210mm + 10.5in + 13in + 17in + 14in + 10.83in + 17in + 11in + + + + + 841mm + 594mm + 420mm + 297mm + 210mm + 148mm + 7.25in + 8.5in + 11in + 8.5in + 8.5in + 8.5in + 11in + 8.5in + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + + + + + + + + + + + + + + + end + + + + + + + + + + + + + + start + + + + + + + + + + + + + + + + + + + + + + + + + NOTICE: + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + +. + + + + + +pt + + + + + + +   + + + + + + + + + + + + 0 + + + + + + + + + + + by + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6pt" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6pt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Warning: + + + + + + + + + + + + + + + + + Note: + + + + + + + + + + + + + FIXME (): + + + + + + + + + + + + + + + + + + + () + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + in + + + + + + + + + + + + + + + + + + + + Table + + +: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Table of contents + + + + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [] + + + + + + + + + + + + page + + + + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/fo/document-to-fo.xsl b/src/docs/cn/src/documentation/skins/common/xslt/fo/document-to-fo.xsl new file mode 100644 index 00000000000..bc00518f247 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/fo/document-to-fo.xsl @@ -0,0 +1,1025 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 841mm + 594mm + 420mm + 297mm + 210mm + 148mm + 7.25in + 8.5in + 11in + 8.5in + 8.5in + 8.5in + 11in + 8.5in + + + + + 1189mm + 841mm + 594mm + 420mm + 297mm + 210mm + 10.5in + 13in + 17in + 14in + 10.83in + 17in + 11in + + + + + + + + + + 1189mm + 841mm + 594mm + 420mm + 297mm + 210mm + 10.5in + 13in + 17in + 14in + 10.83in + 17in + 11in + + + + + 841mm + 594mm + 420mm + 297mm + 210mm + 148mm + 7.25in + 8.5in + 11in + 8.5in + 8.5in + 8.5in + 11in + 8.5in + + + + + + kkkkkkkkkkkkkkkkkkkkkk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + + + + + + + + + + + + + + + end + + + + + + + + + + + + + + start + + + + + + + + + + + + + + + + + + + + + + + + + NOTICE: + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + +. + + + + + +pt + + + + + + +   + + + + + + + + + + + + 0 + + + + + + + + + + + by + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6pt" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6pt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Warning: + + + + + + + + + + + + + + + + + Note: + + + + + + + + + + + + + FIXME (): + + + + + + + + + + + + + + + + + + + () + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + in + + + + + + + + + + + + + + + + + + + + Table + + +: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +目录 + + + + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [] + + + + + + + + + + + + page + + + + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/fo/footerinfo.xsl b/src/docs/cn/src/documentation/skins/common/xslt/fo/footerinfo.xsl new file mode 100644 index 00000000000..c5ba5c9460e --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/fo/footerinfo.xsl @@ -0,0 +1,70 @@ + + + + + + + + + + + + +Copyright © +   + All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/fo/pdfoutline.xsl b/src/docs/cn/src/documentation/skins/common/xslt/fo/pdfoutline.xsl new file mode 100644 index 00000000000..acdc6ac9cf1 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/fo/pdfoutline.xsl @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/book-to-menu.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/book-to-menu.xsl new file mode 100644 index 00000000000..228b57e5c4d --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/book-to-menu.xsl @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • + + + + + + + + +
  • +
    + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/document-to-html.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/document-to-html.xsl new file mode 100644 index 00000000000..6e1dcc607e6 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/document-to-html.xsl @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    + +

    + +

    +
    +
    + +

    + +

    +
    + + + + +
    + + +; + + +
    +
    +
    + +
    + + + + + + + + + + + + + + + + ^ + + + + + + + +15 + + +0 + + + +
    + +
    + + + +
    + + + + + +
    + + + + + + Note + Warning + Fixme () + +
    +
    + +
    +
    +
    + +
    + +Notice: + +
    +
    + + + + _top + + + _blank + + + + + + + + + + + + + + +
    + + +
    +
    + + +
    +
    +      
    +      
    +
    +    
    +
    + + + + + + + + + + + + + + codefrag + + + + + + + +
    + + + + +
    +
    + + + + + + + + +
    +
    + + + + + + + +
    + +
    + + + + + + + + + by + , + + + + + + + + + + + + + + version + + + + + + + + + v + + + + + + + + +

    + +Type: + +

    +
    + +

    + +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/dotdots.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/dotdots.xsl new file mode 100644 index 00000000000..2ff9d1f3266 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/dotdots.xsl @@ -0,0 +1,73 @@ + + + + + + + + + + +../ + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/pathutils.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/pathutils.xsl new file mode 100644 index 00000000000..c1639a4b4f2 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/pathutils.xsl @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/renderlogo.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/renderlogo.xsl new file mode 100644 index 00000000000..698156b9ba2 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/renderlogo.xsl @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + {$name} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/site-to-xhtml.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/site-to-xhtml.xsl new file mode 100644 index 00000000000..2f8b15cd399 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/site-to-xhtml.xsl @@ -0,0 +1,388 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + > + + + > + + + + + + + + + + + + + + + + + + + + + + + + Valid HTML 4.01! + + + + + + + Valid HTML 4.01! + Valid CSS! + + + + + + + PDF +
    + PDF
    + +
    +
    + + + + + TXT +
    + TXT
    + +
    +
    + + + + + POD +
    + POD
    + +
    +
    + + + + + XML +
    + XML
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
    • + + + + + +
    • +
      +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + +
    +
    + + + + + + + + + + 2005 + yyyy + - + + + + + + + + + + + + +
    diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/split.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/split.xsl new file mode 100644 index 00000000000..14c88e72cb4 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/split.xsl @@ -0,0 +1,124 @@ + + + + + + + + + 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/strip_namespaces.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/strip_namespaces.xsl new file mode 100644 index 00000000000..47dec6a1788 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/strip_namespaces.xsl @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/tab-to-menu.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/tab-to-menu.xsl new file mode 100644 index 00000000000..257d2919f70 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/tab-to-menu.xsl @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + | + + + + + + + + | + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/src/docs/cn/src/documentation/skins/common/xslt/html/tabutils.xsl b/src/docs/cn/src/documentation/skins/common/xslt/html/tabutils.xsl new file mode 100644 index 00000000000..0caaaf4c81f --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/html/tabutils.xsl @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + +/ + + + +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/common/xslt/svg/document-to-svg.xsl b/src/docs/cn/src/documentation/skins/common/xslt/svg/document-to-svg.xsl new file mode 100644 index 00000000000..08ca5ba1b7a --- /dev/null +++ b/src/docs/cn/src/documentation/skins/common/xslt/svg/document-to-svg.xsl @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/pelt/css/basic.css b/src/docs/cn/src/documentation/skins/pelt/css/basic.css new file mode 100644 index 00000000000..4ed58b99ae7 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/css/basic.css @@ -0,0 +1,166 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +/** + * General + */ + +img { border: 0; } + +#content table { + border: 0; + width: 100%; +} +/*Hack to get IE to render the table at 100%*/ +* html #content table { margin-left: -3px; } + +#content th, +#content td { + margin: 0; + padding: 0; + vertical-align: top; +} + +.clearboth { + clear: both; +} + +.note, .warning, .fixme { + border: solid black 1px; + margin: 1em 3em; +} + +.note .label { + background: #369; + color: white; + font-weight: bold; + padding: 5px 10px; +} +.note .content { + background: #F0F0FF; + color: black; + line-height: 120%; + font-size: 90%; + padding: 5px 10px; +} +.warning .label { + background: #C00; + color: white; + font-weight: bold; + padding: 5px 10px; +} +.warning .content { + background: #FFF0F0; + color: black; + line-height: 120%; + font-size: 90%; + padding: 5px 10px; +} +.fixme .label { + background: #C6C600; + color: black; + font-weight: bold; + padding: 5px 10px; +} +.fixme .content { + padding: 5px 10px; +} + +/** + * Typography + */ + +body { + font-family: verdana, "Trebuchet MS", arial, helvetica, sans-serif; + font-size: 100%; +} + +#content { + font-family: Georgia, Palatino, Times, serif; + font-size: 95%; +} +#tabs { + font-size: 70%; +} +#menu { + font-size: 80%; +} +#footer { + font-size: 70%; +} + +h1, h2, h3, h4, h5, h6 { + font-family: "Trebuchet MS", verdana, arial, helvetica, sans-serif; + font-weight: bold; + margin-top: 1em; + margin-bottom: .5em; +} + +h1 { + margin-top: 0; + margin-bottom: 1em; + font-size: 1.4em; +} +#content h1 { + font-size: 160%; + margin-bottom: .5em; +} +#menu h1 { + margin: 0; + padding: 10px; + background: #336699; + color: white; +} +h2 { font-size: 120%; } +h3 { font-size: 100%; } +h4 { font-size: 90%; } +h5 { font-size: 80%; } +h6 { font-size: 75%; } + +p { + line-height: 120%; + text-align: left; + margin-top: .5em; + margin-bottom: 1em; +} + +#content li, +#content th, +#content td, +#content li ul, +#content li ol{ + margin-top: .5em; + margin-bottom: .5em; +} + + +#content li li, +#minitoc-area li{ + margin-top: 0em; + margin-bottom: 0em; +} + +#content .attribution { + text-align: right; + font-style: italic; + font-size: 85%; + margin-top: 1em; +} + +.codefrag { + font-family: "Courier New", Courier, monospace; + font-size: 110%; +} diff --git a/src/docs/cn/src/documentation/skins/pelt/css/print.css b/src/docs/cn/src/documentation/skins/pelt/css/print.css new file mode 100644 index 00000000000..8916b9fc01e --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/css/print.css @@ -0,0 +1,54 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +body { + font-family: Georgia, Palatino, serif; + font-size: 12pt; + background: white; +} + +#tabs, +#menu, +#content .toc { + display: none; +} + +#content { + width: auto; + padding: 0; + float: none !important; + color: black; + background: inherit; +} + +a:link, a:visited { + color: #336699; + background: inherit; + text-decoration: underline; +} + +#top .logo { + padding: 0; + margin: 0 0 2em 0; +} + +#footer { + margin-top: 4em; +} + +acronym { + border: 0; +} diff --git a/src/docs/cn/src/documentation/skins/pelt/css/profile.css.xslt b/src/docs/cn/src/documentation/skins/pelt/css/profile.css.xslt new file mode 100644 index 00000000000..a1dcb23e49c --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/css/profile.css.xslt @@ -0,0 +1,182 @@ + + + + + + + + +#top { background-color: ;} + + +#top .header .current { background-color: ;} +#top .header .current a:link { color: ; } +#top .header .current a:visited { color: ; } +#top .header .current a:hover { color: ; } + + +#tabs li { background-color: ;} +#tabs li a:link { color: ; } +#tabs li a:visited { color: ; } +#tabs li a:hover { color: ; } + + +#level2tabs a.selected { background-color: ;} +#level2tabs a:link { color: ; } +#level2tabs a:visited { color: ; } +#level2tabs a:hover { color: ; } + + +#level2tabs { background-color: ;} +#level2tabs a.unselected:link { color: ; } +#level2tabs a.unselected:visited { color: ; } +#level2tabs a.unselected:hover { color: ; } + + +.heading { background-color: ;} + + +.boxed { background-color: ;} +.underlined_5 {border-bottom: solid 5px ;} +.underlined_10 {border-bottom: solid 10px ;} +table caption { +background-color: ; +color: ; +} + + +#feedback { +color: ; +background: ; +text-align: ; +} +#feedback #feedbackto { +color: ; +} + + +#main .breadtrail { +background: ; +color: ; +} +#main .breadtrail a:link { color: ; } +#main .breadtrail a:visited { color: ; } +#main .breadtrail a:hover { color: ; } +#top .breadtrail { +background: ; +color: ; +} +#top .breadtrail a:link { color: ; } +#top .breadtrail a:visited { color: ; } +#top .breadtrail a:hover { color: ; } + + + +#publishedStrip { +color: ; +background: ; +} + + + +#publishedStrip { +color: ; +background: ; +} + + +#menu .menupagetitle { background-color: ; + color: ;} + + +#menu { border-color: ;} +#menu .menupagetitle { border-color: ;} +#menu .menupageitemgroup { border-color: ;} + + +#menu { background-color: ;} +#menu { color: ;} +#menu a:link { color: ;} +#menu a:visited { color: ;} +#menu a:hover { +background-color: ; +color: ;} + + +#menu .menupageitemgroup { +background-color: ; +} +#menu .menupageitem { +color: ; +} +#menu .menupageitem a:link { color: ;} +#menu .menupageitem a:visited { color: ;} +#menu .menupageitem a:hover { +background-color: ; +color: ; +} + + +#menu h1 { +color: ; +background-color: ; +} + + +#top .searchbox { +background-color: ; +color: ; +} + + +body{ +background-color: ; +color: ; +} +a:link { color:} +a:visited { color:} +a:hover { color:} + + + +#footer { background-color: ;} + + + +.highlight { background-color: ;} + + +.fixme { border-color: ;} + + +.note { border-color: ;} + + +.warning { border-color: ;} + + +.code { border-color: ;} + + +.ForrestTable { background-color: ;} + + +.ForrestTable td { background-color: ;} + + diff --git a/src/docs/cn/src/documentation/skins/pelt/css/screen.css b/src/docs/cn/src/documentation/skins/pelt/css/screen.css new file mode 100644 index 00000000000..aa8c457cb30 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/css/screen.css @@ -0,0 +1,587 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You 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. +*/ +body { margin: 0px 0px 0px 0px; font-family: Verdana, Helvetica, sans-serif; } + +h1 { font-size : 160%; margin: 0px 0px 0px 0px; padding: 0px; } +h2 { font-size : 140%; margin: 1em 0px 0.8em 0px; padding: 0px; font-weight : bold;} +h3 { font-size : 130%; margin: 0.8em 0px 0px 0px; padding: 0px; font-weight : bold; } +.h3 { margin: 22px 0px 3px 0px; } +h4 { font-size : 120%; margin: 0.7em 0px 0px 0px; padding: 0px; font-weight : normal; text-align: left; } +.h4 { margin: 18px 0px 0px 0px; } +h4.faq { font-size : 120%; margin: 18px 0px 0px 0px; padding: 0px; font-weight : bold; text-align: left; } +h5 { font-size : 100%; margin: 14px 0px 0px 0px; padding: 0px; font-weight : normal; text-align: left; } + +/** +* table +*/ +table .title { background-color: #000000; } +.ForrestTable { + color: #ffffff; + background-color: #7099C5; + width: 100%; + font-size : 100%; + empty-cells: show; +} +table caption { + padding-left: 5px; + color: white; + text-align: left; + font-weight: bold; + background-color: #000000; +} +.ForrestTable td { + color: black; + background-color: #f0f0ff; +} +.ForrestTable th { text-align: center; } +/** + * Page Header + */ + +#top { + position: relative; + float: left; + width: 100%; + background: #294563; /* if you want a background in the header, put it here */ +} + +#top .breadtrail { + background: #CFDCED; + color: black; + border-bottom: solid 1px white; + padding: 3px 10px; + font-size: 75%; +} +#top .breadtrail a { color: black; } + +#top .header { + float: left; + width: 100%; + background: url("images/header_white_line.gif") repeat-x bottom; +} + +#top .grouplogo { + padding: 7px 0 10px 10px; + float: left; + text-align: left; +} +#top .projectlogo { + padding: 7px 0 10px 10px; + float: left; + width: 33%; + text-align: right; +} +#top .projectlogoA1 { + padding: 7px 0 10px 10px; + float: right; +} +html>body #top .searchbox { + bottom: 0px; +} +#top .searchbox { + position: absolute; + right: 10px; + height: 42px; + font-size: 70%; + white-space: nowrap; + text-align: right; + color: white; + background-color: #000000; + z-index:0; + background-image: url(images/rc-t-l-5-1header-2searchbox-3searchbox.png); + background-repeat: no-repeat; + background-position: top left; + bottom: -1px; /* compensate for IE rendering issue */ +} + +#top .searchbox form { + padding: 5px 10px; + margin: 0; +} +#top .searchbox p { + padding: 0 0 2px 0; + margin: 0; +} +#top .searchbox input { + font-size: 100%; +} + +#tabs { + clear: both; + padding-left: 10px; + margin: 0; + list-style: none; +} +/* background: #CFDCED url("images/tab-right.gif") no-repeat right top;*/ +#tabs li { + float: left; + background-image: url(images/rc-t-r-5-1header-2tab-unselected-3tab-unselected.png); + background-repeat: no-repeat; + background-position: top right; + background-color: #000000; + margin: 0 3px 0 0; + padding: 0; +} + +/*background: url("images/tab-left.gif") no-repeat left top;*/ +#tabs li a { + float: left; + display: block; + font-family: verdana, arial, sans-serif; + text-decoration: none; + color: black; + white-space: nowrap; + background-image: url(images/rc-t-l-5-1header-2tab-unselected-3tab-unselected.png); + background-repeat: no-repeat; + background-position: top left; + padding: 5px 15px 4px; + width: .1em; /* IE/Win fix */ +} + +#tabs li a:hover { + + cursor: pointer; + text-decoration:underline; +} + +#tabs > li a { width: auto; } /* Rest of IE/Win fix */ + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +#tabs a { float: none; } +/* End IE5-Mac hack */ + +#top .header .current { + background-color: #4C6C8F; + background-image: url(images/rc-t-r-5-1header-2tab-selected-3tab-selected.png); + background-repeat: no-repeat; + background-position: top right; +} +#top .header .current a { + font-weight: bold; + padding-bottom: 5px; + color: white; + background-image: url(images/rc-t-l-5-1header-2tab-selected-3tab-selected.png); + background-repeat: no-repeat; + background-position: top left; +} +#publishedStrip { + padding-right: 10px; + padding-left: 20px; + padding-top: 3px; + padding-bottom:3px; + color: #ffffff; + font-size : 60%; + font-weight: bold; + background-color: #4C6C8F; + text-align:right; +} + +#level2tabs { +margin: 0; +float:left; +position:relative; + +} + + + +#level2tabs a:hover { + + cursor: pointer; + text-decoration:underline; + +} + +#level2tabs a{ + + cursor: pointer; + text-decoration:none; + background-image: url('images/chapter.gif'); + background-repeat: no-repeat; + background-position: center left; + padding-left: 6px; + margin-left: 6px; +} + +/* +* border-top: solid #4C6C8F 15px; +*/ +#main { + position: relative; + background: white; + clear:both; +} +#main .breadtrail { + clear:both; + position: relative; + background: #CFDCED; + color: black; + border-bottom: solid 1px black; + border-top: solid 1px black; + padding: 0px 180px; + font-size: 75%; + z-index:10; +} +/** +* Round corner +*/ +#roundtop { + background-image: url(images/rc-t-r-15-1body-2menu-3menu.png); + background-repeat: no-repeat; + background-position: top right; +} + +#roundbottom { + background-image: url(images/rc-b-r-15-1body-2menu-3menu.png); + background-repeat: no-repeat; + background-position: top right; +} + +img.corner { + width: 15px; + height: 15px; + border: none; + display: block !important; +} + +.roundtopsmall { + background-image: url(images/rc-t-r-5-1header-2searchbox-3searchbox.png); + background-repeat: no-repeat; + background-position: top right; +} + +#roundbottomsmall { + background-image: url(images/rc-b-r-5-1header-2tab-selected-3tab-selected.png); + background-repeat: no-repeat; + background-position: top right; +} + +img.cornersmall { + width: 5px; + height: 5px; + border: none; + display: block !important; +} +/** + * Side menu + */ +#menu a { font-weight: normal; text-decoration: none;} +#menu a:visited { font-weight: normal; } +#menu a:active { font-weight: normal; } +#menu a:hover { font-weight: normal; text-decoration:underline;} + +#menuarea { width:10em;} +#menu { + position: relative; + float: left; + width: 160px; + padding-top: 0px; + top:-18px; + left:10px; + z-index: 20; + background-color: #f90; + font-size : 70%; + +} + +.menutitle { + cursor:pointer; + padding: 3px 12px; + margin-left: 10px; + background-image: url('images/chapter.gif'); + background-repeat: no-repeat; + background-position: center left; + font-weight : bold; + + +} + +.menutitle:hover{text-decoration:underline;cursor: pointer;} + +#menu .menuitemgroup { + margin: 0px 0px 6px 8px; + padding: 0px; + font-weight : bold; } + +#menu .selectedmenuitemgroup{ + margin: 0px 0px 0px 8px; + padding: 0px; + font-weight : normal; + + } + +#menu .menuitem { + padding: 2px 0px 1px 13px; + background-image: url('images/page.gif'); + background-repeat: no-repeat; + background-position: center left; + font-weight : normal; + margin-left: 10px; +} + +#menu .menupage { + margin: 2px 0px 1px 10px; + padding: 0px 3px 0px 12px; + background-image: url('images/page.gif'); + background-repeat: no-repeat; + background-position: center left; + font-style : normal; +} +#menu .menupagetitle { + padding: 0px 0px 0px 1px; + font-style : normal; + border-style: solid; + border-width: 1px; + margin-right: 10px; + +} +#menu .menupageitemgroup { + padding: 3px 0px 4px 6px; + font-style : normal; + border-bottom: 1px solid ; + border-left: 1px solid ; + border-right: 1px solid ; + margin-right: 10px; +} +#menu .menupageitem { + font-style : normal; + font-weight : normal; + border-width: 0px; + font-size : 90%; +} +#menu #credit { + text-align: center; +} +#menu #credit2 { + text-align: center; + padding: 3px 3px 3px 3px; + background-color: #ffffff; +} +#menu .searchbox { + text-align: center; +} +#menu .searchbox form { + padding: 3px 3px; + margin: 0; +} +#menu .searchbox input { + font-size: 100%; +} + +#content { + padding: 20px 20px 20px 180px; + margin: 0; + font : small Verdana, Helvetica, sans-serif; + font-size : 80%; +} + +#content ul { + margin: 0; + padding: 0 25px; +} +#content li { + padding: 0 5px; +} +#feedback { + color: black; + background: #CFDCED; + text-align:center; + margin-top: 5px; +} +#feedback #feedbackto { + font-size: 90%; + color: black; +} +#footer { + clear: both; + position: relative; /* IE bugfix (http://www.dracos.co.uk/web/css/ie6floatbug/) */ + width: 100%; + background: #CFDCED; + border-top: solid 1px #4C6C8F; + color: black; +} +#footer .copyright { + position: relative; /* IE bugfix cont'd */ + padding: 5px; + margin: 0; + width: 45%; +} +#footer .lastmodified { + position: relative; /* IE bugfix cont'd */ + float: right; + width: 45%; + padding: 5px; + margin: 0; + text-align: right; +} +#footer a { color: white; } + +#footer #logos { + text-align: left; +} + + +/** + * Misc Styles + */ + +acronym { cursor: help; } +.boxed { background-color: #a5b6c6;} +.underlined_5 {border-bottom: solid 5px #4C6C8F;} +.underlined_10 {border-bottom: solid 10px #4C6C8F;} +/* ==================== snail trail ============================ */ + +.trail { + position: relative; /* IE bugfix cont'd */ + font-size: 70%; + text-align: right; + float: right; + margin: -10px 5px 0px 5px; + padding: 0; +} + +#motd-area { + position: relative; /* IE bugfix cont'd */ + float: right; + width: 35%; + background-color: #f0f0ff; + border-top: solid 1px #4C6C8F; + border-bottom: solid 1px #4C6C8F; + margin-bottom: 15px; + margin-left: 15px; + margin-right: 10%; + padding-bottom: 5px; + padding-top: 5px; +} + +#minitoc-area { + border-top: solid 1px #4C6C8F; + border-bottom: solid 1px #4C6C8F; + margin: 15px 10% 5px 15px; + /* margin-bottom: 15px; + margin-left: 15px; + margin-right: 10%;*/ + padding-bottom: 7px; + padding-top: 5px; +} +.minitoc { + list-style-image: url('images/current.gif'); + font-weight: normal; +} + +li p { + margin: 0; + padding: 0; +} + +.pdflink { + position: relative; /* IE bugfix cont'd */ + float: right; + margin: 0px 5px; + padding: 0; +} +.pdflink br { + margin-top: -10px; + padding-left: 1px; +} +.pdflink a { + display: block; + font-size: 70%; + text-align: center; + margin: 0; + padding: 0; +} + +.pdflink img { + display: block; + height: 16px; + width: 16px; +} +.xmllink { + position: relative; /* IE bugfix cont'd */ + float: right; + margin: 0px 5px; + padding: 0; +} +.xmllink br { + margin-top: -10px; + padding-left: 1px; +} +.xmllink a { + display: block; + font-size: 70%; + text-align: center; + margin: 0; + padding: 0; +} + +.xmllink img { + display: block; + height: 16px; + width: 16px; +} +.podlink { + position: relative; /* IE bugfix cont'd */ + float: right; + margin: 0px 5px; + padding: 0; +} +.podlink br { + margin-top: -10px; + padding-left: 1px; +} +.podlink a { + display: block; + font-size: 70%; + text-align: center; + margin: 0; + padding: 0; +} + +.podlink img { + display: block; + height: 16px; + width: 16px; +} + +.printlink { + position: relative; /* IE bugfix cont'd */ + float: right; +} +.printlink br { + margin-top: -10px; + padding-left: 1px; +} +.printlink a { + display: block; + font-size: 70%; + text-align: center; + margin: 0; + padding: 0; +} +.printlink img { + display: block; + height: 16px; + width: 16px; +} + +p.instruction { + display: list-item; + list-style-image: url('../images/instruction_arrow.png'); + list-style-position: outside; + margin-left: 2em; +} diff --git a/src/docs/cn/src/documentation/skins/pelt/images/chapter.gif b/src/docs/cn/src/documentation/skins/pelt/images/chapter.gif new file mode 100644 index 0000000000000000000000000000000000000000..d3d8245d0c7693b5b6c6f25ca9d615858656d4ad GIT binary patch literal 49 zcmZ?wbhEHbWMN=uXkcJiy6xEi|Nj+#vM@3*Ff!;c00Bsbfr-O~Pb~Az>JSYEYXC!` B3(^1p literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/chapter_open.gif b/src/docs/cn/src/documentation/skins/pelt/images/chapter_open.gif new file mode 100644 index 0000000000000000000000000000000000000000..eecce18b50a0146d663334eb5b38691fa40b4d5a GIT binary patch literal 49 zcmZ?wbhEHbWM^PuXkcJiy6xEi|Nj+#vM@3*Ff!;c00Bsbfr+Dqzfm%aH&TPa8UR61 B3ljhU literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/current.gif b/src/docs/cn/src/documentation/skins/pelt/images/current.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd82c082012faa682ecd4e68d2eedef9ae2e6231 GIT binary patch literal 54 zcmZ?wbhEHbdvgf9JlRm%f*ED|^)zR->+Co862^^pk!u5$EP!3fjzw8XU#}8Il-2 zEI`Z*Zh{lXkg>50Py~%EL5*|HpdHu^uz_@DjRE$?+OB>2cHigy_~CiltzA2q(dY-R zE0ws?)uol-wpiR0>Zwh8gwrE{IE4kjFcsa zE<)u6=*0rOQdlXmQsSg~b2v>_e&*;)omVU%Jn>|M%;yddYu#v-EI}s0b+HN;3oue* zQpwmBX(`VSO8MC}-CeIu#fheb@BCT0%4VJ)QmWBvMb)yUR4#8pr71Q^aZ=)y#HSK3 zi^EBYPE(AO)UWyiAN=;Wkbp|%%%IeP9kb@tPsPeiHEF9Vw+tJ-#7Rk}u8!&z%Kp{@mlFk3&u$Ct;y9Gvwjj5D*FIBO$!^50-oB?3Lr$5Eqo7T}kG=xr4bXpv< z*R5s2hBg2OdwSTmay3J5pCob)Pe6dk!R?o=fVuO#q_s7>Q>ALh8Y@Tzqa&PbKSJ$w z&E#upxTXuR!K0ET*c*tT*NLtS0W6A@QMF#>Raf`zl9=%LrG z(NhYzXXUD;0X283s6e9Dd0|~m^4KvDJaG4riJ9HtH#%5 zaygn>T9_F{)I}5FE|f$7HUxB-XnqrXz$VE+aIOd*cRo4pZbnIJuD_l|_iaJMF{b2v z6}7djx&K}&m8Sc#-9!PrU_5gRxDe1l5`6!(6;Mgig`AkVPSWw?R@KtNqOJE6WwThV z+4@nHho0%-^oygxpzfTX|wxJzZvc-fOu>C=>| zWlLH7!>vTQ9Nsy0-SQ1y|IGoCW5@W#+E(;vf`}qM|Il_CZf<3SfDQp$f?ERp-nl;S z+NTw;=$B7>lP1rNXI_F=E^cP=_6LZ{%5c{5*sUA+`*Xi$P8>5giWz;mgJ)WAMvsmX z#WAaY@?#plw2I^+xCzkb{lQLarr!d9k z_v$o7%i?F%JCApceRpoAeb3$ra3{b8hy|QJc!>RN8!%Ghyr<7QhJ!~2&s)|WI_2C8 zlX+9#2cBNKd`5+_uVl4q)Ka1AW^ksWoPTt7QWr&B9mSL(CUm+3ObDbQ5M6r>eco}V zyPH{2Ou_rXE^AhFTHXDg1OV)8Y+6!n%%QwCGo>*Mc!vy7E+AWiy9vi^%ya@W1crjg z0tN47w>4ipX7%r<;#~Gh_Wc?4%W8Z$P%Xp)AHtZQ<1PX^iU#9K^J87Fg6E{OgWcAy ze`OjtOmQE$IQ}S;cbYPp{R$ccVo@xF@LXyzMb|4n8(_dYPB{Cg6VBe)X-&uF81MO7 zeoIC54K*UVy+Vi^D}^YFgdmi%H3SkLIPab7_5R>lZ+EWYIZTJA00000NkvXXu0mjf DMgv2X literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/header_white_line.gif b/src/docs/cn/src/documentation/skins/pelt/images/header_white_line.gif new file mode 100644 index 0000000000000000000000000000000000000000..369cae8dcf2da7d30c4ed7a8781b6bdf95a022d6 GIT binary patch literal 37 pcmZ?wbh9u|6k%XwXkcLY|NsA?3y*XdfB+=Iz{JwhKa-Wg8UV|E3E%(# literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/info.png b/src/docs/cn/src/documentation/skins/pelt/images/info.png new file mode 100644 index 0000000000000000000000000000000000000000..2e53447e8c2446ea0f6a56fec811e1786e691d49 GIT binary patch literal 1320 zcmWlXZ&1?)7>7&1q8${icL>E5?6e0xt=eJLszo9c2$*4!0MS*JoAHQRSf*8T8ZdHE zdRib#rv*B$t7TU0vk_F6krFk# z{0M25qh^EI4M??m+775mn6kUQeL~QvCalpgYqHn@xlXRFsY7J;T8#q3zT}0 zu;LUag($-0k|C^~pi$aJ+k6t3L20L!v>^lo$Y9Rx2UH}^x-^6ZHrfE0PN-#QtCz1f z$hAb9uTRgoFxDjmDTUq~4U%GrF>-CTwtj@536oo*Mj+BAL(FDpH_5djlwFBglzL7_ zImJ4Y0yT+YMx>=BIuoEW@TH&(ra*%YrCmY|X|i|o6{wD~Tikw$3IUXOG{hP$UI}P` zNV`bOptuoZ-C~#(g27uJi_6d2y8*c#P~aNE3LEVTJtu+~HExxooWbm&tX?T%mZ4_8 znv4$qX=ww*Y5_<~btZ&z;;h@(_dw6OL7bDotl8-=iC<6|G$~}44$kAP9Ua1hVMbYI z(YHL_C!&vp+epy%d z_3j;s5joeyGfxrfn#PmK8C#pN@SD3&FD!}K(X#nWD%6oXH({C}Y6y*4m3X)(buAR@ z4_u-yOwl?l(jk_j&-{tbZdh$!_x1T+6Jg2bX;OMh!&bv=a;{VYmguFkd>YejL z(yTq&UT55&C3U5Wc1=z%)jo#Yy zen~|sWUbU>aWPdDk^bhLbiZ$$`@YGsl+Uv~3ilO$Jt!N&UyaY^nfEtyNxtf*>aZ0P zYs$CH`_7_B`7<&$#o^RQSmo zVQlJ$#Y0d3y_u4%5I*UAefd&)*3;{b6J4v+)5D0SPOme`?20|p-rCw|0gnzQ=TAF# z^l^V6aX8}eo%wKHvLh@tv_@JJd7i&)WJBOUUKy47jkq_-)i|*w;aVUrH|R!ZNY~pb U&-nRQwxE@~taLcd4Hh&10}nn9o^tnS&|T3i>qxFe$? f}PJadT6$68(tDnm{r-UW|L@jfU literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/label.gif b/src/docs/cn/src/documentation/skins/pelt/images/label.gif new file mode 100644 index 0000000000000000000000000000000000000000..c83a3893c5526efb52f2edab685a1b0d7a1ecc74 GIT binary patch literal 54 zcmZ?wbhEHbdhCYGe8D3oWGWGIAWq$;?3`UWs4{$yd~ fVqj#@VE_V<76vBXp8m=M4RQ+_jm%nu85yhr=NMS;ykzBV zGV@+Ib>8iG+0i+5o5%e;$DOmCbGDtGouBno)Pp@O`xkod^YDHAe&7q={KCBSjEXQs zia-R}v;dr7tR!PTU@gZjorczO*Y4(!3udEUXj^5nt6CcbI=M{9lA3*v!R*V{5Xk12*s*W`tyJQzcOyP zZ|4nGYCwl+^~R>oQ9yIziSOk@uI9c7MHdfo+O=dPhNjo`t2TAlmN1bw7PY!& zb8wiMUN#=~j?AJaqD?aaD8@$vs`?(gvBH&H+cp7{2^cJn$wdq^+uv$+z|MKKt+?hr z*QsL5i(y(cUzD}JiFa$qb^-fga2lYfPWKeWPkU;dXzH zDz+;0UGiO>WV7RjIU=PTtqnMrXIV?F-0jLxCcN%Rd*oPrek$=zU&fPf)RHo>wLjZ` v{OiZh;9_~M^1Bpx^As`Ho2BPVXIo0*@-_bK23aA9FY1)%eyY46N3#9^6k+17 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/printer.gif b/src/docs/cn/src/documentation/skins/pelt/images/printer.gif new file mode 100644 index 0000000000000000000000000000000000000000..a8d0d419c905e4754d17c24314d8c1449388bfa3 GIT binary patch literal 603 zcmd6kzfTiU9KavaO05;|svuef&N~om0e_)AU1X6T8y!esYdVom<`NTSI5k=a3sciX zb73%18Em5_?_x-axdUs$VmXNZB}bC%VxwSp6_waJ)d|kVIc)zPRqeIZZsP!%PWP&!rJ{ccrcVef_824V*rcNe`YK8X6u^&TVfiYDOC!)l_wikn`gg#xkmuz4&!! zCzsZ~Q+eXo?}^E*8nm^kOS`apx&1SHP xOSk{*ch5;mUqxD8)P4*PsMYcJGhc`tpL?Kv*ou)#zg(Cser$hB&OAcs)<55`ex3jT literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/images/success.png b/src/docs/cn/src/documentation/skins/pelt/images/success.png new file mode 100644 index 0000000000000000000000000000000000000000..96fcfea3225f0cbd8cda790dc352811fafde0075 GIT binary patch literal 1291 zcmV+m1@!ufP)&bhz z5bnJPc@Iw>rR$Xk0NnAP0=%b=G`t?HCJ;1;sS0GUaR^Poy(d)4L1!Z`B|uSw*8!8D z1>h1*q8RGKdru$=?;A%ZB_OKlg75{_YH&hNW(a$3KZtet`*CCTW|RqnCt6&9fL-$C zDR`VAOJA7@%7*R5r%~t_!pzTQ{PyECD&+v42uz$ZeUl8ZOTM%Yg!+h+nIH~LchAyC zG1xhRv*%9Z$h&VKs1PWGgNRZBQXUX%?&{cdP2ocD!(ST!+#jwNkiW-tkatpx$iKuDWS zjlmkan~AW!xEI~IUYz>&BtH857{(?B(L3A$QGsv>7uHrX&|ttObr0cOZ8RGP9>iGh zW?Z>CgO?8P$BOj@EL+Aj1LI!1pvMp{xF|nlMi(MNrlpRA51c)0HD~J1>JbH7( z*fz2os)`p6?T2-jQQXvrT;4%gtC0&SgfvxylmLTh?0CT8?*3i4Z}>^vxCq=Vl_457 z8uA{>z{6wDAe+hI*zu$IVd@*KzOx_Q16hbz2<5t&szK8dNK^(d^O(B&9kQ7m9^1SR zf1R5}xjbKue%s33Sk|=)znq`Kn@3;8=%zjl6!U;Xl=3)o3uh}POm;hk;QLFTVS4T& zio@gBw(1E?U$};#5}??<0e3CmiTO$ylP^Du!bld&*B6kIP)Q#b9id!3)r>hIrOymP`xd*0hyA5F0Rtdmn&^ z(AIAF^ryEm`_E;F2oAh533QiH+|Y+yzAY7X^0y||7ta8M)C4T?H$3d~#Ec+Y!r@Q$ z;qn>6)bFP;zI6~?{q0bRQyfmEhD^j|AWeM?nw22KO4S2}k3K(J8&|GC zzL0}Mv$`ud-Gm^L?u5<0hT@~sizf;X5;RL-Q6**~3r$2Rwa|#lH|K-! zJXbqLQ6z+jtJ|p&kODTAfegZ0Su_KGoV_;b1KLAGIq$uZC+9sG5jkNsC3UKnRklpk za8aLUQc+eDGAE)?GAFDiY)(aeP~zi_yj$be_!rlyryjz7fr7dsKvk!Vn>-EJ6yV zwCFYvz63#Z5fw@Zda#RSA<;vFP*!L?BpDNvInA8C*8kSS-e=CJT~KEP!3B%8_kLL4 z@Bgjuzu3U_ajgzJvSY3teW9oSl{HhZWS{V|#1F14p?K^260|%Xb}o4LqmAX@ssdp0 zUE9>h(~J_78VifNmT%d7)c|bY(i;$zA5)*e$RT8h=H})-Up#tG+f@O;v?Wi93nmyj zfE~aIijlQ-%YLasU~${N`TCPAP68# zVDBJ4fl`8UjAi|~DI3QG0G;=3m#WP$%7iI_v4gR%0|-ONfyqJ0A>ahf1-x`%!=%a; z0odD%TTRM4)9Ojsg*+1b7c;cXY7<=ZmtPi&3{?$$ME(^f+FT2Hjew!v$jJCga`&kyke7*t94E7%E69^?x z@(}XKsSlfSw)ed?rQD@E5KerChbTW{IoGdV@d=F65Qb3%;nV>omx((Fd#DN;W1Hi} zwqFu}?OVD~eY8P+Qn#G4{-^Y;-RbWD04Glz2TU#yC#WjK()}9aVAq=~iyi-@6<;LY z+XkTJIUaN&*r)9#lwLeS=^1;Eb6>uNBZoi4p<^d7qYM;4P!fnLQ~^;y&7cYtB9!6~ zuL4-}{|-!=vrdMw$f%zBTKJ68lnXh;>e1nU!rD&5qNzYB5SVuaeL1(%za=ta?rF|O9j)JzSq8m0RY&`2UZo! z|L#EhoUJmbGnEn;*AowR&`emeUJobVhPbr@;jDY{`7eyKiH(Tss5u&@AqqPBtF~*j z>)%D@1aZ(Q3PtBuiino zSCl44DCYwxF1B9H>X|Sg3K0M4^eF)A&I360;~#y0X?{qUOU48h593svYn8J=)WDi< zN&*yOz$c}9Eu7Nlo*Mi9!MkxNQ@AS0uq@dhKq^O!~}xz;K@Xd7Y-~+5Tgkg z4;n8VKqrH)>yRyD!_v`xTg$fo_}cDk={CBt?%=_L7Y}CQKjF!DdgqtC!5i1Rxzm5QpK z2~!*=8j6+^RFjFz5M@|438BhMFucKv>1;3p-TwHTham%D8D%61LJ^iMt7uu;wz&}% zK~fJ;qBoRUaQh&XWhh(LZlSnqH_b3b)m(6g zK+=dNG@3;&+^-;m=LJ!M4B%C*Af?S^ax==QAzA<_v`7S4HpL}He-Nm8UeOD#i~wLVu%rwe1afI z+(Y0VFOHKq?)B^mK}2Y#{GWePpygL(#X+o$wPAbweFC$Gv2yh($4v7Cwy&zTbtKo@ zS6N-()=14cpC71f8JKBz_S+7fXusd+8r?r-Yq~s+)%9=Mo#%$$cR9~YzG`T@8>qGK z*j_hwKHy!W`Klw%?kC@KLIfOb?t4*F=a_#vd)D!`^$tBheQa@fZeX@^a;V|_ZNk1q z_HxHB+zX9YjJ3S(?HG%_>v&vs^W?>+HoR}+)0>Z%9+|NZ*9J$LdY=6#2)?P|(^nss We^=By_~!n}n&~UIh@aF1*7FC9)cB|X literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/skins/pelt/note.txt b/src/docs/cn/src/documentation/skins/pelt/note.txt new file mode 100644 index 00000000000..d34c8db5ef4 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/note.txt @@ -0,0 +1,50 @@ +Notes for developer: + +--Legend------------------- +TODO -> blocker +DONE -> blocker +ToDo -> enhancement bug +done -> enhancement bug + +--Issues------------------- +- the corner images should be rendered through svg with the header color. +-> DONE +-> ToDo: get rid of the images and use only divs! + +- the menu points should be displayed "better". +-> DONE +-- Use the krysalis-site menu approach for the overall menu display. +-> DONE +-- Use the old lenya innermenu approch to further enhance the menu . +-> DONE + +- the content area needs some attention. +-> DONE +-- introduce the heading scheme from krysalis () +-> DONE +-> ToDo: make box with round corners +-> done: make underlined with variable border height +-> ToDo: make underline with bottom round corner +-- introduce the toc for each html-page +-> DONE +-- introduce the external-link-images. +-> DONE + +- the publish note should be where now only a border is. +Like
    +-> DONE +, but make it configurable. +-> DONE +- footer needs some attention +-> DONE +-- the footer do not have the color profile! Enable it! +-> DONE +-- the footer should as well contain a feedback link. +See http://issues.apache.org/eyebrowse/ReadMsg?listName=forrest-user@xml.apache.org&msgNo=71 +-> DONE + +- introduce credits alternativ location +-> DONE + +- border for published / breadtrail / menu /tab divs +-> ToDo \ No newline at end of file diff --git a/src/docs/cn/src/documentation/skins/pelt/skinconf.xsl b/src/docs/cn/src/documentation/skins/pelt/skinconf.xsl new file mode 100644 index 00000000000..2f8df12903c --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/skinconf.xsl @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/docs/cn/src/documentation/skins/pelt/xslt/fo/document-to-fo.xsl b/src/docs/cn/src/documentation/skins/pelt/xslt/fo/document-to-fo.xsl new file mode 100644 index 00000000000..0fb2a23731b --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/xslt/fo/document-to-fo.xsl @@ -0,0 +1,22 @@ + + + + + diff --git a/src/docs/cn/src/documentation/skins/pelt/xslt/html/book-to-menu.xsl b/src/docs/cn/src/documentation/skins/pelt/xslt/html/book-to-menu.xsl new file mode 100644 index 00000000000..5242fc85152 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/xslt/html/book-to-menu.xsl @@ -0,0 +1,53 @@ + + + + + + + + + +
  • + +

    +
      + +
  • +
    + + +
  • +
    + +
    + +
    +
    + + + + + +
    diff --git a/src/docs/cn/src/documentation/skins/pelt/xslt/html/document-to-html.xsl b/src/docs/cn/src/documentation/skins/pelt/xslt/html/document-to-html.xsl new file mode 100644 index 00000000000..2d337bf0d60 --- /dev/null +++ b/src/docs/cn/src/documentation/skins/pelt/xslt/html/document-to-html.xsl @@ -0,0 +1,154 @@ + + + + + + + + + +
    +

    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 literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/hdfsarchitecture.gif b/src/docs/cn/src/documentation/resources/images/hdfsarchitecture.gif new file mode 100644 index 0000000000000000000000000000000000000000..7bbe150dacdadc3f88059fb7119ce945566fdf5b GIT binary patch literal 17653 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⪙<0I)1W_|6R&n%OJdX8-;P*pt`UpM zsD?Pg6k5`~!i)Q|mPBnNAL*X$9b3atC?Tk0xsZO4?HsTnIzG+zhL{?B~}cOyY2RH7&vnE2O9 z+?Q~l^Q`_?kExU(B%dWe+5Iq>2EU&UT{kr9jv~?KmJQX#VHSBkzMl&1{qaL=nW=>B zFA(B6w=rtZF;T@APQDhqI$qn`;@2_%PUAMJK3S;#VYfo?ic%4-eYgM02~ zXHRtv)?#Vc&|V(oq=6$@ydzmvl?_45siwt?5-2okHs{n$boQovb~dqgf(}UZ^ml z9_>iIk82(Gk2Sj7#)TOAc5C#QJ03CD7znMZP(S9>PHu&UWray$SDqa-^(u2!nAiIJ zV^4oTZy0vCZmr-PklYnW4nftp3R-#nIar+1&VT5Yhx02C#P}Hi5j#$-1z%>W!)o236WTmWsdO1yDs5>o6$LmRj^}9Y zS^9MK`B2X5_yzrk^H*S*S6Z8n@}XU!Ik(+(u<5>|KwPQU<|b=zP~rMJ?{PEX1+TV+ zXQA!4eCVfULrSx2*~E_TM&}lO{;HT>r8!bbFV>PCKP0UZW`13y#6P41EXuqStM`6K zK6Ll5@duj%6@~3j+)^5)5``#lMO≥N$*zy5)@ST&9{1^n?wA_Yh=!d1qu;*K*|# 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 KPoKldE9@*kmH&Kb z{IKGf!+49>$=weXk<}X_u-y)lM4SmAeeH8l@R_$WAEKf6n;7aM#Zp$}SA#?yVc|pG zI2Nn9qX#DVg zmQ!f(cVsmL0>{S_l-$yt8%zM^<_Fd_S;)(JQPcp-A|r zI92rq1Q@nug=;oB0CFRA(-$zeUFlo?zT91x6+Pk#>Mw3ogigJH{sRFU-WzV(``@yV zjAea0*?xlIDplN?BgMpv1gA=Wm;MPhw6o+FxS^=r(OHXv1_sfDFG`RxMM#+nE>z^- zhhkFw_q+LP#93r1I*fR^^&XHkbz`GuNPTUT?34ay?68j#U;e7MK175K>Tr&{f(3B&_x0eOHPKmeFAOc9UTALvwfzH{eCu<{6L@W(WhrchWWsf&aj8;4rY1EIniv0Z)JlKy@H9nZZCyAO~Ox zoq--e0GKgM5s(I0fHj~AcmX0XGJpoy01SFVb9fFn$Z}XhmXH7cuaZtJ@~@UN|Fu(Y zG0cxx&m0I9V$~D740{Vrdh!@a#^HJLIRAB{|L=bNot!1NaCC6}*Dt)!81*}kNbU6- z$}zRJ%ECRJrL8of}2nWuP~ zde$({qA9OwFSYB4b7==++fA71o)LQLa5gIFoUe>ZuvEm^X?|r^Q4uSw-@2wdPJfQL zC>7hLl60NwVU=-s$&;-kBEv=$v!|+t-$&=WF`FDQ<{V?mE#@Vt{V+Kq`0!ZvuJH9c z-E}&PKSko2TOX*+-ucd~6Dw#R(o>dbEOD6mePDC{Ma%R8l=(?fD_wkOEL>g-t>{f2 zFv~bltj!uw`TTeYZ^fnV7F?R0>(S55Le56|mhasHx8g*MtoEes^o>-#dnGFCtg?+- z8Sg#mLceEM>@JrZ8%5ZOOB(-Jc@c*@Lc4cDM6cPJ`l0;sty05_U$f)uP&2W!iErxQ zVTY_>&Wrj76qvm9jdKq@$w~9SdvSGfK_yMU*T%-^SrK()(!Jlm9Gq>!vFDzazJ7L_ z(f#Z7H`ezXvAe#+C;W;R7Cy`OWJB(=pXj3P$B1sJc09vtC7uZO%*7S%RHa{(^ai87 zCvS1mGjA<5Fk;s)#&rW$U>)MN70Q@=mv?7PJD zTjyuEe`Qb%QAbygc8Ya7X1FWgn;$#6>*pEH2;ISQRsUW-`b~Y02^67@h@?db8|dD6 z#B?-9NFNA%gJzV(4H*IeW)T+r&1YfsCY}OV@KH7LZM;9usHS~yi3IFSMJrtWfGZ-e zHIAc@)(nofO7md)7}|YrWQ^piPXPN;xDg#Rx}1^FfpGFku=9|unTkGwP(eW+QXIN^ zU2HOm7L9(yR0l=Knj1(BIAAb2oTPAFh~vC4#yb-Q99KrO&WzIxf`tMhwn158EvR$C^Jozh)=0QiNEui0_rPd84@|Yd1zz29P7t(nwb!O@=5h+ zJLI8@p+7h~tVHARVllPSTj5tH)IldAl^RPIu)80qq6Or)i72#ae60-6Yit-8k=?;6L$HH{P=cc*esOes$7%(3I$@SHYF*0-=lt{!H z2CV6tks4_sSmo?5?2{}9BWYzrYQXGM0v~X-DpjX1iYk1ExR*c5en#g|`6bh>G89uL z*FRo8e_izMc`1tpmDmG}V>E=dYD_hq_giDnW|i4nE*CVZ*vRuI)k{LL_pmT?Q9srz zTtMqk$%Iv96lcj&TLJlNSkhY)R(wYqDZwC5SR}SgZk+1o#N>U>P2a!GGmui2S&rr* zT24N35~kaj@GkTBg7JBd#~aTacM!3V`pGsMo0qGgz|@k~A>(%TF|CQ=E8;4()A)Ld zA`j|{2D_B=rbY^kf@bVs-yyo*k!oVFuEe9$1caE_ts<}+idw>yIN%eT0^u;iB^C;eV_ix%*gQ;c*DFOSr$l`Q5#@gCh*X;|u;AXL}_& zXL>&)re<4#o4{f66)VA@h{oB>YZm!CWkhwU_QJ!7#niC}47KO0v-imaTEpEkp0e_p za^2Z}E;_vNEJpK>wTt!fjs7}Y#$wflbg%~zuvsEHor(@{k{LH#q*o(cbj*Z@x#*#w z2ue?sgZ;Sbg=Ba$G9;nBV4?ldD|cMsf~~%w!ajpi9BwYjBH)_jdS363OS4VtoX$xB zItwS?!{M(;eQbC7q^(f5?ZUCaLGY4w*zm5^#0mxr44B)GZFr&AFlDt?tYV?tFLt|`MI;}f7p9L-~ouWMU;^<_jK})*! zGe#Yc?fs1Fm9KP<5lcF*GsJt0dX;Am=GAZ;CNrk;;UZivUiI2W>e zntq?N9v7m=r{lW8;Md_!iy4fY3*H9K)x}&HlV9U%SGkNgifevA+El^Ut|}q5c`P#7 zX8k_Z`eijY&IHZ{8W$4&b8Yg*s?mzV4yY}It|Q?tz5n9tg3NA`>PrX}`OU@AF?&1d zsXxAWQq+cn-$-0qUpCo!Qq?l-7uD>`k{Xn`+>H%|fVr|v5}nyqZQvu3I-;6HLmXDZ zWzTp%_Ot?V40Vks4d!Rspd=GtwzDsmQ_k8-qgCME2^6;>aUIGL^X-3_$|VV^RA8#6evjGpekcFc{T|@T&(206&n!3F zw_i7k%r5)2Vw+d>JAB1Xl!4mAn4G;Ag18sTh{Mehk@*TpLaV=(qVKGdl@VUicFadC z3SI~QH&XLX?KzhOZ?J9dM0-6LiK+G_wwxy1MyrnU(AoN)lI6BS(}>k#+x(dRfh-4X zI#uqlTumWMqGE9jbavd|aPbLnV6VdQu2?U=IDI8ZuHwef9^VwzXk~My^7@ZrY3K6{ zH3$xj7Aza9AnR#HGxi7RQGtHw=Q zaJX|1$=~-morX#oECP=K3))wFtH%&;)=;z zt^jYM&!O$3mVPFJ-(6C5bal-PrgCUtwRJ}KZwunHETq#Tn^s<(ty~{>PfpD`@OEP! znziA{A5$ec24kro8=MT?w-+fN8wT|wvs=;hfaJS0acpw3OBlm7JD?ywIffGzF# z%bVr8HdPbZBaAix=_P}x9-m;Hrx);7Nl{5n?r|l$sceVdwQDRwR0e(8_%?Nz-^`N7 z-B#PzIxDwpt+IgEP_|g3+#zg5EBbTeV1uyrgtgIRGrVn%+lC?#H%X)U!u$+6wv?^1 zL#m^Wy~BE2Q1F=QS1%pt=r;GtTaHlJei#pl>P#%HfO${TYrD9|xb(_3i$;hmPEUbB zTlF{VXv4;83$7?JZ22T8yrIXMazW^i)vn6b>u4NlL>08m2>yA>-2ZwthOxYd=fk>j(=``d=M+TR zlu!jy`%3|XImr)hEgIk1)8-K#{UuzznEPug^sKP&rJMJ~Q#R?{Y;s))wn4E|9w=2% z>@AJ;PDd4U#M^3e7VV*GgoX|yJYA)`)5{_Xc^R*zyellTC!Jfo)T16&eA!Sz*!P6~=)e#`|X**)|* zHleWPvqO84jxWkC_PH7zM_8x@PK=H#$|1I`DV;!Aa66&9sN_Pd<;hF1xbl4~@@~P; zw9XZ*a{wz6tkaT^;EW%Ar2t1-q3Tih^H2H~)w>1IRmbfr72_#=&B>0g$NEDI6;}=O zDQT<&r{{+?VTcO!7(*fq(1+!QZ0VQ(^|kwDv59W(-g9>T7@9@>heOYV_F#ZkRo@q! z-DWV@Ymu#KX8vC%CneZ&J2ejb)gg>Ybj8W!ayWj3Kiz|P3H^diz@ z^M|Y)gLYNt$fxpi&!SY~mYGn%ad3J6&c4&dz z11cQ=084Pw|z+Ysl@7);HaXch~0sFFGF>N*OOCbI1+U86dFb-h{9 zUH4>;qJD)^#JW|}D`)d!&T|Ao+CUe-ps7=qEhvTU7ePsHU9BX+(}Lb5OF^@_{sJR37V-6?v45`;S-G)z!t7?VQ@; z_3?RhGhK@VSZiP$bGC;`v+ye~A-dMO7EA+dH(s|b>olHdbzJ+`gV`kRN!Gux&Ez;F z(12ar)D+J6=k&{>Awt{NiLHZ&+9xP$l&pPyr;zWpU2NhoRk1AoO>eE4dYyEVXZ%9$ zXwujuI#XqBJoq)GY(cfadVh#yT2;tJ93y|8H)e7L3(^1!{kI_SK5M|%%V~HGOW1Z;5r3jC=DP@0dgWs@$*SMd2QEQvUboD*MB&WBS@4fD zzfnE<*SAE~AIh!YIdCDv4$19(AKX&~$A)K5{e8NB92o00=VEO+it= z7b^`#E8viNw|*IszNIcy;071Ae7HNikQCrPp!elTu&|Lku~EYHF#wn1FIM4~SZBxk4V+q)#xD!fKa-K zM8^(ObqRp)Otdy8H4Qo@e_@6qo;CTIq5T3xhB_Th+8b!@7Yn_Uh}~ z@LO--=5@%hB}BoNeu@&l^|jAQ-;mt6x4^YX2!0TlxWou~g$D)Y^5~=81Xzs)xSrAk zl_vCnO&WbXQ*F1#f+TnMOxn|ST;lgQ?SlqvHu#B(LJ;SAkcTH|sTB*LoTc*bnO|}H zyU({#S0ET@=7pA_{jvjP;4i2?d8Guqk%+?WQqhz@h0~r9#GsMBP5~OE#gT{~a5npd zYVrs+a{P?Kn-QCBkFuWOhJ`~A00*;oqyvz>M7~R=KOv#9WxI)w2(MF4^W9s=#i)_! z=??S{O4WaiUG{=)=UzdBLrpsQ${_$q?Li=6(icXTQ*}_So1qp7$?k?_4&jq8C<`^G zjf4Y*FvENV=*8dNFZ*2c-XdI9HpPDs$*axsU7cFu=*!_$_+KZo8Q{O}t#1L#XM;Bk zrqUudo-ewWNHUXwQMfS#TDO;@F{Ff*ZN_%L(PAhJG~gws`w?O#SCRV3 z;9!Q-`p{!-;QM19%2L#fLCTD9L98;9NQ)`ejP_AGO#%XUQ-61F?7<0FZ)xdx@LQcb z7s4<}=9D%od@vj7*Xg^1UlF(0kfOGbHeq^#wh@ddc&L+tD-bWI(q%}gf&yCv_prI| zmwLVwKN*cc)rXrFJZ&^^3#y} zkB$p1kPJZ~d zF}C61{qDXNOm!@My$-L=ZumAc%lPu?kmc;|0#vnmv?_VK3Aaw>RobJgQ*XHOoO`!~ z5oQZ~I$5*mobr`j3RBe^MS9-wQz%WrsAo9^s$!1AX9QvF0M~KCM4nJ9j)bs|)Oh=E z64fTMC=9Mv*Y%=;(i;vQS!3h+v*5jD2w{TJXR(KhxCaiJ;R|UbU9t&Dve|xRD4BE& zYLTUWHfAzsYLTx8>G94PP4w17Y%FKaCu)j@D>C@lWCiCab=HQ9GK3yh4ajp@SdJs? z6&T%^=2K}p72o5mN2TbR^@IAQ8P?_Mv~7ikIsHSTh=(s+h>oA%^B;)Cdm^>zRxKvNq>TOeL@Hx7 zO8|k}g^ty*So?P-nOJJBg1g^02=wX85U);9zVLVu4nqm+a>h21j&0VYU%a9OJ6uCo zvv{OCSqR-4b3XHLG#mOilZ9BS?N*tuy-w`Lf?eLZ`m456u%~TugG$e+W+TfS!{EL4 z>mIPrw+ijgFzttu>|>?{fSQQ!nks1<&9*JGpYo`Fx0#{NCfSd3eMwHZbLFDl-Gg#% zp4512lI~`*+ojGsHD5xBEJtLBU(`KsE2qrcM_0VLxkP=xy}Y>PoJ#?uZg_zuzuM!| zieIp5bS$DR9z|4NC2e~mfRP&2b2S8VJWby$6DfV@Y~uvd^m!*jE_8{r!RIcQ3zfXD z_pn1Qd*VGmBb51Q+QA9rtA@(Ht@_npxfOc1zI%1EL$X)T%Pw^Re>yB37h^lTAM!E1 zx8vN889j|bJ;Ed;F(U9P$0@LKxBxO_97T)b?vXf{tL7PnEeZ^=26>W#OA*S=Qy!32 zTkfii9e=H-_jzX>l#D@Al^;o1*J!j{czQ3e{7iIf^fI)m%T|57J@MA@VuZZ^^SeG( z{^I7uTit0L`0RE+aJZ01r);_yvcF807t9P`&oxm{ZX>DMm$IBcEr+3?&U||Iio((Iq9i03 z5%;Y_#7CJ?Q5#(lRXxg}R?)g+mZ&6e5z|umtd*9Vi!Dw_r;a=4j15_J3KG-G5@vTL z%W4kk2!A6z04vKd3E;U82$8a`uu4e`*T3EIJipf}swwy}|3wS(KAbTW#O$?SxVBY7 zY^Gp&qy6X3!``tRM|pN%9-4}jMd+HWr9{*8ue`>7D5`U$+?&^=MQ$T$-AQ@Ya32S1 z#`+*d?9`ry$zKCp790JZVis*7m=sp*oiYacI*8k2x6#%%2dplW7`+yQ9R8V#At1LW6T*u3t@nn z-=5it0{SEewRS81at*qSRcDqbvQBR?6-WLo2lcoTzNs(Z>b~?%s*JAnu<5Crqs6U) zTPQK+M$+%-Cw-GpHIkAxUdN|ql*IIm!nLHY4rYT5@ZH0XtgZZOIMetURcC>Xp4;R@ znvaNvb^+$M+Y_wp<2TNuyFjsnRu1hvs7vaVx}gRh(wJ=I)%{PYRQ9#|Dw~^XQZ&v3 z&LF^JVoX({$tZQG2)$)!P)cJpBi2Agpt5#97g&X-MqjBR#myY%34Fep51U{B20IBk zIAxTI8A9RQ2y~;fLrqc6Jmh6XPyEu!gQ?};mkkP?x8=0|S(*b>eVR;snhuO77rC%j zR#joo%aM0(c@kzr9-7xsU#2_Z&tInBov%&=Uw9fW1z%Qs%Kz6MfuRFdo0phC1X9Y) z{yI7yE$kd_Y6BOVs)cBsuuNpB9C!EH<6PKiwq+J`ll`wd;&y?8Hn0X?zp*V{$-(<| zDkWLZQ%E~>qU&x^FYcheXoYEi|Gb-CoqW;O2qQe~lDP$=J*-B1;fE6CFFZylw8pr2 zukA?z=X4b%t@q&2_=&Q2=K~*wW;=pEi@VHDhc}7mGQ2sPHe?R#zk1H7JnXR9qR`4X z_vmwi=dOcOSei)vMk#|y)K8BBNi-ZMQ$(fht33x{*ie(aQA6w`;7WdNGLASb?r)B8 zo4N5QirQtHB7HBJ@fX!b!Nz`A<57yJ1jj24n}{5dT7XHLV~K8v0Bn~jx%GnJcqkQa z9$r$pv7$?YZ>Y_>lo{9kSSNe&S%VOFN%yTc#z+2P3G9RgjOzkEUj{s%TE^2;^X&y; z3UR0&k?#=97wC$YXTy@$=2)ezcsTmita7=Cz4S|jWnez+>i%9&jhH~jtk?Qs0eR7D zDsaCx-0IK3gzA99<}k#7?T$gJuJ{GX=9#d~q6gXYLjxnZbPAuD$_Th(h=`ZjTyx!5 z*Xs`MCw;D`$tReh@cP&D{uCL}seRia)w^bv7l+?xxA)Da4_YtmpL$mH@w&hq`p(Ym zVyQAVBx3A>?r8ZD*^^%tzOUhdiv2T?2!5*ixi|3v{AVcn`wbWf84d^t{4>blzh`s)!>IX8Dy{!# zAQ_n;ZJY5OA^7qQ6>|TC`M|K=5;(T3Od4L9=v;(b1#VoSSdVxW5bvYAO7lbe-uLqj z=AoA<7hXJXyNmS|dcuJM3gPnS{7zmRGrBZlCr($M_HQ}w(f#9o>YT=kV7NejTnsd| z(rEw;>UIuTqLiaF_$i;FqWp3|3JE}5G23j-&9>#YVqjO~G3DUlt(&6^ivn}X*`vo< zKC*@?;}U$?y^^-RS_iWOv*n(FpS9!?ugscMdO0_J9d6Q1P6tfT}x`ni!IsOPag zN};QkY{P|X8%w^SJZam;fv0t~`zYAu;tHFy{QbUvl}KL3#U^vvxK|q%LQYC-nP**= zY`CKJPFuDXiM<`}?*-~7h{T>%?fKZdi`(v1taI_WgWrSn)zlV0&2v4C8WX&(tmOo+ z+K=p_OpRzlzS^+WzsYTVgL~-D@i#3>aXsbTirYoQ9`H8SmY;x0c+g-#K@^H34y6z` zN70^N$|!e0TFW=H>@qY0e@y7_?2Nq`)v$AsJ_5LFWBvX zoOECQ^rPy%+#vx)+F@2}hm%~?KaQB_A~`1$#MX(d@pS4l*&HH}LNw7N?^ZR8_;^&L z{-4&P`85adC-F1VXME#-Z#{pem6gn#tPO1R&8-~i0RJlfp=VUOJ}S=X);y3C@(Hyv z9sjtalCaHXJrgDD^q- z!73F#m?^YmxmXB&r0N1J;))cOv|VU7nVBbpA`rruW12-a)y9+6nGL5omH-^Mww!3{ z7?>|1@iPHcXgAOe`PrbMF9;AKFr-8Pwz%vW5BZb(fgfHo&zmYY230m?fFxvE+p8QZfdXJ#bI51>%AXEsWrK(1s4*!UMx$jeg_0f zBmvYij=$D}Pgw-5R<}<0O$Q2!W~zyoarZ?Mv+Glxbvg>$YCVXlP9ewN=c4Td)~)!F zce#08sRW0|i`qe9VO&o*LTJt*C%9cG%(ORF0!w=&Qu-sU)8aFE)~Hkz3_KC=RIF{Q zLzv2+C}8B@+1TCcWTC7e`&AP%f!Y7Oo`Ec*ISNMLl)jb~`bi z{H-@5UqdHfze`wCUY5kZx!hdtJGritS&C`Yd%&^)O`C{`zlI=g;;LF39wN6Q8HIG6 zr(hhXvc(gZ-)BV4ElL6h?@$(~Pu8@N@j#O(E#0<5w~--G=d3TW;FK%zO$Nx;&0~5G zYGvhb##ZjS7~JTuS=?v-# zR{R@q;@_|;oj0fny&Mm-Cgq*84qdG0E0s%;1#6Gmke0Bp9t!=wh@Sz<>|##kmX@nw zr%7JH1=3%ijU{Aht$tN%(ONLr(p9{biK8PMz_gIu7U4AUhT`7(+_KN{G&{~!IVYdJ zo)=nV`Fw@rve!gUbMb6gSG2D)*IS+Dq+(y{K^u8l5H|nTK3Zsn=i@lP`vp6O`D*|> zG)xd6?g#Agt?>&Cb&$pJhH$f07k07E0DCRyP2LXm-HbsC$X3_P6iUsd1V&6X*=|M9 za}T000a>rsK*FQ@ra=zs6XX5((Rgz|BBGL#04#QCV*{fo+M5O1h^28m`mV^=TaW-M z^|<{)1r}wZDKF0>1@{r1j*^5fr%7EZ!oB{X6=1LLgTOUwr`{z^4nVavo?lqS%{p2y z-NOmU{j-Qxh1TdAzfvbwme+4F!a6Q*BE>Oho;zfV)7rXZ?;z8QH_W%77`Q;QVyoMhEb5URm2Qe9?)cZ*Z~Npoh*sr zHJRtsU5mT+S#ch=qF@ztSZ%^?`Y3i__gXLF(^1kUX(ffidZY#^e?BX6DyY|Is<>e@tR*wM@2*%4Pkg9>aDxw&Xw4@+#syLwQ=DJ*v>+j z=b*|z4@p`Lt=?t;d$wFL=PusLrd!@a5kU_^8iJWx8`!6U)fbv$$#U=VDal8JP~jTJ z3KSp=%v{#8=dfrt>Y#5;zqpMVo(?!Xuz^Q&J5n|8*$=zy{WpgbQ@3Fh;9kqQ;U}xo&eg+@cUI&R!BO^RM ziwPIHT6eXuUi8wae9Bg(;2q+{a3WQ}`5D8-?1AfMwmPr*fn*f&_GV0DCzz`pEm#Qk zk&x+Qd?-5U!T^&%vZ6MIlZDQZgzx$wD7OOjXyH;Ao2GoHPu?kVkvakvN@Schda{z; za8J@sf}gZ*agnt9WpWKVMaE7hs4qw(=Ay!fijH|ys^kOjp01y%YVz~dzxR{-Lt zrcs3Kck>LuO~e}ZB~vMl@_Ek=rsEqk;uKlwr9;p`^{=3X1N@?XDGykw$UVFM7s>ncf!3D{dG-G9$XQ?$5Nk z#<^RXNO8tGwPZz$Ps^euzD4_mq zXY*BBy1?+RIicR@1MBCW1{LcSGPpLbW79*Z0~ztaPTHWJTZaXX0s&>;T#`A(8=%H3>>>B^$Bqn`ge&2Rgs2?430b z>UVu=8ut_E#)Z2-M47v+r!ZI~8XNFRu*nl9u#1T>kMSW#4sJ!Shr@Q?eK=P9!0-!?AE z%><;CvzVz+O4b34M{>TtlXdKFUPweO}1;DF~f8?@hQkz;-{4aCuf?rh~1 z)VIV}s^+9(r|Xp(Sp;;LKX!2+UGyhSb`YCY^?gU}MY}o%)Q?-9^2@STM;=DId4d zHhw%Ul*3OPwcSMDREI1DN1tARTyb=G0UPMahGTkDcJ)v>{pPS@%WW8QlN+f9M6GDFEE~h|Y1_n)5JXp6NEVm}Y{gM?o_&9nI zSJ++A>!#ZM4&=>%%1zR_d0)kBcXMf7e8K7{PbybUcaQVEt&S)z=DcyOVQm)n%8m4a zwT-(==cpI>Xy!#2Vzr+BdvK0jw+d3i*7(`;14ln*&ghmmm23(k0VxO}M4CbC<)X=Dk{~bj=m0e?$`=8Yn^xFAq2NCNLx;FHWcV zi&`Fv`q}yq;9a3!7A-Be#i>tl6{qs83g6_-owTrJq81s#^mj_o;U_~(X0tX)MX7-5 zs;~mKqGs^rZG329b&Gi@#m#ehV8{H}k>rD}&?2&L;?{530;oBWIbS3TC0?sqO=QPJ zj93Zd4tm8(cs_cQ61he(P};jxE1~SUf-!vn?T3^w08)vL{2lA zOuxHk+O5hP zLZF++hHz%IDWo~&_2e5Z#S|<`t1wLK`L+Ra;N^L1Q=1ebv+szi`FX=Sxv3bcr#A=0 z5GVLBb`6dI27p*-J3%&pSiG6b?tZCj6z^b8Oq81E*%R9&pRLvLJgjp=xX)gC5i@f~ z9ak&9-uxH)ok~&&`h|pW1r$a*C)yS*l@BrNP}YyFr6t}`Jx0b%R3{N{-x`B;@Iivo zYVK4~SdD&mXzyh+wTDvr*`Vt)C*Nl`rttIF8`k?#sW>gzZ71^a(3$!b} z&LKNXSEnA(NPLox%_A9&z^h3mxE;$Ooih*lB#|f;pW0dMY@Hs)E|BQMpbJRWkYaY& zMVdAD1tE(9>5lFZdZi+-6X=vR4QEQP0-DX2lic#DULoYfu}~ASJ_|m_Wj}iC!Iu+> z{aiRRrcrJJ&kge!Xc@Lx)s(*JoznDFdq%f{6uw`{Dt8(;#j`L5fySXPcSzEVP|C!D zphDydl@uop9z^X>?6wf`@cfk;OE)J|c$F^L1VJVdKjN#xo(Jp9@#lEpaLL+BE80DK zrdih${leltTtwKvLUqMeNyM!?QQ%g|80r#vO?in-h|2X>!U>FcGrrvvPHhlfl(95V@eo7Er^p(r)6)k;tpm0YiNV+a;&m!Jv6ou#-Zj`2n%`Gu+Yp=EcG^S0R z_jt@_sS`0=#->oDA$%pPZJ7A5XhQ>_zB+M$r36cjFlBvA^Ru18DO+l4CEqH<&bNvy zi~f3y_{(8^>7>DiU0> zRnzSXw%b@Gu8{*Zq2{5_)p`k5ia2(UsV$Xl&IzxCU+Mwow&PZBL2Jy>W)tdScVe%R zR_>+4SIgX8W79MJ0B1|sNEkUfW|P}(_%=&~RifY>+jf10%}coZ*wh#7hPT*6oFWpw zQlqhi)$Ww1Q!+&ufgEcJAhxtpuo$=TjEdv0E2~_YjqOG`1*GJdh1By~^1xEG)GV^w zEWp{K8w2GQde&Iuen;<8Y}?1vp!e;lNyyuoIrvp++`u5|U68Ip__k}4Xz6Nllmbh~ zfyP~n6lRO}7Kp*>{2eL`Oc7bC$?>B<4jbv+(*-8KcEUqQvz)rgdW&E3v#5Vqex+kB zq6kuydfJ)X_hh_vxw5m$AcXimD1k()bVmT9y^~!ol5w?2nuLYdr{O(dfaJe{#vSVjWOyk+gb_)%4d;jjB zJ}QRXoOVi?LOjd$ldO>~Y4vv0B7Em4Ib0-%^ooG!?y7-53E?yJk75;ufuES1c z+bkGF|J&at=X!01**hpDbQDFDYiy+cqz?*iBzGYL+x?`VzhemZ2RIY^Lxq|xFPAo= znUa$O^1IJX1?eWbLuv1(%ywL=;#Rt{uG)@@1uewD^Esgaa>ephqy}paaz|iJku_&- zxF4F<9AERj=(1|Fs~vgabG}spG{7kul)aR*(g~*nR`~jYeEFKXZ8aK%eTk@x#rhy3 zM_!8QASL@a=Pf5nH%(R4s?>4#f1Av76vpAnkN2{a!!xxId3)_re%tsSrxODZIA~$8lC7);PwNhTuVEi;2PP|XYHTufc9w60XrS6ar z(qYxIpMGX9`WQb;Zqwqb?|r-8oh@Vu@hxN(IY8+C;*sm%cI^Bp6Z;O!r|OzIa0)^i z9XEAK`TT;Rui7Y0R;Wgz7@1!j^&+MIy?M8!}{6xQ< zqdaHk$2KA2WFaO+H4++sDKj1M-2!j#;VS~8Q;)nFzZ<#lx=nI?B$3BW-#`V?;cTe9 zNn(}&r{}47Qu{sf*RJ)uafm)^&(9O|v+zhJDK&V;eabdPnpkb3Q7Di?al?4vfw0}b z-;01zOx-bdAi_E$7l7>)w7#!LRkhd;e-PVGbxC0~Xg>$voY=<`v1)AWimD#Gf4}Cy z>{q#0WKA!l;(2rkU9(GeNc%R5lwBixk0+Uh$|;htL2ZrFc4=$xh%DPcyLBZXkBZe!E9udP$gWShyB* z!-^uybBA`U=`spoFkz%fx(b%QoEdhjb=%OqJac%O=%G+sJDAYRBSk;VmDg}e*3vK0 zoEbWDAc8U^yic#Ovxbb+c4?Ecj-+_j=DsS(qYd=0Ty>^!uk<{D)wG!hW z)-R3ocS=4KtHJ-n95m0{3$;WC0)qW~C;#7H*u(r`4jKah<~FAP!yVMnbX;LW@!r&p z)ql`;asC0-!lVy^n<}{jfmCIl&Z5=lcJrxo&cPmL)SN)I*sb8fj5uRE#ml2i0h z?eM63f9TK`$5T{GPoz93zfWNsNIuyu<$0mk>=#uQI?v+!PowDQU&5%-E&9GCG|(i4 zSVVC104l26p#_0q^B{gd;hzzhtRx>t4F{)7mLOkz z^=8)qOR*X&975AZlS&*nys@Yx80cyG?tb>ETNdPFe6cdyBpJU*iyk)F6{eQQxB8+t zQ~6W|Ug*BhDKZmIjxu}Dk>wa2qyk|F7GkBL#*i(mYWxiJx z#ezlZ4uO{f_)Y|m^r-1-B=C%JM^h|CX2b({C@t7Nf>l=b3#puv$)(K{_{OayC`&Q! zU{HKSY-2M%jhAKN5Fzh;9hOG*ZsXiJ;Ȋ_<90G&)U9Coz0;g*H;fg>j`Ur&?|) zX8O@A8KuL?{UIQknZG0;d8p?rDp%bWq>`#uh)G|S3(OfGq1-OR4LabR#(b54^)f<$ zZPhaon`jN3O)o>hu3d)f z`h2TQppL-MPw- zis2K)taX|(UqZU!G`p1Q_#G#Vi-251B-nkp1w|Gr07|s==WT6EDqf#dOTd16@au&N zL-L|nSq+xWV!$a=jhxapldI^>CBAeEYZVc<^x zMS5aYwcUt;Z#X4*H{iKU?QWeo6-;>;I-o&lVeuk&Ys-fV3sa9gOs_?~{Y|c!t$by8 zNJ+Ih0x@mg!_j-u>*5UqoV%hsLVJx>^U0Dz`}Wbo0E@;Jp_q>%-9_+Z^n0~nGV#t$ z#KbRT{wJj$s!&!(Jp1+n+WW5ci#xA{fHjo(0SrVN#OdtWB<7qe{pb&@>0aU&=h~>kaLe&xn z^^$oE~#v6PLUdL}T(5*wZaQN&1Xfo}NSe<9J_(sHELx zZryg0E=>crI`^2;W=)_si;akwV>Qr*WiV`q%vQlP~&9yysO{Wx2_3lKE?Hb zTz*LsOnU#c?%kZdQ5MY00_)1J$>UWpltC4q7DskGAT~o#ziuR`g_hj$AoLWS_45vj68}Laxt;>W-l7KPW%`xa@uPn&HAlFSd?sVGs z65ep#R*@iDMLfy5?}pM)j$rhTvHO%Kmaa_OYWCauK@0``o5T~VJqC%XKlfe>;<9Zj zB30@_f~ces6)bdXvUSSFY78^drrm$@~zGp-u6Q)XI2IwX=PlZkDge~UHZK_+Z zwTm2{D%q>&(tu5_6E>A|?yPu|TAWY?1s|=$^mQc*ZQ%Uq_2SHvWscRVp-SF#Q3Mvu~3&m&up>qo7ENC+;DCU7KCPF6gXTrUOz z^S!%8?iGjots!X|gaOV84-4|wu|$(+kUzJv<$g0U@Kf6k_H%ArP7)Xd1?W?$@zcnt z23fK}Y5S=^%YW8CJdb}jYx7Uuhnt=8KfV5b6xQE2faE{71Z{0h%uSsf^a19!HjWH* zjsSgtlcRyY1Kq!H{vNRKN4oQmeX4T*%|buR|HRQZG&Hs{{)Dx4pfhxGaQNTx<^KZx zfe?tNKLq7P+wmysh1U0d;)dv{=b!vZ({wK=6R}t;=QvMUg&eqP!&f3_<>Hk#m zKjGl~+4+A==0D*$*qS;RJO10n`s47=Gy3;>{rC?^e@^D_m;C>Z()k}y0JgSP|2Gu; z|5Kwsg}eWNVs5Q(YV1fSU=Fa>w{!e|U7}7PjCLX}AfP|%ABB&AD7^nXz)`4{xR z{uY0a@cARA@Rx^q0X{{XHD$pMHO5^8EW#K-K*(?$;C~qa)Ma^ literal 0 HcmV?d00001 diff --git a/src/docs/cn/src/documentation/resources/images/hdfsarchitecture.png b/src/docs/cn/src/documentation/resources/images/hdfsarchitecture.png new file mode 100644 index 0000000000000000000000000000000000000000..70e434c1dc619b5166cf4dd907cb0bae7b710574 GIT binary patch literal 40571 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 z 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