Skip to content

Commit eb00307

Browse files
committed
Remove maintenance
1 parent 4318e17 commit eb00307

29 files changed

Lines changed: 250 additions & 375 deletions

docs/quick-reference.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,6 @@ You have some control over which peers you're connected to:
5959
* the `connect` command asks the instance to connect to a specific peer.
6060
* the `droppeer` command asks the instance to drop the connection with a specific peer.
6161

62-
### Maintenance
63-
64-
Core keeps historical data needed for publish (such as SCP history)
65-
66-
Sometimes you need to clean up more than this (for example, if you have a large maintenance debt).
67-
In this case running the command `maintenance?count=100000000` (integer is a large number, bigger than your max backlog) will perform the full maintenance.
68-
69-
Note that this may hang the instance for minutes (hours even).
70-
71-
After performing such maintenance, you may issue a postgres `VACUUM FULL;` that will reclaim all
72-
disk space (note that this requires a lot of free disk space).
73-
7462
### Testing
7563

7664
The `manualclose` command allows to close a ledger, this is used when the instance is

docs/software/commands.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,6 @@ Most commands return their results in JSON format.
279279
* **logrotate**
280280
Rotate log files.
281281

282-
* **maintenance**
283-
`maintenance?[queue=true]`<br>
284-
Performs maintenance tasks on the instance.
285-
* `queue` performs deletion of queue data. See `setcursor` for more information.
286-
287282
* **metrics**
288283
`metrics?[enable=PARTITION_1,PARTITION_2,...,PARTITION_N]`<br>
289284
Returns a snapshot of the metrics registry (for monitoring and debugging

docs/stellar-core_example.cfg

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -417,19 +417,6 @@ QUORUM_INTERSECTION_CHECKER=true
417417
# This limits the number that will be active at a time.
418418
MAX_CONCURRENT_SUBPROCESSES=16
419419

420-
# AUTOMATIC_MAINTENANCE_PERIOD (integer, seconds) default 359
421-
# Interval between automatic maintenance executions
422-
# Set to 0 to disable automatic maintenance
423-
AUTOMATIC_MAINTENANCE_PERIOD=359
424-
425-
# AUTOMATIC_MAINTENANCE_COUNT (integer) default 400
426-
# Number of unneeded ledgers in each table that will be removed during one
427-
# maintenance run.
428-
# NB: make sure that enough ledgers are deleted as to offset the growth of
429-
# data accumulated by closing ledgers (catchup and normal operation)
430-
# Set to 0 to disable automatic maintenance
431-
AUTOMATIC_MAINTENANCE_COUNT=400
432-
433420
# AUTOMATIC_SELF_CHECK_PERIOD (integer, seconds) default 10800
434421
# Interval between automatic self-checks, including connectivity
435422
# and consistency checking against configured history archives.

src/bucket/test/BucketManagerTests.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "ledger/test/LedgerTestUtils.h"
2323
#include "main/Application.h"
2424
#include "main/Config.h"
25-
#include "main/Maintainer.h"
2625
#include "test/Catch2.h"
2726
#include "test/TestUtils.h"
2827
#include "test/test.h"
@@ -807,9 +806,6 @@ TEST_CASE_VERSIONS(
807806
while (hm.getPublishSuccessCount() < 5)
808807
{
809808
clock.crank(false);
810-
811-
// Trim history after publishing whenever possible.
812-
app->getMaintainer().performMaintenance(50000);
813809
}
814810
});
815811
}

src/database/Database.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,40 @@ dropMiscTablesFromMain(Application& app)
323323
}
324324
}
325325

326+
void
327+
migrateLedgerHeadersToStoreState(Database& db)
328+
{
329+
// Migrate LCL header from ledgerheaders table to storestate
330+
std::string lclHash;
331+
332+
db.getRawSession() << "SELECT state FROM storestate WHERE statename = "
333+
"'lastclosedledger'",
334+
soci::into(lclHash);
335+
// When we're doing this migration for a new db, storestate will be empty.
336+
// So, only try to set lastclosedledgerheader when the data is found
337+
if (db.getRawSession().got_data())
338+
{
339+
340+
if (lclHash.empty())
341+
{
342+
throw std::runtime_error(
343+
"No reference in DB to any last closed ledger");
344+
}
345+
346+
std::string headerData =
347+
LedgerHeaderUtils::getHeaderDataForHash(db, hexToBin256(lclHash));
348+
349+
db.getRawSession() << "INSERT INTO storestate (statename, state) "
350+
"VALUES ('lastclosedledgerheader', :v)",
351+
soci::use(headerData);
352+
353+
db.getRawSession()
354+
<< "DELETE FROM storestate WHERE statename = 'lastclosedledger'";
355+
}
356+
357+
db.getRawSession() << "DROP TABLE ledgerheaders";
358+
}
359+
326360
void
327361
Database::applySchemaUpgrade(unsigned long vers)
328362
{
@@ -343,6 +377,9 @@ Database::applySchemaUpgrade(unsigned long vers)
343377
dropMiscTablesFromMain(mApp);
344378
}
345379
break;
380+
case 27:
381+
migrateLedgerHeadersToStoreState(*this);
382+
break;
346383
default:
347384
throw std::runtime_error("Unknown DB schema version");
348385
}

