View Javadoc

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  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceQuota;
25  
26  @InterfaceAudience.Public
27  @InterfaceStability.Evolving
28  public class QuotaSettingsFactory {
29    private QuotaSettingsFactory() {
30      // Utility class
31    }
32  
33    static class QuotaGlobalsSettingsBypass extends QuotaSettings {
34      private final boolean bypassGlobals;
35  
36      QuotaGlobalsSettingsBypass(final String userName, final TableName tableName,
37          final String namespace, final boolean bypassGlobals) {
38        super(userName, tableName, namespace);
39        this.bypassGlobals = bypassGlobals;
40      }
41  
42      @Override
43      public QuotaType getQuotaType() {
44        return QuotaType.GLOBAL_BYPASS;
45      }
46  
47      @Override
48      protected void setupSetQuotaRequest(SetQuotaRequest.Builder builder) {
49        builder.setBypassGlobals(bypassGlobals);
50      }
51  
52      @Override
53      public String toString() {
54        return "GLOBAL_BYPASS => " + bypassGlobals;
55      }
56    }
57  
58    /*
59     * ========================================================================== QuotaSettings from
60     * the Quotas object
61     */
62    static List<QuotaSettings> fromUserQuotas(final String userName, final Quotas quotas) {
63      return fromQuotas(userName, null, null, quotas);
64    }
65  
66    static List<QuotaSettings> fromUserQuotas(final String userName, final TableName tableName,
67        final Quotas quotas) {
68      return fromQuotas(userName, tableName, null, quotas);
69    }
70  
71    static List<QuotaSettings> fromUserQuotas(final String userName, final String namespace,
72        final Quotas quotas) {
73      return fromQuotas(userName, null, namespace, quotas);
74    }
75  
76    static List<QuotaSettings> fromTableQuotas(final TableName tableName, final Quotas quotas) {
77      return fromQuotas(null, tableName, null, quotas);
78    }
79  
80    static List<QuotaSettings> fromNamespaceQuotas(final String namespace, final Quotas quotas) {
81      return fromQuotas(null, null, namespace, quotas);
82    }
83  
84    private static List<QuotaSettings> fromQuotas(final String userName, final TableName tableName,
85        final String namespace, final Quotas quotas) {
86      List<QuotaSettings> settings = new ArrayList<QuotaSettings>();
87      if (quotas.hasThrottle()) {
88        settings.addAll(fromThrottle(userName, tableName, namespace, quotas.getThrottle()));
89      }
90      if (quotas.getBypassGlobals() == true) {
91        settings.add(new QuotaGlobalsSettingsBypass(userName, tableName, namespace, true));
92      }
93      if (quotas.hasSpace()) {
94        settings.add(fromSpace(tableName, namespace, quotas.getSpace()));
95      }
96      return settings;
97    }
98  
99    private static List<QuotaSettings> fromThrottle(final String userName, final TableName tableName,
100       final String namespace, final QuotaProtos.Throttle throttle) {
101     List<QuotaSettings> settings = new ArrayList<QuotaSettings>();
102     if (throttle.hasReqNum()) {
103       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
104         ThrottleType.REQUEST_NUMBER, throttle.getReqNum()));
105     }
106     if (throttle.hasReqSize()) {
107       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
108         ThrottleType.REQUEST_SIZE, throttle.getReqSize()));
109     }
110     if (throttle.hasWriteNum()) {
111       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
112           ThrottleType.WRITE_NUMBER, throttle.getWriteNum()));
113     }
114     if (throttle.hasWriteSize()) {
115       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
116           ThrottleType.WRITE_SIZE, throttle.getWriteSize()));
117     }
118     if (throttle.hasReadNum()) {
119       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
120           ThrottleType.READ_NUMBER, throttle.getReadNum()));
121     }
122     if (throttle.hasReadSize()) {
123       settings.add(ThrottleSettings.fromTimedQuota(userName, tableName, namespace,
124           ThrottleType.READ_SIZE, throttle.getReadSize()));
125     }
126     return settings;
127   }
128 
129   static QuotaSettings fromSpace(TableName table, String namespace, SpaceQuota protoQuota) {
130     if ((table == null && namespace == null) || (table != null && namespace != null)) {
131       throw new IllegalArgumentException(
132           "Can only construct SpaceLimitSettings for a table or namespace.");
133     }
134     if (table != null) {
135       return SpaceLimitSettings.fromSpaceQuota(table, protoQuota);
136     } else {
137       // namespace must be non-null
138       return SpaceLimitSettings.fromSpaceQuota(namespace, protoQuota);
139     }
140   }
141 
142   /* ==========================================================================
143    *  RPC Throttle
144    */
145 
146   /**
147    * Throttle the specified user.
148    * @param userName the user to throttle
149    * @param type the type of throttling
150    * @param limit the allowed number of request/data per timeUnit
151    * @param timeUnit the limit time unit
152    * @return the quota settings
153    */
154   public static QuotaSettings throttleUser(final String userName, final ThrottleType type,
155       final long limit, final TimeUnit timeUnit) {
156     return throttle(userName, null, null, type, limit, timeUnit);
157   }
158 
159   /**
160    * Throttle the specified user on the specified table.
161    * @param userName the user to throttle
162    * @param tableName the table to throttle
163    * @param type the type of throttling
164    * @param limit the allowed number of request/data per timeUnit
165    * @param timeUnit the limit time unit
166    * @return the quota settings
167    */
168   public static QuotaSettings throttleUser(final String userName, final TableName tableName,
169       final ThrottleType type, final long limit, final TimeUnit timeUnit) {
170     return throttle(userName, tableName, null, type, limit, timeUnit);
171   }
172 
173   /**
174    * Throttle the specified user on the specified namespace.
175    * @param userName the user to throttle
176    * @param namespace the namespace to throttle
177    * @param type the type of throttling
178    * @param limit the allowed number of request/data per timeUnit
179    * @param timeUnit the limit time unit
180    * @return the quota settings
181    */
182   public static QuotaSettings throttleUser(final String userName, final String namespace,
183       final ThrottleType type, final long limit, final TimeUnit timeUnit) {
184     return throttle(userName, null, namespace, type, limit, timeUnit);
185   }
186 
187   /**
188    * Remove the throttling for the specified user.
189    * @param userName the user
190    * @return the quota settings
191    */
192   public static QuotaSettings unthrottleUser(final String userName) {
193     return throttle(userName, null, null, null, 0, null);
194   }
195 
196   /**
197    * Remove the throttling for the specified user on the specified table.
198    * @param userName the user
199    * @param tableName the table
200    * @return the quota settings
201    */
202   public static QuotaSettings unthrottleUser(final String userName, final TableName tableName) {
203     return throttle(userName, tableName, null, null, 0, null);
204   }
205 
206   /**
207    * Remove the throttling for the specified user on the specified namespace.
208    * @param userName the user
209    * @param namespace the namespace
210    * @return the quota settings
211    */
212   public static QuotaSettings unthrottleUser(final String userName, final String namespace) {
213     return throttle(userName, null, namespace, null, 0, null);
214   }
215 
216   /**
217    * Throttle the specified table.
218    * @param tableName the table to throttle
219    * @param type the type of throttling
220    * @param limit the allowed number of request/data per timeUnit
221    * @param timeUnit the limit time unit
222    * @return the quota settings
223    */
224   public static QuotaSettings throttleTable(final TableName tableName, final ThrottleType type,
225       final long limit, final TimeUnit timeUnit) {
226     return throttle(null, tableName, null, type, limit, timeUnit);
227   }
228 
229   /**
230    * Remove the throttling for the specified table.
231    * @param tableName the table
232    * @return the quota settings
233    */
234   public static QuotaSettings unthrottleTable(final TableName tableName) {
235     return throttle(null, tableName, null, null, 0, null);
236   }
237 
238   /**
239    * Throttle the specified namespace.
240    * @param namespace the namespace to throttle
241    * @param type the type of throttling
242    * @param limit the allowed number of request/data per timeUnit
243    * @param timeUnit the limit time unit
244    * @return the quota settings
245    */
246   public static QuotaSettings throttleNamespace(final String namespace, final ThrottleType type,
247       final long limit, final TimeUnit timeUnit) {
248     return throttle(null, null, namespace, type, limit, timeUnit);
249   }
250 
251   /**
252    * Remove the throttling for the specified namespace.
253    * @param namespace the namespace
254    * @return the quota settings
255    */
256   public static QuotaSettings unthrottleNamespace(final String namespace) {
257     return throttle(null, null, namespace, null, 0, null);
258   }
259 
260   /* Throttle helper */
261   private static QuotaSettings throttle(final String userName, final TableName tableName,
262       final String namespace, final ThrottleType type, final long limit, final TimeUnit timeUnit) {
263     QuotaProtos.ThrottleRequest.Builder builder = QuotaProtos.ThrottleRequest.newBuilder();
264     if (type != null) {
265       builder.setType(ProtobufUtil.toProtoThrottleType(type));
266     }
267     if (timeUnit != null) {
268       builder.setTimedQuota(ProtobufUtil.toTimedQuota(limit, timeUnit, QuotaScope.MACHINE));
269     }
270     return new ThrottleSettings(userName, tableName, namespace, builder.build());
271   }
272 
273   /*
274    * ========================================================================== Global Settings
275    */
276 
277   /**
278    * Set the "bypass global settings" for the specified user
279    * @param userName the user to throttle
280    * @param bypassGlobals true if the global settings should be bypassed
281    * @return the quota settings
282    */
283   public static QuotaSettings bypassGlobals(final String userName, final boolean bypassGlobals) {
284     return new QuotaGlobalsSettingsBypass(userName, null, null, bypassGlobals);
285   }
286 
287   /* ==========================================================================
288    *  FileSystem Space Settings
289    */
290 
291   /**
292    * Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given table
293    * to the given size in bytes. When the space usage is exceeded by the table, the provided
294    * {@link SpaceViolationPolicy} is enacted on the table.
295    *
296    * @param tableName The name of the table on which the quota should be applied.
297    * @param sizeLimit The limit of a table's size in bytes.
298    * @param violationPolicy The action to take when the quota is exceeded.
299    * @return An {@link QuotaSettings} object.
300    */
301   public static QuotaSettings limitTableSpace(
302       final TableName tableName, long sizeLimit, final SpaceViolationPolicy violationPolicy) {
303     return new SpaceLimitSettings(tableName, sizeLimit, violationPolicy);
304   }
305 
306   /**
307    * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given
308    * table.
309    *
310    * @param tableName The name of the table to remove the quota for.
311    * @return A {@link QuotaSettings} object.
312    */
313   public static QuotaSettings removeTableSpaceLimit(TableName tableName) {
314     return new SpaceLimitSettings(tableName);
315   }
316 
317   /**
318    * Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given
319    * namespace to the given size in bytes. When the space usage is exceeded by all tables in the
320    * namespace, the provided {@link SpaceViolationPolicy} is enacted on all tables in the namespace.
321    *
322    * @param namespace The namespace on which the quota should be applied.
323    * @param sizeLimit The limit of the namespace's size in bytes.
324    * @param violationPolicy The action to take when the the quota is exceeded.
325    * @return An {@link QuotaSettings} object.
326    */
327   public static QuotaSettings limitNamespaceSpace(
328       final String namespace, long sizeLimit, final SpaceViolationPolicy violationPolicy) {
329     return new SpaceLimitSettings(namespace, sizeLimit, violationPolicy);
330   }
331 
332   /**
333    * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given
334    * namespace.
335    *
336    * @param namespace The namespace to remove the quota on.
337    * @return A {@link QuotaSettings} object.
338    */
339   public static QuotaSettings removeNamespaceSpaceLimit(String namespace) {
340     return new SpaceLimitSettings(namespace);
341   }
342 }