Skip to content

Commit

Permalink
Update selfRestarter with final version of appSatate.
Browse files Browse the repository at this point in the history
  • Loading branch information
herve-er committed Apr 30, 2024
1 parent f92805a commit bf8b7cd
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 24 deletions.
9 changes: 6 additions & 3 deletions src/libcommon/utility/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/libparms/db/parmsdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
21 changes: 17 additions & 4 deletions src/libparms/db/parmsdbappstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>(AppStateKey::Test)));
ASSERT(queryBindValue(SELECT_APP_STATE_REQUEST_ID, 1, static_cast<int>(key)));
if (!queryNext(SELECT_APP_STATE_REQUEST_ID, found)) {
LOG_WARN(_logger, "Error getting query result: " << SELECT_APP_STATE_REQUEST_ID);
return false;
Expand All @@ -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<int>(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<int>(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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<int>(key)));
ASSERT(queryBindValue(UPDATE_APP_STATE_REQUEST_ID, 2, value));
Expand Down
3 changes: 2 additions & 1 deletion src/libparms/db/parmsdbappstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
#define APP_STATE_KEY_DEFAULT_LastServerSelfRestart "0"
#define APP_STATE_KEY_DEFAULT_LastClientSelfRestart "0"
50 changes: 42 additions & 8 deletions src/server/appserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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::seconds>(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
Expand Down Expand Up @@ -2056,16 +2066,28 @@ 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 {
CommServer::instance()->setHasQuittedProperly(false);
long timestamp =
std::chrono::time_point_cast<std::chrono::seconds>(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");
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/server/appserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class AppServer : public SharedTools::QtSingleApplication {
QTimer _restartSyncsTimer;
std::unordered_map<int, SyncCache> _syncCacheMap;
std::unordered_map<int, std::unordered_set<NodeId>> _undecidedListCacheMap;
QString _crashMessage = tr("kDrive application will close due to a fatal error.");


#if defined(WITH_CRASHREPORTER)
Expand Down
23 changes: 16 additions & 7 deletions test/libparms/db/testparmsdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<AppStateKey>(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<AppStateKey>(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__
Expand Down

0 comments on commit bf8b7cd

Please sign in to comment.