-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-25902 HMaster failed to start with NoSuchColumnFamilyException during upgrade from HBase 1.x to HBase 2.x #3287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,7 @@ | |
| import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint; | ||
| import org.apache.hadoop.hbase.exceptions.DeserializationException; | ||
| import org.apache.hadoop.hbase.regionserver.BloomType; | ||
| import org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException; | ||
| import org.apache.yetus.audience.InterfaceAudience; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
@@ -94,6 +95,10 @@ public class FSTableDescriptors implements TableDescriptors { | |
| // TODO. | ||
| private final Map<TableName, TableDescriptor> cache = new ConcurrentHashMap<>(); | ||
|
|
||
| // Default meta table descriptor, will be used by RegionServer during rolling upgrade until | ||
| // HMaster write latest 2.x meta table descriptor | ||
| private TableDescriptor defaultMetaTableDesc = null; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens when using this "default descriptor" the regionserver attempts to update meta? Can that happen? We are assuming the master will rewrite soon, but is that valid? Regionservers don't run masters, they rely on an operator to do that. Who knows what the operator is doing. Would it be better to address specific fallbacks where something is missing or not expected?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RegionServer can't update the meta descriptor, |
||
|
|
||
| /** | ||
| * Construct a FSTableDescriptors instance using the hbase root dir of the given conf and the | ||
| * filesystem where that root dir lives. This instance can do write operations (is not read only). | ||
|
|
@@ -112,6 +117,14 @@ public FSTableDescriptors(final FileSystem fs, final Path rootdir, final boolean | |
| this.rootdir = rootdir; | ||
| this.fsreadonly = fsreadonly; | ||
| this.usecache = usecache; | ||
| // Create default in-memory meta table descriptor for RegionServer | ||
| if (this.fsreadonly) { | ||
| try { | ||
| defaultMetaTableDesc = createMetaTableDescriptorBuilder(fs.getConf()).build(); | ||
| } catch (IOException ioe) { | ||
| LOG.warn("Exception occurred while creating meta table descriptor", ioe); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public static void tryUpdateMetaTableDescriptor(Configuration conf) throws IOException { | ||
|
|
@@ -123,8 +136,10 @@ public static TableDescriptor tryUpdateAndGetMetaTableDescriptor(Configuration c | |
| FileSystem fs, Path rootdir) throws IOException { | ||
| // see if we already have meta descriptor on fs. Write one if not. | ||
| try { | ||
| return getTableDescriptorFromFs(fs, rootdir, TableName.META_TABLE_NAME); | ||
| } catch (TableInfoMissingException e) { | ||
| TableDescriptor td = getTableDescriptorFromFs(fs, rootdir, TableName.META_TABLE_NAME); | ||
| validateMetaTableDescriptor(td); | ||
| return td; | ||
| } catch (TableInfoMissingException | NoSuchColumnFamilyException e) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes sense. The table might be missing altogether (what current code handles), or might be missing a column family due to legacy (what this change handles) |
||
| TableDescriptorBuilder builder = createMetaTableDescriptorBuilder(conf); | ||
| TableDescriptor td = builder.build(); | ||
| LOG.info("Creating new hbase:meta table descriptor {}", td); | ||
|
|
@@ -139,6 +154,21 @@ public static TableDescriptor tryUpdateAndGetMetaTableDescriptor(Configuration c | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Validate meta table descriptor whether default column families exist or not | ||
| */ | ||
| private static void validateMetaTableDescriptor(TableDescriptor td) | ||
| throws NoSuchColumnFamilyException, TableInfoMissingException { | ||
| if (td == null) { | ||
| throw new TableInfoMissingException("Meta .tableinfo not found"); | ||
| } | ||
| for (byte[] cf : HConstants.UNDELETABLE_META_COLUMNFAMILIES) { | ||
| if (!td.hasColumnFamily(cf)) { | ||
| throw new NoSuchColumnFamilyException("Column family " + Bytes.toString(cf) + " not found"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static TableDescriptorBuilder createMetaTableDescriptorBuilder(final Configuration conf) | ||
| throws IOException { | ||
| // TODO We used to set CacheDataInL1 for META table. When we have BucketCache in file mode, now | ||
|
|
@@ -223,6 +253,21 @@ public TableDescriptor get(TableName tableName) { | |
| } catch (NullPointerException | IOException ioe) { | ||
| LOG.debug("Exception during readTableDecriptor. Current table name = " + tableName, ioe); | ||
| } | ||
|
|
||
| // Validate whether meta table descriptor is in HBase 2.x format | ||
| if (TableName.isMetaTableName(tableName) && defaultMetaTableDesc != null) { | ||
| try { | ||
| validateMetaTableDescriptor(tdmt); | ||
| // FS have proper meta table descriptor, we don't need to validate it again. | ||
| // Reset defaultMetaTableDesc | ||
| defaultMetaTableDesc = null; | ||
| } catch (TableInfoMissingException | NoSuchColumnFamilyException e) { | ||
| // Meta is still in old format, return the default meta table descriptor util we have meta | ||
| // descriptor in HBase 2.x format | ||
| return defaultMetaTableDesc; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems wrong.
If we need fallbacks to ride over an upgrade case, those fallbacks should be implemented where the errors are happening.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the current version of code createMetaTableDescriptorBuilder is used only during HMaster startup via InitMetaProcedure when table info file is missing. |
||
| } | ||
| } | ||
|
|
||
| // last HTD written wins | ||
| if (usecache && tdmt != null) { | ||
| this.cache.put(tableName, tdmt); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is wrong, right? We don't have any tooling in HConstants.
This should go where table descriptors are defined and managed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, will move it back to ModifyTableProcedure