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.procedure; 019 020import com.google.errorprone.annotations.RestrictedApi; 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Map; 027import org.apache.hadoop.conf.Configuration; 028import org.apache.hadoop.fs.FileSystem; 029import org.apache.hadoop.fs.Path; 030import org.apache.hadoop.hbase.DoNotRetryIOException; 031import org.apache.hadoop.hbase.HBaseIOException; 032import org.apache.hadoop.hbase.MetaTableAccessor; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.TableNotFoundException; 035import org.apache.hadoop.hbase.client.Connection; 036import org.apache.hadoop.hbase.client.RegionInfo; 037import org.apache.hadoop.hbase.client.RegionReplicaUtil; 038import org.apache.hadoop.hbase.client.TableDescriptor; 039import org.apache.hadoop.hbase.errorhandling.ForeignException; 040import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher; 041import org.apache.hadoop.hbase.favored.FavoredNodesManager; 042import org.apache.hadoop.hbase.fs.ErasureCodingUtils; 043import org.apache.hadoop.hbase.master.MasterFileSystem; 044import org.apache.hadoop.hbase.master.MetricsSnapshot; 045import org.apache.hadoop.hbase.master.RegionState; 046import org.apache.hadoop.hbase.master.assignment.AssignmentManager; 047import org.apache.hadoop.hbase.monitoring.MonitoredTask; 048import org.apache.hadoop.hbase.monitoring.TaskMonitor; 049import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer; 050import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils; 051import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper; 052import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils; 053import org.apache.hadoop.hbase.snapshot.SnapshotManifest; 054import org.apache.hadoop.hbase.snapshot.SnapshotTTLExpiredException; 055import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 056import org.apache.hadoop.hbase.util.Pair; 057import org.apache.yetus.audience.InterfaceAudience; 058import org.slf4j.Logger; 059import org.slf4j.LoggerFactory; 060 061import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 062import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 063import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RestoreParentToChildRegionsPair; 064import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RestoreSnapshotState; 065import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RestoreSnapshotStateData; 066import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription; 067 068@InterfaceAudience.Private 069public class RestoreSnapshotProcedure 070 extends AbstractStateMachineTableProcedure<RestoreSnapshotState> { 071 private static final Logger LOG = LoggerFactory.getLogger(RestoreSnapshotProcedure.class); 072 073 private TableDescriptor oldTableDescriptor; 074 private TableDescriptor modifiedTableDescriptor; 075 private List<RegionInfo> regionsToRestore = null; 076 private List<RegionInfo> regionsToRemove = null; 077 private List<RegionInfo> regionsToAdd = null; 078 private Map<String, Pair<String, String>> parentsToChildrenPairMap = new HashMap<>(); 079 080 private SnapshotDescription snapshot; 081 private boolean restoreAcl; 082 083 // Monitor 084 private MonitoredTask monitorStatus = null; 085 086 /** 087 * Constructor (for failover) 088 */ 089 public RestoreSnapshotProcedure() { 090 } 091 092 public RestoreSnapshotProcedure(final MasterProcedureEnv env, 093 final TableDescriptor tableDescriptor, final SnapshotDescription snapshot) 094 throws HBaseIOException { 095 this(env, tableDescriptor, snapshot, false); 096 } 097 098 public RestoreSnapshotProcedure(final MasterProcedureEnv env, 099 final TableDescriptor tableDescriptor, final SnapshotDescription snapshot, 100 final boolean restoreAcl) throws HBaseIOException { 101 this(env, tableDescriptor, tableDescriptor, snapshot, restoreAcl); 102 } 103 104 /** 105 * Constructor 106 * @param env MasterProcedureEnv 107 * @param modifiedTableDescriptor the table to operate on 108 * @param snapshot snapshot to restore from 109 */ 110 public RestoreSnapshotProcedure(final MasterProcedureEnv env, 111 final TableDescriptor oldTableDescriptor, final TableDescriptor modifiedTableDescriptor, 112 final SnapshotDescription snapshot, final boolean restoreAcl) throws HBaseIOException { 113 super(env); 114 this.oldTableDescriptor = oldTableDescriptor; 115 // This is the new schema we are going to write out as this modification. 116 this.modifiedTableDescriptor = modifiedTableDescriptor; 117 preflightChecks(env, null/* Table can be online when restore is called? */); 118 // Snapshot information 119 this.snapshot = snapshot; 120 this.restoreAcl = restoreAcl; 121 122 // Monitor 123 getMonitorStatus(); 124 } 125 126 /** 127 * Set up monitor status if it is not created. 128 */ 129 private MonitoredTask getMonitorStatus() { 130 if (monitorStatus == null) { 131 monitorStatus = TaskMonitor.get().createStatus( 132 "Restoring snapshot '" + snapshot.getName() + "' to table " + getTableName()); 133 } 134 return monitorStatus; 135 } 136 137 @Override 138 protected Flow executeFromState(final MasterProcedureEnv env, final RestoreSnapshotState state) 139 throws InterruptedException { 140 LOG.trace("{} execute state={}", this, state); 141 142 // Make sure that the monitor status is set up 143 getMonitorStatus(); 144 145 try { 146 switch (state) { 147 case RESTORE_SNAPSHOT_PRE_OPERATION: 148 // Verify if we can restore the table 149 prepareRestore(env); 150 setNextState(RestoreSnapshotState.RESTORE_SNAPSHOT_UPDATE_TABLE_DESCRIPTOR); 151 break; 152 case RESTORE_SNAPSHOT_UPDATE_TABLE_DESCRIPTOR: 153 updateTableDescriptor(env); 154 // for restore, table dir already exists. sync EC if necessary before doing the real 155 // restore. this may be useful in certain restore scenarios where a user is explicitly 156 // trying to disable EC for some reason as part of the restore. 157 if (ErasureCodingUtils.needsSync(oldTableDescriptor, modifiedTableDescriptor)) { 158 setNextState(RestoreSnapshotState.RESTORE_SNAPSHOT_SYNC_ERASURE_CODING_POLICY); 159 } else { 160 setNextState(RestoreSnapshotState.RESTORE_SNAPSHOT_WRITE_FS_LAYOUT); 161 } 162 break; 163 case RESTORE_SNAPSHOT_SYNC_ERASURE_CODING_POLICY: 164 ErasureCodingUtils.sync(env.getMasterFileSystem().getFileSystem(), 165 env.getMasterFileSystem().getRootDir(), modifiedTableDescriptor); 166 setNextState(RestoreSnapshotState.RESTORE_SNAPSHOT_WRITE_FS_LAYOUT); 167 break; 168 case RESTORE_SNAPSHOT_WRITE_FS_LAYOUT: 169 restoreSnapshot(env); 170 setNextState(RestoreSnapshotState.RESTORE_SNAPSHOT_UPDATE_META); 171 break; 172 case RESTORE_SNAPSHOT_UPDATE_META: 173 updateMETA(env); 174 setNextState(RestoreSnapshotState.RESTORE_SNAPSHOT_RESTORE_ACL); 175 break; 176 case RESTORE_SNAPSHOT_RESTORE_ACL: 177 restoreSnapshotAcl(env); 178 return Flow.NO_MORE_STATE; 179 default: 180 throw new UnsupportedOperationException("unhandled state=" + state); 181 } 182 } catch (IOException e) { 183 if (isRollbackSupported(state)) { 184 setFailure("master-restore-snapshot", e); 185 } else { 186 LOG.warn("Retriable error trying to restore snapshot=" + snapshot.getName() + " to table=" 187 + getTableName() + " (in state=" + state + ")", e); 188 } 189 } 190 return Flow.HAS_MORE_STATE; 191 } 192 193 @Override 194 protected void rollbackState(final MasterProcedureEnv env, final RestoreSnapshotState state) 195 throws IOException { 196 if (state == RestoreSnapshotState.RESTORE_SNAPSHOT_PRE_OPERATION) { 197 // nothing to rollback 198 return; 199 } 200 201 // The restore snapshot doesn't have a rollback. The execution will succeed, at some point. 202 throw new UnsupportedOperationException("unhandled state=" + state); 203 } 204 205 @Override 206 protected boolean isRollbackSupported(final RestoreSnapshotState state) { 207 switch (state) { 208 case RESTORE_SNAPSHOT_PRE_OPERATION: 209 return true; 210 default: 211 return false; 212 } 213 } 214 215 @Override 216 protected RestoreSnapshotState getState(final int stateId) { 217 return RestoreSnapshotState.valueOf(stateId); 218 } 219 220 @Override 221 protected int getStateId(final RestoreSnapshotState state) { 222 return state.getNumber(); 223 } 224 225 @Override 226 protected RestoreSnapshotState getInitialState() { 227 return RestoreSnapshotState.RESTORE_SNAPSHOT_PRE_OPERATION; 228 } 229 230 @Override 231 public TableName getTableName() { 232 return modifiedTableDescriptor.getTableName(); 233 } 234 235 @Override 236 public TableOperationType getTableOperationType() { 237 return TableOperationType.EDIT; // Restore is modifying a table 238 } 239 240 @Override 241 public boolean abort(final MasterProcedureEnv env) { 242 // TODO: We may be able to abort if the procedure is not started yet. 243 return false; 244 } 245 246 @Override 247 public void toStringClassDetails(StringBuilder sb) { 248 sb.append(getClass().getSimpleName()); 249 sb.append(" (table="); 250 sb.append(getTableName()); 251 sb.append(" snapshot="); 252 sb.append(snapshot); 253 sb.append(")"); 254 } 255 256 @Override 257 protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException { 258 super.serializeStateData(serializer); 259 260 RestoreSnapshotStateData.Builder restoreSnapshotMsg = RestoreSnapshotStateData.newBuilder() 261 .setUserInfo(MasterProcedureUtil.toProtoUserInfo(getUser())).setSnapshot(this.snapshot) 262 .setModifiedTableSchema(ProtobufUtil.toTableSchema(modifiedTableDescriptor)) 263 .setOldTableSchema(ProtobufUtil.toTableSchema(oldTableDescriptor)); 264 265 if (regionsToRestore != null) { 266 for (RegionInfo hri : regionsToRestore) { 267 restoreSnapshotMsg.addRegionInfoForRestore(ProtobufUtil.toRegionInfo(hri)); 268 } 269 } 270 if (regionsToRemove != null) { 271 for (RegionInfo hri : regionsToRemove) { 272 restoreSnapshotMsg.addRegionInfoForRemove(ProtobufUtil.toRegionInfo(hri)); 273 } 274 } 275 if (regionsToAdd != null) { 276 for (RegionInfo hri : regionsToAdd) { 277 restoreSnapshotMsg.addRegionInfoForAdd(ProtobufUtil.toRegionInfo(hri)); 278 } 279 } 280 if (!parentsToChildrenPairMap.isEmpty()) { 281 final Iterator<Map.Entry<String, Pair<String, String>>> it = 282 parentsToChildrenPairMap.entrySet().iterator(); 283 while (it.hasNext()) { 284 final Map.Entry<String, Pair<String, String>> entry = it.next(); 285 286 RestoreParentToChildRegionsPair.Builder parentToChildrenPair = 287 RestoreParentToChildRegionsPair.newBuilder().setParentRegionName(entry.getKey()) 288 .setChild1RegionName(entry.getValue().getFirst()) 289 .setChild2RegionName(entry.getValue().getSecond()); 290 restoreSnapshotMsg.addParentToChildRegionsPairList(parentToChildrenPair); 291 } 292 } 293 restoreSnapshotMsg.setRestoreAcl(restoreAcl); 294 serializer.serialize(restoreSnapshotMsg.build()); 295 } 296 297 @Override 298 protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException { 299 super.deserializeStateData(serializer); 300 301 RestoreSnapshotStateData restoreSnapshotMsg = 302 serializer.deserialize(RestoreSnapshotStateData.class); 303 setUser(MasterProcedureUtil.toUserInfo(restoreSnapshotMsg.getUserInfo())); 304 snapshot = restoreSnapshotMsg.getSnapshot(); 305 oldTableDescriptor = ProtobufUtil.toTableDescriptor(restoreSnapshotMsg.getOldTableSchema()); 306 modifiedTableDescriptor = 307 ProtobufUtil.toTableDescriptor(restoreSnapshotMsg.getModifiedTableSchema()); 308 309 if (restoreSnapshotMsg.getRegionInfoForRestoreCount() == 0) { 310 regionsToRestore = null; 311 } else { 312 regionsToRestore = new ArrayList<>(restoreSnapshotMsg.getRegionInfoForRestoreCount()); 313 for (HBaseProtos.RegionInfo hri : restoreSnapshotMsg.getRegionInfoForRestoreList()) { 314 regionsToRestore.add(ProtobufUtil.toRegionInfo(hri)); 315 } 316 } 317 if (restoreSnapshotMsg.getRegionInfoForRemoveCount() == 0) { 318 regionsToRemove = null; 319 } else { 320 regionsToRemove = new ArrayList<>(restoreSnapshotMsg.getRegionInfoForRemoveCount()); 321 for (HBaseProtos.RegionInfo hri : restoreSnapshotMsg.getRegionInfoForRemoveList()) { 322 regionsToRemove.add(ProtobufUtil.toRegionInfo(hri)); 323 } 324 } 325 if (restoreSnapshotMsg.getRegionInfoForAddCount() == 0) { 326 regionsToAdd = null; 327 } else { 328 regionsToAdd = new ArrayList<>(restoreSnapshotMsg.getRegionInfoForAddCount()); 329 for (HBaseProtos.RegionInfo hri : restoreSnapshotMsg.getRegionInfoForAddList()) { 330 regionsToAdd.add(ProtobufUtil.toRegionInfo(hri)); 331 } 332 } 333 if (restoreSnapshotMsg.getParentToChildRegionsPairListCount() > 0) { 334 for (RestoreParentToChildRegionsPair parentToChildrenPair : restoreSnapshotMsg 335 .getParentToChildRegionsPairListList()) { 336 parentsToChildrenPairMap.put(parentToChildrenPair.getParentRegionName(), new Pair<>( 337 parentToChildrenPair.getChild1RegionName(), parentToChildrenPair.getChild2RegionName())); 338 } 339 } 340 if (restoreSnapshotMsg.hasRestoreAcl()) { 341 restoreAcl = restoreSnapshotMsg.getRestoreAcl(); 342 } 343 } 344 345 /** 346 * Action before any real action of restoring from snapshot. 347 * @param env MasterProcedureEnv 348 */ 349 private void prepareRestore(final MasterProcedureEnv env) throws IOException { 350 final TableName tableName = getTableName(); 351 // Checks whether the table exists 352 if (!env.getMasterServices().getTableDescriptors().exists(tableName)) { 353 throw new TableNotFoundException(tableName); 354 } 355 356 // check whether ttl has expired for this snapshot 357 if ( 358 SnapshotDescriptionUtils.isExpiredSnapshot(snapshot.getTtl(), snapshot.getCreationTime(), 359 EnvironmentEdgeManager.currentTime()) 360 ) { 361 throw new SnapshotTTLExpiredException(ProtobufUtil.createSnapshotDesc(snapshot)); 362 } 363 364 // Check whether table is disabled. 365 env.getMasterServices().checkTableModifiable(tableName); 366 367 // Check that we have at least 1 CF 368 if (modifiedTableDescriptor.getColumnFamilyCount() == 0) { 369 throw new DoNotRetryIOException( 370 "Table " + getTableName().toString() + " should have at least one column family."); 371 } 372 373 if (!getTableName().isSystemTable()) { 374 // Table already exist. Check and update the region quota for this table namespace. 375 final MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem(); 376 SnapshotManifest manifest = 377 SnapshotManifest.open(env.getMasterConfiguration(), mfs.getFileSystem(), 378 SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshot, mfs.getRootDir()), snapshot); 379 int snapshotRegionCount = manifest.getRegionManifestsMap().size(); 380 int tableRegionCount = 381 ProcedureSyncWait.getMasterQuotaManager(env).getRegionCountOfTable(tableName); 382 383 if (snapshotRegionCount > 0 && tableRegionCount != snapshotRegionCount) { 384 ProcedureSyncWait.getMasterQuotaManager(env).checkAndUpdateNamespaceRegionQuota(tableName, 385 snapshotRegionCount); 386 } 387 } 388 } 389 390 /** 391 * Update descriptor 392 * @param env MasterProcedureEnv 393 **/ 394 private void updateTableDescriptor(final MasterProcedureEnv env) throws IOException { 395 env.getMasterServices().getTableDescriptors().update(modifiedTableDescriptor); 396 } 397 398 /** 399 * Execute the on-disk Restore 400 * @param env MasterProcedureEnv 401 **/ 402 private void restoreSnapshot(final MasterProcedureEnv env) throws IOException { 403 MasterFileSystem fileSystemManager = env.getMasterServices().getMasterFileSystem(); 404 FileSystem fs = fileSystemManager.getFileSystem(); 405 Path rootDir = fileSystemManager.getRootDir(); 406 final ForeignExceptionDispatcher monitorException = new ForeignExceptionDispatcher(); 407 final Configuration conf = new Configuration(env.getMasterConfiguration()); 408 409 LOG.info("Starting restore snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot)); 410 try { 411 Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshot, rootDir); 412 SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshot); 413 RestoreSnapshotHelper restoreHelper = new RestoreSnapshotHelper(conf, fs, manifest, 414 modifiedTableDescriptor, rootDir, monitorException, getMonitorStatus()); 415 416 RestoreSnapshotHelper.RestoreMetaChanges metaChanges = restoreHelper.restoreHdfsRegions(); 417 regionsToRestore = metaChanges.getRegionsToRestore(); 418 regionsToRemove = metaChanges.getRegionsToRemove(); 419 regionsToAdd = metaChanges.getRegionsToAdd(); 420 parentsToChildrenPairMap = metaChanges.getParentToChildrenPairMap(); 421 } catch (IOException e) { 422 String msg = "restore snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot) 423 + " failed in on-disk restore. Try re-running the restore command."; 424 LOG.error(msg, e); 425 monitorException 426 .receive(new ForeignException(env.getMasterServices().getServerName().toString(), e)); 427 throw new IOException(msg, e); 428 } 429 } 430 431 /** 432 * Apply changes to hbase:meta 433 * @param env MasterProcedureEnv 434 **/ 435 private void updateMETA(final MasterProcedureEnv env) throws IOException { 436 try { 437 Connection conn = env.getMasterServices().getConnection(); 438 int regionReplication = modifiedTableDescriptor.getRegionReplication(); 439 440 // 1. Prepare to restore 441 getMonitorStatus().setStatus("Preparing to restore each region"); 442 443 // 2. Applies changes to hbase:meta and in-memory states 444 // (2.1). Removes the current set of regions from META and in-memory states 445 // 446 // By removing also the regions to restore (the ones present both in the snapshot 447 // and in the current state) we ensure that no extra fields are present in META 448 // e.g. with a simple add addRegionToMeta() the splitA and splitB attributes 449 // not overwritten/removed, so you end up with old informations 450 // that are not correct after the restore. 451 if (regionsToRemove != null) { 452 MetaTableAccessor.deleteRegionInfos(conn, regionsToRemove); 453 deleteRegionsFromInMemoryStates(regionsToRemove, env, regionReplication); 454 } 455 456 // (2.2). Add the new set of regions to META and in-memory states 457 // 458 // At this point the old regions are no longer present in META. 459 // and the set of regions present in the snapshot will be written to META. 460 // All the information in hbase:meta are coming from the .regioninfo of each region present 461 // in the snapshot folder. 462 if (regionsToAdd != null) { 463 MetaTableAccessor.addRegionsToMeta(conn, regionsToAdd, regionReplication); 464 addRegionsToInMemoryStates(regionsToAdd, env, regionReplication); 465 } 466 467 if (regionsToRestore != null) { 468 MetaTableAccessor.overwriteRegions(conn, regionsToRestore, regionReplication); 469 470 deleteRegionsFromInMemoryStates(regionsToRestore, env, regionReplication); 471 addRegionsToInMemoryStates(regionsToRestore, env, regionReplication); 472 } 473 474 RestoreSnapshotHelper.RestoreMetaChanges metaChanges = 475 new RestoreSnapshotHelper.RestoreMetaChanges(modifiedTableDescriptor, 476 parentsToChildrenPairMap); 477 metaChanges.updateMetaParentRegions(conn, regionsToAdd); 478 479 // At this point the restore is complete. 480 LOG.info("Restore snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot) 481 + " on table=" + getTableName() + " completed!"); 482 } catch (IOException e) { 483 final ForeignExceptionDispatcher monitorException = new ForeignExceptionDispatcher(); 484 String msg = "restore snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot) 485 + " failed in meta update. Try re-running the restore command."; 486 LOG.error(msg, e); 487 monitorException 488 .receive(new ForeignException(env.getMasterServices().getServerName().toString(), e)); 489 throw new IOException(msg, e); 490 } 491 492 monitorStatus.markComplete("Restore snapshot '" + snapshot.getName() + "'!"); 493 MetricsSnapshot metricsSnapshot = new MetricsSnapshot(); 494 metricsSnapshot 495 .addSnapshotRestore(monitorStatus.getCompletionTimestamp() - monitorStatus.getStartTime()); 496 } 497 498 /** 499 * Delete regions from in-memory states 500 * @param regionInfos regions to delete 501 * @param env MasterProcedureEnv 502 * @param regionReplication the number of region replications 503 */ 504 private void deleteRegionsFromInMemoryStates(List<RegionInfo> regionInfos, MasterProcedureEnv env, 505 int regionReplication) { 506 FavoredNodesManager fnm = env.getMasterServices().getFavoredNodesManager(); 507 508 env.getAssignmentManager().getRegionStates().deleteRegions(regionInfos); 509 env.getMasterServices().getServerManager().removeRegions(regionInfos); 510 if (fnm != null) { 511 fnm.deleteFavoredNodesForRegions(regionInfos); 512 } 513 514 // For region replicas 515 if (regionReplication > 1) { 516 for (RegionInfo regionInfo : regionInfos) { 517 for (int i = 1; i < regionReplication; i++) { 518 RegionInfo regionInfoForReplica = 519 RegionReplicaUtil.getRegionInfoForReplica(regionInfo, i); 520 env.getAssignmentManager().getRegionStates().deleteRegion(regionInfoForReplica); 521 env.getMasterServices().getServerManager().removeRegion(regionInfoForReplica); 522 if (fnm != null) { 523 fnm.deleteFavoredNodesForRegion(regionInfoForReplica); 524 } 525 } 526 } 527 } 528 } 529 530 /** 531 * Add regions to in-memory states 532 * @param regionInfos regions to add 533 * @param env MasterProcedureEnv 534 * @param regionReplication the number of region replications 535 */ 536 private void addRegionsToInMemoryStates(List<RegionInfo> regionInfos, MasterProcedureEnv env, 537 int regionReplication) { 538 AssignmentManager am = env.getAssignmentManager(); 539 for (RegionInfo regionInfo : regionInfos) { 540 if (regionInfo.isSplit()) { 541 am.getRegionStates().updateRegionState(regionInfo, RegionState.State.SPLIT); 542 } else { 543 am.getRegionStates().updateRegionState(regionInfo, RegionState.State.CLOSED); 544 545 // For region replicas 546 for (int i = 1; i < regionReplication; i++) { 547 RegionInfo regionInfoForReplica = 548 RegionReplicaUtil.getRegionInfoForReplica(regionInfo, i); 549 am.getRegionStates().updateRegionState(regionInfoForReplica, RegionState.State.CLOSED); 550 } 551 } 552 } 553 } 554 555 private void restoreSnapshotAcl(final MasterProcedureEnv env) throws IOException { 556 if ( 557 restoreAcl && snapshot.hasUsersAndPermissions() && snapshot.getUsersAndPermissions() != null 558 && SnapshotDescriptionUtils.isSecurityAvailable(env.getMasterServices().getConfiguration()) 559 ) { 560 // restore acl of snapshot to table. 561 RestoreSnapshotHelper.restoreSnapshotAcl(snapshot, TableName.valueOf(snapshot.getTable()), 562 env.getMasterServices().getConfiguration()); 563 } 564 } 565 566 /** 567 * Exposed for Testing: HBASE-26462 568 */ 569 @RestrictedApi(explanation = "Should only be called in tests", link = "", 570 allowedOnPath = ".*/src/test/.*") 571 public boolean getRestoreAcl() { 572 return restoreAcl; 573 } 574}