Skip to content

Commit 4d27053

Browse files
wchevreuilJosh Elser
authored andcommitted
HBASE-26326 CreateTableProcedure fails when FileBasedStoreFileTracker… (apache#3721)
Amend HBASE-26326 - HBASE-21515 has been challenging to backport into this branch. For HBASE-26326, we actually only need the changes HBASE-21515 added to ReflectionUtils, so I had given up on attempting to bring in HBASE-21515 and am adding these required changes as an amend to HBASE-26326. Change-Id: I82e9e2f44a2b64fa0423531cd1775ce55a1e1607 Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Josh Elser <elserj@apache.org>
1 parent fb4997a commit 4d27053

11 files changed

Lines changed: 76 additions & 47 deletions

File tree

hbase-common/src/main/java/org/apache/hadoop/hbase/util/ReflectionUtils.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,20 @@ public static <T> Constructor<T> findConstructor(Class<T> type, Object... paramT
8383

8484
boolean match = true;
8585
for (int i = 0; i < ctorParamTypes.length && match; ++i) {
86-
Class<?> paramType = paramTypes[i].getClass();
87-
match = (!ctorParamTypes[i].isPrimitive()) ? ctorParamTypes[i].isAssignableFrom(paramType) :
88-
((int.class.equals(ctorParamTypes[i]) && Integer.class.equals(paramType)) ||
89-
(long.class.equals(ctorParamTypes[i]) && Long.class.equals(paramType)) ||
90-
(double.class.equals(ctorParamTypes[i]) && Double.class.equals(paramType)) ||
91-
(char.class.equals(ctorParamTypes[i]) && Character.class.equals(paramType)) ||
92-
(short.class.equals(ctorParamTypes[i]) && Short.class.equals(paramType)) ||
93-
(boolean.class.equals(ctorParamTypes[i]) && Boolean.class.equals(paramType)) ||
94-
(byte.class.equals(ctorParamTypes[i]) && Byte.class.equals(paramType)));
86+
if (paramTypes[i] == null) {
87+
match = !ctorParamTypes[i].isPrimitive();
88+
} else {
89+
Class<?> paramType = paramTypes[i].getClass();
90+
match = (!ctorParamTypes[i].isPrimitive()) ?
91+
ctorParamTypes[i].isAssignableFrom(paramType) :
92+
((int.class.equals(ctorParamTypes[i]) && Integer.class.equals(paramType)) ||
93+
(long.class.equals(ctorParamTypes[i]) && Long.class.equals(paramType)) ||
94+
(double.class.equals(ctorParamTypes[i]) && Double.class.equals(paramType)) ||
95+
(char.class.equals(ctorParamTypes[i]) && Character.class.equals(paramType)) ||
96+
(short.class.equals(ctorParamTypes[i]) && Short.class.equals(paramType)) ||
97+
(boolean.class.equals(ctorParamTypes[i]) && Boolean.class.equals(paramType)) ||
98+
(byte.class.equals(ctorParamTypes[i]) && Byte.class.equals(paramType)));
99+
}
95100
}
96101

97102
if (match) {

hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/CreateTableProcedure.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.apache.hadoop.hbase.client.RegionInfo;
3232
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
3333
import org.apache.hadoop.hbase.client.TableDescriptor;
34-
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
3534
import org.apache.hadoop.hbase.client.TableState;
3635
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
3736
import org.apache.hadoop.hbase.master.MasterFileSystem;
@@ -272,9 +271,8 @@ private void preCreate(final MasterProcedureEnv env)
272271
(newRegions != null ? newRegions.size() : 0));
273272
}
274273

275-
TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableDescriptor);
276-
StoreFileTrackerFactory.persistTrackerConfig(env.getMasterConfiguration(), builder);
277-
tableDescriptor = builder.build();
274+
tableDescriptor = StoreFileTrackerFactory.updateWithTrackerConfigs(env.getMasterConfiguration(),
275+
tableDescriptor);
278276

