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:
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(".."));
|
||||
|
Reference in New Issue
Block a user