pub(crate) fn copy_chunks(
        log: &ReplicaLogger,
        root_old: &Path,
        root_new: &Path,
        manifest_old: &Manifest,
        manifest_new: &Manifest,
        diff_script: &DiffScript,
    ) {
        use std::os::unix::fs::FileExt;

        type DstIndex = usize;
        type SrcIndex = usize;
        type ChunkGroup = Vec<(DstIndex, SrcIndex)>;
        // Group chunks by the file index to lower cost of opening files.
        // Key is the pair of dst file index and src file index,
        // value is vector of pairs of the dst chunk index and src chunk index.
        let mut chunk_groups: HashMap<(DstIndex, SrcIndex), ChunkGroup> = HashMap::default();

        for (dst_chunk_index, src_chunk_index) in &diff_script.copy_chunks {
            let dst_file_index = manifest_new.chunk_table[*dst_chunk_index].file_index;
            let src_file_index = manifest_old.chunk_table[*src_chunk_index].file_index;
            let entry = chunk_groups
                .entry((dst_file_index as usize, src_file_index as usize))
                .or_insert_with(Vec::new);
            entry.push((*dst_chunk_index, *src_chunk_index));
        }

        for ((dst_file_index, src_file_index), chunk_group) in chunk_groups.iter() {
            let dst_path = root_new.join(&manifest_new.file_table[*dst_file_index].relative_path);
            let src_path = root_old.join(&manifest_old.file_table[*src_file_index].relative_path);
            if dst_path.ends_with("state_file") {
                let src_cow_base_dir = src_path.parent().expect("paths must have a parent");
                let dst_cow_base_dir = dst_path.parent().expect("paths must have a parent");

                let src_cow_mgr =
                    CowMemoryManagerImpl::open_readonly(src_cow_base_dir.to_path_buf());
                let src_mapped_state = src_cow_mgr.get_map();
                src_mapped_state.make_heap_accessible();
                let src_heap_base = src_mapped_state.get_heap_base();

                let dst_cow_mgr =
                    CowMemoryManagerImpl::open_readwrite_statesync(dst_cow_base_dir.to_path_buf());
                let dst_mapped_state = dst_cow_mgr.get_map();

                for (dst_chunk_index, src_chunk_index) in chunk_group {
                    let dst_chunk = &manifest_new.chunk_table[*dst_chunk_index];
                    let src_chunk = &manifest_old.chunk_table[*src_chunk_index];

                    assert_eq!(src_chunk.size_bytes % *PAGE_SIZE as u32, 0);

                    let dst_base_page = dst_chunk.offset / *PAGE_SIZE as u64;
                    let nr_pages = src_chunk.size_bytes / *PAGE_SIZE as u32;

                    let pages_to_copy: Vec<u64> = (0..nr_pages)
                        .map(|page| page as u64 + dst_base_page)
                        .collect();

                    let bytes = unsafe {
                        let base = src_heap_base.add(src_chunk.offset as usize);
                        std::slice::from_raw_parts(base, src_chunk.size_bytes as usize)
                    };
                    dst_mapped_state.copy_to_heap(dst_chunk.offset, &bytes);

                    dst_mapped_state.soft_commit(&pages_to_copy);
                }
                continue;
            }

            let dst = std::fs::OpenOptions::new()
                .write(true)
                .create(false)
                .open(&dst_path)
                .unwrap_or_else(|err| {
                    fatal!(log, "Failed to open file {}: {}", dst_path.display(), err)
                });

            let src = std::fs::File::open(&src_path).unwrap_or_else(|err| {
                fatal!(log, "Failed to open file {}: {}", src_path.display(), err)
            });

            for (dst_chunk_index, src_chunk_index) in chunk_group {
                let dst_chunk = &manifest_new.chunk_table[*dst_chunk_index];
                let src_chunk = &manifest_old.chunk_table[*src_chunk_index];
                let mut buf = vec![0; src_chunk.size_bytes as usize];
                src.read_exact_at(&mut buf[..], src_chunk.offset)
                    .unwrap_or_else(|err| {
                        fatal!(
                            log,
                            "Failed to read chunk (offset = {}, size = {}) from file {}: {}",
                            src_chunk.offset,
                            src_chunk.size_bytes,
                            src_path.display(),
                            err
                        )
                    });

                dst.write_at(&buf, dst_chunk.offset).unwrap_or_else(|err| {
                    fatal!(
                        log,
                        "Failed to write chunk (offset = {}, size = {}) to file {}: {}",
                        dst_chunk.offset,
                        dst_chunk.size_bytes,
                        dst_path.display(),
                        err
                    )
                });
            }
        }
    }
