From 4ac31cd8b69b7a1e2d714bd61ae5b2fcbaeaacf9 Mon Sep 17 00:00:00 2001 From: William Johnson Date: Fri, 6 Dec 2024 14:16:45 -0800 Subject: [PATCH] Improve saving state in DB a bit. Note: this is a bit of a band-aid - the saving of states to DB needs to be cleaned up and simplified. There is a `feature/UpdateDbSchema` branch that starts to do some of this, but it is by no means complete. --- src/InterSpec.cpp | 70 ++++++++++++++++++++++++++++------------ src/InterSpecUser.cpp | 4 ++- src/SpectraFileModel.cpp | 5 +-- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/InterSpec.cpp b/src/InterSpec.cpp index 4921efdb..a4615970 100644 --- a/src/InterSpec.cpp +++ b/src/InterSpec.cpp @@ -3310,12 +3310,13 @@ void InterSpec::saveStateToDb( Wt::Dbo::ptr entry ) std::shared_ptr second = measurment( SpecUtils::SpectrumType::SecondForeground ); std::shared_ptr background = measurment( SpecUtils::SpectrumType::Background ); + const bool updateInDb = false; //We will update the file, or make a copy ourselves Dbo::ptr dbforeground, dbsecond, dbbackground; - dbforeground = measurementFromDb( SpecUtils::SpectrumType::Foreground, true ); + dbforeground = measurementFromDb( SpecUtils::SpectrumType::Foreground, updateInDb ); if( foreground != second ) - dbsecond = measurementFromDb( SpecUtils::SpectrumType::SecondForeground, true ); + dbsecond = measurementFromDb( SpecUtils::SpectrumType::SecondForeground, updateInDb ); if( (background != foreground) && (background != second) ) - dbbackground = measurementFromDb( SpecUtils::SpectrumType::Background, true ); + dbbackground = measurementFromDb( SpecUtils::SpectrumType::Background, updateInDb ); //JIC, make sure indices have all been assigned to everything. m_sql->session()->flush(); @@ -3327,7 +3328,10 @@ void InterSpec::saveStateToDb( Wt::Dbo::ptr entry ) // We dont need to make a copy of the file if it was not part of a save state, but now its // becoming part of one if( deepCopy && (dbfile->isPartOfSaveState || dbfile->snapshotParent) ) + { dbfile = UserFileInDb::makeDeepCopyOfFileInDatabase( dbfile, *m_sql, true ); + m_sql->session()->flush(); + } dbfile.modify()->isPartOfSaveState = true; @@ -3357,15 +3361,37 @@ void InterSpec::saveStateToDb( Wt::Dbo::ptr entry ) };//create_copy_or_update_in_db lambda create_copy_or_update_in_db( dbforeground, foreground ); - create_copy_or_update_in_db( dbsecond, second ); - create_copy_or_update_in_db( dbbackground, background ); - if( !dbforeground && foreground ) throw runtime_error( "Error saving foreground to the database" ); //not displayed to user, so not internationalized - if( !dbsecond && second ) - throw runtime_error( "Error saving second foreground to the database" ); - if( !dbbackground && background ) - throw runtime_error( "Error saving background to the database" ); + + if( second ) + { + if( second == foreground ) + { + dbsecond = dbforeground; + }else + { + create_copy_or_update_in_db( dbsecond, second ); + if( !dbsecond ) + throw runtime_error( "Error saving second foreground to the database" ); + } + }//if( second ) + + if( background ) + { + if( background == foreground ) + { + dbbackground = dbforeground; + }else if( background == second ) + { + dbbackground = dbsecond; + }else + { + create_copy_or_update_in_db( dbbackground, background ); + if( !dbbackground ) + throw runtime_error( "Error saving background to the database" ); + } + }//if( background ) //We need to make sure dbforeground, dbbackground, dbsecond will have been // written to the database, so there id()'s will be not -1. @@ -6078,33 +6104,38 @@ void InterSpec::saveStateForEndOfSession() // Remove existing end-of-session state - DataBaseUtils::DbTransaction transaction( *m_sql ); try { + DataBaseUtils::DbTransaction transaction( *m_sql ); Dbo::collection> prevEosStates = m_sql->session()->find() .where( "InterSpecUser_id = ? AND StateType = ?" ) .bind( m_user.id() ) .bind( int(UserState::kEndOfSessionTemp) ); - //assert( prevEosStates.size() <= 1 ); - for( auto iter = prevEosStates.begin(); iter != prevEosStates.end(); ++iter ) - UserState::removeFromDatabase( *iter, *m_sql ); + try + { + for( auto iter = prevEosStates.begin(); iter != prevEosStates.end(); ++iter ) + UserState::removeFromDatabase( *iter, *m_sql ); + }catch( std::exception &e ) + { + Wt::log("error") << "InterSpec::saveStateForEndOfSession() error removing last state: " << e.what(); + } + + transaction.commit(); }catch( std::exception &e ) { - Wt::log("error") << "InterSpec::saveStateForEndOfSession() error removing last state: " << e.what(); - transaction.rollback(); + Wt::log("error") << "InterSpec::saveStateForEndOfSession() error getting last state: " << e.what(); return; } // I we dont want to save states, or there is no foreground - nothing more to do here if( !saveState || !m_dataMeasurement ) - { - transaction.commit(); return; - } try { + DataBaseUtils::DbTransaction transaction( *m_sql ); + // Check if we are connected with a database state const long long int current_state_index = currentAppStateDbId(); Wt::Dbo::ptr parentState; @@ -6132,7 +6163,6 @@ void InterSpec::saveStateForEndOfSession() }catch( std::exception &e ) { Wt::log("error") << "InterSpec::saveStateForEndOfSession() error: " << e.what(); - transaction.rollback(); } }//void saveStateForEndOfSession() #endif //#if( USE_DB_TO_STORE_SPECTRA ) diff --git a/src/InterSpecUser.cpp b/src/InterSpecUser.cpp index 2d17c69b..02717624 100644 --- a/src/InterSpecUser.cpp +++ b/src/InterSpecUser.cpp @@ -539,7 +539,7 @@ Dbo::ptr UserFileInDb::makeDeepCopyOfFileInDatabase( // The passed in `UserFileInDb` may not actually be in the database, so we have to check // for this. - if( orig.id() >= 0 ) + if( !orig.isTransient() ) { for( Dbo::collection< Dbo::ptr >::const_iterator iter = orig->filedata.begin(); iter != orig->filedata.end(); ++iter ) @@ -549,6 +549,7 @@ Dbo::ptr UserFileInDb::makeDeepCopyOfFileInDatabase( session->add( newdata ); } + /* for( Dbo::collection< Dbo::ptr >::const_iterator iter = orig->modelsUsedWith.begin(); iter != orig->modelsUsedWith.end(); @@ -559,6 +560,7 @@ Dbo::ptr UserFileInDb::makeDeepCopyOfFileInDatabase( Dbo::ptr modelptr = session->add( newmodel ); modelptr.modify()->filesUsedWith.insert( answer ); }//for( loop over ShieldingSourceModel ) + */ }//if( orig.id() >= 0 ) transaction.commit(); diff --git a/src/SpectraFileModel.cpp b/src/SpectraFileModel.cpp index a4c33f85..d834f05e 100644 --- a/src/SpectraFileModel.cpp +++ b/src/SpectraFileModel.cpp @@ -708,7 +708,7 @@ void SpectraFileHeader::saveToDatabase( std::shared_ptr input ) } - if( !fileDbEntry ) + if( !fileDbEntry || fileDbEntry.isTransient() ) { UserFileInDb *info = new UserFileInDb(); Dbo::ptr info_dbo_ptr( info ); @@ -741,10 +741,11 @@ void SpectraFileHeader::saveToDatabase( std::shared_ptr input ) { DataBaseUtils::DbTransaction transaction( *m_sql ); fileDbEntry = m_sql->session()->find().where("id = ?").bind(fileDbEntry.id()).resultValue(); + //fileDbEntry.flush(); transaction.commit(); if( !fileDbEntry ) - runtime_error("no entry"); + throw runtime_error("no entry"); }catch( Wt::Dbo::Exception &e ) { throw runtime_error( "SpectraFileHeader::saveToDatabase(), database error: " + string(e.what()) );