View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.hadoop.hbase.quotas;
18  
19  import java.util.Objects;
20  
21  import org.apache.hadoop.hbase.TableName;
22  import org.apache.hadoop.hbase.classification.InterfaceAudience;
23  import org.apache.hadoop.hbase.classification.InterfaceStability;
24  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
25  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
26  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest.Builder;
27  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceLimitRequest;
28  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceQuota;
29  
30  /**
31   * A {@link QuotaSettings} implementation for configuring filesystem-use quotas.
32   */
33  @InterfaceAudience.Private
34  @InterfaceStability.Evolving
35  class SpaceLimitSettings extends QuotaSettings {
36  
37    private final SpaceLimitRequest proto;
38  
39    SpaceLimitSettings(TableName tableName, long sizeLimit, SpaceViolationPolicy violationPolicy) {
40      super(null, Objects.requireNonNull(tableName), null);
41      if (sizeLimit < 0L) {
42        throw new IllegalArgumentException("Size limit must be a non-negative value.");
43      }
44      proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
45    }
46  
47    /**
48     * Constructs a {@code SpaceLimitSettings} to remove a space quota on the given {@code tableName}.
49     */
50    SpaceLimitSettings(TableName tableName) {
51      super(null, Objects.requireNonNull(tableName), null);
52      proto = buildProtoRemoveQuota();
53    }
54  
55    SpaceLimitSettings(String namespace, long sizeLimit, SpaceViolationPolicy violationPolicy) {
56      super(null, null, Objects.requireNonNull(namespace));
57      if (sizeLimit < 0L) {
58        throw new IllegalArgumentException("Size limit must be a non-negative value.");
59      }
60      proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy));
61    }
62  
63    /**
64     * Constructs a {@code SpaceLimitSettings} to remove a space quota on the given {@code namespace}.
65     */
66    SpaceLimitSettings(String namespace) {
67      super(null, null, Objects.requireNonNull(namespace));
68      proto = buildProtoRemoveQuota();
69    }
70  
71    /**
72     * Builds a {@link SpaceQuota} protobuf object given the arguments.
73     *
74     * @param sizeLimit The size limit of the quota.
75     * @param violationPolicy The action to take when the quota is exceeded.
76     * @return The protobuf SpaceQuota representation.
77     */
78    private SpaceLimitRequest buildProtoAddQuota(
79        long sizeLimit, SpaceViolationPolicy violationPolicy) {
80      return SpaceLimitRequest.newBuilder().setQuota(
81          SpaceQuota.newBuilder()
82              .setSoftLimit(sizeLimit)
83              .setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(violationPolicy))
84              .build())
85          .build();
86    }
87  
88    /**
89     * Builds a {@link SpaceQuota} protobuf object to remove a quota.
90     *
91     * @return The protobuf SpaceQuota representation.
92     */
93    private SpaceLimitRequest buildProtoRemoveQuota() {
94      return SpaceLimitRequest.newBuilder().setQuota(
95          SpaceQuota.newBuilder()
96              .setRemove(true)
97              .build())
98          .build();
99    }
100 
101   /**
102    * Returns a copy of the internal state of <code>this</code>
103    */
104   SpaceLimitRequest getProto() {
105     return proto.toBuilder().build();
106   }
107 
108   @Override
109   public QuotaType getQuotaType() {
110     return QuotaType.SPACE;
111   }
112 
113   @Override
114   protected void setupSetQuotaRequest(Builder builder) {
115     // TableName/Namespace are serialized in QuotaSettings
116     builder.setSpaceLimit(proto);
117   }
118 
119   /**
120    * Constructs a {@link SpaceLimitSettings} from the provided protobuf message and tablename.
121    *
122    * @param tableName The target tablename for the limit.
123    * @param proto The protobuf representation.
124    * @return A QuotaSettings.
125    */
126   static SpaceLimitSettings fromSpaceQuota(
127       final TableName tableName, final QuotaProtos.SpaceQuota proto) {
128     validateProtoArguments(proto);
129     return new SpaceLimitSettings(tableName, proto.getSoftLimit(),
130         ProtobufUtil.toViolationPolicy(proto.getViolationPolicy()));
131   }
132 
133   /**
134    * Constructs a {@link SpaceLimitSettings} from the provided protobuf message and namespace.
135    *
136    * @param namespace The target namespace for the limit.
137    * @param proto The protobuf representation.
138    * @return A QuotaSettings.
139    */
140   static SpaceLimitSettings fromSpaceQuota(
141       final String namespace, final QuotaProtos.SpaceQuota proto) {
142     validateProtoArguments(proto);
143     return new SpaceLimitSettings(namespace, proto.getSoftLimit(),
144         ProtobufUtil.toViolationPolicy(proto.getViolationPolicy()));
145   }
146 
147   /**
148    * Validates that the provided protobuf SpaceQuota has the necessary information to construct
149    * a {@link SpaceLimitSettings}.
150    *
151    * @param proto The protobuf message to validate.
152    */
153   static void validateProtoArguments(final QuotaProtos.SpaceQuota proto) {
154     if (!Objects.requireNonNull(proto).hasSoftLimit()) {
155       throw new IllegalArgumentException("Cannot handle SpaceQuota without a soft limit");
156     }
157     if (!proto.hasViolationPolicy()) {
158       throw new IllegalArgumentException("Cannot handle SpaceQuota without a violation policy");
159     }
160   }
161 
162   @Override
163   public int hashCode() {
164     return Objects.hash(getTableName(), getNamespace(), proto);
165   }
166 
167   @Override
168   public boolean equals(Object o) {
169     if (o == this) {
170       return true;
171     }
172     if (!(o instanceof SpaceLimitSettings)) {
173       return false;
174     }
175     // o is non-null and an instance of SpaceLimitSettings
176     SpaceLimitSettings other = (SpaceLimitSettings) o;
177     return Objects.equals(getTableName(), other.getTableName()) &&
178         Objects.equals(getNamespace(), other.getNamespace()) &&
179         Objects.equals(proto, other.proto);
180   }
181 
182   @Override
183   public String toString() {
184     StringBuilder sb = new StringBuilder();
185     sb.append("TYPE => SPACE");
186     if (getTableName() != null) {
187       sb.append(", TABLE => ").append(getTableName());
188     }
189     if (getNamespace() != null) {
190       sb.append(", NAMESPACE => ").append(getNamespace());
191     }
192     if (proto.getQuota().getRemove()) {
193       sb.append(", REMOVE => ").append(proto.getQuota().getRemove());
194     } else {
195       sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit());
196       sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy());
197     }
198     return sb.toString();
199   }
200 }