Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/revlog/nodemap_docket.rs @ 46128:c58c8f1d63b1
copies-rust: hide most of the comparison details inside a closure
The function that compares values needs various supporting elements that are
the same for each call. We are about to both make change to these element and
change to call sites in our upcoming work. So abstracting most of the details
will help to avoid conflict while these works happen in parallel.
Differential Revision: https://phab.mercurial-scm.org/D9426
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Sat, 21 Nov 2020 10:50:14 +0100 |
parents | 9eb07ab3f2d4 |
children | 8a4914397d02 |
rev | line source |
---|---|
46091
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
1 use memmap::Mmap; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
2 use std::convert::TryInto; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
3 use std::path::{Path, PathBuf}; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
4 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
5 use super::revlog::{mmap_open, RevlogError}; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
6 use crate::utils::strip_suffix; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
7 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
8 const ONDISK_VERSION: u8 = 1; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
9 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
10 pub(super) struct NodeMapDocket { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
11 pub data_length: usize, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
12 // TODO: keep here more of the data from `parse()` when we need it |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
13 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
14 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
15 impl NodeMapDocket { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
16 /// Return `Ok(None)` when the caller should proceed without a persistent |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
17 /// nodemap: |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
18 /// |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
19 /// * This revlog does not have a `.n` docket file (it is not generated for |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
20 /// small revlogs), or |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
21 /// * The docket has an unsupported version number (repositories created by |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
22 /// later hg, maybe that should be a requirement instead?), or |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
23 /// * The docket file points to a missing (likely deleted) data file (this |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
24 /// can happen in a rare race condition). |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
25 pub fn read_from_file( |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
26 index_path: &Path, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
27 ) -> Result<Option<(Self, Mmap)>, RevlogError> { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
28 let docket_path = index_path.with_extension("n"); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
29 let docket_bytes = match std::fs::read(&docket_path) { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
30 Err(e) if e.kind() == std::io::ErrorKind::NotFound => { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
31 return Ok(None) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
32 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
33 Err(e) => return Err(RevlogError::IoError(e)), |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
34 Ok(bytes) => bytes, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
35 }; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
36 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
37 let mut input = if let Some((&ONDISK_VERSION, rest)) = |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
38 docket_bytes.split_first() |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
39 { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
40 rest |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
41 } else { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
42 return Ok(None); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
43 }; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
44 let input = &mut input; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
45 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
46 let uid_size = read_u8(input)? as usize; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
47 let _tip_rev = read_be_u64(input)?; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
48 // TODO: do we care about overflow for 4 GB+ nodemap files on 32-bit |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
49 // systems? |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
50 let data_length = read_be_u64(input)? as usize; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
51 let _data_unused = read_be_u64(input)?; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
52 let tip_node_size = read_be_u64(input)? as usize; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
53 let uid = read_bytes(input, uid_size)?; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
54 let _tip_node = read_bytes(input, tip_node_size)?; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
55 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
56 let uid = |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
57 std::str::from_utf8(uid).map_err(|_| RevlogError::Corrupted)?; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
58 let docket = NodeMapDocket { data_length }; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
59 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
60 let data_path = rawdata_path(&docket_path, uid); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
61 // TODO: use `std::fs::read` here when the `persistent-nodemap.mmap` |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
62 // config is false? |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
63 match mmap_open(&data_path) { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
64 Ok(mmap) => { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
65 if mmap.len() >= data_length { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
66 Ok(Some((docket, mmap))) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
67 } else { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
68 Err(RevlogError::Corrupted) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
69 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
70 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
71 Err(error) => { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
72 if error.kind() == std::io::ErrorKind::NotFound { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
73 Ok(None) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
74 } else { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
75 Err(RevlogError::IoError(error)) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
76 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
77 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
78 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
79 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
80 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
81 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
82 fn read_bytes<'a>( |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
83 input: &mut &'a [u8], |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
84 count: usize, |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
85 ) -> Result<&'a [u8], RevlogError> { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
86 if let Some(start) = input.get(..count) { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
87 *input = &input[count..]; |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
88 Ok(start) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
89 } else { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
90 Err(RevlogError::Corrupted) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
91 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
92 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
93 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
94 fn read_u8<'a>(input: &mut &[u8]) -> Result<u8, RevlogError> { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
95 Ok(read_bytes(input, 1)?[0]) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
96 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
97 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
98 fn read_be_u64<'a>(input: &mut &[u8]) -> Result<u64, RevlogError> { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
99 let array = read_bytes(input, std::mem::size_of::<u64>())? |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
100 .try_into() |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
101 .unwrap(); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
102 Ok(u64::from_be_bytes(array)) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
103 } |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
104 |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
105 fn rawdata_path(docket_path: &Path, uid: &str) -> PathBuf { |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
106 let docket_name = docket_path |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
107 .file_name() |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
108 .expect("expected a base name") |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
109 .to_str() |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
110 .expect("expected an ASCII file name in the store"); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
111 let prefix = strip_suffix(docket_name, ".n.a") |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
112 .or_else(|| strip_suffix(docket_name, ".n")) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
113 .expect("expected docket path in .n or .n.a"); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
114 let name = format!("{}-{}.nd", prefix, uid); |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
115 docket_path |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
116 .parent() |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
117 .expect("expected a non-root path") |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
118 .join(name) |
9eb07ab3f2d4
rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
119 } |