This is an automated email from the ASF dual-hosted git repository.

tkalkirill pushed a commit to branch ignite-26180
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 289e9e1ba44e3609e934d3b1d81f4237d4609289
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Fri Oct 3 16:29:27 2025 +0300

    IGNITE-26180 wip
---
 .../persistence/store/FilePageStore.java           |  18 ++++
 .../persistence/store/GroupPageStoresMap.java      |   9 +-
 .../persistence/store/FilePageStoreTest.java       |  23 +++++
 .../PersistentPageMemoryStorageEngine.java         |   7 ++
 .../PersistentPageMemoryStorageMetricSource.java   |  85 +++++++++++++++
 .../PersistentPageMemoryStorageMetrics.java        |  51 +++++++++
 .../PersistentPageMemoryStorageMetricsTest.java    | 114 +++++++++++++++++++++
 7 files changed, 305 insertions(+), 2 deletions(-)

diff --git 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStore.java
 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStore.java
index 1e91dfb4b05..867e62a1f16 100644
--- 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStore.java
+++ 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStore.java
@@ -252,6 +252,24 @@ public class FilePageStore implements PageStore {
         return filePageStoreIo.size();
     }
 
+    /**
+     * Returns full size of the page store and its delta files in bytes.
+     *
+     * <p>May differ from {@link #pages} * {@link FilePageStoreIo#pageSize()} 
due to delayed writes or due to other implementation specific
+     * details.
+     *
+     * @throws IgniteInternalCheckedException If an I/O error occurs.
+     */
+    public long fullSize() throws IgniteInternalCheckedException {
+        long size = filePageStoreIo.size();
+
+        for (DeltaFilePageStoreIo deltaFilePageStoreIo : 
deltaFilePageStoreIos) {
+            size += deltaFilePageStoreIo.size();
+        }
+
+        return size;
+    }
+
     /**
      * Returns file page store path.
      */
diff --git 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/GroupPageStoresMap.java
 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/GroupPageStoresMap.java
