@@ -60,10 +60,6 @@ using namespace std;
60
60
61
61
bool Database::gDriversRegistered = false ;
62
62
63
- // smallest schema version supported
64
- static unsigned long const MIN_SCHEMA_VERSION = 21 ;
65
- static unsigned long const SCHEMA_VERSION = 24 ;
66
-
67
63
// These should always match our compiled version precisely, since we are
68
64
// using a bundled version to get access to carray(). But in case someone
69
65
// overrides that or our build configuration changes, it's nicer to get a
@@ -184,6 +180,7 @@ Database::Database(Application& app)
184
180
: mApp (app)
185
181
, mQueryMeter (
186
182
app.getMetrics().NewMeter({" database" , " query" , " exec" }, " query" ))
183
+ , mSession (" main" )
187
184
, mStatementsSize (
188
185
app.getMetrics().NewCounter({" database" , " memory" , " statements" }))
189
186
{
@@ -198,17 +195,17 @@ Database::Database(Application& app)
198
195
void
199
196
Database::open ()
200
197
{
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 );
204
201
}
205
202
206
203
void
207
204
Database::applySchemaUpgrade (unsigned long vers)
208
205
{
209
- clearPreparedStatementCache ();
206
+ clearPreparedStatementCache (mSession );
210
207
211
- soci::transaction tx (mSession );
208
+ soci::transaction tx (mSession . session () );
212
209
switch (vers)
213
210
{
214
211
case 22 :
@@ -220,6 +217,7 @@ Database::applySchemaUpgrade(unsigned long vers)
220
217
break ;
221
218
case 24 :
222
219
getSession () << " DROP TABLE IF EXISTS pubsub;" ;
220
+ mApp .getPersistentState ().migrateToSlotStateTable ();
223
221
break ;
224
222
default :
225
223
throw std::runtime_error (" Unknown DB schema version" );
@@ -263,62 +261,66 @@ Database::upgradeToCurrentSchema()
263
261
void
264
262
Database::maybeUpgradeToBucketListDB ()
265
263
{
266
- if (mApp .getPersistentState ().getState (PersistentState::kDBBackend ) !=
264
+ if (mApp .getPersistentState ().getState (PersistentState::kDBBackend ,
265
+ getSession ()) !=
267
266
BucketIndex::DB_BACKEND_STATE)
268
267
{
269
268
CLOG_INFO (Database, " Upgrading to BucketListDB" );
270
269
271
270
// Drop all LedgerEntry tables except for offers
272
271
CLOG_INFO (Database, " Dropping table accounts" );
273
- getSession () << " DROP TABLE IF EXISTS accounts;" ;
272
+ getRawSession () << " DROP TABLE IF EXISTS accounts;" ;
274
273
275
274
CLOG_INFO (Database, " Dropping table signers" );
276
- getSession () << " DROP TABLE IF EXISTS signers;" ;
275
+ getRawSession () << " DROP TABLE IF EXISTS signers;" ;
277
276
278
277
CLOG_INFO (Database, " Dropping table claimablebalance" );
279
- getSession () << " DROP TABLE IF EXISTS claimablebalance;" ;
278
+ getRawSession () << " DROP TABLE IF EXISTS claimablebalance;" ;
280
279
281
280
CLOG_INFO (Database, " Dropping table configsettings" );
282
- getSession () << " DROP TABLE IF EXISTS configsettings;" ;
281
+ getRawSession () << " DROP TABLE IF EXISTS configsettings;" ;
283
282
284
283
CLOG_INFO (Database, " Dropping table contractcode" );
285
- getSession () << " DROP TABLE IF EXISTS contractcode;" ;
284
+ getRawSession () << " DROP TABLE IF EXISTS contractcode;" ;
286
285
287
286
CLOG_INFO (Database, " Dropping table contractdata" );
288
- getSession () << " DROP TABLE IF EXISTS contractdata;" ;
287
+ getRawSession () << " DROP TABLE IF EXISTS contractdata;" ;
289
288
290
289
CLOG_INFO (Database, " Dropping table accountdata" );
291
- getSession () << " DROP TABLE IF EXISTS accountdata;" ;
290
+ getRawSession () << " DROP TABLE IF EXISTS accountdata;" ;
292
291
293
292
CLOG_INFO (Database, " Dropping table liquiditypool" );
294
- getSession () << " DROP TABLE IF EXISTS liquiditypool;" ;
293
+ getRawSession () << " DROP TABLE IF EXISTS liquiditypool;" ;
295
294
296
295
CLOG_INFO (Database, " Dropping table trustlines" );
297
- getSession () << " DROP TABLE IF EXISTS trustlines;" ;
296
+ getRawSession () << " DROP TABLE IF EXISTS trustlines;" ;
298
297
299
298
CLOG_INFO (Database, " Dropping table ttl" );
300
- getSession () << " DROP TABLE IF EXISTS ttl;" ;
299
+ getRawSession () << " DROP TABLE IF EXISTS ttl;" ;
301
300
302
301
mApp .getPersistentState ().setState (PersistentState::kDBBackend ,
303
- BucketIndex::DB_BACKEND_STATE);
302
+ BucketIndex::DB_BACKEND_STATE,
303
+ getSession ());
304
304
}
305
305
}
306
306
307
307
void
308
308
Database::putSchemaVersion (unsigned long vers)
309
309
{
310
310
mApp .getPersistentState ().setState (PersistentState::kDatabaseSchema ,
311
- std::to_string (vers));
311
+ std::to_string (vers),
312
+ mApp .getDatabase ().getSession ());
312
313
}
313
314
314
315
unsigned long
315
316
Database::getDBSchemaVersion ()
316
317
{
318
+ releaseAssert (threadIsMain ());
317
319
unsigned long vers = 0 ;
318
320
try
319
321
{
320
322
auto vstr = mApp .getPersistentState ().getState (
321
- PersistentState::kDatabaseSchema );
323
+ PersistentState::kDatabaseSchema , getSession () );
322
324
vers = std::stoul (vstr);
323
325
}
324
326
catch (...)
@@ -332,16 +334,9 @@ Database::getDBSchemaVersion()
332
334
return vers;
333
335
}
334
336
335
- unsigned long
336
- Database::getAppSchemaVersion ()
337
- {
338
- return SCHEMA_VERSION;
339
- }
340
-
341
337
medida::TimerContext
342
338
Database::getInsertTimer (std::string const & entityName)
343
339
{
344
- mEntityTypes .insert (entityName);
345
340
mQueryMeter .Mark ();
346
341
return mApp .getMetrics ()
347
342
.NewTimer ({" database" , " insert" , entityName})
@@ -351,7 +346,6 @@ Database::getInsertTimer(std::string const& entityName)
351
346
medida::TimerContext
352
347
Database::getSelectTimer (std::string const & entityName)
353
348
{
354
- mEntityTypes .insert (entityName);
355
349
mQueryMeter .Mark ();
356
350
return mApp .getMetrics ()
357
351
.NewTimer ({" database" , " select" , entityName})
@@ -361,7 +355,6 @@ Database::getSelectTimer(std::string const& entityName)
361
355
medida::TimerContext
362
356
Database::getDeleteTimer (std::string const & entityName)
363
357
{
364
- mEntityTypes .insert (entityName);
365
358
mQueryMeter .Mark ();
366
359
return mApp .getMetrics ()
367
360
.NewTimer ({" database" , " delete" , entityName})
@@ -371,7 +364,6 @@ Database::getDeleteTimer(std::string const& entityName)
371
364
medida::TimerContext
372
365
Database::getUpdateTimer (std::string const & entityName)
373
366
{
374
- mEntityTypes .insert (entityName);
375
367
mQueryMeter .Mark ();
376
368
return mApp .getMetrics ()
377
369
.NewTimer ({" database" , " update" , entityName})
@@ -381,7 +373,6 @@ Database::getUpdateTimer(std::string const& entityName)
381
373
medida::TimerContext
382
374
Database::getUpsertTimer (std::string const & entityName)
383
375
{
384
- mEntityTypes .insert (entityName);
385
376
mQueryMeter .Mark ();
386
377
return mApp .getMetrics ()
387
378
.NewTimer ({" database" , " upsert" , entityName})
@@ -393,7 +384,8 @@ Database::setCurrentTransactionReadOnly()
393
384
{
394
385
if (!isSqlite ())
395
386
{
396
- auto prep = getPreparedStatement (" SET TRANSACTION READ ONLY" );
387
+ auto prep =
388
+ getPreparedStatement (" SET TRANSACTION READ ONLY" , getSession ());
397
389
auto & st = prep.statement ();
398
390
st.define_and_bind ();
399
391
st.execute (false );
@@ -429,14 +421,31 @@ Database::canUsePool() const
429
421
void
430
422
Database::clearPreparedStatementCache ()
431
423
{
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
+
432
441
// Flush all prepared statements; in sqlite they represent open cursors
433
442
// and will conflict with any DROP TABLE commands issued below
434
- for (auto st : mStatements )
443
+ for (auto st : mCaches [session. getSessionName ()] )
435
444
{
436
445
st.second ->clean_up (true );
446
+ mStatementsSize .dec ();
437
447
}
438
- mStatements .clear ();
439
- mStatementsSize .set_count (mStatements .size ());
448
+ mCaches .erase (session.getSessionName ());
440
449
}
441
450
442
451
void
@@ -452,8 +461,9 @@ Database::initialize()
452
461
int i;
453
462
std::string databaseName, databaseLocation;
454
463
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));
457
467
st.execute (true );
458
468
while (st.got_data ())
459
469
{
@@ -466,7 +476,7 @@ Database::initialize()
466
476
}
467
477
if (!fn.empty () && fs::exists (fn))
468
478
{
469
- mSession .close ();
479
+ getRawSession () .close ();
470
480
std::remove (fn.c_str ());
471
481
open ();
472
482
}
@@ -476,7 +486,7 @@ Database::initialize()
476
486
477
487
// only time this section should be modified is when
478
488
// consolidating changes found in applySchemaUpgrade here
479
- Upgrades::dropAll (*this );
489
+ Upgrades::dropSupportUpgradeHistory (*this );
480
490
OverlayManager::dropAll (*this );
481
491
PersistentState::dropAll (*this );
482
492
LedgerHeaderUtils::dropAll (*this );
@@ -487,21 +497,26 @@ Database::initialize()
487
497
HerderPersistence::dropAll (*this );
488
498
BanManager::dropAll (*this );
489
499
putSchemaVersion (MIN_SCHEMA_VERSION);
490
- mApp .getHerderPersistence ().createQuorumTrackingTable (mSession );
491
500
492
501
LOG_INFO (DEFAULT_LOG, " * " );
493
502
LOG_INFO (DEFAULT_LOG, " * The database has been initialized" );
494
503
LOG_INFO (DEFAULT_LOG, " * " );
495
504
}
496
505
497
- soci::session &
506
+ SessionWrapper &
498
507
Database::getSession ()
499
508
{
500
509
// global session can only be used from the main thread
501
510
releaseAssert (threadIsMain ());
502
511
return mSession ;
503
512
}
504
513
514
+ soci::session&
515
+ Database::getRawSession ()
516
+ {
517
+ return getSession ().session ();
518
+ }
519
+
505
520
soci::connection_pool&
506
521
Database::getPool ()
507
522
{
@@ -568,17 +583,21 @@ class SQLLogContext : NonCopyable
568
583
};
569
584
570
585
StatementContext
571
- Database::getPreparedStatement (std::string const & query)
586
+ Database::getPreparedStatement (std::string const & query,
587
+ SessionWrapper& session)
572
588
{
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);
574
593
std::shared_ptr<soci::statement> p;
575
- if (i == mStatements .end ())
594
+ if (i == cache .end ())
576
595
{
577
- p = std::make_shared<soci::statement>(mSession );
596
+ p = std::make_shared<soci::statement>(session. session () );
578
597
p->alloc ();
579
598
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 ( );
582
601
}
583
602
else
584
603
{
@@ -591,6 +610,6 @@ Database::getPreparedStatement(std::string const& query)
591
610
std::shared_ptr<SQLLogContext>
592
611
Database::captureAndLogSQL (std::string contextName)
593
612
{
594
- return make_shared<SQLLogContext>(contextName, mSession );
613
+ return make_shared<SQLLogContext>(contextName, mSession . session () );
595
614
}
596
615
}
0 commit comments