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 /** Returns {@code true} if the quota is being violated, {@code false} otherwise. */ 078 @Override 079 public boolean isInViolation() { 080 return inViolation; 081 } 082 083 /** 084 * Returns a singleton referring to a quota which is not in violation. 085 */ 086 public static SpaceQuotaStatus notInViolation() { 087 return NOT_IN_VIOLATION; 088 } 089 090 @Override 091 public int hashCode() { 092 return new HashCodeBuilder().append(policy == null ? 0 : policy.hashCode()) 093 .append(inViolation).toHashCode(); 094 } 095 096 @Override 097 public boolean equals(Object o) { 098 if (o instanceof SpaceQuotaStatus) { 099 SpaceQuotaStatus other = (SpaceQuotaStatus) o; 100 return Objects.equals(policy, other.policy) && inViolation == other.inViolation; 101 } 102 return false; 103 } 104 105 @Override 106 public String toString() { 107 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); 108 sb.append("[policy=").append(policy); 109 sb.append(", inViolation=").append(inViolation).append("]"); 110 return sb.toString(); 111 } 112 113 public static QuotaProtos.SpaceQuotaStatus toProto(SpaceQuotaStatus status) { 114 QuotaProtos.SpaceQuotaStatus.Builder builder = QuotaProtos.SpaceQuotaStatus.newBuilder(); 115 builder.setInViolation(status.inViolation); 116 if (status.isInViolation()) { 117 builder.setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(status.getPolicy().get())); 118 } 119 return builder.build(); 120 } 121 122 public static SpaceQuotaStatus toStatus(QuotaProtos.SpaceQuotaStatus proto) { 123 if (proto.getInViolation()) { 124 return new SpaceQuotaStatus(ProtobufUtil.toViolationPolicy(proto.getViolationPolicy())); 125 } else { 126 return NOT_IN_VIOLATION; 127 } 128 } 129 } 130 131 public SpaceQuotaSnapshot(SpaceQuotaStatus quotaStatus, long usage, long limit) { 132 this.quotaStatus = Objects.requireNonNull(quotaStatus); 133 this.usage = usage; 134 this.limit = limit; 135 } 136 137 /** 138 * Returns the status of the quota. 139 */ 140 @Override 141 public SpaceQuotaStatus getQuotaStatus() { 142 return quotaStatus; 143 } 144 145 /** 146 * Returns the current usage, in bytes, of the target (e.g. table, namespace). 147 */ 148 @Override 149 public long getUsage() { 150 return usage; 151 } 152 153 /** 154 * Returns the limit, in bytes, of the target (e.g. table, namespace). 155 */ 156 @Override 157 public long getLimit() { 158 return limit; 159 } 160 161 @Override 162 public int hashCode() { 163 return new HashCodeBuilder().append(quotaStatus.hashCode()).append(usage).append(limit) 164 .toHashCode(); 165 } 166 167 @Override 168 public boolean equals(Object o) { 169 if (o instanceof SpaceQuotaSnapshot) { 170 SpaceQuotaSnapshot other = (SpaceQuotaSnapshot) o; 171 return quotaStatus.equals(other.quotaStatus) && usage == other.usage && limit == other.limit; 172 } 173 return false; 174 } 175 176 @Override 177 public String toString() { 178 StringBuilder sb = new StringBuilder(32); 179 sb.append("SpaceQuotaSnapshot[policy=").append(quotaStatus).append(", use="); 180 sb.append(StringUtils.byteDesc(usage)).append("/"); 181 sb.append(StringUtils.byteDesc(limit)).append("]"); 182 return sb.toString(); 183 } 184 185 // ProtobufUtil is in hbase-client, and this doesn't need to be public. 186 public static SpaceQuotaSnapshot toSpaceQuotaSnapshot(QuotaProtos.SpaceQuotaSnapshot proto) { 187 return new SpaceQuotaSnapshot(SpaceQuotaStatus.toStatus(proto.getQuotaStatus()), 188 proto.getQuotaUsage(), proto.getQuotaLimit()); 189 } 190 191 public static QuotaProtos.SpaceQuotaSnapshot toProtoSnapshot(SpaceQuotaSnapshot snapshot) { 192 return QuotaProtos.SpaceQuotaSnapshot.newBuilder() 193 .setQuotaStatus(SpaceQuotaStatus.toProto(snapshot.getQuotaStatus())) 194 .setQuotaUsage(snapshot.getUsage()).setQuotaLimit(snapshot.getLimit()).build(); 195 } 196 197 /** 198 * Returns a singleton that corresponds to no snapshot information. 199 */ 200 public static SpaceQuotaSnapshot getNoSuchSnapshot() { 201 return NO_SUCH_SNAPSHOT; 202 } 203}