/// Traverse node tree, set inode index, ino, child_index and
/// child_count etc according to RAFS format, then store to nodes collection.
Traverse node tree, set inode index, ino, child_index and
child_count etc according to RAFS format, then store to nodes collection.
Traverse node tree set inode index ino child_index and child_count etc according to RAFS format then store to nodes collection .
fn build_rafs(&mut self, tree: &mut Tree, nodes: &mut Vec<Node>) -> Result<()> {
        let index = nodes.len() as u64;
        let parent = &mut nodes[tree.node.index as usize - 1];
        if parent.is_dir() {
            parent.inode.i_child_index = index as u32 + 1;
            parent.inode.i_child_count = tree.children.len() as u32;
        }
        let parent_ino = parent.inode.i_ino;
        // Cache dir tree for BFS walk
        let mut dirs: Vec<&mut Tree> = Vec::new();
        // Sort children list by name,
        // so that we can improve performance in fs read_dir using binary search.
        tree.children
            .sort_by_key(|child| child.node.name().to_os_string());
        for child in tree.children.iter_mut() {
            let index = nodes.len() as u64 + 1;
            child.node.index = index;
            child.node.inode.i_parent = parent_ino;
            // Hardlink handle, all hardlink nodes' ino, nlink should be the same,
            // because the real_ino may be conflicted between different layers,
            // so we need to find hardlink node index list in the layer where the node is located.
            let inode_map = if child.node.overlay.lower_layer() {
                &mut self.lower_inode_map
            } else {
                &mut self.upper_inode_map
            };
            if let Some(indexes) = inode_map.get_mut(&(child.node.real_ino, child.node.dev)) {
                indexes.push(index);
                let first_index = indexes.first().unwrap();
                let nlink = indexes.len() as u32;
                child.node.inode.i_ino = *first_index;
                child.node.inode.i_nlink = nlink;
                // Update nlink for previous hardlink inodes
                for idx in indexes {
                    if index == *idx {
                        continue;
                    }
                    nodes[*idx as usize - 1].inode.i_nlink = nlink;
                }
            } else {
                child.node.inode.i_ino = index;
                child.node.inode.i_nlink = 1;
                // Store inode real ino
                inode_map.insert(
                    (child.node.real_ino, child.node.dev),
                    vec![child.node.index],
                );
            }
            // Store node for bootstrap & blob dump.
            // Put the whiteout file of upper layer in the front of node list for layered build,
            // so that it can be applied to the node tree of lower layer first than other files of upper layer.
            if self.f_parent_bootstrap.is_some() && child.node.whiteout_type().is_some() {
                nodes.insert(0, child.node.clone());
            } else {
                nodes.push(child.node.clone());
            }
            if self.need_prefetch(&child.node) {
                self.readahead_files
                    .insert(child.node.rootfs(), Some(child.node.index));
            }
            // Store chunk for chunk deduplicate
            if child.node.is_reg() {
                for chunk in &child.node.chunks {
                    self.chunk_cache.insert(chunk.block_id, *chunk);
                }
            }
            if child.node.is_dir() {
                dirs.push(child);
            }
        }
        // According to filesystem semantics, a parent dir should have nlink equal to
        // 2 plus the number of its child directory. And in case of layered build,
        // updating parent directory's nlink here is reliable since builder re-constructs
        // the entire tree and intends to layout all inodes into a plain array fetching
        // from the previously applied tree.
        if tree.node.is_dir() {
            let parent_dir = &mut nodes[tree.node.index as usize - 1];
            parent_dir.inode.i_nlink = (2 + dirs.len()) as u32;
        }
        for dir in dirs {
            self.build_rafs(dir, nodes)?;
        }
        Ok(())
    }
fn build_rafs ( & mut self , tree : & mut Tree , nodes : & mut Vec < Node > ) -> Result < ( ) > { let index = nodes . len ( ) as u64 ; let parent = & mut nodes [ tree . node . index as usize - 1 ] ; if parent . is_dir ( ) { parent . inode . i_child_index = index as u32 + 1 ; parent . inode . i_child_count = tree . children . len ( ) as u32 ; } let parent_ino = parent . inode . i_ino ; // Cache dir tree for BFS walk let mut dirs : Vec < & mut Tree > = Vec :: new ( ) ; // Sort children list by name, // so that we can improve performance in fs read_dir using binary search. tree . children . sort_by_key ( | child | child . node . name ( ) . to_os_string ( ) ) ; for child in tree . children . iter_mut ( ) { let index = nodes . len ( ) as u64 + 1 ; child . node . index = index ; child . node . inode . i_parent = parent_ino ; // Hardlink handle, all hardlink nodes' ino, nlink should be the same, // because the real_ino may be conflicted between different layers, // so we need to find hardlink node index list in the layer where the node is located. let inode_map = if child . node . overlay . lower_layer ( ) { & mut self . lower_inode_map } else { & mut self . upper_inode_map } ; if let Some ( indexes ) = inode_map . get_mut ( & ( child . node . real_ino , child . node . dev ) ) { indexes . push ( index ) ; let first_index = indexes . first ( ) . unwrap ( ) ; let nlink = indexes . len ( ) as u32 ; child . node . inode . i_ino = * first_index ; child . node . inode . i_nlink = nlink ; // Update nlink for previous hardlink inodes for idx in indexes { if index == * idx { continue ; } nodes [ * idx as usize - 1 ] . inode . i_nlink = nlink ; } } else { child . node . inode . i_ino = index ; child . node . inode . i_nlink = 1 ; // Store inode real ino inode_map . insert ( ( child . node . real_ino , child . node . dev ) , vec ! [ child node index ] , ) ; } // Store node for bootstrap & blob dump. // Put the whiteout file of upper layer in the front of node list for layered build, // so that it can be applied to the node tree of lower layer first than other files of upper layer. if self . f_parent_bootstrap . is_some ( ) && child . node . whiteout_type ( ) . is_some ( ) { nodes . insert ( 0 , child . node . clone ( ) ) ; } else { nodes . push ( child . node . clone ( ) ) ; } if self . need_prefetch ( & child . node ) { self . readahead_files . insert ( child . node . rootfs ( ) , Some ( child . node . index ) ) ; } // Store chunk for chunk deduplicate if child . node . is_reg ( ) { for chunk in & child . node . chunks { self . chunk_cache . insert ( chunk . block_id , * chunk ) ; } } if child . node . is_dir ( ) { dirs . push ( child ) ; } } // According to filesystem semantics, a parent dir should have nlink equal to // 2 plus the number of its child directory. And in case of layered build, // updating parent directory's nlink here is reliable since builder re-constructs // the entire tree and intends to layout all inodes into a plain array fetching // from the previously applied tree. if tree . node . is_dir ( ) { let parent_dir = & mut nodes [ tree . node . index as usize - 1 ] ; parent_dir . inode . i_nlink = ( 2 + dirs . len ( ) ) as u32 ; } for dir in dirs { self . build_rafs ( dir , nodes ) ? ; } Ok ( ( ) ) }
Traverse node tree, set inode index, ino, child_index and
child_count etc according to RAFS format, then store to nodes collection.
Traverse node tree set inode index ino child_index and child_count etc according to RAFS format then store to nodes collection .
&mut self
tree
&mut Tree
nodes
&mut Vec<Node>