Show More
@@ -49,6 +49,10 b" pub struct DirstateMap<'on_disk> {" | |||||
49 |
|
49 | |||
50 | /// How many bytes of `on_disk` are not used anymore |
|
50 | /// How many bytes of `on_disk` are not used anymore | |
51 | pub(super) unreachable_bytes: u32, |
|
51 | pub(super) unreachable_bytes: u32, | |
|
52 | ||||
|
53 | /// Size of the data used to first load this `DirstateMap`. Used in case | |||
|
54 | /// we need to write some new metadata, but no new data on disk. | |||
|
55 | pub(super) old_data_size: usize, | |||
52 | } |
|
56 | } | |
53 |
|
57 | |||
54 | /// Using a plain `HgPathBuf` of the full path from the repository root as a |
|
58 | /// Using a plain `HgPathBuf` of the full path from the repository root as a | |
@@ -429,6 +433,7 b" impl<'on_disk> DirstateMap<'on_disk> {" | |||||
429 | nodes_with_copy_source_count: 0, |
|
433 | nodes_with_copy_source_count: 0, | |
430 | ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN], |
|
434 | ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN], | |
431 | unreachable_bytes: 0, |
|
435 | unreachable_bytes: 0, | |
|
436 | old_data_size: 0, | |||
432 | } |
|
437 | } | |
433 | } |
|
438 | } | |
434 |
|
439 | |||
@@ -989,12 +994,13 b' impl OwningDirstateMap {' | |||||
989 | /// Returns new data and metadata together with whether that data should be |
|
994 | /// Returns new data and metadata together with whether that data should be | |
990 | /// appended to the existing data file whose content is at |
|
995 | /// appended to the existing data file whose content is at | |
991 | /// `map.on_disk` (true), instead of written to a new data file |
|
996 | /// `map.on_disk` (true), instead of written to a new data file | |
992 | /// (false). |
|
997 | /// (false), and the previous size of data on disk. | |
993 | #[timed] |
|
998 | #[timed] | |
994 | pub fn pack_v2( |
|
999 | pub fn pack_v2( | |
995 | &self, |
|
1000 | &self, | |
996 | can_append: bool, |
|
1001 | can_append: bool, | |
997 |
) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> |
|
1002 | ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool, usize), DirstateError> | |
|
1003 | { | |||
998 | let map = self.get_map(); |
|
1004 | let map = self.get_map(); | |
999 | on_disk::write(map, can_append) |
|
1005 | on_disk::write(map, can_append) | |
1000 | } |
|
1006 | } |
@@ -290,6 +290,7 b" pub(super) fn read<'on_disk>(" | |||||
290 | nodes_with_copy_source_count: meta.nodes_with_copy_source_count.get(), |
|
290 | nodes_with_copy_source_count: meta.nodes_with_copy_source_count.get(), | |
291 | ignore_patterns_hash: meta.ignore_patterns_hash, |
|
291 | ignore_patterns_hash: meta.ignore_patterns_hash, | |
292 | unreachable_bytes: meta.unreachable_bytes.get(), |
|
292 | unreachable_bytes: meta.unreachable_bytes.get(), | |
|
293 | old_data_size: on_disk.len(), | |||
293 | }; |
|
294 | }; | |
294 | Ok(dirstate_map) |
|
295 | Ok(dirstate_map) | |
295 | } |
|
296 | } | |
@@ -601,11 +602,11 b" pub(crate) fn for_each_tracked_path<'on_" | |||||
601 | /// Returns new data and metadata, together with whether that data should be |
|
602 | /// Returns new data and metadata, together with whether that data should be | |
602 | /// appended to the existing data file whose content is at |
|
603 | /// appended to the existing data file whose content is at | |
603 | /// `dirstate_map.on_disk` (true), instead of written to a new data file |
|
604 | /// `dirstate_map.on_disk` (true), instead of written to a new data file | |
604 | /// (false). |
|
605 | /// (false), and the previous size of data on disk. | |
605 | pub(super) fn write( |
|
606 | pub(super) fn write( | |
606 | dirstate_map: &DirstateMap, |
|
607 | dirstate_map: &DirstateMap, | |
607 | can_append: bool, |
|
608 | can_append: bool, | |
608 | ) -> Result<(Vec<u8>, TreeMetadata, bool), DirstateError> { |
|
609 | ) -> Result<(Vec<u8>, TreeMetadata, bool, usize), DirstateError> { | |
609 | let append = can_append && dirstate_map.write_should_append(); |
|
610 | let append = can_append && dirstate_map.write_should_append(); | |
610 |
|
611 | |||
611 | // This ignores the space for paths, and for nodes without an entry. |
|
612 | // This ignores the space for paths, and for nodes without an entry. | |
@@ -631,7 +632,7 b' pub(super) fn write(' | |||||
631 | unused: [0; 4], |
|
632 | unused: [0; 4], | |
632 | ignore_patterns_hash: dirstate_map.ignore_patterns_hash, |
|
633 | ignore_patterns_hash: dirstate_map.ignore_patterns_hash, | |
633 | }; |
|
634 | }; | |
634 | Ok((writer.out, meta, append)) |
|
635 | Ok((writer.out, meta, append, dirstate_map.old_data_size)) | |
635 | } |
|
636 | } | |
636 |
|
637 | |||
637 | struct Writer<'dmap, 'on_disk> { |
|
638 | struct Writer<'dmap, 'on_disk> { |
@@ -438,7 +438,8 b' impl Repo {' | |||||
438 | let uuid = self.dirstate_data_file_uuid.get_or_init(self)?; |
|
438 | let uuid = self.dirstate_data_file_uuid.get_or_init(self)?; | |
439 | let mut uuid = uuid.as_ref(); |
|
439 | let mut uuid = uuid.as_ref(); | |
440 | let can_append = uuid.is_some(); |
|
440 | let can_append = uuid.is_some(); | |
441 |
let (data, tree_metadata, append) = |
|
441 | let (data, tree_metadata, append, old_data_size) = | |
|
442 | map.pack_v2(can_append)?; | |||
442 | if !append { |
|
443 | if !append { | |
443 | uuid = None |
|
444 | uuid = None | |
444 | } |
|
445 | } | |
@@ -464,10 +465,19 b' impl Repo {' | |||||
464 | // returns `ErrorKind::AlreadyExists`? Collision chance of two |
|
465 | // returns `ErrorKind::AlreadyExists`? Collision chance of two | |
465 | // random IDs is one in 2**32 |
|
466 | // random IDs is one in 2**32 | |
466 | let mut file = options.open(&data_filename)?; |
|
467 | let mut file = options.open(&data_filename)?; | |
467 | file.write_all(&data)?; |
|
468 | if data.is_empty() { | |
468 | file.flush()?; |
|
469 | // If we're not appending anything, the data size is the | |
469 | // TODO: use https://doc.rust-lang.org/std/io/trait.Seek.html#method.stream_position when we require Rust 1.51+ |
|
470 | // same as in the previous docket. It is *not* the file | |
470 | file.seek(SeekFrom::Current(0)) |
|
471 | // length, since it could have garbage at the end. | |
|
472 | // We don't have to worry about it when we do have data | |||
|
473 | // to append since we rewrite the root node in this case. | |||
|
474 | Ok(old_data_size as u64) | |||
|
475 | } else { | |||
|
476 | file.write_all(&data)?; | |||
|
477 | file.flush()?; | |||
|
478 | // TODO: use https://doc.rust-lang.org/std/io/trait.Seek.html#method.stream_position when we require Rust 1.51+ | |||
|
479 | file.seek(SeekFrom::Current(0)) | |||
|
480 | } | |||
471 | })() |
|
481 | })() | |
472 | .when_writing_file(&data_filename)?; |
|
482 | .when_writing_file(&data_filename)?; | |
473 | DirstateDocket::serialize( |
|
483 | DirstateDocket::serialize( |
@@ -211,7 +211,7 b' py_class!(pub class DirstateMap |py| {' | |||||
211 | let inner = self.inner(py).borrow(); |
|
211 | let inner = self.inner(py).borrow(); | |
212 | let result = inner.pack_v2(can_append); |
|
212 | let result = inner.pack_v2(can_append); | |
213 | match result { |
|
213 | match result { | |
214 | Ok((packed, tree_metadata, append)) => { |
|
214 | Ok((packed, tree_metadata, append, _old_data_size)) => { | |
215 | let packed = PyBytes::new(py, &packed); |
|
215 | let packed = PyBytes::new(py, &packed); | |
216 | let tree_metadata = PyBytes::new(py, tree_metadata.as_bytes()); |
|
216 | let tree_metadata = PyBytes::new(py, tree_metadata.as_bytes()); | |
217 | let tuple = (packed, tree_metadata, append); |
|
217 | let tuple = (packed, tree_metadata, append); |
General Comments 0
You need to be logged in to leave comments.
Login now