blob: 0c139b843ed0ce2cde85c89fc05918b39e447998 [file] [log] [blame]
<?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 -&gt; Install New Software -&gt; (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 -&gt; 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 -&gt; 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(); &lt;--- 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 &lt;---- don't do this!!!!
* @return &lt;---- 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>