Patchwork D8098: rust-nodemap: a method for full invalidation

login
register
mail settings
Submitter phabricator
Date Feb. 8, 2020, 5:46 p.m.
Message ID <differential-rev-PHID-DREV-pdpnu6cwjp5snkgonp65-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/45052/
State New
Headers show

Comments

phabricator - Feb. 8, 2020, 5:46 p.m.
marmoute created this revision.
Herald added subscribers: mercurial-devel, kevincox.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This will be used for exceptional operations,
  such as a `__delitem__` on the `MixedIndex` with
  Rust nodemap.
  
  In principle, `NodeTree` should also be able to forget
  an entry in an efficient way, by accepting to insert
  `Element::None` instead of only `Element::Rev(r)`,
  but that seems really overkill at this point. We need
  to support exceptional operations such as `__delitem__`,
  only for completeness of the revlog index as seen from
  Python. The Python callers don't seem to even really
  need it, deciding to drop the nodemap inconditionnally at
  at higher level when calling `hg strip`. Also, `hg strip`
  is very costly for reasons that are unrelated to nodemap
  aspects.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D8098

AFFECTED FILES
  rust/hg-core/src/revlog/nodemap.rs

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: kevincox, mercurial-devel
phabricator - Feb. 24, 2020, 10:56 a.m.
kevincox added inline comments.
kevincox accepted this revision.

INLINE COMMENTS

> nodemap.rs:577
> +    /// immutable part.
> +    pub fn invalidate_all(&mut self) -> () {
> +        self.root = Block::new();

`-> ()` is unnecessary.

> nodemap.rs:580
> +        self.growable = Vec::new();
> +        self.masked_inner_blocks = self.readonly.len()
> +    }

End the line with a `;`.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8098/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8098

To: marmoute, #hg-reviewers, kevincox
Cc: kevincox, mercurial-devel

Patch

diff --git a/rust/hg-core/src/revlog/nodemap.rs b/rust/hg-core/src/revlog/nodemap.rs
--- a/rust/hg-core/src/revlog/nodemap.rs
+++ b/rust/hg-core/src/revlog/nodemap.rs
@@ -544,11 +544,25 @@ 
         Ok(())
     }
 
+    /// Make the whole `NodeTree` logically empty, without touching the
+    /// immutable part.
+    pub fn invalidate_all(&mut self) -> () {
+        self.root = Block::new();
+        self.growable = Vec::new();
+        self.masked_inner_blocks = self.readonly.len()
+    }
+
     /// Return the number of blocks in the readonly part that are currently
     /// masked in the mutable part.
     ///
     /// The `NodeTree` structure has no efficient way to know how many blocks
     /// are already unreachable in the readonly part.
+    ///
+    /// After a call to `invalidate_all()`, the returned number can be actually
+    /// bigger than the whole readonly part, a conventional way to mean that
+    /// all the readonly blocks have been masked. This is what is really
+    /// useful to the caller and does not require to know how many were
+    /// actually unreachable to begin with.
     pub fn masked_readonly_blocks(&self) -> usize {
         if let Some(readonly_root) = self.readonly.last() {
             if readonly_root == &self.root {
@@ -1025,6 +1039,27 @@ 
     }
 
     #[test]
+    fn test_invalidate_all() -> Result<(), NodeMapError> {
+        let mut idx = TestNtIndex::new();
+        idx.insert(0, "1234")?;
+        idx.insert(1, "1235")?;
+        idx.insert(2, "131")?;
+        idx.insert(3, "cafe")?;
+        let mut idx = idx.commit();
+
+        idx.nt.invalidate_all();
+
+        assert_eq!(idx.find_hex("1234")?, None);
+        assert_eq!(idx.find_hex("1235")?, None);
+        assert_eq!(idx.find_hex("131")?, None);
+        assert_eq!(idx.find_hex("cafe")?, None);
+        // all the readonly blocks have been masked, this is the
+        // conventional expected response
+        assert_eq!(idx.nt.masked_readonly_blocks(), idx.nt.readonly.len() + 1);
+        Ok(())
+    }
+
+    #[test]
     fn test_into_added_empty() {
         assert!(sample_nodetree().into_readonly_and_added().1.is_empty());
         assert!(sample_nodetree()