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 org.apache.hadoop.hbase.CellUtil; 022import org.apache.hadoop.hbase.HConstants; 023import org.apache.hadoop.hbase.TableName; 024import org.apache.hadoop.hbase.client.BufferedMutator; 025import org.apache.hadoop.hbase.client.Connection; 026import org.apache.hadoop.hbase.client.Put; 027import org.apache.hadoop.hbase.client.Result; 028import org.apache.hadoop.hbase.client.ResultScanner; 029import org.apache.hadoop.hbase.client.Scan; 030import org.apache.hadoop.hbase.client.Table; 031import org.apache.hadoop.hbase.client.TableDescriptor; 032import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 033import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException; 034import org.apache.hadoop.hbase.procedure2.ProcedureUtil; 035import org.apache.hadoop.hbase.procedure2.ProcedureYieldException; 036import org.apache.hadoop.hbase.procedure2.StateMachineProcedure; 037import org.apache.hadoop.hbase.util.FSTableDescriptors; 038import org.apache.hadoop.hbase.util.RetryCounter; 039import org.apache.yetus.audience.InterfaceAudience; 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.MigrateNamespaceTableProcedureState; 044 045/** 046 * Migrate the namespace data to meta table's namespace family while upgrading 047 */ 048@InterfaceAudience.Private 049public class MigrateNamespaceTableProcedure 050 extends StateMachineProcedure<MasterProcedureEnv, MigrateNamespaceTableProcedureState> 051 implements GlobalProcedureInterface { 052 053 private static final Logger LOG = LoggerFactory.getLogger(MigrateNamespaceTableProcedure.class); 054 055 private RetryCounter retryCounter; 056 057 @Override 058 public String getGlobalId() { 059 return getClass().getSimpleName(); 060 } 061 062 private void migrate(MasterProcedureEnv env) throws IOException { 063 Connection conn = env.getMasterServices().getConnection(); 064 try (Table nsTable = conn.getTable(TableName.NAMESPACE_TABLE_NAME); 065 ResultScanner scanner = nsTable.getScanner( 066 new Scan().addFamily(TableDescriptorBuilder.NAMESPACE_FAMILY_INFO_BYTES).readAllVersions()); 067 BufferedMutator mutator = conn.getBufferedMutator(TableName.META_TABLE_NAME)) { 068 for (Result result;;) { 069 result = scanner.next(); 070 if (result == null) { 071 break; 072 } 073 Put put = new Put(result.getRow()); 074 result 075 .getColumnCells(TableDescriptorBuilder.NAMESPACE_FAMILY_INFO_BYTES, 076 TableDescriptorBuilder.NAMESPACE_COL_DESC_BYTES) 077 .forEach(c -> put.addColumn(HConstants.NAMESPACE_FAMILY, 078 HConstants.NAMESPACE_COL_DESC_QUALIFIER, c.getTimestamp(), CellUtil.cloneValue(c))); 079 mutator.mutate(put); 080 } 081 } 082 } 083 084 @Override 085 protected Flow executeFromState(MasterProcedureEnv env, MigrateNamespaceTableProcedureState state) 086 throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException { 087 try { 088 switch (state) { 089 case MIGRATE_NAMESPACE_TABLE_ADD_FAMILY: 090 TableDescriptor metaTableDesc = 091 env.getMasterServices().getTableDescriptors().get(TableName.META_TABLE_NAME); 092 if (!metaTableDesc.hasColumnFamily(HConstants.NAMESPACE_FAMILY)) { 093 TableDescriptor newMetaTableDesc = TableDescriptorBuilder.newBuilder(metaTableDesc) 094 .setColumnFamily( 095 FSTableDescriptors.getNamespaceFamilyDescForMeta(env.getMasterConfiguration())) 096 .build(); 097 addChildProcedure(new ModifyTableProcedure(env, newMetaTableDesc)); 098 } 099 setNextState(MigrateNamespaceTableProcedureState.MIGRATE_NAMESPACE_TABLE_MIGRATE_DATA); 100 return Flow.HAS_MORE_STATE; 101 case MIGRATE_NAMESPACE_TABLE_MIGRATE_DATA: 102 migrate(env); 103 setNextState(MigrateNamespaceTableProcedureState.MIGRATE_NAMESPACE_TABLE_DISABLE_TABLE); 104 return Flow.HAS_MORE_STATE; 105 case MIGRATE_NAMESPACE_TABLE_DISABLE_TABLE: 106 addChildProcedure(new DisableTableProcedure(env, TableName.NAMESPACE_TABLE_NAME, false)); 107 return Flow.NO_MORE_STATE; 108 default: 109 throw new UnsupportedOperationException("Unhandled state=" + state); 110 } 111 } catch (IOException e) { 112 if (retryCounter == null) { 113 retryCounter = ProcedureUtil.createRetryCounter(env.getMasterConfiguration()); 114 } 115 long backoff = retryCounter.getBackoffTimeAndIncrementAttempts(); 116 LOG.warn("Failed migrating namespace data, suspend {}secs {}", backoff / 1000, this, e); 117 throw suspend(Math.toIntExact(backoff), true); 118 } 119 } 120 121 @Override 122 protected void rollbackState(MasterProcedureEnv env, MigrateNamespaceTableProcedureState state) 123 throws IOException, InterruptedException { 124 } 125 126 @Override 127 protected MigrateNamespaceTableProcedureState getState(int stateId) { 128 return MigrateNamespaceTableProcedureState.forNumber(stateId); 129 } 130 131 @Override 132 protected int getStateId(MigrateNamespaceTableProcedureState state) { 133 return state.getNumber(); 134 } 135 136 @Override 137 protected MigrateNamespaceTableProcedureState getInitialState() { 138 return MigrateNamespaceTableProcedureState.MIGRATE_NAMESPACE_TABLE_ADD_FAMILY; 139 } 140 141 @Override 142 protected void completionCleanup(MasterProcedureEnv env) { 143 env.getMasterServices().getClusterSchema().getTableNamespaceManager().setMigrationDone(); 144 } 145}