From 0a745b97e5dfd5984ba38e603939b51e062ff9e4 Mon Sep 17 00:00:00 2001 From: Tamas Penzes Date: Thu, 8 Nov 2018 15:14:50 +0100 Subject: [PATCH] ZOOKEEPER-3155: Remove Forrest XMLs and their build process from the project (branch 3.5) In this commit I've removed the forrest XML files and their result from the repository. I've also removed the process to generate HTML and PDF files from the forrest files, since it's not needed anymore. It also effects the test-github-pr.sh and test-patch.sh, since we do have less parameters for them (FORREST_HOME). Change-Id: I30ecdb181f19eed05d86838b12c75e0c03e33710 --- build.xml | 29 +- docs/bookkeeperConfig.html | 384 --- docs/bookkeeperConfig.pdf | Bin 13807 -> 0 bytes docs/bookkeeperOverview.html | 694 ----- docs/bookkeeperOverview.pdf | Bin 147574 -> 0 bytes docs/bookkeeperProgrammer.html | 1083 ------- docs/bookkeeperProgrammer.pdf | Bin 24965 -> 0 bytes docs/bookkeeperStarted.html | 448 --- docs/bookkeeperStarted.pdf | Bin 17115 -> 0 bytes docs/bookkeeperStream.html | 612 ---- docs/bookkeeperStream.pdf | Bin 13200 -> 0 bytes docs/broken-links.xml | 2 - docs/images/2pc.jpg | Bin 15174 -> 0 bytes docs/images/bk-overview.jpg | Bin 124211 -> 0 bytes docs/images/built-with-forrest-button.png | Bin 1936 -> 0 bytes docs/images/favicon.ico | Bin 766 -> 0 bytes docs/images/hadoop-logo.jpg | Bin 9443 -> 0 bytes docs/images/instruction_arrow.png | Bin 285 -> 0 bytes docs/images/state_dia.jpg | Bin 51364 -> 0 bytes docs/images/zkcomponents.jpg | Bin 30831 -> 0 bytes docs/images/zknamespace.jpg | Bin 35414 -> 0 bytes docs/images/zkperfRW-3.2.jpg | Bin 41948 -> 0 bytes docs/images/zkperfRW.jpg | Bin 161542 -> 0 bytes docs/images/zkperfreliability.jpg | Bin 69825 -> 0 bytes docs/images/zkservice.jpg | Bin 86790 -> 0 bytes docs/images/zookeeper_small.gif | Bin 4847 -> 0 bytes docs/index.html | 352 --- docs/index.pdf | Bin 12657 -> 0 bytes docs/javaExample.html | 900 ------ docs/javaExample.pdf | Bin 33818 -> 0 bytes docs/linkmap.html | 394 --- docs/linkmap.pdf | Bin 10826 -> 0 bytes docs/recipes.html | 1024 ------- docs/recipes.pdf | Bin 33856 -> 0 bytes docs/releasenotes.html | 2251 -------------- docs/skin/CommonMessages_de.xml | 23 - docs/skin/CommonMessages_en_US.xml | 23 - docs/skin/CommonMessages_es.xml | 23 - docs/skin/CommonMessages_fr.xml | 23 - docs/skin/basic.css | 167 -- docs/skin/breadcrumbs-optimized.js | 90 - docs/skin/breadcrumbs.js | 237 -- docs/skin/fontsize.js | 166 - docs/skin/getBlank.js | 40 - docs/skin/getMenu.js | 45 - docs/skin/images/README.txt | 1 - docs/skin/images/add.jpg | Bin 1142 -> 0 bytes docs/skin/images/apache-thanks.png | Bin 4840 -> 0 bytes docs/skin/images/built-with-cocoon.gif | Bin 2252 -> 0 bytes .../skin/images/built-with-forrest-button.png | Bin 1936 -> 0 bytes docs/skin/images/chapter.gif | Bin 49 -> 0 bytes docs/skin/images/chapter_open.gif | Bin 49 -> 0 bytes docs/skin/images/current.gif | Bin 54 -> 0 bytes docs/skin/images/error.png | Bin 1709 -> 0 bytes docs/skin/images/external-link.gif | Bin 71 -> 0 bytes docs/skin/images/fix.jpg | Bin 932 -> 0 bytes docs/skin/images/forrest-credit-logo.png | Bin 4633 -> 0 bytes docs/skin/images/hack.jpg | Bin 743 -> 0 bytes docs/skin/images/header_white_line.gif | Bin 37 -> 0 bytes docs/skin/images/info.png | Bin 1320 -> 0 bytes docs/skin/images/instruction_arrow.png | Bin 285 -> 0 bytes docs/skin/images/label.gif | Bin 54 -> 0 bytes docs/skin/images/page.gif | Bin 79 -> 0 bytes docs/skin/images/pdfdoc.gif | Bin 1008 -> 0 bytes docs/skin/images/poddoc.png | Bin 856 -> 0 bytes docs/skin/images/printer.gif | Bin 603 -> 0 bytes .../images/rc-b-l-15-1body-2menu-3menu.png | Bin 348 -> 0 bytes .../images/rc-b-r-15-1body-2menu-3menu.png | Bin 319 -> 0 bytes ...-5-1header-2tab-selected-3tab-selected.png | Bin 200 -> 0 bytes ...rc-t-l-5-1header-2searchbox-3searchbox.png | Bin 199 -> 0 bytes ...-5-1header-2tab-selected-3tab-selected.png | Bin 209 -> 0 bytes ...header-2tab-unselected-3tab-unselected.png | Bin 199 -> 0 bytes .../images/rc-t-r-15-1body-2menu-3menu.png | Bin 390 -> 0 bytes ...rc-t-r-5-1header-2searchbox-3searchbox.png | Bin 214 -> 0 bytes ...-5-1header-2tab-selected-3tab-selected.png | Bin 215 -> 0 bytes ...header-2tab-unselected-3tab-unselected.png | Bin 214 -> 0 bytes docs/skin/images/remove.jpg | Bin 1251 -> 0 bytes docs/skin/images/rss.png | Bin 360 -> 0 bytes docs/skin/images/spacer.gif | Bin 43 -> 0 bytes docs/skin/images/success.png | Bin 1291 -> 0 bytes docs/skin/images/txtdoc.png | Bin 784 -> 0 bytes docs/skin/images/update.jpg | Bin 990 -> 0 bytes docs/skin/images/valid-html401.png | Bin 2948 -> 0 bytes docs/skin/images/vcss.png | Bin 1134 -> 0 bytes docs/skin/images/warning.png | Bin 1215 -> 0 bytes docs/skin/images/xmldoc.gif | Bin 992 -> 0 bytes docs/skin/menu.js | 48 - docs/skin/note.txt | 50 - docs/skin/print.css | 54 - docs/skin/profile.css | 168 -- docs/skin/prototype.js | 1257 -------- docs/skin/screen.css | 587 ---- docs/zookeeperAdmin.html | 2669 ----------------- docs/zookeeperAdmin.pdf | Bin 102168 -> 0 bytes docs/zookeeperHierarchicalQuorums.html | 264 -- docs/zookeeperHierarchicalQuorums.pdf | Bin 6654 -> 0 bytes docs/zookeeperInternals.html | 793 ----- docs/zookeeperInternals.pdf | Bin 48811 -> 0 bytes docs/zookeeperJMX.html | 467 --- docs/zookeeperJMX.pdf | Bin 16475 -> 0 bytes docs/zookeeperObservers.html | 354 --- docs/zookeeperObservers.pdf | Bin 12868 -> 0 bytes docs/zookeeperOtherInfo.html | 230 -- docs/zookeeperOtherInfo.pdf | Bin 2947 -> 0 bytes docs/zookeeperOver.html | 692 ----- docs/zookeeperOver.pdf | Bin 302467 -> 0 bytes docs/zookeeperProgrammers.html | 2517 ---------------- docs/zookeeperProgrammers.pdf | Bin 144324 -> 0 bytes docs/zookeeperQuotas.html | 278 -- docs/zookeeperQuotas.pdf | Bin 11184 -> 0 bytes docs/zookeeperReconfig.html | 1250 -------- docs/zookeeperReconfig.pdf | Bin 62416 -> 0 bytes docs/zookeeperStarted.html | 618 ---- docs/zookeeperStarted.pdf | Bin 28078 -> 0 bytes docs/zookeeperTutorial.html | 925 ------ docs/zookeeperTutorial.pdf | Bin 34212 -> 0 bytes zookeeper-docs/forrest.properties | 109 - zookeeper-docs/src/documentation/README.txt | 7 - zookeeper-docs/src/documentation/TODO.txt | 227 -- .../classes/CatalogManager.properties | 37 - .../src/documentation/conf/cli.xconf | 328 -- .../src/documentation/content/xdocs/index.xml | 87 - .../content/xdocs/javaExample.xml | 664 ---- .../documentation/content/xdocs/recipes.xml | 688 ----- .../src/documentation/content/xdocs/site.xml | 97 - .../src/documentation/content/xdocs/tabs.xml | 36 - .../content/xdocs/zookeeperAdmin.xml | 2315 -------------- .../xdocs/zookeeperHierarchicalQuorums.xml | 75 - .../content/xdocs/zookeeperInternals.xml | 487 --- .../content/xdocs/zookeeperJMX.xml | 236 -- .../content/xdocs/zookeeperObservers.xml | 145 - .../content/xdocs/zookeeperOtherInfo.xml | 46 - .../content/xdocs/zookeeperOver.xml | 464 --- .../content/xdocs/zookeeperProgrammers.xml | 1872 ------------ .../content/xdocs/zookeeperQuotas.xml | 71 - .../content/xdocs/zookeeperReconfig.xml | 883 ------ .../content/xdocs/zookeeperStarted.xml | 419 --- .../content/xdocs/zookeeperTutorial.xml | 712 ----- .../documentation/resources/images/2pc.jpg | Bin 15174 -> 0 bytes .../resources/images/bk-overview.jpg | Bin 124211 -> 0 bytes .../resources/images/favicon.ico | Bin 766 -> 0 bytes .../resources/images/hadoop-logo.jpg | Bin 9443 -> 0 bytes .../resources/images/state_dia.dia | Bin 2597 -> 0 bytes .../resources/images/state_dia.jpg | Bin 51364 -> 0 bytes .../documentation/resources/images/zkarch.jpg | Bin 24535 -> 0 bytes .../resources/images/zkcomponents.jpg | Bin 30831 -> 0 bytes .../resources/images/zknamespace.jpg | Bin 35414 -> 0 bytes .../resources/images/zkperfRW-3.2.jpg | Bin 41948 -> 0 bytes .../resources/images/zkperfRW.jpg | Bin 161542 -> 0 bytes .../resources/images/zkperfreliability.jpg | Bin 69825 -> 0 bytes .../resources/images/zkservice.jpg | Bin 86790 -> 0 bytes .../resources/images/zookeeper_small.gif | Bin 4847 -> 0 bytes zookeeper-docs/src/documentation/skinconf.xml | 360 --- zookeeper-docs/status.xml | 74 - .../src/test/resources/test-github-pr.sh | 42 +- .../src/test/resources/test-patch.sh | 44 +- 156 files changed, 45 insertions(+), 32712 deletions(-) delete mode 100644 docs/bookkeeperConfig.html delete mode 100644 docs/bookkeeperConfig.pdf delete mode 100644 docs/bookkeeperOverview.html delete mode 100644 docs/bookkeeperOverview.pdf delete mode 100644 docs/bookkeeperProgrammer.html delete mode 100644 docs/bookkeeperProgrammer.pdf delete mode 100644 docs/bookkeeperStarted.html delete mode 100644 docs/bookkeeperStarted.pdf delete mode 100644 docs/bookkeeperStream.html delete mode 100644 docs/bookkeeperStream.pdf delete mode 100644 docs/broken-links.xml delete mode 100644 docs/images/2pc.jpg delete mode 100644 docs/images/bk-overview.jpg delete mode 100644 docs/images/built-with-forrest-button.png delete mode 100644 docs/images/favicon.ico delete mode 100644 docs/images/hadoop-logo.jpg delete mode 100644 docs/images/instruction_arrow.png delete mode 100644 docs/images/state_dia.jpg delete mode 100644 docs/images/zkcomponents.jpg delete mode 100644 docs/images/zknamespace.jpg delete mode 100644 docs/images/zkperfRW-3.2.jpg delete mode 100644 docs/images/zkperfRW.jpg delete mode 100644 docs/images/zkperfreliability.jpg delete mode 100644 docs/images/zkservice.jpg delete mode 100644 docs/images/zookeeper_small.gif delete mode 100644 docs/index.html delete mode 100644 docs/index.pdf delete mode 100644 docs/javaExample.html delete mode 100644 docs/javaExample.pdf delete mode 100644 docs/linkmap.html delete mode 100644 docs/linkmap.pdf delete mode 100644 docs/recipes.html delete mode 100644 docs/recipes.pdf delete mode 100644 docs/releasenotes.html delete mode 100644 docs/skin/CommonMessages_de.xml delete mode 100644 docs/skin/CommonMessages_en_US.xml delete mode 100644 docs/skin/CommonMessages_es.xml delete mode 100644 docs/skin/CommonMessages_fr.xml delete mode 100644 docs/skin/basic.css delete mode 100644 docs/skin/breadcrumbs-optimized.js delete mode 100644 docs/skin/breadcrumbs.js delete mode 100644 docs/skin/fontsize.js delete mode 100644 docs/skin/getBlank.js delete mode 100644 docs/skin/getMenu.js delete mode 100644 docs/skin/images/README.txt delete mode 100644 docs/skin/images/add.jpg delete mode 100644 docs/skin/images/apache-thanks.png delete mode 100644 docs/skin/images/built-with-cocoon.gif delete mode 100644 docs/skin/images/built-with-forrest-button.png delete mode 100644 docs/skin/images/chapter.gif delete mode 100644 docs/skin/images/chapter_open.gif delete mode 100644 docs/skin/images/current.gif delete mode 100644 docs/skin/images/error.png delete mode 100644 docs/skin/images/external-link.gif delete mode 100644 docs/skin/images/fix.jpg delete mode 100644 docs/skin/images/forrest-credit-logo.png delete mode 100644 docs/skin/images/hack.jpg delete mode 100644 docs/skin/images/header_white_line.gif delete mode 100644 docs/skin/images/info.png delete mode 100644 docs/skin/images/instruction_arrow.png delete mode 100644 docs/skin/images/label.gif delete mode 100644 docs/skin/images/page.gif delete mode 100644 docs/skin/images/pdfdoc.gif delete mode 100644 docs/skin/images/poddoc.png delete mode 100644 docs/skin/images/printer.gif delete mode 100644 docs/skin/images/rc-b-l-15-1body-2menu-3menu.png delete mode 100644 docs/skin/images/rc-b-r-15-1body-2menu-3menu.png delete mode 100644 docs/skin/images/rc-b-r-5-1header-2tab-selected-3tab-selected.png delete mode 100644 docs/skin/images/rc-t-l-5-1header-2searchbox-3searchbox.png delete mode 100644 docs/skin/images/rc-t-l-5-1header-2tab-selected-3tab-selected.png delete mode 100644 docs/skin/images/rc-t-l-5-1header-2tab-unselected-3tab-unselected.png delete mode 100644 docs/skin/images/rc-t-r-15-1body-2menu-3menu.png delete mode 100644 docs/skin/images/rc-t-r-5-1header-2searchbox-3searchbox.png delete mode 100644 docs/skin/images/rc-t-r-5-1header-2tab-selected-3tab-selected.png delete mode 100644 docs/skin/images/rc-t-r-5-1header-2tab-unselected-3tab-unselected.png delete mode 100644 docs/skin/images/remove.jpg delete mode 100644 docs/skin/images/rss.png delete mode 100644 docs/skin/images/spacer.gif delete mode 100644 docs/skin/images/success.png delete mode 100644 docs/skin/images/txtdoc.png delete mode 100644 docs/skin/images/update.jpg delete mode 100644 docs/skin/images/valid-html401.png delete mode 100644 docs/skin/images/vcss.png delete mode 100644 docs/skin/images/warning.png delete mode 100644 docs/skin/images/xmldoc.gif delete mode 100644 docs/skin/menu.js delete mode 100644 docs/skin/note.txt delete mode 100644 docs/skin/print.css delete mode 100644 docs/skin/profile.css delete mode 100644 docs/skin/prototype.js delete mode 100644 docs/skin/screen.css delete mode 100644 docs/zookeeperAdmin.html delete mode 100644 docs/zookeeperAdmin.pdf delete mode 100644 docs/zookeeperHierarchicalQuorums.html delete mode 100644 docs/zookeeperHierarchicalQuorums.pdf delete mode 100644 docs/zookeeperInternals.html delete mode 100644 docs/zookeeperInternals.pdf delete mode 100644 docs/zookeeperJMX.html delete mode 100644 docs/zookeeperJMX.pdf delete mode 100644 docs/zookeeperObservers.html delete mode 100644 docs/zookeeperObservers.pdf delete mode 100644 docs/zookeeperOtherInfo.html delete mode 100644 docs/zookeeperOtherInfo.pdf delete mode 100644 docs/zookeeperOver.html delete mode 100644 docs/zookeeperOver.pdf delete mode 100644 docs/zookeeperProgrammers.html delete mode 100644 docs/zookeeperProgrammers.pdf delete mode 100644 docs/zookeeperQuotas.html delete mode 100644 docs/zookeeperQuotas.pdf delete mode 100644 docs/zookeeperReconfig.html delete mode 100644 docs/zookeeperReconfig.pdf delete mode 100644 docs/zookeeperStarted.html delete mode 100644 docs/zookeeperStarted.pdf delete mode 100644 docs/zookeeperTutorial.html delete mode 100644 docs/zookeeperTutorial.pdf delete mode 100644 zookeeper-docs/forrest.properties delete mode 100644 zookeeper-docs/src/documentation/README.txt delete mode 100644 zookeeper-docs/src/documentation/TODO.txt delete mode 100644 zookeeper-docs/src/documentation/classes/CatalogManager.properties delete mode 100644 zookeeper-docs/src/documentation/conf/cli.xconf delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/index.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/javaExample.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/recipes.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/site.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/tabs.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperHierarchicalQuorums.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperInternals.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperJMX.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperObservers.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperOtherInfo.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperOver.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperProgrammers.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperQuotas.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperReconfig.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperStarted.xml delete mode 100644 zookeeper-docs/src/documentation/content/xdocs/zookeeperTutorial.xml delete mode 100755 zookeeper-docs/src/documentation/resources/images/2pc.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/bk-overview.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/favicon.ico delete mode 100644 zookeeper-docs/src/documentation/resources/images/hadoop-logo.jpg delete mode 100755 zookeeper-docs/src/documentation/resources/images/state_dia.dia delete mode 100755 zookeeper-docs/src/documentation/resources/images/state_dia.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zkarch.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zkcomponents.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zknamespace.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zkperfRW-3.2.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zkperfRW.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zkperfreliability.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zkservice.jpg delete mode 100644 zookeeper-docs/src/documentation/resources/images/zookeeper_small.gif delete mode 100644 zookeeper-docs/src/documentation/skinconf.xml delete mode 100644 zookeeper-docs/status.xml diff --git a/build.xml b/build.xml index 9854b482a11..0216a113af7 100644 --- a/build.xml +++ b/build.xml @@ -549,24 +549,6 @@ xmlns:cs="antlib:com.puppycrawl.tools.checkstyle.ant"> - - - - - - - - - - ') -} - - -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/docs/skin/images/README.txt b/docs/skin/images/README.txt deleted file mode 100644 index e0932f4a46d..00000000000 --- a/docs/skin/images/README.txt +++ /dev/null @@ -1 +0,0 @@ -The images in this directory are used if the current skin lacks them. diff --git a/docs/skin/images/add.jpg b/docs/skin/images/add.jpg deleted file mode 100644 index 06831eeb3ddf196c72e23557e0ed23ab5eebef14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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 diff --git a/docs/skin/images/apache-thanks.png b/docs/skin/images/apache-thanks.png deleted file mode 100644 index c0bea09cc8bcb9783fa3a67cb35db96f761002c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4840 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 diff --git a/docs/skin/images/built-with-forrest-button.png b/docs/skin/images/built-with-forrest-button.png deleted file mode 100644 index 4a787abe4dc7831124c5a3105d328309d671654e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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-IJSYEYXC!` B3(^1p diff --git a/docs/skin/images/chapter_open.gif b/docs/skin/images/chapter_open.gif deleted file mode 100644 index eecce18b50a0146d663334eb5b38691fa40b4d5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmZ?wbhEHbWM^PuXkcJiy6xEi|Nj+#vM@3*Ff!;c00Bsbfr+Dqzfm%aH&TPa8UR61 B3ljhU diff --git a/docs/skin/images/current.gif b/docs/skin/images/current.gif deleted file mode 100644 index fd82c082012faa682ecd4e68d2eedef9ae2e6231..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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 diff --git a/docs/skin/images/external-link.gif b/docs/skin/images/external-link.gif deleted file mode 100644 index ff2f7b2a0edcd149b45744fdcb0868e37143710c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71 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 P00000NkvXXu0mjfVyU~g diff --git a/docs/skin/images/hack.jpg b/docs/skin/images/hack.jpg deleted file mode 100644 index f38d50fe4e87cb4ede05ce4b6f124460b77f2a0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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 diff --git a/docs/skin/images/header_white_line.gif b/docs/skin/images/header_white_line.gif deleted file mode 100644 index 369cae8dcf2da7d30c4ed7a8781b6bdf95a022d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37 pcmZ?wbh9u|6k%XwXkcLY|NsA?3y*XdfB+=Iz{JwhKa-Wg8UV|E3E%(# diff --git a/docs/skin/images/info.png b/docs/skin/images/info.png deleted file mode 100644 index 2e53447e8c2446ea0f6a56fec811e1786e691d49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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 diff --git a/docs/skin/images/label.gif b/docs/skin/images/label.gif deleted file mode 100644 index c83a3893c5526efb52f2edab685a1b0d7a1ecc74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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 diff --git a/docs/skin/images/poddoc.png b/docs/skin/images/poddoc.png deleted file mode 100644 index a393df7372349f6df300eacf8d62987dba6f85aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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;0000axdUs$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 diff --git a/docs/skin/images/rc-b-l-15-1body-2menu-3menu.png b/docs/skin/images/rc-b-l-15-1body-2menu-3menu.png deleted file mode 100644 index cdb460a1da7304fcc2d5e326db43e27c6fa9b025..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 348 zcmeAS@N?(olHy`uVBq!ia0vp^{2|H(?D8gCb5n0T@z;^_M8K-LV zNdpBhc)B=-RNPAba`NT>^A2hWNr{PR3em>=;?_TBi7s_Hc|B+4`ZEU(9`l-)7A&jU zw*UXXiOVBh8rmIW1DhHR$*SJK%G8XnD!U=Fb1;@b0XlLnh)q2r=G4T4?@%xY8I4J~G88*bRV z@j)-^8Y2b$lol(aFVkF%GBiAm42+EveLZx3%wg?nJ=YY_W-h?yH diff --git a/docs/skin/images/rc-b-r-15-1body-2menu-3menu.png b/docs/skin/images/rc-b-r-15-1body-2menu-3menu.png deleted file mode 100644 index 3eff254fd179852394e8bd960eb1f610f05f2d4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^{2|H(?D8gCb5n0T@z;^_M8K-LV zNdpBpd%8G=RNPAba`NT>^A2hWO5w`f+{Qm=?YwdG#C08QO_zCTW@ch+#j>hKxom73 zTjv>7&YHT!RZ_*3)#Lh^W2X*H5PRiN6|!;D27?YTi6X6M9-jv*7;6_w9) zZgF9{q@i@+@P#?TM-Ci3*X5yc#3IzEqkW;KHHXLNh0Bbb8ks*SpICXq?9mk-FNPk6 z6&k9CCJ5ymU$9Q0)4KMskfp|2uWoLm2qtCuDGUxDJvbN`4z&r&mdK II;Vst0FZQVxBvhE diff --git a/docs/skin/images/rc-b-r-5-1header-2tab-selected-3tab-selected.png b/docs/skin/images/rc-b-r-5-1header-2tab-selected-3tab-selected.png deleted file mode 100644 index b175f27b16e19464241853fd16c8030d649b6d4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G(@^*J&_z!{$_AZ|c6yYrJh%9Dc;5!1sj8nDw zq=AAqo-U3d6}OVVoP7EJd;{Bz3#=?Zb_B4_oH;{c&DT)DCIv=EySz4*dTBPX4PtS6 mY}~b?ZBH1Y+4#!B*chy;Ss!r=G{ytXVeoYIb6Mw<&;$T7sy6BX diff --git a/docs/skin/images/rc-t-l-5-1header-2searchbox-3searchbox.png b/docs/skin/images/rc-t-l-5-1header-2searchbox-3searchbox.png deleted file mode 100644 index e9f4440d1f58d53fa16a2ea141bd04cb69f0a595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G(@^*J&_z!{$_AZ|c6yYrJh%9Dc;5!1sj8nDw zq=ACgo-U3d6}OWA@U#7wu&b{+{^9NK^tSr?dgBcZEcf=*o%!(mygu6k9cB)L#t;SW l23E(Y39JX26pSx0GKAXcJpW&R>>bb;22WQ%mvv4FO#q7bJP`l@ diff --git a/docs/skin/images/rc-t-l-5-1header-2tab-selected-3tab-selected.png b/docs/skin/images/rc-t-l-5-1header-2tab-selected-3tab-selected.png deleted file mode 100644 index f1e015b36c399a2d3a5879d69c3f31a82ee9f7bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G(@^*J&_z!{$_AZ|c6yYrJh%9Dc;5!1sj8nDw zq=AC2o-U3d6}OWA@Uz(0{Y#73_gCfc!(wyExc&dn9AFaCcpHE6!;`1hZT9v53>z4P wJ&s(UHx3vIVCg!0D03wUjP6A diff --git a/docs/skin/images/rc-t-l-5-1header-2tab-unselected-3tab-unselected.png b/docs/skin/images/rc-t-l-5-1header-2tab-unselected-3tab-unselected.png deleted file mode 100644 index e9f4440d1f58d53fa16a2ea141bd04cb69f0a595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G(@^*J&_z!{$_AZ|c6yYrJh%9Dc;5!1sj8nDw zq=ACgo-U3d6}OWA@U#7wu&b{+{^9NK^tSr?dgBcZEcf=*o%!(mygu6k9cB)L#t;SW l23E(Y39JX26pSx0GKAXcJpW&R>>bb;22WQ%mvv4FO#q7bJP`l@ diff --git a/docs/skin/images/rc-t-r-15-1body-2menu-3menu.png b/docs/skin/images/rc-t-r-15-1body-2menu-3menu.png deleted file mode 100644 index 29388b5efc9155a12ec75c7ea12940bf45d5b3fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmeAS@N?(olHy`uVBq!ia0vp^{2|H(?D8gCb5n0T@z;^_M8K-LV zNdpCcdAc};RNPAba`NT>^M?+dIdJscF$HbSBMB>)A4*uZ_=JL{)&U2O4GkUk_5X}& zetn+%@YUSqJlo~>r9|v_$Osmj3zsmE%8e hpTGaab)Hi`4ELR~XEsLn)B!_*!PC{xWt~$(69Dz9se1qb diff --git a/docs/skin/images/rc-t-r-5-1header-2searchbox-3searchbox.png b/docs/skin/images/rc-t-r-5-1header-2searchbox-3searchbox.png deleted file mode 100644 index 944ed73333d834f3509955d65fecc604393bf626..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G(@^*J&_z!{$_AZ|c6yYrJh%9Dc;5!1sj8nDw zq=AB7o-U3d6}OUWem!|spO%)!#^)EuW@jhJ=H{lxrpBi5bP0l+XkK DqZdXo diff --git a/docs/skin/images/rc-t-r-5-1header-2tab-unselected-3tab-unselected.png b/docs/skin/images/rc-t-r-5-1header-2tab-unselected-3tab-unselected.png deleted file mode 100644 index 944ed73333d834f3509955d65fecc604393bf626..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G(@^*J&_z!{$_AZ|c6yYrJh%9Dc;5!1sj8nDw zq=AB7o-U3d6}OUWem!|spO%)!#^)EuW@jhJ=H{lxrpBi5TL 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 diff --git a/docs/skin/images/rss.png b/docs/skin/images/rss.png deleted file mode 100644 index f0796ac886201eb43b7a15113e2deb1b32fa9a09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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|5zme0000&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_!rlyryjz7fr004R> 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`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 diff --git a/docs/skin/images/valid-html401.png b/docs/skin/images/valid-html401.png deleted file mode 100644 index 3855210c6c3c85c56f90221b3247fa664374b6bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2948 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 IbxsLQ074N#oB#j- diff --git a/docs/skin/images/warning.png b/docs/skin/images/warning.png deleted file mode 100644 index b81b2ce8a12f88ec3a4c64a910809e667cc20480..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1215 zcmV;w1VH7dsKvk!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 diff --git a/docs/skin/menu.js b/docs/skin/menu.js deleted file mode 100644 index 06ea471dc57..00000000000 --- a/docs/skin/menu.js +++ /dev/null @@ -1,48 +0,0 @@ -/* -* 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/docs/skin/note.txt b/docs/skin/note.txt deleted file mode 100644 index d34c8db5ef4..00000000000 --- a/docs/skin/note.txt +++ /dev/null @@ -1,50 +0,0 @@ -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/docs/skin/print.css b/docs/skin/print.css deleted file mode 100644 index aaa99319acd..00000000000 --- a/docs/skin/print.css +++ /dev/null @@ -1,54 +0,0 @@ -/* -* 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; -} \ No newline at end of file diff --git a/docs/skin/profile.css b/docs/skin/profile.css deleted file mode 100644 index eefaa88735d..00000000000 --- a/docs/skin/profile.css +++ /dev/null @@ -1,168 +0,0 @@ - - -/* ==================== 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); -} - -#top { background-color: #FFFFFF;} - -#top .header .current { background-color: #4C6C8F;} -#top .header .current a:link { color: #ffffff; } -#top .header .current a:visited { color: #ffffff; } -#top .header .current a:hover { color: #ffffff; } - -#tabs li { background-color: #E5E4D9 ;} -#tabs li a:link { color: #000000; } -#tabs li a:visited { color: #000000; } -#tabs li a:hover { color: #000000; } - -#level2tabs a.selected { background-color: #4C6C8F ;} -#level2tabs a:link { color: #ffffff; } -#level2tabs a:visited { color: #ffffff; } -#level2tabs a:hover { color: #ffffff; } - -#level2tabs { background-color: #E5E4D9;} -#level2tabs a.unselected:link { color: #000000; } -#level2tabs a.unselected:visited { color: #000000; } -#level2tabs a.unselected:hover { color: #000000; } - -.heading { background-color: #E5E4D9;} - -.boxed { background-color: #E5E4D9;} -.underlined_5 {border-bottom: solid 5px #E5E4D9;} -.underlined_10 {border-bottom: solid 10px #E5E4D9;} -table caption { -background-color: #E5E4D9; -color: #000000; -} - -#feedback { -color: #FFFFFF; -background: #4C6C8F; -text-align: center; -} -#feedback #feedbackto { -color: #FFFFFF; -} - -#publishedStrip { -color: #FFFFFF; -background: #4C6C8F; -} - -#publishedStrip { -color: #000000; -background: #E5E4D9; -} - -#menu .menupagetitle { background-color: #CFDCED; - color: #000000;} - -#menu { border-color: #999999;} -#menu .menupagetitle { border-color: #999999;} -#menu .menupageitemgroup { border-color: #999999;} - -#menu { background-color: #4C6C8F;} -#menu { color: #ffffff;} -#menu a:link { color: #ffffff;} -#menu a:visited { color: #ffffff;} -#menu a:hover { -background-color: #4C6C8F; -color: #ffffff;} - -#menu h1 { -color: #000000; -background-color: #cfdced; -} - -#top .searchbox { -background-color: #E5E4D9 ; -color: #000000; -} - -#menu .menupageitemgroup { -background-color: #E5E4D9; -} -#menu .menupageitem { -color: #000000; -} -#menu .menupageitem a:link { color: #000000;} -#menu .menupageitem a:visited { color: #000000;} -#menu .menupageitem a:hover { -background-color: #E5E4D9; -color: #000000; -} - -body{ -background-color: #ffffff; -color: #000000; -} -a:link { color:#0000ff} -a:visited { color:#009999} -a:hover { color:#6587ff} - - -.ForrestTable { background-color: #ccc;} - -.ForrestTable td { background-color: #ffffff;} - -.highlight { background-color: #ffff00;} - -.fixme { border-color: #c60;} - -.note { border-color: #069;} - -.warning { border-color: #900;} - -.code { border-color: #a5b6c6;} - -#footer { background-color: #E5E4D9;} -/* extra-css */ - - p.quote { - margin-left: 2em; - padding: .5em; - background-color: #f0f0f0; - font-family: monospace; - } - - pre.code { - margin-left: 0em; - padding: 0.5em; - background-color: #f0f0f0; - font-family: monospace; - } - - - - \ No newline at end of file diff --git a/docs/skin/prototype.js b/docs/skin/prototype.js deleted file mode 100644 index ed7d920cb5f..00000000000 --- a/docs/skin/prototype.js +++ /dev/null @@ -1,1257 +0,0 @@ -/* 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/docs/skin/screen.css b/docs/skin/screen.css deleted file mode 100644 index 221cbe54010..00000000000 --- a/docs/skin/screen.css +++ /dev/null @@ -1,587 +0,0 @@ -/* -* 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: 60%; -} -#footer .lastmodified { - position: relative; /* IE bugfix cont'd */ - float: right; - width: 30%; - 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; - float:right; - width: 35%; - background-color: #f0f0ff; - border: solid 1px #4C6C8F; - margin: 0px 0px 10px 10px; - padding: 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; -} - -.abstract{ - text-align:justify; - } - -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; -} \ No newline at end of file diff --git a/docs/zookeeperAdmin.html b/docs/zookeeperAdmin.html deleted file mode 100644 index 487c8538715..00000000000 --- a/docs/zookeeperAdmin.html +++ /dev/null @@ -1,2669 +0,0 @@ - - - - - - - -ZooKeeper Administrator's Guide - - - - - - - - - -
- - - -
- - - - - - - - - - - - -
-
-
-
- -
- - -
- -
- -   -
- - - - - -
- -

ZooKeeper Administrator's Guide

-

A Guide to Deployment and Administration

- - - - - - - - - -

Deployment

-
-

This section contains information about deploying Zookeeper and - covers these topics:

- -

The first two sections assume you are interested in installing - ZooKeeper in a production environment such as a datacenter. The final - section covers situations in which you are setting up ZooKeeper on a - limited basis - for evaluation, testing, or development - but not in a - production environment.

- -

System Requirements

- -

Supported Platforms

-

ZooKeeper consists of multiple components. Some components are - supported broadly, and other components are supported only on a smaller - set of platforms.

-
    - -
  • - -

    -Client is the Java client - library, used by applications to connect to a ZooKeeper ensemble. -

    - -
  • - -
  • - -

    -Server is the Java server - that runs on the ZooKeeper ensemble nodes.

    - -
  • - -
  • - -

    -Native Client is a client - implemented in C, similar to the Java client, used by applications - to connect to a ZooKeeper ensemble.

    - -
  • - -
  • - -

    -Contrib refers to multiple - optional add-on components.

    - -
  • - -
-

The following matrix describes the level of support committed for - running each component on different operating system platforms.

- - - -Support Matrix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Support Matrix
Operating SystemClientServerNative ClientContrib
GNU/LinuxDevelopment and ProductionDevelopment and ProductionDevelopment and ProductionDevelopment and Production
SolarisDevelopment and ProductionDevelopment and ProductionNot SupportedNot Supported
FreeBSDDevelopment and ProductionDevelopment and ProductionNot SupportedNot Supported
WindowsDevelopment and ProductionDevelopment and ProductionNot SupportedNot Supported
Mac OS XDevelopment OnlyDevelopment OnlyNot SupportedNot Supported
-

For any operating system not explicitly mentioned as supported in - the matrix, components may or may not work. The ZooKeeper community - will fix obvious bugs that are reported for other platforms, but there - is no full support.

- -

Required Software

-

ZooKeeper runs in Java, release 1.8 or greater (JDK 8 or - greater, FreeBSD support requires openjdk8). It runs as an - ensemble of ZooKeeper servers. Three - ZooKeeper servers is the minimum recommended size for an - ensemble, and we also recommend that they run on separate - machines. At Yahoo!, ZooKeeper is usually deployed on - dedicated RHEL boxes, with dual-core processors, 2GB of RAM, - and 80GB IDE hard drives.

- -

Clustered (Multi-Server) Setup

-

For reliable ZooKeeper service, you should deploy ZooKeeper in a - cluster known as an ensemble. As long as a majority - of the ensemble are up, the service will be available. Because Zookeeper - requires a majority, it is best to use an - odd number of machines. For example, with four machines ZooKeeper can - only handle the failure of a single machine; if two machines fail, the - remaining two machines do not constitute a majority. However, with five - machines ZooKeeper can handle the failure of two machines.

-
-
Note
-
- -

- As mentioned in the - ZooKeeper Getting Started Guide - , a minimum of three servers are required for a fault tolerant - clustered setup, and it is strongly recommended that you have an - odd number of servers. -

- -

Usually three servers is more than enough for a production - install, but for maximum reliability during maintenance, you may - wish to install five servers. With three servers, if you perform - maintenance on one of them, you are vulnerable to a failure on one - of the other two servers during that maintenance. If you have five - of them running, you can take one down for maintenance, and know - that you're still OK if one of the other four suddenly fails. -

- -

Your redundancy considerations should include all aspects of - your environment. If you have three ZooKeeper servers, but their - network cables are all plugged into the same network switch, then - the failure of that switch will take down your entire ensemble. -

- -
-
-

Here are the steps to setting a server that will be part of an - ensemble. These steps should be performed on every host in the - ensemble:

-
    - -
  1. - -

    Install the Java JDK. You can use the native packaging system - for your system, or download the JDK from:

    - - -

    -http://java.sun.com/javase/downloads/index.jsp -

    - -
  2. - - -
  3. - -

    Set the Java heap size. This is very important to avoid - swapping, which will seriously degrade ZooKeeper performance. To - determine the correct value, use load tests, and make sure you are - well below the usage limit that would cause you to swap. Be - conservative - use a maximum heap size of 3GB for a 4GB - machine.

    - -
  4. - - -
  5. - -

    Install the ZooKeeper Server Package. It can be downloaded - from: -

    - -

    - - - http://zookeeper.apache.org/releases.html - - -

    - -
  6. - - -
  7. - -

    Create a configuration file. This file can be called anything. - Use the following settings as a starting point:

    - - -
    -tickTime=2000
    -dataDir=/var/lib/zookeeper/
    -clientPort=2181
    -initLimit=5
    -syncLimit=2
    -server.1=zoo1:2888:3888
    -server.2=zoo2:2888:3888
    -server.3=zoo3:2888:3888
    - - -

    You can find the meanings of these and other configuration - settings in the section Configuration Parameters. A word - though about a few here:

    - - -

    Every machine that is part of the ZooKeeper ensemble should know - about every other machine in the ensemble. You accomplish this with - the series of lines of the form server.id=host:port:port. The parameters host and port are straightforward. You attribute the - server id to each machine by creating a file named - myid, one for each server, which resides in - that server's data directory, as specified by the configuration file - parameter dataDir.

    -
  8. - - -
  9. -

    The myid file - consists of a single line containing only the text of that machine's - id. So myid of server 1 would contain the text - "1" and nothing else. The id must be unique within the - ensemble and should have a value between 1 and 255. IMPORTANT: if you - enable extended features such as TTL Nodes (see below) the id must be - between 1 and 254 due to internal limitations.

    - -
  10. - - -
  11. - -

    If your configuration file is set up, you can start a - ZooKeeper server:

    - - -

    -$ java -cp zookeeper.jar:lib/slf4j-api-1.7.5.jar:lib/slf4j-log4j12-1.7.5.jar:lib/log4j-1.2.17.jar:conf \ - org.apache.zookeeper.server.quorum.QuorumPeerMain zoo.cfg - -

    - - -

    QuorumPeerMain starts a ZooKeeper server, - JMX - management beans are also registered which allows - management through a JMX management console. - The ZooKeeper JMX - document contains details on managing ZooKeeper with JMX. -

    - - -

    See the script bin/zkServer.sh, - which is included in the release, for an example - of starting server instances.

    - - -
  12. - - -
  13. - -

    Test your deployment by connecting to the hosts:

    - - -

    In Java, you can run the following command to execute - simple operations:

    - - -

    -$ bin/zkCli.sh -server 127.0.0.1:2181 -

    - -
  14. - -
- -

Single Server and Developer Setup

-

If you want to setup ZooKeeper for development purposes, you will - probably want to setup a single server instance of ZooKeeper, and then - install either the Java or C client-side libraries and bindings on your - development machine.

-

The steps to setting up a single server instance are the similar - to the above, except the configuration file is simpler. You can find the - complete instructions in the Installing and - Running ZooKeeper in Single Server Mode section of the ZooKeeper Getting Started - Guide.

-

For information on installing the client side libraries, refer to - the Bindings - section of the ZooKeeper - Programmer's Guide.

-
- - - -

Administration

-
-

This section contains information about running and maintaining - ZooKeeper and covers these topics:

- - -

Designing a ZooKeeper Deployment

-

The reliablity of ZooKeeper rests on two basic assumptions.

-
    - -
  1. -

    Only a minority of servers in a deployment - will fail. Failure in this context - means a machine crash, or some error in the network that - partitions a server off from the majority.

    - -
  2. - -
  3. -

    Deployed machines operate correctly. To - operate correctly means to execute code correctly, to have - clocks that work properly, and to have storage and network - components that perform consistently.

    - -
  4. - -
-

The sections below contain considerations for ZooKeeper - administrators to maximize the probability for these assumptions - to hold true. Some of these are cross-machines considerations, - and others are things you should consider for each and every - machine in your deployment.

- -

Cross Machine Requirements

-

For the ZooKeeper service to be active, there must be a - majority of non-failing machines that can communicate with - each other. To create a deployment that can tolerate the - failure of F machines, you should count on deploying 2xF+1 - machines. Thus, a deployment that consists of three machines - can handle one failure, and a deployment of five machines can - handle two failures. Note that a deployment of six machines - can only handle two failures since three machines is not a - majority. For this reason, ZooKeeper deployments are usually - made up of an odd number of machines.

-

To achieve the highest probability of tolerating a failure - you should try to make machine failures independent. For - example, if most of the machines share the same switch, - failure of that switch could cause a correlated failure and - bring down the service. The same holds true of shared power - circuits, cooling systems, etc.

- -

Single Machine Requirements

-

If ZooKeeper has to contend with other applications for - access to resources like storage media, CPU, network, or - memory, its performance will suffer markedly. ZooKeeper has - strong durability guarantees, which means it uses storage - media to log changes before the operation responsible for the - change is allowed to complete. You should be aware of this - dependency then, and take great care if you want to ensure - that ZooKeeper operations aren’t held up by your media. Here - are some things you can do to minimize that sort of - degradation: -

-
    - -
  • - -

    ZooKeeper's transaction log must be on a dedicated - device. (A dedicated partition is not enough.) ZooKeeper - writes the log sequentially, without seeking Sharing your - log device with other processes can cause seeks and - contention, which in turn can cause multi-second - delays.

    - -
  • - - -
  • - -

    Do not put ZooKeeper in a situation that can cause a - swap. In order for ZooKeeper to function with any sort of - timeliness, it simply cannot be allowed to swap. - Therefore, make certain that the maximum heap size given - to ZooKeeper is not bigger than the amount of real memory - available to ZooKeeper. For more on this, see - Things to Avoid - below.

    - -
  • - -
- -

Provisioning

-

- -

Things to Consider: ZooKeeper Strengths and Limitations

-

- -

Administering

-

- -

Maintenance

-

Little long term maintenance is required for a ZooKeeper - cluster however you must be aware of the following:

- -

Ongoing Data Directory Cleanup

-

The ZooKeeper Data - Directory contains files which are a persistent copy - of the znodes stored by a particular serving ensemble. These - are the snapshot and transactional log files. As changes are - made to the znodes these changes are appended to a - transaction log. Occasionally, when a log grows large, a - snapshot of the current state of all znodes will be written - to the filesystem and a new transaction log file is created - for future transactions. During snapshotting, ZooKeeper may - continue appending incoming transactions to the old log file. - Therefore, some transactions which are newer than a snapshot - may be found in the last transaction log preceding the - snapshot. -

-

A ZooKeeper server will not remove - old snapshots and log files when using the default - configuration (see autopurge below), this is the - responsibility of the operator. Every serving environment is - different and therefore the requirements of managing these - files may differ from install to install (backup for example). -

-

The PurgeTxnLog utility implements a simple retention - policy that administrators can use. The API docs contains details on - calling conventions (arguments, etc...). -

-

In the following example the last count snapshots and - their corresponding logs are retained and the others are - deleted. The value of <count> should typically be - greater than 3 (although not required, this provides 3 backups - in the unlikely event a recent log has become corrupted). This - can be run as a cron job on the ZooKeeper server machines to - clean up the logs daily.

-
 java -cp zookeeper.jar:lib/slf4j-api-1.7.5.jar:lib/slf4j-log4j12-1.7.5.jar:lib/log4j-1.2.17.jar:conf org.apache.zookeeper.server.PurgeTxnLog <dataDir> <snapDir> -n <count>
-

Automatic purging of the snapshots and corresponding - transaction logs was introduced in version 3.4.0 and can be - enabled via the following configuration parameters autopurge.snapRetainCount and autopurge.purgeInterval. For more on - this, see Advanced Configuration - below.

- -

Debug Log Cleanup (log4j)

-

See the section on logging in this document. It is - expected that you will setup a rolling file appender using the - in-built log4j feature. The sample configuration file in the - release tar's conf/log4j.properties provides an example of - this. -

- -

Supervision

-

You will want to have a supervisory process that manages - each of your ZooKeeper server processes (JVM). The ZK server is - designed to be "fail fast" meaning that it will shutdown - (process exit) if an error occurs that it cannot recover - from. As a ZooKeeper serving cluster is highly reliable, this - means that while the server may go down the cluster as a whole - is still active and serving requests. Additionally, as the - cluster is "self healing" the failed server once restarted will - automatically rejoin the ensemble w/o any manual - interaction.

-

Having a supervisory process such as daemontools or - SMF - (other options for supervisory process are also available, it's - up to you which one you would like to use, these are just two - examples) managing your ZooKeeper server ensures that if the - process does exit abnormally it will automatically be restarted - and will quickly rejoin the cluster.

-

It is also recommended to configure the ZooKeeper server process to - terminate and dump its heap if an - OutOfMemoryError occurs. This is achieved - by launching the JVM with the following arguments on Linux and Windows - respectively. The zkServer.sh and - zkServer.cmd scripts that ship with ZooKeeper set - these options. -

-
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p'
-
"-XX:+HeapDumpOnOutOfMemoryError" "-XX:OnOutOfMemoryError=cmd /c taskkill /pid %%%%p /t /f"
- -

Monitoring

-

The ZooKeeper service can be monitored in one of two - primary ways; 1) the command port through the use of 4 letter words and 2) JMX. See the appropriate section for - your environment/requirements.

- -

Logging

-

- ZooKeeper uses SLF4J - version 1.7.5 as its logging infrastructure. For backward compatibility it is bound to - LOG4J but you can use - LOGBack - or any other supported logging framework of your choice. -

-

- The ZooKeeper default log4j.properties - file resides in the conf directory. Log4j requires that - log4j.properties either be in the working directory - (the directory from which ZooKeeper is run) or be accessible from the classpath. -

-

For more information about SLF4J, see - its manual.

-

For more information about LOG4J, see - Log4j Default Initialization Procedure - of the log4j manual.

- -

Troubleshooting

-
- -
- Server not coming up because of file corruption -
-
-

A server might not be able to read its database and fail to come up because of - some file corruption in the transaction logs of the ZooKeeper server. You will - see some IOException on loading ZooKeeper database. In such a case, - make sure all the other servers in your ensemble are up and working. Use "stat" - command on the command port to see if they are in good health. After you have verified that - all the other servers of the ensemble are up, you can go ahead and clean the database - of the corrupt server. Delete all the files in datadir/version-2 and datalogdir/version-2/. - Restart the server. -

-
- -
- -

Configuration Parameters

-

ZooKeeper's behavior is governed by the ZooKeeper configuration - file. This file is designed so that the exact same file can be used by - all the servers that make up a ZooKeeper server assuming the disk - layouts are the same. If servers use different configuration files, care - must be taken to ensure that the list of servers in all of the different - configuration files match.

-
-
Note
-
- -

In 3.5.0 and later, some of these parameters should be placed in - a dynamic configuration file. If they are placed in the static - configuration file, ZooKeeper will automatically move them over to the - dynamic configuration file. See - Dynamic Reconfiguration for more information.

- -
-
- -

Minimum Configuration

-

Here are the minimum configuration keywords that must be defined - in the configuration file:

-
- -
-clientPort -
-
-

the port to listen for client connections; that is, the - port that clients attempt to connect to.

-
- - -
-secureClientPort -
-
-

the port to listen on for secure client connections using SSL. - - clientPort specifies - the port for plaintext connections while - secureClientPort specifies the port for SSL - connections. Specifying both enables mixed-mode while omitting - either will disable that mode.

-

Note that SSL feature will be enabled when user plugs-in - zookeeper.serverCnxnFactory, zookeeper.clientCnxnSocket as Netty.

-
- - -
-dataDir -
-
-

the location where ZooKeeper will store the in-memory - database snapshots and, unless specified otherwise, the - transaction log of updates to the database.

-
-
Note
-
- -

Be careful where you put the transaction log. A - dedicated transaction log device is key to consistent good - performance. Putting the log on a busy device will adversely - effect performance.

- -
-
-
- - -
-tickTime -
-
-

the length of a single tick, which is the basic time unit - used by ZooKeeper, as measured in milliseconds. It is used to - regulate heartbeats, and timeouts. For example, the minimum - session timeout will be two ticks.

-
- -
- -

Advanced Configuration

-

The configuration settings in the section are optional. You can - use them to further fine tune the behaviour of your ZooKeeper servers. - Some can also be set using Java system properties, generally of the - form zookeeper.keyword. The exact system - property, when available, is noted below.

-
- -
-dataLogDir -
-
-

(No Java system property)

-

This option will direct the machine to write the - transaction log to the dataLogDir rather than the dataDir. This allows a dedicated log - device to be used, and helps avoid competition between logging - and snaphots.

-
-
Note
-
- -

Having a dedicated log device has a large impact on - throughput and stable latencies. It is highly recommened to - dedicate a log device and set dataLogDir to point to a directory on - that device, and then make sure to point dataDir to a directory - not residing on that device.

- -
-
-
- - -
-globalOutstandingLimit -
-
-

(Java system property: zookeeper.globalOutstandingLimit.)

-

Clients can submit requests faster than ZooKeeper can - process them, especially if there are a lot of clients. To - prevent ZooKeeper from running out of memory due to queued - requests, ZooKeeper will throttle clients so that there is no - more than globalOutstandingLimit outstanding requests in the - system. The default limit is 1,000.

-
- - -
-preAllocSize -
-
-

(Java system property: zookeeper.preAllocSize)

-

To avoid seeks ZooKeeper allocates space in the - transaction log file in blocks of preAllocSize kilobytes. The - default block size is 64M. One reason for changing the size of - the blocks is to reduce the block size if snapshots are taken - more often. (Also, see snapCount).

-
- - -
-snapCount -
-
-

(Java system property: zookeeper.snapCount)

-

ZooKeeper records its transactions using snapshots and - a transaction log (think write-ahead log).The number of - transactions recorded in the transaction log before a snapshot - can be taken (and the transaction log rolled) is determined - by snapCount. In order to prevent all of the machines in the quorum - from taking a snapshot at the same time, each ZooKeeper server - will take a snapshot when the number of transactions in the transaction log - reaches a runtime generated random value in the [snapCount/2+1, snapCount] - range.The default snapCount is 100,000.

-
- - -
-maxClientCnxns -
-
-

(No Java system property)

-

Limits the number of concurrent connections (at the socket - level) that a single client, identified by IP address, may make - to a single member of the ZooKeeper ensemble. This is used to - prevent certain classes of DoS attacks, including file - descriptor exhaustion. The default is 60. Setting this to 0 - entirely removes the limit on concurrent connections.

-
- - -
-clientPortAddress -
-
-

-New in 3.3.0: the - address (ipv4, ipv6 or hostname) to listen for client - connections; that is, the address that clients attempt - to connect to. This is optional, by default we bind in - such a way that any connection to the clientPort for any - address/interface/nic on the server will be - accepted.

-
- - -
-minSessionTimeout -
-
-

(No Java system property)

-

-New in 3.3.0: the - minimum session timeout in milliseconds that the server - will allow the client to negotiate. Defaults to 2 times - the tickTime.

-
- - -
-maxSessionTimeout -
-
-

(No Java system property)

-

-New in 3.3.0: the - maximum session timeout in milliseconds that the server - will allow the client to negotiate. Defaults to 20 times - the tickTime.

-
- - -
-fsync.warningthresholdms -
-
-

(Java system property: zookeeper.fsync.warningthresholdms)

-

-New in 3.3.4: A - warning message will be output to the log whenever an - fsync in the Transactional Log (WAL) takes longer than - this value. The values is specified in milliseconds and - defaults to 1000. This value can only be set as a - system property.

-
- - -
-autopurge.snapRetainCount -
-
-

(No Java system property)

-

-New in 3.4.0: - When enabled, ZooKeeper auto purge feature retains - the autopurge.snapRetainCount most - recent snapshots and the corresponding transaction logs in the - dataDir and dataLogDir respectively and deletes the rest. - Defaults to 3. Minimum value is 3.

-
- - -
-autopurge.purgeInterval -
-
-

(No Java system property)

-

-New in 3.4.0: The - time interval in hours for which the purge task has to - be triggered. Set to a positive integer (1 and above) - to enable the auto purging. Defaults to 0.

-
- - -
-syncEnabled -
-
-

(Java system property: zookeeper.observer.syncEnabled)

-

-New in 3.4.6, 3.5.0: - The observers now log transaction and write snapshot to disk - by default like the participants. This reduces the recovery time - of the observers on restart. Set to "false" to disable this - feature. Default is "true"

-
- - -
-zookeeper.extendedTypesEnabled -
-
-

(Java system property only: zookeeper.extendedTypesEnabled)

-

-New in 3.5.4, 3.6.0: Define to "true" to enable - extended features such as the creation of TTL Nodes. - They are disabled by default. IMPORTANT: when enabled server IDs must - be less than 255 due to internal limitations. -

-
- - -
-zookeeper.emulate353TTLNodes -
-
-

(Java system property only: zookeeper.emulate353TTLNodes)

-

-New in 3.5.4, 3.6.0: Due to - ZOOKEEPER-2901 TTL nodes - created in version 3.5.3 are not supported in 3.5.4/3.6.0. However, a workaround is provided via the - zookeeper.emulate353TTLNodes system property. If you used TTL nodes in ZooKeeper 3.5.3 and need to maintain - compatibility set zookeeper.emulate353TTLNodes to "true" in addition to - zookeeper.extendedTypesEnabled. NOTE: due to the bug, server IDs - must be 127 or less. Additionally, the maximum support TTL value is 1099511627775 which is smaller - than what was allowed in 3.5.3 (1152921504606846975)

-
- - -
- -

Cluster Options

-

The options in this section are designed for use with an ensemble - of servers -- that is, when deploying clusters of servers.

-
- -
-electionAlg -
-
-

(No Java system property)

-

Election implementation to use. A value of "0" corresponds - to the original UDP-based version, "1" corresponds to the - non-authenticated UDP-based version of fast leader election, "2" - corresponds to the authenticated UDP-based version of fast - leader election, and "3" corresponds to TCP-based version of - fast leader election. Currently, algorithm 3 is the default

-
-
Note
-
- -

The implementations of leader election 0, 1, and 2 are now - deprecated . We have the intention - of removing them in the next release, at which point only the - FastLeaderElection will be available. -

- -
-
-
- - -
-initLimit -
-
-

(No Java system property)

-

Amount of time, in ticks (see tickTime), to allow followers to - connect and sync to a leader. Increased this value as needed, if - the amount of data managed by ZooKeeper is large.

-
- - -
-leaderServes -
-
-

(Java system property: zookeeper.leaderServes)

-

Leader accepts client connections. Default value is "yes". - The leader machine coordinates updates. For higher update - throughput at thes slight expense of read throughput the leader - can be configured to not accept clients and focus on - coordination. The default to this option is yes, which means - that a leader will accept client connections.

-
-
Note
-
- -

Turning on leader selection is highly recommended when - you have more than three ZooKeeper servers in an ensemble.

- -
-
-
- - -
-server.x=[hostname]:nnnnn[:nnnnn], etc -
-
-

(No Java system property)

-

servers making up the ZooKeeper ensemble. When the server - starts up, it determines which server it is by looking for the - file myid in the data directory. That file - contains the server number, in ASCII, and it should match - x in server.x in the left hand side of this - setting.

-

The list of servers that make up ZooKeeper servers that is - used by the clients must match the list of ZooKeeper servers - that each ZooKeeper server has.

-

There are two port numbers nnnnn. - The first followers use to connect to the leader, and the second is for - leader election. The leader election port is only necessary if electionAlg - is 1, 2, or 3 (default). If electionAlg is 0, then the second port is not - necessary. If you want to test multiple servers on a single machine, then - different ports can be used for each server.

-
- - -
-syncLimit -
-
-

(No Java system property)

-

Amount of time, in ticks (see tickTime), to allow followers to sync - with ZooKeeper. If followers fall too far behind a leader, they - will be dropped.

-
- - -
-group.x=nnnnn[:nnnnn] -
-
-

(No Java system property)

-

Enables a hierarchical quorum construction."x" is a group identifier - and the numbers following the "=" sign correspond to server identifiers. - The left-hand side of the assignment is a colon-separated list of server - identifiers. Note that groups must be disjoint and the union of all groups - must be the ZooKeeper ensemble.

-

You will find an example here - -

-
- - -
-weight.x=nnnnn -
-
-

(No Java system property)

-

Used along with "group", it assigns a weight to a server when - forming quorums. Such a value corresponds to the weight of a server - when voting. There are a few parts of ZooKeeper that require voting - such as leader election and the atomic broadcast protocol. By default - the weight of server is 1. If the configuration defines groups, but not - weights, then a value of 1 will be assigned to all servers. -

-

You will find an example here - -

-
- - -
-cnxTimeout -
-
-

(Java system property: zookeeper.cnxTimeout)

-

Sets the timeout value for opening connections for leader election notifications. - Only applicable if you are using electionAlg 3. -

-
-
Note
-
- -

Default value is 5 seconds.

- -
-
-
- - -
-standaloneEnabled -
-
-

(No Java system property)

-

-New in 3.5.0: - When set to false, a single server can be started in replicated - mode, a lone participant can run with observers, and a cluster - can reconfigure down to one node, and up from one node. The - default is true for backwards compatibility. It can be set - using QuorumPeerConfig's setStandaloneEnabled method or by - adding "standaloneEnabled=false" or "standaloneEnabled=true" - to a server's config file. -

-
- - -
-reconfigEnabled -
-
-

(No Java system property)

-

-New in 3.5.3: - This controls the enabling or disabling of - - Dynamic Reconfiguration feature. When the feature - is enabled, users can perform reconfigure operations through - the ZooKeeper client API or through ZooKeeper command line tools - assuming users are authorized to perform such operations. - When the feature is disabled, no user, including the super user, - can perform a reconfiguration. Any attempt to reconfigure will return an error. - "reconfigEnabled" option can be set as - "reconfigEnabled=false" or - "reconfigEnabled=true" - to a server's config file, or using QuorumPeerConfig's - setReconfigEnabled method. The default value is false. - - If present, the value should be consistent across every server in - the entire ensemble. Setting the value as true on some servers and false - on other servers will cause inconsistent behavior depending on which server - is elected as leader. If the leader has a setting of - "reconfigEnabled=true", then the ensemble - will have reconfig feature enabled. If the leader has a setting of - "reconfigEnabled=false", then the ensemble - will have reconfig feature disabled. It is thus recommended to have a consistent - value for "reconfigEnabled" across servers - in the ensemble. -

-
- - -
-4lw.commands.whitelist -
-
-

(Java system property: zookeeper.4lw.commands.whitelist)

-

-New in 3.5.3: - A list of comma separated Four Letter Words - commands that user wants to use. A valid Four Letter Words - command must be put in this list else ZooKeeper server will - not enable the command. - By default the whitelist only contains "srvr" command - which zkServer.sh uses. The rest of four letter word commands are disabled - by default. -

-

Here's an example of the configuration that enables stat, ruok, conf, and isro - command while disabling the rest of Four Letter Words command:

-
-                4lw.commands.whitelist=stat, ruok, conf, isro
-              
-

If you really need enable all four letter word commands by default, you can use - the asterisk option so you don't have to include every command one by one in the list. - As an example, this will enable all four letter word commands: -

-
-                4lw.commands.whitelist=*
-              
-
- - -
-tcpKeepAlive -
-
-

(Java system property: zookeeper.tcpKeepAlive)

-

-New in 3.5.4: - Setting this to true sets the TCP keepAlive flag on the - sockets used by quorum members to perform elections. - This will allow for connections between quorum members to - remain up when there is network infrastructure that may - otherwise break them. Some NATs and firewalls may terminate - or lose state for long running or idle connections.

-

Enabling this option relies on OS level settings to work - properly, check your operating system's options regarding TCP - keepalive for more information. Defaults to - false. -

-
- - -
-

- -

Encryption, Authentication, Authorization Options

-

The options in this section allow control over - encryption/authentication/authorization performed by the service.

-
- -
-DigestAuthenticationProvider.superDigest -
-
-

(Java system property: zookeeper.DigestAuthenticationProvider.superDigest)

-

By default this feature is disabled -

-

-New in 3.2: - Enables a ZooKeeper ensemble administrator to access the - znode hierarchy as a "super" user. In particular no ACL - checking occurs for a user authenticated as - super.

-

org.apache.zookeeper.server.auth.DigestAuthenticationProvider - can be used to generate the superDigest, call it with - one parameter of "super:<password>". Provide the - generated "super:<data>" as the system property value - when starting each server of the ensemble.

-

When authenticating to a ZooKeeper server (from a - ZooKeeper client) pass a scheme of "digest" and authdata - of "super:<password>". Note that digest auth passes - the authdata in plaintext to the server, it would be - prudent to use this authentication method only on - localhost (not over the network) or over an encrypted - connection.

-
- - -
-X509AuthenticationProvider.superUser -
-
-

(Java system property: zookeeper.X509AuthenticationProvider.superUser)

-

The SSL-backed way to enable a ZooKeeper ensemble - administrator to access the znode hierarchy as a "super" user. - When this parameter is set to an X500 principal name, only an - authenticated client with that principal will be able to bypass - ACL checking and have full privileges to all znodes.

-
- - -
-zookeeper.superUser -
-
-

(Java system property: zookeeper.superUser)

-

Similar to zookeeper.X509AuthenticationProvider.superUser - but is generic for SASL based logins. It stores the name of - a user that can access the znode hierarchy as a "super" user. -

-
- - -
-ssl.keyStore.location and ssl.keyStore.password -
-
-

(Java system properties: - zookeeper.ssl.keyStore.location and zookeeper.ssl.keyStore.password)

-

Specifies the file path to a JKS containing the local - credentials to be used for SSL connections, and the - password to unlock the file.

-
- - -
-ssl.trustStore.location and ssl.trustStore.password -
-
-

(Java system properties: - zookeeper.ssl.trustStore.location and zookeeper.ssl.trustStore.password)

-

Specifies the file path to a JKS containing the remote - credentials to be used for SSL connections, and the - password to unlock the file.

-
- - -
-ssl.authProvider -
-
-

(Java system property: zookeeper.ssl.authProvider)

-

Specifies a subclass of - org.apache.zookeeper.auth.X509AuthenticationProvider - to use for secure client authentication. This is useful in - certificate key infrastructures that do not use JKS. It may be - necessary to extend javax.net.ssl.X509KeyManager - and javax.net.ssl.X509TrustManager - to get the desired behavior from the SSL stack. To configure the - ZooKeeper server to use the custom provider for authentication, - choose a scheme name for the custom AuthenticationProvider and - set the property zookeeper.authProvider.[scheme] - to the fully-qualified class name of the custom - implementation. This will load the provider into the ProviderRegistry. - Then set this property - zookeeper.ssl.authProvider=[scheme] and that provider - will be used for secure authentication.

-
- -
- -

Experimental Options/Features

-

New features that are currently considered experimental.

-
- -
-Read Only Mode Server -
-
-

(Java system property: readonlymode.enabled)

-

-New in 3.4.0: - Setting this value to true enables Read Only Mode server - support (disabled by default). ROM allows clients - sessions which requested ROM support to connect to the - server even when the server might be partitioned from - the quorum. In this mode ROM clients can still read - values from the ZK service, but will be unable to write - values and see changes from other clients. See - ZOOKEEPER-784 for more details. -

-
- - -
- -

Unsafe Options

-

The following options can be useful, but be careful when you use - them. The risk of each is explained along with the explanation of what - the variable does.

-
- -
-forceSync -
-
-

(Java system property: zookeeper.forceSync)

-

Requires updates to be synced to media of the transaction - log before finishing processing the update. If this option is - set to no, ZooKeeper will not require updates to be synced to - the media.

-
- - -
-jute.maxbuffer: -
-
-

(Java system property: - jute.maxbuffer)

-

This option can only be set as a Java system property. - There is no zookeeper prefix on it. It specifies the maximum - size of the data that can be stored in a znode. The default is - 0xfffff, or just under 1M. If this option is changed, the system - property must be set on all servers and clients otherwise - problems will arise. This is really a sanity check. ZooKeeper is - designed to store data on the order of kilobytes in size.

-
- - -
-skipACL -
-
-

(Java system property: zookeeper.skipACL)

-

Skips ACL checks. This results in a boost in throughput, - but opens up full access to the data tree to everyone.

-
- - -
-quorumListenOnAllIPs -
-
-

When set to true the ZooKeeper server will listen - for connections from its peers on all available IP addresses, - and not only the address configured in the server list of the - configuration file. It affects the connections handling the - ZAB protocol and the Fast Leader Election protocol. Default - value is false.

-
- - -
- -

Disabling data directory autocreation

-

-New in 3.5: The default - behavior of a ZooKeeper server is to automatically create the - data directory (specified in the configuration file) when - started if that directory does not already exist. This can be - inconvenient and even dangerous in some cases. Take the case - where a configuration change is made to a running server, - wherein the dataDir parameter - is accidentally changed. When the ZooKeeper server is - restarted it will create this non-existent directory and begin - serving - with an empty znode namespace. This scenario can - result in an effective "split brain" situation (i.e. data in - both the new invalid directory and the original valid data - store). As such is would be good to have an option to turn off - this autocreate behavior. In general for production - environments this should be done, unfortunately however the - default legacy behavior cannot be changed at this point and - therefore this must be done on a case by case basis. This is - left to users and to packagers of ZooKeeper distributions. -

-

When running zkServer.sh autocreate can be disabled - by setting the environment variable ZOO_DATADIR_AUTOCREATE_DISABLE to 1. - When running ZooKeeper servers directly from class files this - can be accomplished by setting zookeeper.datadir.autocreate=false on - the java command line, i.e. -Dzookeeper.datadir.autocreate=false - -

-

When this feature is disabled, and the ZooKeeper server - determines that the required directories do not exist it will - generate an error and refuse to start. -

-

A new script zkServer-initialize.sh is provided to - support this new feature. If autocreate is disabled it is - necessary for the user to first install ZooKeeper, then create - the data directory (and potentially txnlog directory), and - then start the server. Otherwise as mentioned in the previous - paragraph the server will not start. Running zkServer-initialize.sh will create the - required directories, and optionally setup the myid file - (optional command line parameter). This script can be used - even if the autocreate feature itself is not used, and will - likely be of use to users as this (setup, including creation - of the myid file) has been an issue for users in the past. - Note that this script ensures the data directories exist only, - it does not create a config file, but rather requires a config - file to be available in order to execute. -

- -

Performance Tuning Options

-

-New in 3.5.0: Several subsystems have been reworked - to improve read throughput. This includes multi-threading of the NIO communication subsystem and - request processing pipeline (Commit Processor). NIO is the default client/server communication - subsystem. Its threading model comprises 1 acceptor thread, 1-N selector threads and 0-M - socket I/O worker threads. In the request processing pipeline the system can be configured - to process multiple read request at once while maintaining the same consistency guarantee - (same-session read-after-write). The Commit Processor threading model comprises 1 main - thread and 0-N worker threads. -

-

- The default values are aimed at maximizing read throughput on a dedicated ZooKeeper machine. - Both subsystems need to have sufficient amount of threads to achieve peak read throughput. -

-
- - -
-zookeeper.nio.numSelectorThreads -
-
-

(Java system property only: zookeeper.nio.numSelectorThreads) -

-

-New in 3.5.0: - Number of NIO selector threads. At least 1 selector thread required. - It is recommended to use more than one selector for large numbers - of client connections. The default value is sqrt( number of cpu cores / 2 ). -

-
- - -
-zookeeper.nio.numWorkerThreads -
-
-

(Java system property only: zookeeper.nio.numWorkerThreads) -

-

-New in 3.5.0: - Number of NIO worker threads. If configured with 0 worker threads, the selector threads - do the socket I/O directly. The default value is 2 times the number of cpu cores. -

-
- - -
-zookeeper.commitProcessor.numWorkerThreads -
-
-

(Java system property only: zookeeper.commitProcessor.numWorkerThreads) -

-

-New in 3.5.0: - Number of Commit Processor worker threads. If configured with 0 worker threads, the main thread - will process the request directly. The default value is the number of cpu cores. -

-
- - -
-znode.container.checkIntervalMs -
-
-

(Java system property only)

-

-New in 3.5.1: The - time interval in milliseconds for each check of candidate container - and ttl nodes. Default is "60000".

-
- - -
-znode.container.maxPerMinute -
-
-

(Java system property only)

-

-New in 3.5.1: The - maximum number of container nodes that can be deleted per - minute. This prevents herding during container deletion. - Default is "10000".

-
- -
- -

Communication using the Netty framework

-

-Netty - is an NIO based client/server communication framework, it - simplifies (over NIO being used directly) many of the - complexities of network level communication for java - applications. Additionally the Netty framework has built - in support for encryption (SSL) and authentication - (certificates). These are optional features and can be - turned on or off individually. -

-

In versions 3.5+, a ZooKeeper server can use Netty - instead of NIO (default option) by setting the environment - variable zookeeper.serverCnxnFactory - to org.apache.zookeeper.server.NettyServerCnxnFactory; - for the client, set zookeeper.clientCnxnSocket - to org.apache.zookeeper.ClientCnxnSocketNetty. -

-

- TBD - tuning options for netty - currently there are none that are netty specific but we should add some. Esp around max bound on the number of reader worker threads netty creates. -

-

- TBD - how to manage encryption -

-

- TBD - how to manage certificates -

- -

AdminServer configuration

-

-New in 3.5.0: The following - options are used to configure the AdminServer.

-
- -
-admin.enableServer -
-
-

(Java system property: zookeeper.admin.enableServer)

-

Set to "false" to disable the AdminServer. By default the - AdminServer is enabled.

-
- - -
-admin.serverAddress -
-
-

(Java system property: zookeeper.admin.serverAddress)

-

The address the embedded Jetty server listens on. Defaults to 0.0.0.0.

-
- - -
-admin.serverPort -
-
-

(Java system property: zookeeper.admin.serverPort)

-

The port the embedded Jetty server listens on. Defaults to 8080.

-
- - -
-admin.idleTimeout -
-
-

(Java system property: zookeeper.admin.idleTimeout)

-

Set the maximum idle time in milliseconds that a connection can wait - before sending or receiving data. Defaults to 30000 ms.

-
- - - -
-admin.commandURL -
-
-

(Java system property: zookeeper.admin.commandURL)

-

The URL for listing and issuing commands relative to the - root URL. Defaults to "/commands".

-
- -
- -

ZooKeeper Commands

- -

The Four Letter Words

-

ZooKeeper responds to a small set of commands. Each command is - composed of four letters. You issue the commands to ZooKeeper via telnet - or nc, at the client port.

-

Three of the more interesting commands: "stat" gives some - general information about the server and connected clients, - while "srvr" and "cons" give extended details on server and - connections respectively.

-

-New in 3.5.3: - Four Letter Words need to be explicitly white listed before using. - Please refer 4lw.commands.whitelist - described in - cluster configuration section for details. - Moving forward, Four Letter Words will be deprecated, please use - AdminServer instead. -

-
- -
-conf -
-
-

-New in 3.3.0: Print - details about serving configuration.

-
- - -
-cons -
-
-

-New in 3.3.0: List - full connection/session details for all clients connected - to this server. Includes information on numbers of packets - received/sent, session id, operation latencies, last - operation performed, etc...

-
- - -
-crst -
-
-

-New in 3.3.0: Reset - connection/session statistics for all connections.

-
- - -
-dump -
-
-

Lists the outstanding sessions and ephemeral nodes. This - only works on the leader.

-
- - -
-envi -
-
-

Print details about serving environment

-
- - -
-ruok -
-
-

Tests if server is running in a non-error state. The server - will respond with imok if it is running. Otherwise it will not - respond at all.

-

A response of "imok" does not necessarily indicate that the - server has joined the quorum, just that the server process is active - and bound to the specified client port. Use "stat" for details on - state wrt quorum and client connection information.

-
- - -
-srst -
-
-

Reset server statistics.

-
- - -
-srvr -
-
-

-New in 3.3.0: Lists - full details for the server.

-
- - -
-stat -
-
-

Lists brief details for the server and connected - clients.

-
- - -
-wchs -
-
-

-New in 3.3.0: Lists - brief information on watches for the server.

-
- - -
-wchc -
-
-

-New in 3.3.0: Lists - detailed information on watches for the server, by - session. This outputs a list of sessions(connections) - with associated watches (paths). Note, depending on the - number of watches this operation may be expensive (ie - impact server performance), use it carefully.

-
- - -
-dirs -
-
-

-New in 3.5.1: - Shows the total size of snapshot and log files in bytes -

-
- - -
-wchp -
-
-

-New in 3.3.0: Lists - detailed information on watches for the server, by path. - This outputs a list of paths (znodes) with associated - sessions. Note, depending on the number of watches this - operation may be expensive (ie impact server performance), - use it carefully.

-
- - - -
-mntr -
-
-

-New in 3.4.0: Outputs a list - of variables that could be used for monitoring the health of the cluster.

-
$ echo mntr | nc localhost 2185
-
-              zk_version  3.4.0
-              zk_avg_latency  0
-              zk_max_latency  0
-              zk_min_latency  0
-              zk_packets_received 70
-              zk_packets_sent 69
-              zk_num_alive_connections	1
-              zk_outstanding_requests 0
-              zk_server_state leader
-              zk_znode_count   4
-              zk_watch_count  0
-              zk_ephemerals_count 0
-              zk_approximate_data_size    27
-              zk_followers    4                   - only exposed by the Leader
-              zk_synced_followers 4               - only exposed by the Leader
-              zk_pending_syncs    0               - only exposed by the Leader
-              zk_open_file_descriptor_count 23    - only available on Unix platforms
-              zk_max_file_descriptor_count 1024   - only available on Unix platforms
-              zk_last_proposal_size 23
-              zk_min_proposal_size 23
-              zk_max_proposal_size 64
-              
-

The output is compatible with java properties format and the content - may change over time (new keys added). Your scripts should expect changes.

-

ATTENTION: Some of the keys are platform specific and some of the keys are only exported by the Leader.

-

The output contains multiple lines with the following format:

-
key \t value
-
- - -
-isro -
-
-

-New in 3.4.0: Tests if - server is running in read-only mode. The server will respond with - "ro" if in read-only mode or "rw" if not in read-only mode.

-
- - -
-gtmk -
-
-

Gets the current trace mask as a 64-bit signed long value in - decimal format. See stmk for an explanation of - the possible values.

-
- - -
-stmk -
-
-

Sets the current trace mask. The trace mask is 64 bits, - where each bit enables or disables a specific category of trace - logging on the server. Log4J must be configured to enable - TRACE level first in order to see trace logging - messages. The bits of the trace mask correspond to the following - trace logging categories.

- - - -Trace Mask Bit Values - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Trace Mask Bit Values
0b0000000000Unused, reserved for future use.
0b0000000010Logs client requests, excluding ping - requests.
0b0000000100Unused, reserved for future use.
0b0000001000Logs client ping requests.
0b0000010000Logs packets received from the quorum peer that is - the current leader, excluding ping requests.
0b0000100000Logs addition, removal and validation of client - sessions.
0b0001000000Logs delivery of watch events to client - sessions.
0b0010000000Logs ping packets received from the quorum peer - that is the current leader.
0b0100000000Unused, reserved for future use.
0b1000000000Unused, reserved for future use.
-

All remaining bits in the 64-bit value are unused and - reserved for future use. Multiple trace logging categories are - specified by calculating the bitwise OR of the documented values. - The default trace mask is 0b0100110010. Thus, by default, trace - logging includes client requests, packets received from the - leader and sessions.

-

To set a different trace mask, send a request containing the - stmk four-letter word followed by the trace - mask represented as a 64-bit signed long value. This example uses - the Perl pack function to construct a trace - mask that enables all trace logging categories described above and - convert it to a 64-bit signed long value with big-endian byte - order. The result is appended to stmk and sent - to the server using netcat. The server responds with the new - trace mask in decimal format.

-
$ perl -e "print 'stmk', pack('q>', 0b0011111010)" | nc localhost 2181
-250
-              
-
- -
-

Here's an example of the ruok - command:

-
$ echo ruok | nc 127.0.0.1 5111
-        imok
-        
- -

The AdminServer

-

-New in 3.5.0: The AdminServer is - an embedded Jetty server that provides an HTTP interface to the four - letter word commands. By default, the server is started on port 8080, - and commands are issued by going to the URL "/commands/[command name]", - e.g., http://localhost:8080/commands/stat. The command response is - returned as JSON. Unlike the original protocol, commands are not - restricted to four-letter names, and commands can have multiple names; - for instance, "stmk" can also be referred to as "set_trace_mask". To - view a list of all available commands, point a browser to the URL - /commands (e.g., http://localhost:8080/commands). See the AdminServer configuration options - for how to change the port and URLs.

-

The AdminServer is enabled by default, but can be disabled by either:

-
    - -
  • -

    Setting the zookeeper.admin.enableServer system - property to false.

    -
  • - -
  • -

    Removing Jetty from the classpath. (This option is - useful if you would like to override ZooKeeper's jetty - dependency.)

    -
  • - -
-

Note that the TCP four letter word interface is still available if - the AdminServer is disabled.

- -

Data File Management

-

ZooKeeper stores its data in a data directory and its transaction - log in a transaction log directory. By default these two directories are - the same. The server can (and should) be configured to store the - transaction log files in a separate directory than the data files. - Throughput increases and latency decreases when transaction logs reside - on a dedicated log devices.

- -

The Data Directory

-

This directory has two files in it:

-
    - -
  • - -

    -myid - contains a single integer in - human readable ASCII text that represents the server id.

    - -
  • - - -
  • - -

    -snapshot.<zxid> - holds the fuzzy - snapshot of a data tree.

    - -
  • - -
-

Each ZooKeeper server has a unique id. This id is used in two - places: the myid file and the configuration file. - The myid file identifies the server that - corresponds to the given data directory. The configuration file lists - the contact information for each server identified by its server id. - When a ZooKeeper server instance starts, it reads its id from the - myid file and then, using that id, reads from the - configuration file, looking up the port on which it should - listen.

-

The snapshot files stored in the data - directory are fuzzy snapshots in the sense that during the time the - ZooKeeper server is taking the snapshot, updates are occurring to the - data tree. The suffix of the snapshot file names - is the zxid, the ZooKeeper transaction id, of the - last committed transaction at the start of the snapshot. Thus, the - snapshot includes a subset of the updates to the data tree that - occurred while the snapshot was in process. The snapshot, then, may - not correspond to any data tree that actually existed, and for this - reason we refer to it as a fuzzy snapshot. Still, ZooKeeper can - recover using this snapshot because it takes advantage of the - idempotent nature of its updates. By replaying the transaction log - against fuzzy snapshots ZooKeeper gets the state of the system at the - end of the log.

- -

The Log Directory

-

The Log Directory contains the ZooKeeper transaction logs. - Before any update takes place, ZooKeeper ensures that the transaction - that represents the update is written to non-volatile storage. A new - log file is started when the number of transactions written to the - current log file reaches a (variable) threshold. The threshold is - computed using the same parameter which influences the frequency of - snapshotting (see snapCount above). The log file's suffix is the first - zxid written to that log.

- -

File Management

-

The format of snapshot and log files does not change between - standalone ZooKeeper servers and different configurations of - replicated ZooKeeper servers. Therefore, you can pull these files from - a running replicated ZooKeeper server to a development machine with a - stand-alone ZooKeeper server for trouble shooting.

-

Using older log and snapshot files, you can look at the previous - state of ZooKeeper servers and even restore that state. The - LogFormatter class allows an administrator to look at the transactions - in a log.

-

The ZooKeeper server creates snapshot and log files, but - never deletes them. The retention policy of the data and log - files is implemented outside of the ZooKeeper server. The - server itself only needs the latest complete fuzzy snapshot, all log - files following it, and the last log file preceding it. The latter - requirement is necessary to include updates which happened after this - snapshot was started but went into the existing log file at that time. - This is possible because snapshotting and rolling over of logs - proceed somewhat independently in ZooKeeper. See the - maintenance section in - this document for more details on setting a retention policy - and maintenance of ZooKeeper storage. -

-
-
Note
-
- -

The data stored in these files is not encrypted. In the case of - storing sensitive data in ZooKeeper, necessary measures need to be - taken to prevent unauthorized access. Such measures are external to - ZooKeeper (e.g., control access to the files) and depend on the - individual settings in which it is being deployed.

- -
-
- -

Recovery - TxnLogToolkit

-

TxnLogToolkit is a command line tool shipped with ZooKeeper which - is capable of recovering transaction log entries with broken CRC.

-

Running it without any command line parameters or with the "-h,--help" - argument, it outputs the following help page:

-
-          $ bin/zkTxnLogToolkit.sh
-
-          usage: TxnLogToolkit [-dhrv] txn_log_file_name
-          -d,--dump      Dump mode. Dump all entries of the log file. (this is the default)
-          -h,--help      Print help message
-          -r,--recover   Recovery mode. Re-calculate CRC for broken entries.
-          -v,--verbose   Be verbose in recovery mode: print all entries, not just fixed ones.
-          -y,--yes       Non-interactive mode: repair all CRC errors without asking
-        
-

The default behaviour is safe: it dumps the entries of the given - transaction log file to the screen: (same as using '-d,--dump' parameter)

-
-          $ bin/zkTxnLogToolkit.sh log.100000001
-          ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
-          4/5/18 2:15:58 PM CEST session 0x16295bafcc40000 cxid 0x0 zxid 0x100000001 createSession 30000
-          CRC ERROR - 4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
-          4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
-          4/5/18 2:16:12 PM CEST session 0x26295bafcc90000 cxid 0x0 zxid 0x100000003 createSession 30000
-          4/5/18 2:17:34 PM CEST session 0x26295bafcc90000 cxid 0x0 zxid 0x200000001 closeSession null
-          4/5/18 2:17:34 PM CEST session 0x16295bd23720000 cxid 0x0 zxid 0x200000002 createSession 30000
-          4/5/18 2:18:02 PM CEST session 0x16295bd23720000 cxid 0x2 zxid 0x200000003 create '/andor,#626262,v{s{31,s{'world,'anyone}}},F,1
-          EOF reached after 6 txns.
-        
-

There's a CRC error in the 2nd entry of the above transaction log file. In dump - mode, the toolkit only prints this information to the screen without touching the original file. In - recovery mode (-r,--recover flag) the original file still remains - untouched and all transactions will be copied over to a new txn log file with ".fixed" suffix. It recalculates - CRC values and copies the calculated value, if it doesn't match the original txn entry. - By default, the tool works interactively: it asks for confirmation whenever CRC error encountered.

-
-          $ bin/zkTxnLogToolkit.sh -r log.100000001
-          ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
-          CRC ERROR - 4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
-          Would you like to fix it (Yes/No/Abort) ?
-        
-

Answering Yes means the newly calculated CRC value will be outputted - to the new file. No means that the original CRC value will be copied over. - Abort will abort the entire operation and exits. - (In this case the ".fixed" will not be deleted and left in a half-complete state: contains only entries which - have already been processed or only the header if the operation was aborted at the first entry.)

-
-          $ bin/zkTxnLogToolkit.sh -r log.100000001
-          ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
-          CRC ERROR - 4/5/18 2:16:05 PM CEST session 0x16295bafcc40000 cxid 0x1 zxid 0x100000002 closeSession null
-          Would you like to fix it (Yes/No/Abort) ? y
-          EOF reached after 6 txns.
-          Recovery file log.100000001.fixed has been written with 1 fixed CRC error(s)
-        
-

The default behaviour of recovery is to be silent: only entries with CRC error get printed to the screen. - One can turn on verbose mode with the -v,--verbose parameter to see all records. - Interactive mode can be turned off with the -y,--yes parameter. In this case all CRC errors will be fixed - in the new transaction file.

- -

Things to Avoid

-

Here are some common problems you can avoid by configuring - ZooKeeper correctly:

-
- -
-inconsistent lists of servers -
-
-

The list of ZooKeeper servers used by the clients must match - the list of ZooKeeper servers that each ZooKeeper server has. - Things work okay if the client list is a subset of the real list, - but things will really act strange if clients have a list of - ZooKeeper servers that are in different ZooKeeper clusters. Also, - the server lists in each Zookeeper server configuration file - should be consistent with one another.

-
- - -
-incorrect placement of transaction log -
-
-

The most performance critical part of ZooKeeper is the - transaction log. ZooKeeper syncs transactions to media before it - returns a response. A dedicated transaction log device is key to - consistent good performance. Putting the log on a busy device will - adversely effect performance. If you only have one storage device, - put trace files on NFS and increase the snapshotCount; it doesn't - eliminate the problem, but it should mitigate it.

-
- - -
-incorrect Java heap size -
-
-

You should take special care to set your Java max heap size - correctly. In particular, you should not create a situation in - which ZooKeeper swaps to disk. The disk is death to ZooKeeper. - Everything is ordered, so if processing one request swaps the - disk, all other queued requests will probably do the same. the - disk. DON'T SWAP.

-

Be conservative in your estimates: if you have 4G of RAM, do - not set the Java max heap size to 6G or even 4G. For example, it - is more likely you would use a 3G heap for a 4G machine, as the - operating system and the cache also need memory. The best and only - recommend practice for estimating the heap size your system needs - is to run load tests, and then make sure you are well below the - usage limit that would cause the system to swap.

-
- - -
-Publicly accessible deployment -
-
-

- A ZooKeeper ensemble is expected to operate in a trusted computing environment. - It is thus recommended to deploy ZooKeeper behind a firewall. -

-
- -
- -

Best Practices

-

For best results, take note of the following list of good - Zookeeper practices:

-

For multi-tennant installations see the section - detailing ZooKeeper "chroot" support, this can be very useful - when deploying many applications/services interfacing to a - single ZooKeeper cluster.

-
- -

- -

-
- -
 
-
- - - diff --git a/docs/zookeeperAdmin.pdf b/docs/zookeeperAdmin.pdf deleted file mode 100644 index 3c818357fb8876eca33d0ad8f92b13c5a5b76cdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102168 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 diff --git a/docs/zookeeperHierarchicalQuorums.html b/docs/zookeeperHierarchicalQuorums.html deleted file mode 100644 index 794872984c5..00000000000 --- a/docs/zookeeperHierarchicalQuorums.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - -Introduction to hierarchical quorums - - - - - - - - - -
- - - -
- - - - - - - - - - - - -
-
-
-
- -
- - -
- -
- -   -
- - - - - -
- -

Introduction to hierarchical quorums

-
- - - - - -

- This document gives an example of how to use hierarchical quorums. The basic idea is - very simple. First, we split servers into groups, and add a line for each group listing - the servers that form this group. Next we have to assign a weight to each server. -

- - -

- The following example shows how to configure a system with three groups of three servers - each, and we assign a weight of 1 to each server: -

- - -
-    group.1=1:2:3
-    group.2=4:5:6
-    group.3=7:8:9
-   
-    weight.1=1
-    weight.2=1
-    weight.3=1
-    weight.4=1
-    weight.5=1
-    weight.6=1
-    weight.7=1
-    weight.8=1
-    weight.9=1
- 	
- - -

- When running the system, we are able to form a quorum once we have a majority of votes from - a majority of non-zero-weight groups. Groups that have zero weight are discarded and not - considered when forming quorums. Looking at the example, we are able to form a quorum once - we have votes from at least two servers from each of two different groups. -

- -

- -

-
- -
 
-
- - - diff --git a/docs/zookeeperHierarchicalQuorums.pdf b/docs/zookeeperHierarchicalQuorums.pdf deleted file mode 100644 index b23e3197c29584c2080793fac7a0241d7e34b3d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6654 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 P$Esrx%F0F-WW;{}Wyoql diff --git a/docs/zookeeperInternals.html b/docs/zookeeperInternals.html deleted file mode 100644 index 08d6ede72e6..00000000000 --- a/docs/zookeeperInternals.html +++ /dev/null @@ -1,793 +0,0 @@ - - - - - - - -ZooKeeper Internals - - - - - - - - - -
- - - -
- - - - - - - - - - - - -
-
-
-
- -
- - -
- -
- -   -
- - - - - -
- -

ZooKeeper Internals

- - - - - - - -

Introduction

-
-

This document contains information on the inner workings of ZooKeeper. - So far, it discusses these topics: -

- -
- - - -

Atomic Broadcast

-
-

-At the heart of ZooKeeper is an atomic messaging system that keeps all of the servers in sync.

- -

Guarantees, Properties, and Definitions

-

-The specific guarantees provided by the messaging system used by ZooKeeper are the following:

-
- - -
- -Reliable delivery - -
-
-

If a message, m, is delivered -by one server, it will be eventually delivered by all servers.

-
- - -
- -Total order - -
-
-

If a message is -delivered before message b by one server, a will be delivered before b by all -servers. If a and b are delivered messages, either a will be delivered before b -or b will be delivered before a.

-
- - -
- -Causal order - -
-
-

-If a message b is sent after a message a has been delivered by the sender of b, -a must be ordered before b. If a sender sends c after sending b, c must be ordered after b. -

-
- - -
-

-The ZooKeeper messaging system also needs to be efficient, reliable, and easy to -implement and maintain. We make heavy use of messaging, so we need the system to -be able to handle thousands of requests per second. Although we can require at -least k+1 correct servers to send new messages, we must be able to recover from -correlated failures such as power outages. When we implemented the system we had -little time and few engineering resources, so we needed a protocol that is -accessible to engineers and is easy to implement. We found that our protocol -satisfied all of these goals. - -

-

-Our protocol assumes that we can construct point-to-point FIFO channels between -the servers. While similar services usually assume message delivery that can -lose or reorder messages, our assumption of FIFO channels is very practical -given that we use TCP for communication. Specifically we rely on the following property of TCP:

-
- - -
- -Ordered delivery - -
-
-

Data is delivered in the same order it is sent and a message m is -delivered only after all messages sent before m have been delivered. -(The corollary to this is that if message m is lost all messages after m will be lost.)

-
- - -
- -No message after close - -
-
-

Once a FIFO channel is closed, no messages will be received from it.

-
- - -
-

-FLP proved that consensus cannot be achieved in asynchronous distributed systems -if failures are possible. To ensure we achieve consensus in the presence of failures -we use timeouts. However, we rely on times for liveness not for correctness. So, -if timeouts stop working (clocks malfunction for example) the messaging system may -hang, but it will not violate its guarantees.

-

When describing the ZooKeeper messaging protocol we will talk of packets, -proposals, and messages:

-
- -
- -Packet - -
-
-

a sequence of bytes sent through a FIFO channel

-
-
- -Proposal - -
-
-

a unit of agreement. Proposals are agreed upon by exchanging packets -with a quorum of ZooKeeper servers. Most proposals contain messages, however the -NEW_LEADER proposal is an example of a proposal that does not correspond to a message.

-
-
- -Message - -
-
-

a sequence of bytes to be atomically broadcast to all ZooKeeper -servers. A message put into a proposal and agreed upon before it is delivered.

-
- - -
-

-As stated above, ZooKeeper guarantees a total order of messages, and it also -guarantees a total order of proposals. ZooKeeper exposes the total ordering using -a ZooKeeper transaction id (zxid). All proposals will be stamped with a zxid when -it is proposed and exactly reflects the total ordering. Proposals are sent to all -ZooKeeper servers and committed when a quorum of them acknowledge the proposal. -If a proposal contains a message, the message will be delivered when the proposal -is committed. Acknowledgement means the server has recorded the proposal to persistent storage. -Our quorums have the requirement that any pair of quorum must have at least one server -in common. We ensure this by requiring that all quorums have size (n/2+1) where -n is the number of servers that make up a ZooKeeper service. -

-

-The zxid has two parts: the epoch and a counter. In our implementation the zxid -is a 64-bit number. We use the high order 32-bits for the epoch and the low order -32-bits for the counter. Because it has two parts represent the zxid both as a -number and as a pair of integers, (epoch, count). The epoch number represents a -change in leadership. Each time a new leader comes into power it will have its -own epoch number. We have a simple algorithm to assign a unique zxid to a proposal: -the leader simply increments the zxid to obtain a unique zxid for each proposal. -Leadership activation will ensure that only one leader uses a given epoch, so our -simple algorithm guarantees that every proposal will have a unique id. - -

-

-ZooKeeper messaging consists of two phases:

-
- -
- -Leader activation - -
-
-

In this phase a leader establishes the correct state of the system -and gets ready to start making proposals.

-
- - -
- -Active messaging - -
-
-

In this phase a leader accepts messages to propose and coordinates message delivery.

-
- -
-

-ZooKeeper is a holistic protocol. We do not focus on individual proposals, rather -look at the stream of proposals as a whole. Our strict ordering allows us to do this -efficiently and greatly simplifies our protocol. Leadership activation embodies -this holistic concept. A leader becomes active only when a quorum of followers -(The leader counts as a follower as well. You can always vote for yourself ) has synced -up with the leader, they have the same state. This state consists of all of the -proposals that the leader believes have been committed and the proposal to follow -the leader, the NEW_LEADER proposal. (Hopefully you are thinking to -yourself, Does the set of proposals that the leader believes has been committed -included all the proposals that really have been committed? The answer is yes. -Below, we make clear why.) -

- -

Leader Activation

-

-Leader activation includes leader election. We currently have two leader election -algorithms in ZooKeeper: LeaderElection and FastLeaderElection (AuthFastLeaderElection -is a variant of FastLeaderElection that uses UDP and allows servers to perform a simple -form of authentication to avoid IP spoofing). ZooKeeper messaging doesn't care about the -exact method of electing a leader has long as the following holds: -

-
    - - -
  • -

    The leader has seen the highest zxid of all the followers.

    -
  • - -
  • -

    A quorum of servers have committed to following the leader.

    -
  • - - -
-

-Of these two requirements only the first, the highest zxid amoung the followers -needs to hold for correct operation. The second requirement, a quorum of followers, -just needs to hold with high probability. We are going to recheck the second requirement, -so if a failure happens during or after the leader election and quorum is lost, -we will recover by abandoning leader activation and running another election. -

-

-After leader election a single server will be designated as a leader and start -waiting for followers to connect. The rest of the servers will try to connect to -the leader. The leader will sync up with followers by sending any proposals they -are missing, or if a follower is missing too many proposals, it will send a full -snapshot of the state to the follower. -

-

-There is a corner case in which a follower that has proposals, U, not seen -by a leader arrives. Proposals are seen in order, so the proposals of U will have a zxids -higher than zxids seen by the leader. The follower must have arrived after the -leader election, otherwise the follower would have been elected leader given that -it has seen a higher zxid. Since committed proposals must be seen by a quorum of -servers, and a quorum of servers that elected the leader did not see U, the proposals -of you have not been committed, so they can be discarded. When the follower connects -to the leader, the leader will tell the follower to discard U. -

-

-A new leader establishes a zxid to start using for new proposals by getting the -epoch, e, of the highest zxid it has seen and setting the next zxid to use to be -(e+1, 0), fter the leader syncs with a follower, it will propose a NEW_LEADER -proposal. Once the NEW_LEADER proposal has been committed, the leader will activate -and start receiving and issuing proposals. -

-

-It all sounds complicated but here are the basic rules of operation during leader -activation: -

-
    - -
  • -

    A follower will ACK the NEW_LEADER proposal after it has synced with the leader.

    -
  • - -
  • -

    A follower will only ACK a NEW_LEADER proposal with a given zxid from a single server.

    -
  • - -
  • -

    A new leader will COMMIT the NEW_LEADER proposal when a quorum of followers have ACKed it.

    -
  • - -
  • -

    A follower will commit any state it received from the leader when the NEW_LEADER proposal is COMMIT.

    -
  • - -
  • -

    A new leader will not accept new proposals until the NEW_LEADER proposal has been COMMITED.

    -
  • - -
-

-If leader election terminates erroneously, we don't have a problem since the -NEW_LEADER proposal will not be committed since the leader will not have quorum. -When this happens, the leader and any remaining followers will timeout and go back -to leader election. -

- -

Active Messaging

-

-Leader Activation does all the heavy lifting. Once the leader is coronated he can -start blasting out proposals. As long as he remains the leader no other leader can -emerge since no other leader will be able to get a quorum of followers. If a new -leader does emerge, -it means that the leader has lost quorum, and the new leader will clean up any -mess left over during her leadership activation. -

-

ZooKeeper messaging operates similar to a classic two-phase commit.

-

-All communication channels are FIFO, so everything is done in order. Specifically -the following operating constraints are observed:

-
    - - -
  • -

    The leader sends proposals to all followers using -the same order. Moreover, this order follows the order in which requests have been -received. Because we use FIFO channels this means that followers also receive proposals in order. -

    -
  • - - -
  • -

    Followers process messages in the order they are received. This -means that messages will be ACKed in order and the leader will receive ACKs from -followers in order, due to the FIFO channels. It also means that if message $m$ -has been written to non-volatile storage, all messages that were proposed before -$m$ have been written to non-volatile storage.

    -
  • - - -
  • -

    The leader will issue a COMMIT to all followers as soon as a -quorum of followers have ACKed a message. Since messages are ACKed in order, -COMMITs will be sent by the leader as received by the followers in order.

    -
  • - - -
  • -

    COMMITs are processed in order. Followers deliver a proposals -message when that proposal is committed.

    -
  • - - -
- -

Summary

-

So there you go. Why does it work? Specifically, why does a set of proposals -believed by a new leader always contain any proposal that has actually been committed? -First, all proposals have a unique zxid, so unlike other protocols, we never have -to worry about two different values being proposed for the same zxid; followers -(a leader is also a follower) see and record proposals in order; proposals are -committed in order; there is only one active leader at a time since followers only -follow a single leader at a time; a new leader has seen all committed proposals -from the previous epoch since it has seen the highest zxid from a quorum of servers; -any uncommited proposals from a previous epoch seen by a new leader will be committed -by that leader before it becomes active.

- -

Comparisons

-

-Isn't this just Multi-Paxos? No, Multi-Paxos requires some way of assuring that -there is only a single coordinator. We do not count on such assurances. Instead -we use the leader activation to recover from leadership change or old leaders -believing they are still active. -

-

-Isn't this just Paxos? Your active messaging phase looks just like phase 2 of Paxos? -Actually, to us active messaging looks just like 2 phase commit without the need to -handle aborts. Active messaging is different from both in the sense that it has -cross proposal ordering requirements. If we do not maintain strict FIFO ordering of -all packets, it all falls apart. Also, our leader activation phase is different from -both of them. In particular, our use of epochs allows us to skip blocks of uncommitted -proposals and to not worry about duplicate proposals for a given zxid. -

-
- - - -

Quorums

-
-

-Atomic broadcast and leader election use the notion of quorum to guarantee a consistent -view of the system. By default, ZooKeeper uses majority quorums, which means that every -voting that happens in one of these protocols requires a majority to vote on. One example is -acknowledging a leader proposal: the leader can only commit once it receives an -acknowledgement from a quorum of servers. -

-

-If we extract the properties that we really need from our use of majorities, we have that we only -need to guarantee that groups of processes used to validate an operation by voting (e.g., acknowledging -a leader proposal) pairwise intersect in at least one server. Using majorities guarantees such a property. -However, there are other ways of constructing quorums different from majorities. For example, we can assign -weights to the votes of servers, and say that the votes of some servers are more important. To obtain a quorum, -we get enough votes so that the sum of weights of all votes is larger than half of the total sum of all weights. -

-

-A different construction that uses weights and is useful in wide-area deployments (co-locations) is a hierarchical -one. With this construction, we split the servers into disjoint groups and assign weights to processes. To form -a quorum, we have to get a hold of enough servers from a majority of groups G, such that for each group g in G, -the sum of votes from g is larger than half of the sum of weights in g. Interestingly, this construction enables -smaller quorums. If we have, for example, 9 servers, we split them into 3 groups, and assign a weight of 1 to each -server, then we are able to form quorums of size 4. Note that two subsets of processes composed each of a majority -of servers from each of a majority of groups necessarily have a non-empty intersection. It is reasonable to expect -that a majority of co-locations will have a majority of servers available with high probability. -

-

-With ZooKeeper, we provide a user with the ability of configuring servers to use majority quorums, weights, or a -hierarchy of groups. -

-
- - - -

Logging

-
-

-Zookeeper uses -slf4j as an abstraction layer for logging. -log4j in version 1.2 is chosen as the final logging implementation for now. -For better embedding support, it is planned in the future to leave the decision of choosing the final logging implementation to the end user. -Therefore, always use the slf4j api to write log statements in the code, but configure log4j for how to log at runtime. -Note that slf4j has no FATAL level, former messages at FATAL level have been moved to ERROR level. -For information on configuring log4j for -ZooKeeper, see the Logging section -of the ZooKeeper Administrator's Guide. - - -

- -

Developer Guidelines

-

Please follow the -slf4j manual when creating log statements within code. -Also read the -FAQ on performance -, when creating log statements. Patch reviewers will look for the following:

- -

Logging at the Right Level

-

-There are several levels of logging in slf4j. -It's important to pick the right one. In order of higher to lower severity:

-
    - -
  1. -

    ERROR level designates error events that might still allow the application to continue running.

    -
  2. - -
  3. -

    WARN level designates potentially harmful situations.

    -
  4. - -
  5. -

    INFO level designates informational messages that highlight the progress of the application at coarse-grained level.

    -
  6. - -
  7. -

    DEBUG Level designates fine-grained informational events that are most useful to debug an application.

    -
  8. - -
  9. -

    TRACE Level designates finer-grained informational events than the DEBUG.

    -
  10. - -
-

-ZooKeeper is typically run in production such that log messages of INFO level -severity and higher (more severe) are output to the log.

- -

Use of Standard slf4j Idioms

-

-Static Message Logging -

-
-LOG.debug("process completed successfully!");
-
-

-However when creating parameterized messages are required, use formatting anchors. -

-
-LOG.debug("got {} messages in {} minutes",new Object[]{count,time});    
-
-

-Naming -

-

-Loggers should be named after the class in which they are used. -

-
-public class Foo {
-    private static final Logger LOG = LoggerFactory.getLogger(Foo.class);
-    ....
-    public Foo() {
-       LOG.info("constructing Foo");
-
-

-Exception handling -

-
-try {
-  // code
-} catch (XYZException e) {
-  // do this
-  LOG.error("Something bad happened", e);
-  // don't do this (generally)
-  // LOG.error(e);
-  // why? because "don't do" case hides the stack trace
- 
-  // continue process here as you need... recover or (re)throw
-}
-
-
- - -

- -

-
- -
 
-
- - - diff --git a/docs/zookeeperInternals.pdf b/docs/zookeeperInternals.pdf deleted file mode 100644 index ec99459064d66fab084b86130f7acfbac0d9f602..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48811 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