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.master.region; 019 020import static org.apache.hadoop.hbase.HConstants.HREGION_LOGDIR_NAME; 021 022import com.google.errorprone.annotations.RestrictedApi; 023import java.io.IOException; 024import java.util.List; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.fs.FileStatus; 027import org.apache.hadoop.fs.FileSystem; 028import org.apache.hadoop.fs.Path; 029import org.apache.hadoop.hbase.HBaseIOException; 030import org.apache.hadoop.hbase.RegionTooBusyException; 031import org.apache.hadoop.hbase.Server; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 034import org.apache.hadoop.hbase.client.ConnectionUtils; 035import org.apache.hadoop.hbase.client.Get; 036import org.apache.hadoop.hbase.client.RegionInfo; 037import org.apache.hadoop.hbase.client.RegionInfoBuilder; 038import org.apache.hadoop.hbase.client.Result; 039import org.apache.hadoop.hbase.client.ResultScanner; 040import org.apache.hadoop.hbase.client.Scan; 041import org.apache.hadoop.hbase.client.TableDescriptor; 042import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 043import org.apache.hadoop.hbase.log.HBaseMarkers; 044import org.apache.hadoop.hbase.regionserver.HRegion; 045import org.apache.hadoop.hbase.regionserver.HRegion.FlushResult; 046import org.apache.hadoop.hbase.regionserver.HRegionFileSystem; 047import org.apache.hadoop.hbase.regionserver.RegionScanner; 048import org.apache.hadoop.hbase.regionserver.StoreFileInfo; 049import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTracker; 050import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory; 051import org.apache.hadoop.hbase.regionserver.wal.AbstractFSWAL; 052import org.apache.hadoop.hbase.regionserver.wal.WALSyncTimeoutIOException; 053import org.apache.hadoop.hbase.util.Bytes; 054import org.apache.hadoop.hbase.util.CommonFSUtils; 055import org.apache.hadoop.hbase.util.FSTableDescriptors; 056import org.apache.hadoop.hbase.util.FSUtils; 057import org.apache.hadoop.hbase.util.HFileArchiveUtil; 058import org.apache.hadoop.hbase.util.RecoverLeaseFSUtils; 059import org.apache.hadoop.hbase.util.Threads; 060import org.apache.hadoop.hbase.wal.AbstractFSWALProvider; 061import org.apache.hadoop.hbase.wal.WAL; 062import org.apache.hadoop.hbase.wal.WALFactory; 063import org.apache.yetus.audience.InterfaceAudience; 064import org.slf4j.Logger; 065import org.slf4j.LoggerFactory; 066 067import org.apache.hbase.thirdparty.com.google.common.math.IntMath; 068 069/** 070 * A region that stores data in a separated directory, which can be used to store master local data. 071 * <p/> 072 * FileSystem layout: 073 * 074 * <pre> 075 * hbase 076 * | 077 * --<region dir> 078 * | 079 * --data 080 * | | 081 * | --/<ns>/<table>/<encoded-region-name> <---- The region data 082 * | | 083 * | --replay <---- The edits to replay 084 * | 085 * --WALs 086 * | 087 * --<master-server-name> <---- The WAL dir for active master 088 * | 089 * --<master-server-name>-dead <---- The WAL dir for dead master 090 * </pre> 091 * 092 * Notice that, you can use different root file system and WAL file system. Then the above directory 093 * will be on two file systems, the root file system will have the data directory while the WAL 094 * filesystem will have the WALs directory. The archived HFile will be moved to the global HFile 095 * archived directory with the {@link MasterRegionParams#archivedHFileSuffix()} suffix. The archived 096 * WAL will be moved to the global WAL archived directory with the 097 * {@link MasterRegionParams#archivedWalSuffix()} suffix. 098 */ 099@InterfaceAudience.Private 100public final class MasterRegion { 101 102 private static final Logger LOG = LoggerFactory.getLogger(MasterRegion.class); 103 104 private static final String REPLAY_EDITS_DIR = "recovered.wals"; 105 106 private static final String DEAD_WAL_DIR_SUFFIX = "-dead"; 107 108 static final String INITIALIZING_FLAG = ".initializing"; 109 110 static final String INITIALIZED_FLAG = ".initialized"; 111 112 private static final int REGION_ID = 1; 113 114 private final Server server; 115 116 private final WALFactory walFactory; 117 118 final HRegion region; 119 120 final MasterRegionFlusherAndCompactor flusherAndCompactor; 121 122 private MasterRegionWALRoller walRoller; 123 124 private final int maxRetriesForRegionUpdates; 125 126 private final long regionUpdateRetryPauseTime; 127 128 private MasterRegion(Server server, HRegion region, WALFactory walFactory, 129 MasterRegionFlusherAndCompactor flusherAndCompactor, MasterRegionWALRoller walRoller) { 130 this.server = server; 131 this.region = region; 132 this.walFactory = walFactory; 133 this.flusherAndCompactor = flusherAndCompactor; 134 this.walRoller = walRoller; 135 this.maxRetriesForRegionUpdates = 136 server.getConfiguration().getInt("hbase.master.region.update.max.retries", 9); 137 this.regionUpdateRetryPauseTime = 138 server.getConfiguration().getLong("hbase.master.region.update.retry.pause", 100); 139 } 140 141 private void closeRegion(boolean abort) { 142 try { 143 region.close(abort); 144 } catch (IOException e) { 145 LOG.warn("Failed to close region", e); 146 } 147 } 148 149 private void shutdownWAL() { 150 try { 151 walFactory.shutdown(); 152 } catch (IOException e) { 153 LOG.warn("Failed to shutdown WAL", e); 154 } 155 } 156 157 /** 158 * Performs the mutation to the master region using UpdateMasterRegion update action. 159 * @param action Update region action. 160 * @throws IOException IO error that causes active master to abort. 161 */ 162 public void update(UpdateMasterRegion action) throws IOException { 163 for (int tries = 0; tries < maxRetriesForRegionUpdates; tries++) { 164 try { 165 // If the update is successful, return immediately. 166 action.update(region); 167 flusherAndCompactor.onUpdate(); 168 return; 169 } catch (RegionTooBusyException e) { 170 // RegionTooBusyException is the type of IOException for which we can retry 171 // for few times before aborting the active master. The master region might 172 // have genuine case for delayed flushes and/or some procedure bug causing 173 // heavy pressure on the memstore. 174 flusherAndCompactor.onUpdate(); 175 if (tries == (maxRetriesForRegionUpdates - 1)) { 176 abortServer(e); 177 } 178 LOG.info("Master region {} is too busy... retry attempt: {}", region, tries); 179 // Exponential backoff is performed by ConnectionUtils.getPauseTime(). 180 // It uses HConstants.RETRY_BACKOFF array for the backoff multiplier, the 181 // same array is used as backoff multiplier with RPC retries. 182 Threads.sleep(ConnectionUtils.getPauseTime(regionUpdateRetryPauseTime, tries)); 183 } catch (IOException e) { 184 // We catch IOException here to ensure that if the mutation is not successful 185 // even after the internal retries done within AbstractFSWAL, we better abort 186 // the active master so that the new active master can take care of resuming 187 // the procedure state which could not be persisted successfully by previously 188 // aborted master. Refer to Jira: HBASE-29251. 189 abortServer(e); 190 } 191 } 192 } 193 194 /** 195 * Log the error and abort the master daemon immediately. Use this utility only when procedure 196 * state store update fails and the only way to recover is by terminating the active master so 197 * that new failed-over active master can resume the procedure execution. 198 * @param e IO error that causes active master to abort. 199 * @throws IOException IO error that causes active master to abort. 200 */ 201 private void abortServer(IOException e) throws IOException { 202 LOG.error(HBaseMarkers.FATAL, 203 "MasterRegion update is not successful. Aborting server to let new active master " 204 + "resume failed proc store update."); 205 server.abort("MasterRegion update is not successful", e); 206 throw e; 207 } 208 209 public Result get(Get get) throws IOException { 210 return region.get(get); 211 } 212 213 public ResultScanner getScanner(Scan scan) throws IOException { 214 return new RegionScannerAsResultScanner(region.getScanner(scan)); 215 } 216 217 public RegionScanner getRegionScanner(Scan scan) throws IOException { 218 return region.getScanner(scan); 219 } 220 221 public FlushResult flush(boolean force) throws IOException { 222 try { 223 flusherAndCompactor.resetChangesAfterLastFlush(); 224 FlushResult flushResult = region.flush(force); 225 flusherAndCompactor.recordLastFlushTime(); 226 return flushResult; 227 } catch (WALSyncTimeoutIOException e) { 228 LOG.error(HBaseMarkers.FATAL, "WAL sync timeout. Aborting server."); 229 server.abort("WAL sync timeout", e); 230 throw e; 231 } 232 } 233 234 @RestrictedApi(explanation = "Should only be called in tests", link = "", 235 allowedOnPath = ".*/src/test/.*") 236 public void requestRollAll() { 237 walRoller.requestRollAll(); 238 } 239 240 @RestrictedApi(explanation = "Should only be called in tests", link = "", 241 allowedOnPath = ".*/src/test/.*") 242 public void waitUntilWalRollFinished() throws InterruptedException { 243 walRoller.waitUntilWalRollFinished(); 244 } 245 246 public void close(boolean abort) { 247 LOG.info("Closing local region {}, isAbort={}", region.getRegionInfo(), abort); 248 if (flusherAndCompactor != null) { 249 flusherAndCompactor.close(); 250 } 251 // if abort, we shutdown wal first to fail the ongoing updates to the region, and then close the 252 // region, otherwise there will be dead lock. 253 if (abort) { 254 shutdownWAL(); 255 closeRegion(true); 256 } else { 257 closeRegion(false); 258 shutdownWAL(); 259 } 260 261 if (walRoller != null) { 262 walRoller.close(); 263 } 264 } 265 266 private static WAL createWAL(WALFactory walFactory, MasterRegionWALRoller walRoller, 267 String serverName, FileSystem walFs, Path walRootDir, RegionInfo regionInfo) 268 throws IOException { 269 String logName = AbstractFSWALProvider.getWALDirectoryName(serverName); 270 Path walDir = new Path(walRootDir, logName); 271 LOG.debug("WALDir={}", walDir); 272 if (walFs.exists(walDir)) { 273 throw new HBaseIOException( 274 "Already created wal directory at " + walDir + " for local region " + regionInfo); 275 } 276 if (!walFs.mkdirs(walDir)) { 277 throw new IOException( 278 "Can not create wal directory " + walDir + " for local region " + regionInfo); 279 } 280 WAL wal = walFactory.getWAL(regionInfo); 281 walRoller.addWAL(wal); 282 return wal; 283 } 284 285 private static HRegion bootstrap(Configuration conf, TableDescriptor td, FileSystem fs, 286 Path rootDir, FileSystem walFs, Path walRootDir, WALFactory walFactory, 287 MasterRegionWALRoller walRoller, String serverName, boolean touchInitializingFlag) 288 throws IOException { 289 TableName tn = td.getTableName(); 290 RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tn).setRegionId(REGION_ID).build(); 291 Path tableDir = CommonFSUtils.getTableDir(rootDir, tn); 292 // persist table descriptor 293 FSTableDescriptors.createTableDescriptorForTableDirectory(fs, tableDir, td, true); 294 HRegion.createHRegion(conf, regionInfo, fs, tableDir, td).close(); 295 Path initializedFlag = new Path(tableDir, INITIALIZED_FLAG); 296 if (!fs.mkdirs(initializedFlag)) { 297 throw new IOException("Can not touch initialized flag: " + initializedFlag); 298 } 299 Path initializingFlag = new Path(tableDir, INITIALIZING_FLAG); 300 if (!fs.delete(initializingFlag, true)) { 301 LOG.warn("failed to clean up initializing flag: " + initializingFlag); 302 } 303 WAL wal = createWAL(walFactory, walRoller, serverName, walFs, walRootDir, regionInfo); 304 return HRegion.openHRegionFromTableDir(conf, fs, tableDir, regionInfo, td, wal, null, null); 305 } 306 307 private static RegionInfo loadRegionInfo(FileSystem fs, Path tableDir) throws IOException { 308 Path regionDir = 309 fs.listStatus(tableDir, p -> RegionInfo.isEncodedRegionName(Bytes.toBytes(p.getName())))[0] 310 .getPath(); 311 return HRegionFileSystem.loadRegionInfoFileContent(fs, regionDir); 312 } 313 314 private static HRegion open(Configuration conf, TableDescriptor td, RegionInfo regionInfo, 315 FileSystem fs, Path rootDir, FileSystem walFs, Path walRootDir, WALFactory walFactory, 316 MasterRegionWALRoller walRoller, String serverName) throws IOException { 317 Path tableDir = CommonFSUtils.getTableDir(rootDir, td.getTableName()); 318 Path walRegionDir = FSUtils.getRegionDirFromRootDir(walRootDir, regionInfo); 319 Path replayEditsDir = new Path(walRegionDir, REPLAY_EDITS_DIR); 320 if (!walFs.exists(replayEditsDir) && !walFs.mkdirs(replayEditsDir)) { 321 throw new IOException("Failed to create replay directory: " + replayEditsDir); 322 } 323 324 // Replay any WALs for the Master Region before opening it. 325 Path walsDir = new Path(walRootDir, HREGION_LOGDIR_NAME); 326 // In open(...), we expect that the WAL directory for the MasterRegion to already exist. 327 // This is in contrast to bootstrap() where we create the MasterRegion data and WAL dir. 328 // However, it's possible that users directly remove the WAL directory. We expect walsDir 329 // to always exist in normal situations, but we should guard against users changing the 330 // filesystem outside of HBase's line of sight. 331 if (walFs.exists(walsDir)) { 332 replayWALs(conf, walFs, walRootDir, walsDir, regionInfo, serverName, replayEditsDir); 333 } else { 334 LOG.error( 335 "UNEXPECTED: WAL directory for MasterRegion is missing." + " {} is unexpectedly missing.", 336 walsDir); 337 } 338 339 // Create a new WAL 340 WAL wal = createWAL(walFactory, walRoller, serverName, walFs, walRootDir, regionInfo); 341 conf.set(HRegion.SPECIAL_RECOVERED_EDITS_DIR, 342 replayEditsDir.makeQualified(walFs.getUri(), walFs.getWorkingDirectory()).toString()); 343 // we do not do WAL splitting here so it is possible to have uncleanly closed WAL files, so we 344 // need to ignore EOFException. 345 conf.setBoolean(HRegion.RECOVERED_EDITS_IGNORE_EOF, true); 346 return HRegion.openHRegionFromTableDir(conf, fs, tableDir, regionInfo, td, wal, null, null); 347 } 348 349 private static void replayWALs(Configuration conf, FileSystem walFs, Path walRootDir, 350 Path walsDir, RegionInfo regionInfo, String serverName, Path replayEditsDir) 351 throws IOException { 352 for (FileStatus walDir : walFs.listStatus(walsDir)) { 353 if (!walDir.isDirectory()) { 354 continue; 355 } 356 if (walDir.getPath().getName().startsWith(serverName)) { 357 LOG.warn("This should not happen in real production as we have not created our WAL " 358 + "directory yet, ignore if you are running a local region related UT"); 359 } 360 Path deadWALDir; 361 if (!walDir.getPath().getName().endsWith(DEAD_WAL_DIR_SUFFIX)) { 362 deadWALDir = 363 new Path(walDir.getPath().getParent(), walDir.getPath().getName() + DEAD_WAL_DIR_SUFFIX); 364 if (!walFs.rename(walDir.getPath(), deadWALDir)) { 365 throw new IOException("Can not rename " + walDir + " to " + deadWALDir 366 + " when recovering lease of proc store"); 367 } 368 LOG.info("Renamed {} to {} as it is dead", walDir.getPath(), deadWALDir); 369 } else { 370 deadWALDir = walDir.getPath(); 371 LOG.info("{} is already marked as dead", deadWALDir); 372 } 373 for (FileStatus walFile : walFs.listStatus(deadWALDir)) { 374 Path replayEditsFile = new Path(replayEditsDir, walFile.getPath().getName()); 375 RecoverLeaseFSUtils.recoverFileLease(walFs, walFile.getPath(), conf); 376 if (!walFs.rename(walFile.getPath(), replayEditsFile)) { 377 throw new IOException("Can not rename " + walFile.getPath() + " to " + replayEditsFile 378 + " when recovering lease for local region"); 379 } 380 LOG.info("Renamed {} to {}", walFile.getPath(), replayEditsFile); 381 } 382 LOG.info("Delete empty local region wal dir {}", deadWALDir); 383 walFs.delete(deadWALDir, true); 384 } 385 } 386 387 private static void tryMigrate(Configuration conf, FileSystem fs, Path tableDir, 388 RegionInfo regionInfo, TableDescriptor oldTd, TableDescriptor newTd) throws IOException { 389 Class<? extends StoreFileTracker> oldSft = 390 StoreFileTrackerFactory.getTrackerClass(oldTd.getValue(StoreFileTrackerFactory.TRACKER_IMPL)); 391 Class<? extends StoreFileTracker> newSft = 392 StoreFileTrackerFactory.getTrackerClass(newTd.getValue(StoreFileTrackerFactory.TRACKER_IMPL)); 393 if (oldSft.equals(newSft)) { 394 LOG.debug("old store file tracker {} is the same with new store file tracker, skip migration", 395 StoreFileTrackerFactory.getStoreFileTrackerName(oldSft)); 396 if (!oldTd.equals(newTd)) { 397 // we may change other things such as adding a new family, so here we still need to persist 398 // the new table descriptor 399 LOG.info("Update table descriptor from {} to {}", oldTd, newTd); 400 FSTableDescriptors.createTableDescriptorForTableDirectory(fs, tableDir, newTd, true); 401 } 402 return; 403 } 404 LOG.info("Migrate store file tracker from {} to {}", oldSft.getSimpleName(), 405 newSft.getSimpleName()); 406 HRegionFileSystem hfs = 407 HRegionFileSystem.openRegionFromFileSystem(conf, fs, tableDir, regionInfo, false); 408 for (ColumnFamilyDescriptor oldCfd : oldTd.getColumnFamilies()) { 409 StoreFileTracker oldTracker = StoreFileTrackerFactory.create(conf, oldTd, oldCfd, hfs); 410 StoreFileTracker newTracker = StoreFileTrackerFactory.create(conf, oldTd, oldCfd, hfs); 411 List<StoreFileInfo> files = oldTracker.load(); 412 LOG.debug("Store file list for {}: {}", oldCfd.getNameAsString(), files); 413 newTracker.set(oldTracker.load()); 414 } 415 // persist the new table descriptor after migration 416 LOG.info("Update table descriptor from {} to {}", oldTd, newTd); 417 FSTableDescriptors.createTableDescriptorForTableDirectory(fs, tableDir, newTd, true); 418 } 419 420 public static MasterRegion create(MasterRegionParams params) throws IOException { 421 TableDescriptor td = params.tableDescriptor(); 422 LOG.info("Create or load local region for table " + td); 423 Server server = params.server(); 424 Configuration baseConf = server.getConfiguration(); 425 FileSystem fs = CommonFSUtils.getRootDirFileSystem(baseConf); 426 FileSystem walFs = CommonFSUtils.getWALFileSystem(baseConf); 427 Path globalRootDir = CommonFSUtils.getRootDir(baseConf); 428 Path globalWALRootDir = CommonFSUtils.getWALRootDir(baseConf); 429 Path rootDir = new Path(globalRootDir, params.regionDirName()); 430 Path walRootDir = new Path(globalWALRootDir, params.regionDirName()); 431 // we will override some configurations so create a new one. 432 Configuration conf = new Configuration(baseConf); 433 CommonFSUtils.setRootDir(conf, rootDir); 434 CommonFSUtils.setWALRootDir(conf, walRootDir); 435 MasterRegionFlusherAndCompactor.setupConf(conf, params.flushSize(), params.flushPerChanges(), 436 params.flushIntervalMs()); 437 conf.setInt(AbstractFSWAL.MAX_LOGS, params.maxWals()); 438 if (params.useHsync() != null) { 439 conf.setBoolean(HRegion.WAL_HSYNC_CONF_KEY, params.useHsync()); 440 } 441 if (params.useMetaCellComparator() != null) { 442 conf.setBoolean(HRegion.USE_META_CELL_COMPARATOR, params.useMetaCellComparator()); 443 } 444 conf.setInt(AbstractFSWAL.RING_BUFFER_SLOT_COUNT, 445 IntMath.ceilingPowerOfTwo(params.ringBufferSlotCount())); 446 447 MasterRegionWALRoller walRoller = MasterRegionWALRoller.create( 448 td.getTableName() + "-WAL-Roller", conf, server, walFs, walRootDir, globalWALRootDir, 449 params.archivedWalSuffix(), params.rollPeriodMs(), params.flushSize()); 450 walRoller.start(); 451 452 WALFactory walFactory = new WALFactory(conf, server.getServerName(), server); 453 Path tableDir = CommonFSUtils.getTableDir(rootDir, td.getTableName()); 454 Path initializingFlag = new Path(tableDir, INITIALIZING_FLAG); 455 Path initializedFlag = new Path(tableDir, INITIALIZED_FLAG); 456 HRegion region; 457 if (!fs.exists(tableDir)) { 458 // bootstrap, no doubt 459 if (!fs.mkdirs(initializedFlag)) { 460 throw new IOException("Can not touch initialized flag"); 461 } 462 region = bootstrap(conf, td, fs, rootDir, walFs, walRootDir, walFactory, walRoller, 463 server.getServerName().toString(), true); 464 } else { 465 if (!fs.exists(initializedFlag)) { 466 if (!fs.exists(initializingFlag)) { 467 // should be old style, where we do not have the initializing or initialized file, persist 468 // the table descriptor, touch the initialized flag and then open the region. 469 // the store file tracker must be DEFAULT 470 LOG.info("No {} or {} file, try upgrading", INITIALIZING_FLAG, INITIALIZED_FLAG); 471 TableDescriptor oldTd = 472 TableDescriptorBuilder.newBuilder(td).setValue(StoreFileTrackerFactory.TRACKER_IMPL, 473 StoreFileTrackerFactory.Trackers.DEFAULT.name()).build(); 474 FSTableDescriptors.createTableDescriptorForTableDirectory(fs, tableDir, oldTd, true); 475 if (!fs.mkdirs(initializedFlag)) { 476 throw new IOException("Can not touch initialized flag: " + initializedFlag); 477 } 478 RegionInfo regionInfo = loadRegionInfo(fs, tableDir); 479 tryMigrate(conf, fs, tableDir, regionInfo, oldTd, td); 480 region = open(conf, td, regionInfo, fs, rootDir, walFs, walRootDir, walFactory, walRoller, 481 server.getServerName().toString()); 482 } else { 483 // delete all contents besides the initializing flag, here we can make sure tableDir 484 // exists(unless someone delete it manually...), so we do not do null check here. 485 for (FileStatus status : fs.listStatus(tableDir)) { 486 if (!status.getPath().getName().equals(INITIALIZING_FLAG)) { 487 fs.delete(status.getPath(), true); 488 } 489 } 490 region = bootstrap(conf, td, fs, rootDir, walFs, walRootDir, walFactory, walRoller, 491 server.getServerName().toString(), false); 492 } 493 } else { 494 if (fs.exists(initializingFlag) && !fs.delete(initializingFlag, true)) { 495 LOG.warn("failed to clean up initializing flag: " + initializingFlag); 496 } 497 // open it, make sure to load the table descriptor from fs 498 TableDescriptor oldTd = FSTableDescriptors.getTableDescriptorFromFs(fs, tableDir); 499 RegionInfo regionInfo = loadRegionInfo(fs, tableDir); 500 tryMigrate(conf, fs, tableDir, regionInfo, oldTd, td); 501 region = open(conf, td, regionInfo, fs, rootDir, walFs, walRootDir, walFactory, walRoller, 502 server.getServerName().toString()); 503 } 504 } 505 506 Path globalArchiveDir = HFileArchiveUtil.getArchivePath(baseConf); 507 MasterRegionFlusherAndCompactor flusherAndCompactor = new MasterRegionFlusherAndCompactor(conf, 508 server, region, params.flushSize(), params.flushPerChanges(), params.flushIntervalMs(), 509 params.compactMin(), globalArchiveDir, params.archivedHFileSuffix()); 510 walRoller.setFlusherAndCompactor(flusherAndCompactor); 511 Path archiveDir = HFileArchiveUtil.getArchivePath(conf); 512 if (!fs.mkdirs(archiveDir)) { 513 LOG.warn("Failed to create archive directory {}. Usually this should not happen but it will" 514 + " be created again when we actually archive the hfiles later, so continue", archiveDir); 515 } 516 return new MasterRegion(server, region, walFactory, flusherAndCompactor, walRoller); 517 } 518}