/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.snapshot;
import java.io.IOException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.PathFilter;
import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
import org.apache.hadoop.hbase.util.FSUtils;
/**
* Reference all the hfiles in a region for a snapshot.
* <p>
* Doesn't take into acccount if the hfiles are valid or not, just keeps track of what's in the
* region's directory.
*/
public class ReferenceRegionHFilesTask extends SnapshotTask {
public static final Log LOG = LogFactory.getLog(ReferenceRegionHFilesTask.class);
private final Path regiondir;
private final FileSystem fs;
private final PathFilter fileFilter;
private final Path snapshotDir;
/**
* Reference all the files in the given region directory
* @param snapshot snapshot for which to add references
* @param monitor to check/send error
* @param regionDir region directory to look for errors
* @param fs {@link FileSystem} where the snapshot/region live
* @param regionSnapshotDir directory in the snapshot to store region files
*/
public ReferenceRegionHFilesTask(final SnapshotDescription snapshot,
ForeignExceptionDispatcher monitor, Path regionDir, final FileSystem fs, Path regionSnapshotDir) {
super(snapshot, monitor);
this.regiondir = regionDir;
this.fs = fs;
this.fileFilter = new PathFilter() {
@Override
public boolean accept(Path path) {
try {
return fs.isFile(path);
} catch (IOException e) {
LOG.error("Failed to reach fs to check file:" + path + ", marking as not file");
ReferenceRegionHFilesTask.this.snapshotFailure("Failed to reach fs to check file status",
e);
return false;
}
}
};
this.snapshotDir = regionSnapshotDir;
}
@Override
public Void call() throws IOException {
FileStatus[] families = FSUtils.listStatus(fs, regiondir, new FSUtils.FamilyDirFilter(fs));
// if no families, then we are done again
if (families == null || families.length == 0) {
LOG.info("No families under region directory:" + regiondir
+ ", not attempting to add references.");
return null;
}
// snapshot directories to store the hfile reference
List<Path> snapshotFamilyDirs = TakeSnapshotUtils.getFamilySnapshotDirectories(snapshot,
snapshotDir, families);
LOG.debug("Add hfile references to snapshot directories:" + snapshotFamilyDirs);
for (int i = 0; i < families.length; i++) {
FileStatus family = families[i];
Path familyDir = family.getPath();
// get all the hfiles in the family
FileStatus[] hfiles = FSUtils.listStatus(fs, familyDir, fileFilter);
// if no hfiles, then we are done with this family
if (hfiles == null || hfiles.length == 0) {
LOG.debug("Not hfiles found for family: " + familyDir + ", skipping.");
continue;
}
// make the snapshot's family directory
Path snapshotFamilyDir = snapshotFamilyDirs.get(i);
fs.mkdirs(snapshotFamilyDir);
// create a reference for each hfile
for (FileStatus hfile : hfiles) {
// references are 0-length files, relying on file name.
Path referenceFile = new Path(snapshotFamilyDir, hfile.getPath().getName());
LOG.debug("Creating reference for:" + hfile.getPath() + " at " + referenceFile);
if (!fs.createNewFile(referenceFile)) {
throw new IOException("Failed to create reference file:" + referenceFile);
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Finished referencing hfiles, current region state:");
FSUtils.logFileSystemState(fs, regiondir, LOG);
LOG.debug("and the snapshot directory:");
FSUtils.logFileSystemState(fs, snapshotDir, LOG);
}
return null;
}
}