mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-24 08:10:05 +02:00
Sequence consistency check throws; new unused commit functions use it
This commit is contained in:
parent
6b0c5c096b
commit
2ba6065961
@ -411,7 +411,8 @@ void RecordingRecoveryHandler::HandleXMLEndTag(const wxChar *tag)
|
||||
WaveClip* clip = track->NewestOrNewClip();
|
||||
Sequence* seq = clip->GetSequence();
|
||||
|
||||
seq->ConsistencyCheck(wxT("RecordingRecoveryHandler::HandleXMLEndTag"));
|
||||
seq->ConsistencyCheck
|
||||
(wxT("RecordingRecoveryHandler::HandleXMLEndTag"), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,7 +474,8 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
|
||||
elapsed = timer.Time();
|
||||
|
||||
if (mBlockDetail) {
|
||||
t->GetClipByIndex(0)->GetSequence()->DebugPrintf(&tempStr);
|
||||
auto seq = t->GetClipByIndex(0)->GetSequence();
|
||||
seq->DebugPrintf(seq->GetBlockArray(), seq->GetNumSamples(), &tempStr);
|
||||
mToPrint += tempStr;
|
||||
}
|
||||
Printf(wxT("Time to perform %d edits: %ld ms\n"), trials, elapsed);
|
||||
|
136
src/Sequence.cpp
136
src/Sequence.cpp
@ -50,6 +50,8 @@
|
||||
#include "blockfile/SimpleBlockFile.h"
|
||||
#include "blockfile/SilentBlockFile.h"
|
||||
|
||||
#include "InconsistencyException.h"
|
||||
|
||||
size_t Sequence::sMaxDiskBlockSize = 1048576;
|
||||
|
||||
// Sequence methods
|
||||
@ -222,7 +224,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
|
||||
*pbChanged = false; // Revert overall change flag, in case we had some partial success in the loop.
|
||||
}
|
||||
|
||||
bSuccess &= ConsistencyCheck(wxT("Sequence::ConvertToSampleFormat()"));
|
||||
ConsistencyCheck(wxT("Sequence::ConvertToSampleFormat()"));
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
@ -437,9 +439,7 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
|
||||
// Increase ref count or duplicate file
|
||||
}
|
||||
|
||||
if (! ConsistencyCheck(wxT("Sequence::Copy()")))
|
||||
//THROW_INCONSISTENCY_EXCEPTION
|
||||
;
|
||||
dest->ConsistencyCheck(wxT("Sequence::Copy()"));
|
||||
|
||||
return dest;
|
||||
}
|
||||
@ -505,7 +505,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
AppendBlock(*mDirManager, mBlock, mNumSamples, srcBlock[i]);
|
||||
// Increase ref count or duplicate file
|
||||
|
||||
return ConsistencyCheck(wxT("Paste branch one"));
|
||||
ConsistencyCheck(wxT("Paste branch one"));
|
||||
return true;
|
||||
}
|
||||
|
||||
const int b = (s == mNumSamples) ? mBlock.size() - 1 : FindBlock(s);
|
||||
@ -547,7 +548,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
|
||||
mNumSamples += addedLen;
|
||||
|
||||
return ConsistencyCheck(wxT("Paste branch two"));
|
||||
ConsistencyCheck(wxT("Paste branch two"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Case three: if we are inserting four or fewer blocks,
|
||||
@ -639,7 +641,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
|
||||
mNumSamples += addedLen;
|
||||
|
||||
return ConsistencyCheck(wxT("Paste branch three"));
|
||||
ConsistencyCheck(wxT("Paste branch three"));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::SetSilence(sampleCount s0, sampleCount len)
|
||||
@ -693,7 +696,8 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len)
|
||||
bool bResult = Paste(s0, &sTrack);
|
||||
wxASSERT(bResult);
|
||||
|
||||
return bResult && ConsistencyCheck(wxT("InsertSilence"));
|
||||
ConsistencyCheck(wxT("InsertSilence"));
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Sequence::AppendAlias(const wxString &fullPath,
|
||||
@ -1253,7 +1257,8 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format,
|
||||
b++;
|
||||
}
|
||||
|
||||
return ConsistencyCheck(wxT("Set"));
|
||||
ConsistencyCheck(wxT("Set"));
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1683,7 +1688,8 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
|
||||
mNumSamples -= len;
|
||||
|
||||
return ConsistencyCheck(wxT("Delete - branch one"));
|
||||
ConsistencyCheck(wxT("Delete - branch one"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create a NEW array of blocks
|
||||
@ -1790,44 +1796,120 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
// Update total number of samples and do a consistency check.
|
||||
mNumSamples -= len;
|
||||
|
||||
return ConsistencyCheck(wxT("Delete - branch two"));
|
||||
ConsistencyCheck(wxT("Delete - branch two"));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::ConsistencyCheck(const wxChar *whereStr) const
|
||||
void Sequence::ConsistencyCheck(const wxChar *whereStr, bool mayThrow) const
|
||||
{
|
||||
unsigned int i;
|
||||
sampleCount pos = 0;
|
||||
unsigned int numBlocks = mBlock.size();
|
||||
bool bError = false;
|
||||
ConsistencyCheck(mBlock, 0, mNumSamples, whereStr, mayThrow);
|
||||
}
|
||||
|
||||
for (i = 0; !bError && i < numBlocks; i++) {
|
||||
void Sequence::ConsistencyCheck
|
||||
(const BlockArray &mBlock, size_t from,
|
||||
sampleCount mNumSamples, const wxChar *whereStr,
|
||||
bool mayThrow)
|
||||
{
|
||||
bool bError = false;
|
||||
// Construction of the exception at the appropriate line of the function
|
||||
// gives a little more discrimination
|
||||
InconsistencyException ex;
|
||||
|
||||
unsigned int i;
|
||||
sampleCount pos = mBlock[from].start;
|
||||
if ( from == 0 && pos != 0 )
|
||||
ex = CONSTRUCT_INCONSISTENCY_EXCEPTION, bError = true;
|
||||
|
||||
unsigned int numBlocks = mBlock.size();
|
||||
|
||||
for (i = from; !bError && i < numBlocks; i++) {
|
||||
const SeqBlock &seqBlock = mBlock[i];
|
||||
if (pos != seqBlock.start)
|
||||
bError = true;
|
||||
ex = CONSTRUCT_INCONSISTENCY_EXCEPTION, bError = true;
|
||||
|
||||
if (seqBlock.f)
|
||||
if ( seqBlock.f )
|
||||
pos += seqBlock.f->GetLength();
|
||||
else
|
||||
bError = true;
|
||||
ex = CONSTRUCT_INCONSISTENCY_EXCEPTION, bError = true;
|
||||
}
|
||||
if (pos != mNumSamples)
|
||||
bError = true;
|
||||
if ( !bError && pos != mNumSamples )
|
||||
ex = CONSTRUCT_INCONSISTENCY_EXCEPTION, bError = true;
|
||||
|
||||
if (bError)
|
||||
if ( bError )
|
||||
{
|
||||
wxLogError(wxT("*** Consistency check failed after %s. ***"), whereStr);
|
||||
wxString str;
|
||||
DebugPrintf(&str);
|
||||
DebugPrintf(mBlock, mNumSamples, &str);
|
||||
wxLogError(wxT("%s"), str.c_str());
|
||||
wxLogError(wxT("*** Please report this error to feedback@audacityteam.org. ***\n\n")
|
||||
wxT("Recommended course of action:\n")
|
||||
wxT("Undo the failed operation(s), then export or save your work and quit."));
|
||||
}
|
||||
|
||||
return !bError;
|
||||
if (mayThrow)
|
||||
//throw ex
|
||||
;
|
||||
else
|
||||
wxASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::DebugPrintf(wxString *dest) const
|
||||
void Sequence::CommitChangesIfConsistent
|
||||
(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
|
||||
{
|
||||
ConsistencyCheck( newBlock, 0, numSamples, whereStr ); // may throw
|
||||
|
||||
// now commit
|
||||
// use NOFAIL-GUARANTEE
|
||||
|
||||
mBlock.swap(newBlock);
|
||||
mNumSamples = numSamples;
|
||||
}
|
||||
|
||||
void Sequence::AppendBlocksIfConsistent
|
||||
(BlockArray &additionalBlocks, bool replaceLast,
|
||||
sampleCount numSamples, const wxChar *whereStr)
|
||||
{
|
||||
// Any additional blocks are meant to be appended,
|
||||
// replacing the final block if there was one.
|
||||
|
||||
if (additionalBlocks.empty())
|
||||
return;
|
||||
|
||||
bool tmpValid = false;
|
||||
SeqBlock tmp;
|
||||
|
||||
if ( replaceLast && ! mBlock.empty() ) {
|
||||
tmp = mBlock.back(), tmpValid = true;
|
||||
mBlock.pop_back();
|
||||
}
|
||||
|
||||
auto prevSize = mBlock.size();
|
||||
|
||||
bool consistent = false;
|
||||
auto cleanup = finally( [&] {
|
||||
if ( !consistent ) {
|
||||
mBlock.resize( prevSize );
|
||||
if ( tmpValid )
|
||||
mBlock.push_back( tmp );
|
||||
}
|
||||
} );
|
||||
|
||||
std::copy( additionalBlocks.begin(), additionalBlocks.end(),
|
||||
std::back_inserter( mBlock ) );
|
||||
|
||||
// Check consistency only of the blocks that were added,
|
||||
// avoiding quadratic time for repeated checking of repeating appends
|
||||
ConsistencyCheck( mBlock, prevSize, numSamples, whereStr ); // may throw
|
||||
|
||||
// now commit
|
||||
// use NOFAIL-GUARANTEE
|
||||
|
||||
mNumSamples = numSamples;
|
||||
consistent = true;
|
||||
}
|
||||
|
||||
void Sequence::DebugPrintf
|
||||
(const BlockArray &mBlock, sampleCount mNumSamples, wxString *dest)
|
||||
{
|
||||
unsigned int i;
|
||||
decltype(mNumSamples) pos = 0;
|
||||
|
@ -263,19 +263,38 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
bool Get(int b, samplePtr buffer, sampleFormat format,
|
||||
sampleCount start, size_t len, bool mayThrow) const;
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
//
|
||||
// Public methods intended for debugging only
|
||||
// Public methods
|
||||
//
|
||||
|
||||
// This function makes sure that the track isn't messed up
|
||||
// This function throws if the track is messed up
|
||||
// because of inconsistent block starts & lengths
|
||||
bool ConsistencyCheck(const wxChar *whereStr) const;
|
||||
void ConsistencyCheck (const wxChar *whereStr, bool mayThrow = true) const;
|
||||
|
||||
// This function prints information to stdout about the blocks in the
|
||||
// tracks and indicates if there are inconsistencies.
|
||||
void DebugPrintf(wxString *dest) const;
|
||||
static void DebugPrintf
|
||||
(const BlockArray &block, sampleCount numSamples, wxString *dest);
|
||||
|
||||
private:
|
||||
static void ConsistencyCheck
|
||||
(const BlockArray &block, size_t from,
|
||||
sampleCount numSamples, const wxChar *whereStr,
|
||||
bool mayThrow = true);
|
||||
|
||||
// The next two are used in methods that give a strong guarantee.
|
||||
// They either throw because final consistency check fails, or swap the
|
||||
// changed contents into place.
|
||||
|
||||
void CommitChangesIfConsistent
|
||||
(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr);
|
||||
|
||||
void AppendBlocksIfConsistent
|
||||
(BlockArray &additionalBlocks, bool replaceLast,
|
||||
sampleCount numSamples, const wxChar *whereStr);
|
||||
|
||||
};
|
||||
|
||||
#endif // __AUDACITY_SEQUENCE__
|
||||
|
Loading…
x
Reference in New Issue
Block a user