diff --git a/src/BlockFile.cpp b/src/BlockFile.cpp index fcb3f9d2f..db43cfc26 100644 --- a/src/BlockFile.cpp +++ b/src/BlockFile.cpp @@ -116,6 +116,7 @@ unsigned long BlockFile::gBlockFileDestructionCount { 0 }; BlockFile::~BlockFile() { if (!IsLocked() && mFileName.HasName()) + // PRL: what should be done if this fails? wxRemoveFile(mFileName.GetFullPath()); ++gBlockFileDestructionCount; diff --git a/src/Dependencies.cpp b/src/Dependencies.cpp index c728e4cd5..1406e30b5 100644 --- a/src/Dependencies.cpp +++ b/src/Dependencies.cpp @@ -81,16 +81,12 @@ static void GetAllSeqBlocks(AudacityProject *project, // tracks and replace each aliased block file with its replacement. // Note that this code respects reference-counting and thus the // process of making a project self-contained is actually undoable. -static void ReplaceBlockFiles(AudacityProject *project, +static void ReplaceBlockFiles(BlockPtrArray &blocks, ReplacedBlockFileHash &hash) +// NOFAIL-GUARANTEE { - //const auto &dirManager = project->GetDirManager(); - BlockPtrArray blocks; - GetAllSeqBlocks(project, &blocks); - - int i; - for (i = 0; i < (int)blocks.size(); i++) { - auto &f = blocks[i]->f; + for (const auto &pBlock : blocks) { + auto &f = pBlock->f; const auto src = &*f; if (hash.count( src ) > 0) { const auto &dst = hash[src]; @@ -156,6 +152,7 @@ void FindDependencies(AudacityProject *project, // all of those alias block files with disk block files. static void RemoveDependencies(AudacityProject *project, AliasedFileArray &aliasedFiles) +// STRONG-GUARANTEE { const auto &dirManager = project->GetDirManager(); @@ -198,6 +195,8 @@ static void RemoveDependencies(AudacityProject *project, BlockFilePtr newBlockFile; { 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); newBlockFile = dirManager->NewSimpleBlockFile(buffer.ptr(), len, format); @@ -210,15 +209,18 @@ static void RemoveDependencies(AudacityProject *project, completedBytes += SAMPLE_SIZE(format) * len; updateResult = progress.Update(completedBytes, totalBytesToProcess); if (updateResult != ProgressResult::Success) - break; + // leave the project unchanged + return; } } + // COMMIT OPERATIONS needing NOFAIL-GUARANTEE: + // Above, we created a SimpleBlockFile contained in our project // to go with each AliasBlockFile that we wanted to migrate. // However, that didn't actually change any references to these // 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)) { - AliasedFileArray aliasedFilesToDelete; + AliasedFileArray aliasedFilesToDelete, remainingAliasedFiles; long i = 0; - for(auto iter = mAliasedFiles.begin(); iter != mAliasedFiles.end();) { - if (mFileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED)) { - // Two-step move could be simplified when all compilers have C++11 vector - aliasedFilesToDelete.push_back(AliasedFile{}); - aliasedFilesToDelete.back() = std::move(*iter); - iter = mAliasedFiles.erase(iter); - } + for( const auto &file : mAliasedFiles ) { + if (mFileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED)) + aliasedFilesToDelete.push_back( file ); else - ++iter; + remainingAliasedFiles.push_back( file ); ++i; } + // provides STRONG-GUARANTEE RemoveDependencies(mProject, aliasedFilesToDelete); + + // COMMIT OPERATIONS needing NOFAIL-GUARANTEE: + mAliasedFiles.swap( remainingAliasedFiles ); PopulateList(); if (mAliasedFiles.empty() || !mHasNonMissingFiles)