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