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; 019 020import org.apache.hadoop.hbase.HConstants; 021import org.apache.hadoop.hbase.TableName; 022import org.apache.hadoop.hbase.ipc.AnnotationReadingPriorityFunction; 023import org.apache.yetus.audience.InterfaceAudience; 024 025import org.apache.hbase.thirdparty.com.google.protobuf.Message; 026 027import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 028import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 029import org.apache.hadoop.hbase.shaded.protobuf.generated.RPCProtos.RequestHeader; 030import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos; 031 032/** 033 * Priority function specifically for the master. 034 * <p/> 035 * This doesn't make the super users always priority since that would make everything to the master 036 * into high priority. 037 * <p/> 038 * Specifically when reporting that a region is in transition master will try and edit the meta 039 * table. That edit will block the thread until successful. However if at the same time meta is also 040 * moving then we need to ensure that the regular region that's moving isn't blocking processing of 041 * the request to online meta. To accomplish this this priority function makes sure that all 042 * requests to transition meta are handled in different threads from other report region in 043 * transition calls. 044 * <p/> 045 * After HBASE-21754, ReportRegionStateTransitionRequest for meta region will be assigned a META_QOS 046 * , a separate executor called metaTransitionExecutor will execute it. Other transition request 047 * will be executed in priorityExecutor to prevent being mixed with normal requests 048 */ 049@InterfaceAudience.Private 050public class MasterAnnotationReadingPriorityFunction 051 extends AnnotationReadingPriorityFunction<MasterRpcServices> { 052 053 /** 054 * We reference this value in SimpleRpcScheduler so this class have to be public instead of 055 * package private 056 */ 057 public static final int META_TRANSITION_QOS = 300; 058 059 MasterAnnotationReadingPriorityFunction(MasterRpcServices rpcServices) { 060 super(rpcServices); 061 } 062 063 @Override 064 protected int normalizePriority(int priority) { 065 // no one can have higher priority than meta transition. 066 if (priority >= META_TRANSITION_QOS) { 067 return META_TRANSITION_QOS - 1; 068 } else { 069 return priority; 070 } 071 } 072 073 @Override 074 protected int getBasePriority(RequestHeader header, Message param) { 075 // If meta is moving then all the other of reports of state transitions will be 076 // un able to edit meta. Those blocked reports should not keep the report that opens meta from 077 // running. Hence all reports of meta transition should always be in a different thread. 078 // This keeps from deadlocking the cluster. 079 if (param instanceof RegionServerStatusProtos.ReportRegionStateTransitionRequest) { 080 // Regions are moving. Lets see which ones. 081 RegionServerStatusProtos.ReportRegionStateTransitionRequest tRequest = 082 (RegionServerStatusProtos.ReportRegionStateTransitionRequest) param; 083 for (RegionServerStatusProtos.RegionStateTransition rst : tRequest.getTransitionList()) { 084 if (rst.getRegionInfoList() != null) { 085 for (HBaseProtos.RegionInfo info : rst.getRegionInfoList()) { 086 TableName tn = ProtobufUtil.toTableName(info.getTableName()); 087 if (TableName.META_TABLE_NAME.equals(tn)) { 088 return META_TRANSITION_QOS; 089 } 090 } 091 } 092 } 093 return HConstants.HIGH_QOS; 094 } 095 // also use HIGH_QOS for region server report 096 if (param instanceof RegionServerStatusProtos.RegionServerReportRequest) { 097 return HConstants.HIGH_QOS; 098 } 099 // Trust the client-set priorities if set 100 if (header.hasPriority()) { 101 return header.getPriority(); 102 } 103 return HConstants.NORMAL_QOS; 104 } 105 106 @Override 107 public long getDeadline(RequestHeader header, Message param) { 108 return 0; 109 } 110}