001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.util;
019
020import java.io.IOException;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.fs.Path;
023import org.apache.hadoop.hbase.HConstants;
024import org.apache.hadoop.hbase.TableName;
025import org.apache.hadoop.hbase.client.RegionInfo;
026import org.apache.hadoop.hbase.regionserver.HRegion;
027import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
028import org.apache.yetus.audience.InterfaceAudience;
029
030/**
031 * Helper class for all utilities related to archival/retrieval of HFiles
032 */
033@InterfaceAudience.Private
034public final class HFileArchiveUtil {
035  private HFileArchiveUtil() {
036    // non-external instantiation - util class
037  }
038
039  /**
040   * Get the directory to archive a store directory
041   * @param conf       {@link Configuration} to read for the archive directory name
042   * @param tableName  table name under which the store currently lives
043   * @param regionName region encoded name under which the store currently lives
044   * @param familyName name of the family in the store
045   * @return {@link Path} to the directory to archive the given store or <tt>null</tt> if it should
046   *         not be archived
047   */
048  public static Path getStoreArchivePath(final Configuration conf, final TableName tableName,
049    final String regionName, final String familyName) throws IOException {
050    Path tableArchiveDir = getTableArchivePath(conf, tableName);
051    return HRegionFileSystem.getStoreHomedir(tableArchiveDir, regionName,
052      Bytes.toBytes(familyName));
053  }
054
055  /**
056   * Get the directory to archive a store directory
057   * @param conf     {@link Configuration} to read for the archive directory name.
058   * @param region   parent region information under which the store currently lives
059   * @param tabledir directory for the table under which the store currently lives
060   * @param family   name of the family in the store
061   * @return {@link Path} to the directory to archive the given store or <tt>null</tt> if it should
062   *         not be archived
063   */
064  public static Path getStoreArchivePath(Configuration conf, RegionInfo region, Path tabledir,
065    byte[] family) throws IOException {
066    return getStoreArchivePath(conf, region, family);
067  }
068
069  /**
070   * Gets the directory to archive a store directory.
071   * @param conf   {@link Configuration} to read for the archive directory name.
072   * @param region parent region information under which the store currently lives
073   * @param family name of the family in the store
074   * @return {@link Path} to the directory to archive the given store or <tt>null</tt> if it should
075   *         not be archived
076   */
077  public static Path getStoreArchivePath(Configuration conf, RegionInfo region, byte[] family)
078    throws IOException {
079    Path rootDir = CommonFSUtils.getRootDir(conf);
080    Path tableArchiveDir = getTableArchivePath(rootDir, region.getTable());
081    return HRegionFileSystem.getStoreHomedir(tableArchiveDir, region, family);
082  }
083
084  /**
085   * Gets the archive directory under specified root dir. One scenario where this is useful is when
086   * WAL and root dir are configured under different file systems, i.e. root dir on S3 and WALs on
087   * HDFS. This is mostly useful for archiving recovered edits, when
088   * <b>hbase.region.archive.recovered.edits</b> is enabled.
089   * @param rootDir {@link Path} the root dir under which archive path should be created.
090   * @param region  parent region information under which the store currently lives
091   * @param family  name of the family in the store
092   * @return {@link Path} to the WAL FS directory to archive the given store or <tt>null</tt> if it
093   *         should not be archived
094   */
095  public static Path getStoreArchivePathForRootDir(Path rootDir, RegionInfo region, byte[] family) {
096    Path tableArchiveDir = getTableArchivePath(rootDir, region.getTable());
097    return HRegionFileSystem.getStoreHomedir(tableArchiveDir, region, family);
098  }
099
100  public static Path getStoreArchivePathForArchivePath(Path archivePath, RegionInfo region,
101    byte[] family) {
102    Path tableArchiveDir = CommonFSUtils.getTableDir(archivePath, region.getTable());
103    return HRegionFileSystem.getStoreHomedir(tableArchiveDir, region, family);
104  }
105
106  /**
107   * Get the archive directory for a given region under the specified table
108   * @param tableName the table name. Cannot be null.
109   * @param regiondir the path to the region directory. Cannot be null.
110   * @return {@link Path} to the directory to archive the given region, or <tt>null</tt> if it
111   *         should not be archived
112   */
113  public static Path getRegionArchiveDir(Path rootDir, TableName tableName, Path regiondir) {
114    // get the archive directory for a table
115    Path archiveDir = getTableArchivePath(rootDir, tableName);
116
117    // then add on the region path under the archive
118    String encodedRegionName = regiondir.getName();
119    return HRegion.getRegionDir(archiveDir, encodedRegionName);
120  }
121
122  /**
123   * Get the archive directory for a given region under the specified table
124   * @param rootDir   {@link Path} to the root directory where hbase files are stored (for building
125   *                  the archive path)
126   * @param tableName name of the table to archive. Cannot be null.
127   * @return {@link Path} to the directory to archive the given region, or <tt>null</tt> if it
128   *         should not be archived
129   */
130  public static Path getRegionArchiveDir(Path rootDir, TableName tableName,
131    String encodedRegionName) {
132    // get the archive directory for a table
133    Path archiveDir = getTableArchivePath(rootDir, tableName);
134    return HRegion.getRegionDir(archiveDir, encodedRegionName);
135  }
136
137  /**
138   * Get the path to the table archive directory based on the configured archive directory.
139   * <p>
140   * Get the path to the table's archive directory.
141   * <p>
142   * Generally of the form: /hbase/.archive/[tablename]
143   * @param rootdir   {@link Path} to the root directory where hbase files are stored (for building
144   *                  the archive path)
145   * @param tableName Name of the table to be archived. Cannot be null.
146   * @return {@link Path} to the archive directory for the table
147   */
148  public static Path getTableArchivePath(final Path rootdir, final TableName tableName) {
149    return CommonFSUtils.getTableDir(getArchivePath(rootdir), tableName);
150  }
151
152  /**
153   * Get the path to the table archive directory based on the configured archive directory.
154   * <p>
155   * Assumed that the table should already be archived.
156   * @param conf      {@link Configuration} to read the archive directory property. Can be null
157   * @param tableName Name of the table to be archived. Cannot be null.
158   * @return {@link Path} to the archive directory for the table
159   */
160  public static Path getTableArchivePath(final Configuration conf, final TableName tableName)
161    throws IOException {
162    return CommonFSUtils.getTableDir(getArchivePath(conf), tableName);
163  }
164
165  /**
166   * Get the full path to the archive directory on the configured
167   * {@link org.apache.hadoop.hbase.master.MasterFileSystem}
168   * @param conf to look for archive directory name and root directory. Cannot be null. Notes for
169   *             testing: requires a FileSystem root directory to be specified.
170   * @return the full {@link Path} to the archive directory, as defined by the configuration
171   * @throws IOException if an unexpected error occurs
172   */
173  public static Path getArchivePath(Configuration conf) throws IOException {
174    return getArchivePath(CommonFSUtils.getRootDir(conf));
175  }
176
177  /**
178   * Get the full path to the archive directory on the configured
179   * {@link org.apache.hadoop.hbase.master.MasterFileSystem}
180   * @param rootdir {@link Path} to the root directory where hbase files are stored (for building
181   *                the archive path)
182   * @return the full {@link Path} to the archive directory, as defined by the configuration
183   */
184  private static Path getArchivePath(final Path rootdir) {
185    return new Path(rootdir, HConstants.HFILE_ARCHIVE_DIRECTORY);
186  }
187
188  /*
189   * @return table name given archive file path
190   */
191  public static TableName getTableName(Path archivePath) {
192    Path p = archivePath;
193    String tbl = null;
194    // namespace is the 4th parent of file
195    for (int i = 0; i < 5; i++) {
196      if (p == null) return null;
197      if (i == 3) tbl = p.getName();
198      p = p.getParent();
199    }
200    if (p == null) return null;
201    return TableName.valueOf(p.getName(), tbl);
202  }
203}