001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.quotas; 019 020import java.util.Objects; 021import java.util.Optional; 022import org.apache.commons.lang3.builder.HashCodeBuilder; 023import org.apache.hadoop.util.StringUtils; 024import org.apache.yetus.audience.InterfaceAudience; 025 026import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 027import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos; 028 029/** 030 * A point-in-time view of a space quota on a table. 031 */ 032@InterfaceAudience.Private 033public class SpaceQuotaSnapshot implements SpaceQuotaSnapshotView { 034 private static final SpaceQuotaSnapshot NO_SUCH_SNAPSHOT = 035 new SpaceQuotaSnapshot(SpaceQuotaStatus.notInViolation(), 0, Long.MAX_VALUE); 036 private final SpaceQuotaStatus quotaStatus; 037 private final long usage; 038 private final long limit; 039 040 /** 041 * Encapsulates the state of a quota on a table. The quota may or may not be in violation. If the 042 * quota is not in violation, the violation may be null. If the quota is in violation, there is 043 * guaranteed to be a non-null violation policy. 044 */ 045 @InterfaceAudience.Private 046 public static class SpaceQuotaStatus implements SpaceQuotaStatusView { 047 private static final SpaceQuotaStatus NOT_IN_VIOLATION = new SpaceQuotaStatus(null, false); 048 final Optional<SpaceViolationPolicy> policy; 049 final boolean inViolation; 050 051 /** 052 * Constructs a {@code SpaceQuotaSnapshot} which is in violation of the provided {@code policy}. 053 * <p/> 054 * Use {@link #notInViolation()} to obtain an instance of this class for the cases when the 055 * quota is not in violation. 056 * @param policy The non-null policy being violated. 057 */ 058 public SpaceQuotaStatus(SpaceViolationPolicy policy) { 059 // If the caller is instantiating a status, the policy must be non-null 060 this(Objects.requireNonNull(policy), true); 061 } 062 063 private SpaceQuotaStatus(SpaceViolationPolicy policy, boolean inViolation) { 064 this.policy = Optional.ofNullable(policy); 065 this.inViolation = inViolation; 066 } 067 068 /** 069 * Returns the violation policy, which may be null. It is guaranteed to be non-null if 070 * {@link #isInViolation()} is {@code true}, but may be null otherwise. 071 */ 072 @Override 073 public Optional<SpaceViolationPolicy> getPolicy() { 074 return policy; 075 } 076 077 /** 078 * @return {@code true} if the quota is being violated, {@code false} otherwise. 079 */ 080 @Override 081 public boolean isInViolation() { 082 return inViolation; 083 } 084 085 /** 086 * Returns a singleton referring to a quota which is not in violation. 087 */ 088 public static SpaceQuotaStatus notInViolation() { 089 return NOT_IN_VIOLATION; 090 } 091 092 @Override 093 public int hashCode() { 094 return new HashCodeBuilder().append(policy == null ? 0 : policy.hashCode()) 095 .append(inViolation).toHashCode(); 096 } 097 098 @Override 099 public boolean equals(Object o) { 100 if (o instanceof SpaceQuotaStatus) { 101 SpaceQuotaStatus other = (SpaceQuotaStatus) o; 102 return Objects.equals(policy, other.policy) && inViolation == other.inViolation; 103 } 104 return false; 105 } 106 107 @Override 108 public String toString() { 109 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); 110 sb.append("[policy=").append(policy); 111 sb.append(", inViolation=").append(inViolation).append("]"); 112 return sb.toString(); 113 } 114 115 public static QuotaProtos.SpaceQuotaStatus toProto(SpaceQuotaStatus status) { 116 QuotaProtos.SpaceQuotaStatus.Builder builder = QuotaProtos.SpaceQuotaStatus.newBuilder(); 117 builder.setInViolation(status.inViolation); 118 if (status.isInViolation()) { 119 builder.setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(status.getPolicy().get())); 120 } 121 return builder.build(); 122 } 123 124 public static SpaceQuotaStatus toStatus(QuotaProtos.SpaceQuotaStatus proto) { 125 if (proto.getInViolation()) { 126 return new SpaceQuotaStatus(ProtobufUtil.toViolationPolicy(proto.getViolationPolicy())); 127 } else { 128 return NOT_IN_VIOLATION; 129 } 130 } 131 } 132 133 public SpaceQuotaSnapshot(SpaceQuotaStatus quotaStatus, long usage, long limit) { 134 this.quotaStatus = Objects.requireNonNull(quotaStatus); 135 this.usage = usage; 136 this.limit = limit; 137 } 138 139 /** 140 * Returns the status of the quota. 141 */ 142 @Override 143 public SpaceQuotaStatus getQuotaStatus() { 144 return quotaStatus; 145 } 146 147 /** 148 * Returns the current usage, in bytes, of the target (e.g. table, namespace). 149 */ 150 @Override 151 public long getUsage() { 152 return usage; 153 } 154 155 /** 156 * Returns the limit, in bytes, of the target (e.g. table, namespace). 157 */ 158 @Override 159 public long getLimit() { 160 return limit; 161 } 162 163 @Override 164 public int hashCode() { 165 return new HashCodeBuilder().append(quotaStatus.hashCode()).append(usage).append(limit) 166 .toHashCode(); 167 } 168 169 @Override 170 public boolean equals(Object o) { 171 if (o instanceof SpaceQuotaSnapshot) { 172 SpaceQuotaSnapshot other = (SpaceQuotaSnapshot) o; 173 return quotaStatus.equals(other.quotaStatus) && usage == other.usage && limit == other.limit; 174 } 175 return false; 176 } 177 178 @Override 179 public String toString() { 180 StringBuilder sb = new StringBuilder(32); 181 sb.append("SpaceQuotaSnapshot[policy=").append(quotaStatus).append(", use="); 182 sb.append(StringUtils.byteDesc(usage)).append("/"); 183 sb.append(StringUtils.byteDesc(limit)).append("]"); 184 return sb.toString(); 185 } 186 187 // ProtobufUtil is in hbase-client, and this doesn't need to be public. 188 public static SpaceQuotaSnapshot toSpaceQuotaSnapshot(QuotaProtos.SpaceQuotaSnapshot proto) { 189 return new SpaceQuotaSnapshot(SpaceQuotaStatus.toStatus(proto.getQuotaStatus()), 190 proto.getQuotaUsage(), proto.getQuotaLimit()); 191 } 192 193 public static QuotaProtos.SpaceQuotaSnapshot toProtoSnapshot(SpaceQuotaSnapshot snapshot) { 194 return QuotaProtos.SpaceQuotaSnapshot.newBuilder() 195 .setQuotaStatus(SpaceQuotaStatus.toProto(snapshot.getQuotaStatus())) 196 .setQuotaUsage(snapshot.getUsage()).setQuotaLimit(snapshot.getLimit()).build(); 197 } 198 199 /** 200 * Returns a singleton that corresponds to no snapshot information. 201 */ 202 public static SpaceQuotaSnapshot getNoSuchSnapshot() { 203 return NO_SUCH_SNAPSHOT; 204 } 205}