src/database/Database.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Application;
2929

3030
// smallest schema version supported
3131
static constexpr unsigned long MIN_SCHEMA_VERSION = 25;
32-
static constexpr unsigned long SCHEMA_VERSION = 26;
32+
static constexpr unsigned long SCHEMA_VERSION = 27;
3333
static constexpr unsigned long FIRST_MAIN_VERSION_WITH_MISC = 26;
3434
// Misc schema version 0 means no misc table exists yet
3535
static constexpr unsigned long MIN_MISC_SCHEMA_VERSION = 0;

src/database/test/DatabaseTests.cpp

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "crypto/Hex.h"
77
#include "crypto/KeyUtils.h"
88
#include "database/Database.h"
9+
#include "ledger/LedgerHeaderUtils.h"
910
#include "ledger/LedgerTxn.h"
1011
#include "ledger/test/LedgerTestUtils.h"
1112
#include "lib/util/stdrandom.h"
@@ -494,9 +495,18 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
494495
"('ledgerupgrades', 'testvalue')",
495496
db.getSession());
496497

498+
LedgerHeader header = LedgerManager::genesisLedger();
499+
// Change one value from the genesis ledger to ensure that we did
500+
// actually migrate correctly
501+
header.ledgerSeq = 12345;
502+
LedgerHeaderUtils::storeInDatabase(db, header, db.getSession());
503+
std::string hash;
504+
std::string headerEncoded =
505+
LedgerHeaderUtils::encodeHeader(header, hash);
506+
497507
// Insert test data that should stay in main DB
498-
execSQL("INSERT INTO storestate (statename, state) VALUES "
499-
"('lastclosedledger', 'maintestvalue')",
508+
execSQL("INSERT INTO storestate (statename, state) VALUES " +
509+
fmt::format("('lastclosedledger', '{}')", hash),
500510
db.getSession());
501511

502512
// Verify data exists in main before migration
@@ -515,13 +525,13 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
515525
std::string result;
516526
auto prep = db.getPreparedStatement(
517527
"SELECT state FROM storestate WHERE statename = "
518-
"'lastclosedledger'",
528+
"'lastclosedledgerheader'",
519529
db.getSession());
520530
auto& st = prep.statement();
521531
st.exchange(soci::into(result));
522532
st.define_and_bind();
523533
st.execute(true);
524-
REQUIRE(result == "maintestvalue");
534+
REQUIRE(result == headerEncoded);
525535
}
526536

527537
// Verify storestate table still exists in main DB
@@ -576,3 +586,85 @@ TEST_CASE("Database splitting migration works correctly", "[db]")
576586
}
577587
}
578588
}
589+
590+
TEST_CASE("ledgerheaders migration works correctly", "[db]")
591+
{
592+
Config::TestDbMode mode = GENERATE(Config::TESTDB_BUCKET_DB_PERSISTENT
593+
#ifdef USE_POSTGRES
594+
,
595+
Config::TESTDB_POSTGRESQL
596+
#endif
597+
);
598+
Config cfg = getTestConfig(0, mode);
599+
INFO("Testing mode: " << (mode == Config::TESTDB_POSTGRESQL
600+
? "PostgreSQL"
601+
: "Persistent"));
602+
603+
VirtualClock clock;
604+
// Set startApp to false to trigger migration manually
605+
Application::pointer app = createTestApplication(
606+
clock, cfg, /* newDB */ true, /* startApp */ false);
607+
608+
std::optional<std::string> expectedLCLHeader;
609+
auto checkMigration = [&app](std::optional<std::string> expectedLCL) {
610+
REQUIRE(app->getDatabase().getMainDBSchemaVersion() == SCHEMA_VERSION);
611+
REQUIRE_THROWS(app->getDatabase().getRawSession()
612+
<< "SELECT COUNT(1) FROM ledgerheaders");
613+
614+
{
615+
// Check that lastclosedledger has been removed
616+
auto& sess = app->getDatabase().getRawSession();
617+
int i;
618+
sess << "SELECT COUNT(1) FROM storestate WHERE statename = "
619+
"'lastclosedledger'",
620+
soci::into(i);
621+
REQUIRE(sess.got_data());
622+
REQUIRE(i == 0);
623+
}
624+
625+
std::string lclHeader = app->getPersistentState().getState(
626+
PersistentState::kLastClosedLedgerHeader,
627+
app->getDatabase().getSession());
628+
629+
if (expectedLCL)
630+
{
631+
REQUIRE(lclHeader == expectedLCL);
632+
}
633+
else
634+
{
635+
LedgerHeader lh = LedgerHeaderUtils::decodeFromData(lclHeader);
636+
REQUIRE(
637+
app->getLedgerManager().getLastClosedLedgerHeader().header ==
638+
lh);
639+
}
640+
};
641+
642+
SECTION("Just running newdb")
643+
{
644+
checkMigration(std::nullopt);
645+
}
646+
647+
SECTION("Migrate from old schema with LCL header")
648+
{
649+
auto& db = app->getDatabase();
650+
db.initialize();
651+
652+
auto& lcl = app->getLedgerManager().getLastClosedLedgerHeader();
653+
LedgerHeader header = lcl.header;
654+
header.ledgerSeq++;
655+
header.previousLedgerHash = lcl.hash;
656+
LedgerHeaderUtils::storeInDatabase(db, header, db.getSession());
657+
658+
std::string hash;
659+
std::string headerEncoded =
660+
LedgerHeaderUtils::encodeHeader(header, hash);
661+
db.getRawSession()
662+
<< "INSERT INTO storestate (statename, state) VALUES "
663+
"('lastclosedledger', :h)",
664+
soci::use(hash);
665+
666+
db.upgradeToCurrentSchema();
667+
668+
checkMigration(headerEncoded);
669+
}
670+
}

