/* (non-Javadoc) * @see org.apache.hadoop.hbase.TableDescriptors#getTableDescriptor(byte[]) */ @Override public HTableDescriptor get(final String tablename) throws IOException { invocations++; if (HTableDescriptor.ROOT_TABLEDESC.getNameAsString().equals(tablename)) { cachehits++; return HTableDescriptor.ROOT_TABLEDESC; } if (HTableDescriptor.META_TABLEDESC.getNameAsString().equals(tablename)) { cachehits++; return HTableDescriptor.META_TABLEDESC; } // .META. and -ROOT- is already handled. If some one tries to get the descriptor for // .logs, .oldlogs or .corrupt throw an exception. if (HConstants.HBASE_NON_USER_TABLE_DIRS.contains(tablename)) { throw new IOException("No descriptor found for table = " + tablename); } // Look in cache of descriptors. TableDescriptorModtime cachedtdm = this.cache.get(tablename); if (cachedtdm != null) { // Check mod time has not changed (this is trip to NN). if (getTableInfoModtime(this.fs, this.rootdir, tablename) <= cachedtdm.getModtime()) { cachehits++; return cachedtdm.getTableDescriptor(); } } TableDescriptorModtime tdmt = null; try { tdmt = getTableDescriptorModtime(this.fs, this.rootdir, tablename); } catch (NullPointerException e) { LOG.debug("Exception during readTableDecriptor. Current table name = " + tablename, e); } catch (IOException ioe) { LOG.debug("Exception during readTableDecriptor. Current table name = " + tablename, ioe); } if (tdmt == null) { LOG.warn( "The following folder is in HBase's root directory and " + "doesn't contain a table descriptor, " + "do consider deleting it: " + tablename); } else { this.cache.put(tablename, tdmt); } return tdmt == null ? null : tdmt.getTableDescriptor(); }
/** * Checks if the specified table exists. Looks at the META table hosted on the specified server. * * @param catalogTracker * @param tableName table to check * @return true if the table exists in meta, false if not * @throws IOException */ public static boolean tableExists(CatalogTracker catalogTracker, String tableName) throws IOException { if (tableName.equals(HTableDescriptor.ROOT_TABLEDESC.getNameAsString()) || tableName.equals(HTableDescriptor.META_TABLEDESC.getNameAsString())) { // Catalog tables always exist. return true; } final byte[] tableNameBytes = Bytes.toBytes(tableName); // Make a version of ResultCollectingVisitor that only collects the first CollectingVisitor<HRegionInfo> visitor = new CollectingVisitor<HRegionInfo>() { private HRegionInfo current = null; @Override public boolean visit(Result r) throws IOException { this.current = parseHRegionInfoFromCatalogResult(r, HConstants.REGIONINFO_QUALIFIER); if (this.current == null) { LOG.warn("No serialized HRegionInfo in " + r); return true; } if (!isInsideTable(this.current, tableNameBytes)) return false; // Else call super and add this Result to the collection. super.visit(r); // Stop collecting regions from table after we get one. return false; } @Override void add(Result r) { // Add the current HRI. this.results.add(this.current); } }; fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableNameBytes)); // If visitor has results >= 1 then table exists. return visitor.getResults().size() >= 1; }
@Test public void testCreateBadTables() throws IOException { String msg = null; try { this.admin.createTable(HTableDescriptor.ROOT_TABLEDESC); } catch (IllegalArgumentException e) { msg = e.toString(); } assertTrue( "Unexcepted exception message " + msg, msg != null && msg.startsWith(IllegalArgumentException.class.getName()) && msg.contains(HTableDescriptor.ROOT_TABLEDESC.getNameAsString())); msg = null; try { this.admin.createTable(HTableDescriptor.META_TABLEDESC); } catch (IllegalArgumentException e) { msg = e.toString(); } assertTrue( "Unexcepted exception message " + msg, msg != null && msg.startsWith(IllegalArgumentException.class.getName()) && msg.contains(HTableDescriptor.META_TABLEDESC.getNameAsString())); // Now try and do concurrent creation with a bunch of threads. final HTableDescriptor threadDesc = new HTableDescriptor("threaded_testCreateBadTables"); threadDesc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); int count = 10; Thread[] threads = new Thread[count]; final AtomicInteger successes = new AtomicInteger(0); final AtomicInteger failures = new AtomicInteger(0); final HBaseAdmin localAdmin = this.admin; for (int i = 0; i < count; i++) { threads[i] = new Thread(Integer.toString(i)) { @Override public void run() { try { localAdmin.createTable(threadDesc); successes.incrementAndGet(); } catch (TableExistsException e) { failures.incrementAndGet(); } catch (IOException e) { throw new RuntimeException("Failed threaded create" + getName(), e); } } }; } for (int i = 0; i < count; i++) { threads[i].start(); } for (int i = 0; i < count; i++) { while (threads[i].isAlive()) { try { Thread.sleep(1000); } catch (InterruptedException e) { // continue } } } // All threads are now dead. Count up how many tables were created and // how many failed w/ appropriate exception. assertEquals(1, successes.get()); assertEquals(count - 1, failures.get()); }