HBASE-10785 Metas own location should be cached git-svn-id: https://svn.apache.org/repos/asf/hbase/branches/hbase-10070@1586653 13f79535-47bb-0310-9956-ffa450edef68
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/48ffa4d5 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/48ffa4d5 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/48ffa4d5 Branch: refs/heads/master Commit: 48ffa4d5e615c78f6db8f6c2beddd93460887642 Parents: 579f305 Author: Enis Soztutar <e...@apache.org> Authored: Fri Apr 11 13:46:59 2014 +0000 Committer: Enis Soztutar <e...@apache.org> Committed: Fri Jun 27 16:39:39 2014 -0700 ---------------------------------------------------------------------- .../hadoop/hbase/client/ConnectionManager.java | 36 +++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/48ffa4d5/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionManager.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionManager.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionManager.java index ff30ef4..d6d6491 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionManager.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionManager.java @@ -560,6 +560,9 @@ class ConnectionManager { // package protected for the tests ClusterStatusListener clusterStatusListener; + + private final Object metaRegionLock = new Object(); + // We have a single lock for master & zk to prevent deadlocks. Having // one lock for ZK and one lock for master is not possible: // When creating a connection to master, we need a connection to ZK to get @@ -1085,13 +1088,44 @@ class ConnectionManager { } if (tableName.equals(TableName.META_TABLE_NAME)) { - return this.registry.getMetaRegionLocation(); + return locateMeta(tableName, useCache, replicaId); } else { // Region not in the cache - have to go to the meta RS return locateRegionInMeta(tableName, row, useCache, retry, replicaId); } } + private RegionLocations locateMeta(final TableName tableName, + boolean useCache, int replicaId) throws IOException { + // HBASE-10785: We cache the location of the META itself, so that we are not overloading + // zookeeper with one request for every region lookup. We cache the META with empty row + // key in MetaCache. + byte[] metaCacheKey = HConstants.EMPTY_START_ROW; // use byte[0] as the row for meta + RegionLocations locations = null; + if (useCache) { + locations = getCachedLocation(tableName, metaCacheKey); + if (locations != null) { + return locations; + } + } + + // only one thread should do the lookup. + synchronized (metaRegionLock) { + // Check the cache again for a hit in case some other thread made the + // same query while we were waiting on the lock. + locations = getCachedLocation(tableName, metaCacheKey); + if (locations != null) { + return locations; + } + // Look up from zookeeper + locations = this.registry.getMetaRegionLocation(); + if (locations != null) { + cacheLocation(tableName, locations); + } + } + return locations; + } + /* * Search the hbase:meta table for the HRegionLocation * info that contains the table and row we're seeking.