Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 36 additions & 27 deletions CommonData/databaseinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

DatabaseInterface * DatabaseInterface::_singleton = nullptr;

thread_local int _transactionWriteDepth = 0,
_transactionReadDepth = 0;


//#define SIR_LOG_A_LOT

const std::string DatabaseInterface::_dbConstructionSql =
Expand Down Expand Up @@ -2050,10 +2054,7 @@ sqlite3 * DatabaseInterface::_db()
if(_dbCreated && _dbCreator == id)
return _dbCreated;

if(!_dbs.count(id))
load();

return _dbs.at(id);
return load();
}

void DatabaseInterface::create()
Expand Down Expand Up @@ -2132,40 +2133,41 @@ void DatabaseInterface::preloadInterfaceForThread()
_db();
}

void DatabaseInterface::load()
sqlite3* DatabaseInterface::load()
{
JASPTIMER_SCOPE(DatabaseInterface::load);
assert(!_dbCreated || std::this_thread::get_id() != _dbCreator);
assert(!_dbCreated || std::this_thread::get_id() != _dbCreator);

_loadMutex.lock();
if(_dbs.count(std::this_thread::get_id()))
{
sqlite3* connection = _dbs.at(std::this_thread::get_id());
_loadMutex.unlock();
return;
return connection;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you returning this?

}


if(!std::filesystem::exists(dbFile()))
throw std::runtime_error("Trying to load '" + dbFile() + "' but it doesn't exist!");
if(!std::filesystem::exists(dbFile()))
throw std::runtime_error("Trying to load '" + dbFile() + "' but it doesn't exist!");

bool loadingWorked = false;
size_t loadingAttempt = 0;
sqlite3 * db = nullptr;

for(bool loadingWorked = false; !loadingWorked; )
{
int ret = sqlite3_open_v2(dbFile().c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX, NULL);
int ret = sqlite3_open_v2(dbFile().c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX, NULL);

if(ret != SQLITE_OK)
{
Log::log() << "Couldnt open sqlite internal db, because of: " << (db ? sqlite3_errmsg(db) : "not even a broken sqlite3 obj was returned..." ) << std::endl;
throw std::runtime_error("JASP cannot run without an internal database and it cannot be created. Contact the JASP team for help.");
}
else
Log::log() << "Opened internal sqlite database for loading at '" << dbFile() << "'. This is for thread " << std::this_thread::get_id() << std::endl;
if(ret != SQLITE_OK)
{
Log::log() << "Couldnt open sqlite internal db, because of: " << (db ? sqlite3_errmsg(db) : "not even a broken sqlite3 obj was returned..." ) << std::endl;
throw std::runtime_error("JASP cannot run without an internal database and it cannot be created. Contact the JASP team for help.");
}
else
Log::log() << "Opened internal sqlite database for loading at '" << dbFile() << "'. This is for thread " << std::this_thread::get_id() << std::endl;

_dbs[std::this_thread::get_id()] = db;

_dbs[std::this_thread::get_id()] = db;
_loadMutex.unlock();

for(bool loadingWorked = false; !loadingWorked; )
{
sqlite3_busy_timeout(db, 100);

try
Expand All @@ -2187,17 +2189,14 @@ void DatabaseInterface::load()
if(!loadingWorked)
{
if(loadingAttempt > 10 * 60) //Timeout is 0.1 sec, so this lets the db try for 1 minute to connect...
{
_loadMutex.unlock();
throw dbMalformedException();
}

Log::log() << "There was a problem loading the database, retrying for the #" << loadingAttempt << " time" << std::endl;
std::this_thread::sleep_for(std::chrono::nanoseconds(100000000));
}
}

_loadMutex.unlock();
return db;
}

void DatabaseInterface::close()
Expand Down Expand Up @@ -2254,6 +2253,16 @@ bool DatabaseInterface::tableExists(const std::string &name)
return runStatementsId("SELECT COUNT(name) FROM sqlite_master WHERE type='table' AND name='" + name + "';") > 0;
}

int DatabaseInterface::transactionWriteDepth()
{
return _transactionWriteDepth;
}

int DatabaseInterface::transactionReadDepth()
{
return _transactionReadDepth;
}

void DatabaseInterface::transactionWriteBegin()
{
JASPTIMER_SCOPE(DatabaseInterface::transactionWriteBegin);
Expand Down Expand Up @@ -2294,7 +2303,7 @@ void DatabaseInterface::transactionWriteEnd(bool rollback)
}
else if(_transactionWriteDepth == 0 || --_transactionWriteDepth == 0)
runStatements("COMMIT", true);

}

void DatabaseInterface::transactionReadEnd()
Expand Down
9 changes: 3 additions & 6 deletions CommonData/databaseinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ class DatabaseInterface
void truncateAllTables();
bool tableHasColumn(const std::string & tableName, const std::string & columnName);
bool tableExists(const std::string & name);
int transactionWriteDepth() { return _transactionWriteDepth; }
int transactionReadDepth() { return _transactionReadDepth; }
int transactionWriteDepth();
int transactionReadDepth();

void preloadInterfaceForThread();
void close(); ///< Closes the loaded database and disconnects
Expand All @@ -197,13 +197,10 @@ class DatabaseInterface
void _runStatementsRepeatedly( const std::string & statements, std::function<bool( std::function<void(sqlite3_stmt *stmt)> ** bindParameters, size_t row)> bindParameterFactory, std::function<void(size_t row, size_t repetition, sqlite3_stmt *stmt)> * processRow = nullptr, bool ignoreFails = false);

void create(); ///< Creates a new sqlite database in sessiondir and loads it
void load(); ///< Loads a sqlite database from sessiondir (after loading a jaspfile)
sqlite3* load(); ///< Loads a sqlite database from sessiondir (after loading a jaspfile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I on purpose kept sqlite3 stuff out of the api because this is supposed to abstract away from that so we could change sqlite for some other sql some day.

Why did you add it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true, this is not necessary anymore (this is just a relic of old attempts). I'll change this

Copy link
Contributor

@JorisGoosen JorisGoosen Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ill do so, or not




int _transactionWriteDepth = 0,
_transactionReadDepth = 0;

std::map<std::thread::id, sqlite3*> _dbs;
std::thread::id _dbCreator;
sqlite3* _dbCreated = nullptr;
Expand Down
2 changes: 0 additions & 2 deletions Desktop/data/datasetloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ void DataSetLoader::loadPackage(const string &locator, const string &extension,

void DataSetLoader::syncPackage(const string &locator, const string &extension, std::function<void(int)> progress)
{
Utils::sleep(100); // :'(

Importer* importer = getImporter(locator, extension);

if (importer)
Expand Down
Loading