You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Ignite TC Bot (Jira)" <ji...@apache.org> on 2026/07/12 06:47:00 UTC

[jira] [Commented] (IGNITE-28870) Restore snapshot temporary files cleanup logic

    [ https://issues.apache.org/jira/browse/IGNITE-28870?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18095669#comment-18095669 ] 

Ignite TC Bot commented on IGNITE-28870:
----------------------------------------

{panel:title=Branch: [pull/13358/head] Base: [master] : No blockers found!|borderStyle=dashed|borderColor=#ccc|titleBGColor=#D6F7C1}{panel}
{panel:title=Branch: [pull/13358/head] Base: [master] : New Tests (8)|borderStyle=dashed|borderColor=#ccc|titleBGColor=#D6F7C1}
{color:#00008b}Snapshots 7{color} [[tests 8|https://ci2.ignite.apache.org/viewLog.html?buildId=9201595]]
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsRemovedIfNotEmptyOnError[encryption=false, onlyPrimay=true] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsNotRemovedIfNotEmptyOnSuccess[encryption=false, onlyPrimay=true] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsRemovedIfNotEmptyOnError[encryption=false, onlyPrimay=false] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsNotRemovedIfNotEmptyOnSuccess[encryption=false, onlyPrimay=false] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsRemovedIfNotEmptyOnError[encryption=true, onlyPrimay=true] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsNotRemovedIfNotEmptyOnSuccess[encryption=true, onlyPrimay=true] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsRemovedIfNotEmptyOnError[encryption=true, onlyPrimay=false] - PASSED{color}
* {color:#013220}IgniteSnapshotTestSuite7: IgniteSnapshotManagerSelfTest.testSnapshotTmpRootIsNotRemovedIfNotEmptyOnSuccess[encryption=true, onlyPrimay=false] - PASSED{color}

{panel}
[TeamCity *--&gt; Run :: All* Results|https://ci2.ignite.apache.org/viewLog.html?buildId=9201603&amp;buildTypeId=IgniteTests24Java8_RunAll]
{color:#ffffff}tcbot-analysis-comment chainBuildId=9201603 rerunBuildIds=9202192{color}

> Restore snapshot temporary files cleanup logic
> ----------------------------------------------
>
>                 Key: IGNITE-28870
>                 URL: https://issues.apache.org/jira/browse/IGNITE-28870
>             Project: Ignite
>          Issue Type: Bug
>            Reporter: Oleg Valuyskiy
>            Assignee: Oleg Valuyskiy
>            Priority: Minor
>              Labels: ise
>         Attachments: SnapshotTmpDirCleanupReproducer.patch
>
>          Time Spent: 50m
>  Remaining Estimate: 0h
>
> h3. Problem
> After the changes introduced in IGNITE-24130 / PR #11896, the temporary snapshot files cleanup logic was accidentally changed. Previously, snapshot cleanup used two different directories:
> {code:java}
> U.delete(sft.tempFileTree().nodeStorage());
> // Delete snapshot directory if no other files exists.
> try {
>     if (U.fileCount(sft.tempFileTree().root().toPath()) == 0 || err != null)
>         U.delete(sft.tempFileTree().root().toPath());
> }
> catch (IOException e) {
>     log.error("Snapshot directory doesn't exist [snpName=" + snpName + ", dir=" + sft.tempFileTree().root() + ']');
> }
> {code}
> These two directories represent different levels of the temporary snapshot file tree. For example:
>  * sft.tempFileTree().root() - <work_dir>/db/<node_storage>/snp/<snapshot_name>
>  * sft.tempFileTree().nodeStorage() - <work_dir>/db/<node_storage>/snp/<snapshot_name>/db/<node_storage>
> So the original cleanup logic was:
>  * remove the node-specific temporary snapshot storage directory
>  * then check the temporary root directory of the current snapshot
>  * remove the root directory only if it becomes empty
>  * remove the root directory regardless of its contents if snapshot processing finished with an error, because the temporary state of the current snapshot is considered invalid
> In other words, the original logic intentionally worked with two different filesystem levels.
> h3. Regression
> After IGNITE-24130 / PR #11896, the cleanup logic was refactored into a helper method:
> {code:java}
> public static void removeTmpSnapshotFiles(SnapshotFileTree sft, boolean err, IgniteLogger log) {
>     NodeFileTree tmpFt = sft.tempFileTree();
>     ```
>     removeTmpDir(tmpFt.root(), err, log);
>     for (File tmpDrStorage : tmpFt.extraStorages().values())
>         removeTmpDir(tmpDrStorage.getParentFile(), err, log);
>     ```
> }
> {code}
> And the helper currently accepts only one directory:
> {code:java}
> private static void removeTmpDir(File dir, boolean err, IgniteLogger log) {
>     U.delete(dir);
>     ```
>     // Delete snapshot directory if no other files exists.
>     try {
>         if (U.fileCount(dir.toPath()) == 0 || err)
>             U.delete(dir.toPath());
>     }
>     catch (IOException e) {
>         log.error("Snapshot directory doesn't exist [snpName=" + dir.getName() + ", dir=" + dir.getParentFile() + ']');
>     }
>     ```
> }
> {code}
> This accidentally collapses the original two-level cleanup logic into a single directory. As a result, the code now:
>  * removes the snapshot temporary root directory
>  * then tries to count files in the same directory
>  * then tries to delete the same directory again
> For example, instead of deleting:
> {code:java}
> <work_dir>/db/<node_storage>/snp/<snapshot_name>/db/<node_storage>{code}
> and then checking:
> {code:java}
> <work_dir>/db/<node_storage>/snp/<snapshot_name>{code}
> the current implementation deletes:
> {code:java}
> <work_dir>/db/<node_storage>/snp/<snapshot_name>{code}
> and then calls *U.fileCount(...)* for the same already deleted path. This leads to a  false ERROR in the log after a successful snapshot creation:
> {code:java}
> Snapshot directory doesn't exist [snpName=<snapshot_name>, dir=<work_dir>/db/<node_storage>/snp]{code}
> (this is how the issue was identified in the first place, reproducer: [^SnapshotTmpDirCleanupReproducer.patch])
> Thus, because of the cahnges introduced in IGNITE-24130 the original cleanup logic was changed. The success path became more aggressive: the whole snapshot temporary root is removed before checking whether it still contains any unexpected files. Previously, such a non-empty root was not removed on the success path.
> h3. Expected behavior
> The cleanup logic should restore the original two-level behavior:
>  * remove the node-specific temporary snapshot storage directory
>  * then check the snapshot temporary root directory
>  * remove the root directory if it becomes empty
>  * remove the root directory regardless of its contents if snapshot processing finished with an error
>  * do not call *U.fileCount(...)* on the directory that has just been deleted
>  * do not log an error when the temporary directory has already been successfully removed



--
This message was sent by Atlassian Jira
(v8.20.10#820010)