Index: src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (revision 1220630) +++ src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (working copy) @@ -623,14 +623,20 @@ throws MasterNotRunningException, ZooKeeperConnectionException { // Check if we already have a good master connection - if (master != null) { - if (master.isMasterRunning()) { + try { + if (master != null && master.isMasterRunning()) { return master; } + } catch (UndeclaredThrowableException ute) { + // log, but ignore, the loop below will attempt to reconnect + LOG.info("Exception contacting master. Retrying...", ute.getCause()); } + checkIfBaseNodeAvailable(); ServerName sn = null; synchronized (this.masterLock) { + this.master = null; + for (int tries = 0; !this.closed && !this.masterChecked && this.master == null && @@ -679,15 +685,19 @@ throw new RuntimeException("Thread was interrupted while trying to connect to master."); } } - this.masterChecked = true; - } - if (this.master == null) { - if (sn == null) { - throw new MasterNotRunningException(); + // Avoid re-checking in the future if this is a managed HConnection, + // even if we failed to acquire a master. + // (this is to retain the existing behavior before HBASE-5058) + this.masterChecked = managed; + + if (this.master == null) { + if (sn == null) { + throw new MasterNotRunningException(); + } + throw new MasterNotRunningException(sn.toString()); } - throw new MasterNotRunningException(sn.toString()); + return this.master; } - return this.master; } private void checkIfBaseNodeAvailable() throws MasterNotRunningException { Index: src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (revision 1220630) +++ src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (working copy) @@ -95,7 +95,7 @@ public HBaseAdmin(Configuration c) throws MasterNotRunningException, ZooKeeperConnectionException { this.conf = HBaseConfiguration.create(c); - this.connection = HConnectionManager.getConnection(this.conf); + this.connection = HConnectionManager.getConnection(this.conf); this.pause = this.conf.getLong("hbase.client.pause", 1000); this.numRetries = this.conf.getInt("hbase.client.retries.number", 10); this.retryLongerMultiplier = this.conf.getInt( @@ -111,9 +111,6 @@ } catch (MasterNotRunningException mnre) { HConnectionManager.deleteStaleConnection(this.connection); this.connection = HConnectionManager.getConnection(this.conf); - } catch (UndeclaredThrowableException ute) { - HConnectionManager.deleteStaleConnection(this.connection); - this.connection = HConnectionManager.getConnection(this.conf); } tries++; @@ -135,6 +132,29 @@ } } + /** + * Constructor for externally managed HConnections. + * This constructor fails fast if the HMaster is not running. + * The HConnection can be re-used again in another attempt. + * This constructor fails fast. + * + * @param connection The HConnection instance to use + * @throws MasterNotRunningException if the master is not running + * @throws ZooKeeperConnectionException if unable to connect to zookeeper + */ + public HBaseAdmin(HConnection connection) + throws MasterNotRunningException, ZooKeeperConnectionException { + this.conf = connection.getConfiguration(); + this.connection = connection; + + this.pause = this.conf.getLong("hbase.client.pause", 1000); + this.numRetries = this.conf.getInt("hbase.client.retries.number", 10); + this.retryLongerMultiplier = this.conf.getInt( + "hbase.client.retries.longer.multiplier", 10); + + this.connection.getMaster(); + } + /** * @return A new CatalogTracker instance; call {@link #cleanupCatalogTracker(CatalogTracker)} * to cleanup the returned catalog tracker.