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