diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java index 3f596cf65220b..3946d4fba3428 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java @@ -50,6 +50,7 @@ import static java.nio.ByteOrder.nativeOrder; import static java.nio.file.Files.walkFileTree; import static java.nio.file.StandardOpenOption.READ; +import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION; import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CACHE_START; import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CHECKPOINT; import static org.apache.ignite.internal.processors.performancestatistics.OperationType.JOB; @@ -83,6 +84,9 @@ * @see FilePerformanceStatisticsWriter */ public class FilePerformanceStatisticsReader { + /** Legacy format version without Ignite product version in header. */ + static final short LEGACY_FILE_FORMAT_VERSION_1 = 1; + /** Default file read buffer size. */ private static final int DFLT_READ_BUFFER_SIZE = (int)(8 * U.MB); @@ -229,15 +233,26 @@ private boolean deserialize(ByteBuffer buf, UUID nodeId, boolean firstRecord) th throw new IgniteException("Unsupported file format"); if (opType == VERSION) { - if (buf.remaining() < OperationType.versionRecordSize()) + if (buf.remaining() < Short.BYTES) return false; short ver = buf.getShort(); + String ignVer = null; + + if (ver == FILE_FORMAT_VERSION) { + ForwardableString verStr = readString(buf); + + if (verStr == null) + return false; - if (ver != FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION) { - throw new IgniteException("Unsupported file format version [fileVer=" + ver + ", supportedVer=" + - FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION + ']'); + ignVer = verStr.str; } + else if (ver != LEGACY_FILE_FORMAT_VERSION_1) + throw new IgniteException("Unsupported file format version [fileVer=" + ver + ", currentVer=" + + FILE_FORMAT_VERSION + ']'); + + for (PerformanceStatisticsHandler hnd : curHnd) + hnd.version(nodeId, ver, ignVer); return true; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java index 36f48e7854678..4d757177d7893 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java @@ -46,6 +46,7 @@ import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_BUFFER_SIZE; import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_FILE_MAX_SIZE; import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_FLUSH_SIZE; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CACHE_START; import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CHECKPOINT; import static org.apache.ignite.internal.processors.performancestatistics.OperationType.JOB; @@ -96,7 +97,7 @@ public class FilePerformanceStatisticsWriter { * File format version. This version should be incremented each time when format of existing events are * changed (fields added/removed) to avoid unexpected non-informative errors on deserialization. */ - public static final short FILE_FORMAT_VERSION = 1; + public static final short FILE_FORMAT_VERSION = 2; /** File writer thread name. */ static final String WRITER_THREAD_NAME = "performance-statistics-writer"; @@ -155,7 +156,10 @@ public FilePerformanceStatisticsWriter(GridKernalContext ctx) throws IgniteCheck fileWriter = new FileWriter(ctx, log); - doWrite(OperationType.VERSION, OperationType.versionRecordSize(), buf -> buf.putShort(FILE_FORMAT_VERSION)); + doWrite(OperationType.VERSION, OperationType.versionRecordSize(), buf -> { + buf.putShort(FILE_FORMAT_VERSION); + writeString(buf, VER_STR, false); + }); } /** Starts collecting performance statistics. */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java index 2f1f76d7661e0..612976ae1a3cd 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java @@ -23,6 +23,8 @@ import java.util.Map; import org.jetbrains.annotations.Nullable; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; + /** * Performance statistics operation type. */ @@ -295,7 +297,7 @@ public static int checkpointRecordSize() { /** @return Version record size. */ public static int versionRecordSize() { - return Short.BYTES; + return Short.BYTES + 1 + Integer.BYTES + VER_STR.length(); } /** @return Pages write throttle record size. */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java index a6c20d7b3cfad..44298b9cd2e20 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java @@ -22,12 +22,22 @@ import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType; import org.apache.ignite.internal.util.GridIntList; import org.apache.ignite.lang.IgniteUuid; +import org.jetbrains.annotations.Nullable; /** * The interface represents performance statistics operations collection for purposes of troubleshooting and * performance analysis. */ public interface PerformanceStatisticsHandler { + /** + * @param nodeId Node id. + * @param fileFormatVer Performance statistics file format version. + * @param ignVer Ignite version stored in file header, if present. + */ + default void version(UUID nodeId, short fileFormatVer, @Nullable String ignVer) { + // No-op. + } + /** * @param nodeId Node id. * @param cacheId Cache id. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/SystemViewFileWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/SystemViewFileWriter.java index df975e18af5b2..04688302950e8 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/SystemViewFileWriter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/SystemViewFileWriter.java @@ -39,6 +39,7 @@ import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_BUFFER_SIZE; import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_FLUSH_SIZE; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.DFLT_BUFFER_SIZE; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.DFLT_FLUSH_SIZE; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION; @@ -112,6 +113,7 @@ public SystemViewFileWriter(GridKernalContext ctx) throws IgniteCheckedException doWrite(buf -> { buf.put(OperationType.VERSION.id()); buf.putShort(FILE_FORMAT_VERSION); + writeString(buf, VER_STR, false); }); } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadQueryPropertyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadQueryPropertyTest.java index 1fe7f1e6eb21c..0469d81b3cb9e 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadQueryPropertyTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadQueryPropertyTest.java @@ -20,7 +20,9 @@ import java.io.File; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.ignite.internal.processors.cache.persistence.file.FileIO; @@ -28,31 +30,53 @@ import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType; import org.apache.ignite.internal.util.typedef.internal.U; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import static java.util.Collections.singletonList; import static java.util.UUID.randomUUID; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; +import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsReader.LEGACY_FILE_FORMAT_VERSION_1; +import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.PERF_STAT_DIR; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.writeString; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.writeUuid; +import static org.junit.runners.Parameterized.Parameter; +import static org.junit.runners.Parameterized.Parameters; /** * Tests forward read mode for {@link OperationType#QUERY_PROPERTY} records. */ +@RunWith(Parameterized.class) public class ForwardReadQueryPropertyTest extends AbstractPerformanceStatisticsTest { /** Read buffer size. */ private static final int BUFFER_SIZE = 100; + /** File format version. */ + @Parameter + public short fileFormatVer; + + /** @return Test parameters. */ + @Parameters(name = "fileFormatVer={0}") + public static Collection parameters() { + return List.of(FILE_FORMAT_VERSION, LEGACY_FILE_FORMAT_VERSION_1); + } + /** @throws Exception If failed. */ @Test public void testStringForwardRead() throws Exception { File dir = U.resolveWorkDirectory(U.defaultWorkDirectory(), PERF_STAT_DIR, false); - Map expProps = createStatistics(dir); + Map expProps = createStatistics(dir, fileFormatVer); Map actualProps = new HashMap<>(); new FilePerformanceStatisticsReader(BUFFER_SIZE, new TestHandler() { - @Override public void queryProperty(UUID nodeId, GridCacheQueryType type, UUID qryNodeId, long id, String name, - String val) { + @Override public void version(UUID nodeId, short fileFormatVer, String ignVer) { + assertEquals(ForwardReadQueryPropertyTest.this.fileFormatVer, fileFormatVer); + assertEquals(ForwardReadQueryPropertyTest.this.fileFormatVer == LEGACY_FILE_FORMAT_VERSION_1 ? null : VER_STR, ignVer); + } + + @Override public void queryProperty(UUID nodeId, GridCacheQueryType type, UUID qryNodeId, long id, String name, String val) { assertNotNull(name); assertNotNull(val); @@ -64,14 +88,20 @@ public void testStringForwardRead() throws Exception { } /** Creates test performance statistics file. */ - private Map createStatistics(File dir) throws Exception { + private Map createStatistics(File dir, short fileFormatVer) throws Exception { File file = new File(dir, "node-" + randomUUID() + ".prf"); try (FileIO fileIo = new RandomAccessFileIOFactory().create(file)) { ByteBuffer buf = ByteBuffer.allocate(1024).order(ByteOrder.nativeOrder()); buf.put(OperationType.VERSION.id()); - buf.putShort(FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION); + + if (fileFormatVer == FILE_FORMAT_VERSION) { + buf.putShort(fileFormatVer); + writeString(buf, VER_STR, false); + } + else + buf.putShort(fileFormatVer); writeQueryProperty(buf, "property", true, "val", true); writeQueryProperty(buf, "property", false, "val", false); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadTest.java index c5c2238e13489..b01efaa4fd286 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/ForwardReadTest.java @@ -39,6 +39,7 @@ import static com.google.common.collect.Lists.cartesianProduct; import static java.util.Collections.singletonList; import static java.util.UUID.randomUUID; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.PERF_STAT_DIR; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.writeIgniteUuid; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.writeString; @@ -93,6 +94,7 @@ private Map createStatistics(File dir) throws Exception { buf.put(OperationType.VERSION.id()); buf.putShort(FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION); + writeString(buf, VER_STR, false); expTasks = writeData(buf); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsPropertiesTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsPropertiesTest.java index 6f53f6145e4b7..ab99820619c87 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsPropertiesTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsPropertiesTest.java @@ -113,7 +113,9 @@ public void testFileMaxSize() throws Exception { @Test @WithSystemProperty(key = IGNITE_PERF_STAT_FLUSH_SIZE, value = "" + TEST_FLUSH_SIZE) public void testFlushSize() throws Exception { - long initLen = srv.context().cache().cacheDescriptors().values().stream().mapToInt( + long initLen = 1 + OperationType.versionRecordSize(); + + initLen += srv.context().cache().cacheDescriptors().values().stream().mapToInt( desc -> 1 + cacheStartRecordSize(desc.cacheName().getBytes().length, false)).sum(); long opsCnt = (TEST_FLUSH_SIZE - initLen) / (/*typeOp*/1 + OperationType.cacheRecordSize()); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsSystemViewTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsSystemViewTest.java index 728bfa89a683c..d8da170bb8fa8 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsSystemViewTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsSystemViewTest.java @@ -41,6 +41,7 @@ import static java.util.UUID.randomUUID; import static java.util.function.Function.identity; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; import static org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager.METASTORE_VIEW; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.PERF_STAT_DIR; import static org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsWriter.writeString; @@ -197,6 +198,7 @@ private List createStatistics(File dir) throws Exception { buf.put(OperationType.VERSION.id()); buf.putShort(FilePerformanceStatisticsWriter.FILE_FORMAT_VERSION); + writeString(buf, VER_STR, false); writeSystemView(buf, "customView", "customWalker", null);