annotate rust/hg-core/src/revlog/nodemap_docket.rs @ 46578:a34cd9aa3323

copies-rust: yield both p1 and p2 copies in `ChangedFiles.actions()` Instead of filtering the relevant parent inside de ChangedFiles method, we now yield all copies information and let the caller do the filtering. Soon, the filtering will be replaced by dispatching. Differential Revision: https://phab.mercurial-scm.org/D9649
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 21 Dec 2020 10:24:16 +0100
parents 43d63979a75e
children 842f2372ced6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
1 use crate::errors::{HgError, HgResultExt};
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
2 use bytes_cast::{unaligned, BytesCast};
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
3 use memmap::Mmap;
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
4 use std::path::{Path, PathBuf};
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
5
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
6 use super::revlog::RevlogError;
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
7 use crate::repo::Repo;
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
8 use crate::utils::strip_suffix;
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 const ONDISK_VERSION: u8 = 1;
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
11
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
12 pub(super) struct NodeMapDocket {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
13 pub data_length: usize,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
14 // 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
15 }
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
16
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
17 #[derive(BytesCast)]
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
18 #[repr(C)]
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
19 struct DocketHeader {
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
20 uid_size: u8,
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
21 _tip_rev: unaligned::U64Be,
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
22 data_length: unaligned::U64Be,
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
23 _data_unused: unaligned::U64Be,
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
24 tip_node_size: unaligned::U64Be,
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
25 }
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
26
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
27 impl NodeMapDocket {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
28 /// 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
29 /// nodemap:
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
30 ///
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
31 /// * 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
32 /// small revlogs), or
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
33 /// * 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
34 /// 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
35 /// * 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
36 /// can happen in a rare race condition).
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
37 pub fn read_from_file(
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
38 repo: &Repo,
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
39 index_path: &Path,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
40 ) -> Result<Option<(Self, Mmap)>, RevlogError> {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
41 let docket_path = index_path.with_extension("n");
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
42 let docket_bytes = if let Some(bytes) =
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
43 repo.store_vfs().read(&docket_path).io_not_found_as_none()?
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
44 {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
45 bytes
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
46 } else {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
47 return Ok(None);
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
48 };
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
49
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
50 let input = if let Some((&ONDISK_VERSION, rest)) =
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
51 docket_bytes.split_first()
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
52 {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
53 rest
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
54 } else {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
55 return Ok(None);
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
56 };
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
57
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
58 /// Treat any error as a parse error
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
59 fn parse<T, E>(result: Result<T, E>) -> Result<T, RevlogError> {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
60 result.map_err(|_| {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
61 HgError::corrupted("nodemap docket parse error").into()
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
62 })
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
63 }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
64
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
65 let (header, rest) = parse(DocketHeader::from_bytes(input))?;
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
66 let uid_size = header.uid_size as usize;
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
67 // 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
68 // systems?
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
69 let tip_node_size = header.tip_node_size.get() as usize;
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
70 let data_length = header.data_length.get() as usize;
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
71 let (uid, rest) = parse(u8::slice_from_bytes(rest, uid_size))?;
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
72 let (_tip_node, _rest) =
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
73 parse(u8::slice_from_bytes(rest, tip_node_size))?;
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
74 let uid = parse(std::str::from_utf8(uid))?;
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
75 let docket = NodeMapDocket { data_length };
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 let data_path = rawdata_path(&docket_path, uid);
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
78 // TODO: use `vfs.read()` here when the `persistent-nodemap.mmap`
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
79 // config is false?
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
80 if let Some(mmap) = repo
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
81 .store_vfs()
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
82 .mmap_open(&data_path)
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
83 .io_not_found_as_none()?
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
84 {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
85 if mmap.len() >= data_length {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
86 Ok(Some((docket, mmap)))
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
87 } else {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
88 Err(HgError::corrupted("persistent nodemap too short").into())
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
89 }
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
90 } else {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
91 Ok(None)
46090
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 }
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
95
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
96 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
97 let docket_name = docket_path
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
98 .file_name()
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
99 .expect("expected a base name")
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
100 .to_str()
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
101 .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
102 let prefix = strip_suffix(docket_name, ".n.a")
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
103 .or_else(|| strip_suffix(docket_name, ".n"))
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
104 .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
105 let name = format!("{}-{}.nd", prefix, uid);
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
106 docket_path
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
107 .parent()
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
108 .expect("expected a non-root path")
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
109 .join(name)
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents:
diff changeset
110 }