From 4ec7044639f7ebceac59d5bdfa75f749c00f59be Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 7 Nov 2016 16:46:36 -0500 Subject: [PATCH] Better calculation of space usage in undo history dialog... ... Don't double-count any block files. Count each only in the latest undo history state containing it, because you reclaim its space only by deleting the history at least up to that state. Block files may still be double-counted between undo history and the clipboard. --- src/UndoManager.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/UndoManager.cpp b/src/UndoManager.cpp index bfeb2f3f9..979a0ce7d 100644 --- a/src/UndoManager.cpp +++ b/src/UndoManager.cpp @@ -72,7 +72,7 @@ UndoManager::~UndoManager() namespace { SpaceArray::value_type - CalculateUsage(TrackList *tracks, Set *prev, Set *cur) + CalculateUsage(TrackList *tracks, Set *seen) { SpaceArray::value_type result = 0; @@ -90,18 +90,17 @@ namespace { { const auto &file = block.f; - // Accumulate space used by the file if the file didn't exist - // in the previous level - if (!prev || !cur || - (prev->count( &*file ) == 0 && cur->count( &*file ) == 0)) + // Accumulate space used by the file if the file was not + // yet seen + if ( !seen || (seen->count( &*file ) == 0 ) ) { unsigned long long usage{ file->GetSpaceUsage() }; result += usage; } // Add file to current set - if (cur) - cur->insert( &*file ); + if (seen) + seen->insert( &*file ); } } @@ -117,25 +116,31 @@ void UndoManager::CalculateSpaceUsage() space.clear(); space.resize(stack.size(), 0); - Set s1, s2; - Set *prev = &s1; - Set *cur = &s2; + Set seen; - for (size_t i = 0, cnt = stack.size(); i < cnt; i++) + // After copies and pastes, a block file may be used in more than + // one place in one undo history state, and it may be used in more than + // one undo history state. It might even be used in two states, but not + // in another state that is between them -- as when you have state A, + // then make a cut to get state B, but then paste it back into state C. + + // So be sure to count each block file once only, in the last undo item that + // contains it. + + // Why the last and not the first? Because the user of the History dialog + // may delete undo states, oldest first. To reclaim disk space you must + // delete all states containing the block file. So the block file's + // contribution to space usage should be counted only in that latest state. + + for (size_t nn = stack.size(); nn--;) { - // Swap map pointers - std::swap(cur, prev); - - // And clean out the NEW current map - cur->clear(); - // Scan all tracks at current level - auto tracks = stack[i]->state.tracks.get(); - space[i] = CalculateUsage(tracks, prev, cur); + auto tracks = stack[nn]->state.tracks.get(); + space[nn] = CalculateUsage(tracks, &seen); } mClipboardSpaceUsage = CalculateUsage - (AudacityProject::GetClipboardTracks(), nullptr, nullptr); + (AudacityProject::GetClipboardTracks(), nullptr); //TIMER_STOP( space_calc ); }