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.commons.lang.builder.HashCodeBuilder;
22  import org.apache.hadoop.hbase.classification.InterfaceAudience;
23  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
24  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
25  
26  /**
27   * A point-in-time view of a space quota on a table.
28   */
29  @InterfaceAudience.Private
30  public class SpaceQuotaSnapshot {
31    private static final SpaceQuotaSnapshot NO_SUCH_SNAPSHOT = new SpaceQuotaSnapshot(SpaceQuotaStatus.notInViolation(), 0, Long.MAX_VALUE);
32    private final SpaceQuotaStatus quotaStatus;
33    private final long usage;
34    private final long limit;
35  
36    /**
37     * Encapsulates the state of a quota on a table. The quota may or may not be in violation.
38     * If the quota is not in violation, the violation may be null. If the quota is in violation,
39     * there is guaranteed to be a non-null violation policy.
40     */
41    @InterfaceAudience.Private
42    public static class SpaceQuotaStatus {
43      private static final SpaceQuotaStatus NOT_IN_VIOLATION = new SpaceQuotaStatus(null, false);
44      final SpaceViolationPolicy policy;
45      final boolean inViolation;
46  
47      /**
48       * Constructs a {@code SpaceQuotaSnapshot} which is in violation of the provided {@code policy}.
49       *
50       * Use {@link #notInViolation()} to obtain an instance of this class for the cases when the
51       * quota is not in violation.
52       *
53       * @param policy The non-null policy being violated.
54       */
55      public SpaceQuotaStatus(SpaceViolationPolicy policy) {
56        // If the caller is instantiating a status, the policy must be non-null
57        this (Objects.requireNonNull(policy), true);
58      }
59  
60      private SpaceQuotaStatus(SpaceViolationPolicy policy, boolean inViolation) {
61        this.policy = policy;
62        this.inViolation = inViolation;
63      }
64  
65      /**
66       * Returns the violation policy, which may be null. It is guaranteed to be non-null if
67       * {@link #isInViolation()} is {@code true}, but may be null otherwise.
68       */
69      public SpaceViolationPolicy getPolicy() {
70        return policy;
71      }
72  
73      /**
74       * @return {@code true} if the quota is being violated, {@code false} otherwise.
75       */
76      public boolean isInViolation() {
77        return inViolation;
78      }
79  
80      /**
81       * Returns a singleton referring to a quota which is not in violation. 
82       */
83      public static SpaceQuotaStatus notInViolation() {
84        return NOT_IN_VIOLATION;
85      }
86  
87      @Override
88      public int hashCode() {
89        return new HashCodeBuilder().append(policy == null ? 0 : policy.hashCode())
90            .append(inViolation).toHashCode();
91      }
92  
93      @Override
94      public boolean equals(Object o) {
95        if (o instanceof SpaceQuotaStatus) {
96          SpaceQuotaStatus other = (SpaceQuotaStatus) o;
97          return Objects.equals(policy, other.policy) && inViolation == other.inViolation;
98        }
99        return false;
100     }
101 
102     @Override
103     public String toString() {
104       StringBuilder sb = new StringBuilder(getClass().getSimpleName());
105       sb.append("[policy=").append(policy);
106       sb.append(", inViolation=").append(inViolation).append("]");
107       return sb.toString();
108     }
109 
110     public static QuotaProtos.SpaceQuotaStatus toProto(SpaceQuotaStatus status) {
111       QuotaProtos.SpaceQuotaStatus.Builder builder = QuotaProtos.SpaceQuotaStatus.newBuilder();
112       builder.setInViolation(status.inViolation);
113       if (status.isInViolation()) {
114         builder.setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(status.getPolicy()));
115       }
116       return builder.build();
117     }
118 
119     public static SpaceQuotaStatus toStatus(QuotaProtos.SpaceQuotaStatus proto) {
120       if (proto.getInViolation()) {
121         return new SpaceQuotaStatus(ProtobufUtil.toViolationPolicy(proto.getViolationPolicy()));
122       } else {
123         return NOT_IN_VIOLATION;
124       }
125     }
126   }
127 
128   public SpaceQuotaSnapshot(SpaceQuotaStatus quotaStatus, long usage, long limit) {
129     this.quotaStatus = Objects.requireNonNull(quotaStatus);
130     this.usage = usage;
131     this.limit = limit;
132   }
133 
134   /**
135    * Returns the status of the quota.
136    */
137   public SpaceQuotaStatus getQuotaStatus() {
138     return quotaStatus;
139   }
140 
141   /**
142    * Returns the current usage, in bytes, of the target (e.g. table, namespace).
143    */
144   public long getUsage() {
145     return usage;
146   }
147 
148   /**
149    * Returns the limit, in bytes, of the target (e.g. table, namespace).
150    */
151   public long getLimit() {
152     return limit;
153   }
154 
155   @Override
156   public int hashCode() {
157     return new HashCodeBuilder()
158         .append(quotaStatus.hashCode())
159         .append(usage)
160         .append(limit)
161         .toHashCode();
162   }
163 
164   @Override
165   public boolean equals(Object o) {
166     if (o instanceof SpaceQuotaSnapshot) {
167       SpaceQuotaSnapshot other = (SpaceQuotaSnapshot) o;
168       return quotaStatus.equals(other.quotaStatus) && usage == other.usage && limit == other.limit;
169     }
170     return false;
171   }
172 
173   @Override
174   public String toString() {
175     StringBuilder sb = new StringBuilder(32);
176     sb.append("SpaceQuotaSnapshot[policy=").append(quotaStatus).append(", use=");
177     sb.append(usage).append("bytes/").append(limit).append("bytes]");
178     return sb.toString();
179   }
180 
181   // ProtobufUtil is in hbase-client, and this doesn't need to be public.
182   public static SpaceQuotaSnapshot toSpaceQuotaSnapshot(QuotaProtos.SpaceQuotaSnapshot proto) {
183     return new SpaceQuotaSnapshot(SpaceQuotaStatus.toStatus(proto.getQuotaStatus()),
184         proto.getQuotaUsage(), proto.getQuotaLimit());
185   }
186 
187   public static QuotaProtos.SpaceQuotaSnapshot toProtoSnapshot(SpaceQuotaSnapshot snapshot) {
188     return QuotaProtos.SpaceQuotaSnapshot.newBuilder()
189         .setQuotaStatus(SpaceQuotaStatus.toProto(snapshot.getQuotaStatus()))
190         .setQuotaUsage(snapshot.getUsage()).setQuotaLimit(snapshot.getLimit()).build();
191   }
192 
193   public static SpaceQuotaSnapshot getNoSuchSnapshot() {
194     return NO_SUCH_SNAPSHOT;
195   }
196 }