Add Incremental Snapshot support to RPC (#19559)

#### Problem

There's no way to get incremental snapshot information from RPC.

#### Summary of Changes

- Add new RPC method, `getHighestSnapshotSlot` that returns a `SnapshotSlotInfo`, which contains both the highest full snapshot slot, and the highest incremental snapshot slot _based on_ the full snapshot.
- Deprecate old RPC method, `getSnapshotSlot`
- Update API docs

Fixes #19579
This commit is contained in:
Brooks Prumo
2021-09-02 15:25:42 -05:00
committed by GitHub
parent f4f14c42bb
commit 8ac94b2cf4
9 changed files with 227 additions and 78 deletions

View File

@ -2276,8 +2276,8 @@ pub mod rpc_minimal {
commitment: Option<CommitmentConfig>,
) -> Result<u64>;
#[rpc(meta, name = "getSnapshotSlot")]
fn get_snapshot_slot(&self, meta: Self::Metadata) -> Result<Slot>;
#[rpc(meta, name = "getHighestSnapshotSlot")]
fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo>;
#[rpc(meta, name = "getTransactionCount")]
fn get_transaction_count(
@ -2373,16 +2373,31 @@ pub mod rpc_minimal {
Ok(meta.get_block_height(commitment))
}
fn get_snapshot_slot(&self, meta: Self::Metadata) -> Result<Slot> {
debug!("get_snapshot_slot rpc request received");
fn get_highest_snapshot_slot(&self, meta: Self::Metadata) -> Result<RpcSnapshotSlotInfo> {
debug!("get_highest_snapshot_slot rpc request received");
meta.snapshot_config
.and_then(|snapshot_config| {
snapshot_utils::get_highest_full_snapshot_archive_slot(
&snapshot_config.snapshot_archives_dir,
)
})
.ok_or_else(|| RpcCustomError::NoSnapshot.into())
if meta.snapshot_config.is_none() {
return Err(RpcCustomError::NoSnapshot.into());
}
let snapshot_archives_dir = meta
.snapshot_config
.map(|snapshot_config| snapshot_config.snapshot_archives_dir)
.unwrap();
let full_snapshot_slot =
snapshot_utils::get_highest_full_snapshot_archive_slot(&snapshot_archives_dir)
.ok_or(RpcCustomError::NoSnapshot)?;
let incremental_snapshot_slot =
snapshot_utils::get_highest_incremental_snapshot_archive_slot(
&snapshot_archives_dir,
full_snapshot_slot,
);
Ok(RpcSnapshotSlotInfo {
full: full_snapshot_slot,
incremental: incremental_snapshot_slot,
})
}
fn get_transaction_count(
@ -3686,6 +3701,9 @@ pub mod rpc_deprecated_v1_8 {
&self,
meta: Self::Metadata,
) -> Result<RpcResponse<RpcFeeRateGovernor>>;
#[rpc(meta, name = "getSnapshotSlot")]
fn get_snapshot_slot(&self, meta: Self::Metadata) -> Result<Slot>;
}
pub struct DeprecatedV1_8Impl;
@ -3729,6 +3747,18 @@ pub mod rpc_deprecated_v1_8 {
debug!("get_fee_rate_governor rpc request received");
Ok(meta.get_fee_rate_governor())
}
fn get_snapshot_slot(&self, meta: Self::Metadata) -> Result<Slot> {
debug!("get_snapshot_slot rpc request received");
meta.snapshot_config
.and_then(|snapshot_config| {
snapshot_utils::get_highest_full_snapshot_archive_slot(
&snapshot_config.snapshot_archives_dir,
)
})
.ok_or_else(|| RpcCustomError::NoSnapshot.into())
}
}
}

View File

@ -59,7 +59,8 @@ pub struct JsonRpcService {
struct RpcRequestMiddleware {
ledger_path: PathBuf,
snapshot_archive_path_regex: Regex,
full_snapshot_archive_path_regex: Regex,
incremental_snapshot_archive_path_regex: Regex,
snapshot_config: Option<SnapshotConfig>,
bank_forks: Arc<RwLock<BankForks>>,
health: Arc<RpcHealth>,
@ -74,8 +75,12 @@ impl RpcRequestMiddleware {
) -> Self {
Self {
ledger_path,
snapshot_archive_path_regex: Regex::new(
r"^/snapshot-\d+-[[:alnum:]]+\.(tar|tar\.bz2|tar\.zst|tar\.gz)$",
full_snapshot_archive_path_regex: Regex::new(
snapshot_utils::FULL_SNAPSHOT_ARCHIVE_FILENAME_REGEX,
)
.unwrap(),
incremental_snapshot_archive_path_regex: Regex::new(
snapshot_utils::INCREMENTAL_SNAPSHOT_ARCHIVE_FILENAME_REGEX,
)
.unwrap(),
snapshot_config,
@ -108,16 +113,23 @@ impl RpcRequestMiddleware {
}
fn is_file_get_path(&self, path: &str) -> bool {
match path {
DEFAULT_GENESIS_DOWNLOAD_PATH => true,
_ => {
if self.snapshot_config.is_some() {
self.snapshot_archive_path_regex.is_match(path)
} else {
false
}
}
if path == DEFAULT_GENESIS_DOWNLOAD_PATH {
return true;
}
if self.snapshot_config.is_none() {
return false;
}
let starting_character = '/';
if !path.starts_with(starting_character) {
return false;
}
let path = path.trim_start_matches(starting_character);
self.full_snapshot_archive_path_regex.is_match(path)
|| self.incremental_snapshot_archive_path_regex.is_match(path)
}
#[cfg(unix)]
@ -497,6 +509,7 @@ mod tests {
},
},
solana_sdk::{
clock::Slot,
genesis_config::{ClusterType, DEFAULT_GENESIS_ARCHIVE},
signature::Signer,
signer::keypair::Keypair,
@ -602,8 +615,8 @@ mod tests {
let rrm_with_snapshot_config = RpcRequestMiddleware::new(
PathBuf::from("/"),
Some(SnapshotConfig {
full_snapshot_archive_interval_slots: 0,
incremental_snapshot_archive_interval_slots: u64::MAX,
full_snapshot_archive_interval_slots: Slot::MAX,
incremental_snapshot_archive_interval_slots: Slot::MAX,
snapshot_archives_dir: PathBuf::from("/"),
bank_snapshots_dir: PathBuf::from("/"),
archive_format: ArchiveFormat::TarBzip2,
@ -622,6 +635,10 @@ mod tests {
assert!(!rrm.is_file_get_path(
"/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(!rrm.is_file_get_path(
"/incremental-snapshot-100-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(rrm_with_snapshot_config.is_file_get_path(
"/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
@ -633,11 +650,32 @@ mod tests {
assert!(rrm_with_snapshot_config
.is_file_get_path("/snapshot-100-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar"));
assert!(rrm_with_snapshot_config.is_file_get_path(
"/incremental-snapshot-100-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(rrm_with_snapshot_config.is_file_get_path(
"/incremental-snapshot-100-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.zst"
));
assert!(rrm_with_snapshot_config.is_file_get_path(
"/incremental-snapshot-100-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.gz"
));
assert!(rrm_with_snapshot_config.is_file_get_path(
"/incremental-snapshot-100-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar"
));
assert!(!rrm_with_snapshot_config.is_file_get_path(
"/snapshot-notaslotnumber-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(!rrm_with_snapshot_config.is_file_get_path(
"/incremental-snapshot-notaslotnumber-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(!rrm_with_snapshot_config.is_file_get_path(
"/incremental-snapshot-100-notaslotnumber-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.bz2"
));
assert!(!rrm_with_snapshot_config.is_file_get_path("../../../test/snapshot-123-xxx.tar"));
assert!(!rrm_with_snapshot_config
.is_file_get_path("../../../test/incremental-snapshot-123-456-xxx.tar"));
assert!(!rrm.is_file_get_path("/"));
assert!(!rrm.is_file_get_path(".."));