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