/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.internal.statistics; import static org.apache.geode.internal.statistics.StatArchiveFormat.NANOS_PER_MILLI; import static org.apache.geode.internal.statistics.StatUtils.*; import static org.apache.geode.internal.statistics.TestStatArchiveWriter.*; import static org.junit.Assert.*; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.rules.TestName; import org.apache.geode.StatisticDescriptor; import org.apache.geode.Statistics; import org.apache.geode.StatisticsType; import org.apache.geode.internal.statistics.StatArchiveReader.ResourceInst; import org.apache.geode.internal.statistics.StatArchiveReader.StatValue; /** * Generates the stat archive file that is committed under src/test/resources for * {@link StatArchiveWithConsecutiveResourceInstIntegrationTest} to load. * * <p> * The generated gfs file is used to confirm GEODE-1782 and its fix. * * @since Geode 1.0 */ public class StatArchiveWithConsecutiveResourceInstGenerator { private static final Logger logger = LogManager.getLogger(); protected static final String STATS_TYPE_NAME = "TestStats"; protected static final String STATS_SPEC_STRING = ":" + STATS_TYPE_NAME; protected static final String TEST_NAME = StatArchiveWithConsecutiveResourceInstIntegrationTest.class.getSimpleName(); protected static final String ARCHIVE_FILE_NAME = TEST_NAME + ".gfs"; private File dir; private Map<String, String> statisticTypes; private Map<String, Map<String, Number>> allStatistics; protected String archiveFileName; private TestStatisticsManager manager; private TestStatisticsSampler sampler; private SampleCollector sampleCollector; private StatArchiveWriter writer; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Rule public TestName testName = new TestName(); @Before public void setUpGenerator() throws Exception { this.statisticTypes = new HashMap<>(); this.allStatistics = new HashMap<>(); this.dir = this.temporaryFolder.getRoot(); this.archiveFileName = new File(this.dir.getAbsolutePath(), ARCHIVE_FILE_NAME).getAbsolutePath(); this.manager = new TestStatisticsManager(1, getUniqueName(), WRITER_INITIAL_DATE_MILLIS); StatArchiveDescriptor archiveDescriptor = new StatArchiveDescriptor.Builder().setArchiveName(this.archiveFileName).setSystemId(1) .setSystemStartTime(WRITER_INITIAL_DATE_MILLIS - 2000).setSystemDirectoryPath(TEST_NAME) .setProductDescription(TEST_NAME).build(); this.writer = new TestStatArchiveWriter(archiveDescriptor); this.sampler = new TestStatisticsSampler(manager); this.sampleCollector = new SampleCollector(sampler); this.sampleCollector.addSampleHandler(this.writer); } @After public void tearDown() throws Exception { StatisticsTypeFactoryImpl.clear(); } @Test public void generateStatArchiveFile() throws Exception { long sampleTimeNanos = WRITER_PREVIOUS_TIMESTAMP_NANOS + NANOS_PER_MILLI * 1000; // 1) create statistics StatisticsType type = createStatisticsType(STATS_TYPE_NAME, "description of " + STATS_TYPE_NAME); Statistics statistics1 = createStatistics(type, STATS_TYPE_NAME + "1", 1); // 2) sample changing stat for (int i = 0; i < 100; i++) { incInt(statistics1, "stat", 1); this.sampleCollector.sample(sampleTimeNanos += (1000 * NANOS_PER_MILLI)); } // 3) close statistics statistics1.close(); // 4) recreate statistics Statistics statistics2 = createStatistics(type, STATS_TYPE_NAME + "1", 1); // 5) sample changing stat again for (int i = 0; i < 100; i++) { incInt(statistics2, "stat", 1); this.sampleCollector.sample(sampleTimeNanos += (1000 * NANOS_PER_MILLI)); } // close the writer this.writer.close(); // validate that stat archive file exists File actual = new File(this.archiveFileName); assertTrue(actual.exists()); // validate content of stat archive file using StatArchiveReader StatArchiveReader reader = new StatArchiveReader(new File[] {actual}, null, false); // compare all resourceInst values against what was printed above for (final Iterator iter = reader.getResourceInstList().iterator(); iter.hasNext();) { StatArchiveReader.ResourceInst ri = (StatArchiveReader.ResourceInst) iter.next(); String resourceName = ri.getName(); assertNotNull(resourceName); String expectedStatsType = this.statisticTypes.get(resourceName); assertNotNull(expectedStatsType); assertEquals(expectedStatsType, ri.getType().getName()); Map<String, Number> expectedStatValues = this.allStatistics.get(resourceName); assertNotNull(expectedStatValues); StatValue[] statValues = ri.getStatValues(); for (int i = 0; i < statValues.length; i++) { final String statName = ri.getType().getStats()[i].getName(); assertNotNull(statName); assertNotNull(expectedStatValues.get(statName)); assertEquals(statName, statValues[i].getDescriptor().getName()); statValues[i].setFilter(StatValue.FILTER_NONE); double[] rawSnapshots = statValues[i].getRawSnapshots(); assertEquals("Value " + i + " for " + statName + " is wrong: " + expectedStatValues, expectedStatValues.get(statName).doubleValue(), statValues[i].getSnapshotsMostRecent(), 0.01); } } validateArchiveFile(); } protected void validateArchiveFile() throws IOException { final File archiveFile = new File(this.archiveFileName); assertTrue(archiveFile.exists()); logger.info("ArchiveFile: {}", archiveFile.getAbsolutePath()); logger.info("ArchiveFile length: {}", archiveFile.length()); for (ResourceInst resourceInst : findResourceInsts(archiveFile, STATS_SPEC_STRING)) { logger.info("ResourceInst: {}", resourceInst); } } private String getUniqueName() { return StatArchiveWithConsecutiveResourceInstGenerator.class + "_" + this.testName.getMethodName(); } private StatisticsType createStatisticsType(final String name, final String description) { StatisticDescriptor[] descriptors = new StatisticDescriptor[] { manager.createIntCounter("stat", "description of stat", "units"),}; return manager.createType(name, description, descriptors); } private Statistics createStatistics(final StatisticsType type, final String textId, final long numericId) { return manager.createAtomicStatistics(type, textId, 1); } private void incInt(Statistics statistics, String stat, int value) { assertFalse(statistics.isClosed()); Map<String, Number> statValues = this.allStatistics.get(statistics.getTextId()); if (statValues == null) { statValues = new HashMap<>(); this.allStatistics.put(statistics.getTextId(), statValues); } statistics.incInt(stat, value); statValues.put(stat, statistics.getInt(stat)); if (this.statisticTypes.get(statistics.getTextId()) == null) { this.statisticTypes.put(statistics.getTextId(), statistics.getType().getName()); } } }