Initial commit: add a README.

Change-Id: Ieef2aac31e697049207c574d0a1e79595aacd2f7
Initial commit: import the code.

Change-Id: Ibd70fdf70af54901883980185b0d17d67f0febb0
Fix a ClassCastException in the code handling NotServingRegionException.

When invoked from RegionClient#deserialize, a String is always passed
in argument, not a byte[].

Change-Id: I80b409330290095360808adc5e953edc40dcd88d
Stop using a ChannelDownstreamHandler in the RegionClient.

When sending an RPC out to the wire, the code used to call:
  Channels.write(chan, rpc);
Then Netty would create a DownstreamMessageEvent wrapping the HBaseRpc,
and hand it to the RegionClient corresponding to this channel.
Then HBaseRpc would then get serialized into a ChannelBuffer, which
would then be passed on downstream (after being wrapped into another
new DownstreamMessageEvent) to the ChannelSink.

The new code instead serializes the HBaseRpc into a ChannelBuffer
before giving it to Netty, which will pass it straight to the
ChannelSink (after wrapping it in a DownstreamMessageEvent).  This
results in a smaller code path before we actually hit the wire and
fewer objects allocated on each write (so less work for the GC).

Change-Id: I0828f6443bf8c4d9e570e0c78720187b1543bdd2
Switch from LGPLv3+ to BSD license.

For the records, I wanted to use the LGPL, I think it's a fair license.
Unfortunately, the ASF doesn't allow inclusion of LGPL code in their
projects, and many seemed concerned about the "virality" of the LGPL.
I don't approve this change, and I tried to resist it, but due to
popular demand, this software package is switching to the BSD license.

Change-Id: Ice53f20c9927a708dc1805a2e1af3fa17be14125
Fix the retry logic for the multiPut RPC.

When a multiPut partially fails, the code builds another multiPut to
retry all the edits that are known to have potentially failed.  But
the new multiPut RPC that was built always had its `size' attribute
set to 0.

Also, MultiPutRequest had an `attempt' attribute that was
unintentionally shadowing the `attempt' attribute in the parent class
(HBaseRpc).  This was confusing and error-prone, so the attribute got
renamed as `retrycnt'.

MultiPutRequest now overrides toString in order to provide a meaningful
return value (which is particularly important when logging failed puts).

Change-Id: Ie0cb550c8c3b02d71cb2b3028c8e52776a28fc6b
Fix the comparator of .META. row keys to properly handle keys with commas.

A .META. row key looks like this:
    table,start_key,timestamp[.md5hash.]
But the code in RegionNameCmp failed to take into account that
`start_key' could contain an arbitrary number of commas.  The fix
is straightforward: start looking for the 2nd comma from the end.

This consequence of this bug was that sometimes, HBaseClient was unable
to execute RPCs for row keys containing a comma in them as it would find
the wrong entry in its region cache.

Change-Id: Ida8e608848bb65906183bfacae1da681efc942a4
Add Berk to the THANKS file, for his code reviews.

Change-Id: Iab165e5733bc845b9adc2d6491202df260627801
Add a missing final keyword.

Without this, there was a potential (albeit very unlikely)
race condition when assigning the first RPC ID.

Change-Id: I0ba5b4e2133a5ec32e5199cf35aa3393a5b3478f
Implement a meaningful toString method for getClosestRowBefore.

This anonymous HBaseRpc had a toString representation that was not
helpful during debugging.

Change-Id: If0061fc13b96044da9ee862dc2321228cd498e38
Fix some logging messages to be more consistent.

No actual code change.  Makes grepping logs easier.
One of the log messages was confusing as it was referring to
a callback that was removed a long time ago, even before the
public release.

Change-Id: I037e7c9a04bf37ce7fdf7b4a1ae7748492e65a6d
Log only slow DNS lookups.

Since DNS is blocking and can be slow, logging was added (albeit at the
DEBUG level) to keep track of time spent doing DNS lookups.  This change
makes logging more useful and less spammy at the DEBUG level.  Lookups
that complete in less than 0.5ms aren't logged at all (typically cache
hits when the JDK has already looked up the name before).  Lookups that
complete in 3ms or more are logged at the WARN level.  Given that HBase
is typically deployed in high-speed LANs, 3ms sounds like a reasonable
threshold for a DNS lookup.

Change-Id: I976dfad8c8218c4fb4a3524c0f719df75b927bbb
Fix improper synchronization.

Before accessing the `ip2client' map, one code path was acquiring
the wrong monitor, which lead to weird race conditions while it was
iterating on the map's entries.

Change-Id: I2b3ebd6f68950f276ebac0f4af858306d99e56a9
Reduce lock contention on ip2client's lock.