src/herder/HerderImpl.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,23 @@ HerderImpl::setupTriggerNextLedger()
12881288
#endif
12891289
}
12901290

1291+
// Returns the ledger index of the oldest ledger that it is safe to delete while
1292+
// still keeping all the information needed to publish checkpoints
1293+
uint32_t
1294+
getSafeLedgerToDelete(uint32_t ledger, Config const& cfg)
1295+
{
1296+
// Calculate the minimum of *minSlot and/or any queued checkpoint.
1297+
uint32_t ql = HistoryManager::getMinLedgerQueuedToPublish(cfg);
1298+
uint32_t qmin = ql == 0 ? ledger : std::min(ql, ledger);
1299+
1300+
// Next calculate, given qmin, the first ledger it'd be _safe to delete_
1301+
// while still keeping everything required to publish. So if qmin is
1302+
// (for example) 0x7f = 127, then we want to keep 64 ledgers before
1303+
// that, and therefore can erase 0x3f = 63 and less.
1304+
uint32_t freq = HistoryManager::getCheckpointFrequency(cfg);
1305+
return qmin >= freq ? qmin - freq : 0;
1306+
}
1307+
12911308
void
12921309
HerderImpl::eraseBelow(uint32 ledgerSeq)
12931310
{
@@ -1296,6 +1313,14 @@ HerderImpl::eraseBelow(uint32 ledgerSeq)
12961313
mPendingEnvelopes.eraseBelow(ledgerSeq, lastCheckpointSeq);
12971314
auto lastIndex = trackingConsensusLedgerIndex();
12981315
mApp.getOverlayManager().clearLedgersBelow(ledgerSeq, lastIndex);
1316+
1317+
uint32_t lmin = getSafeLedgerToDelete(ledgerSeq, mApp.getConfig());
1318+
// To avoid blocking too long, don't delete more than one checkpoint of
1319+
// history
1320+
uint32_t const ledgersToDelete =
1321+
HistoryManager::getCheckpointFrequency(mApp.getConfig());
1322+
HerderPersistence::deleteOldEntries(mApp.getDatabase().getRawMiscSession(),
1323+
lmin, ledgersToDelete);
12991324
}
13001325

13011326
bool

src/herder/test/HerderTests.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include "crypto/SHA.h"
2525
#include "database/Database.h"
2626
#include "herder/HerderUtils.h"
27-
#include "ledger/LedgerHeaderUtils.h"
2827
#include "ledger/LedgerManager.h"
2928
#include "ledger/LedgerTxn.h"
3029
#include "ledger/LedgerTxnHeader.h"

src/history/HistoryManagerImpl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include "historywork/PutSnapshotFilesWork.h"
2525
#include "historywork/ResolveSnapshotWork.h"
2626
#include "historywork/WriteSnapshotWork.h"
27-
#include "ledger/LedgerHeaderUtils.h"
2827
#include "ledger/LedgerManager.h"
2928
#include "main/Application.h"
3029
#include "main/Config.h"

0 commit comments

Comments
 (0)