##// END OF EJS Templates
rust-nodemap: special case for prefixes of NULL_NODE...
Georges Racinet -
r44871:00d251d3 default
parent child Browse files
Show More
@@ -1,936 +1,960 b''
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net>
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net>
2 // and Mercurial contributors
2 // and Mercurial contributors
3 //
3 //
4 // This software may be used and distributed according to the terms of the
4 // This software may be used and distributed according to the terms of the
5 // GNU General Public License version 2 or any later version.
5 // GNU General Public License version 2 or any later version.
6 //! Indexing facilities for fast retrieval of `Revision` from `Node`
6 //! Indexing facilities for fast retrieval of `Revision` from `Node`
7 //!
7 //!
8 //! This provides a variation on the 16-ary radix tree that is
8 //! This provides a variation on the 16-ary radix tree that is
9 //! provided as "nodetree" in revlog.c, ready for append-only persistence
9 //! provided as "nodetree" in revlog.c, ready for append-only persistence
10 //! on disk.
10 //! on disk.
11 //!
11 //!
12 //! Following existing implicit conventions, the "nodemap" terminology
12 //! Following existing implicit conventions, the "nodemap" terminology
13 //! is used in a more abstract context.
13 //! is used in a more abstract context.
14
14
15 use super::{
15 use super::{
16 Node, NodeError, NodePrefix, NodePrefixRef, Revision, RevlogIndex,
16 node::NULL_NODE, Node, NodeError, NodePrefix, NodePrefixRef, Revision,
17 RevlogIndex, NULL_REVISION,
17 };
18 };
18
19
19 use std::fmt;
20 use std::fmt;
20 use std::mem;
21 use std::mem;
21 use std::ops::Deref;
22 use std::ops::Deref;
22 use std::ops::Index;
23 use std::ops::Index;
23 use std::slice;
24 use std::slice;
24
25
25 #[derive(Debug, PartialEq)]
26 #[derive(Debug, PartialEq)]
26 pub enum NodeMapError {
27 pub enum NodeMapError {
27 MultipleResults,
28 MultipleResults,
28 InvalidNodePrefix(NodeError),
29 InvalidNodePrefix(NodeError),
29 /// A `Revision` stored in the nodemap could not be found in the index
30 /// A `Revision` stored in the nodemap could not be found in the index
30 RevisionNotInIndex(Revision),
31 RevisionNotInIndex(Revision),
31 }
32 }
32
33
33 impl From<NodeError> for NodeMapError {
34 impl From<NodeError> for NodeMapError {
34 fn from(err: NodeError) -> Self {
35 fn from(err: NodeError) -> Self {
35 NodeMapError::InvalidNodePrefix(err)
36 NodeMapError::InvalidNodePrefix(err)
36 }
37 }
37 }
38 }
38
39
39 /// Mapping system from Mercurial nodes to revision numbers.
40 /// Mapping system from Mercurial nodes to revision numbers.
40 ///
41 ///
41 /// ## `RevlogIndex` and `NodeMap`
42 /// ## `RevlogIndex` and `NodeMap`
42 ///
43 ///
43 /// One way to think about their relationship is that
44 /// One way to think about their relationship is that
44 /// the `NodeMap` is a prefix-oriented reverse index of the `Node` information
45 /// the `NodeMap` is a prefix-oriented reverse index of the `Node` information
45 /// carried by a [`RevlogIndex`].
46 /// carried by a [`RevlogIndex`].
46 ///
47 ///
47 /// Many of the methods in this trait take a `RevlogIndex` argument
48 /// Many of the methods in this trait take a `RevlogIndex` argument
48 /// which is used for validation of their results. This index must naturally
49 /// which is used for validation of their results. This index must naturally
49 /// be the one the `NodeMap` is about, and it must be consistent.
50 /// be the one the `NodeMap` is about, and it must be consistent.
50 ///
51 ///
51 /// Notably, the `NodeMap` must not store
52 /// Notably, the `NodeMap` must not store
52 /// information about more `Revision` values than there are in the index.
53 /// information about more `Revision` values than there are in the index.
53 /// In these methods, an encountered `Revision` is not in the index, a
54 /// In these methods, an encountered `Revision` is not in the index, a
54 /// [`RevisionNotInIndex`] error is returned.
55 /// [`RevisionNotInIndex`] error is returned.
55 ///
56 ///
56 /// In insert operations, the rule is thus that the `NodeMap` must always
57 /// In insert operations, the rule is thus that the `NodeMap` must always
57 /// be updated after the `RevlogIndex`
58 /// be updated after the `RevlogIndex`
58 /// be updated first, and the `NodeMap` second.
59 /// be updated first, and the `NodeMap` second.
59 ///
60 ///
60 /// [`RevisionNotInIndex`]: enum.NodeMapError.html#variant.RevisionNotInIndex
61 /// [`RevisionNotInIndex`]: enum.NodeMapError.html#variant.RevisionNotInIndex
61 /// [`RevlogIndex`]: ../trait.RevlogIndex.html
62 /// [`RevlogIndex`]: ../trait.RevlogIndex.html
62 pub trait NodeMap {
63 pub trait NodeMap {
63 /// Find the unique `Revision` having the given `Node`
64 /// Find the unique `Revision` having the given `Node`
64 ///
65 ///
65 /// If no Revision matches the given `Node`, `Ok(None)` is returned.
66 /// If no Revision matches the given `Node`, `Ok(None)` is returned.
66 fn find_node(
67 fn find_node(
67 &self,
68 &self,
68 index: &impl RevlogIndex,
69 index: &impl RevlogIndex,
69 node: &Node,
70 node: &Node,
70 ) -> Result<Option<Revision>, NodeMapError> {
71 ) -> Result<Option<Revision>, NodeMapError> {
71 self.find_bin(index, node.into())
72 self.find_bin(index, node.into())
72 }
73 }
73
74
74 /// Find the unique Revision whose `Node` starts with a given binary prefix
75 /// Find the unique Revision whose `Node` starts with a given binary prefix
75 ///
76 ///
76 /// If no Revision matches the given prefix, `Ok(None)` is returned.
77 /// If no Revision matches the given prefix, `Ok(None)` is returned.
77 ///
78 ///
78 /// If several Revisions match the given prefix, a [`MultipleResults`]
79 /// If several Revisions match the given prefix, a [`MultipleResults`]
79 /// error is returned.
80 /// error is returned.
80 fn find_bin<'a>(
81 fn find_bin<'a>(
81 &self,
82 &self,
82 idx: &impl RevlogIndex,
83 idx: &impl RevlogIndex,
83 prefix: NodePrefixRef<'a>,
84 prefix: NodePrefixRef<'a>,
84 ) -> Result<Option<Revision>, NodeMapError>;
85 ) -> Result<Option<Revision>, NodeMapError>;
85
86
86 /// Find the unique Revision whose `Node` hexadecimal string representation
87 /// Find the unique Revision whose `Node` hexadecimal string representation
87 /// starts with a given prefix
88 /// starts with a given prefix
88 ///
89 ///
89 /// If no Revision matches the given prefix, `Ok(None)` is returned.
90 /// If no Revision matches the given prefix, `Ok(None)` is returned.
90 ///
91 ///
91 /// If several Revisions match the given prefix, a [`MultipleResults`]
92 /// If several Revisions match the given prefix, a [`MultipleResults`]
92 /// error is returned.
93 /// error is returned.
93 fn find_hex(
94 fn find_hex(
94 &self,
95 &self,
95 idx: &impl RevlogIndex,
96 idx: &impl RevlogIndex,
96 prefix: &str,
97 prefix: &str,
97 ) -> Result<Option<Revision>, NodeMapError> {
98 ) -> Result<Option<Revision>, NodeMapError> {
98 self.find_bin(idx, NodePrefix::from_hex(prefix)?.borrow())
99 self.find_bin(idx, NodePrefix::from_hex(prefix)?.borrow())
99 }
100 }
100 }
101 }
101
102
102 pub trait MutableNodeMap: NodeMap {
103 pub trait MutableNodeMap: NodeMap {
103 fn insert<I: RevlogIndex>(
104 fn insert<I: RevlogIndex>(
104 &mut self,
105 &mut self,
105 index: &I,
106 index: &I,
106 node: &Node,
107 node: &Node,
107 rev: Revision,
108 rev: Revision,
108 ) -> Result<(), NodeMapError>;
109 ) -> Result<(), NodeMapError>;
109 }
110 }
110
111
111 /// Low level NodeTree [`Blocks`] elements
112 /// Low level NodeTree [`Blocks`] elements
112 ///
113 ///
113 /// These are exactly as for instance on persistent storage.
114 /// These are exactly as for instance on persistent storage.
114 type RawElement = i32;
115 type RawElement = i32;
115
116
116 /// High level representation of values in NodeTree
117 /// High level representation of values in NodeTree
117 /// [`Blocks`](struct.Block.html)
118 /// [`Blocks`](struct.Block.html)
118 ///
119 ///
119 /// This is the high level representation that most algorithms should
120 /// This is the high level representation that most algorithms should
120 /// use.
121 /// use.
121 #[derive(Clone, Debug, Eq, PartialEq)]
122 #[derive(Clone, Debug, Eq, PartialEq)]
122 enum Element {
123 enum Element {
123 Rev(Revision),
124 Rev(Revision),
124 Block(usize),
125 Block(usize),
125 None,
126 None,
126 }
127 }
127
128
128 impl From<RawElement> for Element {
129 impl From<RawElement> for Element {
129 /// Conversion from low level representation, after endianness conversion.
130 /// Conversion from low level representation, after endianness conversion.
130 ///
131 ///
131 /// See [`Block`](struct.Block.html) for explanation about the encoding.
132 /// See [`Block`](struct.Block.html) for explanation about the encoding.
132 fn from(raw: RawElement) -> Element {
133 fn from(raw: RawElement) -> Element {
133 if raw >= 0 {
134 if raw >= 0 {
134 Element::Block(raw as usize)
135 Element::Block(raw as usize)
135 } else if raw == -1 {
136 } else if raw == -1 {
136 Element::None
137 Element::None
137 } else {
138 } else {
138 Element::Rev(-raw - 2)
139 Element::Rev(-raw - 2)
139 }
140 }
140 }
141 }
141 }
142 }
142
143
143 impl From<Element> for RawElement {
144 impl From<Element> for RawElement {
144 fn from(element: Element) -> RawElement {
145 fn from(element: Element) -> RawElement {
145 match element {
146 match element {
146 Element::None => 0,
147 Element::None => 0,
147 Element::Block(i) => i as RawElement,
148 Element::Block(i) => i as RawElement,
148 Element::Rev(rev) => -rev - 2,
149 Element::Rev(rev) => -rev - 2,
149 }
150 }
150 }
151 }
151 }
152 }
152
153
153 /// A logical block of the `NodeTree`, packed with a fixed size.
154 /// A logical block of the `NodeTree`, packed with a fixed size.
154 ///
155 ///
155 /// These are always used in container types implementing `Index<Block>`,
156 /// These are always used in container types implementing `Index<Block>`,
156 /// such as `&Block`
157 /// such as `&Block`
157 ///
158 ///
158 /// As an array of integers, its ith element encodes that the
159 /// As an array of integers, its ith element encodes that the
159 /// ith potential edge from the block, representing the ith hexadecimal digit
160 /// ith potential edge from the block, representing the ith hexadecimal digit
160 /// (nybble) `i` is either:
161 /// (nybble) `i` is either:
161 ///
162 ///
162 /// - absent (value -1)
163 /// - absent (value -1)
163 /// - another `Block` in the same indexable container (value β‰₯ 0)
164 /// - another `Block` in the same indexable container (value β‰₯ 0)
164 /// - a `Revision` leaf (value ≀ -2)
165 /// - a `Revision` leaf (value ≀ -2)
165 ///
166 ///
166 /// Endianness has to be fixed for consistency on shared storage across
167 /// Endianness has to be fixed for consistency on shared storage across
167 /// different architectures.
168 /// different architectures.
168 ///
169 ///
169 /// A key difference with the C `nodetree` is that we need to be
170 /// A key difference with the C `nodetree` is that we need to be
170 /// able to represent the [`Block`] at index 0, hence -1 is the empty marker
171 /// able to represent the [`Block`] at index 0, hence -1 is the empty marker
171 /// rather than 0 and the `Revision` range upper limit of -2 instead of -1.
172 /// rather than 0 and the `Revision` range upper limit of -2 instead of -1.
172 ///
173 ///
173 /// Another related difference is that `NULL_REVISION` (-1) is not
174 /// Another related difference is that `NULL_REVISION` (-1) is not
174 /// represented at all, because we want an immutable empty nodetree
175 /// represented at all, because we want an immutable empty nodetree
175 /// to be valid.
176 /// to be valid.
176
177
177 #[derive(Copy, Clone)]
178 #[derive(Copy, Clone)]
178 pub struct Block([u8; BLOCK_SIZE]);
179 pub struct Block([u8; BLOCK_SIZE]);
179
180
180 /// Not derivable for arrays of length >32 until const generics are stable
181 /// Not derivable for arrays of length >32 until const generics are stable
181 impl PartialEq for Block {
182 impl PartialEq for Block {
182 fn eq(&self, other: &Self) -> bool {
183 fn eq(&self, other: &Self) -> bool {
183 &self.0[..] == &other.0[..]
184 &self.0[..] == &other.0[..]
184 }
185 }
185 }
186 }
186
187
187 pub const BLOCK_SIZE: usize = 64;
188 pub const BLOCK_SIZE: usize = 64;
188
189
189 impl Block {
190 impl Block {
190 fn new() -> Self {
191 fn new() -> Self {
191 // -1 in 2's complement to create an absent node
192 // -1 in 2's complement to create an absent node
192 let byte: u8 = 255;
193 let byte: u8 = 255;
193 Block([byte; BLOCK_SIZE])
194 Block([byte; BLOCK_SIZE])
194 }
195 }
195
196
196 fn get(&self, nybble: u8) -> Element {
197 fn get(&self, nybble: u8) -> Element {
197 let index = nybble as usize * mem::size_of::<RawElement>();
198 let index = nybble as usize * mem::size_of::<RawElement>();
198 Element::from(RawElement::from_be_bytes([
199 Element::from(RawElement::from_be_bytes([
199 self.0[index],
200 self.0[index],
200 self.0[index + 1],
201 self.0[index + 1],
201 self.0[index + 2],
202 self.0[index + 2],
202 self.0[index + 3],
203 self.0[index + 3],
203 ]))
204 ]))
204 }
205 }
205
206
206 fn set(&mut self, nybble: u8, element: Element) {
207 fn set(&mut self, nybble: u8, element: Element) {
207 let values = RawElement::to_be_bytes(element.into());
208 let values = RawElement::to_be_bytes(element.into());
208 let index = nybble as usize * mem::size_of::<RawElement>();
209 let index = nybble as usize * mem::size_of::<RawElement>();
209 self.0[index] = values[0];
210 self.0[index] = values[0];
210 self.0[index + 1] = values[1];
211 self.0[index + 1] = values[1];
211 self.0[index + 2] = values[2];
212 self.0[index + 2] = values[2];
212 self.0[index + 3] = values[3];
213 self.0[index + 3] = values[3];
213 }
214 }
214 }
215 }
215
216
216 impl fmt::Debug for Block {
217 impl fmt::Debug for Block {
217 /// sparse representation for testing and debugging purposes
218 /// sparse representation for testing and debugging purposes
218 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
219 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
219 f.debug_map()
220 f.debug_map()
220 .entries((0..16).filter_map(|i| match self.get(i) {
221 .entries((0..16).filter_map(|i| match self.get(i) {
221 Element::None => None,
222 Element::None => None,
222 element => Some((i, element)),
223 element => Some((i, element)),
223 }))
224 }))
224 .finish()
225 .finish()
225 }
226 }
226 }
227 }
227
228
228 /// A mutable 16-radix tree with the root block logically at the end
229 /// A mutable 16-radix tree with the root block logically at the end
229 ///
230 ///
230 /// Because of the append only nature of our node trees, we need to
231 /// Because of the append only nature of our node trees, we need to
231 /// keep the original untouched and store new blocks separately.
232 /// keep the original untouched and store new blocks separately.
232 ///
233 ///
233 /// The mutable root `Block` is kept apart so that we don't have to rebump
234 /// The mutable root `Block` is kept apart so that we don't have to rebump
234 /// it on each insertion.
235 /// it on each insertion.
235 pub struct NodeTree {
236 pub struct NodeTree {
236 readonly: Box<dyn Deref<Target = [Block]> + Send>,
237 readonly: Box<dyn Deref<Target = [Block]> + Send>,
237 growable: Vec<Block>,
238 growable: Vec<Block>,
238 root: Block,
239 root: Block,
239 }
240 }
240
241
241 impl Index<usize> for NodeTree {
242 impl Index<usize> for NodeTree {
242 type Output = Block;
243 type Output = Block;
243
244
244 fn index(&self, i: usize) -> &Block {
245 fn index(&self, i: usize) -> &Block {
245 let ro_len = self.readonly.len();
246 let ro_len = self.readonly.len();
246 if i < ro_len {
247 if i < ro_len {
247 &self.readonly[i]
248 &self.readonly[i]
248 } else if i == ro_len + self.growable.len() {
249 } else if i == ro_len + self.growable.len() {
249 &self.root
250 &self.root
250 } else {
251 } else {
251 &self.growable[i - ro_len]
252 &self.growable[i - ro_len]
252 }
253 }
253 }
254 }
254 }
255 }
255
256
256 /// Return `None` unless the `Node` for `rev` has given prefix in `index`.
257 /// Return `None` unless the `Node` for `rev` has given prefix in `index`.
257 fn has_prefix_or_none(
258 fn has_prefix_or_none(
258 idx: &impl RevlogIndex,
259 idx: &impl RevlogIndex,
259 prefix: NodePrefixRef,
260 prefix: NodePrefixRef,
260 rev: Revision,
261 rev: Revision,
261 ) -> Result<Option<Revision>, NodeMapError> {
262 ) -> Result<Option<Revision>, NodeMapError> {
262 idx.node(rev)
263 idx.node(rev)
263 .ok_or_else(|| NodeMapError::RevisionNotInIndex(rev))
264 .ok_or_else(|| NodeMapError::RevisionNotInIndex(rev))
264 .map(|node| {
265 .map(|node| {
265 if prefix.is_prefix_of(node) {
266 if prefix.is_prefix_of(node) {
266 Some(rev)
267 Some(rev)
267 } else {
268 } else {
268 None
269 None
269 }
270 }
270 })
271 })
271 }
272 }
272
273
274 /// validate that the candidate's node starts indeed with given prefix,
275 /// and treat ambiguities related to `NULL_REVISION`.
276 ///
277 /// From the data in the NodeTree, one can only conclude that some
278 /// revision is the only one for a *subprefix* of the one being looked up.
279 fn validate_candidate(
280 idx: &impl RevlogIndex,
281 prefix: NodePrefixRef,
282 rev: Option<Revision>,
283 ) -> Result<Option<Revision>, NodeMapError> {
284 if prefix.is_prefix_of(&NULL_NODE) {
285 // NULL_REVISION always matches a prefix made only of zeros
286 // and any other *valid* result is an ambiguity
287 match rev {
288 None => Ok(Some(NULL_REVISION)),
289 Some(r) => match has_prefix_or_none(idx, prefix, r)? {
290 None => Ok(Some(NULL_REVISION)),
291 _ => Err(NodeMapError::MultipleResults),
292 },
293 }
294 } else {
295 rev.map_or(Ok(None), |r| has_prefix_or_none(idx, prefix, r))
296 }
297 }
298
273 impl NodeTree {
299 impl NodeTree {
274 /// Initiate a NodeTree from an immutable slice-like of `Block`
300 /// Initiate a NodeTree from an immutable slice-like of `Block`
275 ///
301 ///
276 /// We keep `readonly` and clone its root block if it isn't empty.
302 /// We keep `readonly` and clone its root block if it isn't empty.
277 fn new(readonly: Box<dyn Deref<Target = [Block]> + Send>) -> Self {
303 fn new(readonly: Box<dyn Deref<Target = [Block]> + Send>) -> Self {
278 let root = readonly
304 let root = readonly
279 .last()
305 .last()
280 .map(|b| b.clone())
306 .map(|b| b.clone())
281 .unwrap_or_else(|| Block::new());
307 .unwrap_or_else(|| Block::new());
282 NodeTree {
308 NodeTree {
283 readonly: readonly,
309 readonly: readonly,
284 growable: Vec::new(),
310 growable: Vec::new(),
285 root: root,
311 root: root,
286 }
312 }
287 }
313 }
288
314
289 /// Create from an opaque bunch of bytes
315 /// Create from an opaque bunch of bytes
290 ///
316 ///
291 /// The created `NodeTreeBytes` from `buffer`,
317 /// The created `NodeTreeBytes` from `buffer`,
292 /// of which exactly `amount` bytes are used.
318 /// of which exactly `amount` bytes are used.
293 ///
319 ///
294 /// - `buffer` could be derived from `PyBuffer` and `Mmap` objects.
320 /// - `buffer` could be derived from `PyBuffer` and `Mmap` objects.
295 /// - `offset` allows for the final file format to include fixed data
321 /// - `offset` allows for the final file format to include fixed data
296 /// (generation number, behavioural flags)
322 /// (generation number, behavioural flags)
297 /// - `amount` is expressed in bytes, and is not automatically derived from
323 /// - `amount` is expressed in bytes, and is not automatically derived from
298 /// `bytes`, so that a caller that manages them atomically can perform
324 /// `bytes`, so that a caller that manages them atomically can perform
299 /// temporary disk serializations and still rollback easily if needed.
325 /// temporary disk serializations and still rollback easily if needed.
300 /// First use-case for this would be to support Mercurial shell hooks.
326 /// First use-case for this would be to support Mercurial shell hooks.
301 ///
327 ///
302 /// panics if `buffer` is smaller than `amount`
328 /// panics if `buffer` is smaller than `amount`
303 pub fn load_bytes(
329 pub fn load_bytes(
304 bytes: Box<dyn Deref<Target = [u8]> + Send>,
330 bytes: Box<dyn Deref<Target = [u8]> + Send>,
305 amount: usize,
331 amount: usize,
306 ) -> Self {
332 ) -> Self {
307 NodeTree::new(Box::new(NodeTreeBytes::new(bytes, amount)))
333 NodeTree::new(Box::new(NodeTreeBytes::new(bytes, amount)))
308 }
334 }
309
335
310 /// Retrieve added `Block` and the original immutable data
336 /// Retrieve added `Block` and the original immutable data
311 pub fn into_readonly_and_added(
337 pub fn into_readonly_and_added(
312 self,
338 self,
313 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<Block>) {
339 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<Block>) {
314 let mut vec = self.growable;
340 let mut vec = self.growable;
315 let readonly = self.readonly;
341 let readonly = self.readonly;
316 if readonly.last() != Some(&self.root) {
342 if readonly.last() != Some(&self.root) {
317 vec.push(self.root);
343 vec.push(self.root);
318 }
344 }
319 (readonly, vec)
345 (readonly, vec)
320 }
346 }
321
347
322 /// Retrieve added `Blocks` as bytes, ready to be written to persistent
348 /// Retrieve added `Blocks` as bytes, ready to be written to persistent
323 /// storage
349 /// storage
324 pub fn into_readonly_and_added_bytes(
350 pub fn into_readonly_and_added_bytes(
325 self,
351 self,
326 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<u8>) {
352 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<u8>) {
327 let (readonly, vec) = self.into_readonly_and_added();
353 let (readonly, vec) = self.into_readonly_and_added();
328 // Prevent running `v`'s destructor so we are in complete control
354 // Prevent running `v`'s destructor so we are in complete control
329 // of the allocation.
355 // of the allocation.
330 let vec = mem::ManuallyDrop::new(vec);
356 let vec = mem::ManuallyDrop::new(vec);
331
357
332 // Transmute the `Vec<Block>` to a `Vec<u8>`. Blocks are contiguous
358 // Transmute the `Vec<Block>` to a `Vec<u8>`. Blocks are contiguous
333 // bytes, so this is perfectly safe.
359 // bytes, so this is perfectly safe.
334 let bytes = unsafe {
360 let bytes = unsafe {
335 // Assert that `Block` hasn't been changed and has no padding
361 // Assert that `Block` hasn't been changed and has no padding
336 let _: [u8; 4 * BLOCK_SIZE] =
362 let _: [u8; 4 * BLOCK_SIZE] =
337 std::mem::transmute([Block::new(); 4]);
363 std::mem::transmute([Block::new(); 4]);
338
364
339 // /!\ Any use of `vec` after this is use-after-free.
365 // /!\ Any use of `vec` after this is use-after-free.
340 // TODO: use `into_raw_parts` once stabilized
366 // TODO: use `into_raw_parts` once stabilized
341 Vec::from_raw_parts(
367 Vec::from_raw_parts(
342 vec.as_ptr() as *mut u8,
368 vec.as_ptr() as *mut u8,
343 vec.len() * BLOCK_SIZE,
369 vec.len() * BLOCK_SIZE,
344 vec.capacity() * BLOCK_SIZE,
370 vec.capacity() * BLOCK_SIZE,
345 )
371 )
346 };
372 };
347 (readonly, bytes)
373 (readonly, bytes)
348 }
374 }
349
375
350 /// Total number of blocks
376 /// Total number of blocks
351 fn len(&self) -> usize {
377 fn len(&self) -> usize {
352 self.readonly.len() + self.growable.len() + 1
378 self.readonly.len() + self.growable.len() + 1
353 }
379 }
354
380
355 /// Implemented for completeness
381 /// Implemented for completeness
356 ///
382 ///
357 /// A `NodeTree` always has at least the mutable root block.
383 /// A `NodeTree` always has at least the mutable root block.
358 #[allow(dead_code)]
384 #[allow(dead_code)]
359 fn is_empty(&self) -> bool {
385 fn is_empty(&self) -> bool {
360 false
386 false
361 }
387 }
362
388
363 /// Main working method for `NodeTree` searches
389 /// Main working method for `NodeTree` searches
364 ///
365 /// This partial implementation lacks special cases for NULL_REVISION
366 fn lookup<'p>(
390 fn lookup<'p>(
367 &self,
391 &self,
368 prefix: NodePrefixRef<'p>,
392 prefix: NodePrefixRef<'p>,
369 ) -> Result<Option<Revision>, NodeMapError> {
393 ) -> Result<Option<Revision>, NodeMapError> {
370 for visit_item in self.visit(prefix) {
394 for visit_item in self.visit(prefix) {
371 if let Some(opt) = visit_item.final_revision() {
395 if let Some(opt) = visit_item.final_revision() {
372 return Ok(opt);
396 return Ok(opt);
373 }
397 }
374 }
398 }
375 Err(NodeMapError::MultipleResults)
399 Err(NodeMapError::MultipleResults)
376 }
400 }
377
401
378 fn visit<'n, 'p>(
402 fn visit<'n, 'p>(
379 &'n self,
403 &'n self,
380 prefix: NodePrefixRef<'p>,
404 prefix: NodePrefixRef<'p>,
381 ) -> NodeTreeVisitor<'n, 'p> {
405 ) -> NodeTreeVisitor<'n, 'p> {
382 NodeTreeVisitor {
406 NodeTreeVisitor {
383 nt: self,
407 nt: self,
384 prefix: prefix,
408 prefix: prefix,
385 visit: self.len() - 1,
409 visit: self.len() - 1,
386 nybble_idx: 0,
410 nybble_idx: 0,
387 done: false,
411 done: false,
388 }
412 }
389 }
413 }
390 /// Return a mutable reference for `Block` at index `idx`.
414 /// Return a mutable reference for `Block` at index `idx`.
391 ///
415 ///
392 /// If `idx` lies in the immutable area, then the reference is to
416 /// If `idx` lies in the immutable area, then the reference is to
393 /// a newly appended copy.
417 /// a newly appended copy.
394 ///
418 ///
395 /// Returns (new_idx, glen, mut_ref) where
419 /// Returns (new_idx, glen, mut_ref) where
396 ///
420 ///
397 /// - `new_idx` is the index of the mutable `Block`
421 /// - `new_idx` is the index of the mutable `Block`
398 /// - `mut_ref` is a mutable reference to the mutable Block.
422 /// - `mut_ref` is a mutable reference to the mutable Block.
399 /// - `glen` is the new length of `self.growable`
423 /// - `glen` is the new length of `self.growable`
400 ///
424 ///
401 /// Note: the caller wouldn't be allowed to query `self.growable.len()`
425 /// Note: the caller wouldn't be allowed to query `self.growable.len()`
402 /// itself because of the mutable borrow taken with the returned `Block`
426 /// itself because of the mutable borrow taken with the returned `Block`
403 fn mutable_block(&mut self, idx: usize) -> (usize, &mut Block, usize) {
427 fn mutable_block(&mut self, idx: usize) -> (usize, &mut Block, usize) {
404 let ro_blocks = &self.readonly;
428 let ro_blocks = &self.readonly;
405 let ro_len = ro_blocks.len();
429 let ro_len = ro_blocks.len();
406 let glen = self.growable.len();
430 let glen = self.growable.len();
407 if idx < ro_len {
431 if idx < ro_len {
408 // TODO OPTIM I think this makes two copies
432 // TODO OPTIM I think this makes two copies
409 self.growable.push(ro_blocks[idx].clone());
433 self.growable.push(ro_blocks[idx].clone());
410 (glen + ro_len, &mut self.growable[glen], glen + 1)
434 (glen + ro_len, &mut self.growable[glen], glen + 1)
411 } else if glen + ro_len == idx {
435 } else if glen + ro_len == idx {
412 (idx, &mut self.root, glen)
436 (idx, &mut self.root, glen)
413 } else {
437 } else {
414 (idx, &mut self.growable[idx - ro_len], glen)
438 (idx, &mut self.growable[idx - ro_len], glen)
415 }
439 }
416 }
440 }
417
441
418 /// Main insertion method
442 /// Main insertion method
419 ///
443 ///
420 /// This will dive in the node tree to find the deepest `Block` for
444 /// This will dive in the node tree to find the deepest `Block` for
421 /// `node`, split it as much as needed and record `node` in there.
445 /// `node`, split it as much as needed and record `node` in there.
422 /// The method then backtracks, updating references in all the visited
446 /// The method then backtracks, updating references in all the visited
423 /// blocks from the root.
447 /// blocks from the root.
424 ///
448 ///
425 /// All the mutated `Block` are copied first to the growable part if
449 /// All the mutated `Block` are copied first to the growable part if
426 /// needed. That happens for those in the immutable part except the root.
450 /// needed. That happens for those in the immutable part except the root.
427 pub fn insert<I: RevlogIndex>(
451 pub fn insert<I: RevlogIndex>(
428 &mut self,
452 &mut self,
429 index: &I,
453 index: &I,
430 node: &Node,
454 node: &Node,
431 rev: Revision,
455 rev: Revision,
432 ) -> Result<(), NodeMapError> {
456 ) -> Result<(), NodeMapError> {
433 let ro_len = &self.readonly.len();
457 let ro_len = &self.readonly.len();
434
458
435 let mut visit_steps: Vec<_> = self.visit(node.into()).collect();
459 let mut visit_steps: Vec<_> = self.visit(node.into()).collect();
436 let read_nybbles = visit_steps.len();
460 let read_nybbles = visit_steps.len();
437 // visit_steps cannot be empty, since we always visit the root block
461 // visit_steps cannot be empty, since we always visit the root block
438 let deepest = visit_steps.pop().unwrap();
462 let deepest = visit_steps.pop().unwrap();
439
463
440 let (mut block_idx, mut block, mut glen) =
464 let (mut block_idx, mut block, mut glen) =
441 self.mutable_block(deepest.block_idx);
465 self.mutable_block(deepest.block_idx);
442
466
443 if let Element::Rev(old_rev) = deepest.element {
467 if let Element::Rev(old_rev) = deepest.element {
444 let old_node = index
468 let old_node = index
445 .node(old_rev)
469 .node(old_rev)
446 .ok_or_else(|| NodeMapError::RevisionNotInIndex(old_rev))?;
470 .ok_or_else(|| NodeMapError::RevisionNotInIndex(old_rev))?;
447 if old_node == node {
471 if old_node == node {
448 return Ok(()); // avoid creating lots of useless blocks
472 return Ok(()); // avoid creating lots of useless blocks
449 }
473 }
450
474
451 // Looping over the tail of nybbles in both nodes, creating
475 // Looping over the tail of nybbles in both nodes, creating
452 // new blocks until we find the difference
476 // new blocks until we find the difference
453 let mut new_block_idx = ro_len + glen;
477 let mut new_block_idx = ro_len + glen;
454 let mut nybble = deepest.nybble;
478 let mut nybble = deepest.nybble;
455 for nybble_pos in read_nybbles..node.nybbles_len() {
479 for nybble_pos in read_nybbles..node.nybbles_len() {
456 block.set(nybble, Element::Block(new_block_idx));
480 block.set(nybble, Element::Block(new_block_idx));
457
481
458 let new_nybble = node.get_nybble(nybble_pos);
482 let new_nybble = node.get_nybble(nybble_pos);
459 let old_nybble = old_node.get_nybble(nybble_pos);
483 let old_nybble = old_node.get_nybble(nybble_pos);
460
484
461 if old_nybble == new_nybble {
485 if old_nybble == new_nybble {
462 self.growable.push(Block::new());
486 self.growable.push(Block::new());
463 block = &mut self.growable[glen];
487 block = &mut self.growable[glen];
464 glen += 1;
488 glen += 1;
465 new_block_idx += 1;
489 new_block_idx += 1;
466 nybble = new_nybble;
490 nybble = new_nybble;
467 } else {
491 } else {
468 let mut new_block = Block::new();
492 let mut new_block = Block::new();
469 new_block.set(old_nybble, Element::Rev(old_rev));
493 new_block.set(old_nybble, Element::Rev(old_rev));
470 new_block.set(new_nybble, Element::Rev(rev));
494 new_block.set(new_nybble, Element::Rev(rev));
471 self.growable.push(new_block);
495 self.growable.push(new_block);
472 break;
496 break;
473 }
497 }
474 }
498 }
475 } else {
499 } else {
476 // Free slot in the deepest block: no splitting has to be done
500 // Free slot in the deepest block: no splitting has to be done
477 block.set(deepest.nybble, Element::Rev(rev));
501 block.set(deepest.nybble, Element::Rev(rev));
478 }
502 }
479
503
480 // Backtrack over visit steps to update references
504 // Backtrack over visit steps to update references
481 while let Some(visited) = visit_steps.pop() {
505 while let Some(visited) = visit_steps.pop() {
482 let to_write = Element::Block(block_idx);
506 let to_write = Element::Block(block_idx);
483 if visit_steps.is_empty() {
507 if visit_steps.is_empty() {
484 self.root.set(visited.nybble, to_write);
508 self.root.set(visited.nybble, to_write);
485 break;
509 break;
486 }
510 }
487 let (new_idx, block, _) = self.mutable_block(visited.block_idx);
511 let (new_idx, block, _) = self.mutable_block(visited.block_idx);
488 if block.get(visited.nybble) == to_write {
512 if block.get(visited.nybble) == to_write {
489 break;
513 break;
490 }
514 }
491 block.set(visited.nybble, to_write);
515 block.set(visited.nybble, to_write);
492 block_idx = new_idx;
516 block_idx = new_idx;
493 }
517 }
494 Ok(())
518 Ok(())
495 }
519 }
496 }
520 }
497
521
498 pub struct NodeTreeBytes {
522 pub struct NodeTreeBytes {
499 buffer: Box<dyn Deref<Target = [u8]> + Send>,
523 buffer: Box<dyn Deref<Target = [u8]> + Send>,
500 len_in_blocks: usize,
524 len_in_blocks: usize,
501 }
525 }
502
526
503 impl NodeTreeBytes {
527 impl NodeTreeBytes {
504 fn new(
528 fn new(
505 buffer: Box<dyn Deref<Target = [u8]> + Send>,
529 buffer: Box<dyn Deref<Target = [u8]> + Send>,
506 amount: usize,
530 amount: usize,
507 ) -> Self {
531 ) -> Self {
508 assert!(buffer.len() >= amount);
532 assert!(buffer.len() >= amount);
509 let len_in_blocks = amount / BLOCK_SIZE;
533 let len_in_blocks = amount / BLOCK_SIZE;
510 NodeTreeBytes {
534 NodeTreeBytes {
511 buffer,
535 buffer,
512 len_in_blocks,
536 len_in_blocks,
513 }
537 }
514 }
538 }
515 }
539 }
516
540
517 impl Deref for NodeTreeBytes {
541 impl Deref for NodeTreeBytes {
518 type Target = [Block];
542 type Target = [Block];
519
543
520 fn deref(&self) -> &[Block] {
544 fn deref(&self) -> &[Block] {
521 unsafe {
545 unsafe {
522 slice::from_raw_parts(
546 slice::from_raw_parts(
523 (&self.buffer).as_ptr() as *const Block,
547 (&self.buffer).as_ptr() as *const Block,
524 self.len_in_blocks,
548 self.len_in_blocks,
525 )
549 )
526 }
550 }
527 }
551 }
528 }
552 }
529
553
530 struct NodeTreeVisitor<'n, 'p> {
554 struct NodeTreeVisitor<'n, 'p> {
531 nt: &'n NodeTree,
555 nt: &'n NodeTree,
532 prefix: NodePrefixRef<'p>,
556 prefix: NodePrefixRef<'p>,
533 visit: usize,
557 visit: usize,
534 nybble_idx: usize,
558 nybble_idx: usize,
535 done: bool,
559 done: bool,
536 }
560 }
537
561
538 #[derive(Debug, PartialEq, Clone)]
562 #[derive(Debug, PartialEq, Clone)]
539 struct NodeTreeVisitItem {
563 struct NodeTreeVisitItem {
540 block_idx: usize,
564 block_idx: usize,
541 nybble: u8,
565 nybble: u8,
542 element: Element,
566 element: Element,
543 }
567 }
544
568
545 impl<'n, 'p> Iterator for NodeTreeVisitor<'n, 'p> {
569 impl<'n, 'p> Iterator for NodeTreeVisitor<'n, 'p> {
546 type Item = NodeTreeVisitItem;
570 type Item = NodeTreeVisitItem;
547
571
548 fn next(&mut self) -> Option<Self::Item> {
572 fn next(&mut self) -> Option<Self::Item> {
549 if self.done || self.nybble_idx >= self.prefix.len() {
573 if self.done || self.nybble_idx >= self.prefix.len() {
550 return None;
574 return None;
551 }
575 }
552
576
553 let nybble = self.prefix.get_nybble(self.nybble_idx);
577 let nybble = self.prefix.get_nybble(self.nybble_idx);
554 self.nybble_idx += 1;
578 self.nybble_idx += 1;
555
579
556 let visit = self.visit;
580 let visit = self.visit;
557 let element = self.nt[visit].get(nybble);
581 let element = self.nt[visit].get(nybble);
558 if let Element::Block(idx) = element {
582 if let Element::Block(idx) = element {
559 self.visit = idx;
583 self.visit = idx;
560 } else {
584 } else {
561 self.done = true;
585 self.done = true;
562 }
586 }
563
587
564 Some(NodeTreeVisitItem {
588 Some(NodeTreeVisitItem {
565 block_idx: visit,
589 block_idx: visit,
566 nybble: nybble,
590 nybble: nybble,
567 element: element,
591 element: element,
568 })
592 })
569 }
593 }
570 }
594 }
571
595
572 impl NodeTreeVisitItem {
596 impl NodeTreeVisitItem {
573 // Return `Some(opt)` if this item is final, with `opt` being the
597 // Return `Some(opt)` if this item is final, with `opt` being the
574 // `Revision` that it may represent.
598 // `Revision` that it may represent.
575 //
599 //
576 // If the item is not terminal, return `None`
600 // If the item is not terminal, return `None`
577 fn final_revision(&self) -> Option<Option<Revision>> {
601 fn final_revision(&self) -> Option<Option<Revision>> {
578 match self.element {
602 match self.element {
579 Element::Block(_) => None,
603 Element::Block(_) => None,
580 Element::Rev(r) => Some(Some(r)),
604 Element::Rev(r) => Some(Some(r)),
581 Element::None => Some(None),
605 Element::None => Some(None),
582 }
606 }
583 }
607 }
584 }
608 }
585
609
586 impl From<Vec<Block>> for NodeTree {
610 impl From<Vec<Block>> for NodeTree {
587 fn from(vec: Vec<Block>) -> Self {
611 fn from(vec: Vec<Block>) -> Self {
588 Self::new(Box::new(vec))
612 Self::new(Box::new(vec))
589 }
613 }
590 }
614 }
591
615
592 impl fmt::Debug for NodeTree {
616 impl fmt::Debug for NodeTree {
593 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594 let readonly: &[Block] = &*self.readonly;
618 let readonly: &[Block] = &*self.readonly;
595 write!(
619 write!(
596 f,
620 f,
597 "readonly: {:?}, growable: {:?}, root: {:?}",
621 "readonly: {:?}, growable: {:?}, root: {:?}",
598 readonly, self.growable, self.root
622 readonly, self.growable, self.root
599 )
623 )
600 }
624 }
601 }
625 }
602
626
603 impl Default for NodeTree {
627 impl Default for NodeTree {
604 /// Create a fully mutable empty NodeTree
628 /// Create a fully mutable empty NodeTree
605 fn default() -> Self {
629 fn default() -> Self {
606 NodeTree::new(Box::new(Vec::new()))
630 NodeTree::new(Box::new(Vec::new()))
607 }
631 }
608 }
632 }
609
633
610 impl NodeMap for NodeTree {
634 impl NodeMap for NodeTree {
611 fn find_bin<'a>(
635 fn find_bin<'a>(
612 &self,
636 &self,
613 idx: &impl RevlogIndex,
637 idx: &impl RevlogIndex,
614 prefix: NodePrefixRef<'a>,
638 prefix: NodePrefixRef<'a>,
615 ) -> Result<Option<Revision>, NodeMapError> {
639 ) -> Result<Option<Revision>, NodeMapError> {
616 self.lookup(prefix.clone()).and_then(|opt| {
640 validate_candidate(idx, prefix.clone(), self.lookup(prefix)?)
617 opt.map_or(Ok(None), |rev| has_prefix_or_none(idx, prefix, rev))
618 })
619 }
641 }
620 }
642 }
621
643
622 #[cfg(test)]
644 #[cfg(test)]
623 mod tests {
645 mod tests {
624 use super::NodeMapError::*;
646 use super::NodeMapError::*;
625 use super::*;
647 use super::*;
626 use crate::revlog::node::{hex_pad_right, Node};
648 use crate::revlog::node::{hex_pad_right, Node};
627 use std::collections::HashMap;
649 use std::collections::HashMap;
628
650
629 /// Creates a `Block` using a syntax close to the `Debug` output
651 /// Creates a `Block` using a syntax close to the `Debug` output
630 macro_rules! block {
652 macro_rules! block {
631 {$($nybble:tt : $variant:ident($val:tt)),*} => (
653 {$($nybble:tt : $variant:ident($val:tt)),*} => (
632 {
654 {
633 let mut block = Block::new();
655 let mut block = Block::new();
634 $(block.set($nybble, Element::$variant($val)));*;
656 $(block.set($nybble, Element::$variant($val)));*;
635 block
657 block
636 }
658 }
637 )
659 )
638 }
660 }
639
661
640 #[test]
662 #[test]
641 fn test_block_debug() {
663 fn test_block_debug() {
642 let mut block = Block::new();
664 let mut block = Block::new();
643 block.set(1, Element::Rev(3));
665 block.set(1, Element::Rev(3));
644 block.set(10, Element::Block(0));
666 block.set(10, Element::Block(0));
645 assert_eq!(format!("{:?}", block), "{1: Rev(3), 10: Block(0)}");
667 assert_eq!(format!("{:?}", block), "{1: Rev(3), 10: Block(0)}");
646 }
668 }
647
669
648 #[test]
670 #[test]
649 fn test_block_macro() {
671 fn test_block_macro() {
650 let block = block! {5: Block(2)};
672 let block = block! {5: Block(2)};
651 assert_eq!(format!("{:?}", block), "{5: Block(2)}");
673 assert_eq!(format!("{:?}", block), "{5: Block(2)}");
652
674
653 let block = block! {13: Rev(15), 5: Block(2)};
675 let block = block! {13: Rev(15), 5: Block(2)};
654 assert_eq!(format!("{:?}", block), "{5: Block(2), 13: Rev(15)}");
676 assert_eq!(format!("{:?}", block), "{5: Block(2), 13: Rev(15)}");
655 }
677 }
656
678
657 #[test]
679 #[test]
658 fn test_raw_block() {
680 fn test_raw_block() {
659 let mut raw = [255u8; 64];
681 let mut raw = [255u8; 64];
660
682
661 let mut counter = 0;
683 let mut counter = 0;
662 for val in [0, 15, -2, -1, -3].iter() {
684 for val in [0, 15, -2, -1, -3].iter() {
663 for byte in RawElement::to_be_bytes(*val).iter() {
685 for byte in RawElement::to_be_bytes(*val).iter() {
664 raw[counter] = *byte;
686 raw[counter] = *byte;
665 counter += 1;
687 counter += 1;
666 }
688 }
667 }
689 }
668 let block = Block(raw);
690 let block = Block(raw);
669 assert_eq!(block.get(0), Element::Block(0));
691 assert_eq!(block.get(0), Element::Block(0));
670 assert_eq!(block.get(1), Element::Block(15));
692 assert_eq!(block.get(1), Element::Block(15));
671 assert_eq!(block.get(3), Element::None);
693 assert_eq!(block.get(3), Element::None);
672 assert_eq!(block.get(2), Element::Rev(0));
694 assert_eq!(block.get(2), Element::Rev(0));
673 assert_eq!(block.get(4), Element::Rev(1));
695 assert_eq!(block.get(4), Element::Rev(1));
674 }
696 }
675
697
676 type TestIndex = HashMap<Revision, Node>;
698 type TestIndex = HashMap<Revision, Node>;
677
699
678 impl RevlogIndex for TestIndex {
700 impl RevlogIndex for TestIndex {
679 fn node(&self, rev: Revision) -> Option<&Node> {
701 fn node(&self, rev: Revision) -> Option<&Node> {
680 self.get(&rev)
702 self.get(&rev)
681 }
703 }
682
704
683 fn len(&self) -> usize {
705 fn len(&self) -> usize {
684 self.len()
706 self.len()
685 }
707 }
686 }
708 }
687
709
688 /// Pad hexadecimal Node prefix with zeros on the right
710 /// Pad hexadecimal Node prefix with zeros on the right
689 ///
711 ///
690 /// This avoids having to repeatedly write very long hexadecimal
712 /// This avoids having to repeatedly write very long hexadecimal
691 /// strings for test data, and brings actual hash size independency.
713 /// strings for test data, and brings actual hash size independency.
692 #[cfg(test)]
714 #[cfg(test)]
693 fn pad_node(hex: &str) -> Node {
715 fn pad_node(hex: &str) -> Node {
694 Node::from_hex(&hex_pad_right(hex)).unwrap()
716 Node::from_hex(&hex_pad_right(hex)).unwrap()
695 }
717 }
696
718
697 /// Pad hexadecimal Node prefix with zeros on the right, then insert
719 /// Pad hexadecimal Node prefix with zeros on the right, then insert
698 fn pad_insert(idx: &mut TestIndex, rev: Revision, hex: &str) {
720 fn pad_insert(idx: &mut TestIndex, rev: Revision, hex: &str) {
699 idx.insert(rev, pad_node(hex));
721 idx.insert(rev, pad_node(hex));
700 }
722 }
701
723
702 fn sample_nodetree() -> NodeTree {
724 fn sample_nodetree() -> NodeTree {
703 NodeTree::from(vec![
725 NodeTree::from(vec![
704 block![0: Rev(9)],
726 block![0: Rev(9)],
705 block![0: Rev(0), 1: Rev(9)],
727 block![0: Rev(0), 1: Rev(9)],
706 block![0: Block(1), 1:Rev(1)],
728 block![0: Block(1), 1:Rev(1)],
707 ])
729 ])
708 }
730 }
709
731
710 #[test]
732 #[test]
711 fn test_nt_debug() {
733 fn test_nt_debug() {
712 let nt = sample_nodetree();
734 let nt = sample_nodetree();
713 assert_eq!(
735 assert_eq!(
714 format!("{:?}", nt),
736 format!("{:?}", nt),
715 "readonly: \
737 "readonly: \
716 [{0: Rev(9)}, {0: Rev(0), 1: Rev(9)}, {0: Block(1), 1: Rev(1)}], \
738 [{0: Rev(9)}, {0: Rev(0), 1: Rev(9)}, {0: Block(1), 1: Rev(1)}], \
717 growable: [], \
739 growable: [], \
718 root: {0: Block(1), 1: Rev(1)}",
740 root: {0: Block(1), 1: Rev(1)}",
719 );
741 );
720 }
742 }
721
743
722 #[test]
744 #[test]
723 fn test_immutable_find_simplest() -> Result<(), NodeMapError> {
745 fn test_immutable_find_simplest() -> Result<(), NodeMapError> {
724 let mut idx: TestIndex = HashMap::new();
746 let mut idx: TestIndex = HashMap::new();
725 pad_insert(&mut idx, 1, "1234deadcafe");
747 pad_insert(&mut idx, 1, "1234deadcafe");
726
748
727 let nt = NodeTree::from(vec![block! {1: Rev(1)}]);
749 let nt = NodeTree::from(vec![block! {1: Rev(1)}]);
728 assert_eq!(nt.find_hex(&idx, "1")?, Some(1));
750 assert_eq!(nt.find_hex(&idx, "1")?, Some(1));
729 assert_eq!(nt.find_hex(&idx, "12")?, Some(1));
751 assert_eq!(nt.find_hex(&idx, "12")?, Some(1));
730 assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1));
752 assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1));
731 assert_eq!(nt.find_hex(&idx, "1a")?, None);
753 assert_eq!(nt.find_hex(&idx, "1a")?, None);
732 assert_eq!(nt.find_hex(&idx, "ab")?, None);
754 assert_eq!(nt.find_hex(&idx, "ab")?, None);
733
755
734 // and with full binary Nodes
756 // and with full binary Nodes
735 assert_eq!(nt.find_node(&idx, idx.get(&1).unwrap())?, Some(1));
757 assert_eq!(nt.find_node(&idx, idx.get(&1).unwrap())?, Some(1));
736 let unknown = Node::from_hex(&hex_pad_right("3d")).unwrap();
758 let unknown = Node::from_hex(&hex_pad_right("3d")).unwrap();
737 assert_eq!(nt.find_node(&idx, &unknown)?, None);
759 assert_eq!(nt.find_node(&idx, &unknown)?, None);
738 Ok(())
760 Ok(())
739 }
761 }
740
762
741 #[test]
763 #[test]
742 fn test_immutable_find_one_jump() {
764 fn test_immutable_find_one_jump() {
743 let mut idx = TestIndex::new();
765 let mut idx = TestIndex::new();
744 pad_insert(&mut idx, 9, "012");
766 pad_insert(&mut idx, 9, "012");
745 pad_insert(&mut idx, 0, "00a");
767 pad_insert(&mut idx, 0, "00a");
746
768
747 let nt = sample_nodetree();
769 let nt = sample_nodetree();
748
770
749 assert_eq!(nt.find_hex(&idx, "0"), Err(MultipleResults));
771 assert_eq!(nt.find_hex(&idx, "0"), Err(MultipleResults));
750 assert_eq!(nt.find_hex(&idx, "01"), Ok(Some(9)));
772 assert_eq!(nt.find_hex(&idx, "01"), Ok(Some(9)));
751 assert_eq!(nt.find_hex(&idx, "00"), Ok(Some(0)));
773 assert_eq!(nt.find_hex(&idx, "00"), Err(MultipleResults));
752 assert_eq!(nt.find_hex(&idx, "00a"), Ok(Some(0)));
774 assert_eq!(nt.find_hex(&idx, "00a"), Ok(Some(0)));
775 assert_eq!(nt.find_hex(&idx, "000"), Ok(Some(NULL_REVISION)));
753 }
776 }
754
777
755 #[test]
778 #[test]
756 fn test_mutated_find() -> Result<(), NodeMapError> {
779 fn test_mutated_find() -> Result<(), NodeMapError> {
757 let mut idx = TestIndex::new();
780 let mut idx = TestIndex::new();
758 pad_insert(&mut idx, 9, "012");
781 pad_insert(&mut idx, 9, "012");
759 pad_insert(&mut idx, 0, "00a");
782 pad_insert(&mut idx, 0, "00a");
760 pad_insert(&mut idx, 2, "cafe");
783 pad_insert(&mut idx, 2, "cafe");
761 pad_insert(&mut idx, 3, "15");
784 pad_insert(&mut idx, 3, "15");
762 pad_insert(&mut idx, 1, "10");
785 pad_insert(&mut idx, 1, "10");
763
786
764 let nt = NodeTree {
787 let nt = NodeTree {
765 readonly: sample_nodetree().readonly,
788 readonly: sample_nodetree().readonly,
766 growable: vec![block![0: Rev(1), 5: Rev(3)]],
789 growable: vec![block![0: Rev(1), 5: Rev(3)]],
767 root: block![0: Block(1), 1:Block(3), 12: Rev(2)],
790 root: block![0: Block(1), 1:Block(3), 12: Rev(2)],
768 };
791 };
769 assert_eq!(nt.find_hex(&idx, "10")?, Some(1));
792 assert_eq!(nt.find_hex(&idx, "10")?, Some(1));
770 assert_eq!(nt.find_hex(&idx, "c")?, Some(2));
793 assert_eq!(nt.find_hex(&idx, "c")?, Some(2));
771 assert_eq!(nt.find_hex(&idx, "00")?, Some(0));
794 assert_eq!(nt.find_hex(&idx, "00"), Err(MultipleResults));
795 assert_eq!(nt.find_hex(&idx, "000")?, Some(NULL_REVISION));
772 assert_eq!(nt.find_hex(&idx, "01")?, Some(9));
796 assert_eq!(nt.find_hex(&idx, "01")?, Some(9));
773 Ok(())
797 Ok(())
774 }
798 }
775
799
776 struct TestNtIndex {
800 struct TestNtIndex {
777 index: TestIndex,
801 index: TestIndex,
778 nt: NodeTree,
802 nt: NodeTree,
779 }
803 }
780
804
781 impl TestNtIndex {
805 impl TestNtIndex {
782 fn new() -> Self {
806 fn new() -> Self {
783 TestNtIndex {
807 TestNtIndex {
784 index: HashMap::new(),
808 index: HashMap::new(),
785 nt: NodeTree::default(),
809 nt: NodeTree::default(),
786 }
810 }
787 }
811 }
788
812
789 fn insert(
813 fn insert(
790 &mut self,
814 &mut self,
791 rev: Revision,
815 rev: Revision,
792 hex: &str,
816 hex: &str,
793 ) -> Result<(), NodeMapError> {
817 ) -> Result<(), NodeMapError> {
794 let node = pad_node(hex);
818 let node = pad_node(hex);
795 self.index.insert(rev, node.clone());
819 self.index.insert(rev, node.clone());
796 self.nt.insert(&self.index, &node, rev)?;
820 self.nt.insert(&self.index, &node, rev)?;
797 Ok(())
821 Ok(())
798 }
822 }
799
823
800 fn find_hex(
824 fn find_hex(
801 &self,
825 &self,
802 prefix: &str,
826 prefix: &str,
803 ) -> Result<Option<Revision>, NodeMapError> {
827 ) -> Result<Option<Revision>, NodeMapError> {
804 self.nt.find_hex(&self.index, prefix)
828 self.nt.find_hex(&self.index, prefix)
805 }
829 }
806
830
807 /// Drain `added` and restart a new one
831 /// Drain `added` and restart a new one
808 fn commit(self) -> Self {
832 fn commit(self) -> Self {
809 let mut as_vec: Vec<Block> =
833 let mut as_vec: Vec<Block> =
810 self.nt.readonly.iter().map(|block| block.clone()).collect();
834 self.nt.readonly.iter().map(|block| block.clone()).collect();
811 as_vec.extend(self.nt.growable);
835 as_vec.extend(self.nt.growable);
812 as_vec.push(self.nt.root);
836 as_vec.push(self.nt.root);
813
837
814 Self {
838 Self {
815 index: self.index,
839 index: self.index,
816 nt: NodeTree::from(as_vec).into(),
840 nt: NodeTree::from(as_vec).into(),
817 }
841 }
818 }
842 }
819 }
843 }
820
844
821 #[test]
845 #[test]
822 fn test_insert_full_mutable() -> Result<(), NodeMapError> {
846 fn test_insert_full_mutable() -> Result<(), NodeMapError> {
823 let mut idx = TestNtIndex::new();
847 let mut idx = TestNtIndex::new();
824 idx.insert(0, "1234")?;
848 idx.insert(0, "1234")?;
825 assert_eq!(idx.find_hex("1")?, Some(0));
849 assert_eq!(idx.find_hex("1")?, Some(0));
826 assert_eq!(idx.find_hex("12")?, Some(0));
850 assert_eq!(idx.find_hex("12")?, Some(0));
827
851
828 // let's trigger a simple split
852 // let's trigger a simple split
829 idx.insert(1, "1a34")?;
853 idx.insert(1, "1a34")?;
830 assert_eq!(idx.nt.growable.len(), 1);
854 assert_eq!(idx.nt.growable.len(), 1);
831 assert_eq!(idx.find_hex("12")?, Some(0));
855 assert_eq!(idx.find_hex("12")?, Some(0));
832 assert_eq!(idx.find_hex("1a")?, Some(1));
856 assert_eq!(idx.find_hex("1a")?, Some(1));
833
857
834 // reinserting is a no_op
858 // reinserting is a no_op
835 idx.insert(1, "1a34")?;
859 idx.insert(1, "1a34")?;
836 assert_eq!(idx.nt.growable.len(), 1);
860 assert_eq!(idx.nt.growable.len(), 1);
837 assert_eq!(idx.find_hex("12")?, Some(0));
861 assert_eq!(idx.find_hex("12")?, Some(0));
838 assert_eq!(idx.find_hex("1a")?, Some(1));
862 assert_eq!(idx.find_hex("1a")?, Some(1));
839
863
840 idx.insert(2, "1a01")?;
864 idx.insert(2, "1a01")?;
841 assert_eq!(idx.nt.growable.len(), 2);
865 assert_eq!(idx.nt.growable.len(), 2);
842 assert_eq!(idx.find_hex("1a"), Err(NodeMapError::MultipleResults));
866 assert_eq!(idx.find_hex("1a"), Err(NodeMapError::MultipleResults));
843 assert_eq!(idx.find_hex("12")?, Some(0));
867 assert_eq!(idx.find_hex("12")?, Some(0));
844 assert_eq!(idx.find_hex("1a3")?, Some(1));
868 assert_eq!(idx.find_hex("1a3")?, Some(1));
845 assert_eq!(idx.find_hex("1a0")?, Some(2));
869 assert_eq!(idx.find_hex("1a0")?, Some(2));
846 assert_eq!(idx.find_hex("1a12")?, None);
870 assert_eq!(idx.find_hex("1a12")?, None);
847
871
848 // now let's make it split and create more than one additional block
872 // now let's make it split and create more than one additional block
849 idx.insert(3, "1a345")?;
873 idx.insert(3, "1a345")?;
850 assert_eq!(idx.nt.growable.len(), 4);
874 assert_eq!(idx.nt.growable.len(), 4);
851 assert_eq!(idx.find_hex("1a340")?, Some(1));
875 assert_eq!(idx.find_hex("1a340")?, Some(1));
852 assert_eq!(idx.find_hex("1a345")?, Some(3));
876 assert_eq!(idx.find_hex("1a345")?, Some(3));
853 assert_eq!(idx.find_hex("1a341")?, None);
877 assert_eq!(idx.find_hex("1a341")?, None);
854
878
855 Ok(())
879 Ok(())
856 }
880 }
857
881
858 #[test]
882 #[test]
859 fn test_insert_extreme_splitting() -> Result<(), NodeMapError> {
883 fn test_insert_extreme_splitting() -> Result<(), NodeMapError> {
860 // check that the splitting loop is long enough
884 // check that the splitting loop is long enough
861 let mut nt_idx = TestNtIndex::new();
885 let mut nt_idx = TestNtIndex::new();
862 let nt = &mut nt_idx.nt;
886 let nt = &mut nt_idx.nt;
863 let idx = &mut nt_idx.index;
887 let idx = &mut nt_idx.index;
864
888
865 let node0_hex = hex_pad_right("444444");
889 let node0_hex = hex_pad_right("444444");
866 let mut node1_hex = hex_pad_right("444444").clone();
890 let mut node1_hex = hex_pad_right("444444").clone();
867 node1_hex.pop();
891 node1_hex.pop();
868 node1_hex.push('5');
892 node1_hex.push('5');
869 let node0 = Node::from_hex(&node0_hex).unwrap();
893 let node0 = Node::from_hex(&node0_hex).unwrap();
870 let node1 = Node::from_hex(&node1_hex).unwrap();
894 let node1 = Node::from_hex(&node1_hex).unwrap();
871
895
872 idx.insert(0, node0.clone());
896 idx.insert(0, node0.clone());
873 nt.insert(idx, &node0, 0)?;
897 nt.insert(idx, &node0, 0)?;
874 idx.insert(1, node1.clone());
898 idx.insert(1, node1.clone());
875 nt.insert(idx, &node1, 1)?;
899 nt.insert(idx, &node1, 1)?;
876
900
877 assert_eq!(nt.find_bin(idx, (&node0).into())?, Some(0));
901 assert_eq!(nt.find_bin(idx, (&node0).into())?, Some(0));
878 assert_eq!(nt.find_bin(idx, (&node1).into())?, Some(1));
902 assert_eq!(nt.find_bin(idx, (&node1).into())?, Some(1));
879 Ok(())
903 Ok(())
880 }
904 }
881
905
882 #[test]
906 #[test]
883 fn test_insert_partly_immutable() -> Result<(), NodeMapError> {
907 fn test_insert_partly_immutable() -> Result<(), NodeMapError> {
884 let mut idx = TestNtIndex::new();
908 let mut idx = TestNtIndex::new();
885 idx.insert(0, "1234")?;
909 idx.insert(0, "1234")?;
886 idx.insert(1, "1235")?;
910 idx.insert(1, "1235")?;
887 idx.insert(2, "131")?;
911 idx.insert(2, "131")?;
888 idx.insert(3, "cafe")?;
912 idx.insert(3, "cafe")?;
889 let mut idx = idx.commit();
913 let mut idx = idx.commit();
890 assert_eq!(idx.find_hex("1234")?, Some(0));
914 assert_eq!(idx.find_hex("1234")?, Some(0));
891 assert_eq!(idx.find_hex("1235")?, Some(1));
915 assert_eq!(idx.find_hex("1235")?, Some(1));
892 assert_eq!(idx.find_hex("131")?, Some(2));
916 assert_eq!(idx.find_hex("131")?, Some(2));
893 assert_eq!(idx.find_hex("cafe")?, Some(3));
917 assert_eq!(idx.find_hex("cafe")?, Some(3));
894
918
895 idx.insert(4, "123A")?;
919 idx.insert(4, "123A")?;
896 assert_eq!(idx.find_hex("1234")?, Some(0));
920 assert_eq!(idx.find_hex("1234")?, Some(0));
897 assert_eq!(idx.find_hex("1235")?, Some(1));
921 assert_eq!(idx.find_hex("1235")?, Some(1));
898 assert_eq!(idx.find_hex("131")?, Some(2));
922 assert_eq!(idx.find_hex("131")?, Some(2));
899 assert_eq!(idx.find_hex("cafe")?, Some(3));
923 assert_eq!(idx.find_hex("cafe")?, Some(3));
900 assert_eq!(idx.find_hex("123A")?, Some(4));
924 assert_eq!(idx.find_hex("123A")?, Some(4));
901
925
902 idx.insert(5, "c0")?;
926 idx.insert(5, "c0")?;
903 assert_eq!(idx.find_hex("cafe")?, Some(3));
927 assert_eq!(idx.find_hex("cafe")?, Some(3));
904 assert_eq!(idx.find_hex("c0")?, Some(5));
928 assert_eq!(idx.find_hex("c0")?, Some(5));
905 assert_eq!(idx.find_hex("c1")?, None);
929 assert_eq!(idx.find_hex("c1")?, None);
906 assert_eq!(idx.find_hex("1234")?, Some(0));
930 assert_eq!(idx.find_hex("1234")?, Some(0));
907
931
908 Ok(())
932 Ok(())
909 }
933 }
910
934
911 #[test]
935 #[test]
912 fn test_into_added_empty() {
936 fn test_into_added_empty() {
913 assert!(sample_nodetree().into_readonly_and_added().1.is_empty());
937 assert!(sample_nodetree().into_readonly_and_added().1.is_empty());
914 assert!(sample_nodetree()
938 assert!(sample_nodetree()
915 .into_readonly_and_added_bytes()
939 .into_readonly_and_added_bytes()
916 .1
940 .1
917 .is_empty());
941 .is_empty());
918 }
942 }
919
943
920 #[test]
944 #[test]
921 fn test_into_added_bytes() -> Result<(), NodeMapError> {
945 fn test_into_added_bytes() -> Result<(), NodeMapError> {
922 let mut idx = TestNtIndex::new();
946 let mut idx = TestNtIndex::new();
923 idx.insert(0, "1234")?;
947 idx.insert(0, "1234")?;
924 let mut idx = idx.commit();
948 let mut idx = idx.commit();
925 idx.insert(4, "cafe")?;
949 idx.insert(4, "cafe")?;
926 let (_, bytes) = idx.nt.into_readonly_and_added_bytes();
950 let (_, bytes) = idx.nt.into_readonly_and_added_bytes();
927
951
928 // only the root block has been changed
952 // only the root block has been changed
929 assert_eq!(bytes.len(), BLOCK_SIZE);
953 assert_eq!(bytes.len(), BLOCK_SIZE);
930 // big endian for -2
954 // big endian for -2
931 assert_eq!(&bytes[4..2 * 4], [255, 255, 255, 254]);
955 assert_eq!(&bytes[4..2 * 4], [255, 255, 255, 254]);
932 // big endian for -6
956 // big endian for -6
933 assert_eq!(&bytes[12 * 4..13 * 4], [255, 255, 255, 250]);
957 assert_eq!(&bytes[12 * 4..13 * 4], [255, 255, 255, 250]);
934 Ok(())
958 Ok(())
935 }
959 }
936 }
960 }
General Comments 0
You need to be logged in to leave comments. Login now