comparison rust/hg-core/src/dirstate_tree/on_disk.rs @ 47476:f23eafb036af

dirstate-v2: Use 32-bit integers instead of 64-bit for offsets This saves 12 bytes per node. (Nodes representing files or directories.) These are offsets to other parts of the file. This would only be a limitation for a `.hg/dirstate` file larger than 4 GiB, which would only happen for a repository with dozens of millions of files and directories. Differential Revision: https://phab.mercurial-scm.org/D10920
author Simon Sapin <simon.sapin@octobus.net>
date Mon, 28 Jun 2021 15:41:50 +0200
parents 94e38822d395
children ca8121d26732
comparison
equal deleted inserted replaced
47475:94e38822d395 47476:f23eafb036af
15 use crate::utils::hg_path::HgPath; 15 use crate::utils::hg_path::HgPath;
16 use crate::DirstateEntry; 16 use crate::DirstateEntry;
17 use crate::DirstateError; 17 use crate::DirstateError;
18 use crate::DirstateParents; 18 use crate::DirstateParents;
19 use crate::EntryState; 19 use crate::EntryState;
20 use bytes_cast::unaligned::{I32Be, I64Be, U32Be, U64Be}; 20 use bytes_cast::unaligned::{I32Be, I64Be, U32Be};
21 use bytes_cast::BytesCast; 21 use bytes_cast::BytesCast;
22 use std::borrow::Cow; 22 use std::borrow::Cow;
23 use std::convert::TryFrom; 23 use std::convert::TryFrom;
24 use std::time::{Duration, SystemTime, UNIX_EPOCH}; 24 use std::time::{Duration, SystemTime, UNIX_EPOCH};
25 25
133 nanoseconds: U32Be, 133 nanoseconds: U32Be,
134 } 134 }
135 135
136 /// Counted in bytes from the start of the file 136 /// Counted in bytes from the start of the file
137 /// 137 ///
138 /// NOTE: If we decide to never support `.hg/dirstate` files larger than 4 GiB 138 /// NOTE: not supporting `.hg/dirstate` files larger than 4 GiB.
139 /// we could save space by using `U32Be` instead. 139 type Offset = U32Be;
140 type Offset = U64Be;
141 140
142 /// Counted in number of items 141 /// Counted in number of items
143 /// 142 ///
144 /// NOTE: not supporting directories with more than 4 billion direct children, 143 /// NOTE: not supporting directories with more than 4 billion direct children,
145 /// or filenames more than 4 GiB. 144 /// or filenames more than 4 GiB.
170 /// Either nothing if `start == 0`, or a `HgPath` of `len` bytes 169 /// Either nothing if `start == 0`, or a `HgPath` of `len` bytes
171 type OptPathSlice = Slice; 170 type OptPathSlice = Slice;
172 171
173 /// Make sure that size-affecting changes are made knowingly 172 /// Make sure that size-affecting changes are made knowingly
174 fn _static_assert_size_of() { 173 fn _static_assert_size_of() {
175 let _ = std::mem::transmute::<Header, [u8; 92]>; 174 let _ = std::mem::transmute::<Header, [u8; 88]>;
176 let _ = std::mem::transmute::<Node, [u8; 57]>; 175 let _ = std::mem::transmute::<Node, [u8; 45]>;
177 } 176 }
178 177
179 /// Unexpected file format found in `.hg/dirstate` with the "v2" format. 178 /// Unexpected file format found in `.hg/dirstate` with the "v2" format.
180 /// 179 ///
181 /// This should only happen if Mercurial is buggy or a repository is corrupted. 180 /// This should only happen if Mercurial is buggy or a repository is corrupted.
587 586
588 fn write_slice<T>(slice: &[T], out: &mut Vec<u8>) -> Slice 587 fn write_slice<T>(slice: &[T], out: &mut Vec<u8>) -> Slice
589 where 588 where
590 T: BytesCast, 589 T: BytesCast,
591 { 590 {
592 let start = u64::try_from(out.len()) 591 let start = u32::try_from(out.len())
593 // Could only panic on a 128-bit CPU with a dirstate over 16 EiB 592 // Could only panic for a dirstate file larger than 4 GiB
594 .expect("dirstate-v2 offset overflow") 593 .expect("dirstate-v2 offset overflow")
595 .into(); 594 .into();
596 let len = u32::try_from(slice.len()) 595 let len = u32::try_from(slice.len())
597 // Could only panic for paths over 4 GiB or nodes with over 4 billions 596 // Could only panic for paths over 4 GiB or nodes with over 4 billions
598 // child nodes 597 // child nodes