Detect failure to reconnect to temp project when first saving it

This commit is contained in:
Paul Licameli 2020-12-06 22:14:54 -05:00
parent 41eb66fccf
commit aa0b33dc8f
5 changed files with 62 additions and 15 deletions

View File

@ -44,6 +44,7 @@ Paul Licameli split from AudacityProject.cpp
wxDEFINE_EVENT(EVT_PROJECT_TITLE_CHANGE, wxCommandEvent);
wxDEFINE_EVENT( EVT_CHECKPOINT_FAILURE, wxCommandEvent);
wxDEFINE_EVENT( EVT_RECONNECTION_FAILURE, wxCommandEvent);
static const int ProjectFileID = ('A' << 24 | 'U' << 16 | 'D' << 8 | 'Y');
static const int ProjectFileVersion = 1;
@ -263,6 +264,12 @@ ProjectFileIO::~ProjectFileIO()
{
}
bool ProjectFileIO::HasConnection() const
{
auto &connectionPtr = ConnectionPtr::Get( mProject );
return connectionPtr.mpConnection != nullptr;
}
DBConnection &ProjectFileIO::GetConnection()
{
auto &curConn = CurrConn();
@ -2045,20 +2052,38 @@ bool ProjectFileIO::SaveProject(
FilePath savedName = mFileName;
if (CloseConnection())
{
if (MoveProject(savedName, fileName))
bool reopened = false;
bool moved = false;
if (true == (moved = MoveProject(savedName, fileName)))
{
if (!OpenConnection(fileName))
{
if (OpenConnection(fileName))
reopened = true;
else {
MoveProject(fileName, savedName);
OpenConnection(savedName);
reopened = OpenConnection(savedName);
}
}
else {
// Rename can fail -- if it's to a different device, requiring
// real copy of contents, which might exhaust space
OpenConnection(savedName);
return false;
reopened = OpenConnection(savedName);
}
if (!reopened)
wxTheApp->CallAfter([this]{
ShowErrorDialog(nullptr,
XO("Warning"),
XO(
"The project's database failed to reopen, "
"possibly because of limited space on the storage device."),
"Error:_Disk_full_or_not_writable"
);
wxCommandEvent evt{ EVT_RECONNECTION_FAILURE };
mProject.ProcessEvent(evt);
});
if (!moved)
return false;
}
}

View File

@ -45,6 +45,11 @@ using BlockIDs = std::unordered_set<SampleBlockID>;
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_CHECKPOINT_FAILURE, wxCommandEvent );
// An event processed by the project in the main thread after failure to
// reconnect to the database, after temporary close and attempted file movement
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_RECONNECTION_FAILURE, wxCommandEvent );
///\brief Object associated with a project that manages reading and writing
/// of Audacity project file formats, and autosave
class ProjectFileIO final
@ -179,6 +184,10 @@ public:
// 0 for success or non-zero to stop the query
using ExecCB = std::function<int(int cols, char **vals, char **names)>;
//! Return true if a connetion is now open
bool HasConnection() const;
//! Return a reference to a connection, creating it as needed on demand; throw on failure
DBConnection &GetConnection();
private:

View File

@ -302,15 +302,17 @@ bool ProjectFileManager::DoSave(const FilePath & fileName, const bool fromSaveAs
bool success = projectFileIO.SaveProject(fileName, mLastSavedTracks.get());
if (!success)
{
ShowErrorDialog(
&window,
XO("Error Saving Project"),
XO("Could not save project. Perhaps %s \n"
"is not writable or the disk is full.\n"
"For tips on freeing up space, click the help button.")
.Format(fileName),
"Error:_Disk_full_or_not_writable"
);
// Show this error only if we didn't fail reconnection in SaveProject
if (projectFileIO.HasConnection())
ShowErrorDialog(
&window,
XO("Error Saving Project"),
XO("Could not save project. Perhaps %s \n"
"is not writable or the disk is full.\n"
"For tips on freeing up space, click the help button.")
.Format(fileName),
"Error:_Disk_full_or_not_writable"
);
return false;
}

View File

@ -82,6 +82,8 @@ ProjectManager::ProjectManager( AudacityProject &project )
window.Bind( wxEVT_CLOSE_WINDOW, &ProjectManager::OnCloseWindow, this );
mProject.Bind(EVT_PROJECT_STATUS_UPDATE,
&ProjectManager::OnStatusChange, this);
project.Bind( EVT_RECONNECTION_FAILURE,
&ProjectManager::OnReconnectionFailure, this );
}
ProjectManager::~ProjectManager() = default;
@ -589,6 +591,14 @@ AudacityProject *ProjectManager::New()
return p;
}
void ProjectManager::OnReconnectionFailure(wxCommandEvent & event)
{
event.Skip();
wxTheApp->CallAfter([this]{
ProjectWindow::Get(mProject).Close(true);
});
}
void ProjectManager::OnCloseWindow(wxCloseEvent & event)
{
auto &project = mProject;

View File

@ -65,6 +65,7 @@ public:
void SetSkipSavePrompt(bool bSkip) { sbSkipPromptingForSave = bSkip; };
private:
void OnReconnectionFailure(wxCommandEvent & event);
void OnCloseWindow(wxCloseEvent & event);
void OnTimer(wxTimerEvent & event);
void OnOpenAudioFile(wxCommandEvent & event);