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