|
20 | 20 | import static org.junit.Assert.assertEquals;
|
21 | 21 | import static org.junit.Assert.assertFalse;
|
22 | 22 | import static org.junit.Assert.assertTrue;
|
| 23 | +import static org.mockito.ArgumentMatchers.any; |
| 24 | +import static org.mockito.Mockito.mock; |
| 25 | +import static org.mockito.Mockito.times; |
| 26 | +import static org.mockito.Mockito.verify; |
| 27 | +import static org.mockito.Mockito.when; |
23 | 28 |
|
24 | 29 | import java.io.IOException;
|
25 | 30 | import java.security.PrivilegedExceptionAction;
|
26 | 31 | import java.util.ArrayList;
|
| 32 | +import java.util.Collection; |
27 | 33 | import java.util.Collections;
|
28 | 34 | import java.util.List;
|
29 | 35 | import java.util.stream.Collectors;
|
|
39 | 45 | import org.apache.hadoop.hbase.Stoppable;
|
40 | 46 | import org.apache.hadoop.hbase.TableName;
|
41 | 47 | import org.apache.hadoop.hbase.client.Admin;
|
| 48 | +import org.apache.hadoop.hbase.client.RegionInfo; |
42 | 49 | import org.apache.hadoop.hbase.client.Table;
|
43 | 50 | import org.apache.hadoop.hbase.master.cleaner.DirScanPool;
|
44 | 51 | import org.apache.hadoop.hbase.master.cleaner.HFileCleaner;
|
45 | 52 | import org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy;
|
46 | 53 | import org.apache.hadoop.hbase.regionserver.HRegion;
|
47 | 54 | import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
| 55 | +import org.apache.hadoop.hbase.regionserver.HStoreFile; |
48 | 56 | import org.apache.hadoop.hbase.testclassification.MediumTests;
|
49 | 57 | import org.apache.hadoop.hbase.testclassification.MiscTests;
|
50 | 58 | import org.apache.hadoop.hbase.util.Bytes;
|
| 59 | +import org.apache.hadoop.hbase.util.CommonFSUtils; |
51 | 60 | import org.apache.hadoop.hbase.util.FSUtils;
|
52 | 61 | import org.apache.hadoop.hbase.util.HFileArchiveTestingUtil;
|
53 | 62 | import org.apache.hadoop.hbase.util.HFileArchiveUtil;
|
|
62 | 71 | import org.junit.Test;
|
63 | 72 | import org.junit.experimental.categories.Category;
|
64 | 73 | import org.junit.rules.TestName;
|
| 74 | +import org.mockito.ArgumentCaptor; |
65 | 75 | import org.slf4j.Logger;
|
66 | 76 | import org.slf4j.LoggerFactory;
|
67 | 77 |
|
@@ -123,6 +133,107 @@ public static void cleanupTest() throws Exception {
|
123 | 133 | POOL.shutdownNow();
|
124 | 134 | }
|
125 | 135 |
|
| 136 | + @Test |
| 137 | + public void testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot() throws Exception { |
| 138 | + String walDir = "mockFS://mockFSAuthority:9876/mockDir/wals/"; |
| 139 | + String baseDir = FSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/"; |
| 140 | + testArchiveStoreFilesDifferentFileSystems(walDir, baseDir, |
| 141 | + HFileArchiver::archiveStoreFiles); |
| 142 | + } |
| 143 | + |
| 144 | + @Test |
| 145 | + public void testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot() throws Exception { |
| 146 | + String baseDir = FSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/"; |
| 147 | + testArchiveStoreFilesDifferentFileSystems(null, baseDir, |
| 148 | + HFileArchiver::archiveStoreFiles); |
| 149 | + } |
| 150 | + |
| 151 | + @Test |
| 152 | + public void testArchiveStoreFilesDifferentFileSystemsWallAndRootSame() throws Exception { |
| 153 | + String baseDir = FSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/"; |
| 154 | + testArchiveStoreFilesDifferentFileSystems("/hbase/wals/", baseDir, |
| 155 | + HFileArchiver::archiveStoreFiles); |
| 156 | + } |
| 157 | + |
| 158 | + private void testArchiveStoreFilesDifferentFileSystems(String walDir, String expectedBase, |
| 159 | + ArchivingFunction<Configuration, FileSystem, RegionInfo, Path, byte[], |
| 160 | + Collection<HStoreFile>> archivingFunction) throws IOException { |
| 161 | + FileSystem mockedFileSystem = mock(FileSystem.class); |
| 162 | + Configuration conf = new Configuration(UTIL.getConfiguration()); |
| 163 | + if(walDir != null) { |
| 164 | + conf.set(CommonFSUtils.HBASE_WAL_DIR, walDir); |
| 165 | + } |
| 166 | + Path filePath = new Path("/mockDir/wals/mockFile"); |
| 167 | + when(mockedFileSystem.getScheme()).thenReturn("mockFS"); |
| 168 | + when(mockedFileSystem.mkdirs(any())).thenReturn(true); |
| 169 | + when(mockedFileSystem.exists(any())).thenReturn(true); |
| 170 | + RegionInfo mockedRegion = mock(RegionInfo.class); |
| 171 | + TableName tableName = TableName.valueOf("mockTable"); |
| 172 | + when(mockedRegion.getTable()).thenReturn(tableName); |
| 173 | + when(mockedRegion.getEncodedName()).thenReturn("mocked-region-encoded-name"); |
| 174 | + Path tableDir = new Path("mockFS://mockDir/tabledir"); |
| 175 | + byte[] family = Bytes.toBytes("testfamily"); |
| 176 | + HStoreFile mockedFile = mock(HStoreFile.class); |
| 177 | + List<HStoreFile> list = new ArrayList<>(); |
| 178 | + list.add(mockedFile); |
| 179 | + when(mockedFile.getPath()).thenReturn(filePath); |
| 180 | + when(mockedFileSystem.rename(any(),any())).thenReturn(true); |
| 181 | + archivingFunction.apply(conf, mockedFileSystem, mockedRegion, tableDir, family, list); |
| 182 | + ArgumentCaptor<Path> pathCaptor = ArgumentCaptor.forClass(Path.class); |
| 183 | + verify(mockedFileSystem, times(2)).rename(pathCaptor.capture(), any()); |
| 184 | + String expectedDir = expectedBase + |
| 185 | + "archive/data/default/mockTable/mocked-region-encoded-name/testfamily/mockFile"; |
| 186 | + assertTrue(pathCaptor.getAllValues().get(0).toString().equals(expectedDir)); |
| 187 | + } |
| 188 | + |
| 189 | + @FunctionalInterface |
| 190 | + private interface ArchivingFunction<Configuration, FS, Region, Dir, Family, Files> { |
| 191 | + void apply(Configuration config, FS fs, Region region, Dir dir, Family family, Files files) |
| 192 | + throws IOException; |
| 193 | + } |
| 194 | + |
| 195 | + @Test |
| 196 | + public void testArchiveRecoveredEditsWalDirNull() throws Exception { |
| 197 | + testArchiveRecoveredEditsWalDirNullOrSame(null); |
| 198 | + } |
| 199 | + |
| 200 | + @Test |
| 201 | + public void testArchiveRecoveredEditsWalDirSameFsStoreFiles() throws Exception { |
| 202 | + testArchiveRecoveredEditsWalDirNullOrSame("/wal-dir"); |
| 203 | + } |
| 204 | + |
| 205 | + private void testArchiveRecoveredEditsWalDirNullOrSame(String walDir) throws Exception { |
| 206 | + String originalRootDir = UTIL.getConfiguration().get(HConstants.HBASE_DIR); |
| 207 | + try { |
| 208 | + String baseDir = "mockFS://mockFSAuthority:9876/hbase/"; |
| 209 | + UTIL.getConfiguration().set(HConstants.HBASE_DIR, baseDir); |
| 210 | + testArchiveStoreFilesDifferentFileSystems(walDir, baseDir, |
| 211 | + (conf, fs, region, dir, family, list) -> HFileArchiver |
| 212 | + .archiveRecoveredEdits(conf, fs, region, family, list)); |
| 213 | + } finally { |
| 214 | + UTIL.getConfiguration().set(HConstants.HBASE_DIR, originalRootDir); |
| 215 | + } |
| 216 | + } |
| 217 | + |
| 218 | + @Test(expected = IOException.class) |
| 219 | + public void testArchiveRecoveredEditsWrongFS() throws Exception { |
| 220 | + String baseDir = FSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/"; |
| 221 | + //Internally, testArchiveStoreFilesDifferentFileSystems will pass a "mockedFS" |
| 222 | + // to HFileArchiver.archiveRecoveredEdits, but since wal-dir is supposedly on same FS |
| 223 | + // as root dir it would lead to conflicting FSes and an IOException is expected. |
| 224 | + testArchiveStoreFilesDifferentFileSystems("/wal-dir", baseDir, |
| 225 | + (conf, fs, region, dir, family, list) -> HFileArchiver |
| 226 | + .archiveRecoveredEdits(conf, fs, region, family, list)); |
| 227 | + } |
| 228 | + |
| 229 | + @Test |
| 230 | + public void testArchiveRecoveredEditsWalDirDifferentFS() throws Exception { |
| 231 | + String walDir = "mockFS://mockFSAuthority:9876/mockDir/wals/"; |
| 232 | + testArchiveStoreFilesDifferentFileSystems(walDir, walDir, |
| 233 | + (conf, fs, region, dir, family, list) -> |
| 234 | + HFileArchiver.archiveRecoveredEdits(conf, fs, region, family, list)); |
| 235 | + } |
| 236 | + |
126 | 237 | @Test
|
127 | 238 | public void testRemoveRegionDirOnArchive() throws Exception {
|
128 | 239 | final TableName tableName = TableName.valueOf(name.getMethodName());
|
|
0 commit comments