/** * Check individual daughter is up in .META.; fixup if its not. * @param result The contents of the parent row in .META. * @param qualifier Which daughter to check for. * @return 1 if the daughter is missing and fixed. Otherwise 0 * @throws IOException */ static int fixupDaughter(final Result result, final byte [] qualifier, final AssignmentManager assignmentManager, final CatalogTracker catalogTracker) throws IOException { HRegionInfo daughter = MetaReader.parseHRegionInfoFromCatalogResult(result, qualifier); if (daughter == null) return 0; if (isDaughterMissing(catalogTracker, daughter)) { LOG.info("Fixup; missing daughter " + daughter.getRegionNameAsString()); MetaEditor.addDaughter(catalogTracker, daughter, null); // TODO: Log WARN if the regiondir does not exist in the fs. If its not // there then something wonky about the split -- things will keep going // but could be missing references to parent region. // And assign it. assignmentManager.assign(daughter, true); return 1; } else { LOG.debug("Daughter " + daughter.getRegionNameAsString() + " present"); } return 0; }
@Override public void assign(final byte [] regionName)throws IOException { checkInitialized(); Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); if (cpHost != null) { if (cpHost.preAssign(pair.getFirst())) { return; } } assignRegion(pair.getFirst()); if (cpHost != null) { cpHost.postAssign(pair.getFirst()); } }
@Override public void unassign(final byte [] regionName, final boolean force) throws IOException { checkInitialized(); Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); HRegionInfo hri = pair.getFirst(); if (cpHost != null) { if (cpHost.preUnassign(hri, force)) { return; } } if (force) { this.assignmentManager.regionOffline(hri); assignRegion(hri); } else { this.assignmentManager.unassign(hri, force); } if (cpHost != null) { cpHost.postUnassign(hri, force); } }
public static void blockUntilRegionIsInMeta(HTable metaTable, long timeout, HRegionInfo hri) throws IOException, InterruptedException { log("blocking until region is in META: " + hri.getRegionNameAsString()); long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < timeout) { Result result = getRegionRow(metaTable, hri.getRegionName()); if (result != null) { HRegionInfo info = MetaReader.parseCatalogResult(result).getFirst(); if (info != null && !info.isOffline()) { log("found region in META: " + hri.getRegionNameAsString()); break; } } Threads.sleep(10); } }
/********************************* Master related hooks **********************************/ @Override public void postStartMaster(ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { // Need to create the new system table for labels here MasterServices master = ctx.getEnvironment().getMasterServices(); if (!MetaReader.tableExists(master.getCatalogTracker(), LABELS_TABLE_NAME)) { HTableDescriptor labelsTable = new HTableDescriptor(LABELS_TABLE_NAME); HColumnDescriptor labelsColumn = new HColumnDescriptor(LABELS_TABLE_FAMILY); labelsColumn.setBloomFilterType(BloomType.NONE); labelsColumn.setBlockCacheEnabled(false); // We will cache all the labels. No need of normal // table block cache. labelsTable.addFamily(labelsColumn); // Let the "labels" table having only one region always. We are not expecting too many labels in // the system. labelsTable.setValue(HTableDescriptor.SPLIT_POLICY, DisabledRegionSplitPolicy.class.getName()); labelsTable.setValue(Bytes.toBytes(HConstants.DISALLOW_WRITES_IN_RECOVERING), Bytes.toBytes(true)); master.createTable(labelsTable, null); } }
/** * Use this before submitting a TableReduce job. It will * appropriately set up the JobConf. * * @param table The output table. * @param reducer The reducer class to use. * @param job The current job configuration to adjust. * @param partitioner Partitioner to use. Pass <code>null</code> to use * default partitioner. * @param addDependencyJars upload HBase jars and jars for any of the configured * job classes via the distributed cache (tmpjars). * @throws IOException When determining the region count fails. */ public static void initTableReduceJob(String table, Class<? extends TableReduce> reducer, JobConf job, Class partitioner, boolean addDependencyJars) throws IOException { job.setOutputFormat(TableOutputFormat.class); job.setReducerClass(reducer); job.set(TableOutputFormat.OUTPUT_TABLE, table); job.setOutputKeyClass(ImmutableBytesWritable.class); job.setOutputValueClass(Put.class); job.setStrings("io.serializations", job.get("io.serializations"), MutationSerialization.class.getName(), ResultSerialization.class.getName()); if (partitioner == HRegionPartitioner.class) { job.setPartitionerClass(HRegionPartitioner.class); int regions = MetaReader.getRegionCount(HBaseConfiguration.create(job), table); if (job.getNumReduceTasks() > regions) { job.setNumReduceTasks(regions); } } else if (partitioner != null) { job.setPartitionerClass(partitioner); } if (addDependencyJars) { addDependencyJars(job); } initCredentials(job); }
/** * Get the HRegionInfo from cache, if not there, from the hbase:meta table * @param regionName * @return HRegionInfo for the region */ protected HRegionInfo getRegionInfo(final byte [] regionName) { String encodedName = HRegionInfo.encodeRegionName(regionName); RegionState regionState = regionStates.get(encodedName); if (regionState != null) { return regionState.getRegion(); } try { Pair<HRegionInfo, ServerName> p = MetaReader.getRegion(server.getCatalogTracker(), regionName); HRegionInfo hri = p == null ? null : p.getFirst(); if (hri != null) { createRegionState(hri); } return hri; } catch (IOException e) { server.abort("Aborting because error occoured while reading " + Bytes.toStringBinary(regionName) + " from hbase:meta", e); return null; } }
/** * Checks if the specified region has merge qualifiers, if so, try to clean * them * @param region * @return true if the specified region doesn't have merge qualifier now * @throws IOException */ public boolean cleanMergeQualifier(final HRegionInfo region) throws IOException { // Get merge regions if it is a merged region and already has merge // qualifier Pair<HRegionInfo, HRegionInfo> mergeRegions = MetaReader .getRegionsFromMergeQualifier(this.services.getCatalogTracker(), region.getRegionName()); if (mergeRegions == null || (mergeRegions.getFirst() == null && mergeRegions.getSecond() == null)) { // It doesn't have merge qualifier, no need to clean return true; } // It shouldn't happen, we must insert/delete these two qualifiers together if (mergeRegions.getFirst() == null || mergeRegions.getSecond() == null) { LOG.error("Merged region " + region.getRegionNameAsString() + " has only one merge qualifier in META."); return false; } return cleanMergeRegion(region, mergeRegions.getFirst(), mergeRegions.getSecond()); }
/** * Used by the client to identify if all regions have the schema updates * * @param tableName * @return Pair indicating the status of the alter command * @throws IOException */ public Pair<Integer, Integer> getReopenStatus(TableName tableName) throws IOException { List <HRegionInfo> hris = MetaReader.getTableRegions(this.server.getCatalogTracker(), tableName, true); Integer pending = 0; for (HRegionInfo hri : hris) { String name = hri.getEncodedName(); // no lock concurrent access ok: sequential consistency respected. if (regionsToReopen.containsKey(name) || regionStates.isRegionInTransition(name)) { pending++; } } return new Pair<Integer, Integer>(pending, hris.size()); }
private void waitAndVerifyRegionNum(HMaster master, TableName tablename, int expectedRegionNum) throws Exception { List<Pair<HRegionInfo, ServerName>> tableRegionsInMeta; List<HRegionInfo> tableRegionsInMaster; long timeout = System.currentTimeMillis() + waitTime; while (System.currentTimeMillis() < timeout) { tableRegionsInMeta = MetaReader.getTableRegionsAndLocations( master.getCatalogTracker(), tablename); tableRegionsInMaster = master.getAssignmentManager().getRegionStates() .getRegionsOfTable(tablename); if (tableRegionsInMeta.size() == expectedRegionNum && tableRegionsInMaster.size() == expectedRegionNum) { break; } Thread.sleep(250); } tableRegionsInMeta = MetaReader.getTableRegionsAndLocations( master.getCatalogTracker(), tablename); LOG.info("Regions after merge:" + Joiner.on(',').join(tableRegionsInMeta)); assertEquals(expectedRegionNum, tableRegionsInMeta.size()); }
private void disableAndDeleteTable(MasterServices master, TableName tableName) throws IOException { LOG.error(tableName + " already exists. Disabling and deleting table " + tableName + '.'); boolean disabled = master.getAssignmentManager().getZKTable().isDisabledTable(tableName); if (false == disabled) { LOG.info("Disabling table " + tableName + '.'); new DisableTableHandler(master, tableName, master.getCatalogTracker(), master.getAssignmentManager(), master.getTableLockManager(), false).prepare().process(); if (false == master.getAssignmentManager().getZKTable().isDisabledTable(tableName)) { throw new DoNotRetryIOException("Table " + tableName + " not disabled."); } } LOG.info("Disabled table " + tableName + '.'); LOG.info("Deleting table " + tableName + '.'); new DeleteTableHandler(tableName, master, master).prepare().process(); if (true == MetaReader.tableExists(master.getCatalogTracker(), tableName)) { throw new DoNotRetryIOException("Table " + tableName + " not deleted."); } LOG.info("Deleted table " + tableName + '.'); }
public static List<Pair<byte[], ServerName>> getStartKeysAndLocations(HMaster master, String tableName) throws IOException, InterruptedException { List<Pair<HRegionInfo, ServerName>> tableRegionsAndLocations = MetaReader.getTableRegionsAndLocations(master.getCatalogTracker(), TableName.valueOf(tableName)); List<Pair<byte[], ServerName>> startKeyAndLocationPairs = new ArrayList<Pair<byte[], ServerName>>(tableRegionsAndLocations.size()); Pair<byte[], ServerName> startKeyAndLocation = null; for (Pair<HRegionInfo, ServerName> regionAndLocation : tableRegionsAndLocations) { startKeyAndLocation = new Pair<byte[], ServerName>(regionAndLocation.getFirst().getStartKey(), regionAndLocation.getSecond()); startKeyAndLocationPairs.add(startKeyAndLocation); } return startKeyAndLocationPairs; }
private List<Pair<byte[], ServerName>> getStartKeysAndLocations(HMaster master, String tableName) throws IOException, InterruptedException { List<Pair<HRegionInfo, ServerName>> tableRegionsAndLocations = MetaReader.getTableRegionsAndLocations(master.getCatalogTracker(), TableName.valueOf(tableName)); List<Pair<byte[], ServerName>> startKeyAndLocationPairs = new ArrayList<Pair<byte[], ServerName>>(tableRegionsAndLocations.size()); Pair<byte[], ServerName> startKeyAndLocation = null; for (Pair<HRegionInfo, ServerName> regionAndLocation : tableRegionsAndLocations) { startKeyAndLocation = new Pair<byte[], ServerName>(regionAndLocation.getFirst().getStartKey(), regionAndLocation.getSecond()); startKeyAndLocationPairs.add(startKeyAndLocation); } return startKeyAndLocationPairs; }
@Test(timeout = 180000) public void testIndexTableCreationAlongWithNormalTablesAfterMasterRestart() throws Exception { TableName tableName = TableName.valueOf("testIndexTableCreationAlongWithNormalTablesAfterMasterRestart"); HTableDescriptor htd = new HTableDescriptor(tableName); admin.createTable(htd); MiniHBaseCluster cluster = UTIL.getHBaseCluster(); cluster.abortMaster(0); cluster.waitOnMaster(0); HMaster master = cluster.startMaster().getMaster(); cluster.waitForActiveAndReadyMaster(); boolean tableExist = MetaReader.tableExists(master.getCatalogTracker(), TableName.valueOf(IndexUtils.getIndexTableName(tableName))); assertFalse("Index table should be not created after master start up.", tableExist); }
@Override public void unassign(final byte [] regionName, final boolean force) throws IOException { Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(this.catalogTracker, regionName); if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName)); HRegionInfo hri = pair.getFirst(); if (cpHost != null) { if (cpHost.preUnassign(hri, force)) { return; } } if (force) { this.assignmentManager.clearRegionFromTransition(hri); assignRegion(hri); } else { this.assignmentManager.unassign(hri, force); } if (cpHost != null) { cpHost.postUnassign(hri, force); } }
/** * @param tableName Table to check. * @return True if table exists already. * @throws IOException */ public boolean tableExists(final String tableName) throws IOException { boolean b = false; CatalogTracker ct = getCatalogTracker(); try { b = MetaReader.tableExists(ct, tableName); } finally { cleanupCatalogTracker(ct); } return b; }
/** * Flush a table or an individual region. Synchronous operation. * @param tableNameOrRegionName table or region to flush * @throws IOException if a remote or network exception occurs * @throws InterruptedException */ public void flush(final byte[] tableNameOrRegionName) throws IOException, InterruptedException { CatalogTracker ct = getCatalogTracker(); try { Pair<HRegionInfo, ServerName> regionServerPair = getRegion(tableNameOrRegionName, ct); if (regionServerPair != null) { if (regionServerPair.getSecond() == null) { throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName)); } else { flush(regionServerPair.getSecond(), regionServerPair.getFirst()); } } else { final String tableName = tableNameString(tableNameOrRegionName, ct); List<Pair<HRegionInfo, ServerName>> pairs = MetaReader.getTableRegionsAndLocations(ct, tableName); for (Pair<HRegionInfo, ServerName> pair : pairs) { if (pair.getFirst().isOffline()) continue; if (pair.getSecond() == null) continue; try { flush(pair.getSecond(), pair.getFirst()); } catch (NotServingRegionException e) { if (LOG.isDebugEnabled()) { LOG.debug("Trying to flush " + pair.getFirst() + ": " + StringUtils.stringifyException(e)); } } } } } finally { cleanupCatalogTracker(ct); } }
/** * Compact a table or an individual region. Asynchronous operation. * @param tableNameOrRegionName table or region to compact * @param columnFamily column family within a table or region * @param major True if we are to do a major compaction. * @throws IOException if a remote or network exception occurs * @throws InterruptedException */ private void compact(final byte[] tableNameOrRegionName, final byte[] columnFamily, final boolean major) throws IOException, InterruptedException { CatalogTracker ct = getCatalogTracker(); try { Pair<HRegionInfo, ServerName> regionServerPair = getRegion(tableNameOrRegionName, ct); if (regionServerPair != null) { if (regionServerPair.getSecond() == null) { throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName)); } else { compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily); } } else { final String tableName = tableNameString(tableNameOrRegionName, ct); List<Pair<HRegionInfo, ServerName>> pairs = MetaReader.getTableRegionsAndLocations(ct, tableName); for (Pair<HRegionInfo, ServerName> pair : pairs) { if (pair.getFirst().isOffline()) continue; if (pair.getSecond() == null) continue; try { compact(pair.getSecond(), pair.getFirst(), major, columnFamily); } catch (NotServingRegionException e) { if (LOG.isDebugEnabled()) { LOG.debug("Trying to" + (major ? " major" : "") + " compact " + pair.getFirst() + ": " + StringUtils.stringifyException(e)); } } } } } finally { cleanupCatalogTracker(ct); } }
/** * Split a table or an individual region. Asynchronous operation. * @param tableNameOrRegionName table to region to split * @param splitPoint the explicit position to split on * @throws IOException if a remote or network exception occurs * @throws InterruptedException interrupt exception occurred */ public void split(final byte[] tableNameOrRegionName, final byte[] splitPoint) throws IOException, InterruptedException { CatalogTracker ct = getCatalogTracker(); try { Pair<HRegionInfo, ServerName> regionServerPair = getRegion(tableNameOrRegionName, ct); if (regionServerPair != null) { if (regionServerPair.getSecond() == null) { throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName)); } else { split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint); } } else { final String tableName = tableNameString(tableNameOrRegionName, ct); List<Pair<HRegionInfo, ServerName>> pairs = MetaReader.getTableRegionsAndLocations(ct, tableName); for (Pair<HRegionInfo, ServerName> pair : pairs) { // May not be a server for a particular row if (pair.getSecond() == null) continue; HRegionInfo r = pair.getFirst(); // check for parents if (r.isSplitParent()) continue; // if a split point given, only split that particular region if (splitPoint != null && !r.containsRow(splitPoint)) continue; // call out to region server to do split now split(pair.getSecond(), pair.getFirst(), splitPoint); } } } finally { cleanupCatalogTracker(ct); } }
/** * @param tableNameOrRegionName Name of a table or name of a region. * @param ct A {@link CatalogTracker} instance (caller of this method usually has one). * @return a pair of HRegionInfo and ServerName if <code>tableNameOrRegionName</code> is a * verified region name (we call {@link MetaReader#getRegion(CatalogTracker, byte[])} else * null. Throw an exception if <code>tableNameOrRegionName</code> is null. * @throws IOException */ Pair<HRegionInfo, ServerName> getRegion(final byte[] tableNameOrRegionName, final CatalogTracker ct) throws IOException { if (tableNameOrRegionName == null) { throw new IllegalArgumentException("Pass a table name or region name"); } Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, tableNameOrRegionName); if (pair == null) { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>( null); final String encodedName = Bytes.toString(tableNameOrRegionName); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } HRegionInfo info = MetaReader.parseHRegionInfoFromCatalogResult(data, HConstants.REGIONINFO_QUALIFIER); if (info == null) { LOG.warn("No serialized HRegionInfo in " + data); return true; } if (!encodedName.equals(info.getEncodedName())) return true; ServerName sn = MetaReader.getServerNameFromCatalogResult(data); result.set(new Pair<HRegionInfo, ServerName>(info, sn)); return false; // found the region, stop } }; MetaScanner.metaScan(conf, connection, visitor, null); pair = result.get(); } return pair; }
/** * get the regions of a given table. * @param tableName the name of the table * @return Ordered list of {@link HRegionInfo}. * @throws IOException */ public List<HRegionInfo> getTableRegions(final byte[] tableName) throws IOException { CatalogTracker ct = getCatalogTracker(); List<HRegionInfo> Regions = null; try { Regions = MetaReader.getTableRegions(ct, tableName, true); } finally { cleanupCatalogTracker(ct); } return Regions; }
/** * Process a dead region from a dead RS. Checks if the region is disabled or * disabling or if the region has a partially completed split. * @param hri * @param result * @param assignmentManager * @param catalogTracker * @return Returns true if specified region should be assigned, false if not. * @throws IOException */ public static boolean processDeadRegion(HRegionInfo hri, Result result, AssignmentManager assignmentManager, CatalogTracker catalogTracker) throws IOException { boolean tablePresent = assignmentManager.getZKTable().isTablePresent( hri.getTableNameAsString()); if (!tablePresent) { LOG.info("The table " + hri.getTableNameAsString() + " was deleted. Hence not proceeding."); return false; } // If table is not disabled but the region is offlined, boolean disabled = assignmentManager.getZKTable().isDisabledTable( hri.getTableNameAsString()); if (disabled){ LOG.info("The table " + hri.getTableNameAsString() + " was disabled. Hence not proceeding."); return false; } if (hri.isOffline() && hri.isSplit()) { LOG.debug("Offlined and split region " + hri.getRegionNameAsString() + "; checking daughter presence"); if (MetaReader.getRegion(catalogTracker, hri.getRegionName()) == null) { return false; } fixupDaughters(result, assignmentManager, catalogTracker); return false; } boolean disabling = assignmentManager.getZKTable().isDisablingTable( hri.getTableNameAsString()); if (disabling) { LOG.info("The table " + hri.getTableNameAsString() + " is disabled. Hence not assigning region" + hri.getEncodedName()); return false; } return true; }
/** * Look for presence of the daughter OR of a split of the daughter in .META. * Daughter could have been split over on regionserver before a run of the * catalogJanitor had chance to clear reference from parent. * @param daughter Daughter region to search for. * @throws IOException */ private static boolean isDaughterMissing(final CatalogTracker catalogTracker, final HRegionInfo daughter) throws IOException { FindDaughterVisitor visitor = new FindDaughterVisitor(daughter); // Start the scan at what should be the daughter's row in the .META. // We will either 1., find the daughter or some derivative split of the // daughter (will have same table name and start row at least but will sort // after because has larger regionid -- the regionid is timestamp of region // creation), OR, we will not find anything with same table name and start // row. If the latter, then assume daughter missing and do fixup. byte [] startrow = daughter.getRegionName(); MetaReader.fullScan(catalogTracker, visitor, startrow); return !visitor.foundDaughter(); }
@Override public boolean visit(Result r) throws IOException { HRegionInfo hri = MetaReader.parseHRegionInfoFromCatalogResult(r, HConstants.REGIONINFO_QUALIFIER); if (hri == null) { LOG.warn("No serialized HRegionInfo in " + r); return true; } byte [] value = r.getValue(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER); // See if daughter is assigned to some server if (value == null) return false; // Now see if we have gone beyond the daughter's startrow. if (!Bytes.equals(daughter.getTableName(), hri.getTableName())) { // We fell into another table. Stop scanning. return false; } // If our start rows do not compare, move on. if (!Bytes.equals(daughter.getStartKey(), hri.getStartKey())) { return false; } // Else, table name and start rows compare. It means that the daughter // or some derivative split of the daughter is up in .META. Daughter // exists. this.found = true; return false; }
public DisableTableHandler(Server server, byte [] tableName, CatalogTracker catalogTracker, AssignmentManager assignmentManager, boolean skipTableStateCheck) throws TableNotFoundException, TableNotEnabledException, IOException { super(server, EventType.C_M_DISABLE_TABLE); this.tableName = tableName; this.tableNameStr = Bytes.toString(this.tableName); this.assignmentManager = assignmentManager; // Check if table exists // TODO: do we want to keep this in-memory as well? i guess this is // part of old master rewrite, schema to zk to check for table // existence and such if (!MetaReader.tableExists(catalogTracker, this.tableNameStr)) { throw new TableNotFoundException(this.tableNameStr); } // There could be multiple client requests trying to disable or enable // the table at the same time. Ensure only the first request is honored // After that, no other requests can be accepted until the table reaches // DISABLED or ENABLED. if (!skipTableStateCheck) { try { if (!this.assignmentManager.getZKTable().checkEnabledAndSetDisablingTable (this.tableNameStr)) { LOG.info("Table " + tableNameStr + " isn't enabled; skipping disable"); throw new TableNotEnabledException(this.tableNameStr); } } catch (KeeperException e) { throw new IOException("Unable to ensure that the table will be" + " disabling because of a ZooKeeper issue", e); } } }
private void handleEnableTable() throws IOException, KeeperException, InterruptedException { // I could check table is disabling and if so, not enable but require // that user first finish disabling but that might be obnoxious. // Set table enabling flag up in zk. this.assignmentManager.getZKTable().setEnablingTable(this.tableNameStr); boolean done = false; // Get the regions of this table. We're done when all listed // tables are onlined. List<Pair<HRegionInfo, ServerName>> tableRegionsAndLocations = MetaReader .getTableRegionsAndLocations(this.ct, tableName, true); int countOfRegionsInTable = tableRegionsAndLocations.size(); List<HRegionInfo> regions = regionsToAssignWithServerName(tableRegionsAndLocations); int regionsCount = regions.size(); if (regionsCount == 0) { done = true; } LOG.info("Table has " + countOfRegionsInTable + " regions of which " + regionsCount + " are offline."); BulkEnabler bd = new BulkEnabler(this.server, regions, countOfRegionsInTable, true); try { if (bd.bulkAssign()) { done = true; } } catch (InterruptedException e) { LOG.warn("Enable was interrupted"); // Preserve the interrupt. Thread.currentThread().interrupt(); } // Flip the table to enabled. if (done) this.assignmentManager.getZKTable().setEnabledTable( this.tableNameStr); LOG.info("Enabled table is done=" + done); }
void fixupDaughters(final MonitoredTask status) throws IOException, KeeperException { final Map<HRegionInfo, Result> offlineSplitParents = new HashMap<HRegionInfo, Result>(); // This visitor collects offline split parents in the .META. table MetaReader.Visitor visitor = new MetaReader.Visitor() { @Override public boolean visit(Result r) throws IOException { if (r == null || r.isEmpty()) return true; HRegionInfo info = MetaReader.parseHRegionInfoFromCatalogResult( r, HConstants.REGIONINFO_QUALIFIER); if (info == null) return true; // Keep scanning if (info.isOffline() && info.isSplit()) { offlineSplitParents.put(info, r); } // Returning true means "keep scanning" return true; } }; // Run full scan of .META. catalog table passing in our custom visitor MetaReader.fullScan(this.catalogTracker, visitor); // Now work on our list of found parents. See if any we can clean up. int fixups = 0; for (Map.Entry<HRegionInfo, Result> e : offlineSplitParents.entrySet()) { String node = ZKAssign.getNodeName(zooKeeper, e.getKey().getEncodedName()); byte[] data = ZKUtil.getData(zooKeeper, node); if (data == null) { // otherwise, splitting is still going on, skip it fixups += ServerShutdownHandler.fixupDaughters( e.getValue(), assignmentManager, catalogTracker); } } if (fixups != 0) { LOG.info("Scanned the catalog and fixed up " + fixups + " missing daughter region(s)"); } }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ Pair<HRegionInfo, ServerName> getTableRegionForRow( final byte [] tableName, final byte [] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = MetaReader.parseCatalogResult(data); if (pair == null) { return false; } if (!Bytes.equals(pair.getFirst().getTableName(), tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(conf, visitor, tableName, rowKey, 1); return result.get(); }
@Override public void checkTableModifiable(final byte [] tableName) throws IOException { String tableNameStr = Bytes.toString(tableName); if (isCatalogTable(tableName)) { throw new IOException("Can't modify catalog tables"); } if (!MetaReader.tableExists(getCatalogTracker(), tableNameStr)) { throw new TableNotFoundException(tableNameStr); } if (!getAssignmentManager().getZKTable(). isDisabledTable(Bytes.toString(tableName))) { throw new TableNotDisabledException(tableName); } }