[
https://issues.apache.org/jira/browse/IGNITE-28870?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Oleg Valuyskiy updated IGNITE-28870:
------------------------------------
Attachment: SnapshotTmpDirCleanupReproducer.patch
> False ERROR is logged during snapshot temporary directory cleanup
> -----------------------------------------------------------------
>
> 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
>
>
> h3. Problem
> After a snapshot is successfully created, Ignite may log the following ERROR
> during snapshot temporary directory cleanup:
> {code:java}
> Snapshot directory doesn't exist [snpName=<snapshot_name>,
> dir=<work_dir>/db/<consistent_id>/snp]{code}
> At the same time, the snapshot itself is successfully created in the
> configured snapshot directory.
> The error is misleading because it is logged after the snapshot has already
> been successfully created and the temporary snapshot directory has already
> been removed.
> h3. Root cause
> Before the changes introduced as part of {*}IGNITE-24130 / PR #11896{*},
> snapshot cleanup logic 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}
> The original logic was:
> * delete the temporary directory of the current snapshot operation:
> *sft.tempFileTree().nodeStorage()*
> * then check the parent temporary snapshot root: *sft.tempFileTree().root()*
> * if the parent temporary root has no other files/directories, delete it as
> well
> So the cleanup logic relied on two different filesystem levels:
> {code:java}
> <work_dir>/db/<consistent_id>/snp
> └── <snapshot_name>{code}
> Where:
> * nodeStorage() pointed to the temporary directory of the current snapshot
> * root() pointed to the parent temporary root directory that may contain
> temporary directories of other snapshots
> After the refactoring, this logic was extracted into a helper method that
> receives 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}
> As a result, the same directory is used both as:
> * the directory to delete
> * the directory to inspect with U.fileCount(...);
> * the directory to delete again
> This breaks the original two-level cleanup logic. The method first deletes
> the temporary snapshot directory:
> {code:java}
> U.delete(dir);{code}
> Then it tries to count files in the same already deleted directory:
> {code:java}
> U.fileCount(dir.toPath()){code}
> If the directory was successfully removed, U.fileCount(...) throws
> {*}NoSuchFileException{*}, and Ignite logs an ERROR even though cleanup has
> actually succeeded.
> h3. Why err should not be used in the new helper
> The current snapshot temporary directory is already deleted unconditionally:
> {code:java}
> U.delete(dir);{code}
> Therefore, *err* is not needed to decide whether to remove the current
> snapshot temporary directory.
> Using *err* to delete the parent root directory seems to be questionable. The
> error belongs to the current snapshot operation, while the parent temporary
> root may contain other temporary snapshot directories. Therefore, the parent
> root should only be removed when it becomes empty, not because the current
> snapshot operation has failed.
> h3. Expected behavior
> Snapshot cleanup should:
> * always delete the temporary directory of the current snapshot operation
> * delete the parent temporary snapshot root only if it becomes empty after
> that
> * not log ERROR if the temporary snapshot directory has already been
> successfully removed
> * not delete the parent temporary root just because the current snapshot
> operation finished with an error
--
This message was sent by Atlassian Jira
(v8.20.10#820010)