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 <nizhi...@apache.org>
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", ""};
 

Reply via email to