When a new connection was opened to a RegionServer, the code
was unnecessarily holding the lock on the ip2client map while
configuring and connecting the channel.  I actually observed
contention on this lock because of that, even though connect()
is non-blocking and returns quickly.  The new code is slightly
awkward / less natural to read, but it's worth it.

Change-Id: I4482c49c60f50c9a5d6911a2154119755c4d5a77
Behave better when the znode of -ROOT- doesn't exist.

The code was closing the connection to ZK and sleeping 1s before
re-connecting to ZK and trying again.  Now the connection is kept
open and the code simply retries to read the znode again after 1s,
if the ZK session is still valid.

The ideal would be to setup a watch in ZK to wait until the znode
is created or updated.  This will be implemented later.

Change-Id: I305a24efee21f6226616fa28b9594e7fa32b925a
Fix the region name comparator and cache invalidation logic.

The region name comparator wasn't behaving properly when a table had a
name that was a prefix of another one (e.g. "mytable" and "mytablefoo").
When comparing two region names, such as:
  mytable,somekey,1234567890
  mytablefoo,otherkey,1234567890
It was returning the difference between first two different bytes (so
in this case, ',' - 'f' = 44 - 102 = -58).  This bug was non impacting
because ',' (=44) is less than every ASCII character typically used in
table names (typically [-_a-zA-Z0-9], which are all >44).

The cache invalidation logic wasn't properly clearing the regions_cache
when invalidating the last region of a table (the one with an empty stop
key).  It was actually working for all tables except the first one to
appear in the regions_cache (typically .META., unless all .META. regions
have already been invalidated from the cache).  The new logic uses a
different approach to locate the last region of a table in the cache
that also works for the first table.

Change-Id: I78e9ad0eb830f8a3316bf6fececb54ee63f6e246
Add missing synchronization.

client2regions is a map that associates each client connected to a
RegionServer to a list of regions that are known to be served by this
RegionServer.  The map itself is thread-safe, but the lists that were
added to it are not thread-safe, and they were accessed without any
synchronization.  Although there was a potential for race conditions,
those were extremely rare since this map is rarely accessed (only after
successful .META. lookups and after disconnecting from a RegionServer).

Change-Id: I392e5e2a60c9f972eee8891651ea4125f57f28e2
Fix the disconnection handling code.

The code was racy and could lead to lost RPCs or "deadlocks" when
getting unexpectedly disconnected from a RegionServer.  This was
particularly troublesome when HBase restarted (all of it).  When
HBase starts, it first brings online the -ROOT- region.  When the
client reads it to find where .META. is, it may find a stale entry
if the master hasn't updated it already.  Surprisingly, this happened
very frequently during restarts as HBase seems slow to start up.
Similarly, once -ROOT- was updated to point to .META. correctly,
the client could read stale .META. entries while the master was in
the process of bringing back up the regions and updating .META.

Under those circumstances, the client was frequently reading stale
ip:port information and getting a ConnectException.  The code that
was invalidating known information about the client wasn't doing the
right thing in this case, it wasn't invalidating anything, as it
made the wrong assumption that a client that had never been successfully
connected couldn't possibly be in the caches.

The new code prioritizes the invalidation of the reference to the
-ROOT- region when we get disconnected from it.  It also prioritizes
invalidation of our local cache of .META..

Because HBase is slow to start, this change is also increasing the
maximum number of attempts to send an RPC from 4 to 10.  In practice,
it seems that this is still insufficient, although hopefully with the
new master HBase will be able to start faster.  This means that during
an HBase restart, RPCs are likely to fail with a "Too many attempts"
exception, which is acceptable since HBase is indeed unavailable during
this period of time, and the application must be able to ride over such
transient HBase outages.  I'm wary of allow more retry attempts,
although this should be configurable (right now it's not).

Change-Id: I1cffd7bd22d3e6206af8997f5a29983de15dd296
Improve handling of NotServingRegionException slightly.

The code handling NotServingRegionException was suboptimal.  If the
RPC was on its last attempt, the code was making the RPC fail without
invaliding the local META cache.  Also, error reporting wasn't as
good as it could have been.  When an RPC fails because it was already
retried too many times, it would be good to know what the cause of
the last failure was (even though NotServingRegionException is the
most likely cause, swallowing the exception leads to sub-par error
reporting).

The code handling NSRE is still way suboptimal and doesn't always do
the right thing.  It'll be rewritten to be correct soon.

Change-Id: I4180ad007066684df5f0d9a8a16e883b5e83ed3a
Add more missing synchronization.

Once again (re: 7b65ff0), some seemingly innocuous logging statement was
iterating over a value of client2regions without holding the appropriate
lock.  Instead of doing that, we now simply record and log the size of
the array, which also makes the messages logged more readable when using
many regions (otherwise messages could get pretty large).

Change-Id: I593b81d151ad5878997295fbcc0a716c7882ca06