1
0
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:
Paul Licameli 2016-11-24 10:04:40 -05:00
parent 7159966eb4
commit f5fe9281e4
2 changed files with 22 additions and 19 deletions

View File

@ -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;

View File

@ -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)