Conversation
# Conflicts: # modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/schema/IgniteSchema.java
… into IGNITE-29050-Introduce-snapshot-deletion-command # Conflicts: # modules/core/src/main/java/org/apache/ignite/internal/management/snapshot/SnapshotDeleteCommand.java # modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotDeleteRollingUpgradeTest.java
| active for the snapshot. | ||
| * The operation cannot be undone and the deleted snapshot cannot be restored. The command prompts for a confirmation. | ||
| * Before deletion, no snapshot validation is done except finding and reading its metadata. If the metadata isn't found or cannot be read, snapshot isn't deleted. | ||
| * If the provided snapshot path belongs to Ignite's home or to Ignite's a not snapshot work directory, the operation fails. |
There was a problem hiding this comment.
why do we need this additional check ? You think someone can put snap meta file into Ignite home dir ?
There was a problem hiding this comment.
Isn't it a good practice in general as we discussed? Why we allow to create snapshots everywhere inside Ignite? Looks like a bug. I believe, we shouldn't allow any attempts to corrupt Ignite's data with Ignite's features. A project/framework which takes into account such cases looks better to me.
There was a problem hiding this comment.
We discuss: if folder contains snap meta - it can be removed, othervize - no, why we need code complication?
There was a problem hiding this comment.
Also, we discussed that we should not touch Ignite's directories like snapshot creating anywhere inside. Reverted.
There was a problem hiding this comment.
yes, it`s true, no one ignite working directory (besides snap of course) can`t store snap meta.
There was a problem hiding this comment.
yes, it
s true, no one ignite working directory (besides snap of course) cant store snap meta.
Currently, can. You can use relative or absolute path while creating a snp.
|
|
||
| /** {@inheritDoc} */ | ||
| @Override public String confirmationPrompt(SnapshotDeleteCommandArg arg) { | ||
| return "This operation will completely remove snapshot: '" + arg.snapshotName() + "' and all its incrementals " + |
There was a problem hiding this comment.
| return "This operation will completely remove snapshot: '" + arg.snapshotName() + "' and all its incrementals " + | |
| return "This operation will completely remove snapshot: '" + arg.snapshotName() + "' and all its incremental snapshots." + |
| U.nl() + U.nl() + | ||
| "If the security is enabled, the operation requires the snapshot administration permissions." + | ||
| U.nl() + U.nl() + | ||
| "Deletion in not snapshots Ignite's directories and deletion of any data without or corrupted snapshot " + |
There was a problem hiding this comment.
| "Deletion in not snapshots Ignite's directories and deletion of any data without or corrupted snapshot " + | |
| "Deletion of any data without (valid) snapshot metadata is prohibited." + |
There was a problem hiding this comment.
Too complex for understanding, also incorrect:
snapshots Ignite's directories -> Ignite snapshot directories
seems my variant still more readable
| * @return {@code True}, if data is found and completely deleted; | ||
| * {@code False}, if nothing found or if data is found but might not be deleted completely. | ||
| */ | ||
| public boolean deleteLocalSnapshot(SnapshotFileTree sft, @Nullable AtomicBoolean existsFlag) { |
There was a problem hiding this comment.
I wonder - why Atomic here ?
There was a problem hiding this comment.
Because:
Variable used in lambda expression should be final or effectively final
There was a problem hiding this comment.
I question about atomic - you reply about lambda and final )
Seems this complication cause you want return
IgniteSnapshotManager#deleteLocalSnapshot 2 states here, from return mechanism and from AtomicBoolean state, overcomplicated, change it plz
| U.delete(sft.binaryMeta()); | ||
| sft.allStorages().forEach(U::delete); | ||
| U.delete(sft.meta()); | ||
| if (sft.binaryMeta().exists() && !U.delete(sft.binaryMeta()) && sft.binaryMeta().exists()) |
There was a problem hiding this comment.
| if (sft.binaryMeta().exists() && !U.delete(sft.binaryMeta()) && sft.binaryMeta().exists()) | |
| if (sft.binaryMeta().exists() && !U.delete(sft.binaryMeta())) |
There was a problem hiding this comment.
Simplified but in another manner. Added a comment.
| sft.allStorages().forEach(U::delete); | ||
| U.delete(sft.meta()); | ||
| if (sft.binaryMeta().exists() && !U.delete(sft.binaryMeta()) && sft.binaryMeta().exists()) | ||
| res = false; |
There was a problem hiding this comment.
Because we might not delete snapshot al all in this case when nodes share their working and snapshot directories. This would be unexpected behaviour. We have to delete if we can. If someone concurrently deletes, we should not stop. This is not an error in this case. Node can steal deletion jobs
There was a problem hiding this comment.
overcomplicated, you need to use directory lock, check public static class NodeFileLockHolder extends FileLockHolder
|
|
||
| deleteDirectory(sft.binaryMetaRoot()); | ||
| deleteDirectory(sft.marshaller()); | ||
| if (sft.meta().exists() && !U.delete(sft.meta()) && sft.meta().exists()) |
There was a problem hiding this comment.
from spec i can found that : (translated ver)
All data in the snapshot directories is deleted. There are no checks on their type or affiliation to the snapshot.
thus - why do you need all near checks ?
There was a problem hiding this comment.
Here no any data types and content checks. All this made for concurrent deletion when nodes share their working and snapshot directories.
I've added the comment:
// The 'exists' checks are for a concurrent deletion when nodes share their working and snapshot directories.
// Nodes may steal removal jobs and the files aren't synchronized. There are gaps between and `exists()` and `delete()`.
// We try to delete first. If snapshot data wasn't deleted because it doesn't already exist is not a delete error here.
|
|
||
| try { | ||
| contexts.remove(ctx.req.snapshotName()); | ||
| contexts.remove(ctx.req.snapshotName().toLowerCase()); |
There was a problem hiding this comment.
If snap name is case insensitive - it need to be documented somehow and transformed into lower case in command parsing level, isn`t it ?
There was a problem hiding this comment.
This is to prevent concurrent snapshot operations for the same snapshot. User can type the name using any variants of characters cases
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 3
Open (16)
deleteDirectorycurrently returnsfalseeven on success becauseresis initialized tofalse… · NewdeleteDirectorycurrently returnsfalseeven on success becauseresis initialized tofalse… · NewdeleteDirectorycurrently returnsfalseeven on success becauseresis initialized tofalse… · New Typos/grammar in documentation: “pesmissins” → “permissions”, “a not snapshot” → “a non-snapshot”,… · New Typos/grammar in documentation: “pesmissins” → “permissions”, “a not snapshot” → “a non-snapshot”,… · New The loop variabledis not used when streaming data;streamer.addData(i, i)repeatedly writes… · New There are multiple grammar issues in this user-visible confirmation prompt (e.g., “Deletion in not… · New Two issues here: (1)toLowerCase()without an explicit locale can produce surprising results in… · New Two issues here: (1)toLowerCase()without an explicit locale can produce surprising results in… · New Two issues here: (1)toLowerCase()without an explicit locale can produce surprising results in… · New This method rejects other snapshot states viaIgniteCheckedException, but the new “delete in… · New “propogated” is misspelled; should be “propagated”. · New The identifier and the output text contain a typo/awkward phrasing:UNSURED_DELETION_PREFshould… · New Javadoc typos: “exeption” → “exception”, “cant” → “can’t/cannot”. · New The returned validation text has a grammar issue (“a an”) and reads awkwardly for a user-facing… · NewG.allGrids();is a no-op statement here (return value is ignored, and it has no side effects). It… · New
Resolved since last review (9)
This assigns core feature ID 1 to snapshot deletion, but the existing simulated 2.19.2 release… Request identity uses the raw path string, sonull, the default snapshots root, and an equivalent… The set is keyed by the raw path string, butdeletePhasetreats an empty path as the default… This lexical prefix check does not ensure that the path is actually belowsnapshotsRoot: values… The feature check is only performed insidedeletePhase, after this call has broadcast an… The new test cleanup comment misspells “paths”. The distributed process waits forserverNodes(topVer), not baseline nodes, anddeletePhase… The new Javadoc misspells “snapshot”. The new test cleanup comment misspells “patches”.
Possible compatibility issues. Please, check rolling upgrade casesThis PR modifies protected classes (with Order annotation). Affected files:
|
| * The operation cannot be undone and the deleted snapshot cannot be restored. The command prompts for a confirmation. | ||
| * Before deletion, no snapshot validation is done except finding and reading its metadata. If the metadata isn't found | ||
| or cannot be read, snapshot isn't deleted. | ||
| * If the provided snapshot path belongs to Ignite's home or to Ignite's a non-snapshot work directory, the operation fails. |
There was a problem hiding this comment.
now my comment move to this line, no need additional mention here and code checks.
| U.nl() + U.nl() + | ||
| "If the security is enabled, the operation requires the snapshot administration permissions." + | ||
| U.nl() + U.nl() + | ||
| "Deletion in not snapshots Ignite's directories and deletion of any data without or corrupted snapshot " + |
There was a problem hiding this comment.
Too complex for understanding, also incorrect:
snapshots Ignite's directories -> Ignite snapshot directories
seems my variant still more readable
| @Override public String confirmationPrompt(SnapshotDeleteCommandArg arg) { | ||
| return "This operation will completely remove snapshot: '" + arg.snapshotName() + "' and all its incrementals." + | ||
| U.nl() + U.nl() + | ||
| "If the security is enabled, the operation requires the snapshot administration permissions." + | ||
| U.nl() + U.nl() + | ||
| "Deletion in not snapshots Ignite's directories and deletion of any data without or corrupted snapshot " + | ||
| "metadata are prohibited." + | ||
| U.nl() + U.nl() + | ||
| "The operation cannot be reverted." + | ||
| U.nl() + U.nl() + | ||
| "NOTE: Snapshot data on offline server nodes will remain untouched."; | ||
| } |
There was a problem hiding this comment.
Copilot found the same- fix it !
|
|
||
| /** */ | ||
| public String snapshotName() { | ||
| return snapshotName; |
There was a problem hiding this comment.
It`s not about arg processing, it about @Nullable annotation
|
|
||
| /** */ | ||
| public String src() { | ||
| return src; |
There was a problem hiding this comment.
I not aware about other commands and I not reviewed them, if it possible to return null - plz annotate it correctly
| * @return {@code True}, if data is found and completely deleted; | ||
| * {@code False}, if nothing found or if data is found but might not be deleted completely. | ||
| */ | ||
| public boolean deleteLocalSnapshot(SnapshotFileTree sft, @Nullable AtomicBoolean existsFlag) { |
There was a problem hiding this comment.
I question about atomic - you reply about lambda and final )
Seems this complication cause you want return
IgniteSnapshotManager#deleteLocalSnapshot 2 states here, from return mechanism and from AtomicBoolean state, overcomplicated, change it plz
| sft.allStorages().forEach(U::delete); | ||
| U.delete(sft.meta()); | ||
| if (sft.binaryMeta().exists() && !U.delete(sft.binaryMeta()) && sft.binaryMeta().exists()) | ||
| res = false; |
There was a problem hiding this comment.
overcomplicated, you need to use directory lock, check public static class NodeFileLockHolder extends FileLockHolder
| * proceeds if snapshot already deleted. | ||
| */ | ||
| @Test | ||
| public void testConcurrentSnapshotDeleteOperation() throws Exception { |
There was a problem hiding this comment.
From java doc: "Tests that snapshot create detects concurrent deletion", but i see that it tests only already existing snap ? Seems this test is not cover conc deletion opertion, other conc tests need to be re checked too



Thank you for submitting the pull request to the Apache Ignite.
In order to streamline the review of the contribution
we ask you to ensure the following steps have been taken:
The Contribution Checklist
The description explains WHAT and WHY was made instead of HOW.
The following pattern must be used:
IGNITE-XXXX Change summarywhereXXXX- number of JIRA issue.(see the Maintainers list)
the
green visaattached to the JIRA ticket (see tabPR Checkat TC.Bot - Instance 1 or TC.Bot - Instance 2)Notes
If you need any help, please email dev@ignite.apache.org or ask anу advice on http://asf.slack.com #ignite channel.