Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Store the database in a role specific subdirectory #8658

Closed
wants to merge 8 commits into from

Conversation

hirschenberger
Copy link
Contributor

@hirschenberger hirschenberger commented Apr 22, 2021

If there is already a database in the basedir, it will be migrated
(moved) into the role-subdirectory.

fixes #6880

polkadot companion: paritytech/polkadot#2923

TODO:

  • Create an error when trying to migrate the directory if the database-role and the role of the running client differs.

@ordian ordian added A0-please_review Pull request needs code review. B5-clientnoteworthy C1-low PR touches the given topic and has a low impact on builders. labels Apr 22, 2021
@hirschenberger
Copy link
Contributor Author

There's one issue when the client is started in a different role then the database (before migration to the subdirectory), the db gets moved to the subdirectory of the client, not the db. And opening the database later will fail.
Unfortunately then the db is already moved and will stay in the wrong directory, making subsequent starts also fail.

Unfortunately there's no stable way of finding out the DatabaseType in the client before it is opened. But the migration of the database to the subdir must be in this early phase, as the later code must not depend or know any special paths or directory layouts.

I tried to implement a database_type(path) -> Result<DatabaseType> function in the Backend which opens the databases in all modes and checks for failure. Unfortunately I can't call that function from the client, because I don't know the Block type of the backend in this phase.

@hirschenberger
Copy link
Contributor Author

Ready for review.

@paritytech paritytech deleted a comment from cla-bot-2021 bot Jun 3, 2021
@stale
Copy link

stale bot commented Jul 7, 2021

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the A5-stale Pull request did not receive any updates in a long time. No review needed at this stage. Close it. label Jul 7, 2021
@hirschenberger
Copy link
Contributor Author

This issue just needs a review.

@stale stale bot removed the A5-stale Pull request did not receive any updates in a long time. No review needed at this stage. Close it. label Jul 7, 2021
@@ -65,3 +65,39 @@ pub fn run_dev_node_for_a_while(base_path: &Path) {
kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
assert!(wait_for(&mut cmd, 40).map(|x| x.success()).unwrap_or_default());
}

/// Run the node for a while (30 seconds)
pub fn run_node_with_args_for_a_while(base_path: &Path, args: &[&str]) {
Copy link
Member

Choose a reason for hiding this comment

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

run_dev_node_for_a_while could be implemented in terms of run_node_with_args_for_a_while now

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or the caller can just pass &[--dev] as args to run_node_with_args_for_a_while

})
};

if let Some(p) = db_conf.path() {
Copy link
Member

Choose a reason for hiding this comment

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

It looks like the following migration code belongs in sc-client or sc-client-db. Right before opening the database. Cli should not be concerned with database migration. It would also remove the dependency on sc-client-db.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, this was the first thing I tried, but I actually struggled at this problem a bit, because the migration code needs to know the Role in which the client was started and the DatabaseType to be sure not to move the db to the wrong directory.

When I tried to inject the Role from the Cli to the client I had a hard time with the compiler. That's why I chose it the other way around. But maybe moving the Role enum to sc-client would work.

Copy link
Member

Choose a reason for hiding this comment

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

Role is passed down as db_type here

pub fn open_database<Block: BlockT>(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really, there's two distinct (and overlapping) terms.

There's Role from https://github.com/paritytech/substrate/blob/master/client/network/src/config.rs#L148
and DatabaseType from https://github.com/paritytech/substrate/blob/master/client/db/src/utils.rs#L91

Role is coming from the cli as parameter and DatabaseType is determined from the database.

Copy link
Member

@arkpar arkpar Aug 4, 2021

Choose a reason for hiding this comment

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

As far as understand, db_type that's passed to open_database is derived from the CLI argument. The CLI argument selects type of backend to use. Light backend opens the database as light here: https://github.com/paritytech/substrate/blob/master/client/db/src/light.rs#L76
And full backend opens it as full here: https://github.com/paritytech/substrate/blob/master/client/db/src/lib.rs#L1082

open_database does indeed check that expected db_type matches the one in the database. But you can still use expected db_type in the same way you use role w.r.t. migration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But the check for the correct database happens after the migration was applied and the database was opened, so on a mismatch I have to roll back the directories and error?

Copy link
Member

Choose a reason for hiding this comment

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

If you check the database type before migration there should be no mismatch.

I'm suggesting moving your migration code inside the open_database function.
Basically move all of the code from open_database to a helper function, e.g. open_database_at
So that the new version of open_database would do something like this:

  1. Check the base path for an existing database. Try to open it with open_database_at, which will validate expected db_type. If it succeeds, close the database and do the migration.
  2. Append "full" or "light" to base path. Open it with open_database_at and return

A bit of refactoring might be required to extract the meat of open_database to a helper function that does the heavy lifting of actually opening the database.

}

if crate::utils::open_database::<Block>(&config, DatabaseType::Light).is_ok() {
return Ok(DatabaseType::Light);
Copy link
Member

Choose a reason for hiding this comment

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

This method of detecting database type is a bit hacky. It relies on the fact that the databases have different number of columns. Also unlike rocksdb, paritydb does not care if you don't open all of the columns. So it is important to try for full database first, before trying as light. Could you please add a comment to that extend?

Copy link
Contributor

Choose a reason for hiding this comment

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

Skimming through code I just read that open_database also call

pub fn check_database_type(
so should be fine?

Copy link
Member

Choose a reason for hiding this comment

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

Right, there's already a method for 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.

This was the best way I could find to differentiate them, will add a comment for full disclosure.

Copy link
Member

Choose a reason for hiding this comment

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

If you move migration code to sc-client-db you can just use utils::check_database_type instead.

Copy link
Member

Choose a reason for hiding this comment

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

On the other hand utils::check_database_type requires the database to be open already, which in turn requires specifying a DatabaseType. So I guess the current approach is fine after all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I remember, that was the problem.

@arkpar
Copy link
Member

arkpar commented Aug 4, 2021

Thanks for the PR an apologies for the late review. Totally agree that the databases should be separated.
Looks good, apart from migration code should be moved to a different crate.

@arkpar arkpar requested review from bkchr, cheme and debris August 4, 2021 16:57
@hirschenberger
Copy link
Contributor Author

There had been some refactorings in master since this PR was created, so I had to rework some stuff. I'm nearly finished but it still needs some tweaks on the tests.

I'm in holiday for three weeks now but I'll create a new PR based on master when I'm back. Cu...

hirschenberger added a commit to hirschenberger/substrate that referenced this pull request Aug 28, 2021
@hirschenberger
Copy link
Contributor Author

Back from honeymoon, I created a new PR #9645 based on current master.

ghost pushed a commit that referenced this pull request Sep 7, 2021
* Store the database in a role specific subdirectory

This is a cleaned up version of #8658 fixing #6880

polkadot companion: paritytech/polkadot#2923

* Disable prometheus in tests

* Also change p2p port

* Fix migration logic

* Use different identification file for rocks and parity db

Add tests for paritydb migration
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. C1-low PR touches the given topic and has a low impact on builders.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow full and light client on-disk databases to co-exist
4 participants