Repository navigation
ALTER DB: never damage an existing target database (#2800) - #2801
Closed
WingedGuardian wants to merge 1 commit into
Closed
WingedGuardian wants to merge 1 commit into
WingedGuardian wants to merge 1 commit into
Conversation
An existing target is now checked for being pinned like the source, and is renamed aside before the source is moved in; it is deleted only after the move succeeded, and restored if the move fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
See 29d0262 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2800.
Problem
AlterDB.alterdropped an existing target database (DropDB.drop, result ignored) beforemoving the source into place, and
ALTER DBchecked only the source for being opened.On Windows, a file that another process holds open cannot be deleted. The drop then stopped part
way through, the rename failed, and the target was left with files missing and could no longer be
opened. The error named only the source ("Database 'A' could not be renamed.").
Change
org.basex.core.cmd.AlterDB:run(): an existing target is treated like the source. It is closed if the current contextholds it, and the command is refused with
DB_PINNED_Xnaming the target if it is stillpinned or locked (
Context.pinned, the same check as for the source and as indb:alter,which already checks the new name via
NameUpdate.close).alter(): instead of deleting the target first, it is renamed aside to a hidden sibling(
.<target>.<n>; dot-directories are skipped byDatabases.list). Then the source is movedinto place, and only then is the old target deleted. If the source cannot be moved, the target
is moved back. On Windows, renaming a directory fails cleanly while one of its files is open,
so a foreign handle now makes the operation fail without touching either database.
db:alter,db:create(temporary database replacing an existing one) andOPTIMIZE ALLcall thesame
alter()method and get the same guarantee.Behaviour
Measured on Windows 11, Java 24, with the patched class on top of the 13.0 jar (two processes on
one DBPATH):
inf,tbl,txtloratvof the targetatv)OPEN BB; target intactPOSIX
On Linux/macOS, open files never blocked deleting or renaming, so the old code "succeeded" there.
The new code also succeeds there. The aside rename is a directory rename within the same parent,
which is atomic. A reader holding files of the old target keeps its unlinked inodes, exactly as
after the old drop. The new
pinned(target)check refuses where the target is opened by anotherBaseX instance. That case was previously allowed on POSIX and could delete files under a
reader, so this is a deliberate behaviour change, consistent with how the source is handled.
Tests
New
org.basex.core.AlterDBTest:replace: a target is replaced and no hidden aside directory remainstargetOpened: target opened by another session leads to refusal naming the target (command),DB_LOCK1_X(db:alter)targetFileOpened(Windows only, viaAssumptions): aRandomAccessFileon the target'sinf.basexleads to the command anddb:alterfailing with the target intact; the command succeeds after the handle closessourceFileOpened(Windows only): the source cannot be moved, so the target is restoredOn POSIX an open file handle cannot block a rename, so the handle-based cases cannot be simulated
there and are skipped.
targetOpenedruns everywhere.Without the fix,
targetOpenedandtargetFileOpenedfail. With it: AlterDBTest 4/4,CommandTest 43/43, ServerCommandTest, DbModuleTest 56/56 and DbModuleConcurrencyTest all pass.
These were run on Windows against the 13.0 jar; there was no full Maven build.
Open points
DB_NOT_RENAMED_Xnaming the source. Naming the target there would need a new message key inevery
.langfile, so I left it out. The target is no longer modified in that case.between rename and delete), a hidden
.<target>.<n>directory is left behind and logged withUtil.debuglnonly.🤖 Generated with Claude Code