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.util;
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.hbase.HConstants;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
31  
32  /**
33   * A class to migrate table descriptor files to a dedicated subdir.
34   * Invoked by HMaster.finishInitialization before accessing table descriptors.
35   * Migrates snapshots, user tables, and system tables.
36   * 
37   * @deprecated will be removed for the major release after 0.96.
38   */
39  @Deprecated
40  public class FSTableDescriptorMigrationToSubdir {
41    
42    private static final Log LOG = LogFactory.getLog(FSTableDescriptorMigrationToSubdir.class);
43  
44    public static void migrateFSTableDescriptorsIfNecessary(FileSystem fs, Path rootDir)
45    throws IOException {
46      if (needsMigration(fs, rootDir)) {
47        migrateFsTableDescriptors(fs, rootDir);
48        LOG.info("Migration complete.");
49      }
50    }
51  
52    /**
53     * Determines if migration is required by checking to see whether the hbase:meta table has been
54     * migrated.
55     */
56    private static boolean needsMigration(FileSystem fs, Path rootDir) throws IOException {
57      Path metaTableDir = FSUtils.getTableDir(rootDir,
58        TableName.META_TABLE_NAME);
59      FileStatus metaTableInfoStatus =
60        FSTableDescriptors.getTableInfoPath(fs, metaTableDir);
61      return metaTableInfoStatus == null;
62    }
63    
64    /**
65     * Migrates all snapshots, user tables and system tables that require migration.
66     * First migrates snapshots.
67     * Then migrates each user table in order,
68     * then attempts ROOT (should be gone)
69     * Migrates hbase:meta last to indicate migration is complete.
70     */
71    private static void migrateFsTableDescriptors(FileSystem fs, Path rootDir) throws IOException {
72      // First migrate snapshots - will migrate any snapshot dir that contains a table info file
73      Path snapshotsDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);
74      if (fs.exists(snapshotsDir)) {
75        LOG.info("Migrating snapshots");
76        FileStatus[] snapshots = fs.listStatus(snapshotsDir,
77            new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));
78        for (FileStatus snapshot : snapshots) {
79          migrateTable(fs, snapshot.getPath());
80        }
81      }
82      
83      LOG.info("Migrating user tables");
84      List<Path> userTableDirs = FSUtils.getTableDirs(fs, rootDir);
85      for (Path userTableDir : userTableDirs) {
86        migrateTable(fs, userTableDir);
87      }
88      
89      LOG.info("Migrating system tables");
90      // migrate meta last because that's what we check to see if migration is complete
91      migrateTableIfExists(fs, rootDir, TableName.META_TABLE_NAME);
92    }
93  
94    private static void migrateTableIfExists(FileSystem fs, Path rootDir, TableName tableName)
95    throws IOException {
96      Path tableDir = FSUtils.getTableDir(rootDir, tableName);
97      if (fs.exists(tableDir)) {
98        migrateTable(fs, tableDir);
99      }
100   }
101 
102   /**
103    * Migrates table info files.
104    * Moves the latest table info file (is present) from the table dir to the table info subdir.
105    * Removes any older table info files from the table dir and any existing table info subdir.
106    */
107   private static void migrateTable(FileSystem fs, Path tableDir) throws IOException {
108     FileStatus oldTableStatus = FSTableDescriptors.getCurrentTableInfoStatus(fs,  tableDir, true);
109     if (oldTableStatus == null) {
110       LOG.debug("No table info file to migrate for " + tableDir);
111       return;
112     }
113     
114     Path tableInfoDir = new Path(tableDir, FSTableDescriptors.TABLEINFO_DIR);
115     // remove table info subdir if it already exists
116     boolean removedExistingSubdir = FSUtils.deleteDirectory(fs, tableInfoDir);
117     if (removedExistingSubdir) {
118       LOG.info("Removed existing subdir at: " + tableInfoDir);
119     }
120     boolean createdSubdir = fs.mkdirs(tableInfoDir);
121     if (!createdSubdir) {
122       throw new IOException("Unable to create new table info directory: " + tableInfoDir);
123     }
124     
125     Path oldTableInfoPath = oldTableStatus.getPath();
126     Path newTableInfoPath = new Path(tableInfoDir, oldTableInfoPath.getName());
127     boolean renamedInfoFile = fs.rename(oldTableInfoPath, newTableInfoPath);
128     if (!renamedInfoFile) {
129       throw new IOException("Failed to move table info file from old location: "
130         + oldTableInfoPath + " to new location: " + newTableInfoPath);
131     }
132    
133     LOG.info("Migrated table info from: " + oldTableInfoPath
134       + " to new location: " + newTableInfoPath);
135   }
136 
137 }