mirror of
https://github.com/cookiengineer/audacity
synced 2025-09-23 15:41:09 +02:00
Strong safety guarantee for removing file dependencies
This commit is contained in:
parent
7159966eb4
commit
f5fe9281e4
@ -116,6 +116,7 @@ unsigned long BlockFile::gBlockFileDestructionCount { 0 };
|
|||||||
BlockFile::~BlockFile()
|
BlockFile::~BlockFile()
|
||||||
{
|
{
|
||||||
if (!IsLocked() && mFileName.HasName())
|
if (!IsLocked() && mFileName.HasName())
|
||||||
|
// PRL: what should be done if this fails?
|
||||||
wxRemoveFile(mFileName.GetFullPath());
|
wxRemoveFile(mFileName.GetFullPath());
|
||||||
|
|
||||||
++gBlockFileDestructionCount;
|
++gBlockFileDestructionCount;
|
||||||
|
@ -81,16 +81,12 @@ static void GetAllSeqBlocks(AudacityProject *project,
|
|||||||
// tracks and replace each aliased block file with its replacement.
|
// tracks and replace each aliased block file with its replacement.
|
||||||
// Note that this code respects reference-counting and thus the
|
// Note that this code respects reference-counting and thus the
|
||||||
// process of making a project self-contained is actually undoable.
|
// process of making a project self-contained is actually undoable.
|
||||||
static void ReplaceBlockFiles(AudacityProject *project,
|
static void ReplaceBlockFiles(BlockPtrArray &blocks,
|
||||||
ReplacedBlockFileHash &hash)
|
ReplacedBlockFileHash &hash)
|
||||||
|
// NOFAIL-GUARANTEE
|
||||||
{
|
{
|
||||||
//const auto &dirManager = project->GetDirManager();
|
for (const auto &pBlock : blocks) {
|
||||||
BlockPtrArray blocks;
|
auto &f = pBlock->f;
|
||||||
GetAllSeqBlocks(project, &blocks);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < (int)blocks.size(); i++) {
|
|
||||||
auto &f = blocks[i]->f;
|
|
||||||
const auto src = &*f;
|
const auto src = &*f;
|
||||||
if (hash.count( src ) > 0) {
|
if (hash.count( src ) > 0) {
|
||||||
const auto &dst = hash[src];
|
const auto &dst = hash[src];
|
||||||
@ -156,6 +152,7 @@ void FindDependencies(AudacityProject *project,
|
|||||||
// all of those alias block files with disk block files.
|
// all of those alias block files with disk block files.
|
||||||
static void RemoveDependencies(AudacityProject *project,
|
static void RemoveDependencies(AudacityProject *project,
|
||||||
AliasedFileArray &aliasedFiles)
|
AliasedFileArray &aliasedFiles)
|
||||||
|
// STRONG-GUARANTEE
|
||||||
{
|
{
|
||||||
const auto &dirManager = project->GetDirManager();
|
const auto &dirManager = project->GetDirManager();
|
||||||
|
|
||||||
@ -198,6 +195,8 @@ static void RemoveDependencies(AudacityProject *project,
|
|||||||
BlockFilePtr newBlockFile;
|
BlockFilePtr newBlockFile;
|
||||||
{
|
{
|
||||||
SampleBuffer buffer(len, format);
|
SampleBuffer buffer(len, format);
|
||||||
|
// We tolerate exceptions from NewSimpleBlockFile and so we
|
||||||
|
// can allow exceptions from ReadData too
|
||||||
f->ReadData(buffer.ptr(), format, 0, len);
|
f->ReadData(buffer.ptr(), format, 0, len);
|
||||||
newBlockFile =
|
newBlockFile =
|
||||||
dirManager->NewSimpleBlockFile(buffer.ptr(), len, format);
|
dirManager->NewSimpleBlockFile(buffer.ptr(), len, format);
|
||||||
@ -210,15 +209,18 @@ static void RemoveDependencies(AudacityProject *project,
|
|||||||
completedBytes += SAMPLE_SIZE(format) * len;
|
completedBytes += SAMPLE_SIZE(format) * len;
|
||||||
updateResult = progress.Update(completedBytes, totalBytesToProcess);
|
updateResult = progress.Update(completedBytes, totalBytesToProcess);
|
||||||
if (updateResult != ProgressResult::Success)
|
if (updateResult != ProgressResult::Success)
|
||||||
break;
|
// leave the project unchanged
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// COMMIT OPERATIONS needing NOFAIL-GUARANTEE:
|
||||||
|
|
||||||
// Above, we created a SimpleBlockFile contained in our project
|
// Above, we created a SimpleBlockFile contained in our project
|
||||||
// to go with each AliasBlockFile that we wanted to migrate.
|
// to go with each AliasBlockFile that we wanted to migrate.
|
||||||
// However, that didn't actually change any references to these
|
// However, that didn't actually change any references to these
|
||||||
// blockfiles in the Sequences, so we do that next...
|
// blockfiles in the Sequences, so we do that next...
|
||||||
ReplaceBlockFiles(project, blockFileHash);
|
ReplaceBlockFiles(blocks, blockFileHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -473,22 +475,22 @@ void DependencyDialog::OnYes(wxCommandEvent & WXUNUSED(event))
|
|||||||
|
|
||||||
void DependencyDialog::OnCopySelectedFiles(wxCommandEvent & WXUNUSED(event))
|
void DependencyDialog::OnCopySelectedFiles(wxCommandEvent & WXUNUSED(event))
|
||||||
{
|
{
|
||||||
AliasedFileArray aliasedFilesToDelete;
|
AliasedFileArray aliasedFilesToDelete, remainingAliasedFiles;
|
||||||
|
|
||||||
long i = 0;
|
long i = 0;
|
||||||
for(auto iter = mAliasedFiles.begin(); iter != mAliasedFiles.end();) {
|
for( const auto &file : mAliasedFiles ) {
|
||||||
if (mFileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED)) {
|
if (mFileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED))
|
||||||
// Two-step move could be simplified when all compilers have C++11 vector
|
aliasedFilesToDelete.push_back( file );
|
||||||
aliasedFilesToDelete.push_back(AliasedFile{});
|
|
||||||
aliasedFilesToDelete.back() = std::move(*iter);
|
|
||||||
iter = mAliasedFiles.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
++iter;
|
remainingAliasedFiles.push_back( file );
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// provides STRONG-GUARANTEE
|
||||||
RemoveDependencies(mProject, aliasedFilesToDelete);
|
RemoveDependencies(mProject, aliasedFilesToDelete);
|
||||||
|
|
||||||
|
// COMMIT OPERATIONS needing NOFAIL-GUARANTEE:
|
||||||
|
mAliasedFiles.swap( remainingAliasedFiles );
|
||||||
PopulateList();
|
PopulateList();
|
||||||
|
|
||||||
if (mAliasedFiles.empty() || !mHasNonMissingFiles)
|
if (mAliasedFiles.empty() || !mHasNonMissingFiles)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user