/// Copy reusable chunks from previous checkpoint according to diff script.
Copy reusable chunks from previous checkpoint according to diff script.
Copy reusable chunks from previous checkpoint according to diff script .
pub(crate) fn copy_chunks(
        log: &ReplicaLogger,
        root_old: &Path,
        root_new: &Path,
        manifest_old: &Manifest,
        manifest_new: &Manifest,
        diff_script: &DiffScript,
    ) {
        use std::os::unix::fs::FileExt;
        type DstIndex = usize;
        type SrcIndex = usize;
        type ChunkGroup = Vec<(DstIndex, SrcIndex)>;
        // Group chunks by the file index to lower cost of opening files.
        // Key is the pair of dst file index and src file index,
        // value is vector of pairs of the dst chunk index and src chunk index.
        let mut chunk_groups: HashMap<(DstIndex, SrcIndex), ChunkGroup> = HashMap::default();
        for (dst_chunk_index, src_chunk_index) in &diff_script.copy_chunks {
            let dst_file_index = manifest_new.chunk_table[*dst_chunk_index].file_index;
            let src_file_index = manifest_old.chunk_table[*src_chunk_index].file_index;
            let entry = chunk_groups
                .entry((dst_file_index as usize, src_file_index as usize))
                .or_insert_with(Vec::new);
            entry.push((*dst_chunk_index, *src_chunk_index));
        }
        for ((dst_file_index, src_file_index), chunk_group) in chunk_groups.iter() {
            let dst_path = root_new.join(&manifest_new.file_table[*dst_file_index].relative_path);
            let src_path = root_old.join(&manifest_old.file_table[*src_file_index].relative_path);
            if dst_path.ends_with("state_file") {
                let src_cow_base_dir = src_path.parent().expect("paths must have a parent");
                let dst_cow_base_dir = dst_path.parent().expect("paths must have a parent");
                let src_cow_mgr =
                    CowMemoryManagerImpl::open_readonly(src_cow_base_dir.to_path_buf());
                let src_mapped_state = src_cow_mgr.get_map();
                src_mapped_state.make_heap_accessible();
                let src_heap_base = src_mapped_state.get_heap_base();
                let dst_cow_mgr =
                    CowMemoryManagerImpl::open_readwrite_statesync(dst_cow_base_dir.to_path_buf());
                let dst_mapped_state = dst_cow_mgr.get_map();
                for (dst_chunk_index, src_chunk_index) in chunk_group {
                    let dst_chunk = &manifest_new.chunk_table[*dst_chunk_index];
                    let src_chunk = &manifest_old.chunk_table[*src_chunk_index];
                    assert_eq!(src_chunk.size_bytes % *PAGE_SIZE as u32, 0);
                    let dst_base_page = dst_chunk.offset / *PAGE_SIZE as u64;
                    let nr_pages = src_chunk.size_bytes / *PAGE_SIZE as u32;
                    let pages_to_copy: Vec<u64> = (0..nr_pages)
                        .map(|page| page as u64 + dst_base_page)
                        .collect();
                    let bytes = unsafe {
                        let base = src_heap_base.add(src_chunk.offset as usize);
                        std::slice::from_raw_parts(base, src_chunk.size_bytes as usize)
                    };
                    dst_mapped_state.copy_to_heap(dst_chunk.offset, &bytes);
                    dst_mapped_state.soft_commit(&pages_to_copy);
                }
                continue;
            }
            let dst = std::fs::OpenOptions::new()
                .write(true)
                .create(false)
                .open(&dst_path)
                .unwrap_or_else(|err| {
                    fatal!(log, "Failed to open file {}: {}", dst_path.display(), err)
                });
            let src = std::fs::File::open(&src_path).unwrap_or_else(|err| {
                fatal!(log, "Failed to open file {}: {}", src_path.display(), err)
            });
            for (dst_chunk_index, src_chunk_index) in chunk_group {
                let dst_chunk = &manifest_new.chunk_table[*dst_chunk_index];
                let src_chunk = &manifest_old.chunk_table[*src_chunk_index];
                let mut buf = vec![0; src_chunk.size_bytes as usize];
                src.read_exact_at(&mut buf[..], src_chunk.offset)
                    .unwrap_or_else(|err| {
                        fatal!(
                            log,
                            "Failed to read chunk (offset = {}, size = {}) from file {}: {}",
                            src_chunk.offset,
                            src_chunk.size_bytes,
                            src_path.display(),
                            err
                        )
                    });
                dst.write_at(&buf, dst_chunk.offset).unwrap_or_else(|err| {
                    fatal!(
                        log,
                        "Failed to write chunk (offset = {}, size = {}) to file {}: {}",
                        dst_chunk.offset,
                        dst_chunk.size_bytes,
                        dst_path.display(),
                        err
                    )
                });
            }
        }
    }
