-
-
Notifications
You must be signed in to change notification settings - Fork 342
Description
I need to write to the same database from several threads. Sometimes, the threads encounter SQLITE_LOCKED and a std::system_error is thrown, but this is a recoverable issue and I would like to simply retry the step, perhaps with a backoff.
As per the sqlite3_unlock_notify page, perhaps it is possible to work the retry logic into this.
Currently, most of the code involving sqlite3_step() looks like this:
if(sqlite3_step(stmt) == SQLITE_DONE) {
// done..
} else {
throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db));
}
Perhaps it can be changed into something like this.
We set a bool flag in storage_base to indicate if we should block on SQLITE_LOCKED.
int rc = 0;
if (blocking) {
while ((rc = sqlite3_step(stmt)) == SQLITE_LOCKED) {
rc = wait_for_unlock_notify(sqlite3_db_handle(stmt));
}
} else {
rc = sqlite3_step(stmt);
}
if (rc != SQLITE_DONE) {
throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db));
}
Where wait_for_unlock_notify() is similar to the one described in the page above.
However, not all sqlite3 compilations have the sqlite3_unlock_notify() function. In that case, we can somehow fall back to a regular blocking loop:
#include <chrono>
using namespace std::chrono_literals;
int rc = 0;
if (blocking) {
while ((rc = sqlite3_step(stmt)) == SQLITE_LOCKED) {
std::this_thread::sleep_for(1s);
}
} else {
rc = sqlite3_step(stmt);
}
if (rc != SQLITE_DONE) {
throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category()), sqlite3_errmsg(db));
}
Of course, sleep_for can be hidden inside wait_for_unlock_notify (with a better name I guess) and the existence of sqlite3_unlock_notify is detected with SFINAE.
What do you think?
As for the implementation of unlock_notify object, it can be achieved through std::condition_variable and std::mutex to keep it cross-platform, instead of relying on pthread.