##// END OF EJS Templates
dirstate-v2: Reuse existing nodes when appending to a data file...
Simon Sapin -
r48479:731286dc default
parent child Browse files
Show More
@@ -590,8 +590,18 b" impl Writer<'_, '_> {"
590 &mut self,
590 &mut self,
591 nodes: dirstate_map::ChildNodesRef,
591 nodes: dirstate_map::ChildNodesRef,
592 ) -> Result<ChildNodes, DirstateError> {
592 ) -> Result<ChildNodes, DirstateError> {
593 // `dirstate_map::ChildNodes` is a `HashMap` with undefined iteration
593 // Reuse already-written nodes if possible
594 // order. Sort to enable binary search in the written file.
594 if self.append {
595 if let dirstate_map::ChildNodesRef::OnDisk(nodes_slice) = nodes {
596 let start = self.offset_of(nodes_slice);
597 let len = child_nodes_len_from_usize(nodes_slice.len());
598 return Ok(ChildNodes { start, len });
599 }
600 }
601
602 // `dirstate_map::ChildNodes::InMemory` contains a `HashMap` which has
603 // undefined iteration order. Sort to enable binary search in the
604 // written file.
595 let nodes = nodes.sorted();
605 let nodes = nodes.sorted();
596 let nodes_len = nodes.len();
606 let nodes_len = nodes.len();
597
607
@@ -664,32 +674,65 b" impl Writer<'_, '_> {"
664 // … so we can write them contiguously, after writing everything else
674 // … so we can write them contiguously, after writing everything else
665 // they refer to.
675 // they refer to.
666 let start = self.current_offset();
676 let start = self.current_offset();
667 let len = u32::try_from(nodes_len)
677 let len = child_nodes_len_from_usize(nodes_len);
668 // Could only panic with over 4 billion nodes
669 .expect("dirstate-v2 path length overflow")
670 .into();
671 self.out.extend(on_disk_nodes.as_bytes());
678 self.out.extend(on_disk_nodes.as_bytes());
672 Ok(ChildNodes { start, len })
679 Ok(ChildNodes { start, len })
673 }
680 }
674
681
682 /// Takes a slice of items within `on_disk` and returns its offset for the
683 /// start of `on_disk`.
684 ///
685 /// Panics if the given slice is not within `on_disk`.
686 fn offset_of<T>(&self, slice: &[T]) -> Offset
687 where
688 T: BytesCast,
689 {
690 fn address_range(slice: &[u8]) -> std::ops::RangeInclusive<usize> {
691 let start = slice.as_ptr() as usize;
692 let end = start + slice.len();
693 start..=end
694 }
695 let slice_addresses = address_range(slice.as_bytes());
696 let on_disk_addresses = address_range(self.dirstate_map.on_disk);
697 assert!(on_disk_addresses.contains(slice_addresses.start()));
698 assert!(on_disk_addresses.contains(slice_addresses.end()));
699 let offset = slice_addresses.start() - on_disk_addresses.start();
700 offset_from_usize(offset)
701 }
702
675 fn current_offset(&mut self) -> Offset {
703 fn current_offset(&mut self) -> Offset {
676 let mut offset = self.out.len();
704 let mut offset = self.out.len();
677 if self.append {
705 if self.append {
678 offset += self.dirstate_map.on_disk.len()
706 offset += self.dirstate_map.on_disk.len()
679 }
707 }
680 u32::try_from(offset)
708 offset_from_usize(offset)
681 // Could only panic for a dirstate file larger than 4 GiB
682 .expect("dirstate-v2 offset overflow")
683 .into()
684 }
709 }
685
710
686 fn write_path(&mut self, slice: &[u8]) -> PathSlice {
711 fn write_path(&mut self, slice: &[u8]) -> PathSlice {
687 let start = self.current_offset();
712 let start = self.current_offset();
688 let len = u16::try_from(slice.len())
713 let len = path_len_from_usize(slice.len());
689 // Could only panic for paths over 64 KiB
690 .expect("dirstate-v2 path length overflow")
691 .into();
692 self.out.extend(slice.as_bytes());
714 self.out.extend(slice.as_bytes());
693 PathSlice { start, len }
715 PathSlice { start, len }
694 }
716 }
695 }
717 }
718
719 fn offset_from_usize(x: usize) -> Offset {
720 u32::try_from(x)
721 // Could only panic for a dirstate file larger than 4 GiB
722 .expect("dirstate-v2 offset overflow")
723 .into()
724 }
725
726 fn child_nodes_len_from_usize(x: usize) -> Size {
727 u32::try_from(x)
728 // Could only panic with over 4 billion nodes
729 .expect("dirstate-v2 slice length overflow")
730 .into()
731 }
732
733 fn path_len_from_usize(x: usize) -> PathSize {
734 u16::try_from(x)
735 // Could only panic for paths over 64 KiB
736 .expect("dirstate-v2 path length overflow")
737 .into()
738 }
General Comments 0
You need to be logged in to leave comments. Login now