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