001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import static org.junit.jupiter.api.Assertions.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertNotEquals; 023import static org.junit.jupiter.api.Assertions.assertNotNull; 024import static org.junit.jupiter.api.Assertions.assertNull; 025import static org.junit.jupiter.api.Assertions.assertTrue; 026import static org.junit.jupiter.api.Assertions.fail; 027 028import java.io.IOException; 029import java.util.Arrays; 030import java.util.Comparator; 031import java.util.Map; 032import org.apache.hadoop.fs.FSDataOutputStream; 033import org.apache.hadoop.fs.FileStatus; 034import org.apache.hadoop.fs.FileSystem; 035import org.apache.hadoop.fs.Path; 036import org.apache.hadoop.hbase.HBaseCommonTestingUtil; 037import org.apache.hadoop.hbase.HConstants; 038import org.apache.hadoop.hbase.TableDescriptors; 039import org.apache.hadoop.hbase.TableName; 040import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 041import org.apache.hadoop.hbase.client.TableDescriptor; 042import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 043import org.apache.hadoop.hbase.testclassification.MediumTests; 044import org.apache.hadoop.hbase.testclassification.MiscTests; 045import org.junit.jupiter.api.AfterAll; 046import org.junit.jupiter.api.BeforeEach; 047import org.junit.jupiter.api.Tag; 048import org.junit.jupiter.api.Test; 049import org.junit.jupiter.api.TestInfo; 050import org.slf4j.Logger; 051import org.slf4j.LoggerFactory; 052 053/** 054 * Tests for {@link FSTableDescriptors}. 055 */ 056// Do not support to be executed in he same JVM as other tests 057@Tag(MiscTests.TAG) 058@Tag(MediumTests.TAG) 059public class TestFSTableDescriptors { 060 061 private static final HBaseCommonTestingUtil UTIL = new HBaseCommonTestingUtil(); 062 private static final Logger LOG = LoggerFactory.getLogger(TestFSTableDescriptors.class); 063 064 private Path testDir; 065 066 @BeforeEach 067 public void setUp(TestInfo testInfo) { 068 testDir = UTIL.getDataTestDir(testInfo.getTestMethod().get().getName()); 069 } 070 071 @AfterAll 072 public static void tearDownAfterClass() { 073 UTIL.cleanupTestDir(); 074 } 075 076 @Test 077 public void testRegexAgainstOldStyleTableInfo() { 078 Path p = new Path(testDir, FSTableDescriptors.TABLEINFO_FILE_PREFIX); 079 int i = FSTableDescriptors.getTableInfoSequenceIdAndFileLength(p).sequenceId; 080 assertEquals(0, i); 081 // Assert it won't eat garbage -- that it fails 082 Path p2 = new Path(testDir, "abc"); 083 org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, 084 () -> FSTableDescriptors.getTableInfoSequenceIdAndFileLength(p2)); 085 } 086 087 @Test 088 public void testCreateAndUpdate(TestInfo testInfo) throws IOException { 089 TableDescriptor htd = TableDescriptorBuilder 090 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())).build(); 091 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 092 FSTableDescriptors fstd = new FSTableDescriptors(fs, testDir); 093 assertTrue(fstd.createTableDescriptor(htd)); 094 assertFalse(fstd.createTableDescriptor(htd)); 095 Path tableInfoDir = new Path(CommonFSUtils.getTableDir(testDir, htd.getTableName()), 096 FSTableDescriptors.TABLEINFO_DIR); 097 FileStatus[] statuses = fs.listStatus(tableInfoDir); 098 assertEquals(1, statuses.length, "statuses.length=" + statuses.length); 099 for (int i = 0; i < 10; i++) { 100 fstd.update(htd); 101 } 102 statuses = fs.listStatus(tableInfoDir); 103 assertEquals(1, statuses.length); 104 } 105 106 @Test 107 public void testSequenceIdAdvancesOnTableInfo(TestInfo testInfo) throws IOException { 108 TableDescriptor htd = TableDescriptorBuilder 109 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())).build(); 110 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 111 FSTableDescriptors fstd = new FSTableDescriptors(fs, testDir); 112 Path previousPath = null; 113 int previousSeqId = -1; 114 for (int i = 0; i < 10; i++) { 115 Path path = fstd.updateTableDescriptor(htd); 116 int seqId = FSTableDescriptors.getTableInfoSequenceIdAndFileLength(path).sequenceId; 117 if (previousPath != null) { 118 // Assert we cleaned up the old file. 119 assertTrue(!fs.exists(previousPath)); 120 assertEquals(previousSeqId + 1, seqId); 121 } 122 previousPath = path; 123 previousSeqId = seqId; 124 } 125 } 126 127 @Test 128 public void testFormatTableInfoSequenceId() { 129 Path p0 = assertWriteAndReadSequenceId(0); 130 // Assert p0 has format we expect. 131 StringBuilder sb = new StringBuilder(); 132 for (int i = 0; i < FSTableDescriptors.WIDTH_OF_SEQUENCE_ID; i++) { 133 sb.append("0"); 134 } 135 assertEquals(FSTableDescriptors.TABLEINFO_FILE_PREFIX + "." + sb.toString() + ".0", 136 p0.getName()); 137 // Check a few more. 138 Path p2 = assertWriteAndReadSequenceId(2); 139 Path p10000 = assertWriteAndReadSequenceId(10000); 140 // Get a .tablinfo that has no sequenceid suffix. 141 Path p = new Path(p0.getParent(), FSTableDescriptors.TABLEINFO_FILE_PREFIX); 142 FileStatus fs = new FileStatus(0, false, 0, 0, 0, p); 143 FileStatus fs0 = new FileStatus(0, false, 0, 0, 0, p0); 144 FileStatus fs2 = new FileStatus(0, false, 0, 0, 0, p2); 145 FileStatus fs10000 = new FileStatus(0, false, 0, 0, 0, p10000); 146 Comparator<FileStatus> comparator = FSTableDescriptors.TABLEINFO_FILESTATUS_COMPARATOR; 147 assertTrue(comparator.compare(fs, fs0) > 0); 148 assertTrue(comparator.compare(fs0, fs2) > 0); 149 assertTrue(comparator.compare(fs2, fs10000) > 0); 150 } 151 152 private Path assertWriteAndReadSequenceId(final int i) { 153 Path p = 154 new Path(testDir, FSTableDescriptors.getTableInfoFileName(i, HConstants.EMPTY_BYTE_ARRAY)); 155 int ii = FSTableDescriptors.getTableInfoSequenceIdAndFileLength(p).sequenceId; 156 assertEquals(i, ii); 157 return p; 158 } 159 160 @Test 161 public void testRemoves(TestInfo testInfo) throws IOException { 162 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 163 // Cleanup old tests if any detrius laying around. 164 TableDescriptors htds = new FSTableDescriptors(fs, testDir); 165 TableDescriptor htd = TableDescriptorBuilder 166 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())).build(); 167 htds.update(htd); 168 assertNotNull(htds.remove(htd.getTableName())); 169 assertNull(htds.remove(htd.getTableName())); 170 } 171 172 @Test 173 public void testReadingHTDFromFS(TestInfo testInfo) throws IOException { 174 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 175 TableDescriptor htd = TableDescriptorBuilder 176 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())).build(); 177 FSTableDescriptors fstd = new FSTableDescriptors(fs, testDir); 178 fstd.createTableDescriptor(htd); 179 TableDescriptor td2 = 180 FSTableDescriptors.getTableDescriptorFromFs(fs, testDir, htd.getTableName()); 181 assertTrue(htd.equals(td2)); 182 } 183 184 @Test 185 public void testTableDescriptors(TestInfo testInfo) throws IOException, InterruptedException { 186 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 187 // Cleanup old tests if any debris laying around. 188 FSTableDescriptors htds = new FSTableDescriptors(fs, testDir) { 189 @Override 190 public TableDescriptor get(TableName tablename) { 191 LOG.info(tablename + ", cachehits=" + this.cachehits); 192 return super.get(tablename); 193 } 194 }; 195 final int count = 10; 196 // Write out table infos. 197 for (int i = 0; i < count; i++) { 198 htds.createTableDescriptor(TableDescriptorBuilder 199 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)).build()); 200 } 201 202 for (int i = 0; i < count; i++) { 203 assertTrue(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)) != null); 204 } 205 for (int i = 0; i < count; i++) { 206 assertTrue(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)) != null); 207 } 208 // Update the table infos 209 for (int i = 0; i < count; i++) { 210 TableDescriptorBuilder builder = TableDescriptorBuilder 211 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)); 212 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of("" + i)); 213 htds.update(builder.build()); 214 } 215 // Wait a while so mod time we write is for sure different. 216 Thread.sleep(100); 217 for (int i = 0; i < count; i++) { 218 assertTrue(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)) != null); 219 } 220 for (int i = 0; i < count; i++) { 221 assertTrue(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)) != null); 222 } 223 assertEquals(count * 4, htds.invocations); 224 assertTrue(htds.cachehits >= (count * 2), 225 "expected=" + (count * 2) + ", actual=" + htds.cachehits); 226 } 227 228 @Test 229 public void testTableDescriptorsNoCache(TestInfo testInfo) 230 throws IOException, InterruptedException { 231 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 232 // Cleanup old tests if any debris laying around. 233 FSTableDescriptors htds = new FSTableDescriptorsTest(fs, testDir, false); 234 final int count = 10; 235 // Write out table infos. 236 for (int i = 0; i < count; i++) { 237 htds.createTableDescriptor(TableDescriptorBuilder 238 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)).build()); 239 } 240 241 for (int i = 0; i < 2 * count; i++) { 242 assertNotNull(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i % 2)), 243 "Expected HTD, got null instead"); 244 } 245 // Update the table infos 246 for (int i = 0; i < count; i++) { 247 TableDescriptorBuilder builder = TableDescriptorBuilder 248 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)); 249 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of("" + i)); 250 htds.update(builder.build()); 251 } 252 for (int i = 0; i < count; i++) { 253 assertNotNull(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)), 254 "Expected HTD, got null instead"); 255 assertTrue(htds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)) 256 .hasColumnFamily(Bytes.toBytes("" + i)), "Column Family " + i + " missing"); 257 } 258 assertEquals(count * 4, htds.invocations); 259 assertEquals(0, htds.cachehits, "expected=0, actual=" + htds.cachehits); 260 } 261 262 @Test 263 public void testGetAll() throws IOException, InterruptedException { 264 final String name = "testGetAll"; 265 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 266 // Cleanup old tests if any debris laying around. 267 FSTableDescriptors htds = new FSTableDescriptorsTest(fs, testDir); 268 final int count = 4; 269 // Write out table infos. 270 for (int i = 0; i < count; i++) { 271 htds.createTableDescriptor( 272 TableDescriptorBuilder.newBuilder(TableName.valueOf(name + i)).build()); 273 } 274 // add hbase:meta 275 htds 276 .createTableDescriptor(TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).build()); 277 assertEquals(count + 1, htds.getAll().size(), 278 "getAll() didn't return all TableDescriptors, expected: " + (count + 1) + " got: " 279 + htds.getAll().size()); 280 } 281 282 @Test 283 public void testParallelGetAll() throws IOException, InterruptedException { 284 final String name = "testParallelGetAll"; 285 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 286 // Enable parallel load table descriptor. 287 FSTableDescriptors htds = new FSTableDescriptorsTest(fs, testDir, true, 20); 288 final int count = 100; 289 // Write out table infos. 290 for (int i = 0; i < count; i++) { 291 htds.createTableDescriptor( 292 TableDescriptorBuilder.newBuilder(TableName.valueOf(name + i)).build()); 293 } 294 // add hbase:meta 295 htds 296 .createTableDescriptor(TableDescriptorBuilder.newBuilder(TableName.META_TABLE_NAME).build()); 297 298 int getTableDescriptorSize = htds.getAll().size(); 299 assertEquals(count + 1, getTableDescriptorSize, 300 "getAll() didn't return all TableDescriptors, expected: " + (count + 1) + " got: " 301 + getTableDescriptorSize); 302 303 // get again to check whether the cache works well 304 getTableDescriptorSize = htds.getAll().size(); 305 assertEquals(count + 1, getTableDescriptorSize, 306 "getAll() didn't return all TableDescriptors with cache, expected: " + (count + 1) + " got: " 307 + getTableDescriptorSize); 308 } 309 310 @Test 311 public void testGetAllOrdering() throws Exception { 312 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 313 FSTableDescriptors tds = new FSTableDescriptorsTest(fs, testDir); 314 315 String[] tableNames = new String[] { "foo", "bar", "foo:bar", "bar:foo" }; 316 for (String tableName : tableNames) { 317 tds.createTableDescriptor( 318 TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)).build()); 319 } 320 321 Map<String, TableDescriptor> tables = tds.getAll(); 322 // Remove hbase:meta from list. It shows up now since we made it dynamic. The schema 323 // is written into the fs by the FSTableDescriptors constructor now where before it 324 // didn't. 325 tables.remove(TableName.META_TABLE_NAME.getNameAsString()); 326 assertEquals(4, tables.size()); 327 328 String[] tableNamesOrdered = 329 new String[] { "bar:foo", "default:bar", "default:foo", "foo:bar" }; 330 int i = 0; 331 for (Map.Entry<String, TableDescriptor> entry : tables.entrySet()) { 332 assertEquals(tableNamesOrdered[i], entry.getKey()); 333 assertEquals(tableNamesOrdered[i], 334 entry.getValue().getTableName().getNameWithNamespaceInclAsString()); 335 i++; 336 } 337 } 338 339 @Test 340 public void testCacheConsistency(TestInfo testInfo) throws IOException, InterruptedException { 341 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 342 // Cleanup old tests if any debris laying around. 343 FSTableDescriptors chtds = new FSTableDescriptorsTest(fs, testDir); 344 FSTableDescriptors nonchtds = new FSTableDescriptorsTest(fs, testDir, false); 345 346 final int count = 10; 347 // Write out table infos via non-cached FSTableDescriptors 348 for (int i = 0; i < count; i++) { 349 nonchtds.createTableDescriptor(TableDescriptorBuilder 350 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)).build()); 351 } 352 353 // Calls to getAll() won't increase the cache counter, do per table. 354 for (int i = 0; i < count; i++) { 355 assertTrue( 356 chtds.get(TableName.valueOf(testInfo.getTestMethod().get().getName() + i)) != null); 357 } 358 359 assertTrue(nonchtds.getAll().size() == chtds.getAll().size()); 360 361 // add a new entry for random table name. 362 TableName random = TableName.valueOf("random"); 363 TableDescriptor htd = TableDescriptorBuilder.newBuilder(random).build(); 364 nonchtds.createTableDescriptor(htd); 365 366 // random will only increase the cachehit by 1 367 assertEquals(nonchtds.getAll().size(), chtds.getAll().size() + 1); 368 369 for (Map.Entry<String, TableDescriptor> entry : chtds.getAll().entrySet()) { 370 String t = (String) entry.getKey(); 371 TableDescriptor nchtd = entry.getValue(); 372 assertTrue((nchtd.equals(chtds.get(TableName.valueOf(t)))), 373 "expected " + htd.toString() + " got: " + chtds.get(TableName.valueOf(t)).toString()); 374 } 375 // this is by design, for FSTableDescriptor with cache enabled, once we have done a full scan 376 // and load all the table descriptors to cache, we will not go to file system again, as the only 377 // way to update table descriptor is to through us so we can cache it when updating. 378 assertNotNull(nonchtds.get(random)); 379 assertNull(chtds.get(random)); 380 } 381 382 @Test 383 public void testNoSuchTable() throws IOException { 384 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 385 // Cleanup old tests if any detrius laying around. 386 TableDescriptors htds = new FSTableDescriptors(fs, testDir); 387 assertNull(htds.get(TableName.valueOf("NoSuchTable")), 388 "There shouldn't be any HTD for this table"); 389 } 390 391 @Test 392 public void testUpdates(TestInfo testInfo) throws IOException { 393 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 394 // Cleanup old tests if any detrius laying around. 395 TableDescriptors htds = new FSTableDescriptors(fs, testDir); 396 TableDescriptor htd = TableDescriptorBuilder 397 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())).build(); 398 htds.update(htd); 399 htds.update(htd); 400 htds.update(htd); 401 } 402 403 @Test 404 public void testTableInfoFileStatusComparator() { 405 FileStatus bare = new FileStatus(0, false, 0, 0, -1, 406 new Path("/tmp", FSTableDescriptors.TABLEINFO_FILE_PREFIX)); 407 FileStatus future = new FileStatus(0, false, 0, 0, -1, 408 new Path("/tmp/tablinfo." + EnvironmentEdgeManager.currentTime())); 409 FileStatus farFuture = new FileStatus(0, false, 0, 0, -1, 410 new Path("/tmp/tablinfo." + EnvironmentEdgeManager.currentTime() + 1000)); 411 FileStatus[] alist = { bare, future, farFuture }; 412 FileStatus[] blist = { bare, farFuture, future }; 413 FileStatus[] clist = { farFuture, bare, future }; 414 Comparator<FileStatus> c = FSTableDescriptors.TABLEINFO_FILESTATUS_COMPARATOR; 415 Arrays.sort(alist, c); 416 Arrays.sort(blist, c); 417 Arrays.sort(clist, c); 418 // Now assert all sorted same in way we want. 419 for (int i = 0; i < alist.length; i++) { 420 assertTrue(alist[i].equals(blist[i])); 421 assertTrue(blist[i].equals(clist[i])); 422 assertTrue(clist[i].equals(i == 0 ? farFuture : i == 1 ? future : bare)); 423 } 424 } 425 426 @Test 427 public void testReadingInvalidDirectoryFromFS() throws IOException { 428 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 429 try { 430 new FSTableDescriptors(fs, CommonFSUtils.getRootDir(UTIL.getConfiguration())) 431 .get(TableName.valueOf(HConstants.HBASE_TEMP_DIRECTORY)); 432 fail("Shouldn't be able to read a table descriptor for the archive directory."); 433 } catch (Exception e) { 434 LOG.debug("Correctly got error when reading a table descriptor from the archive directory: " 435 + e.getMessage()); 436 } 437 } 438 439 @Test 440 public void testCreateTableDescriptorUpdatesIfExistsAlready(TestInfo testInfo) 441 throws IOException { 442 TableDescriptor htd = TableDescriptorBuilder 443 .newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())).build(); 444 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 445 FSTableDescriptors fstd = new FSTableDescriptors(fs, testDir); 446 assertTrue(fstd.createTableDescriptor(htd)); 447 assertFalse(fstd.createTableDescriptor(htd)); 448 htd = TableDescriptorBuilder.newBuilder(htd) 449 .setValue(Bytes.toBytes("mykey"), Bytes.toBytes("myValue")).build(); 450 assertTrue(fstd.createTableDescriptor(htd)); // this will re-create 451 Path tableDir = CommonFSUtils.getTableDir(testDir, htd.getTableName()); 452 assertEquals(htd, FSTableDescriptors.getTableDescriptorFromFs(fs, tableDir)); 453 } 454 455 @Test 456 public void testIgnoreBrokenTableDescriptorFiles(TestInfo testInfo) throws IOException { 457 TableDescriptor htd = 458 TableDescriptorBuilder.newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())) 459 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf")).build(); 460 TableDescriptor newHtd = 461 TableDescriptorBuilder.newBuilder(TableName.valueOf(testInfo.getTestMethod().get().getName())) 462 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("cf2")).build(); 463 assertNotEquals(newHtd, htd); 464 FileSystem fs = FileSystem.get(UTIL.getConfiguration()); 465 FSTableDescriptors fstd = new FSTableDescriptors(fs, testDir, false, false); 466 fstd.update(htd); 467 byte[] bytes = TableDescriptorBuilder.toByteArray(newHtd); 468 Path tableDir = CommonFSUtils.getTableDir(testDir, htd.getTableName()); 469 Path tableInfoDir = new Path(tableDir, FSTableDescriptors.TABLEINFO_DIR); 470 FileStatus[] statuses = fs.listStatus(tableInfoDir); 471 assertEquals(1, statuses.length); 472 int seqId = 473 FSTableDescriptors.getTableInfoSequenceIdAndFileLength(statuses[0].getPath()).sequenceId + 1; 474 Path brokenFile = new Path(tableInfoDir, FSTableDescriptors.getTableInfoFileName(seqId, bytes)); 475 try (FSDataOutputStream out = fs.create(brokenFile)) { 476 out.write(bytes, 0, bytes.length / 2); 477 } 478 assertTrue(fs.exists(brokenFile)); 479 TableDescriptor getTd = fstd.get(htd.getTableName()); 480 assertEquals(htd, getTd); 481 assertFalse(fs.exists(brokenFile)); 482 } 483 484 private static class FSTableDescriptorsTest extends FSTableDescriptors { 485 486 public FSTableDescriptorsTest(FileSystem fs, Path rootdir) { 487 this(fs, rootdir, true); 488 } 489 490 public FSTableDescriptorsTest(FileSystem fs, Path rootdir, boolean usecache) { 491 super(fs, rootdir, false, usecache); 492 } 493 494 public FSTableDescriptorsTest(FileSystem fs, Path rootdir, boolean usecache, 495 int tableDescriptorParallelLoadThreads) { 496 super(fs, rootdir, false, usecache, tableDescriptorParallelLoadThreads); 497 } 498 499 @Override 500 public TableDescriptor get(TableName tablename) { 501 LOG.info((super.isUsecache() ? "Cached" : "Non-Cached") + " TableDescriptor.get() on " 502 + tablename + ", cachehits=" + this.cachehits); 503 return super.get(tablename); 504 } 505 } 506}