1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
3  * agreements. See the NOTICE file distributed with this work for additional information regarding
4  * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
5  * "License"); you may not use this file except in compliance with the License. You may obtain a
6  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
7  * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
8  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
9  * for the specific language governing permissions and limitations under the License.
10  */
11 package org.apache.hadoop.hbase.quotas;
12 
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.concurrent.TimeUnit;
16 
17 import org.apache.hadoop.hbase.TableName;
18 import org.apache.hadoop.hbase.classification.InterfaceAudience;
19 import org.apache.hadoop.hbase.classification.InterfaceStability;
20 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
21 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest;
22 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
23 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
24 
25 @InterfaceAudience.Public
26 @InterfaceStability.Evolving
27 public class QuotaSettingsFactory {
QuotaSettingsFactory()28   private QuotaSettingsFactory() {
29     // Utility class
30   }
31 
32   static class QuotaGlobalsSettingsBypass extends QuotaSettings {
33     private final boolean bypassGlobals;
34 
QuotaGlobalsSettingsBypass(final String userName, final TableName tableName, final String namespace, final boolean bypassGlobals)35     QuotaGlobalsSettingsBypass(final String userName, final TableName tableName,
36         final String namespace, final boolean bypassGlobals) {
37       super(userName, tableName, namespace);
38       this.bypassGlobals = bypassGlobals;
39     }
40 
41     @Override
getQuotaType()42     public QuotaType getQuotaType() {
43       return QuotaType.GLOBAL_BYPASS;
44     }
45 
46     @Override
setupSetQuotaRequest(SetQuotaRequest.Builder builder)47     protected void setupSetQuotaRequest(SetQuotaRequest.Builder builder) {
48       builder.setBypassGlobals(bypassGlobals);
49     }
50 
51     @Override
toString()52     public String toString() {
53       return "GLOBAL_BYPASS => " + bypassGlobals;
54     }
55   }
56 
57   /*
58    * ========================================================================== QuotaSettings from
59    * the Quotas object
60    */
fromUserQuotas(final String userName, final Quotas quotas)61   static List<QuotaSettings> fromUserQuotas(final String userName, final Quotas quotas) {
62     return fromQuotas(userName, null, null, quotas);
63   }
64 
fromUserQuotas(final String userName, final TableName tableName, final Quotas quotas)65   static List<QuotaSettings> fromUserQuotas(final String userName, final TableName tableName,
66       final Quotas quotas) {
67     return fromQuotas(userName, tableName, null, quotas);
68   }
69 
fromUserQuotas(final String userName, final String namespace, final Quotas quotas)70   static List<QuotaSettings> fromUserQuotas(final String userName, final String namespace,
71       final Quotas quotas) {
72     return fromQuotas(userName, null, namespace, quotas);
73   }
74 
fromTableQuotas(final TableName tableName, final Quotas quotas)75   static List<QuotaSettings> fromTableQuotas(final TableName tableName, final Quotas quotas) {
76     return fromQuotas(null, tableName, null, quotas);
77   }
78 
fromNamespaceQuotas(final String namespace, final Quotas quotas)79   static List<QuotaSettings> fromNamespaceQuotas(final String namespace, final Quotas quotas) {
80     return fromQuotas(null, null, namespace, quotas);
81   }
82 
fromQuotas(final String userName, final TableName tableName, final String namespace, final Quotas quotas)83   private static List<QuotaSettings> fromQuotas(final String userName, final TableName tableName,
84       final String namespace, final Quotas quotas) {
85     List<QuotaSettings> settings = new ArrayList<QuotaSettings>();
86     if (quotas.hasThrottle()) {
87       settings.addAll(fromThrottle(userName, tableName, namespace, quotas.getThrottle()));
88     }
89     if (quotas.getBypassGlobals() == true) {
90       settings.add(new QuotaGlobalsSettingsBypass(userName, tableName, namespace, true));
91     }
92     return settings;
93   }
94 
fromThrottle(final String userName, final TableName tableName, final String namespace, final QuotaProtos.Throttle throttle)95   private static List<QuotaSettings> fromThrottle(final String userName, final TableName tableName,
96       final String namespace, final QuotaProtos.Throttle throttle) {
97     List<QuotaSettings> settings = new ArrayList<QuotaSettings>();
98     if (throttle.hasReqNum()) {
99       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
100         ThrottleType.REQUEST_NUMBER, throttle.getReqNum()));
101     }
102     if (throttle.hasReqSize()) {
103       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
104         ThrottleType.REQUEST_SIZE, throttle.getReqSize()));
105     }
106     if (throttle.hasWriteNum()) {
107       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
108           ThrottleType.WRITE_NUMBER, throttle.getWriteNum()));
109     }
110     if (throttle.hasWriteSize()) {
111       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
112           ThrottleType.WRITE_SIZE, throttle.getWriteSize()));
113     }
114     if (throttle.hasReadNum()) {
115       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
116           ThrottleType.READ_NUMBER, throttle.getReadNum()));
117     }
118     if (throttle.hasReadSize()) {
119       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
120           ThrottleType.READ_SIZE, throttle.getReadSize()));
121     }
122     return settings;
123   }
124 
125   /*
126    * ========================================================================== RPC Throttle
127    */
128 
129   /**
130    * Throttle the specified user.
131    * @param userName the user to throttle
132    * @param type the type of throttling
133    * @param limit the allowed number of request/data per timeUnit
134    * @param timeUnit the limit time unit
135    * @return the quota settings
136    */
throttleUser(final String userName, final ThrottleType type, final long limit, final TimeUnit timeUnit)137   public static QuotaSettings throttleUser(final String userName, final ThrottleType type,
138       final long limit, final TimeUnit timeUnit) {
139     return throttle(userName, null, null, type, limit, timeUnit);
140   }
141 
142   /**
143    * Throttle the specified user on the specified table.
144    * @param userName the user to throttle
145    * @param tableName the table to throttle
146    * @param type the type of throttling
147    * @param limit the allowed number of request/data per timeUnit
148    * @param timeUnit the limit time unit
149    * @return the quota settings
150    */
throttleUser(final String userName, final TableName tableName, final ThrottleType type, final long limit, final TimeUnit timeUnit)151   public static QuotaSettings throttleUser(final String userName, final TableName tableName,
152       final ThrottleType type, final long limit, final TimeUnit timeUnit) {
153     return throttle(userName, tableName, null, type, limit, timeUnit);
154   }
155 
156   /**
157    * Throttle the specified user on the specified namespace.
158    * @param userName the user to throttle
159    * @param namespace the namespace to throttle
160    * @param type the type of throttling
161    * @param limit the allowed number of request/data per timeUnit
162    * @param timeUnit the limit time unit
163    * @return the quota settings
164    */
throttleUser(final String userName, final String namespace, final ThrottleType type, final long limit, final TimeUnit timeUnit)165   public static QuotaSettings throttleUser(final String userName, final String namespace,
166       final ThrottleType type, final long limit, final TimeUnit timeUnit) {
167     return throttle(userName, null, namespace, type, limit, timeUnit);
168   }
169 
170   /**
171    * Remove the throttling for the specified user.
172    * @param userName the user
173    * @return the quota settings
174    */
unthrottleUser(final String userName)175   public static QuotaSettings unthrottleUser(final String userName) {
176     return throttle(userName, null, null, null, 0, null);
177   }
178 
179   /**
180    * Remove the throttling for the specified user on the specified table.
181    * @param userName the user
182    * @param tableName the table
183    * @return the quota settings
184    */
unthrottleUser(final String userName, final TableName tableName)185   public static QuotaSettings unthrottleUser(final String userName, final TableName tableName) {
186     return throttle(userName, tableName, null, null, 0, null);
187   }
188 
189   /**
190    * Remove the throttling for the specified user on the specified namespace.
191    * @param userName the user
192    * @param namespace the namespace
193    * @return the quota settings
194    */
unthrottleUser(final String userName, final String namespace)195   public static QuotaSettings unthrottleUser(final String userName, final String namespace) {
196     return throttle(userName, null, namespace, null, 0, null);
197   }
198 
199   /**
200    * Throttle the specified table.
201    * @param tableName the table to throttle
202    * @param type the type of throttling
203    * @param limit the allowed number of request/data per timeUnit
204    * @param timeUnit the limit time unit
205    * @return the quota settings
206    */
throttleTable(final TableName tableName, final ThrottleType type, final long limit, final TimeUnit timeUnit)207   public static QuotaSettings throttleTable(final TableName tableName, final ThrottleType type,
208       final long limit, final TimeUnit timeUnit) {
209     return throttle(null, tableName, null, type, limit, timeUnit);
210   }
211 
212   /**
213    * Remove the throttling for the specified table.
214    * @param tableName the table
215    * @return the quota settings
216    */
unthrottleTable(final TableName tableName)217   public static QuotaSettings unthrottleTable(final TableName tableName) {
218     return throttle(null, tableName, null, null, 0, null);
219   }
220 
221   /**
222    * Throttle the specified namespace.
223    * @param namespace the namespace to throttle
224    * @param type the type of throttling
225    * @param limit the allowed number of request/data per timeUnit
226    * @param timeUnit the limit time unit
227    * @return the quota settings
228    */
throttleNamespace(final String namespace, final ThrottleType type, final long limit, final TimeUnit timeUnit)229   public static QuotaSettings throttleNamespace(final String namespace, final ThrottleType type,
230       final long limit, final TimeUnit timeUnit) {
231     return throttle(null, null, namespace, type, limit, timeUnit);
232   }
233 
234   /**
235    * Remove the throttling for the specified namespace.
236    * @param namespace the namespace
237    * @return the quota settings
238    */
unthrottleNamespace(final String namespace)239   public static QuotaSettings unthrottleNamespace(final String namespace) {
240     return throttle(null, null, namespace, null, 0, null);
241   }
242 
243   /* Throttle helper */
throttle(final String userName, final TableName tableName, final String namespace, final ThrottleType type, final long limit, final TimeUnit timeUnit)244   private static QuotaSettings throttle(final String userName, final TableName tableName,
245       final String namespace, final ThrottleType type, final long limit, final TimeUnit timeUnit) {
246     QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder();
247     if (type != null) {
248       builder.setType(ProtobufUtil.toProtoThrottleType(type));
249     }
250     if (timeUnit != null) {
251       builder.setTimedQuota(ProtobufUtil.toTimedQuota(limit, timeUnit, QuotaScope.MACHINE));
252     }
253     return new ThrottleSettings(userName, tableName, namespace, builder.build());
254   }
255 
256   /*
257    * ========================================================================== Global Settings
258    */
259 
260   /**
261    * Set the "bypass global settings" for the specified user
262    * @param userName the user to throttle
263    * @param bypassGlobals true if the global settings should be bypassed
264    * @return the quota settings
265    */
bypassGlobals(final String userName, final boolean bypassGlobals)266   public static QuotaSettings bypassGlobals(final String userName, final boolean bypassGlobals) {
267     return new QuotaGlobalsSettingsBypass(userName, null, null, bypassGlobals);
268   }
269 }
270