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.assignment; 019 020import java.io.IOException; 021import org.apache.hadoop.hbase.MetaTableAccessor; 022import org.apache.hadoop.hbase.TableName; 023import org.apache.hadoop.hbase.client.RegionInfo; 024import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineTableProcedure; 025import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 026import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer; 027import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException; 028import org.apache.hadoop.hbase.procedure2.ProcedureYieldException; 029import org.apache.yetus.audience.InterfaceAudience; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 034import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos; 035import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.GCMergedRegionsState; 036 037/** 038 * GC regions that have been Merged. Caller determines if it is GC time. This Procedure does not 039 * check. 040 * <p> 041 * This is a Table Procedure. We take a read lock on the Table. We do NOT keep a lock for the life 042 * of this procedure. The subprocedures take locks on the Regions they are purging. 043 * @deprecated 2.3.0 Use {@link GCMultipleMergedRegionsProcedure}. 044 */ 045@InterfaceAudience.Private 046@Deprecated 047public class GCMergedRegionsProcedure 048 extends AbstractStateMachineTableProcedure<GCMergedRegionsState> { 049 private static final Logger LOG = LoggerFactory.getLogger(GCMergedRegionsProcedure.class); 050 private RegionInfo father; 051 private RegionInfo mother; 052 private RegionInfo mergedChild; 053 054 public GCMergedRegionsProcedure(final MasterProcedureEnv env, final RegionInfo mergedChild, 055 final RegionInfo father, final RegionInfo mother) { 056 super(env); 057 this.father = father; 058 this.mother = mother; 059 this.mergedChild = mergedChild; 060 } 061 062 public GCMergedRegionsProcedure() { 063 // Required by the Procedure framework to create the procedure on replay 064 super(); 065 } 066 067 @Override 068 public TableOperationType getTableOperationType() { 069 return TableOperationType.MERGED_REGIONS_GC; 070 } 071 072 @Override 073 protected Flow executeFromState(MasterProcedureEnv env, GCMergedRegionsState state) 074 throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { 075 if (LOG.isTraceEnabled()) { 076 LOG.trace(this + " execute state=" + state); 077 } 078 try { 079 switch (state) { 080 case GC_MERGED_REGIONS_PREPARE: 081 // Nothing to do to prepare. 082 setNextState(GCMergedRegionsState.GC_MERGED_REGIONS_PURGE); 083 break; 084 case GC_MERGED_REGIONS_PURGE: 085 addChildProcedure(createGCRegionProcedures(env)); 086 setNextState(GCMergedRegionsState.GC_REGION_EDIT_METADATA); 087 break; 088 case GC_REGION_EDIT_METADATA: 089 MetaTableAccessor.deleteMergeQualifiers(env.getMasterServices().getConnection(), 090 mergedChild); 091 return Flow.NO_MORE_STATE; 092 default: 093 throw new UnsupportedOperationException(this + " unhandled state=" + state); 094 } 095 } catch (IOException ioe) { 096 // TODO: This is going to spew log? 097 LOG.warn("Error trying to GC merged regions " + this.father.getShortNameToLog() + " & " 098 + this.mother.getShortNameToLog() + "; retrying...", ioe); 099 } 100 return Flow.HAS_MORE_STATE; 101 } 102 103 private GCRegionProcedure[] createGCRegionProcedures(final MasterProcedureEnv env) { 104 GCRegionProcedure[] procs = new GCRegionProcedure[2]; 105 int index = 0; 106 for (RegionInfo hri : new RegionInfo[] { this.father, this.mother }) { 107 GCRegionProcedure proc = new GCRegionProcedure(env, hri); 108 proc.setOwner(env.getRequestUser().getShortName()); 109 procs[index++] = proc; 110 } 111 return procs; 112 } 113 114 @Override 115 protected void rollbackState(MasterProcedureEnv env, GCMergedRegionsState state) 116 throws IOException, InterruptedException { 117 // no-op 118 } 119 120 @Override 121 protected GCMergedRegionsState getState(int stateId) { 122 return GCMergedRegionsState.forNumber(stateId); 123 } 124 125 @Override 126 protected int getStateId(GCMergedRegionsState state) { 127 return state.getNumber(); 128 } 129 130 @Override 131 protected GCMergedRegionsState getInitialState() { 132 return GCMergedRegionsState.GC_MERGED_REGIONS_PREPARE; 133 } 134 135 @Override 136 protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException { 137 super.serializeStateData(serializer); 138 final MasterProcedureProtos.GCMergedRegionsStateData.Builder msg = 139 MasterProcedureProtos.GCMergedRegionsStateData.newBuilder() 140 .setParentA(ProtobufUtil.toRegionInfo(this.father)) 141 .setParentB(ProtobufUtil.toRegionInfo(this.mother)) 142 .setMergedChild(ProtobufUtil.toRegionInfo(this.mergedChild)); 143 serializer.serialize(msg.build()); 144 } 145 146 @Override 147 protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException { 148 super.deserializeStateData(serializer); 149 final MasterProcedureProtos.GCMergedRegionsStateData msg = 150 serializer.deserialize(MasterProcedureProtos.GCMergedRegionsStateData.class); 151 this.father = ProtobufUtil.toRegionInfo(msg.getParentA()); 152 this.mother = ProtobufUtil.toRegionInfo(msg.getParentB()); 153 this.mergedChild = ProtobufUtil.toRegionInfo(msg.getMergedChild()); 154 } 155 156 @Override 157 public void toStringClassDetails(StringBuilder sb) { 158 sb.append(getClass().getSimpleName()); 159 sb.append(" child="); 160 sb.append(this.mergedChild.getShortNameToLog()); 161 sb.append(", father="); 162 sb.append(this.father.getShortNameToLog()); 163 sb.append(", mother="); 164 sb.append(this.mother.getShortNameToLog()); 165 } 166 167 @Override 168 public TableName getTableName() { 169 return this.mergedChild.getTable(); 170 } 171}