Skip to content

Commit 3e5e9b4

Browse files
author
Duo Zhang
committed
HBASE-26248 Should find a suitable way to let users specify the store file tracker implementation
1 parent 27fd631 commit 3e5e9b4

5 files changed

Lines changed: 135 additions & 23 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ class MigrationStoreFileTracker extends StoreFileTrackerBase {
4343

4444
public MigrationStoreFileTracker(Configuration conf, boolean isPrimaryReplica, StoreContext ctx) {
4545
super(conf, isPrimaryReplica, ctx);
46-
this.src = StoreFileTrackerFactory.create(conf, SRC_IMPL, isPrimaryReplica, ctx);
47-
this.dst = StoreFileTrackerFactory.create(conf, DST_IMPL, isPrimaryReplica, ctx);
46+
this.src = StoreFileTrackerFactory.createForMigration(conf, SRC_IMPL, isPrimaryReplica, ctx);
47+
this.dst = StoreFileTrackerFactory.createForMigration(conf, DST_IMPL, isPrimaryReplica, ctx);
4848
Preconditions.checkArgument(!src.getClass().equals(dst.getClass()),
4949
"src and dst is the same: %s", src.getClass());
5050
}

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

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,66 @@
3434

3535
/**
3636
* Factory method for creating store file tracker.
37+
* <p/>
38+
* The current implementations are:
39+
* <ul>
40+
* <li><em>default</em>: DefaultStoreFileTracker, see {@link DefaultStoreFileTracker}.</li>
41+
* <li><em>file</em>:FileBasedStoreFileTracker, see {@link FileBasedStoreFileTracker}.</li>
42+
* <li><em>migration</em>:MigrationStoreFileTracker, see {@link MigrationStoreFileTracker}.</li>
43+
* </ul>
44+
* @see DefaultStoreFileTracker
45+
* @see FileBasedStoreFileTracker
46+
* @see MigrationStoreFileTracker
3747
*/
3848
@InterfaceAudience.Private
3949
public final class StoreFileTrackerFactory {
4050
public static final String TRACK_IMPL = "hbase.store.file-tracker.impl";
4151
private static final Logger LOG = LoggerFactory.getLogger(StoreFileTrackerFactory.class);
4252

53+
/**
54+
* Maps between configuration names for trackers and implementation classes.
55+
*/
56+
public enum Trackers {
57+
DEFAULT(DefaultStoreFileTracker.class), FILE(FileBasedStoreFileTracker.class),
58+
MIGRATION(MigrationStoreFileTracker.class);
59+
60+
final Class<? extends StoreFileTracker> clazz;
61+
62+
private Trackers(Class<? extends StoreFileTracker> clazz) {
63+
this.clazz = clazz;
64+
}
65+
}
66+
67+
private static Class<? extends StoreFileTracker> getTrackerClass(Configuration conf,
68+
String configName) {
69+
try {
70+
Trackers tracker =
71+
Trackers.valueOf(conf.get(TRACK_IMPL, Trackers.DEFAULT.name()).toUpperCase());
72+
return tracker.clazz;
73+
} catch (IllegalArgumentException e) {
74+
// Fall back to them specifying a class name
75+
return conf.getClass(TRACK_IMPL, Trackers.DEFAULT.clazz, StoreFileTracker.class);
76+
}
77+
}
78+
4379
public static StoreFileTracker create(Configuration conf, boolean isPrimaryReplica,
4480
StoreContext ctx) {
45-
Class<? extends StoreFileTracker> tracker =
46-
conf.getClass(TRACK_IMPL, DefaultStoreFileTracker.class, StoreFileTracker.class);
81+
Class<? extends StoreFileTracker> tracker = getTrackerClass(conf, TRACK_IMPL);
4782
LOG.info("instantiating StoreFileTracker impl {}", tracker.getName());
4883
return ReflectionUtils.newInstance(tracker, conf, isPrimaryReplica, ctx);
4984
}
5085

86+
/**
87+
* Used at master side when splitting/merging regions, as we do not have a Store, thus no
88+
* StoreContext at master side.
89+
*/
5190
public static StoreFileTracker create(Configuration conf, boolean isPrimaryReplica, String family,
5291
HRegionFileSystem regionFs) {
5392
ColumnFamilyDescriptorBuilder fDescBuilder =
5493
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(family));
5594
StoreContext ctx = StoreContext.getBuilder().withColumnFamilyDescriptor(fDescBuilder.build())
5695
.withRegionFileSystem(regionFs).build();
57-
return StoreFileTrackerFactory.create(conf, TRACK_IMPL, isPrimaryReplica, ctx);
96+
return StoreFileTrackerFactory.create(conf, isPrimaryReplica, ctx);
5897
}
5998

6099
public static Configuration mergeConfigurations(Configuration global, TableDescriptor table,
@@ -63,15 +102,30 @@ public static Configuration mergeConfigurations(Configuration global, TableDescr
63102
.addStringMap(family.getConfiguration()).addBytesMap(family.getValues());
64103
}
65104

66-
static StoreFileTrackerBase create(Configuration conf, String configName,
105+
/**
106+
* Create store file tracker to be used as source or destination for
107+
* {@link MigrationStoreFileTracker}.
108+
*/
109+
static StoreFileTrackerBase createForMigration(Configuration conf, String configName,
67110
boolean isPrimaryReplica, StoreContext ctx) {
68-
String className =
111+
String trackerName =
69112
Preconditions.checkNotNull(conf.get(configName), "config %s is not set", configName);
70113
Class<? extends StoreFileTrackerBase> tracker;
71114
try {
72-
tracker = Class.forName(className).asSubclass(StoreFileTrackerBase.class);
73-
} catch (ClassNotFoundException e) {
74-
throw new RuntimeException(e);
115+
tracker =
116+
Trackers.valueOf(trackerName.toUpperCase()).clazz.asSubclass(StoreFileTrackerBase.class);
117+
} catch (IllegalArgumentException e) {
118+
// Fall back to them specifying a class name
119+
try {
120+
tracker = Class.forName(trackerName).asSubclass(StoreFileTrackerBase.class);
121+
} catch (ClassNotFoundException cnfe) {
122+
throw new RuntimeException(cnfe);
123+
}
124+
}
125+
// prevent nest of MigrationStoreFileTracker, it will cause infinite recursion.
126+
if (MigrationStoreFileTracker.class.isAssignableFrom(tracker)) {
127+
throw new IllegalArgumentException("Should not specify " + configName + " as "
128+
+ Trackers.MIGRATION + " because it can not be nested");
75129
}
76130
LOG.info("instantiating StoreFileTracker impl {} as {}", tracker.getName(), configName);
77131
return ReflectionUtils.newInstance(tracker, conf, isPrimaryReplica, ctx);

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import java.io.IOException;
2525
import java.util.ArrayList;
26-
import java.util.Arrays;
2726
import java.util.List;
2827
import java.util.stream.Collectors;
2928
import org.apache.hadoop.conf.Configuration;
@@ -86,10 +85,10 @@ public class TestMigrationStoreFileTracker {
8685
public TestName name = new TestName();
8786

8887
@Parameter(0)
89-
public Class<? extends StoreFileTrackerBase> srcImplClass;
88+
public StoreFileTrackerFactory.Trackers srcImpl;
9089

9190
@Parameter(1)
92-
public Class<? extends StoreFileTrackerBase> dstImplClass;
91+
public StoreFileTrackerFactory.Trackers dstImpl;
9392

9493
private HRegion region;
9594

@@ -99,11 +98,13 @@ public class TestMigrationStoreFileTracker {
9998

10099
@Parameters(name = "{index}: src={0}, dst={1}")
101100
public static List<Object[]> params() {
102-
List<Class<? extends StoreFileTrackerBase>> impls =
103-
Arrays.asList(DefaultStoreFileTracker.class, FileBasedStoreFileTracker.class);
104101
List<Object[]> params = new ArrayList<>();
105-
for (Class<? extends StoreFileTrackerBase> src : impls) {
106-
for (Class<? extends StoreFileTrackerBase> dst : impls) {
102+
for (StoreFileTrackerFactory.Trackers src : StoreFileTrackerFactory.Trackers.values()) {
103+
for (StoreFileTrackerFactory.Trackers dst : StoreFileTrackerFactory.Trackers.values()) {
104+
if (src == StoreFileTrackerFactory.Trackers.MIGRATION
105+
|| dst == StoreFileTrackerFactory.Trackers.MIGRATION) {
106+
continue;
107+
}
107108
if (src.equals(dst)) {
108109
continue;
109110
}
@@ -122,8 +123,8 @@ public static void setUpBeforeClass() {
122123
@Before
123124
public void setUp() throws IOException {
124125
Configuration conf = UTIL.getConfiguration();
125-
conf.setClass(MigrationStoreFileTracker.SRC_IMPL, srcImplClass, StoreFileTrackerBase.class);
126-
conf.setClass(MigrationStoreFileTracker.DST_IMPL, dstImplClass, StoreFileTrackerBase.class);
126+
conf.set(MigrationStoreFileTracker.SRC_IMPL, srcImpl.name().toLowerCase());
127+
conf.set(MigrationStoreFileTracker.DST_IMPL, dstImpl.name().toLowerCase());
127128
rootDir = UTIL.getDataTestDir(name.getMethodName().replaceAll("[=:\\[ ]", "_"));
128129
wal = HBaseTestingUtil.createWal(conf, rootDir, RI);
129130
}
@@ -180,14 +181,14 @@ private void verifyData(int start, int end) throws IOException {
180181

181182
@Test
182183
public void testMigration() throws IOException {
183-
region = createRegion(srcImplClass);
184+
region = createRegion(srcImpl.clazz.asSubclass(StoreFileTrackerBase.class));
184185
putData(0, 100);
185186
verifyData(0, 100);
186187
reopenRegion(MigrationStoreFileTracker.class);
187188
verifyData(0, 100);
188189
region.compact(true);
189190
putData(100, 200);
190-
reopenRegion(dstImplClass);
191+
reopenRegion(dstImpl.clazz.asSubclass(StoreFileTrackerBase.class));
191192
verifyData(0, 200);
192193
}
193194
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ public class TestRegionWithFileBasedStoreFileTracker {
7171
@Before
7272
public void setUp() throws IOException {
7373
Configuration conf = new Configuration(UTIL.getConfiguration());
74-
conf.setClass(StoreFileTrackerFactory.TRACK_IMPL, FileBasedStoreFileTracker.class,
75-
StoreFileTracker.class);
74+
conf.set(StoreFileTrackerFactory.TRACK_IMPL, StoreFileTrackerFactory.Trackers.FILE.name());
7675
region =
7776
HBaseTestingUtil.createRegionAndWAL(RI, UTIL.getDataTestDir(name.getMethodName()), conf, TD);
7877
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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.regionserver.storefiletracker;
19+
20+
import static org.junit.Assert.assertThrows;
21+
22+
import org.apache.hadoop.conf.Configuration;
23+
import org.apache.hadoop.hbase.HBaseClassTestRule;
24+
import org.apache.hadoop.hbase.HBaseConfiguration;
25+
import org.apache.hadoop.hbase.regionserver.StoreContext;
26+
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
27+
import org.apache.hadoop.hbase.testclassification.SmallTests;
28+
import org.junit.ClassRule;
29+
import org.junit.Test;
30+
import org.junit.experimental.categories.Category;
31+
32+
@Category({ RegionServerTests.class, SmallTests.class })
33+
public class TestStoreFileTrackerFactory {
34+
35+
@ClassRule
36+
public static final HBaseClassTestRule CLASS_RULE =
37+
HBaseClassTestRule.forClass(TestStoreFileTrackerFactory.class);
38+
39+
@Test
40+
public void testCreateForMigration() {
41+
Configuration conf = HBaseConfiguration.create();
42+
String configName = "config";
43+
44+
// no config
45+
assertThrows(NullPointerException.class, () -> StoreFileTrackerFactory.createForMigration(conf,
46+
configName, false, StoreContext.getBuilder().build()));
47+
48+
// class not found
49+
conf.set(configName, "config");
50+
assertThrows(RuntimeException.class, () -> StoreFileTrackerFactory.createForMigration(conf,
51+
configName, false, StoreContext.getBuilder().build()));
52+
53+
// nested MigrationStoreFileTracker
54+
conf.setClass(configName, MigrationStoreFileTracker.class, StoreFileTrackerBase.class);
55+
assertThrows(IllegalArgumentException.class, () -> StoreFileTrackerFactory
56+
.createForMigration(conf, configName, false, StoreContext.getBuilder().build()));
57+
}
58+
}

0 commit comments

Comments
 (0)