Index: hbase-server/src/main/java/org/apache/hadoop/hbase/master/TableNamespaceManager.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/TableNamespaceManager.java (revision 1526747) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/TableNamespaceManager.java (working copy) @@ -79,9 +79,8 @@ } public void start() throws IOException { - TableName tableName = TableName.NAMESPACE_TABLE_NAME; if (!MetaReader.tableExists(masterServices.getCatalogTracker(), - tableName)) { + TableName.NAMESPACE_TABLE_NAME)) { LOG.info("Namespace table not found. Creating..."); createNamespaceTable(masterServices); } @@ -92,8 +91,7 @@ // So that it should be initialized later on lazily. long startTime = EnvironmentEdgeManager.currentTimeMillis(); int timeout = conf.getInt(NS_INIT_TIMEOUT, DEFAULT_NS_INIT_TIMEOUT); - while(masterServices.getAssignmentManager() - .getRegionStates().getRegionsOfTable(tableName).isEmpty()) { + while (isTableAssigned()) { if (EnvironmentEdgeManager.currentTimeMillis() - startTime + 100 > timeout) { LOG.warn("Timedout waiting for namespace table to be assigned."); return; @@ -105,47 +103,12 @@ } // initialize namespace table - getNamespaceTable(); + isTableAvailableAndInitialized(); } - @SuppressWarnings("deprecation") private synchronized HTable getNamespaceTable() throws IOException { - if (!initialized) { - try { - nsTable = new HTable(conf, TableName.NAMESPACE_TABLE_NAME); - zkNamespaceManager = new ZKNamespaceManager(masterServices.getZooKeeper()); - zkNamespaceManager.start(); - - if (get(nsTable, NamespaceDescriptor.DEFAULT_NAMESPACE.getName()) == null) { - create(nsTable, NamespaceDescriptor.DEFAULT_NAMESPACE); - } - if (get(nsTable, NamespaceDescriptor.SYSTEM_NAMESPACE.getName()) == null) { - create(nsTable, NamespaceDescriptor.SYSTEM_NAMESPACE); - } - - ResultScanner scanner = nsTable.getScanner(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES); - try { - for(Result result : scanner) { - byte[] val = CellUtil.cloneValue(result.getColumnLatest(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES, - HTableDescriptor.NAMESPACE_COL_DESC_BYTES)); - NamespaceDescriptor ns = - ProtobufUtil.toNamespaceDescriptor( - HBaseProtos.NamespaceDescriptor.parseFrom(val)); - zkNamespaceManager.update(ns); - } - } finally { - scanner.close(); - } - initialized = true; - } catch (IOException ie) { - LOG.warn("Caught exception in initializing namespace table manager", ie); - if (nsTable != null) { - nsTable.close(); - } - throw ie; - } - } else if (nsTable.getConnection().isClosed()) { - nsTable = new HTable(conf, TableName.NAMESPACE_TABLE_NAME); + if (!isTableAvailableAndInitialized()) { + throw new IOException(this.getClass().getName() + " isn't ready to serve"); } return nsTable; } @@ -272,4 +235,68 @@ newRegions, masterServices).prepare()); } + + /** + * This method checks if the namespace table is assigned and then + * tries to create its HTable. If it was already created before, it also makes + * sure that the connection isn't closed. + * @return true if the namespace table manager is ready to serve, false + * otherwise + * @throws IOException + */ + @SuppressWarnings("deprecation") + public synchronized boolean isTableAvailableAndInitialized() throws IOException { + // Did we already get a table? If so, still make sure it's available + if (initialized) { + if (nsTable.getConnection().isClosed()) { + nsTable = new HTable(conf, TableName.NAMESPACE_TABLE_NAME); + } + return true; + } + + // Now check if the table is assigned, if not then fail fast + if (isTableAssigned()) { + try { + nsTable = new HTable(conf, TableName.NAMESPACE_TABLE_NAME); + zkNamespaceManager = new ZKNamespaceManager(masterServices.getZooKeeper()); + zkNamespaceManager.start(); + + if (get(nsTable, NamespaceDescriptor.DEFAULT_NAMESPACE.getName()) == null) { + create(nsTable, NamespaceDescriptor.DEFAULT_NAMESPACE); + } + if (get(nsTable, NamespaceDescriptor.SYSTEM_NAMESPACE.getName()) == null) { + create(nsTable, NamespaceDescriptor.SYSTEM_NAMESPACE); + } + + ResultScanner scanner = nsTable.getScanner(HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES); + try { + for (Result result : scanner) { + byte[] val = CellUtil.cloneValue(result.getColumnLatest( + HTableDescriptor.NAMESPACE_FAMILY_INFO_BYTES, + HTableDescriptor.NAMESPACE_COL_DESC_BYTES)); + NamespaceDescriptor ns = + ProtobufUtil.toNamespaceDescriptor( + HBaseProtos.NamespaceDescriptor.parseFrom(val)); + zkNamespaceManager.update(ns); + } + } finally { + scanner.close(); + } + initialized = true; + return true; + } catch (IOException ie) { + LOG.warn("Caught exception in initializing namespace table manager", ie); + if (nsTable != null) { + nsTable.close(); + } + throw ie; + } + } + return false; + } + + private boolean isTableAssigned() { + return !masterServices.getAssignmentManager() + .getRegionStates().getRegionsOfTable(TableName.NAMESPACE_TABLE_NAME).isEmpty(); + } } Index: hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 1526747) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (working copy) @@ -219,9 +219,7 @@ import org.apache.zookeeper.Watcher; import org.apache.hadoop.hbase.exceptions.DeserializationException; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.google.protobuf.Descriptors; import com.google.protobuf.Message; import com.google.protobuf.RpcCallback; @@ -3092,6 +3090,9 @@ @Override public NamespaceDescriptor getNamespaceDescriptor(String name) throws IOException { + if (!isTableNamespaceManagerReady()) { + throw new IOException("Table Namespace Manager not ready yet, try again later"); + } NamespaceDescriptor nsd = tableNamespaceManager.get(name); if (nsd == null) { throw new NamespaceNotFoundException(name); @@ -3101,23 +3102,41 @@ @Override public List listNamespaceDescriptors() throws IOException { + if (!isTableNamespaceManagerReady()) { + return Lists.newArrayList(); + } return Lists.newArrayList(tableNamespaceManager.list()); } @Override public List listTableDescriptorsByNamespace(String name) throws IOException { + if (!isTableNamespaceManagerReady()) { + return Lists.newArrayList(); + } getNamespaceDescriptor(name); // check that namespace exists return Lists.newArrayList(tableDescriptors.getByNamespace(name).values()); } @Override public List listTableNamesByNamespace(String name) throws IOException { + List tableNames = Lists.newArrayList(); + if (!isTableNamespaceManagerReady()) { + return tableNames; + } getNamespaceDescriptor(name); // check that namespace exists - List tableNames = Lists.newArrayList(); for (HTableDescriptor descriptor: tableDescriptors.getByNamespace(name).values()) { tableNames.add(descriptor.getTableName()); } return tableNames; } + private boolean isTableNamespaceManagerReady() throws IOException { + boolean ready = tableNamespaceManager != null && + tableNamespaceManager.isTableAvailableAndInitialized(); + if (!ready) { + LOG.warn("Table Namespace Manager not ready yet"); + } + return ready; + } + }