Skip to content

Commit 229beb4

Browse files
committed
Support multiple sessions in Database class
1 parent 483b558 commit 229beb4

File tree

2 files changed

+129
-67
lines changed

2 files changed

+129
-67
lines changed

src/database/Database.cpp

+70-51
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ using namespace std;
6060

6161
bool Database::gDriversRegistered = false;
6262

63-
// smallest schema version supported
64-
static unsigned long const MIN_SCHEMA_VERSION = 21;
65-
static unsigned long const SCHEMA_VERSION = 24;
66-
6763
// These should always match our compiled version precisely, since we are
6864
// using a bundled version to get access to carray(). But in case someone
6965
// overrides that or our build configuration changes, it's nicer to get a
@@ -184,6 +180,7 @@ Database::Database(Application& app)
184180
: mApp(app)
185181
, mQueryMeter(
186182
app.getMetrics().NewMeter({"database", "query", "exec"}, "query"))
183+
, mSession("main")
187184
, mStatementsSize(
188185
app.getMetrics().NewCounter({"database", "memory", "statements"}))
189186
{
@@ -198,17 +195,17 @@ Database::Database(Application& app)
198195
void
199196
Database::open()
200197
{
201-
mSession.open(mApp.getConfig().DATABASE.value);
202-
DatabaseConfigureSessionOp op(mSession);
203-
doDatabaseTypeSpecificOperation(op);
198+
mSession.session().open(mApp.getConfig().DATABASE.value);
199+
DatabaseConfigureSessionOp op(mSession.session());
200+
doDatabaseTypeSpecificOperation(op, mSession);
204201
}
205202

206203
void
207204
Database::applySchemaUpgrade(unsigned long vers)
208205
{
209-
clearPreparedStatementCache();
206+
clearPreparedStatementCache(mSession);
210207

211-
soci::transaction tx(mSession);
208+
soci::transaction tx(mSession.session());
212209
switch (vers)
213210
{
214211
case 22:
@@ -220,6 +217,7 @@ Database::applySchemaUpgrade(unsigned long vers)
220217
break;
221218
case 24:
222219
getSession() << "DROP TABLE IF EXISTS pubsub;";
220+
mApp.getPersistentState().migrateToSlotStateTable();
223221
break;
224222
default:
225223
throw std::runtime_error("Unknown DB schema version");
@@ -263,62 +261,66 @@ Database::upgradeToCurrentSchema()
263261
void
264262
Database::maybeUpgradeToBucketListDB()
265263
{
266-
if (mApp.getPersistentState().getState(PersistentState::kDBBackend) !=
264+
if (mApp.getPersistentState().getState(PersistentState::kDBBackend,
265+
getSession()) !=
267266
BucketIndex::DB_BACKEND_STATE)
268267
{
269268
CLOG_INFO(Database, "Upgrading to BucketListDB");
270269

271270
// Drop all LedgerEntry tables except for offers
272271
CLOG_INFO(Database, "Dropping table accounts");
273-
getSession() << "DROP TABLE IF EXISTS accounts;";
272+
getRawSession() << "DROP TABLE IF EXISTS accounts;";
274273

275274
CLOG_INFO(Database, "Dropping table signers");
276-
getSession() << "DROP TABLE IF EXISTS signers;";
275+
getRawSession() << "DROP TABLE IF EXISTS signers;";
277276

278277
CLOG_INFO(Database, "Dropping table claimablebalance");
279-
getSession() << "DROP TABLE IF EXISTS claimablebalance;";
278+
getRawSession() << "DROP TABLE IF EXISTS claimablebalance;";
280279

281280
CLOG_INFO(Database, "Dropping table configsettings");
282-
getSession() << "DROP TABLE IF EXISTS configsettings;";
281+
getRawSession() << "DROP TABLE IF EXISTS configsettings;";
283282

284283
CLOG_INFO(Database, "Dropping table contractcode");
285-
getSession() << "DROP TABLE IF EXISTS contractcode;";
284+
getRawSession() << "DROP TABLE IF EXISTS contractcode;";
286285

287286
CLOG_INFO(Database, "Dropping table contractdata");
288-
getSession() << "DROP TABLE IF EXISTS contractdata;";
287+
getRawSession() << "DROP TABLE IF EXISTS contractdata;";
289288

290289
CLOG_INFO(Database, "Dropping table accountdata");
291-
getSession() << "DROP TABLE IF EXISTS accountdata;";
290+
getRawSession() << "DROP TABLE IF EXISTS accountdata;";
292291

293292
CLOG_INFO(Database, "Dropping table liquiditypool");
294-
getSession() << "DROP TABLE IF EXISTS liquiditypool;";
293+
getRawSession() << "DROP TABLE IF EXISTS liquiditypool;";
295294

296295
CLOG_INFO(Database, "Dropping table trustlines");
297-
getSession() << "DROP TABLE IF EXISTS trustlines;";
296+
getRawSession() << "DROP TABLE IF EXISTS trustlines;";
298297

299298
CLOG_INFO(Database, "Dropping table ttl");
300-
getSession() << "DROP TABLE IF EXISTS ttl;";
299+
getRawSession() << "DROP TABLE IF EXISTS ttl;";
301300

302301
mApp.getPersistentState().setState(PersistentState::kDBBackend,
303-
BucketIndex::DB_BACKEND_STATE);
302+
BucketIndex::DB_BACKEND_STATE,
303+
getSession());
304304
}
305305
}
306306

307307
void
308308
Database::putSchemaVersion(unsigned long vers)
309309
{
310310
mApp.getPersistentState().setState(PersistentState::kDatabaseSchema,
311-
std::to_string(vers));
311+
std::to_string(vers),
312+
mApp.getDatabase().getSession());
312313
}
313314

314315
unsigned long
315316
Database::getDBSchemaVersion()
316317
{
318+
releaseAssert(threadIsMain());
317319
unsigned long vers = 0;
318320
try
319321
{
320322
auto vstr = mApp.getPersistentState().getState(
321-
PersistentState::kDatabaseSchema);
323+
PersistentState::kDatabaseSchema, getSession());
322324
vers = std::stoul(vstr);
323325
}
324326
catch (...)
@@ -332,16 +334,9 @@ Database::getDBSchemaVersion()
332334
return vers;
333335
}
334336

335-
unsigned long
336-
Database::getAppSchemaVersion()
337-
{
338-
return SCHEMA_VERSION;
339-
}
340-
341337
medida::TimerContext
342338
Database::getInsertTimer(std::string const& entityName)
343339
{
344-
mEntityTypes.insert(entityName);
345340
mQueryMeter.Mark();
346341
return mApp.getMetrics()
347342
.NewTimer({"database", "insert", entityName})
@@ -351,7 +346,6 @@ Database::getInsertTimer(std::string const& entityName)
351346
medida::TimerContext
352347
Database::getSelectTimer(std::string const& entityName)
353348
{
354-
mEntityTypes.insert(entityName);
355349
mQueryMeter.Mark();
356350
return mApp.getMetrics()
357351
.NewTimer({"database", "select", entityName})
@@ -361,7 +355,6 @@ Database::getSelectTimer(std::string const& entityName)
361355
medida::TimerContext
362356
Database::getDeleteTimer(std::string const& entityName)
363357
{
364-
mEntityTypes.insert(entityName);
365358
mQueryMeter.Mark();
366359
return mApp.getMetrics()
367360
.NewTimer({"database", "delete", entityName})
@@ -371,7 +364,6 @@ Database::getDeleteTimer(std::string const& entityName)
371364
medida::TimerContext
372365
Database::getUpdateTimer(std::string const& entityName)
373366
{
374-
mEntityTypes.insert(entityName);
375367
mQueryMeter.Mark();
376368
return mApp.getMetrics()
377369
.NewTimer({"database", "update", entityName})
@@ -381,7 +373,6 @@ Database::getUpdateTimer(std::string const& entityName)
381373
medida::TimerContext
382374
Database::getUpsertTimer(std::string const& entityName)
383375
{
384-
mEntityTypes.insert(entityName);
385376
mQueryMeter.Mark();
386377
return mApp.getMetrics()
387378
.NewTimer({"database", "upsert", entityName})
@@ -393,7 +384,8 @@ Database::setCurrentTransactionReadOnly()
393384
{
394385
if (!isSqlite())
395386
{
396-
auto prep = getPreparedStatement("SET TRANSACTION READ ONLY");
387+
auto prep =
388+
getPreparedStatement("SET TRANSACTION READ ONLY", getSession());
397389
auto& st = prep.statement();
398390
st.define_and_bind();
399391
st.execute(false);
@@ -429,14 +421,31 @@ Database::canUsePool() const
429421
void
430422
Database::clearPreparedStatementCache()
431423
{
424+
std::lock_guard<std::mutex> lock(mStatementsMutex);
425+
for (auto& c : mCaches)
426+
{
427+
for (auto& st : c.second)
428+
{
429+
st.second->clean_up(true);
430+
}
431+
}
432+
mCaches.clear();
433+
mStatementsSize.set_count(0);
434+
}
435+
436+
void
437+
Database::clearPreparedStatementCache(SessionWrapper& session)
438+
{
439+
std::lock_guard<std::mutex> lock(mStatementsMutex);
440+
432441
// Flush all prepared statements; in sqlite they represent open cursors
433442
// and will conflict with any DROP TABLE commands issued below
434-
for (auto st : mStatements)
443+
for (auto st : mCaches[session.getSessionName()])
435444
{
436445
st.second->clean_up(true);
446+
mStatementsSize.dec();
437447
}
438-
mStatements.clear();
439-
mStatementsSize.set_count(mStatements.size());
448+
mCaches.erase(session.getSessionName());
440449
}
441450

442451
void
@@ -452,8 +461,9 @@ Database::initialize()
452461
int i;
453462
std::string databaseName, databaseLocation;
454463
soci::statement st =
455-
(mSession.prepare << "PRAGMA database_list;", soci::into(i),
456-
soci::into(databaseName), soci::into(databaseLocation));
464+
(getRawSession().prepare << "PRAGMA database_list;",
465+
soci::into(i), soci::into(databaseName),
466+
soci::into(databaseLocation));
457467
st.execute(true);
458468
while (st.got_data())
459469
{
@@ -466,7 +476,7 @@ Database::initialize()
466476
}
467477
if (!fn.empty() && fs::exists(fn))
468478
{
469-
mSession.close();
479+
getRawSession().close();
470480
std::remove(fn.c_str());
471481
open();
472482
}
@@ -476,7 +486,7 @@ Database::initialize()
476486

477487
// only time this section should be modified is when
478488
// consolidating changes found in applySchemaUpgrade here
479-
Upgrades::dropAll(*this);
489+
Upgrades::dropSupportUpgradeHistory(*this);
480490
OverlayManager::dropAll(*this);
481491
PersistentState::dropAll(*this);
482492
LedgerHeaderUtils::dropAll(*this);
@@ -487,21 +497,26 @@ Database::initialize()
487497
HerderPersistence::dropAll(*this);
488498
BanManager::dropAll(*this);
489499
putSchemaVersion(MIN_SCHEMA_VERSION);
490-
mApp.getHerderPersistence().createQuorumTrackingTable(mSession);
491500

492501
LOG_INFO(DEFAULT_LOG, "* ");
493502
LOG_INFO(DEFAULT_LOG, "* The database has been initialized");
494503
LOG_INFO(DEFAULT_LOG, "* ");
495504
}
496505

497-
soci::session&
506+
SessionWrapper&
498507
Database::getSession()
499508
{
500509
// global session can only be used from the main thread
501510
releaseAssert(threadIsMain());
502511
return mSession;
503512
}
504513

514+
soci::session&
515+
Database::getRawSession()
516+
{
517+
return getSession().session();
518+
}
519+
505520
soci::connection_pool&
506521
Database::getPool()
507522
{
@@ -568,17 +583,21 @@ class SQLLogContext : NonCopyable
568583
};
569584

570585
StatementContext
571-
Database::getPreparedStatement(std::string const& query)
586+
Database::getPreparedStatement(std::string const& query,
587+
SessionWrapper& session)
572588
{
573-
auto i = mStatements.find(query);
589+
std::lock_guard<std::mutex> lock(mStatementsMutex);
590+
591+
auto& cache = mCaches[session.getSessionName()];
592+
auto i = cache.find(query);
574593
std::shared_ptr<soci::statement> p;
575-
if (i == mStatements.end())
594+
if (i == cache.end())
576595
{
577-
p = std::make_shared<soci::statement>(mSession);
596+
p = std::make_shared<soci::statement>(session.session());
578597
p->alloc();
579598
p->prepare(query);
580-
mStatements.insert(std::make_pair(query, p));
581-
mStatementsSize.set_count(mStatements.size());
599+
cache.insert(std::make_pair(query, p));
600+
mStatementsSize.inc();
582601
}
583602
else
584603
{
@@ -591,6 +610,6 @@ Database::getPreparedStatement(std::string const& query)
591610
std::shared_ptr<SQLLogContext>
592611
Database::captureAndLogSQL(std::string contextName)
593612
{
594-
return make_shared<SQLLogContext>(contextName, mSession);
613+
return make_shared<SQLLogContext>(contextName, mSession.session());
595614
}
596615
}

0 commit comments

Comments
 (0)