Skip to content

Allow to preserve legacy DBs layout, use leveldb-only layout by default #357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

uprendis
Copy link
Contributor

@uprendis uprendis commented Aug 29, 2022

  • add presets for DBs layout: ldb-1 (fastest leveldb-only layout), pbl-1 (fastest pebble/leveldb layout), legacy-ldb (legacy layout from 1.1.1 or earlier), legacy-pbl (layout from 1.1.1-rc.2-pebble). ldb-1 is used by default instead of pbl-1.
  • add reformat mode for multidb migration for instant migration with unaltered DBs layout

Migration options:

  • Instant migration from a leveldb-based version: --db.migration.mode reformat --db.preset legacy-ldb
  • Instant migration from 1.1.1-rc.2-pebble: --db.migration.mode reformat --db.preset legacy-pbl
  • Migration with rebuilding DBs according to any configured layout: --db.migration.mode rebuild

Flag --db.migration.mode is required only if datadir isn't migrated.

@thaarok
Copy link
Contributor

thaarok commented Aug 29, 2022

I think Opera should throw an error when trying to use reformat mode with non-legacy preset.

Currently it continues the reformat and fails on broken database:

opera --datadir=/var/opera/mainnet --db.preset=ldb-1 --db.migration.mode=reformat
INFO [08-29|20:31:46.808] Maximum peer count                       total=50
INFO [08-29|20:31:46.808] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
CRIT [08-29|20:31:47.013] LLR state reading failed: genesis not applied

@@ -186,7 +186,7 @@ func translateGossipPrefix(p byte) byte {
return p
}

func migrateLegacyDBs(chaindataDir string, dbs kvdb.FlushableDBProducer) error {
func migrateLegacyDBs(chaindataDir string, dbs kvdb.FlushableDBProducer, mode string) error {
if !isEmpty(path.Join(chaindataDir, "gossip")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this check is not much necessary due to we already check it before calling the function migrateLegacyDBs(); it's okay to re-check inside the function but I prefer to use short circuit as below to reduce one long nested if condition

Suggested change
if !isEmpty(path.Join(chaindataDir, "gossip")) {
if isEmpty(path.Join(chaindataDir, "gossip")) {
return null
}

@hadv
Copy link
Contributor

hadv commented Aug 30, 2022

I think Opera should throw an error when trying to use reformat mode with non-legacy preset.

Currently it continues the reformat and fails on broken database:

opera --datadir=/var/opera/mainnet --db.preset=ldb-1 --db.migration.mode=reformat
INFO [08-29|20:31:46.808] Maximum peer count                       total=50
INFO [08-29|20:31:46.808] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
CRIT [08-29|20:31:47.013] LLR state reading failed: genesis not applied

I think it only migrate the legacy preset via this checking? if legacy preset is presented then the gossip folder does not existed; but of course user can force the --db.preset=ldb-1 to a legacy preset then it might be the issue that you mentioned.

if !isEmpty(path.Join(chaindataDir, "gossip")) {

@hadv
Copy link
Contributor

hadv commented Aug 30, 2022

Instant migration from a leveldb-based version: --db.migration.mode reformat --db.preset legacy-ldb
Instant migration from 1.1.1-rc.2-pebble: --db.migration.mode reformat --db.preset legacy-pbl

If I understand correctly then the from preset layout in the case of reformat is deciding by below code, not by the --db.preset?

		if fileExists(path.Join(chaindataDir, "gossip", "LOG")) {
			oldDBs = leveldb.NewProducer(chaindataDir, cacheFn)
			oldDBsType = "ldb"
		} else {
			oldDBs = pebble.NewProducer(chaindataDir, cacheFn)
			oldDBsType = "pbl"
		}

so the --db.preset will be only meaning used for target preset layout in --db.migration.mode rebuild, right? And what happen if the target preset is legacy one?

@uprendis
Copy link
Contributor Author

uprendis commented Aug 30, 2022

so the --db.preset will be only meaning used for target preset layout in --db.migration.mode rebuild, right? And what happen if the target preset is legacy one?

That's right, reformat and configured DB presets are technically independent from each other. But practically, every DB has two hidden records:

  • FlushIDKey -> FlushID (it was always present)
  • TablesKey -> list of tables of this DB (new record)

reformat currently just moves the tables without adding TablesKeys records. On first launch, multidb will think that those DBs are empty and will add TablesKeys itself according to configured layout. If configured layout is wrong, then it'll place wrong TablesKeys records which will confuse multidb to a point when datadir cannot be recovered anymore

So I have to either:

  • Not just rename DBs but place correct TablesKeys records in there. In a case you set up a wrong DB layout, then it will just say that configured layout is different than datadir's and will exit without "damaging" the datadir
  • Just hardcode that if reformat flag is present, then configured DB layout should strictly match to either legacy-ldb or legacy-pbl, depending on datadir's DB types

@uprendis
Copy link
Contributor Author

Just hardcode that if reformat flag is present, then configured DB layout should strictly match to either legacy-ldb or legacy-pbl, depending on datadir's DB types

Implemented this in dff7354

Copy link
Contributor

@hadv hadv left a comment

Choose a reason for hiding this comment

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

LGTM

@uprendis uprendis merged commit 75e354e into Fantom-foundation:develop Sep 4, 2022
@ymonye
Copy link

ymonye commented May 11, 2023

Hey team, I have a question here. Also, if there's a more appropriate medium to ask besides this comments section, please let me know.

I am attempting to run a fresh archive node sync using txtracing/1.1.2-rc.6 on PebbleDB, while also using genesis mainnet-109331-full-mpt.g to retain archival data. Once my node finishes initializing with the archive genesis file, would I still need to rebuild the database for this v1.1.2-rc6 release? I'm not exactly sure if initializing the genesis file with the PebbleDB flags automatically converts all historical states to a PebbleDB format, but I've been running a node for a while & wanted to ensure everything was done properly.

I'm running an archive node today with the following flags:

/blockchain/clients/ftm/go-opera/build/opera --genesis=/blockchain/nodes/ftm/go-opera/mainnet/mainnet-109331-full-mpt.g --syncmode=full --gcmode=archive --db.preset=pbl-1 --port=30305 --http --http.vhosts="*" --http.corsdomain="*" --http.addr=0.0.0.0 --http.port=8545 --ws --ws.origins="*" --ws.addr=0.0.0.0 --ws.port=8546 --datadir=/blockchain/nodes/ftm/go-opera/mainnet --tracenode --tracing --http.api="ftm,eth,debug,admin,web3,personal,net,txpool,sfc"

Thanks,
Yannick

@jmpike
Copy link
Collaborator

jmpike commented May 11, 2023 via email

@ymonye
Copy link

ymonye commented May 11, 2023

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants