This is an automated email from the ASF dual-hosted git repository. nizhikov pushed a commit to branch IGNITE-19950-snapshot-merge in repository https://gitbox.apache.org/repos/asf/ignite.git
commit 7300b472a518a665ed1021a7d636d65b8feaea06 Author: nizhikov <[email protected]> AuthorDate: Thu Jul 27 18:35:28 2023 +0300 IGNITE-19950 Save metadata implemented --- .../processors/cache/GridLocalConfigManager.java | 8 ++- .../cache/binary/BinaryMetadataFileStore.java | 19 +++---- .../binary/CacheObjectBinaryProcessorImpl.java | 11 ++-- .../snapshot/IgniteSnapshotManager.java | 29 +++++------ .../snapshot/dump/DumpCacheFutureTask.java | 58 ++++++++++++++++++++-- .../snapshot/IgniteCacheDumpSelfTest.java | 34 ++++++++++++- 6 files changed, 122 insertions(+), 37 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridLocalConfigManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridLocalConfigManager.java index 846d7128a99..4a6917e1a04 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridLocalConfigManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridLocalConfigManager.java @@ -541,8 +541,12 @@ public class GridLocalConfigManager { public File cacheConfigurationFile(CacheConfiguration<?, ?> ccfg) { File cacheWorkDir = cacheWorkDir(ccfg); - return ccfg.getGroupName() == null ? new File(cacheWorkDir, CACHE_DATA_FILENAME) : - new File(cacheWorkDir, ccfg.getName() + CACHE_DATA_FILENAME); + return new File(cacheWorkDir, cachDataFilename(ccfg)); + } + + /** @return Name of cache data filename. */ + public static String cachDataFilename(CacheConfiguration<?, ?> ccfg) { + return ccfg.getGroupName() == null ? CACHE_DATA_FILENAME : (ccfg.getName() + CACHE_DATA_FILENAME); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java index b994c4b7d06..fa20227d21b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataFileStore.java @@ -87,32 +87,33 @@ class BinaryMetadataFileStore { final ConcurrentMap<Integer, BinaryMetadataHolder> metadataLocCache, final GridKernalContext ctx, final IgniteLogger log, - final File binaryMetadataFileStoreDir + final File binaryMetadataFileStoreDir, + final boolean forceEnabled ) throws IgniteCheckedException { this.metadataLocCache = metadataLocCache; this.ctx = ctx; - enabled = CU.isPersistenceEnabled(ctx.config()) || CU.isCdcEnabled(ctx.config()); + enabled = forceEnabled || CU.isPersistenceEnabled(ctx.config()) || CU.isCdcEnabled(ctx.config()); this.log = log; - if (!enabled) - return; - - fileIOFactory = ctx.config().getDataStorageConfiguration().getFileIOFactory(); + DataStorageConfiguration dsCfg = ctx.config().getDataStorageConfiguration(); - final String nodeFolderName = ctx.pdsFolderResolver().resolveFolders().folderName(); + fileIOFactory = dsCfg == null ? new DataStorageConfiguration().getFileIOFactory() : dsCfg.getFileIOFactory(); if (binaryMetadataFileStoreDir != null) metadataDir = binaryMetadataFileStoreDir; - else + else { + final String nodeFolderName = ctx.pdsFolderResolver().resolveFolders().folderName(); + metadataDir = new File(U.resolveWorkDirectory( ctx.config().getWorkDirectory(), DataStorageConfiguration.DFLT_BINARY_METADATA_PATH, false ), nodeFolderName); - fixLegacyFolder(nodeFolderName); + fixLegacyFolder(nodeFolderName); + } } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java index db8bb33c8b4..7ca52e66449 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java @@ -261,7 +261,8 @@ public class CacheObjectBinaryProcessorImpl extends GridProcessorAdapter impleme CU.isPersistenceEnabled(ctx.config()) && binaryMetadataFileStoreDir == null ? resolveBinaryWorkDir(ctx.config().getWorkDirectory(), ctx.pdsFolderResolver().resolveFolders().folderName()) : - binaryMetadataFileStoreDir); + binaryMetadataFileStoreDir, + false); metadataFileStore.start(); } @@ -1019,7 +1020,9 @@ public class CacheObjectBinaryProcessorImpl extends GridProcessorAdapter impleme ctx, log, resolveBinaryWorkDir(dir.getAbsolutePath(), - ctx.pdsFolderResolver().resolveFolders().folderName())); + ctx.pdsFolderResolver().resolveFolders().folderName()), + true + ); for (BinaryType type : types) writer.mergeAndWriteMetadata(((BinaryTypeImpl)type).metadata()); @@ -1037,7 +1040,7 @@ public class CacheObjectBinaryProcessorImpl extends GridProcessorAdapter impleme try { ConcurrentMap<Integer, BinaryMetadataHolder> metaCache = new ConcurrentHashMap<>(); - new BinaryMetadataFileStore(metaCache, ctx, log, metadataDir) + new BinaryMetadataFileStore(metaCache, ctx, log, metadataDir, false) .restoreMetadata(); Collection<BinaryMetadata> metadata = F.viewReadOnly(metaCache.values(), BinaryMetadataHolder::metadata); @@ -1073,7 +1076,7 @@ public class CacheObjectBinaryProcessorImpl extends GridProcessorAdapter impleme ConcurrentMap<Integer, BinaryMetadataHolder> metaCache = new ConcurrentHashMap<>(); - new BinaryMetadataFileStore(metaCache, ctx, log, metadataDir).restoreMetadata(typeId); + new BinaryMetadataFileStore(metaCache, ctx, log, metadataDir, false).restoreMetadata(typeId); addMetaLocally(typeId, metaCache.get(typeId).metadata().wrap(binaryContext()), false); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java index f7dbf5a19a8..074833bdd63 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java @@ -164,6 +164,7 @@ import org.apache.ignite.internal.processors.task.GridInternal; import org.apache.ignite.internal.util.BasicRateLimiter; import org.apache.ignite.internal.util.GridBusyLock; import org.apache.ignite.internal.util.GridCloseableIteratorAdapter; +import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.internal.util.distributed.DistributedProcess; import org.apache.ignite.internal.util.distributed.InitMessage; import org.apache.ignite.internal.util.future.GridCompoundFuture; @@ -1224,18 +1225,18 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter } /** - * @param req Request - * @param grpIds0 Groups. + * @param req Request. + * @param grps0 Cache groups to dump. * @return Create dump future. */ - private IgniteInternalFuture<SnapshotOperationResponse> initLocalDump(SnapshotOperationRequest req, List<Integer> grpIds0) { + private IgniteInternalFuture<SnapshotOperationResponse> initLocalDump(SnapshotOperationRequest req, List<Integer> grps0) { IgniteInternalFuture<?> task0; - List<Integer> grpIds = grpIds0.stream().filter(grpId -> cctx.cache().cacheGroup(grpId) != null).collect(Collectors.toList()); + List<Integer> grps = grps0.stream().filter(grpId -> cctx.cache().cacheGroup(grpId) != null).collect(Collectors.toList()); File dumpDir = snapshotLocalDir(req.snapshotName(), null, locDumpDir); - if (grpIds.isEmpty()) + if (grps.isEmpty()) task0 = new GridFinishedFuture<>(Collections.emptySet()); else { dumpDir.mkdirs(); @@ -1248,7 +1249,8 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter req.snapshotPath(), dumpDir, tmpWorkDir, - ioFactory + ioFactory, + grps )); } @@ -1266,7 +1268,7 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter req.requestId(), cctx.localNode().consistentId().toString(), req.snapshotName(), - grpIds, + grps, nodes ); @@ -2903,7 +2905,7 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter /** */ private void removeDumpLock(String dumpName) throws IgniteCheckedException { - File lock = dumpLockFile(snapshotLocalDir(dumpName, null, locDumpDir), cctx); + File lock = new File(nodeDumpDirectory(snapshotLocalDir(dumpName, null, locDumpDir), cctx), DUMP_LOCK); if (!lock.exists()) throw new IgniteCheckedException("Lock file not exists: " + lock); @@ -2913,17 +2915,12 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter } /** */ - public static File dumpLockFile(File dumpDir, GridCacheSharedContext<?, ?> cctx) throws IgniteCheckedException { + public static File nodeDumpDirectory(File dumpDir, GridCacheSharedContext<?, ?> cctx) throws IgniteCheckedException { File nodeDumpDir = new File(dumpDir, databaseRelativePath(cctx.kernalContext().pdsFolderResolver().resolveFolders().folderName())); - if (nodeDumpDir.exists()) { - if (!nodeDumpDir.isDirectory()) - throw new IgniteCheckedException(nodeDumpDir + " must be a directory"); - } - else if (!nodeDumpDir.mkdirs()) - throw new IgniteCheckedException("Dump directory can't be created: " + nodeDumpDir); + IgniteUtils.ensureDirectory(nodeDumpDir, "dump directory", null); - return new File(nodeDumpDir, DUMP_LOCK); + return nodeDumpDir; } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/dump/DumpCacheFutureTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/dump/DumpCacheFutureTask.java index d2090a1ef17..30e56086f57 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/dump/DumpCacheFutureTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/dump/DumpCacheFutureTask.java @@ -19,22 +19,37 @@ package org.apache.ignite.internal.processors.cache.persistence.snapshot.dump; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.internal.MarshallerContextImpl; +import org.apache.ignite.internal.processors.cache.CacheGroupContext; +import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.GridCacheSharedContext; +import org.apache.ignite.internal.processors.cache.StoredCacheData; import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory; import org.apache.ignite.internal.processors.cache.persistence.partstate.GroupPartitionId; import org.apache.ignite.internal.processors.cache.persistence.snapshot.AbstractSnapshotFutureTask; import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager; import org.apache.ignite.internal.processors.cache.persistence.snapshot.SnapshotSender; +import org.apache.ignite.internal.util.IgniteUtils; import org.jetbrains.annotations.Nullable; +import static org.apache.ignite.internal.processors.cache.GridLocalConfigManager.cachDataFilename; +import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.CACHE_DIR_PREFIX; +import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.CACHE_GRP_DIR_PREFIX; +import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.DUMP_LOCK; + /** */ public class DumpCacheFutureTask extends AbstractSnapshotFutureTask<Void> implements BiConsumer<String, File> { /** */ private final File dumpDir; + /** */ + private final List<Integer> grps; + /** * @param cctx Cache context. * @param dumpName Dump name. @@ -51,7 +66,8 @@ public class DumpCacheFutureTask extends AbstractSnapshotFutureTask<Void> implem @Nullable String snpPath, File dumpDir, File tmpWorkDir, - FileIOFactory ioFactory + FileIOFactory ioFactory, + List<Integer> grps ) { super( cctx, @@ -80,6 +96,7 @@ public class DumpCacheFutureTask extends AbstractSnapshotFutureTask<Void> implem ); this.dumpDir = dumpDir; + this.grps = grps; cctx.cache().configManager().addConfigurationChangeListener(this); } @@ -87,9 +104,40 @@ public class DumpCacheFutureTask extends AbstractSnapshotFutureTask<Void> implem /** {@inheritDoc} */ @Override public boolean start() { try { - log.info("start!"); + log.info("Start cache dump [name=" + snpName + ", grps=" + grps + ']'); + + File dumpNodeDir = IgniteSnapshotManager.nodeDumpDirectory(dumpDir, cctx); + + createDumpLock(dumpNodeDir); + + for (Integer grp : grps) { + CacheGroupContext grpCtx = cctx.cache().cacheGroup(grp); + + File grpDir = new File( + dumpNodeDir, + (grpCtx.caches().size() > 1 ? CACHE_GRP_DIR_PREFIX : CACHE_DIR_PREFIX) + grpCtx.cacheOrGroupName() + ); + + IgniteUtils.ensureDirectory(grpDir, "dump group directory", null); + + for (GridCacheContext<?, ?> cacheCtx : grpCtx.caches()) { + CacheConfiguration<?, ?> ccfg = cacheCtx.config(); + + cctx.cache().configManager().writeCacheData( + new StoredCacheData(ccfg), + new File(grpDir, cachDataFilename(ccfg)) + ); + } + } + + cctx.kernalContext().cacheObjects().saveMetadata( + cctx.kernalContext().cacheObjects().binary().types(), + dumpDir + ); - lockDumpDirectory(); + MarshallerContextImpl.saveMappings(cctx.kernalContext(), cctx.kernalContext() + .marshallerContext() + .getCachedMappings(), dumpDir); onDone(); } @@ -101,8 +149,8 @@ public class DumpCacheFutureTask extends AbstractSnapshotFutureTask<Void> implem } /** */ - private void lockDumpDirectory() throws IgniteCheckedException, IOException { - File lock = IgniteSnapshotManager.dumpLockFile(dumpDir, cctx); + private void createDumpLock(File dumpNodeDir) throws IgniteCheckedException, IOException { + File lock = new File(dumpNodeDir, DUMP_LOCK); if (!lock.createNewFile()) throw new IgniteCheckedException("Lock file can't be created or already exists: " + lock.getAbsolutePath()); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteCacheDumpSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteCacheDumpSelfTest.java index 93698443140..1f27df89772 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteCacheDumpSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteCacheDumpSelfTest.java @@ -22,11 +22,22 @@ import java.util.Collections; import java.util.stream.IntStream; import javax.management.DynamicMBean; import org.apache.ignite.IgniteCache; +import org.apache.ignite.cluster.ClusterState; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.platform.model.ACL; +import org.apache.ignite.platform.model.Key; +import org.apache.ignite.platform.model.Role; +import org.apache.ignite.platform.model.User; +import org.apache.ignite.platform.model.Value; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.junit.Test; import static org.apache.ignite.internal.management.api.CommandMBean.INVOKE; +import static org.apache.ignite.platform.model.AccessLevel.SUPER; /** */ public class IgniteCacheDumpSelfTest extends GridCommonAbstractTest { @@ -37,13 +48,34 @@ public class IgniteCacheDumpSelfTest extends GridCommonAbstractTest { cleanPersistenceDir(); } + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + return super.getConfiguration(igniteInstanceName).setDataStorageConfiguration( + new DataStorageConfiguration() + .setDefaultDataRegionConfiguration(new DataRegionConfiguration() + .setPersistenceEnabled(true)) + ); + } + /** */ @Test public void testCacheDump() throws Exception { try (IgniteEx ign = startGrid(0)) { + ign.cluster().state(ClusterState.ACTIVE); + IgniteCache<Object, Object> cache = ign.createCache(DEFAULT_CACHE_NAME); + IgniteCache<Object, Object> grpCache0 = ign.createCache( + new CacheConfiguration<>().setGroupName("grp").setName("cache-0") + ); + IgniteCache<Object, Object> grpCache1 = ign.createCache( + new CacheConfiguration<>().setGroupName("grp").setName("cache-1") + ); - IntStream.range(0, 10).forEach(i -> cache.put(i, i)); + IntStream.range(0, 10).forEach(i -> { + cache.put(i, i); + grpCache0.put(i, new User(i, ACL.values()[i % ACL.values().length], new Role("Role" + i, SUPER))); + grpCache1.put(new Key(i), new Value(String.valueOf(i))); + }); Object[] args = {"dump", ""};
