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 java.io.IOException; 021import java.util.List; 022import org.apache.hadoop.hbase.HBaseIOException; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.hadoop.hbase.client.TableDescriptor; 025import org.apache.hadoop.hbase.client.TableState; 026import org.apache.hadoop.hbase.procedure2.Procedure; 027import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException; 028import org.apache.hadoop.hbase.procedure2.ProcedureYieldException; 029import org.apache.hadoop.hbase.snapshot.SnapshotDoesNotExistException; 030import org.apache.yetus.audience.InterfaceAudience; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 035import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RestoreBackupSystemTableState; 036import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription; 037 038@InterfaceAudience.Private 039public class RestoreBackupSystemTableProcedure 040 extends AbstractStateMachineTableProcedure<RestoreBackupSystemTableState> { 041 private static final Logger LOG = 042 LoggerFactory.getLogger(RestoreBackupSystemTableProcedure.class); 043 044 private final SnapshotDescription snapshot; 045 private boolean enableOnRollback = false; 046 047 // Necessary for the procedure framework. Do not remove. 048 public RestoreBackupSystemTableProcedure() { 049 this(null); 050 } 051 052 public RestoreBackupSystemTableProcedure(SnapshotDescription snapshot) { 053 this.snapshot = snapshot; 054 } 055 056 @Override 057 public TableName getTableName() { 058 return TableName.valueOf(snapshot.getTable()); 059 } 060 061 @Override 062 public TableOperationType getTableOperationType() { 063 return TableOperationType.RESTORE_BACKUP_SYSTEM_TABLE; 064 } 065 066 @Override 067 protected Flow executeFromState(MasterProcedureEnv env, RestoreBackupSystemTableState state) 068 throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { 069 LOG.info("{} execute state={}", this, state); 070 071 try { 072 switch (state) { 073 case RESTORE_BACKUP_SYSTEM_TABLE_PREPARE: 074 prepare(env); 075 return moreState(RestoreBackupSystemTableState.RESTORE_BACKUP_SYSTEM_TABLE_DISABLE); 076 case RESTORE_BACKUP_SYSTEM_TABLE_DISABLE: 077 TableState tableState = 078 env.getMasterServices().getTableStateManager().getTableState(getTableName()); 079 if (tableState.isEnabled()) { 080 addChildProcedure(createDisableTableProcedure(env)); 081 } 082 return moreState(RestoreBackupSystemTableState.RESTORE_BACKUP_SYSTEM_TABLE_RESTORE); 083 case RESTORE_BACKUP_SYSTEM_TABLE_RESTORE: 084 addChildProcedure(createRestoreSnapshotProcedure(env)); 085 return moreState(RestoreBackupSystemTableState.RESTORE_BACKUP_SYSTEM_TABLE_ENABLE); 086 case RESTORE_BACKUP_SYSTEM_TABLE_ENABLE: 087 addChildProcedure(createEnableTableProcedure(env)); 088 return Flow.NO_MORE_STATE; 089 default: 090 throw new UnsupportedOperationException("unhandled state=" + state); 091 } 092 } catch (Exception e) { 093 setFailure("restore-backup-system-table", e); 094 LOG.warn("unexpected exception while execute {}. Mark procedure Failed.", this, e); 095 return Flow.NO_MORE_STATE; 096 } 097 } 098 099 @Override 100 protected void rollbackState(MasterProcedureEnv env, RestoreBackupSystemTableState state) 101 throws IOException, InterruptedException { 102 switch (state) { 103 case RESTORE_BACKUP_SYSTEM_TABLE_DISABLE: 104 case RESTORE_BACKUP_SYSTEM_TABLE_PREPARE: 105 return; 106 case RESTORE_BACKUP_SYSTEM_TABLE_RESTORE: 107 case RESTORE_BACKUP_SYSTEM_TABLE_ENABLE: 108 if (enableOnRollback) { 109 addChildProcedure(createEnableTableProcedure(env)); 110 } 111 return; 112 default: 113 throw new UnsupportedOperationException("unhandled state=" + state); 114 } 115 } 116 117 @Override 118 protected RestoreBackupSystemTableState getState(int stateId) { 119 return RestoreBackupSystemTableState.forNumber(stateId); 120 } 121 122 @Override 123 protected int getStateId(RestoreBackupSystemTableState state) { 124 return state.getNumber(); 125 } 126 127 @Override 128 protected RestoreBackupSystemTableState getInitialState() { 129 return RestoreBackupSystemTableState.RESTORE_BACKUP_SYSTEM_TABLE_PREPARE; 130 } 131 132 private Flow moreState(RestoreBackupSystemTableState next) { 133 setNextState(next); 134 return Flow.HAS_MORE_STATE; 135 } 136 137 private Procedure<MasterProcedureEnv>[] createDisableTableProcedure(MasterProcedureEnv env) 138 throws HBaseIOException { 139 DisableTableProcedure disableTableProcedure = 140 new DisableTableProcedure(env, getTableName(), true); 141 return new DisableTableProcedure[] { disableTableProcedure }; 142 } 143 144 private Procedure<MasterProcedureEnv>[] createEnableTableProcedure(MasterProcedureEnv env) { 145 EnableTableProcedure enableTableProcedure = new EnableTableProcedure(env, getTableName()); 146 return new EnableTableProcedure[] { enableTableProcedure }; 147 } 148 149 private Procedure<MasterProcedureEnv>[] createRestoreSnapshotProcedure(MasterProcedureEnv env) 150 throws IOException { 151 TableDescriptor desc = env.getMasterServices().getTableDescriptors().get(getTableName()); 152 RestoreSnapshotProcedure restoreSnapshotProcedure = 153 new RestoreSnapshotProcedure(env, desc, snapshot); 154 return new RestoreSnapshotProcedure[] { restoreSnapshotProcedure }; 155 } 156 157 private void prepare(MasterProcedureEnv env) throws IOException { 158 List<SnapshotDescription> snapshots = 159 env.getMasterServices().getSnapshotManager().getCompletedSnapshots(); 160 boolean exists = snapshots.stream().anyMatch(s -> s.getName().equals(snapshot.getName())); 161 if (!exists) { 162 throw new SnapshotDoesNotExistException(ProtobufUtil.createSnapshotDesc(snapshot)); 163 } 164 165 TableState tableState = 166 env.getMasterServices().getTableStateManager().getTableState(getTableName()); 167 if (tableState.isEnabled()) { 168 enableOnRollback = true; 169 } 170 } 171}