| <?xml version="1.0"?> |
| <chapter xml:id="developer" |
| version="5.0" xmlns="http://docbook.org/ns/docbook" |
| xmlns:xlink="http://www.w3.org/1999/xlink" |
| xmlns:xi="http://www.w3.org/2001/XInclude" |
| xmlns:svg="http://www.w3.org/2000/svg" |
| xmlns:m="http://www.w3.org/1998/Math/MathML" |
| xmlns:html="http://www.w3.org/1999/xhtml" |
| xmlns:db="http://docbook.org/ns/docbook"> |
| <!-- |
| /** |
| * 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. |
| */ |
| --> |
| <title>Building and Developing HBase</title> |
| <para>This chapter will be of interest only to those building and developing HBase (i.e., as opposed to |
| just downloading the latest distribution). |
| </para> |
| <section xml:id="repos"> |
| <title>HBase Repositories</title> |
| <section xml:id="svn"> |
| <title>SVN</title> |
| <programlisting> |
| svn co http://svn.apache.org/repos/asf/hbase/trunk hbase-core-trunk |
| </programlisting> |
| </section> |
| <section xml:id="git"> |
| <title>Git</title> |
| <programlisting> |
| git clone git://git.apache.org/hbase.git |
| </programlisting> |
| </section> |
| </section> |
| |
| <section xml:id="ides"> |
| <title>IDEs</title> |
| <section xml:id="eclipse"> |
| <title>Eclipse</title> |
| <section xml:id="eclipse.code.formatting"> |
| <title>Code Formatting</title> |
| <para>See <link xlink:href="https://issues.apache.org/jira/browse/HBASE-3678">HBASE-3678 Add Eclipse-based Apache Formatter to HBase Wiki</link> |
| for an Eclipse formatter to help ensure your code conforms to HBase'y coding convention. |
| The issue includes instructions for loading the attached formatter.</para> |
| <para>Also, no @author tags - that's a rule. Quality Javadoc comments are appreciated. And include the Apache license.</para> |
| </section> |
| <section xml:id="eclipse.svn"> |
| <title>Subversive Plugin</title> |
| <para>Download and install the Subversive plugin.</para> |
| <para>Set up an SVN Repository target from <xref linkend="svn"/>, then check out the code.</para> |
| </section> |
| <section xml:id="eclipse.maven.setup"> |
| <title>HBase Project Setup</title> |
| To set up your Eclipse environment for HBase, close Eclipse and execute... |
| <programlisting> |
| mvn eclipse:eclipse |
| </programlisting> |
| ... from your local HBase project directory in your workspace to generate some new <filename>.project</filename> |
| and <filename>.classpath</filename>files. Then reopen Eclipse. |
| </section> |
| <section xml:id="eclipse.maven.plugin"> |
| <title>Maven Plugin</title> |
| <para>Download and install the Maven plugin. For example, Help -> Install New Software -> (search for Maven Plugin)</para> |
| </section> |
| <section xml:id="eclipse.maven.class"> |
| <title>Maven Classpath Variable</title> |
| <para>The <varname>M2_REPO</varname> classpath variable needs to be set up for the project. This needs to be set to |
| your local Maven repository, which is usually <filename>~/.m2/repository</filename></para> |
| If this classpath variable is not configured, you will see compile errors in Eclipse like this... |
| <programlisting> |
| Description Resource Path Location Type |
| The project cannot be built until build path errors are resolved hbase Unknown Java Problem |
| Unbound classpath variable: 'M2_REPO/asm/asm/3.1/asm-3.1.jar' in project 'hbase' hbase Build path Build Path Problem |
| Unbound classpath variable: 'M2_REPO/com/github/stephenc/high-scale-lib/high-scale-lib/1.1.1/high-scale-lib-1.1.1.jar' in project 'hbase' hbase Build path Build Path Problem |
| Unbound classpath variable: 'M2_REPO/com/google/guava/guava/r09/guava-r09.jar' in project 'hbase' hbase Build path Build Path Problem |
| Unbound classpath variable: 'M2_REPO/com/google/protobuf/protobuf-java/2.3.0/protobuf-java-2.3.0.jar' in project 'hbase' hbase Build path Build Path Problem Unbound classpath variable: |
| </programlisting> |
| </section> |
| <section xml:id="eclipse.m2eclipse"> |
| <title>Import via m2eclipse</title> |
| <para>If you install the m2eclipse and import the HBase pom.xml in your workspace, you will have to fix your eclipse Build Path. |
| Remove <filename>target</filename> folder, add <filename>target/generated-jamon</filename> |
| and <filename>target/generated-sources/java</filename> folders. You may also remove from your Build Path |
| the exclusions on the <filename>src/main/resources</filename> and <filename>src/test/resources</filename> |
| to avoid error message in the console 'Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.6:run (default) on project hbase: |
| 'An Ant BuildException has occured: Replace: source file .../target/classes/hbase-default.xml doesn't exist'. This will also |
| reduce the eclipse build cycles and make your life easier when developing.</para> |
| </section> |
| <section xml:id="eclipse.issues"> |
| <title>Eclipse Known Issues</title> |
| <para>Eclipse will currently complain about <filename>Bytes.java</filename>. It is not possible to turn these errors off.</para> |
| <programlisting> |
| Description Resource Path Location Type |
| Access restriction: The method arrayBaseOffset(Class) from the type Unsafe is not accessible due to restriction on required library /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar Bytes.java /hbase/src/main/java/org/apache/hadoop/hbase/util line 1061 Java Problem |
| Access restriction: The method arrayIndexScale(Class) from the type Unsafe is not accessible due to restriction on required library /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar Bytes.java /hbase/src/main/java/org/apache/hadoop/hbase/util line 1064 Java Problem |
| Access restriction: The method getLong(Object, long) from the type Unsafe is not accessible due to restriction on required library /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar Bytes.java /hbase/src/main/java/org/apache/hadoop/hbase/util line 1111 Java Problem |
| </programlisting> |
| </section> |
| <section xml:id="eclipse.more"> |
| <title>Eclipse - More Information</title> |
| <para>For additional information on setting up Eclipse for HBase development on Windows, see |
| <link xlink:href="http://michaelmorello.blogspot.com/2011/09/hbase-subversion-eclipse-windows.html">Michael Morello's blog</link> on the topic. |
| </para> |
| </section> |
| </section> |
| </section> |
| |
| <section xml:id="build"> |
| <title>Building HBase</title> |
| <para>This section will be of interest only to those building HBase from source. |
| </para> |
| <section xml:id="build.snappy"> |
| <title>Building in snappy compression support</title> |
| <para>Pass <code>-Dsnappy</code> to trigger the snappy maven profile for building |
| snappy native libs into hbase.</para> |
| </section> |
| |
| <section xml:id="build.tgz"> |
| <title>Building the HBase tarball</title> |
| <para>Do the following to build the HBase tarball. |
| Passing the -Drelease will generate javadoc and run the RAT plugin to verify licenses on source. |
| <programlisting>% MAVEN_OPTS="-Xmx2g" mvn clean site install assembly:single -Dmaven.test.skip -Prelease</programlisting> |
| </para> |
| </section> |
| |
| <section xml:id="mvn_repo"> |
| <title>Adding an HBase release to Apache's Maven Repository</title> |
| <para>Follow the instructions at |
| <link xlink:href="http://www.apache.org/dev/publishing-maven-artifacts.html">Publishing Maven Artifacts</link>. |
| The 'trick' to making it all work is answering the questions put to you by the mvn release plugin properly, |
| making sure it is using the actual branch AND before doing the <command>mvn release:perform</command> step, |
| VERY IMPORTANT, hand edit the release.properties file that was put under <varname>${HBASE_HOME}</varname> |
| by the previous step, <command>release:perform</command>. You need to edit it to make it point at |
| right locations in SVN. |
| </para> |
| <para>If you see run into the below, its because you need to edit version in the pom.xml and add |
| <code>-SNAPSHOT</code> to the version (and commit). |
| <programlisting>[INFO] Scanning for projects... |
| [INFO] Searching repository for plugin with prefix: 'release'. |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] Building HBase |
| [INFO] task-segment: [release:prepare] (aggregator-style) |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] [release:prepare {execution: default-cli}] |
| [INFO] ------------------------------------------------------------------------ |
| [ERROR] BUILD FAILURE |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] You don't have a SNAPSHOT project in the reactor projects list. |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] For more information, run Maven with the -e switch |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] Total time: 3 seconds |
| [INFO] Finished at: Sat Mar 26 18:11:07 PDT 2011 |
| [INFO] Final Memory: 35M/423M |
| [INFO] -----------------------------------------------------------------------</programlisting> |
| </para> |
| </section> |
| <section xml:id="build.gotchas"><title>Build Gotchas</title> |
| <para>If you see <code>Unable to find resource 'VM_global_library.vm'</code>, ignore it. |
| Its not an error. It is <link xlink:href="http://jira.codehaus.org/browse/MSITE-286">officially ugly</link> though. |
| </para> |
| </section> |
| </section> <!-- build --> |
| |
| <section xml:id="hbase.tests"> |
| <title>Tests</title> |
| |
| <para>HBase tests are divided into two groups: <xref linkend="hbase.unittests"/> and |
| <xref linkend="integration.tests" />. |
| Unit tests are run by the Apache Continuous Integration server and by developers |
| when they are verifying a fix does not cause breakage elsewhere in the code base. |
| Integration tests are generally long-running tests that are invoked out-of-bound of |
| the CI server when you want to do more intensive testing beyond the unit test set. |
| Integration tests, for example, are run proving a release candidate or a production |
| deploy. Below we go into more detail on each of these test types. Developers at a |
| minimum should familiarize themselves with the unit test detail; unit tests in |
| HBase have a character not usually seen in other projects.</para> |
| |
| <section xml:id="hbase.unittests"> |
| <title>Unit Tests</title> |
| <para>HBase unit tests are subdivided into three categories: small, medium and large, with |
| corresponding JUnit <link xlink:href="http://www.junit.org/node/581">categories</link>: |
| <classname>SmallTests</classname>, <classname>MediumTests</classname>, |
| <classname>LargeTests</classname>. JUnit categories are denoted using java annotations |
| and look like this in your unit test code. |
| <programlisting>... |
| @Category(SmallTests.class) |
| public class TestHRegionInfo { |
| |
| @Test |
| public void testCreateHRegionInfoName() throws Exception { |
| // ... |
| } |
| }</programlisting> |
| The above example shows how to mark a test as belonging to the small category. |
| </para> |
| <para> |
| <emphasis>Small</emphasis> tests are executed in a shared JVM. We put in this category all the tests that can |
| be executed quickly in a shared JVM. The maximum execution time for a test is 15 seconds, |
| and they do not use a cluster. <emphasis>Medium</emphasis> tests represent tests that must be executed |
| before proposing a patch. They are designed to run in less than 30 minutes altogether, |
| and are quite stable in their results. They are designed to last less than 50 seconds |
| individually. They can use a cluster, and each of them is executed in a separate JVM. |
| <emphasis>Large</emphasis> tests are everything else. They are typically integration-like |
| tests (yes, some large tests should be moved out to be HBase <xref linkend="integration.tests" />), |
| regression tests for specific bugs, timeout tests, performance tests. |
| They are executed before a commit on the pre-integration machines. They can be run on |
| the developer machine as well. |
| </para> |
| <para>HBase uses a patched maven surefire plugin and maven profiles to implement its |
| unit test characterizations.</para> |
| |
| <section xml:id="hbase.unittests.cmds"> |
| <title>Running tests</title> |
| <para>Below we describe how to run the HBase junit categories.</para> |
| |
| <section xml:id="hbase.unittests.cmds.test"> |
| <title>Default: small and medium category tests |
| </title> |
| <para>Running <programlisting>mvn test</programlisting> will execute all small tests in a single JVM and medium tests in a separate JVM for |
| each test instance. Medium tests are NOT executed if there is an error in a small test. |
| Large tests are NOT executed. There is one report for small tests, and one report for |
| medium tests if they are executed. To run small and medium tests with the security |
| profile enabled, do <programlisting>mvn test -P security</programlisting> |
| </para> |
| </section> |
| |
| <section xml:id="hbase.unittests.cmds.test.runAllTests"> |
| <title>Running all tests</title> |
| <para>Running <programlisting>mvn test -P runAllTests</programlisting> |
| will execute small tests in a single JVM then medium and large tests in a separate JVM for each test. |
| Medium and large tests are NOT executed if there is an error in a small test. |
| Large tests are NOT executed if there is an error in a small or medium test. |
| There is one report for small tests, and one report for medium and large tests if they are executed |
| </para> |
| </section> |
| |
| <section xml:id="hbase.unittests.cmds.test.localtests.mytest"> |
| <title>Running a single test or all tests in a package</title> |
| <para>To run an individual test, e.g. <classname>MyTest</classname>, do |
| <programlisting>mvn test -P localTests -Dtest=MyTest</programlisting> You can also |
| pass multiple, individual tests as a comma-delimited list: |
| <programlisting>mvn test -P localTests -Dtest=MyTest1,MyTest2,MyTest3</programlisting> |
| You can also pass a package, which will run all tests under the package: |
| <programlisting>mvn test -P localTests -Dtest=org.apache.hadoop.hbase.client.*</programlisting> |
| To run a single test with the security profile enabled: |
| <programlisting>mvn test -P security,localTests -Dtest=TestGet</programlisting> |
| </para> |
| |
| <para> |
| The <code>-P localTests</code> will remove the JUnit category effect (without this specific profile, |
| the profiles are taken into account). It will actually use the official release of surefire |
| and the old connector (The HBase build uses a patched version of the maven surefire plugin). |
| junit tests are executed in separated JVM. You will see a new message at the end of the |
| report: "[INFO] Tests are skipped". It's harmless. |
| </para> |
| </section> |
| |
| <section xml:id="hbase.unittests.cmds.test.profiles"> |
| <title>Other test invocation permutations</title> |
| <para>Running <programlisting>mvn test -P runSmallTests</programlisting> will execute small tests only, in a single JVM. |
| </para> |
| <para>Running <programlisting>mvn test -P runMediumTests</programlisting> will execute medium tests in a single JVM. |
| </para> |
| <para>Running <programlisting>mvn test -P runLargeTests</programlisting> execute medium tests in a single JVM. |
| </para> |
| |
| <para>It's also possible to use the script <command>hbasetests.sh</command>. This script runs the medium and |
| large tests in parallel with two maven instances, and provide a single report. |
| It must be executed from the directory which contains the <filename>pom.xml</filename>.</para> |
| <para>For example running |
| <programlisting>./dev-support/hbasetests.sh</programlisting> will execute small and medium tests. |
| Running <programlisting>./dev-support/hbasetests.sh runAllTests</programlisting> will execute all tests. |
| Running <programlisting>./dev-support/hbasetests.sh replayFailed</programlisting> will rerun the failed tests a |
| second time, in a separate jvm and without parallelisation. |
| </para> |
| </section> |
| </section> |
| |
| <section xml:id="hbase.tests.writing"> |
| <title>Writing Tests</title> |
| <section xml:id="hbase.tests.rules"> |
| <title>General rules</title> |
| <itemizedlist> |
| <listitem> |
| As much as possible, tests should be written as category small tests. |
| </listitem> |
| <listitem> |
| All tests must be written to support parallel execution on the same machine, hence they should not use shared resources as fixed ports or fixed file names. |
| </listitem> |
| <listitem> |
| Tests should not overlog. More than 100 lines/second makes the logs complex to read and use i/o that are hence not available for the other tests. |
| </listitem> |
| <listitem> |
| Tests can be written with <classname>HBaseTestingUtility</classname>. |
| This class offers helper functions to create a temp directory and do the cleanup, or to start a cluster. |
| Categories and execution time |
| </listitem> |
| <listitem> |
| All tests must be categorized, if not they could be skipped. |
| </listitem> |
| <listitem> |
| All tests should be written to be as fast as possible. |
| </listitem> |
| <listitem> |
| Small category tests should last less than 15 seconds, and must not have any side effect. |
| </listitem> |
| <listitem> |
| Medium category tests should last less than 50 seconds. |
| </listitem> |
| <listitem> |
| Large category tests should last less than 3 minutes. This should ensure a good parallelization for people using it, and ease the analysis when the test fails. |
| </listitem> |
| </itemizedlist> |
| </section> |
| <section xml:id="hbase.tests.sleeps"> |
| <title>Sleeps in tests</title> |
| <para>Whenever possible, tests should not use <methodname>Thread.sleep</methodname>, but rather waiting for the real event they need. This is faster and clearer for the reader. |
| Tests should not do a <methodname>Thread.sleep</methodname> without testing an ending condition. This allows understanding what the test is waiting for. Moreover, the test will work whatever the machine performance is. |
| Sleep should be minimal to be as fast as possible. Waiting for a variable should be done in a 40ms sleep loop. Waiting for a socket operation should be done in a 200 ms sleep loop. |
| </para> |
| </section> |
| |
| <section xml:id="hbase.tests.cluster"> |
| <title>Tests using a cluster |
| </title> |
| |
| <para>Tests using a HRegion do not have to start a cluster: A region can use the local file system. |
| Start/stopping a cluster cost around 10 seconds. They should not be started per test method but per test class. |
| Started cluster must be shutdown using <methodname>HBaseTestingUtility#shutdownMiniCluster</methodname>, which cleans the directories. |
| As most as possible, tests should use the default settings for the cluster. When they don't, they should document it. This will allow to share the cluster later. |
| </para> |
| </section> |
| </section> |
| </section> |
| |
| <section xml:id="integration.tests"> |
| <title>Integration Tests</title> |
| <para>HBase integration Tests are tests that are beyond HBase unit tests. They |
| are generally long-lasting, sizeable (the test can be asked to 1M rows or 1B rows), |
| targetable (they can take configuration that will point them at the ready-made cluster |
| they are to run against; integration tests do not include cluster start/stop code), |
| and verifying success, integration tests rely on public APIs only; they do not |
| attempt to examine server internals asserring success/fail. Integration tests |
| are what you would run when you need to more elaborate proofing of a release candidate |
| beyond what unit tests can do. They are not generally run on the Apache Continuous Integration |
| build server. |
| </para> |
| <para> |
| Integration tests currently live under the <filename>src/test</filename> directory and |
| will match the regex: <filename>**/IntegrationTest*.java</filename>. |
| </para> |
| <para>HBase 0.92 added a <varname>verify</varname> maven target. |
| Invoking it, for example by doing <code>mvn verify</code>, will |
| run all the phases up to and including the verify phase via the |
| maven <link xlink:href="http://maven.apache.org/plugins/maven-failsafe-plugin/">failsafe plugin</link>, |
| running all the above mentioned HBase unit tests as well as tests that are in the HBase integration test group. |
| If you just want to run the integration tests, you need to run two commands. First: |
| <programlisting>mvn failsafe:integration-test</programlisting> |
| This actually runs ALL the integration tests. |
| <note><para>This command will always output <code>BUILD SUCCESS</code> even if there are test failures. |
| </para></note> |
| At this point, you could grep the output by hand looking for failed tests. However, maven will do this for us; just use: |
| <programlisting>mvn failsafe:verify</programlisting> |
| The above command basically looks at all the test results (so don't remove the 'target' directory) for test failures and reports the results.</para> |
| |
| <section xml:id="maven.build.commanas.integration.tests2"> |
| <title>Running a subset of Integration tests</title> |
| <para>This is very similar to how you specify running a subset of unit tests (see above). |
| To just run <classname>IntegrationTestClassXYZ.java</classname>, use: |
| <programlisting>mvn failsafe:integration-test -Dtest=IntegrationTestClassXYZ</programlisting> |
| Pretty similar, right? |
| The next thing you might want to do is run groups of integration tests, say all integration tests that are named IntegrationTestClassX*.java: |
| <programlisting>mvn failsafe:integration-test -Dtest=*ClassX*</programlisting> |
| This runs everything that is an integration test that matches *ClassX*. This means anything matching: "**/IntegrationTest*ClassX*". |
| You can also run multiple groups of integration tests using comma-delimited lists (similar to unit tests). Using a list of matches still supports full regex matching for each of the groups.This would look something like: |
| <programlisting>mvn failsafe:integration-test -Dtest=*ClassX*, *ClassY</programlisting> |
| </para> |
| </section> |
| </section> |
| </section> <!-- tests --> |
| |
| <section xml:id="maven.build.commands"> |
| <title>Maven Build Commands</title> |
| <para>All commands executed from the local HBase project directory. |
| </para> |
| <para>Note: use Maven 3 (Maven 2 may work but we suggest you use Maven 3). |
| </para> |
| <section xml:id="maven.build.commands.compile"> |
| <title>Compile</title> |
| <programlisting> |
| mvn compile |
| </programlisting> |
| </section> |
| |
| <section xml:id="maven.build.commands.unitall"> |
| <title>Running all or individual Unit Tests</title> |
| <para>See the <xref linkend="hbase.unittests.cmds" /> section |
| above in <xref linkend="hbase.unittests" /></para> |
| </section> |
| |
| <section xml:id="maven.build.commanas.integration.tests"> |
| <title>Running all or individual Integration Tests</title> |
| <para>See <xref linkend="integration.tests" /> |
| </para> |
| </section> |
| |
| <section xml:id="maven.build.hadoop"> |
| <title>To build against hadoop 0.22.x or 0.23.x</title> |
| <programlisting> |
| mvn -Dhadoop.profile=22 ... |
| </programlisting> |
| <para>That is, designate build with hadoop.profile 22. Pass 23 for hadoop.profile to build against hadoop 0.23. |
| Tests do not all pass as of this writing so you may need ot pass <code>-DskipTests</code> unless you are inclined |
| to fix the failing tests. |
| </para> |
| </section> |
| </section> |
| |
| <section xml:id="getting.involved"> |
| <title>Getting Involved</title> |
| <para>HBase gets better only when people contribute! |
| </para> |
| <para>As HBase is an Apache Software Foundation project, see <xref linkend="asf"/> for more information about how the ASF functions. |
| </para> |
| <section xml:id="mailing.list"> |
| <title>Mailing Lists</title> |
| <para>Sign up for the dev-list and the user-list. See the |
| <link xlink:href="http://hbase.apache.org/mail-lists.html">mailing lists</link> page. |
| Posing questions - and helping to answer other people's questions - is encouraged! |
| There are varying levels of experience on both lists so patience and politeness are encouraged (and please |
| stay on topic.) |
| </para> |
| </section> |
| <section xml:id="jira"> |
| <title>Jira</title> |
| <para>Check for existing issues in <link xlink:href="https://issues.apache.org/jira/browse/HBASE">Jira</link>. |
| If it's either a new feature request, enhancement, or a bug, file a ticket. |
| </para> |
| <section xml:id="jira.priorities"><title>Jira Priorities</title> |
| <para>The following is a guideline on setting Jira issue priorities: |
| <itemizedlist> |
| <listitem>Blocker: Should only be used if the issue WILL cause data loss or cluster instability reliably.</listitem> |
| <listitem>Critical: The issue described can cause data loss or cluster instability in some cases.</listitem> |
| <listitem>Major: Important but not tragic issues, like updates to the client API that will add a lot of much-needed functionality or significant |
| bugs that need to be fixed but that don't cause data loss.</listitem> |
| <listitem>Minor: Useful enhancements and annoying but not damaging bugs.</listitem> |
| <listitem>Trivial: Useful enhancements but generally cosmetic.</listitem> |
| </itemizedlist> |
| </para> |
| </section> |
| <section xml:id="submitting.patches.jira.code"> |
| <title>Code Blocks in Jira Comments</title> |
| <para>A commonly used macro in Jira is {code}. If you do this in a Jira comment... |
| <programlisting> |
| {code} |
| code snippet |
| {code} |
| </programlisting> |
| ... Jira will format the code snippet like code, instead of a regular comment. It improves readability. |
| </para> |
| </section> |
| </section> <!-- jira --> |
| </section> <!-- getting involved --> |
| |
| <section xml:id="developing"> |
| <title>Developing</title> |
| <section xml:id="codelines"><title>Codelines</title> |
| <para>Most development is done on TRUNK. However, there are branches for minor releases (e.g., 0.90.1, 0.90.2, and 0.90.3 are on the 0.90 branch).</para> |
| <para>If you have any questions on this just send an email to the dev dist-list.</para> |
| </section> |
| |
| <section xml:id="unit.tests"> |
| <title>Unit Tests</title> |
| <para>In HBase we use <link xlink:href="http://junit.org">JUnit</link> 4. |
| If you need to run miniclusters of HDFS, ZooKeeper, HBase, or MapReduce testing, |
| be sure to checkout the <classname>HBaseTestingUtility</classname>. |
| Alex Baranau of Sematext describes how it can be used in |
| <link xlink:href="http://blog.sematext.com/2010/08/30/hbase-case-study-using-hbasetestingutility-for-local-testing-development/">HBase Case-Study: Using HBaseTestingUtility for Local Testing and Development</link> (2010). |
| </para> |
| <section xml:id="mockito"> |
| <title>Mockito</title> |
| <para>Sometimes you don't need a full running server |
| unit testing. For example, some methods can make do with a |
| a <classname>org.apache.hadoop.hbase.Server</classname> instance |
| or a <classname>org.apache.hadoop.hbase.master.MasterServices</classname> |
| Interface reference rather than a full-blown |
| <classname>org.apache.hadoop.hbase.master.HMaster</classname>. |
| In these cases, you maybe able to get away with a mocked |
| <classname>Server</classname> instance. For example: |
| <programlisting> |
| TODO... |
| </programlisting> |
| </para> |
| </section> |
| <section xml:id="code.standards"> |
| <title>Code Standards</title> |
| <para>See <xref linkend="eclipse.code.formatting"/> and <xref linkend="common.patch.feedback"/>. |
| </para> |
| </section> |
| </section> <!-- unit tests --> |
| |
| </section> <!-- developing --> |
| |
| <section xml:id="submitting.patches"> |
| <title>Submitting Patches</title> |
| <section xml:id="submitting.patches.create"> |
| <title>Create Patch</title> |
| <para>Patch files can be easily generated from Eclipse, for example by selecting "Team -> Create Patch". |
| Patches can also be created by git diff and svn diff. |
| </para> |
| <para>Please submit one patch-file per Jira. For example, if multiple files are changed make sure the |
| selected resource when generating the patch is a directory. Patch files can reflect changes in multiple files. </para> |
| <para>Make sure you review <xref linkend="eclipse.code.formatting"/> for code style. </para> |
| </section> |
| <section xml:id="submitting.patches.naming"> |
| <title>Patch File Naming</title> |
| <para>The patch file should have the HBase Jira ticket in the name. For example, if a patch was submitted for <filename>Foo.java</filename>, then |
| a patch file called <filename>Foo_HBASE_XXXX.patch</filename> would be acceptable where XXXX is the HBase Jira number. |
| </para> |
| <para>If you generating from a branch, then including the target branch in the filename is advised, e.g., <filename>HBASE-XXXX-0.90.patch</filename>. |
| </para> |
| </section> |
| <section xml:id="submitting.patches.tests"> |
| <title>Unit Tests</title> |
| <para>Yes, please. Please try to include unit tests with every code patch (and especially new classes and large changes). |
| Make sure unit tests pass locally before submitting the patch.</para> |
| <para>Also, see <xref linkend="mockito"/>.</para> |
| </section> |
| <section xml:id="submitting.patches.jira"> |
| <title>Attach Patch to Jira</title> |
| <para>The patch should be attached to the associated Jira ticket "More Actions -> Attach Files". Make sure you click the |
| ASF license inclusion, otherwise the patch can't be considered for inclusion. |
| </para> |
| <para>Once attached to the ticket, click "Submit Patch" and |
| the status of the ticket will change. Committers will review submitted patches for inclusion into the codebase. Please |
| understand that not every patch may get committed, and that feedback will likely be provided on the patch. Fear not, though, |
| because the HBase community is helpful! |
| </para> |
| </section> |
| |
| <section xml:id="common.patch.feedback"> |
| <title>Common Patch Feedback</title> |
| <para>The following items are representative of common patch feedback. Your patch process will go faster if these are |
| taken into account <emphasis>before</emphasis> submission. |
| </para> |
| <para> |
| See the <link xlink:href="http://www.oracle.com/technetwork/java/codeconv-138413.html">Java coding standards</link> |
| for more information on coding conventions in Java. |
| </para> |
| <section xml:id="common.patch.feedback.space.invaders"> |
| <title>Space Invaders</title> |
| <para>Rather than do this... |
| <programlisting> |
| if ( foo.equals( bar ) ) { // don't do this |
| </programlisting> |
| ... do this instead... |
| <programlisting> |
| if (foo.equals(bar)) { |
| </programlisting> |
| </para> |
| <para>Also, rather than do this... |
| <programlisting> |
| foo = barArray[ i ]; // don't do this |
| </programlisting> |
| ... do this instead... |
| <programlisting> |
| foo = barArray[i]; |
| </programlisting> |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.autogen"> |
| <title>Auto Generated Code</title> |
| <para>Auto-generated code in Eclipse often looks like this... |
| <programlisting> |
| public void readFields(DataInput arg0) throws IOException { // don't do this |
| foo = arg0.readUTF(); // don't do this |
| </programlisting> |
| ... do this instead ... |
| <programlisting> |
| public void readFields(DataInput di) throws IOException { |
| foo = di.readUTF(); |
| </programlisting> |
| See the difference? 'arg0' is what Eclipse uses for arguments by default. |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.longlines"> |
| <title>Long Lines</title> |
| <para> |
| Keep lines less than 80 characters. |
| <programlisting> |
| Bar bar = foo.veryLongMethodWithManyArguments(argument1, argument2, argument3, argument4, argument5); // don't do this |
| </programlisting> |
| ... do this instead ... |
| <programlisting> |
| Bar bar = foo.veryLongMethodWithManyArguments(argument1, |
| argument2, argument3,argument4, argument5); |
| </programlisting> |
| ... or this, whichever looks better ... |
| <programlisting> |
| Bar bar = foo.veryLongMethodWithManyArguments( |
| argument1, argument2, argument3,argument4, argument5); |
| </programlisting> |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.trailingspaces"> |
| <title>Trailing Spaces</title> |
| <para> |
| This happens more than people would imagine. |
| <programlisting> |
| Bar bar = foo.getBar(); <--- imagine there's an extra space(s) after the semicolon instead of a line break. |
| </programlisting> |
| Make sure there's a line-break after the end of your code, and also avoid lines that have nothing |
| but whitespace. |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.writable"> |
| <title>Implementing Writable</title> |
| <para>Every class returned by RegionServers must implement <code>Writable</code>. If you |
| are creating a new class that needs to implement this interface, don't forget the default constructor. |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.javadoc"> |
| <title>Javadoc</title> |
| <para>This is also a very common feedback item. Don't forget Javadoc! |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.javadoc.defaults"> |
| <title>Javadoc - Useless Defaults</title> |
| <para>Don't just leave the @param arguments the way your IDE generated them. Don't do this... |
| <programlisting> |
| /** |
| * |
| * @param bar <---- don't do this!!!! |
| * @return <---- or this!!!! |
| */ |
| public Foo getFoo(Bar bar); |
| </programlisting> |
| ... either add something descriptive to the @param and @return lines, or just remove them. |
| But the preference is to add something descriptive and useful. |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.onething"> |
| <title>One Thing At A Time, Folks</title> |
| <para>If you submit a patch for one thing, don't do auto-reformatting or unrelated reformatting of code on a completely |
| different area of code. |
| </para> |
| <para>Likewise, don't add unrelated cleanup or refactorings outside the scope of your Jira. |
| </para> |
| </section> |
| <section xml:id="common.patch.feedback.tests"> |
| <title>Ambigious Unit Tests</title> |
| <para>Make sure that you're clear about what you are testing in your unit tests and why. |
| </para> |
| </section> |
| |
| </section> <!-- patch feedback --> |
| |
| <section xml:id="reviewboard"> |
| <title>ReviewBoard</title> |
| <para>Larger patches should go through <link xlink:href="http://reviews.apache.org">ReviewBoard</link>. |
| </para> |
| <para>For more information on how to use ReviewBoard, see |
| <link xlink:href="http://www.reviewboard.org/docs/manual/1.5/">the ReviewBoard documentation</link>. |
| </para> |
| </section> |
| <section xml:id="committing.patches"> |
| <title>Committing Patches</title> |
| <para> |
| Committers do this. See <link xlink:href="http://wiki.apache.org/hadoop/Hbase/HowToCommit">How To Commit</link> in the HBase wiki. |
| </para> |
| <para>Commiters will also resolve the Jira, typically after the patch passes a build. |
| </para> |
| </section> |
| |
| </section> <!-- submitting patches --> |
| |
| </chapter> |