From bf8b7cd50445875474c8a5138729f630ed04801d Mon Sep 17 00:00:00 2001 From: Herve_eruam Date: Tue, 30 Apr 2024 17:35:40 +0200 Subject: [PATCH] Update selfRestarter with final version of appSatate. --- src/libcommon/utility/types.h | 9 ++++-- src/libparms/db/parmsdb.h | 2 +- src/libparms/db/parmsdbappstate.cpp | 21 +++++++++--- src/libparms/db/parmsdbappstate.h | 3 +- src/server/appserver.cpp | 50 ++++++++++++++++++++++++----- src/server/appserver.h | 1 + test/libparms/db/testparmsdb.cpp | 23 +++++++++---- 7 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/libcommon/utility/types.h b/src/libcommon/utility/types.h index d70a96329..bfa3b589d 100644 --- a/src/libcommon/utility/types.h +++ b/src/libcommon/utility/types.h @@ -360,8 +360,11 @@ struct ItemType { }; enum class AppStateKey { - // Adding a new key here requires to add it in insertDefaultAppState in parmsdbappstate.cpp and ideally testparmsdb.cpp - Unknown, // Used for initialization, will throw error if used - Test // To be removed after the implementation of the first key + // Adding a new key here requires to add it in insertDefaultAppState in parmsdbappstate.cpp + LastServerSelfRestart, + LastClientSelfRestart, + + Unknown, //!\ keep in last position (For tests) /!\\ Used for initialization, will throw error if used. }; + } // namespace KDC diff --git a/src/libparms/db/parmsdb.h b/src/libparms/db/parmsdb.h index a04e2c2ab..26756b234 100644 --- a/src/libparms/db/parmsdb.h +++ b/src/libparms/db/parmsdb.h @@ -132,8 +132,8 @@ class PARMS_EXPORT ParmsDb : public Db { ParmsDb(const std::filesystem::path &dbPath, const std::string &version, bool autoDelete, bool test); bool insertDefaultParameters(); - bool insertDefaultSelfRestarterData(); bool insertDefaultAppState(); + bool insertDefaultAppState(AppStateKey key, const std::string &value); bool updateExclusionTemplates(); bool createAppState(); diff --git a/src/libparms/db/parmsdbappstate.cpp b/src/libparms/db/parmsdbappstate.cpp index 41c06e80c..2b8094538 100644 --- a/src/libparms/db/parmsdbappstate.cpp +++ b/src/libparms/db/parmsdbappstate.cpp @@ -65,13 +65,25 @@ bool ParmsDb::prepareAppState() { } bool ParmsDb::insertDefaultAppState() { + if (!insertDefaultAppState(AppStateKey::LastServerSelfRestart, APP_STATE_KEY_DEFAULT_LastServerSelfRestart)) { + return false; + } + + if (!insertDefaultAppState(AppStateKey::LastClientSelfRestart, APP_STATE_KEY_DEFAULT_LastClientSelfRestart)) { + return false; + } + + return true; +} + +bool ParmsDb::insertDefaultAppState(AppStateKey key, const std::string &value) { const std::scoped_lock lock(_mutex); int errId = 0; std::string error; bool found = false; ASSERT(queryResetAndClearBindings(SELECT_APP_STATE_REQUEST_ID)); - ASSERT(queryBindValue(SELECT_APP_STATE_REQUEST_ID, 1, static_cast(AppStateKey::Test))); + ASSERT(queryBindValue(SELECT_APP_STATE_REQUEST_ID, 1, static_cast(key))); if (!queryNext(SELECT_APP_STATE_REQUEST_ID, found)) { LOG_WARN(_logger, "Error getting query result: " << SELECT_APP_STATE_REQUEST_ID); return false; @@ -80,8 +92,8 @@ bool ParmsDb::insertDefaultAppState() { ASSERT(queryResetAndClearBindings(SELECT_APP_STATE_REQUEST_ID)); if (!found) { ASSERT(queryResetAndClearBindings(INSERT_APP_STATE_REQUEST_ID)); - ASSERT(queryBindValue(INSERT_APP_STATE_REQUEST_ID, 1, static_cast(AppStateKey::Test))); - ASSERT(queryBindValue(INSERT_APP_STATE_REQUEST_ID, 2, APP_STATE_KEY_DEFAULT_Test)); + ASSERT(queryBindValue(INSERT_APP_STATE_REQUEST_ID, 1, static_cast(key))); + ASSERT(queryBindValue(INSERT_APP_STATE_REQUEST_ID, 2, value)); if (!queryExec(INSERT_APP_STATE_REQUEST_ID, errId, error)) { LOG_WARN(_logger, "Error running query: " << INSERT_APP_STATE_REQUEST_ID); return false; @@ -90,6 +102,7 @@ bool ParmsDb::insertDefaultAppState() { return true; } + bool ParmsDb::selectAppState(AppStateKey key, std::string &value, bool &found) { const std::scoped_lock lock(_mutex); found = false; @@ -123,7 +136,7 @@ bool ParmsDb::updateAppState(AppStateKey key, const std::string &value, bool &fo } const std::scoped_lock lock(_mutex); - if (found) { + if (found) { ASSERT(queryResetAndClearBindings(UPDATE_APP_STATE_REQUEST_ID)); ASSERT(queryBindValue(UPDATE_APP_STATE_REQUEST_ID, 1, static_cast(key))); ASSERT(queryBindValue(UPDATE_APP_STATE_REQUEST_ID, 2, value)); diff --git a/src/libparms/db/parmsdbappstate.h b/src/libparms/db/parmsdbappstate.h index ec891f8c1..311966941 100644 --- a/src/libparms/db/parmsdbappstate.h +++ b/src/libparms/db/parmsdbappstate.h @@ -35,4 +35,5 @@ #define UPDATE_APP_STATE_REQUEST_ID "update_value_with_key" #define UPDATE_APP_STATE_REQUEST "UPDATE app_state SET value=?2 WHERE key=?1;" -#define APP_STATE_KEY_DEFAULT_Test "Test" \ No newline at end of file +#define APP_STATE_KEY_DEFAULT_LastServerSelfRestart "0" +#define APP_STATE_KEY_DEFAULT_LastClientSelfRestart "0" diff --git a/src/server/appserver.cpp b/src/server/appserver.cpp index 7fc68cf4b..207d6e641 100644 --- a/src/server/appserver.cpp +++ b/src/server/appserver.cpp @@ -321,18 +321,28 @@ AppServer::AppServer(int &argc, char **argv) // Check last crash to avoid crash loop if (_crashRecovered) { + bool found = false; LOG_WARN(_logger, "Server auto restart after a crash."); if (serverCrashedRecently()) { LOG_FATAL(_logger, "Server crashed twice in a short time, exiting"); - QMessageBox::warning(0, QString(APPLICATION_NAME), tr("kDrive application crashed!"), QMessageBox::Ok); - KDC::ParmsDb::instance()->setValueForKey("lastServerSelfRestart", "0"); + QMessageBox::warning(0, QString(APPLICATION_NAME), _crashMessage, QMessageBox::Ok); + if (!KDC::ParmsDb::instance()->updateAppState(AppStateKey::LastServerSelfRestart, "0", found) || !found) { + LOG_WARN(_logger, "Error in ParmsDb::updateAppState"); + addError(Error(ERRID, ExitCodeDbError, ExitCauseDbEntryNotFound)); + throw std::runtime_error("Failed to update last server self restart."); + } QTimer::singleShot(0, this, quit); return; } long timestamp = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); std::string timestampStr = std::to_string(timestamp); - KDC::ParmsDb::instance()->setValueForKey("lastServerSelfRestart", timestampStr); + KDC::ParmsDb::instance()->updateAppState(AppStateKey::LastServerSelfRestart, timestampStr, found); + if (!KDC::ParmsDb::instance()->updateAppState(AppStateKey::LastServerSelfRestart, timestampStr, found) || !found) { + LOG_WARN(_logger, "Error in ParmsDb::updateAppState"); + addError(Error(ERRID, ExitCodeDbError, ExitCauseDbEntryNotFound)); + throw std::runtime_error("Failed to update last server self restart."); + } } // Start client @@ -2056,8 +2066,12 @@ void AppServer::onRestartClientReceived() { // Check last start time if (clientCrashedRecently()) { LOG_FATAL(_logger, "Client crashed twice in a short time, exiting"); - KDC::ParmsDb::instance()->setValueForKey("lastClientSelfRestart", "0"); - QMessageBox::warning(0, QString(APPLICATION_NAME), tr("kDrive application crashed"), QMessageBox::Ok); + bool found = false; + if (!KDC::ParmsDb::instance()->updateAppState(AppStateKey::LastClientSelfRestart, "0", found) || !found) { + addError(Error(ERRID, ExitCodeDbError, ExitCauseDbEntryNotFound)); + LOG_WARN(_logger, "Error in ParmsDb::selectAppState"); + } + QMessageBox::warning(0, QString(APPLICATION_NAME), _crashMessage, QMessageBox::Ok); QTimer::singleShot(0, this, &AppServer::quit); return; } else { @@ -2065,7 +2079,15 @@ void AppServer::onRestartClientReceived() { long timestamp = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); std::string timestampStr = std::to_string(timestamp); - KDC::ParmsDb::instance()->setValueForKey("lastClientSelfRestart", timestampStr); + bool found = false; + if (!KDC::ParmsDb::instance()->updateAppState(AppStateKey::LastClientSelfRestart, timestampStr, found) || !found) { + addError(Error(ERRID, ExitCodeDbError, ExitCauseDbEntryNotFound)); + LOG_WARN(_logger, "Error in ParmsDb::selectAppState"); + QMessageBox::warning(0, QString(APPLICATION_NAME), _crashMessage, QMessageBox::Ok); + QTimer::singleShot(0, this, &AppServer::quit); + return; + } + if (!startClient()) { LOG_WARN(_logger, "Error in startClient"); } @@ -2857,7 +2879,13 @@ bool AppServer::serverCrashedRecently(int seconds) { int64_t lastServerCrash = 0; std::string lastServerCrashStr; - KDC::ParmsDb::instance()->selectValueForKey("lastServerSelfRestart", lastServerCrashStr); + bool found = false; + + if (!KDC::ParmsDb::instance()->selectAppState(AppStateKey::LastServerSelfRestart, lastServerCrashStr, found) || !found) { + addError(Error(ERRID, ExitCodeDbError, ExitCauseDbEntryNotFound)); + LOG_WARN(_logger, "Error in ParmsDb::selectAppState"); + return false; + } if (lastServerCrashStr.empty()) { return false; @@ -2885,7 +2913,13 @@ bool AppServer::clientCrashedRecently(int seconds) { int64_t lastClientCrash = 0; std::string lastClientCrashStr; - KDC::ParmsDb::instance()->selectValueForKey("lastClientSelfRestart", lastClientCrashStr); + bool found = false; + + if (!KDC::ParmsDb::instance()->selectAppState(AppStateKey ::LastClientSelfRestart, lastClientCrashStr, found) || !found) { + addError(Error(ERRID, ExitCodeDbError, ExitCauseDbEntryNotFound)); + LOG_WARN(_logger, "Error in ParmsDb::selectAppState"); + return false; + } if (lastClientCrashStr.empty()) { return false; diff --git a/src/server/appserver.h b/src/server/appserver.h index d2f0ff1e9..af64bd9ed 100644 --- a/src/server/appserver.h +++ b/src/server/appserver.h @@ -131,6 +131,7 @@ class AppServer : public SharedTools::QtSingleApplication { QTimer _restartSyncsTimer; std::unordered_map _syncCacheMap; std::unordered_map> _undecidedListCacheMap; + QString _crashMessage = tr("kDrive application will close due to a fatal error."); #if defined(WITH_CRASHREPORTER) diff --git a/test/libparms/db/testparmsdb.cpp b/test/libparms/db/testparmsdb.cpp index c5f076ee3..f27e515ab 100644 --- a/test/libparms/db/testparmsdb.cpp +++ b/test/libparms/db/testparmsdb.cpp @@ -301,15 +301,24 @@ void TestParmsDb::testExclusionTemplate() { void TestParmsDb::testAppState(void) { bool found = true; std::string value; - CPPUNIT_ASSERT(ParmsDb::instance()->selectAppState(AppStateKey::Test, value, found) && found); - CPPUNIT_ASSERT_EQUAL(std::string("Test"), value); - CPPUNIT_ASSERT(ParmsDb::instance()->updateAppState(AppStateKey::Test, "value 1", found)); - CPPUNIT_ASSERT(ParmsDb::instance()->selectAppState(AppStateKey::Test, value, found) && found); - CPPUNIT_ASSERT_EQUAL(std::string("value 1"), value); - - CPPUNIT_ASSERT(ParmsDb::instance()->updateAppState(static_cast(9548215525211611), "value 2", found)); + CPPUNIT_ASSERT( + ParmsDb::instance()->updateAppState(AppStateKey::Unknown, "value 2", found)); // Test for unknown key (not in db) CPPUNIT_ASSERT(!found); + + + int i = 0; + do { + AppStateKey key = static_cast(i); // Test for all known keys + if (key == AppStateKey::Unknown) { + break; + } + CPPUNIT_ASSERT(ParmsDb::instance()->selectAppState(key, value, found) && found); + CPPUNIT_ASSERT(ParmsDb::instance()->updateAppState(key, "value 1", found)); + CPPUNIT_ASSERT(ParmsDb::instance()->selectAppState(key, value, found) && found); + CPPUNIT_ASSERT_EQUAL(std::string("value 1"), value); + i++; + } while (true); } #ifdef __APPLE__