001/**
002 * Copyright The Apache Software Foundation
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 * http://www.apache.org/licenses/LICENSE-2.0
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 */
017
018package org.apache.hadoop.hbase;
019
020import java.math.BigDecimal;
021import java.util.Objects;
022import org.apache.yetus.audience.InterfaceAudience;
023
024import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
025
026/**
027 * It is used to represent the size with different units.
028 * This class doesn't serve for the precise computation.
029 */
030@InterfaceAudience.Public
031public final class Size implements Comparable<Size> {
032  public static final Size ZERO = new Size(0, Unit.KILOBYTE);
033  private static final BigDecimal SCALE_BASE = BigDecimal.valueOf(1024D);
034
035  public enum Unit {
036    // keep the room to add more units for HBase 10.x
037    PETABYTE(100, "PB"),
038    TERABYTE(99, "TB"),
039    GIGABYTE(98, "GB"),
040    MEGABYTE(97, "MB"),
041    KILOBYTE(96, "KB"),
042    BYTE(95, "B");
043    private final int orderOfSize;
044    private final String simpleName;
045
046    Unit(int orderOfSize, String simpleName) {
047      this.orderOfSize = orderOfSize;
048      this.simpleName = simpleName;
049    }
050
051    public int getOrderOfSize() {
052      return orderOfSize;
053    }
054
055    public String getSimpleName() {
056      return simpleName;
057    }
058  }
059
060  private final double value;
061  private final Unit unit;
062
063  public Size(double value, Unit unit) {
064    if (value < 0) {
065      throw new IllegalArgumentException("The value:" + value + " can't be negative");
066    }
067    this.value = value;
068    this.unit = Preconditions.checkNotNull(unit);
069  }
070
071  /**
072   * @return size unit
073   */
074  public Unit getUnit() {
075    return unit;
076  }
077
078  /**
079   * get the value
080   */
081  public long getLongValue() {
082    return (long) value;
083  }
084
085  /**
086   * get the value
087   */
088  public double get() {
089    return value;
090  }
091
092  /**
093   * get the value which is converted to specified unit.
094   *
095   * @param unit size unit
096   * @return the converted value
097   */
098  public double get(Unit unit) {
099    if (value == 0) {
100      return value;
101    }
102    int diff = this.unit.getOrderOfSize() - unit.getOrderOfSize();
103    if (diff == 0) {
104      return value;
105    }
106
107    BigDecimal rval = BigDecimal.valueOf(value);
108    for (int i = 0; i != Math.abs(diff); ++i) {
109      rval = diff > 0 ? rval.multiply(SCALE_BASE) : rval.divide(SCALE_BASE);
110    }
111    return rval.doubleValue();
112  }
113
114  @Override
115  public int compareTo(Size other) {
116    int diff = unit.getOrderOfSize() - other.unit.getOrderOfSize();
117    if (diff == 0) {
118      return Double.compare(value, other.value);
119    }
120
121    BigDecimal thisValue = BigDecimal.valueOf(value);
122    BigDecimal otherValue = BigDecimal.valueOf(other.value);
123    if (diff > 0) {
124      for (int i = 0; i != Math.abs(diff); ++i) {
125        thisValue = thisValue.multiply(SCALE_BASE);
126      }
127    } else {
128      for (int i = 0; i != Math.abs(diff); ++i) {
129        otherValue = otherValue.multiply(SCALE_BASE);
130      }
131    }
132    return thisValue.compareTo(otherValue);
133  }
134
135  @Override
136  public String toString() {
137    return value + unit.getSimpleName();
138  }
139
140  @Override
141  public boolean equals(Object obj) {
142    if (obj == null) {
143      return false;
144    }
145    if (obj == this) {
146      return true;
147    }
148    if (obj instanceof Size) {
149      return compareTo((Size)obj) == 0;
150    }
151    return false;
152  }
153
154  @Override
155  public int hashCode() {
156    return Objects.hash(value, unit);
157  }
158}