1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.regionserver;
19
20 import java.lang.reflect.Method;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.hbase.HConstants;
27 import org.apache.hadoop.hbase.TableName;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.NotServingRegionException;
30 import org.apache.hadoop.hbase.ipc.PriorityFunction;
31 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
32 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
33 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest;
34 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionStateTransition;
35 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
36 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
37 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
38 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
39 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileRequest;
40 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
41 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
42 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateRequest;
43 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
44 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
45 import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.RequestHeader;
46 import org.apache.hadoop.hbase.regionserver.HRegionServer.QosPriority;
47
48 import com.google.common.annotations.VisibleForTesting;
49 import com.google.protobuf.Message;
50 import com.google.protobuf.TextFormat;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 @InterfaceAudience.Private
75 class AnnotationReadingPriorityFunction implements PriorityFunction {
76 public static final Log LOG =
77 LogFactory.getLog(AnnotationReadingPriorityFunction.class.getName());
78 private final Map<String, Integer> annotatedQos;
79
80
81 private HRegionServer hRegionServer;
82 @SuppressWarnings("unchecked")
83 private final Class<? extends Message>[] knownArgumentClasses = new Class[]{
84 GetRegionInfoRequest.class,
85 GetStoreFileRequest.class,
86 CloseRegionRequest.class,
87 FlushRegionRequest.class,
88 SplitRegionRequest.class,
89 CompactRegionRequest.class,
90 GetRequest.class,
91 MutateRequest.class,
92 ScanRequest.class
93 };
94
95
96 private final Map<String, Class<? extends Message>> argumentToClassMap =
97 new HashMap<String, Class<? extends Message>>();
98 private final Map<String, Map<Class<? extends Message>, Method>> methodMap =
99 new HashMap<String, Map<Class<? extends Message>, Method>>();
100
101 AnnotationReadingPriorityFunction(final HRegionServer hrs) {
102 this.hRegionServer = hrs;
103 Map<String, Integer> qosMap = new HashMap<String, Integer>();
104 for (Method m : HRegionServer.class.getMethods()) {
105 QosPriority p = m.getAnnotation(QosPriority.class);
106 if (p != null) {
107
108
109
110
111
112 String capitalizedMethodName = capitalize(m.getName());
113 qosMap.put(capitalizedMethodName, p.priority());
114 }
115 }
116 this.annotatedQos = qosMap;
117 if (methodMap.get("getRegion") == null) {
118 methodMap.put("hasRegion", new HashMap<Class<? extends Message>, Method>());
119 methodMap.put("getRegion", new HashMap<Class<? extends Message>, Method>());
120 }
121 for (Class<? extends Message> cls : knownArgumentClasses) {
122 argumentToClassMap.put(cls.getName(), cls);
123 try {
124 methodMap.get("hasRegion").put(cls, cls.getDeclaredMethod("hasRegion"));
125 methodMap.get("getRegion").put(cls, cls.getDeclaredMethod("getRegion"));
126 } catch (Exception e) {
127 throw new RuntimeException(e);
128 }
129 }
130 }
131
132 private String capitalize(final String s) {
133 StringBuilder strBuilder = new StringBuilder(s);
134 strBuilder.setCharAt(0, Character.toUpperCase(strBuilder.charAt(0)));
135 return strBuilder.toString();
136 }
137
138 public boolean isMetaRegion(byte[] regionName) {
139 HRegion region;
140 try {
141 region = hRegionServer.getRegion(regionName);
142 } catch (NotServingRegionException ignored) {
143 return false;
144 }
145 return region.getRegionInfo().isMetaTable();
146 }
147
148 @Override
149 public int getPriority(RequestHeader header, Message param) {
150 String methodName = header.getMethodName();
151 Integer priorityByAnnotation = annotatedQos.get(methodName);
152 if (priorityByAnnotation != null) {
153 return priorityByAnnotation;
154 }
155 if (param == null) {
156 return HConstants.NORMAL_QOS;
157 }
158
159 if (header.hasPriority()) {
160 return header.getPriority();
161 }
162 String cls = param.getClass().getName();
163 Class<? extends Message> rpcArgClass = argumentToClassMap.get(cls);
164 RegionSpecifier regionSpecifier = null;
165
166 try {
167
168
169
170
171 Method hasRegion = methodMap.get("hasRegion").get(rpcArgClass);
172 if (hasRegion != null && (Boolean)hasRegion.invoke(param, (Object[])null)) {
173 Method getRegion = methodMap.get("getRegion").get(rpcArgClass);
174 regionSpecifier = (RegionSpecifier)getRegion.invoke(param, (Object[])null);
175 HRegion region = hRegionServer.getRegion(regionSpecifier);
176 if (region.getRegionInfo().isMetaTable()) {
177 if (LOG.isTraceEnabled()) {
178 LOG.trace("High priority because region=" + region.getRegionNameAsString());
179 }
180 return HConstants.HIGH_QOS;
181 }
182 }
183 } catch (Exception ex) {
184
185
186 if (LOG.isTraceEnabled()) LOG.trace("Marking normal priority after getting exception=" + ex);
187 return HConstants.NORMAL_QOS;
188 }
189
190 if (param instanceof ScanRequest) {
191 ScanRequest request = (ScanRequest)param;
192 if (!request.hasScannerId()) {
193 return HConstants.NORMAL_QOS;
194 }
195 RegionScanner scanner = hRegionServer.getScanner(request.getScannerId());
196 if (scanner != null && scanner.getRegionInfo().isMetaRegion()) {
197 if (LOG.isTraceEnabled()) {
198
199 LOG.trace("High priority scanner request " + TextFormat.shortDebugString(request));
200 }
201 return HConstants.HIGH_QOS;
202 }
203 }
204
205
206
207 if (param instanceof ReportRegionStateTransitionRequest) {
208 ReportRegionStateTransitionRequest tRequest = (ReportRegionStateTransitionRequest) param;
209 for (RegionStateTransition transition : tRequest.getTransitionList()) {
210 if (transition.getRegionInfoList() != null) {
211 for (HBaseProtos.RegionInfo info : transition.getRegionInfoList()) {
212 TableName tn = ProtobufUtil.toTableName(info.getTableName());
213 if (tn.isSystemTable()) {
214 return HConstants.HIGH_QOS;
215 }
216 }
217 }
218 }
219 }
220 return HConstants.NORMAL_QOS;
221 }
222
223 @VisibleForTesting
224 void setRegionServer(final HRegionServer hrs) {
225 this.hRegionServer = hrs;
226 }
227 }