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