diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java index d682ccc..6821f0a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HFileArchiver.java @@ -162,6 +162,21 @@ public boolean accept(Path file) { public static void archiveFamily(FileSystem fs, Configuration conf, HRegionInfo parent, Path tableDir, byte[] family) throws IOException { Path familyDir = new Path(tableDir, new Path(parent.getEncodedName(), Bytes.toString(family))); + archiveFamilyByFamilyDir(fs, conf, parent, familyDir, family); + } + + /** + * Removes from the specified region the store files of the specified column family, + * either by archiving them or outright deletion + * @param fs the filesystem where the store files live + * @param conf {@link Configuration} to examine to determine the archive directory + * @param parent Parent region hosting the store files + * @param familyDir {@link Path} to where the family is being stored + * @param family the family hosting the store files + * @throws IOException if the files could not be correctly disposed. + */ + public static void archiveFamilyByFamilyDir(FileSystem fs, Configuration conf, + HRegionInfo parent, Path familyDir, byte[] family) throws IOException { FileStatus[] storeFiles = FSUtils.listStatus(fs, familyDir); if (storeFiles == null) { LOG.debug("No store files to dispose for region=" + parent.getRegionNameAsString() + @@ -171,7 +186,7 @@ public static void archiveFamily(FileSystem fs, Configuration conf, FileStatusConverter getAsFile = new FileStatusConverter(fs); Collection toArchive = Lists.transform(Arrays.asList(storeFiles), getAsFile); - Path storeArchiveDir = HFileArchiveUtil.getStoreArchivePath(conf, parent, tableDir, family); + Path storeArchiveDir = HFileArchiveUtil.getStoreArchivePath(conf, parent, family); // do the actual archive if (!resolveAndArchive(fs, storeArchiveDir, toArchive)) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/DisabledTableSnapshotHandler.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/DisabledTableSnapshotHandler.java index 07f981b..6c05a16 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/DisabledTableSnapshotHandler.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/DisabledTableSnapshotHandler.java @@ -28,6 +28,7 @@ import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; +import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.client.RegionReplicaUtil; @@ -83,12 +84,21 @@ public void snapshotRegions(List> regionsAndLocati if (RegionReplicaUtil.isDefaultReplica(hri)) { regions.add(hri); } - // if it's the first region, add the mob region - if (Bytes.equals(hri.getStartKey(), HConstants.EMPTY_START_ROW)) { - HRegionInfo mobRegion = MobUtils.getMobRegionInfo(hri.getTable()); - regions.add(mobRegion); + } + // handle the mob files if any. + HColumnDescriptor[] hcds = htd.getColumnFamilies(); + boolean mobEnabled = false; + for (HColumnDescriptor hcd : hcds) { + if (hcd.isMobEnabled()) { + mobEnabled = true; + break; } } + if (mobEnabled) { + // snapshot the mob files as a offline region. + HRegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(htd.getTableName()); + regions.add(mobRegionInfo); + } // 2. for each region, write all the info to disk String msg = "Starting to write region info and WALs for regions for offline snapshot:" diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/EnabledTableSnapshotHandler.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/EnabledTableSnapshotHandler.java index 934bb2a..ee839c9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/EnabledTableSnapshotHandler.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/EnabledTableSnapshotHandler.java @@ -25,10 +25,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.errorhandling.ForeignException; import org.apache.hadoop.hbase.master.MasterServices; +import org.apache.hadoop.hbase.mob.MobUtils; import org.apache.hadoop.hbase.procedure.Procedure; import org.apache.hadoop.hbase.procedure.ProcedureCoordinator; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.SnapshotDescription; @@ -103,6 +105,21 @@ protected void snapshotRegions(List> regions) snapshotDisabledRegion(regionInfo); } } + // handle the mob files if any. + HColumnDescriptor[] hcds = htd.getColumnFamilies(); + boolean mobEnabled = false; + for (HColumnDescriptor hcd : hcds) { + if (hcd.isMobEnabled()) { + mobEnabled = true; + break; + } + } + if (mobEnabled) { + LOG.info("Taking snapshot for mob files in table " + htd.getTableName()); + // snapshot the mob files as a offline region. + HRegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(htd.getTableName()); + snapshotMobRegion(mobRegionInfo); + } } catch (InterruptedException e) { ForeignException ee = new ForeignException("Interrupted while waiting for snapshot to finish", e); @@ -112,4 +129,14 @@ protected void snapshotRegions(List> regions) monitor.receive(e); } } + + /** + * Takes a snapshot of the mob region + */ + private void snapshotMobRegion(final HRegionInfo regionInfo) + throws IOException { + snapshotManifest.addMobRegion(regionInfo); + monitor.rethrowException(); + status.setStatus("Completed referencing HFiles for the mob region of table: " + snapshotTable); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 71cc247..ceda31e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -127,7 +127,6 @@ import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils; import org.apache.hadoop.hbase.ipc.RpcCallContext; import org.apache.hadoop.hbase.ipc.RpcServer; -import org.apache.hadoop.hbase.mob.MobUtils; import org.apache.hadoop.hbase.monitoring.MonitoredTask; import org.apache.hadoop.hbase.monitoring.TaskMonitor; import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl.WriteEntry; @@ -3698,24 +3697,6 @@ public void addRegionToSnapshot(SnapshotDescription desc, SnapshotManifest manifest = SnapshotManifest.create(conf, getFilesystem(), snapshotDir, desc, exnSnare); manifest.addRegion(this); - - // The regionserver holding the first region of the table is responsible for taking the - // manifest of the mob dir. - if (!Bytes.equals(getRegionInfo().getStartKey(), HConstants.EMPTY_START_ROW)) - return; - - // if any cf's have is mob enabled, add the "mob region" to the manifest. - List stores = getStores(); - for (Store store : stores) { - boolean hasMobStore = store.getFamily().isMobEnabled(); - if (hasMobStore) { - // use the .mob as the start key and 0 as the regionid - HRegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(this.getTableDesc().getTableName()); - mobRegionInfo.setOffline(true); - manifest.addMobRegion(mobRegionInfo, this.getTableDesc().getColumnFamilies()); - return; - } - } } private void updateSequenceId(final Iterable> cellItr, final long sequenceId) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java index 34e8aea..d1f5372 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java @@ -519,7 +519,7 @@ private void restoreRegion(final HRegionInfo regionInfo, // Family doesn't exists in the snapshot LOG.trace("Removing family=" + Bytes.toString(family) + " from region=" + regionInfo.getEncodedName() + " table=" + tableName); - HFileArchiver.archiveFamily(fs, conf, regionInfo, tableDir, family); + HFileArchiver.archiveFamilyByFamilyDir(fs, conf, regionInfo, familyDir, family); fs.delete(familyDir, true); } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotManifest.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotManifest.java index f410a7f..7dd6f49 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotManifest.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotManifest.java @@ -162,7 +162,7 @@ private RegionVisitor createRegionVisitor(final SnapshotDescription desc) throws } } - public void addMobRegion(HRegionInfo regionInfo, HColumnDescriptor[] hcds) throws IOException { + public void addMobRegion(HRegionInfo regionInfo) throws IOException { // 0. Get the ManifestBuilder/RegionVisitor RegionVisitor visitor = createRegionVisitor(desc); @@ -175,7 +175,7 @@ public void addMobRegion(HRegionInfo regionInfo, HColumnDescriptor[] hcds) throw LOG.debug("Creating references for mob files"); Path mobRegionPath = MobUtils.getMobRegionPath(conf, regionInfo.getTable()); - for (HColumnDescriptor hcd : hcds) { + for (HColumnDescriptor hcd : htd.getColumnFamilies()) { // 2.1. build the snapshot reference for the store if it's a mob store if (!hcd.isMobEnabled()) { continue; @@ -249,9 +249,13 @@ public void addRegion(final Path tableDir, final HRegionInfo regionInfo) throws boolean isMobRegion = MobUtils.isMobRegionInfo(regionInfo); try { + Path baseDir = tableDir; // Open the RegionFS + if (isMobRegion) { + baseDir = FSUtils.getTableDir(MobUtils.getMobHome(conf), regionInfo.getTable()); + } HRegionFileSystem regionFs = HRegionFileSystem.openRegionFromFileSystem(conf, fs, - tableDir, regionInfo, true); + baseDir, regionInfo, true); monitor.rethrowException(); // 1. dump region meta info into the snapshot directory @@ -273,15 +277,7 @@ public void addRegion(final Path tableDir, final HRegionInfo regionInfo) throws Object familyData = visitor.familyOpen(regionData, Bytes.toBytes(familyName)); monitor.rethrowException(); - Collection storeFiles = null; - if (isMobRegion) { - Path regionPath = MobUtils.getMobRegionPath(conf, regionInfo.getTable()); - Path storePath = MobUtils.getMobFamilyPath(regionPath, familyName); - storeFiles = getStoreFiles(storePath); - } else { - storeFiles = regionFs.getStoreFiles(familyName); - } - + Collection storeFiles = regionFs.getStoreFiles(familyName); if (storeFiles == null) { if (LOG.isDebugEnabled()) { LOG.debug("No files under family: " + familyName); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HFileArchiveUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HFileArchiveUtil.java index a235696..faae4ef 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HFileArchiveUtil.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HFileArchiveUtil.java @@ -64,6 +64,20 @@ public static Path getStoreArchivePath(Configuration conf, HRegionInfo region, Path tabledir, byte[] family) throws IOException { + return getStoreArchivePath(conf, region, family); + } + + /** + * Gets the directory to archive a store directory. + * @param conf {@link Configuration} to read for the archive directory name. + * @param region parent region information under which the store currently lives + * @param family name of the family in the store + * @return {@link Path} to the directory to archive the given store or null if it should + * not be archived + */ + public static Path getStoreArchivePath(Configuration conf, + HRegionInfo region, + byte[] family) throws IOException { Path rootDir = FSUtils.getRootDir(conf); Path tableArchiveDir = getTableArchivePath(rootDir, region.getTable()); return HStore.getStoreHomedir(tableArchiveDir, region, family);