This is an automated email from the ASF dual-hosted git repository. tkalkirill pushed a commit to branch ignite-25630 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit a469f1172e487d898e3d9a401a98c4e42c145552 Author: Kirill Tkalenko <[email protected]> AuthorDate: Tue Jun 17 14:49:40 2025 +0300 IGNITE-25630 wip --- .../persistence/PersistentPageMemory.java | 6 ++ .../pagememory/AbstractPageMemoryTableStorage.java | 21 ++++--- .../pagememory/PersistentPageMemoryDataRegion.java | 69 +++++++++++++++++++++- .../PersistentPageMemoryStorageEngine.java | 6 +- .../PersistentPageMemoryTableStorage.java | 7 ++- .../pagememory/VolatilePageMemoryTableStorage.java | 2 +- .../mv/PersistentPageMemoryMvPartitionStorage.java | 4 ++ 7 files changed, 104 insertions(+), 11 deletions(-) diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java index cd32e9d4fbd..23516333e0a 100644 --- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java +++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java @@ -81,6 +81,7 @@ import org.apache.ignite.internal.lang.IgniteInternalException; import org.apache.ignite.internal.logger.IgniteLogger; import org.apache.ignite.internal.logger.Loggers; import org.apache.ignite.internal.metrics.IntGauge; +import org.apache.ignite.internal.metrics.LongGauge; import org.apache.ignite.internal.pagememory.FullPageId; import org.apache.ignite.internal.pagememory.PageMemory; import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfiguration; @@ -290,6 +291,11 @@ public class PersistentPageMemory implements PageMemory { metricSource.addMetric(new IntGauge( "MaxCheckpointBufferPages", "The capacity of checkpoint buffer in pages.", this::maxCheckpointBufferPages )); + metricSource.addMetric(new LongGauge( + "MaxSize", + "Maximum region size in bytes.", + storageProfileView::sizeBytes + )); } /** diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java index 6ec4e53d563..1da4f4af9dd 100644 --- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java +++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java @@ -61,8 +61,8 @@ import org.jetbrains.annotations.Nullable; /** * Abstract table storage implementation based on {@link PageMemory}. */ -public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { - private final MvPartitionStorages<AbstractPageMemoryMvPartitionStorage> mvPartitionStorages; +public abstract class AbstractPageMemoryTableStorage<T extends AbstractPageMemoryMvPartitionStorage> implements MvTableStorage { + final MvPartitionStorages<T> mvPartitionStorages; private final IgniteSpinBusyLock busyLock = new IgniteSpinBusyLock(); @@ -112,6 +112,8 @@ public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { busyLock.block(); + beforeCloseOrDestroy(); + return mvPartitionStorages.getAllForCloseOrDestroy() .thenCompose(storages -> allOf(storages.stream().map(this::destroyMvPartitionStorage).toArray(CompletableFuture[]::new))) .whenComplete((unused, throwable) -> { @@ -132,7 +134,7 @@ public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { * @param partitionId Partition ID. * @throws StorageException If there is an error while creating the mv partition storage. */ - public abstract AbstractPageMemoryMvPartitionStorage createMvPartitionStorage(int partitionId) throws StorageException; + public abstract T createMvPartitionStorage(int partitionId) throws StorageException; /** * Destroys the partition multi-version storage and all its indexes. @@ -145,7 +147,7 @@ public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { @Override public CompletableFuture<MvPartitionStorage> createMvPartition(int partitionId) { return busy(() -> mvPartitionStorages.create(partitionId, partId -> { - AbstractPageMemoryMvPartitionStorage partition = createMvPartitionStorage(partitionId); + T partition = createMvPartitionStorage(partitionId); partition.start(); @@ -202,7 +204,7 @@ public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { } try { - List<AbstractPageMemoryMvPartitionStorage> storages = mvPartitionStorages.getAll(); + List<T> storages = mvPartitionStorages.getAll(); var destroyFutures = new CompletableFuture[storages.size()]; @@ -247,9 +249,10 @@ public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { busyLock.block(); + beforeCloseOrDestroy(); + try { - CompletableFuture<List<AbstractPageMemoryMvPartitionStorage>> allForCloseOrDestroy - = mvPartitionStorages.getAllForCloseOrDestroy(); + CompletableFuture<List<T>> allForCloseOrDestroy = mvPartitionStorages.getAllForCloseOrDestroy(); // 10 seconds is taken by analogy with shutdown of thread pool, in general this should be fairly fast. IgniteUtils.closeAllManually(allForCloseOrDestroy.get(10, TimeUnit.SECONDS).stream()); @@ -392,4 +395,8 @@ public abstract class AbstractPageMemoryTableStorage implements MvTableStorage { public StorageTableDescriptor getTableDescriptor() { return tableDescriptor; } + + protected void beforeCloseOrDestroy() { + // No-op. + } } diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java index 0edbb82b4f7..d70bd6577bc 100644 --- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java +++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryDataRegion.java @@ -27,6 +27,8 @@ import static org.apache.ignite.internal.util.Constants.MiB; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; @@ -35,23 +37,27 @@ import org.apache.ignite.internal.configuration.SystemPropertyView; import org.apache.ignite.internal.lang.IgniteInternalCheckedException; import org.apache.ignite.internal.logger.IgniteLogger; import org.apache.ignite.internal.logger.Loggers; +import org.apache.ignite.internal.metrics.LongGauge; import org.apache.ignite.internal.metrics.MetricManager; import org.apache.ignite.internal.pagememory.DataRegion; import org.apache.ignite.internal.pagememory.FullPageId; import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileConfiguration; import org.apache.ignite.internal.pagememory.configuration.schema.PersistentPageMemoryProfileView; import org.apache.ignite.internal.pagememory.io.PageIoRegistry; +import org.apache.ignite.internal.pagememory.persistence.GroupPartitionId; import org.apache.ignite.internal.pagememory.persistence.PartitionMetaManager; import org.apache.ignite.internal.pagememory.persistence.PersistentPageMemory; import org.apache.ignite.internal.pagememory.persistence.PersistentPageMemoryMetricSource; import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointManager; import org.apache.ignite.internal.pagememory.persistence.checkpoint.CheckpointProgress; +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.throttling.PagesWriteSpeedBasedThrottle; import org.apache.ignite.internal.pagememory.persistence.throttling.PagesWriteThrottlePolicy; import org.apache.ignite.internal.pagememory.persistence.throttling.TargetRatioPagesWriteThrottle; import org.apache.ignite.internal.pagememory.persistence.throttling.ThrottlingType; import org.apache.ignite.internal.storage.StorageException; +import org.apache.ignite.internal.storage.pagememory.mv.PersistentPageMemoryMvPartitionStorage; import org.apache.ignite.internal.util.OffheapReadWriteLock; import org.jetbrains.annotations.Nullable; @@ -98,7 +104,9 @@ class PersistentPageMemoryDataRegion implements DataRegion<PersistentPageMemory> private volatile AtomicLong pageListCacheLimit; - private PersistentPageMemoryMetricSource metricSource; + private final PersistentPageMemoryMetricSource metricSource; + + private final Collection<PersistentPageMemoryTableStorage> tableStorages = ConcurrentHashMap.newKeySet(); /** * Constructor. @@ -158,6 +166,8 @@ class PersistentPageMemoryDataRegion implements DataRegion<PersistentPageMemory> pageMemory.start(); + initMetrics(); + metricManager.registerSource(metricSource); metricManager.enable(metricSource); @@ -395,4 +405,61 @@ class PersistentPageMemoryDataRegion implements DataRegion<PersistentPageMemory> throw new StorageException("Data region not started"); } } + + void addTableStorage(PersistentPageMemoryTableStorage tableStorage) { + boolean add = tableStorages.add(tableStorage); + + assert add : tableStorage.getTableId(); + } + + void removeTableStorage(PersistentPageMemoryTableStorage tableStorage) { + boolean removed = tableStorages.remove(tableStorage); + + assert removed : tableStorage.getTableId(); + } + + private void initMetrics() { + metricSource.addMetric(new LongGauge( + "TotalAllocatedSize", + "Total size of allocated pages on disk in bytes.", + this::totalAllocatedPagesSizeOnDiskInBytes + )); + metricSource.addMetric(new LongGauge( + "TotalUsedSize", + "Total size of non-empty allocated pages on disk in bytes.", + this::totalNonEmptyAllocatedPagesSizeOnDiskInBytes + )); + } + + private long totalAllocatedPagesSizeOnDiskInBytes() { + long pageCount = 0; + + for (PersistentPageMemoryTableStorage tableStorage : tableStorages) { + for (PersistentPageMemoryMvPartitionStorage partitionStorage : tableStorage.mvPartitionStorages.getAll()) { + pageCount += allocatedPageCountOnDisk(tableStorage.getTableId(), partitionStorage.partitionId()); + } + } + + return pageCount * pageSize; + } + + private long totalNonEmptyAllocatedPagesSizeOnDiskInBytes() { + long pageCount = 0; + + for (PersistentPageMemoryTableStorage tableStorage : tableStorages) { + for (PersistentPageMemoryMvPartitionStorage partitionStorage : tableStorage.mvPartitionStorages.getAll()) { + pageCount += allocatedPageCountOnDisk(tableStorage.getTableId(), partitionStorage.partitionId()); + + pageCount -= partitionStorage.emptyDataPageCountInFreeList(); + } + } + + return pageCount * pageSize; + } + + private long allocatedPageCountOnDisk(int tableId, int partitionId) { + FilePageStore store = filePageStoreManager.getStore(new GroupPartitionId(tableId, partitionId)); + + return store == null ? 0 : store.pages(); + } } 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 8312b58d5bc..e297713a0c4 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 @@ -280,7 +280,7 @@ public class PersistentPageMemoryStorageEngine extends AbstractPageMemoryStorage assert dataRegion != null : "tableId=" + tableDescriptor.getId() + ", dataRegion=" + tableDescriptor.getStorageProfile(); - return new PersistentPageMemoryTableStorage( + var tableStorage = new PersistentPageMemoryTableStorage( tableDescriptor, indexDescriptorSupplier, this, @@ -288,6 +288,10 @@ public class PersistentPageMemoryStorageEngine extends AbstractPageMemoryStorage destructionExecutor, failureManager ); + + dataRegion.addTableStorage(tableStorage); + + return tableStorage; } @Override diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java index 97390ad496c..dd052d1bffc 100644 --- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java +++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java @@ -50,7 +50,7 @@ import org.jetbrains.annotations.Nullable; /** * Implementation of {@link AbstractPageMemoryTableStorage} for persistent case. */ -public class PersistentPageMemoryTableStorage extends AbstractPageMemoryTableStorage { +public class PersistentPageMemoryTableStorage extends AbstractPageMemoryTableStorage<PersistentPageMemoryMvPartitionStorage> { /** Storage engine instance. */ private final PersistentPageMemoryStorageEngine engine; @@ -466,4 +466,9 @@ public class PersistentPageMemoryTableStorage extends AbstractPageMemoryTableSto ); } } + + @Override + protected void beforeCloseOrDestroy() { + dataRegion.removeTableStorage(this); + } } diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java index 19704aa7c0d..5dec337b499 100644 --- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java +++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java @@ -37,7 +37,7 @@ import org.apache.ignite.internal.storage.pagememory.mv.gc.GcQueue; /** * Implementation of {@link AbstractPageMemoryTableStorage} for in-memory case. */ -public class VolatilePageMemoryTableStorage extends AbstractPageMemoryTableStorage { +public class VolatilePageMemoryTableStorage extends AbstractPageMemoryTableStorage<VolatilePageMemoryMvPartitionStorage> { private final VolatilePageMemoryStorageEngine engine; private final VolatilePageMemoryDataRegion dataRegion; diff --git a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java index ce1a4583408..30616c563c3 100644 --- a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java +++ b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java @@ -556,4 +556,8 @@ public class PersistentPageMemoryMvPartitionStorage extends AbstractPageMemoryMv public void decrementEstimatedSize() { updateMeta((lastCheckpointId, meta) -> meta.decrementEstimatedSize(lastCheckpointId)); } + + public int emptyDataPageCountInFreeList() { + return renewableState.freeList().emptyDataPages(); + } }
