View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.snapshot;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.fs.FileStatus;
26  import org.apache.hadoop.fs.FileSystem;
27  import org.apache.hadoop.fs.Path;
28  import org.apache.hadoop.fs.PathFilter;
29  import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher;
30  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
31  import org.apache.hadoop.hbase.util.FSUtils;
32  
33  /**
34   * Reference all the hfiles in a region for a snapshot.
35   * <p>
36   * Doesn't take into acccount if the hfiles are valid or not, just keeps track of what's in the
37   * region's directory.
38   */
39  public class ReferenceRegionHFilesTask extends SnapshotTask {
40  
41    public static final Log LOG = LogFactory.getLog(ReferenceRegionHFilesTask.class);
42    private final Path regiondir;
43    private final FileSystem fs;
44    private final PathFilter fileFilter;
45    private final Path snapshotDir;
46  
47    /**
48     * Reference all the files in the given region directory
49     * @param snapshot snapshot for which to add references
50     * @param monitor to check/send error
51     * @param regionDir region directory to look for errors
52     * @param fs {@link FileSystem} where the snapshot/region live
53     * @param regionSnapshotDir directory in the snapshot to store region files
54     */
55    public ReferenceRegionHFilesTask(final SnapshotDescription snapshot,
56        ForeignExceptionDispatcher monitor, Path regionDir, final FileSystem fs, Path regionSnapshotDir) {
57      super(snapshot, monitor);
58      this.regiondir = regionDir;
59      this.fs = fs;
60  
61      this.fileFilter = new PathFilter() {
62        @Override
63        public boolean accept(Path path) {
64          try {
65            return fs.isFile(path);
66          } catch (IOException e) {
67            LOG.error("Failed to reach fs to check file:" + path + ", marking as not file");
68            ReferenceRegionHFilesTask.this.snapshotFailure("Failed to reach fs to check file status",
69              e);
70            return false;
71          }
72        }
73      };
74      this.snapshotDir = regionSnapshotDir;
75    }
76  
77    @Override
78    public Void call() throws IOException {
79      FileStatus[] families = FSUtils.listStatus(fs, regiondir, new FSUtils.FamilyDirFilter(fs));
80  
81      // if no families, then we are done again
82      if (families == null || families.length == 0) {
83        LOG.info("No families under region directory:" + regiondir
84            + ", not attempting to add references.");
85        return null;
86      }
87  
88      // snapshot directories to store the hfile reference
89      List<Path> snapshotFamilyDirs = TakeSnapshotUtils.getFamilySnapshotDirectories(snapshot,
90        snapshotDir, families);
91  
92      LOG.debug("Add hfile references to snapshot directories:" + snapshotFamilyDirs);
93      for (int i = 0; i < families.length; i++) {
94        FileStatus family = families[i];
95        Path familyDir = family.getPath();
96        // get all the hfiles in the family
97        FileStatus[] hfiles = FSUtils.listStatus(fs, familyDir, fileFilter);
98  
99        // if no hfiles, then we are done with this family
100       if (hfiles == null || hfiles.length == 0) {
101         LOG.debug("Not hfiles found for family: " + familyDir + ", skipping.");
102         continue;
103       }
104 
105       // make the snapshot's family directory
106       Path snapshotFamilyDir = snapshotFamilyDirs.get(i);
107       fs.mkdirs(snapshotFamilyDir);
108 
109       // create a reference for each hfile
110       for (FileStatus hfile : hfiles) {
111         // references are 0-length files, relying on file name.
112         Path referenceFile = new Path(snapshotFamilyDir, hfile.getPath().getName());
113         LOG.debug("Creating reference for:" + hfile.getPath() + " at " + referenceFile);
114         if (!fs.createNewFile(referenceFile)) {
115           throw new IOException("Failed to create reference file:" + referenceFile);
116         }
117       }
118     }
119     if (LOG.isDebugEnabled()) {
120       LOG.debug("Finished referencing hfiles, current region state:");
121       FSUtils.logFileSystemState(fs, regiondir, LOG);
122       LOG.debug("and the snapshot directory:");
123       FSUtils.logFileSystemState(fs, snapshotDir, LOG);
124     }
125     return null;
126   }
127 }