Mercurial > hg > release > thermostat-0.5
changeset 885:7c97a7125993
Replace DisplayableValues with a Quantity pattern implementation
The existing DisplayableValues class does a few things in a rather
haphazard way with responsibilities split strangely between
DisplayableValues and Scale classes.
Replace it with a new class called Size that implements the Quantity
pattern and replace all uses of DisplayableValues with that.
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-January/004972.html
line wrap: on
line diff
--- a/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/LocaleResources.java Wed Jan 02 09:47:39 2013 -0500 +++ b/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/LocaleResources.java Thu Jan 03 10:23:48 2013 -0500 @@ -42,8 +42,6 @@ MISSING_INFO, - VALUE_AND_UNIT, - HOST_SERVICE_UNAVAILABLE, VM_SERVICE_UNAVAILABLE, VM_CPU_SERVICE_NOT_AVAILABLE,
--- a/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/VMStatPrinter.java Wed Jan 02 09:47:39 2013 -0500 +++ b/client/cli/src/main/java/com/redhat/thermostat/client/cli/internal/VMStatPrinter.java Thu Jan 03 10:23:48 2013 -0500 @@ -46,12 +46,12 @@ import java.util.List; import java.util.NoSuchElementException; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.cli.TableRenderer; import com.redhat.thermostat.common.dao.VmCpuStatDAO; import com.redhat.thermostat.common.dao.VmMemoryStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues; import com.redhat.thermostat.storage.model.TimeStampedPojo; import com.redhat.thermostat.storage.model.TimeStampedPojoComparator; import com.redhat.thermostat.storage.model.TimeStampedPojoCorrelator; @@ -160,8 +160,7 @@ int i = 0; for (VmMemoryStat.Generation gen : vmMemoryStat.getGenerations()) { for (VmMemoryStat.Space space : gen.getSpaces()) { - String[] displayableSize = DisplayableValues.bytes(space.getUsed()); - memoryUsage[i] = translator.localize(LocaleResources.VALUE_AND_UNIT, displayableSize[0], displayableSize[1]); + memoryUsage[i] = Size.bytes(space.getUsed()).toString(); i++; } }
--- a/client/cli/src/main/resources/com/redhat/thermostat/client/cli/strings.properties Wed Jan 02 09:47:39 2013 -0500 +++ b/client/cli/src/main/resources/com/redhat/thermostat/client/cli/strings.properties Thu Jan 03 10:23:48 2013 -0500 @@ -1,7 +1,5 @@ MISSING_INFO = Missing Information -VALUE_AND_UNIT = {0} {1} - HOST_SERVICE_UNAVAILABLE = Unable to get host information (HostInfoDAO is unavailable) VM_SERVICE_UNAVAILABLE = Unable to get vm information (VmInfoDAO is unavailable) VM_CPU_SERVICE_NOT_AVAILABLE = Unable to access vm cpu information (VmCpuStats not available)
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/BytesTickUnit.java Wed Jan 02 09:47:39 2013 -0500 +++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/BytesTickUnit.java Thu Jan 03 10:23:48 2013 -0500 @@ -39,7 +39,7 @@ import org.jfree.chart.axis.NumberTickUnit; import org.jfree.chart.axis.TickUnit; -import com.redhat.thermostat.common.utils.DisplayableValues; +import com.redhat.thermostat.common.Size; /** * A {@link TickUnit} that displays a byte value with an appropriate @@ -54,7 +54,6 @@ @Override public String valueToString(double value) { - String[] displayable = DisplayableValues.bytes((long) value); - return displayable[0] + " " + displayable[1]; + return Size.bytes((long)value).toString(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/Size.java Thu Jan 03 10:23:48 2013 -0500 @@ -0,0 +1,204 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common; + +import java.util.Objects; + +import com.redhat.thermostat.common.locale.LocaleResources; +import com.redhat.thermostat.common.locale.Translate; + +/** + * Represents a size (of a file, memory, or disk) with a number and a unit. + * <p> + * Once created, an instance of this class is immutable. All operations that + * modify this will return new objects. + */ +public class Size { + + /* This is the Quantity pattern. */ + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + private static final String DOUBLE_FORMAT_STRING = "%.1f"; + + private static final long BYTES_IN_KiB = 1024; + private static final long BYTES_IN_MiB = 1024 * BYTES_IN_KiB; + private static final long BYTES_IN_GiB = 1024 * BYTES_IN_MiB; + private static final long BYTES_IN_TiB = 1024 * BYTES_IN_GiB; + + public enum Unit { + B(1), + KiB(BYTES_IN_KiB), + MiB(BYTES_IN_MiB), + GiB(BYTES_IN_GiB), + TiB(BYTES_IN_TiB); + + private long numBytes; + + private Unit(long numBytes) { + this.numBytes = numBytes; + } + + private long getNumBytes() { + return numBytes; + } + + public static Unit getBestUnit(long bytes) { + if (bytes < BYTES_IN_KiB) { + return Unit.B; + } else if (bytes < BYTES_IN_MiB) { + return Unit.KiB; + } else if (bytes < BYTES_IN_GiB) { + return Unit.MiB; + } else if (bytes < BYTES_IN_TiB) { + return Unit.GiB; + } else { + return Unit.TiB; + } + } + } + + private final double amount; + private final Unit unit; + + public Size(double amount, Unit unit) { + this.amount = amount; + this.unit = Objects.requireNonNull(unit); + } + + public double getValue() { + return amount; + } + + public Unit getUnit() { + return unit; + } + + public Size convertTo(Unit target) { + return new Size(1.0 * amount * unit.getNumBytes() / target.getNumBytes(), target); + } + + @Override + public int hashCode() { + return Objects.hash(amount, unit); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Size)) { + return false; + } + Size other = (Size) obj; + return this.getValue() == other.convertTo(this.getUnit()).getValue(); + } + + // TODO consider implementing these operations: + // + // public int compareTo(Object other) + // + // public boolean greaterThan(Size other) { } + // + // public boolean lessThan(Size other) { } + // + // public Size add(Size toAdd) { } + // + // public Size subtract(Size toSubtract) { } + // + // public Size multiply(double by) { } + // + // public Size divide(double by) { } + + /** + * Returns a simplified and human-readable version of this Size + */ + @Override + public String toString() { + String[] parts = toStringParts(); + return translator.localize(LocaleResources.VALUE_AND_UNIT, parts[0], parts[1]); + } + + /** + * Returns a human-readable version of this Size, appropriate for localization. + * + * @return a two-element string array. The first element is the amount. The second element is the unit. + */ + public String[] toStringParts() { + long amountInBytes = (long) (amount * unit.getNumBytes()); + if (amountInBytes < BYTES_IN_KiB) { + // No decimal units in plain bytes + return new String[] { String.valueOf(amountInBytes), Unit.B.name() }; + } else if (amountInBytes < BYTES_IN_MiB) { + return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) amountInBytes / BYTES_IN_KiB), Unit.KiB.name() }; + } else if (amountInBytes < BYTES_IN_GiB) { + return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) amountInBytes / BYTES_IN_MiB), Unit.MiB.name() }; + } else if (amountInBytes < BYTES_IN_TiB) { + return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) amountInBytes / BYTES_IN_GiB), Unit.GiB.name() }; + } else { + return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) amountInBytes / BYTES_IN_TiB), Unit.TiB.name() }; + } + } + + public static Size bytes(long bytes) { + return new Size(bytes, Unit.B); + } + + /** + * Parses a string (such as "1.0 KiB") into a size. + */ + public static Size parse(String toParse) { + String[] parts = toParse.split(" +"); + String value = toParse; + String units = null; + if (parts.length > 1) { + value = parts[0]; + units = parts[1]; + } + + double result = Double.NaN; + try { + result = Double.parseDouble(value); + if (units != null) { + Unit parsedUnit = Unit.valueOf(units.trim()); + return new Size(result, parsedUnit); + } + return new Size(result, Unit.B); + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException("unable to parse '" + toParse + "'", nfe); + } + } + +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/locale/LocaleResources.java Wed Jan 02 09:47:39 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/locale/LocaleResources.java Thu Jan 03 10:23:48 2013 -0500 @@ -40,6 +40,8 @@ MISSING_INFO, + VALUE_AND_UNIT, + APPLICATION_INFO_LICENSE, APPLICATION_INFO_DESCRIPTION, APPLICATION_VERSION_INFO,
--- a/common/core/src/main/java/com/redhat/thermostat/common/utils/DisplayableValues.java Wed Jan 02 09:47:39 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.common.utils; - -public class DisplayableValues { - - private static final long BYTES_IN_KB = 1024; - private static final long BYTES_IN_MB = 1024*BYTES_IN_KB; - private static final long BYTES_IN_GB = 1024*BYTES_IN_MB; - private static final long BYTES_IN_TB = 1024*BYTES_IN_GB; - - public enum Scale { - B(1), - KiB(BYTES_IN_KB), - MiB(BYTES_IN_MB), - GiB(BYTES_IN_GB), - TiB(BYTES_IN_TB); - - private long numBytes; - - private Scale(long numBytes) { - this.numBytes = numBytes; - } - - public long getNumBytes() { - return numBytes; - } - - public static double convertTo(Scale scale, final long bytes) { - - return ((double) bytes) / ((double) scale.numBytes); - } - - public static double convertTo(Scale scale, final long bytes, long roundTo) { - - double result = ((double) bytes) / ((double) scale.numBytes); - result = ((double) Math.round(result * roundTo)) / roundTo; - - return result; - } - - public static long convertToBytes(final long originalValue, Scale originalScale) { - return originalValue * originalScale.numBytes; - } - - public static Scale getScale(final long bytes) { - if (bytes < BYTES_IN_KB) { - return Scale.B; - } else if (bytes < BYTES_IN_MB) { - return Scale.KiB; - } else if (bytes < BYTES_IN_GB) { - return Scale.MiB; - } else if (bytes < BYTES_IN_TB) { - return Scale.GiB; - } else { - return Scale.TiB; - } - } - } - - private static final String DOUBLE_FORMAT_STRING = "%.1f"; - - private DisplayableValues() {} // Not to be instantiated. - - public static String[] bytes(final long bytes) { - if (bytes < BYTES_IN_KB) { - return new String[] { String.valueOf(bytes), Scale.B.name() }; - } else if (bytes < BYTES_IN_MB) { - return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_KB), Scale.KiB.name() }; - } else if (bytes < BYTES_IN_GB) { - return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_MB), Scale.MiB.name() }; - } else if (bytes < BYTES_IN_TB) { - return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_GB), Scale.GiB.name() }; - } else { - return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_TB), Scale.TiB.name() }; - } - } -}
--- a/common/core/src/main/resources/com/redhat/thermostat/common/locale/strings.properties Wed Jan 02 09:47:39 2013 -0500 +++ b/common/core/src/main/resources/com/redhat/thermostat/common/locale/strings.properties Thu Jan 03 10:23:48 2013 -0500 @@ -1,5 +1,7 @@ MISSING_INFO = Missing Information +VALUE_AND_UNIT = {0} {1} + APPLICATION_INFO_DESCRIPTION = A monitoring and serviceability tool for OpenJDK APPLICATION_INFO_LICENSE = Licensed under GPLv2+ with Classpath exception # First parameter is the application name
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/test/java/com/redhat/thermostat/common/SizeTest.java Thu Jan 03 10:23:48 2013 -0500 @@ -0,0 +1,163 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; + +import java.util.Locale; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.redhat.thermostat.common.Size.Unit; + +public class SizeTest { + private static Locale defaultLocale; + + @BeforeClass + public static void setUp() { + defaultLocale = Locale.getDefault(); + Locale.setDefault(Locale.US); + } + + @AfterClass + public static void tearDown() { + Locale.setDefault(defaultLocale); + } + + @Test + public void testAccessorMethods() { + Size size = new Size(1, Size.Unit.B); + assertEquals(1, size.getValue(), 0.00001); + assertEquals(Size.Unit.B, size.getUnit()); + } + + @Test + public void testHashing() { + Size size1 = new Size(1024, Size.Unit.B); + Size size2 = new Size(1, Size.Unit.B); + + assertTrue(size1.hashCode() != size2.hashCode()); + } + + @Test + public void testEquality() { + Size size1 = new Size(1024, Size.Unit.B); + Size size2 = new Size(1, Size.Unit.KiB); + Size size3 = new Size(2, Size.Unit.KiB); + + assertEquals(size1, size2); + assertEquals(size2, size1); + assertFalse(size1.equals(size3)); + + assertFalse(size1.equals(null)); + assertFalse(size1.equals(new Object())); + } + + @Test + public void testUnitConversion() { + Size size = new Size(1024, Size.Unit.KiB); + + Size sizeInBytes = size.convertTo(Size.Unit.B); + assertEquals(1024 * 1024, sizeInBytes.getValue(), 0.001); + assertEquals(Size.Unit.B, sizeInBytes.getUnit()); + + Size sizeInMegaBytes = size.convertTo(Size.Unit.MiB); + assertEquals(1, sizeInMegaBytes.getValue(), 0.001); + assertEquals(Size.Unit.MiB, sizeInMegaBytes.getUnit()); + + assertEquals(size, sizeInBytes); + assertEquals(size, sizeInMegaBytes); + + } + + @Test + public void testToString() { + assertEquals("1 B", Size.bytes(1).toString()); + assertEquals("1023 B", Size.bytes(1023).toString()); + assertEquals("1.0 KiB", Size.bytes(1024).toString()); + assertEquals("1024.0 KiB", Size.bytes(1_048_575).toString()); + assertEquals("1.0 MiB", Size.bytes(1_048_576).toString()); + assertEquals("10.0 MiB", Size.bytes(10_480_000).toString()); + assertEquals("42.0 MiB", Size.bytes(44_040_000).toString()); + assertEquals("99.9 MiB", Size.bytes(104_752_742).toString()); + assertEquals("100.0 MiB", Size.bytes(104_857_600).toString()); + assertEquals("500.0 MiB", Size.bytes(524_288_000).toString()); + assertEquals("900.0 MiB", Size.bytes(943_718_400).toString()); + assertEquals("999.9 MiB", Size.bytes(1_048_471_000).toString()); + assertEquals("1.0 GiB", Size.bytes(1_073_741_824).toString()); + assertEquals("1.1 GiB", Size.bytes(1_181_116_000).toString()); + assertEquals("9.9 GiB", Size.bytes(10_630_044_000l).toString()); + assertEquals("99.9 GiB", Size.bytes(107_266_808_000l).toString()); + assertEquals("1.0 TiB", Size.bytes(1_099_511_627_776l).toString()); + } + + @Test + public void testParsingNumber() { + assertEquals(Size.bytes(1), Size.parse("1")); + } + + @Test + public void testParsingNumberAndUnit() { + assertEquals(Size.bytes(1), Size.parse("1 B")); + + assertEquals(new Size(1024, Unit.KiB), Size.parse("1024.0 KiB")); + } + + @Test(expected = IllegalArgumentException.class) + public void testParsingString() { + Size.parse("B"); + } + + @Test + public void testGetBestUnit() { + assertEquals(Size.Unit.KiB, Size.Unit.getBestUnit(1024)); + assertEquals(Size.Unit.B, Size.Unit.getBestUnit(999)); + + assertEquals(Size.Unit.MiB, Size.Unit.getBestUnit(943_718_400)); + assertEquals(Size.Unit.MiB, Size.Unit.getBestUnit(1_048_471_000)); + assertEquals(Size.Unit.GiB, Size.Unit.getBestUnit(1_073_741_824)); + assertEquals(Size.Unit.GiB, Size.Unit.getBestUnit(107_266_808_000l)); + + assertEquals(Size.Unit.TiB, Size.Unit.getBestUnit(1_099_511_627_776l)); + } + +}
--- a/common/core/src/test/java/com/redhat/thermostat/common/utils/DisplayableValuesTest.java Wed Jan 02 09:47:39 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.common.utils; - -import static org.junit.Assert.assertEquals; - -import java.util.Locale; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; - -public class DisplayableValuesTest { - - private static Locale defaultLocale; - - @BeforeClass - public static void setUp() { - defaultLocale = Locale.getDefault(); - Locale.setDefault(Locale.US); - } - - @AfterClass - public static void tearDown() { - Locale.setDefault(defaultLocale); - } - - @Test - public void testBytes() { - testBytesOutput("1", "B", DisplayableValues.bytes(1)); - testBytesOutput("1023", "B", DisplayableValues.bytes(1023)); - testBytesOutput("1.0", "KiB", DisplayableValues.bytes(1024)); - testBytesOutput("1024.0", "KiB", DisplayableValues.bytes(1_048_575)); - testBytesOutput("1.0", "MiB", DisplayableValues.bytes(1_048_576)); - testBytesOutput("10.0", "MiB", DisplayableValues.bytes(10_480_000)); - testBytesOutput("42.0", "MiB", DisplayableValues.bytes(44_040_000)); - testBytesOutput("99.9", "MiB", DisplayableValues.bytes(104_752_742)); - testBytesOutput("100.0", "MiB", DisplayableValues.bytes(104_857_600)); - testBytesOutput("500.0", "MiB", DisplayableValues.bytes(524_288_000)); - testBytesOutput("900.0", "MiB", DisplayableValues.bytes(943_718_400)); - testBytesOutput("999.9", "MiB", DisplayableValues.bytes(1_048_471_000)); - testBytesOutput("1.0", "GiB", DisplayableValues.bytes(1_073_741_824)); - testBytesOutput("1.1", "GiB", DisplayableValues.bytes(1_181_116_000)); - testBytesOutput("9.9", "GiB", DisplayableValues.bytes(10_630_044_000l)); - testBytesOutput("99.9", "GiB", DisplayableValues.bytes(107_266_808_000l)); - testBytesOutput("1.0", "TiB", DisplayableValues.bytes(1_099_511_627_776l)); - } - - private void testBytesOutput(String number, String units, String[] output) { - assertEquals(2, output.length); - assertEquals(number, output[0]); - assertEquals(units, output[1]); - } - - @Test - public void testScales() { - - double value = Scale.convertTo(Scale.KiB, 1024); - assertEquals(1, value, 0); - - value = Scale.convertTo(Scale.KiB, 2048); - assertEquals(2, value, 0); - - value = Scale.convertTo(Scale.KiB, 524_288); - assertEquals(512, value, 0); - - value = Scale.convertTo(Scale.MiB, 524_288_000); - assertEquals(500, value, 0); - - long longValue = Scale.convertToBytes(1, Scale.MiB); - assertEquals(1024l * 1024, longValue); - } -}
--- a/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/SWTHostMemoryView.java Wed Jan 02 09:47:39 2013 -0500 +++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/SWTHostMemoryView.java Thu Jan 03 10:23:48 2013 -0500 @@ -70,9 +70,8 @@ import com.redhat.thermostat.host.memory.client.core.HostMemoryView; import com.redhat.thermostat.host.memory.client.locale.LocaleResources; import com.redhat.thermostat.client.ui.ChartColors; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; import com.redhat.thermostat.eclipse.SWTComponent; import com.redhat.thermostat.eclipse.ThermostatConstants; import com.redhat.thermostat.storage.model.DiscreteTimeData; @@ -162,7 +161,7 @@ JFreeChart chart = ChartFactory.createTimeSeriesChart( null, // Title translator.localize(LocaleResources.HOST_MEMORY_CHART_TIME_LABEL), // x-axis Label - translator.localize(LocaleResources.HOST_MEMORY_CHART_SIZE_LABEL, Scale.MiB.name()), // y-axis Label + translator.localize(LocaleResources.HOST_MEMORY_CHART_SIZE_LABEL, Size.Unit.MiB.name()), // y-axis Label memoryCollection, // Dataset false, // Show Legend false, // Use tooltips @@ -258,7 +257,7 @@ RegularTimePeriod period = new FixedMillisecond(timeData.getTimeInMillis()); if (series.getDataItem(period) == null) { Long sizeInBytes = (Long) timeData.getData(); - Double sizeInMegaBytes = DisplayableValues.Scale.convertTo(Scale.MiB, sizeInBytes); + Double sizeInMegaBytes = Size.bytes(sizeInBytes).convertTo(Size.Unit.MiB).getValue(); series.add(new FixedMillisecond(timeData.getTimeInMillis()), sizeInMegaBytes, false); } }
--- a/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/internal/HostMemoryController.java Wed Jan 02 09:47:39 2013 -0500 +++ b/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/internal/HostMemoryController.java Thu Jan 03 10:23:48 2013 -0500 @@ -47,13 +47,13 @@ import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ApplicationService; import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.common.dao.MemoryStatDAO; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues; import com.redhat.thermostat.host.memory.client.core.HostMemoryView; import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider; import com.redhat.thermostat.host.memory.client.core.HostMemoryView.GraphVisibilityChangeListener; @@ -113,8 +113,7 @@ @Override public void run() { long memorySize = HostMemoryController.this.hostInfoDAO.getHostInfo(ref).getTotalMemory(); - String[] memorySizeParts = DisplayableValues.bytes(memorySize); - view.setTotalMemory(translator.localize(LocaleResources.NUMBER_AND_UNIT, memorySizeParts[0], memorySizeParts[1])); + view.setTotalMemory(Size.bytes(memorySize).toString()); doMemoryChartUpdate(); } });
--- a/host-memory/client-swing/src/main/java/com/redhat/thermostat/host/memory/client/swing/internal/HostMemoryPanel.java Wed Jan 02 09:47:39 2013 -0500 +++ b/host-memory/client-swing/src/main/java/com/redhat/thermostat/host/memory/client/swing/internal/HostMemoryPanel.java Thu Jan 03 10:23:48 2013 -0500 @@ -72,9 +72,8 @@ import com.redhat.thermostat.client.ui.ComponentVisibleListener; import com.redhat.thermostat.client.ui.RecentTimeSeriesChartController; import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; import com.redhat.thermostat.host.memory.client.core.HostMemoryView; import com.redhat.thermostat.host.memory.client.locale.LocaleResources; import com.redhat.thermostat.storage.model.DiscreteTimeData; @@ -210,7 +209,7 @@ RegularTimePeriod period = new FixedMillisecond(timeData.getTimeInMillis()); if (series.getDataItem(period) == null) { Long sizeInBytes = (Long) timeData.getData(); - Double sizeInMegaBytes = DisplayableValues.Scale.convertTo(Scale.MiB, sizeInBytes); + Double sizeInMegaBytes = Size.bytes(sizeInBytes).convertTo(Size.Unit.MiB).getValue(); series.add(new FixedMillisecond(timeData.getTimeInMillis()), sizeInMegaBytes, false); } } @@ -303,7 +302,7 @@ JFreeChart chart = ChartFactory.createTimeSeriesChart( translator.localize(LocaleResources.HOST_MEMORY_CHART_TITLE), // Title translator.localize(LocaleResources.HOST_MEMORY_CHART_TIME_LABEL), // x-axis Label - translator.localize(LocaleResources.HOST_MEMORY_CHART_SIZE_LABEL, Scale.MiB.name()), // y-axis Label + translator.localize(LocaleResources.HOST_MEMORY_CHART_SIZE_LABEL, Size.Unit.MiB.name()), // y-axis Label memoryCollection, // Dataset false, // Show Legend false, // Use tooltips
--- a/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/internal/HostOverviewController.java Wed Jan 02 09:47:39 2013 -0500 +++ b/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/internal/HostOverviewController.java Thu Jan 03 10:23:48 2013 -0500 @@ -48,13 +48,13 @@ import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ApplicationService; import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues; import com.redhat.thermostat.host.overview.client.core.HostOverviewView; import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider; import com.redhat.thermostat.host.overview.client.locale.LocaleResources; @@ -94,8 +94,7 @@ view.setCpuModel(hostInfo.getCpuModel()); view.setCpuCount(String.valueOf(hostInfo.getCpuCount())); - String[] parts = DisplayableValues.bytes(hostInfo.getTotalMemory()); - String readableTotalMemory = translator.localize(LocaleResources.NUMBER_AND_UNIT, parts[0], parts[1]); + String readableTotalMemory = new Size(hostInfo.getTotalMemory(), Size.Unit.B).toString(); view.setTotalMemory(readableTotalMemory); List<NetworkInterfaceInfo> networkInfo =
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java Wed Jan 02 09:47:39 2013 -0500 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java Thu Jan 03 10:23:48 2013 -0500 @@ -43,7 +43,8 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; +import com.redhat.thermostat.common.Size; +import com.redhat.thermostat.common.Size.Unit; import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.model.HostInfo; import com.redhat.thermostat.utils.ProcDataSource; @@ -76,9 +77,9 @@ } static class HostMemoryInfo { - public final long totalMemory; + public final Size totalMemory; - public HostMemoryInfo(long totalMemory) { + public HostMemoryInfo(Size totalMemory) { this.totalMemory = totalMemory; } } @@ -93,9 +94,10 @@ String hostname = getHostName(); HostCpuInfo cpuInfo = getCpuInfo(); HostMemoryInfo memoryInfo = getMemoryInfo(); + long totalMemorySize = (long) memoryInfo.totalMemory.convertTo(Unit.B).getValue(); HostOsInfo osInfo = getOsInfo(); - return new HostInfo(hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, memoryInfo.totalMemory); + return new HostInfo(hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, totalMemorySize); } HostCpuInfo getCpuInfo() { @@ -123,19 +125,19 @@ } HostMemoryInfo getMemoryInfo() { - long totalMemory = -1; + Size totalMemory = null; try (BufferedReader bufferedReader = new BufferedReader(dataSource.getMemInfoReader())) { String[] memTotalParts = bufferedReader.readLine().split(" +"); long data = Long.valueOf(memTotalParts[1]); String units = memTotalParts[2]; if (units.equals("kB")) { - totalMemory = Scale.convertToBytes(data, Scale.KiB); + totalMemory = new Size(data, Size.Unit.KiB); } } catch (IOException ioe) { logger.log(Level.WARNING, "unable to read memory info"); } - logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes"); + logger.log(Level.FINEST, "totalMemory: " + totalMemory.toString()); return new HostMemoryInfo(totalMemory); }
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java Wed Jan 02 09:47:39 2013 -0500 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java Thu Jan 03 10:23:48 2013 -0500 @@ -42,8 +42,7 @@ import java.util.logging.Logger; import com.redhat.thermostat.common.NotImplementedException; -import com.redhat.thermostat.common.utils.DisplayableValues; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.model.MemoryStat; import com.redhat.thermostat.utils.ProcDataSource; @@ -126,8 +125,9 @@ try { result = Long.parseLong(value); if (units != null) { + // /proc/meminfo uses kB instead of KiB, incorrectly if (units.equals("kB") || units.equals("KB")) { - result = Scale.convertToBytes(result, Scale.KiB); + result = (long) new Size(result, Size.Unit.KiB).convertTo(Size.Unit.B).getValue(); } else { throw new NotImplementedException("unit conversion from " + units + " not implemented"); }
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java Wed Jan 02 09:47:39 2013 -0500 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java Thu Jan 03 10:23:48 2013 -0500 @@ -51,6 +51,7 @@ import com.redhat.thermostat.backend.system.HostInfoBuilder.HostCpuInfo; import com.redhat.thermostat.backend.system.HostInfoBuilder.HostMemoryInfo; import com.redhat.thermostat.backend.system.HostInfoBuilder.HostOsInfo; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.storage.model.HostInfo; import com.redhat.thermostat.utils.ProcDataSource; @@ -94,7 +95,7 @@ HostMemoryInfo memoryInfo = new HostInfoBuilder(dataSource).getMemoryInfo(); assertNotNull(memoryInfo); - assertEquals(12345 * KILOBYTES_TO_BYTES, memoryInfo.totalMemory); + assertEquals(Size.bytes(12345 * KILOBYTES_TO_BYTES), memoryInfo.totalMemory); verify(dataSource).getMemInfoReader(); }
--- a/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpController.java Wed Jan 02 09:47:39 2013 -0500 +++ b/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpController.java Thu Jan 03 10:23:48 2013 -0500 @@ -50,13 +50,13 @@ import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ApplicationService; import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.cli.CommandException; import com.redhat.thermostat.common.dao.VmMemoryStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; import com.redhat.thermostat.storage.model.HeapInfo; import com.redhat.thermostat.storage.model.VmMemoryStat; import com.redhat.thermostat.storage.model.VmMemoryStat.Generation; @@ -277,14 +277,9 @@ } } model.addData(memoryStats.getTimeStamp(), used, capacity); - - NumberFormat formatter = DecimalFormat.getInstance(); - double res = Scale.convertTo(Scale.B, used); - String _used = formatter.format(res) + " " + Scale.B; - - res = Scale.convertTo(Scale.B, capacity); - String _capacity= formatter.format(capacity) + " " + Scale.B; + String _used = Size.bytes(used).toString(); + String _capacity= Size.bytes(capacity).toString(); view.updateUsedAndCapacity(_used, _capacity); desiredUpdateTimeStamp = Math.max(desiredUpdateTimeStamp, memoryStats.getTimeStamp());
--- a/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/Payload.java Wed Jan 02 09:47:39 2013 -0500 +++ b/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/Payload.java Thu Jan 03 10:23:48 2013 -0500 @@ -36,7 +36,7 @@ package com.redhat.thermostat.vm.memory.client.core; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; +import com.redhat.thermostat.common.Size; public class Payload implements Cloneable { @@ -48,8 +48,8 @@ private double maxUsed; private double used; - private Scale usedUnit; - private Scale capacityUnit; + private Size.Unit usedUnit; + private Size.Unit capacityUnit; private StatsModel model; @@ -61,19 +61,19 @@ return model; } - public void setCapacityUnit(Scale capacityUnit) { + public void setCapacityUnit(Size.Unit capacityUnit) { this.capacityUnit = capacityUnit; } - public Scale getCapacityUnit() { + public Size.Unit getCapacityUnit() { return capacityUnit; } - public void setUsedUnit(Scale usedUnit) { + public void setUsedUnit(Size.Unit usedUnit) { this.usedUnit = usedUnit; } - public Scale getUsedUnit() { + public Size.Unit getUsedUnit() { return usedUnit; }
--- a/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsController.java Wed Jan 02 09:47:39 2013 -0500 +++ b/vm-memory/client-core/src/main/java/com/redhat/thermostat/vm/memory/client/core/internal/MemoryStatsController.java Thu Jan 03 10:23:48 2013 -0500 @@ -48,7 +48,9 @@ import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ApplicationService; import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.Size; import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.Size.Unit; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.command.Request; import com.redhat.thermostat.common.command.RequestResponseListener; @@ -59,7 +61,6 @@ import com.redhat.thermostat.common.dao.VmMemoryStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; import com.redhat.thermostat.gc.remote.common.GCRequest; import com.redhat.thermostat.gc.remote.common.command.GCCommand; import com.redhat.thermostat.storage.model.VmMemoryStat; @@ -104,17 +105,17 @@ payload.setName(space.getName()); } - Scale usedScale = normalizeScale(space.getUsed(), space.getCapacity()); - double used = Scale.convertTo(usedScale, space.getUsed(), 100); - double maxUsed = Scale.convertTo(usedScale, space.getCapacity(), 100); + Size.Unit usedScale = bestUnitForRange(space.getUsed(), space.getCapacity()); + double used = Size.bytes(space.getUsed()).convertTo(usedScale).getValue(); + double maxUsed = Size.bytes(space.getCapacity()).convertTo(usedScale).getValue(); payload.setUsed(used); payload.setMaxUsed(maxUsed); payload.setUsedUnit(usedScale); - Scale maxScale = normalizeScale(space.getCapacity(), space.getMaxCapacity()); - double capacity = Scale.convertTo(maxScale, space.getCapacity(), 100); - double maxCapacity = Scale.convertTo(maxScale, space.getMaxCapacity(), 100); + Size.Unit maxScale = bestUnitForRange(space.getCapacity(), space.getMaxCapacity()); + double capacity = Size.bytes(space.getCapacity()).convertTo(maxScale).getValue(); + double maxCapacity = Size.bytes(space.getMaxCapacity()).convertTo(maxScale).getValue(); payload.setCapacity(capacity); payload.setMaxCapacity(maxCapacity); @@ -134,8 +135,7 @@ } // normalize this always in the same unit - model.addData(memoryStats.getTimeStamp(), - Scale.convertTo(Scale.MiB, space.getUsed(), 100)); + model.addData(memoryStats.getTimeStamp(), Size.bytes(space.getUsed()).convertTo(Unit.MiB).getValue()); payload.setModel(model); if (regions.containsKey(space.getName())) { @@ -224,13 +224,13 @@ return regions; } - private Scale normalizeScale(long min, long max) { + private Size.Unit bestUnitForRange(long min, long max) { // FIXME: this is very dumb and very inefficient // needs cleanup - Scale minScale = Scale.getScale(min); - Scale maxScale = Scale.getScale(max); + Size.Unit minScale = Size.Unit.getBestUnit(min); + Size.Unit maxScale = Size.Unit.getBestUnit(max); - Scale[] scales = Scale.values(); + Size.Unit[] scales = Size.Unit.values(); int maxID = 0; int minID = 0; for (int i = 0; i < scales.length; i++) {
--- a/vm-memory/client-core/src/test/java/com/redhat/thermostat/vm/memory/client/core/PayloadTest.java Wed Jan 02 09:47:39 2013 -0500 +++ b/vm-memory/client-core/src/test/java/com/redhat/thermostat/vm/memory/client/core/PayloadTest.java Thu Jan 03 10:23:48 2013 -0500 @@ -41,7 +41,7 @@ import org.junit.Test; -import com.redhat.thermostat.common.utils.DisplayableValues.Scale; +import com.redhat.thermostat.common.Size; public class PayloadTest { @@ -57,11 +57,11 @@ Payload source = new Payload(); source.setCapacity(10.0); source.setName("fluff"); - source.setCapacityUnit(Scale.GiB); + source.setCapacityUnit(Size.Unit.GiB); source.setMaxCapacity(100.0); source.setMaxUsed(5.0); source.setUsed(3.0); - source.setUsedUnit(Scale.MiB); + source.setUsedUnit(Size.Unit.MiB); source.setModel(model); source.setTooltip("fluffTooltip");