##// END OF EJS Templates
rust-revlog: using constant in test...
rust-revlog: using constant in test Always better

File last commit:

r50527:048f829a default
r51638:3338c6ff stable
Show More
nodemap_docket.rs
108 lines | 3.6 KiB | application/rls-services+xml | RustLexer
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 use crate::errors::{HgError, HgResultExt};
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 use bytes_cast::{unaligned, BytesCast};
Simon Sapin
rust: Switch to the memmap2-rs crate...
r48767 use memmap2::Mmap;
Simon Sapin
rhg: use persistent nodemap when available...
r46706 use std::path::{Path, PathBuf};
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 use crate::vfs::Vfs;
Simon Sapin
rhg: use persistent nodemap when available...
r46706
const ONDISK_VERSION: u8 = 1;
pub(super) struct NodeMapDocket {
pub data_length: usize,
// TODO: keep here more of the data from `parse()` when we need it
}
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 #[derive(BytesCast)]
#[repr(C)]
struct DocketHeader {
uid_size: u8,
_tip_rev: unaligned::U64Be,
data_length: unaligned::U64Be,
_data_unused: unaligned::U64Be,
tip_node_size: unaligned::U64Be,
}
Simon Sapin
rhg: use persistent nodemap when available...
r46706 impl NodeMapDocket {
/// Return `Ok(None)` when the caller should proceed without a persistent
/// nodemap:
///
/// * This revlog does not have a `.n` docket file (it is not generated for
/// small revlogs), or
/// * The docket has an unsupported version number (repositories created by
/// later hg, maybe that should be a requirement instead?), or
/// * The docket file points to a missing (likely deleted) data file (this
/// can happen in a rare race condition).
pub fn read_from_file(
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 store_vfs: &Vfs,
Simon Sapin
rhg: use persistent nodemap when available...
r46706 index_path: &Path,
Simon Sapin
rust: Return HgError instead of RevlogError in revlog constructors...
r48777 ) -> Result<Option<(Self, Mmap)>, HgError> {
Simon Sapin
rhg: use persistent nodemap when available...
r46706 let docket_path = index_path.with_extension("n");
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 let docket_bytes = if let Some(bytes) =
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 store_vfs.read(&docket_path).io_not_found_as_none()?
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 {
bytes
} else {
return Ok(None);
Simon Sapin
rhg: use persistent nodemap when available...
r46706 };
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 let input = if let Some((&ONDISK_VERSION, rest)) =
Simon Sapin
rhg: use persistent nodemap when available...
r46706 docket_bytes.split_first()
{
rest
} else {
return Ok(None);
};
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 /// Treat any error as a parse error
Simon Sapin
rust: Return HgError instead of RevlogError in revlog constructors...
r48777 fn parse<T, E>(result: Result<T, E>) -> Result<T, HgError> {
result
.map_err(|_| HgError::corrupted("nodemap docket parse error"))
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 }
let (header, rest) = parse(DocketHeader::from_bytes(input))?;
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 let uid_size = header.uid_size as usize;
Simon Sapin
rhg: use persistent nodemap when available...
r46706 // TODO: do we care about overflow for 4 GB+ nodemap files on 32-bit
// systems?
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 let tip_node_size = header.tip_node_size.get() as usize;
let data_length = header.data_length.get() as usize;
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 let (uid, rest) = parse(u8::slice_from_bytes(rest, uid_size))?;
let (_tip_node, _rest) =
parse(u8::slice_from_bytes(rest, tip_node_size))?;
let uid = parse(std::str::from_utf8(uid))?;
Simon Sapin
rhg: use persistent nodemap when available...
r46706 let docket = NodeMapDocket { data_length };
let data_path = rawdata_path(&docket_path, uid);
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 // TODO: use `vfs.read()` here when the `persistent-nodemap.mmap`
Simon Sapin
rhg: use persistent nodemap when available...
r46706 // config is false?
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 if let Some(mmap) =
store_vfs.mmap_open(&data_path).io_not_found_as_none()?
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 {
if mmap.len() >= data_length {
Ok(Some((docket, mmap)))
} else {
Simon Sapin
rust: Return HgError instead of RevlogError in revlog constructors...
r48777 Err(HgError::corrupted("persistent nodemap too short"))
Simon Sapin
rhg: use persistent nodemap when available...
r46706 }
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 } else {
Simon Sapin
rhg: Don’t attempt to read persistent nodemap without .hg/requires opt-in...
r47375 // Even if .hg/requires opted in, some revlogs are deemed small
// enough to not need a persistent nodemap.
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 Ok(None)
Simon Sapin
rhg: use persistent nodemap when available...
r46706 }
}
}
fn rawdata_path(docket_path: &Path, uid: &str) -> PathBuf {
let docket_name = docket_path
.file_name()
.expect("expected a base name")
.to_str()
.expect("expected an ASCII file name in the store");
Raphaël Gomès
hg-core: remove unneeded util now that we support Rust 1.42+
r50527 let prefix = docket_name
.strip_suffix(".n.a")
.or_else(|| docket_name.strip_suffix(".n"))
Simon Sapin
rhg: use persistent nodemap when available...
r46706 .expect("expected docket path in .n or .n.a");
let name = format!("{}-{}.nd", prefix, uid);
docket_path
.parent()
.expect("expected a non-root path")
.join(name)
}