referrerpolicy=no-referrer-when-downgrade

polkadot_service/parachains_db/
mod.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14//! A `RocksDB` instance for storing parachain data; availability data, and approvals.
15
16#[cfg(feature = "full-node")]
17use {
18	polkadot_node_subsystem_util::database::Database, std::io, std::path::PathBuf, std::sync::Arc,
19};
20
21#[cfg(feature = "full-node")]
22mod upgrade;
23
24const LOG_TARGET: &str = "parachain::db";
25
26/// Column configuration per version.
27#[cfg(any(test, feature = "full-node"))]
28pub(crate) mod columns {
29	pub mod v0 {
30		pub const NUM_COLUMNS: u32 = 3;
31	}
32
33	pub mod v1 {
34		pub const NUM_COLUMNS: u32 = 5;
35	}
36
37	pub mod v2 {
38		pub const NUM_COLUMNS: u32 = 6;
39
40		#[cfg(test)]
41		pub const COL_SESSION_WINDOW_DATA: u32 = 5;
42	}
43
44	// Version 4 only changed structures in approval voting, so we can re-export the v4 definitions.
45	pub mod v3 {
46		pub use super::v4::{NUM_COLUMNS, ORDERED_COL};
47	}
48
49	pub mod v4 {
50		pub const NUM_COLUMNS: u32 = 5;
51		pub const COL_AVAILABILITY_DATA: u32 = 0;
52		pub const COL_AVAILABILITY_META: u32 = 1;
53		pub const COL_APPROVAL_DATA: u32 = 2;
54		pub const COL_CHAIN_SELECTION_DATA: u32 = 3;
55		pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4;
56
57		pub const ORDERED_COL: &[u32] =
58			&[COL_AVAILABILITY_META, COL_CHAIN_SELECTION_DATA, COL_DISPUTE_COORDINATOR_DATA];
59	}
60}
61
62/// Columns used by different subsystems.
63#[cfg(any(test, feature = "full-node"))]
64#[derive(Debug, Clone)]
65pub struct ColumnsConfig {
66	/// The column used by the av-store for data.
67	pub col_availability_data: u32,
68	/// The column used by the av-store for meta information.
69	pub col_availability_meta: u32,
70	/// The column used by approval voting for data.
71	pub col_approval_data: u32,
72	/// The column used by chain selection for data.
73	pub col_chain_selection_data: u32,
74	/// The column used by dispute coordinator for data.
75	pub col_dispute_coordinator_data: u32,
76}
77
78/// The real columns used by the parachains DB.
79#[cfg(any(test, feature = "full-node"))]
80pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig {
81	col_availability_data: columns::v4::COL_AVAILABILITY_DATA,
82	col_availability_meta: columns::v4::COL_AVAILABILITY_META,
83	col_approval_data: columns::v4::COL_APPROVAL_DATA,
84	col_chain_selection_data: columns::v4::COL_CHAIN_SELECTION_DATA,
85	col_dispute_coordinator_data: columns::v4::COL_DISPUTE_COORDINATOR_DATA,
86};
87
88#[derive(PartialEq, Copy, Clone)]
89pub(crate) enum DatabaseKind {
90	ParityDB,
91	RocksDB,
92}
93
94/// The cache size for each column, in megabytes.
95#[derive(Debug, Clone)]
96pub struct CacheSizes {
97	/// Cache used by availability data.
98	pub availability_data: usize,
99	/// Cache used by availability meta.
100	pub availability_meta: usize,
101	/// Cache used by approval data.
102	pub approval_data: usize,
103}
104
105impl Default for CacheSizes {
106	fn default() -> Self {
107		CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 }
108	}
109}
110
111#[cfg(feature = "full-node")]
112pub(crate) fn other_io_error(err: String) -> io::Error {
113	io::Error::new(io::ErrorKind::Other, err)
114}
115
116/// Open the database on disk, creating it if it doesn't exist.
117#[cfg(feature = "full-node")]
118pub fn open_creating_rocksdb(
119	root: PathBuf,
120	cache_sizes: CacheSizes,
121) -> io::Result<Arc<dyn Database>> {
122	use kvdb_rocksdb::{Database, DatabaseConfig};
123
124	let path = root.join("parachains").join("db");
125
126	let mut db_config = DatabaseConfig::with_columns(columns::v4::NUM_COLUMNS);
127
128	let _ = db_config
129		.memory_budget
130		.insert(columns::v4::COL_AVAILABILITY_DATA, cache_sizes.availability_data);
131	let _ = db_config
132		.memory_budget
133		.insert(columns::v4::COL_AVAILABILITY_META, cache_sizes.availability_meta);
134	let _ = db_config
135		.memory_budget
136		.insert(columns::v4::COL_APPROVAL_DATA, cache_sizes.approval_data);
137
138	let path_str = path
139		.to_str()
140		.ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?;
141
142	std::fs::create_dir_all(&path_str)?;
143	upgrade::try_upgrade_db(&path, DatabaseKind::RocksDB, upgrade::CURRENT_VERSION)?;
144	let db = Database::open(&db_config, &path_str)?;
145	let db = polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter::new(
146		db,
147		columns::v4::ORDERED_COL,
148	);
149
150	Ok(Arc::new(db))
151}
152
153/// Open a parity db database.
154#[cfg(feature = "full-node")]
155pub fn open_creating_paritydb(
156	root: PathBuf,
157	_cache_sizes: CacheSizes,
158) -> io::Result<Arc<dyn Database>> {
159	let path = root.join("parachains");
160	let path_str = path
161		.to_str()
162		.ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?;
163
164	std::fs::create_dir_all(&path_str)?;
165	upgrade::try_upgrade_db(&path, DatabaseKind::ParityDB, upgrade::CURRENT_VERSION)?;
166
167	let db = parity_db::Db::open_or_create(&upgrade::paritydb_version_3_config(&path))
168		.map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))?;
169
170	let db = polkadot_node_subsystem_util::database::paritydb_impl::DbAdapter::new(
171		db,
172		columns::v4::ORDERED_COL,
173	);
174	Ok(Arc::new(db))
175}