pub ( crate ) fn copy_chunks ( log : & ReplicaLogger , root_old : & Path , root_new : & Path , manifest_old : & Manifest , manifest_new : & Manifest , diff_script : & DiffScript , ) { use std :: os :: unix :: fs :: FileExt ; type DstIndex = usize ; type SrcIndex = usize ; type ChunkGroup = Vec < ( DstIndex , SrcIndex ) > ; // Group chunks by the file index to lower cost of opening files. // Key is the pair of dst file index and src file index, // value is vector of pairs of the dst chunk index and src chunk index. let mut chunk_groups : HashMap < ( DstIndex , SrcIndex ) , ChunkGroup > = HashMap :: default ( ) ; for ( dst_chunk_index , src_chunk_index ) in & diff_script . copy_chunks { let dst_file_index = manifest_new . chunk_table [ * dst_chunk_index ] . file_index ; let src_file_index = manifest_old . chunk_table [ * src_chunk_index ] . file_index ; let entry = chunk_groups . entry ( ( dst_file_index as usize , src_file_index as usize ) ) . or_insert_with ( Vec :: new ) ; entry . push ( ( * dst_chunk_index , * src_chunk_index ) ) ; } for ( ( dst_file_index , src_file_index ) , chunk_group ) in chunk_groups . iter ( ) { let dst_path = root_new . join ( & manifest_new . file_table [ * dst_file_index ] . relative_path ) ; let src_path = root_old . join ( & manifest_old . file_table [ * src_file_index ] . relative_path ) ; if dst_path . ends_with ( " " ) { let src_cow_base_dir = src_path . parent ( ) . expect ( " " ) ; let dst_cow_base_dir = dst_path . parent ( ) . expect ( " " ) ; let src_cow_mgr = CowMemoryManagerImpl :: open_readonly ( src_cow_base_dir . to_path_buf ( ) ) ; let src_mapped_state = src_cow_mgr . get_map ( ) ; src_mapped_state . make_heap_accessible ( ) ; let src_heap_base = src_mapped_state . get_heap_base ( ) ; let dst_cow_mgr = CowMemoryManagerImpl :: open_readwrite_statesync ( dst_cow_base_dir . to_path_buf ( ) ) ; let dst_mapped_state = dst_cow_mgr . get_map ( ) ; for ( dst_chunk_index , src_chunk_index ) in chunk_group { let dst_chunk = & manifest_new . chunk_table [ * dst_chunk_index ] ; let src_chunk = & manifest_old . chunk_table [ * src_chunk_index ] ; assert_eq ! ( src_chunk size_bytes PAGE_SIZE as u32 0 ) ; let dst_base_page = dst_chunk . offset / * PAGE_SIZE as u64 ; let nr_pages = src_chunk . size_bytes / * PAGE_SIZE as u32 ; let pages_to_copy : Vec < u64 > = ( 0 .. nr_pages ) . map ( | page | page as u64 + dst_base_page ) . collect ( ) ; let bytes = unsafe { let base = src_heap_base . add ( src_chunk . offset as usize ) ; std :: slice :: from_raw_parts ( base , src_chunk . size_bytes as usize ) } ; dst_mapped_state . copy_to_heap ( dst_chunk . offset , & bytes ) ; dst_mapped_state . soft_commit ( & pages_to_copy ) ; } continue ; } let dst = std :: fs :: OpenOptions :: new ( ) . write ( true ) . create ( false ) . open ( & dst_path ) . unwrap_or_else ( | err | { fatal ! ( log " " dst_path display ( ) err ) } ) ; let src = std :: fs :: File :: open ( & src_path ) . unwrap_or_else ( | err | { fatal ! ( log " " src_path display ( ) err ) } ) ; for ( dst_chunk_index , src_chunk_index ) in chunk_group { let dst_chunk = & manifest_new . chunk_table [ * dst_chunk_index ] ; let src_chunk = & manifest_old . chunk_table [ * src_chunk_index ] ; let mut buf = vec ! [ 0 src_chunk size_bytes as usize ] ; src . read_exact_at ( & mut buf [ .. ] , src_chunk . offset ) . unwrap_or_else ( | err | { fatal ! ( log " " src_chunk offset src_chunk size_bytes src_path display ( ) err ) } ) ; dst . write_at ( & buf , dst_chunk . offset ) . unwrap_or_else ( | err | { fatal ! ( log " " dst_chunk offset dst_chunk size_bytes dst_path display ( ) err ) } ) ; } } }
Copy reusable chunks from previous checkpoint according to diff script.
Copy reusable chunks from previous checkpoint according to diff script .
log
&ReplicaLogger
root_old
&Path
root_new
&Path
manifest_old
&Manifest
manifest_new
&Manifest
diff_script
&DiffScript
log
&ReplicaLogger
root_old
&Path
root_new
&Path
manifest_old
&Manifest
manifest_new
&Manifest
diff_script
&DiffScript