index 0554d47378c..a177d51b238 100644
--- 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/GroupPageStoresMap.java
+++ 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/store/GroupPageStoresMap.java
@@ -119,9 +119,14 @@ public class GroupPageStoresMap<T extends PageStore> {
 
         private final T pageStore;
 
+        /** Constructor. */
+        public GroupPartitionPageStore(GroupPartitionId groupPartitionId, T 
pageStore) {
+            this.groupPartitionId = groupPartitionId;
+            this.pageStore = pageStore;
+        }
+
         private GroupPartitionPageStore(Map.Entry<GroupPartitionId, T> entry) {
-            this.groupPartitionId = entry.getKey();
-            this.pageStore = entry.getValue();
+            this(entry.getKey(), entry.getValue());
         }
 
         /**
diff --git 
a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreTest.java
 
b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreTest.java
index ce89c917505..f78b22335f6 100644
--- 
a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreTest.java
+++ 
b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/store/FilePageStoreTest.java
@@ -520,6 +520,29 @@ public class FilePageStoreTest extends 
BaseIgniteAbstractTest {
         }
     }
 
+    @Test
+    void testFullSize() throws Exception {
+        DeltaFilePageStoreIo deltaFile0 = mock(DeltaFilePageStoreIo.class);
+        DeltaFilePageStoreIo deltaFile1 = mock(DeltaFilePageStoreIo.class);
+
+        when(deltaFile0.size()).thenReturn(100L);
+        when(deltaFile1.size()).thenReturn(200L);
+
+        try (FilePageStore filePageStore = 
createFilePageStore(workDir.resolve("test"), deltaFile0, deltaFile1)) {
+            assertEquals(300L, filePageStore.fullSize());
+
+            filePageStore.ensure();
+
+            assertEquals(300L + PAGE_SIZE, filePageStore.fullSize());
+
+            long pageId0 = createDataPageId(filePageStore::allocatePage);
+
+            filePageStore.write(pageId0, createPageByteBuffer(pageId0, 
PAGE_SIZE));
+
+            assertEquals(300L + PAGE_SIZE * 2, filePageStore.fullSize());
+        }
+    }
+
     private static FilePageStore createFilePageStore(Path filePath) {
         return createFilePageStore(filePath, new 
FilePageStoreHeader(VERSION_1, PAGE_SIZE));
     }
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
index 194e5dd22c5..c6173b2cbf2 100644
--- 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
@@ -269,8 +269,15 @@ public class PersistentPageMemoryStorageEngine extends 
AbstractPageMemoryStorage
 
         destructionExecutor = executor;
 
+        var storageMetricSource = new 
PersistentPageMemoryStorageMetricSource("storage." + ENGINE_NAME);
+
+        PersistentPageMemoryStorageMetrics.initMetrics(storageMetricSource, 
filePageStoreManager);
+
         metricManager.registerSource(checkpointMetricSource);
+        metricManager.registerSource(storageMetricSource);
+
         metricManager.enable(checkpointMetricSource);
+        metricManager.enable(storageMetricSource);
     }
 
     /** Creates a checkpoint configuration based on the provided {@link 
PageMemoryCheckpointConfiguration}. */
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetricSource.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetricSource.java
new file mode 100644
index 00000000000..0d813d0af98
--- /dev/null
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetricSource.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ignite.internal.storage.pagememory;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.MetricSet;
+import org.apache.ignite.internal.metrics.MetricSource;
+import org.jetbrains.annotations.Nullable;
+
+/** Persistent page memory storage metric source. */
+class PersistentPageMemoryStorageMetricSource implements MetricSource {
+    private final String name;
+
+    /** Metrics map. Only modified in {@code synchronized} context. */
+    private final Map<String, Metric> metrics = new HashMap<>();
+
+    /** Enabled flag. Only modified in {@code synchronized} context. */
+    private boolean enabled;
+
+    /**
+     * Constructor.
+     *
+     * @param name Metric set name.
+     */
+    PersistentPageMemoryStorageMetricSource(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public @Nullable String group() {
+        return "storage";
+    }
+
+    /** Adds metric to the source. */
+    synchronized <T extends Metric> T addMetric(T metric) {
+        assert !enabled : "Cannot add metrics when source is enabled";
+
+        metrics.put(metric.name(), metric);
+
+        return metric;
+    }
+
+    @Override
+    public synchronized @Nullable MetricSet enable() {
+        if (enabled) {
+            return null;
+        }
+
+        enabled = true;
+
+        return new MetricSet(name, description(), group(), 
Map.copyOf(metrics));
+    }
+
+    @Override
+    public synchronized void disable() {
+        enabled = false;
+    }
+
+    @Override
+    public synchronized boolean enabled() {
+        return enabled;
+    }
+}
diff --git 
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetrics.java
 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetrics.java
new file mode 100644
index 00000000000..852815376a8
--- /dev/null
+++ 
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetrics.java
@@ -0,0 +1,51 @@
+/*
+ * 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.ignite.internal.storage.pagememory;
+
+import org.apache.ignite.internal.lang.IgniteInternalCheckedException;
+import org.apache.ignite.internal.metrics.LongGauge;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import 
org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreManager;
+import 
org.apache.ignite.internal.pagememory.persistence.store.GroupPageStoresMap.GroupPartitionPageStore;
+
+/** Persistent page memory storage metrics. */
+class PersistentPageMemoryStorageMetrics {
+    /** Initializes metrics in the given metric source. */
+    static void initMetrics(
+            PersistentPageMemoryStorageMetricSource source,
+            FilePageStoreManager filePageStoreManager
+    ) {
+        source.addMetric(new LongGauge(
+                "StorageSize",
+                "Size of the entire storage in bytes.",
+                () -> storageSize(filePageStoreManager)
+        ));
+    }
+
+    private static long storageSize(FilePageStoreManager filePageStoreManager) 
{
+        return 
filePageStoreManager.allPageStores().mapToLong(PersistentPageMemoryStorageMetrics::fullSize).sum();
+    }
+
+    private static long fullSize(GroupPartitionPageStore<FilePageStore> 
pageStore) {
+        try {
+            return pageStore.pageStore().fullSize();
+        } catch (IgniteInternalCheckedException e) {
+            return 0;
+        }
+    }
+}
diff --git 
a/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetricsTest.java
 
b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetricsTest.java
new file mode 100644
index 00000000000..434dce47e91
--- /dev/null
+++ 
b/modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageMetricsTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ignite.internal.storage.pagememory;
+
+import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+import org.apache.ignite.internal.lang.IgniteInternalCheckedException;
+import org.apache.ignite.internal.manager.ComponentContext;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.MetricManager;
+import org.apache.ignite.internal.metrics.MetricSet;
+import org.apache.ignite.internal.metrics.TestMetricManager;
+import org.apache.ignite.internal.pagememory.persistence.GroupPartitionId;
+import org.apache.ignite.internal.pagememory.persistence.store.FilePageStore;
+import 
org.apache.ignite.internal.pagememory.persistence.store.FilePageStoreManager;
+import 
org.apache.ignite.internal.pagememory.persistence.store.GroupPageStoresMap.GroupPartitionPageStore;
+import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/** For {@link PersistentPageMemoryStorageMetrics} testing. */
+public class PersistentPageMemoryStorageMetricsTest extends 
BaseIgniteAbstractTest {
+    private final MetricManager metricManager = new TestMetricManager();
+
+    private final PersistentPageMemoryStorageMetricSource metricSource = new 
PersistentPageMemoryStorageMetricSource("test");
+
+    private final FilePageStoreManager filePageStoreManager = 
mock(FilePageStoreManager.class);
+
+    @BeforeEach
+    void setUp() {
+        PersistentPageMemoryStorageMetrics.initMetrics(metricSource, 
filePageStoreManager);
+
+        metricManager.registerSource(metricSource);
+        metricManager.enable(metricSource);
+
+        assertThat(metricManager.startAsync(new ComponentContext()), 
willCompleteSuccessfully());
+    }
+
+    @AfterEach
+    void tearDown() {
+        metricManager.beforeNodeStop();
+
+        assertThat(metricManager.stopAsync(new ComponentContext()), 
willCompleteSuccessfully());
+    }
+
+    @Test
+    void testStorageSize() throws Exception {
+        checkMetricValue("StorageSize", "0");
+
+        setAllPageStores(
+                pageStore(new GroupPartitionId(1, 1), 100L),
+                pageStore(new GroupPartitionId(1, 2), 200L),
+                pageStoreWithException(new GroupPartitionId(2, 1))
+        );
+
+        checkMetricValue("StorageSize", "300");
+    }
+
+    @SafeVarargs
+    private void setAllPageStores(GroupPartitionPageStore<FilePageStore>... 
pageStores) {
+        Stream<GroupPartitionPageStore<FilePageStore>> stream = 
Arrays.stream(pageStores);
+
+        when(filePageStoreManager.allPageStores()).thenReturn(stream);
+    }
+
+    private static GroupPartitionPageStore<FilePageStore> 
pageStore(GroupPartitionId groupPartitionId, long size) throws Exception {
+        FilePageStore pageStore = mock(FilePageStore.class);
+
+        when(pageStore.fullSize()).thenReturn(size);
+
+        return new GroupPartitionPageStore<>(groupPartitionId, pageStore);
+    }
+
+    private static GroupPartitionPageStore<FilePageStore> 
pageStoreWithException(GroupPartitionId groupPartitionId) throws Exception {
+        FilePageStore pageStore = mock(FilePageStore.class);
+
+        
when(pageStore.fullSize()).thenThrow(IgniteInternalCheckedException.class);
+
+        return new GroupPartitionPageStore<>(groupPartitionId, pageStore);
+    }
+
+    private void checkMetricValue(String metricName, String exp) {
+        MetricSet metricSet = 
metricManager.metricSnapshot().metrics().get(metricSource.name());
+
+        Metric metric = metricSet.get(metricName);
+
+        assertNotNull(metric, metricName);
+
+        assertEquals(exp, metric.getValueAsString(), metricName);
+    }
+}

Reply via email to