279277
final MasterCoprocessorHost cpHost = env.getMasterCoprocessorHost();
280278
if (cpHost != null) {

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreUtils.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
import org.apache.hadoop.hbase.Cell;
3232
import org.apache.hadoop.hbase.CellComparator;
3333
import org.apache.hadoop.hbase.CellUtil;
34+
import org.apache.hadoop.hbase.CompoundConfiguration;
3435
import org.apache.hadoop.hbase.HConstants;
36+
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
37+
import org.apache.hadoop.hbase.client.TableDescriptor;
3538
import org.apache.hadoop.hbase.io.hfile.HFile;
3639
import org.apache.hadoop.hbase.util.ChecksumType;
3740
import org.apache.hadoop.hbase.CompoundConfiguration;
@@ -170,6 +173,14 @@ public static int getBytesPerChecksum(Configuration conf) {
170173
HFile.DEFAULT_BYTES_PER_CHECKSUM);
171174
}
172175

176+
public static Configuration createStoreConfiguration(Configuration conf, TableDescriptor td,
177+
ColumnFamilyDescriptor cfd) {
178+
// CompoundConfiguration will look for keys in reverse order of addition, so we'd
179+
// add global config first, then table and cf overrides, then cf metadata.
180+
return new CompoundConfiguration().add(conf).addBytesMap(td.getValues())
181+
.addStringMap(cfd.getConfiguration()).addBytesMap(cfd.getValues());
182+
}
183+
173184
public static List<StoreFileInfo> toStoreFileInfo(Collection<HStoreFile> storefiles) {
174185
return storefiles.stream().map(HStoreFile::getFileInfo).collect(Collectors.toList());
175186
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/storefiletracker/FileBasedStoreFileTracker.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ class FileBasedStoreFileTracker extends StoreFileTrackerBase {
5656

5757
public FileBasedStoreFileTracker(Configuration conf, boolean isPrimaryReplica, StoreContext ctx) {
5858
super(conf, isPrimaryReplica, ctx);
59-
backedFile = new StoreFileListFile(ctx);
59+
//CreateTableProcedure needs to instantiate the configured SFT impl, in order to update table
60+
//descriptors with the SFT impl specific configs. By the time this happens, the table has no
61+
//regions nor stores yet, so it can't create a proper StoreContext.
62+
if (ctx != null) {
63+
backedFile = new StoreFileListFile(ctx);
64+
} else {
65+
backedFile = null;
66+
}
6067
}
6168

6269
@Override

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/storefiletracker/MigrationStoreFileTracker.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,6 @@ void set(List<StoreFileInfo> files) {
8989
"Should not call this method on " + getClass().getSimpleName());
9090
}
9191

92-
@Override
93-
public void persistConfiguration(TableDescriptorBuilder builder) {
94-
super.persistConfiguration(builder);
95-
TableDescriptor desc = builder.build();
96-
if (StringUtils.isEmpty(desc.getValue(SRC_IMPL))) {
97-
builder.setValue(SRC_IMPL, src.getTrackerName());
98-
}
99-
if (StringUtils.isEmpty(desc.getValue(DST_IMPL))) {
100-
builder.setValue(DST_IMPL, dst.getTrackerName());
101-
}
102-
}
103-
10492
static Class<? extends StoreFileTracker> getSrcTrackerClass(Configuration conf) {
10593
return StoreFileTrackerFactory.getStoreFileTrackerClassForMigration(conf, SRC_IMPL);
10694
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/storefiletracker/StoreFileTracker.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Collection;
2222
import java.util.List;
2323

24+
import org.apache.hadoop.hbase.client.TableDescriptor;
2425
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
2526
import org.apache.hadoop.hbase.regionserver.CreateStoreFileWriterParams;
2627
import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
@@ -75,13 +76,13 @@ void replace(Collection<StoreFileInfo> compactedFiles, Collection<StoreFileInfo>
7576
StoreFileWriter createWriter(CreateStoreFileWriterParams params) throws IOException;
7677

7778
/**
78-
* Saves StoreFileTracker implementations specific configurations into the table descriptors.
79+
* Adds StoreFileTracker implementations specific configurations into the table descriptor.
7980
* <p/>
8081
* This is used to avoid accidentally data loss when changing the cluster level store file tracker
8182
* implementation, and also possible misconfiguration between master and region servers.
8283
* <p/>
8384
* See HBASE-26246 for more details.
8485
* @param builder The table descriptor builder for the given table.
8586
*/
86-
void persistConfiguration(TableDescriptorBuilder builder);
87+
TableDescriptorBuilder updateWithTrackerConfigs(TableDescriptorBuilder builder);
8788
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/storefiletracker/StoreFileTrackerBase.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.apache.hadoop.hbase.io.hfile.HFile;
3434
import org.apache.hadoop.hbase.io.hfile.HFileContext;
3535
import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
36-
import org.apache.hadoop.hbase.procedure2.util.StringUtils;
3736
import org.apache.hadoop.hbase.regionserver.CreateStoreFileWriterParams;
3837
import org.apache.hadoop.hbase.regionserver.StoreContext;
3938
import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
@@ -84,11 +83,9 @@ public final void replace(Collection<StoreFileInfo> compactedFiles,
8483
}
8584

8685
@Override
87-
public void persistConfiguration(TableDescriptorBuilder builder) {
88-
TableDescriptor desc = builder.build();
89-
if (StringUtils.isEmpty(desc.getValue(TRACKER_IMPL))) {
90-
builder.setValue(TRACKER_IMPL, getTrackerName());
91-
}
86+
public TableDescriptorBuilder updateWithTrackerConfigs(TableDescriptorBuilder builder) {
87+
builder.setValue(TRACKER_IMPL, getTrackerName());
88+
return builder;
9289
}
9390

9491
protected final String getTrackerName() {

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/storefiletracker/StoreFileTrackerFactory.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.util.Collections;
2020
import java.util.HashMap;
2121
import java.util.Map;
22+
23+
import org.apache.commons.lang3.StringUtils;
2224
import org.apache.hadoop.conf.Configuration;
2325
import org.apache.hadoop.hbase.CompoundConfiguration;
2426
import org.apache.hadoop.hbase.DoNotRetryIOException;
@@ -27,6 +29,7 @@
2729
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
2830
import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
2931
import org.apache.hadoop.hbase.regionserver.StoreContext;
32+
import org.apache.hadoop.hbase.regionserver.StoreUtils;
3033
import org.apache.hadoop.hbase.util.ReflectionUtils;
3134
import org.apache.yetus.audience.InterfaceAudience;
3235
import org.slf4j.Logger;
@@ -115,16 +118,13 @@ public static StoreFileTracker create(Configuration conf, TableDescriptor td,
115118
ColumnFamilyDescriptor cfd, HRegionFileSystem regionFs) {
116119
StoreContext ctx =
117120
StoreContext.getBuilder().withColumnFamilyDescriptor(cfd).withRegionFileSystem(regionFs)
118-
.withFamilyStoreDirectoryPath(regionFs.getStoreDir(cfd.getNameAsString()))
119-
.withFamilyStoreDirectoryPath(regionFs.getStoreDir(cfd.getNameAsString()))
120-
.build();
121+
.withFamilyStoreDirectoryPath(regionFs.getStoreDir(cfd.getNameAsString())).build();
121122
return StoreFileTrackerFactory.create(mergeConfigurations(conf, td, cfd), true, ctx);
122123
}
123124

124125
private static Configuration mergeConfigurations(Configuration global, TableDescriptor table,
125126
ColumnFamilyDescriptor family) {
126-
return new CompoundConfiguration().add(global).addBytesMap(table.getValues())
127-
.addStringMap(family.getConfiguration()).addBytesMap(family.getValues());
127+
return StoreUtils.createStoreConfiguration(global, table, family);
128128
}
129129

130130
static Class<? extends StoreFileTrackerBase>
@@ -161,12 +161,18 @@ static StoreFileTrackerBase createForMigration(Configuration conf, String config
161161
return ReflectionUtils.newInstance(tracker, conf, isPrimaryReplica, ctx);
162162
}
163163

164-
public static void persistTrackerConfig(Configuration conf, TableDescriptorBuilder builder) {
165-
TableDescriptor tableDescriptor = builder.build();
166-
ColumnFamilyDescriptor cfDesc = tableDescriptor.getColumnFamilies()[0];
167-
StoreContext context = StoreContext.getBuilder().withColumnFamilyDescriptor(cfDesc).build();
168-
StoreFileTracker tracker = StoreFileTrackerFactory.create(conf, true, context);
169-
tracker.persistConfiguration(builder);
164+
public static TableDescriptor updateWithTrackerConfigs(Configuration conf,
165+
TableDescriptor descriptor) {
166+
//CreateTableProcedure needs to instantiate the configured SFT impl, in order to update table
167+
//descriptors with the SFT impl specific configs. By the time this happens, the table has no
168+
//regions nor stores yet, so it can't create a proper StoreContext.
169+
if (StringUtils.isEmpty(descriptor.getValue(TRACKER_IMPL))) {
170+
StoreFileTracker tracker =
171+
StoreFileTrackerFactory.create(conf, true, null);
172+
TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(descriptor);
173+
return tracker.updateWithTrackerConfigs(builder).build();
174+
}
175+
return descriptor;
170176
}
171177

172178
// should not use MigrationStoreFileTracker for new family

hbase-server/src/test/java/org/apache/hadoop/hbase/master/procedure/TestCreateTableProcedure.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apache.hadoop.hbase.procedure2.Procedure;
4040
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
4141
import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
42+
import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory;
4243
import org.apache.hadoop.hbase.regionserver.storefiletracker.TestStoreFileTracker;
4344
import org.apache.hadoop.hbase.testclassification.MasterTests;
4445
import org.apache.hadoop.hbase.testclassification.MediumTests;
@@ -105,6 +106,21 @@ public void testCreateWithTrackImpl() throws Exception {
105106
assertEquals(trackerName, htd.getValue(TRACKER_IMPL));
106107
}
107108

109+
@Test
110+
public void testCreateWithFileBasedStoreTrackerImpl() throws Exception {
111+
ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
112+
procExec.getEnvironment().getMasterConfiguration().set(StoreFileTrackerFactory.TRACKER_IMPL,
113+
StoreFileTrackerFactory.Trackers.FILE.name());
114+
final TableName tableName = TableName.valueOf(name.getMethodName());
115+
TableDescriptor htd = MasterProcedureTestingUtility.createHTD(tableName, F1);
116+
RegionInfo[] regions = ModifyRegionUtils.createRegionInfos(htd, null);
117+
long procId = ProcedureTestingUtility.submitAndWait(procExec,
118+
new CreateTableProcedure(procExec.getEnvironment(), htd, regions));
119+
ProcedureTestingUtility.assertProcNotFailed(procExec.getResult(procId));
120+
htd = getMaster().getTableDescriptors().get(tableName);
121+
assertEquals(StoreFileTrackerFactory.Trackers.FILE.name(), htd.getValue(TRACKER_IMPL));
122+
}
123+
108124
@Test
109125
public void testCreateWithoutColumnFamily() throws Exception {
110126
final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();

hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/storefiletracker/TestChangeStoreFileTracker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public static void setUp() throws Exception {
6565
}
6666

6767
@AfterClass
68-
public static void tearDown() throws IOException {
68+
public static void tearDown() throws Exception {
6969
UTIL.shutdownMiniCluster();
7070
}
7171

0 commit comments

Comments
 (0)