fn copy_recursively_respecting_tombstones(
    log: &ReplicaLogger,
    root_src: &Path,
    root_dst: &Path,
    dst_permissions: FilePermissions,
    thread_pool: Option<&mut scoped_threadpool::Pool>,
) -> std::io::Result<()> {
    let mut copy_plan = CopyPlan {
        create_and_sync_dir: vec![],
        copy_and_sync_file: vec![],
    };

    build_copy_plan(root_src, root_dst, &mut copy_plan)?;

    // Ensure that the target root directory exists.
    // Note: all the files and directories below the target root (including the
    // target root itself) will be synced after this function returns.  However,
    // create_dir_all might create some parents that won't be synced. It's fine
    // because:
    //   1. We only care about internal consistency of checkpoints, and the
    //   parents create_dir_all might have created do not belong to a
    //   checkpoint.
    //
    //   2. We only invoke this function with DST being a child of a
    //   directory that is wiped out on replica start, so we don't care much
    //   about this temporary directory being properly synced.
    fs::create_dir_all(&root_dst)?;
    match thread_pool {
        Some(thread_pool) => {
            let results = parallel_map(thread_pool, copy_plan.create_and_sync_dir.iter(), |op| {
                fs::create_dir_all(&op.dst)
            });
            results.into_iter().try_for_each(identity)?;
            let results = parallel_map(thread_pool, copy_plan.copy_and_sync_file.iter(), |op| {
                copy_and_sync_file(log, &op.src, &op.dst, dst_permissions)
            });
            results.into_iter().try_for_each(identity)?;
            let results = parallel_map(thread_pool, copy_plan.create_and_sync_dir.iter(), |op| {
                sync_path(&op.dst)
            });
            results.into_iter().try_for_each(identity)?;
        }
        None => {
            for op in copy_plan.create_and_sync_dir.iter() {
                fs::create_dir_all(&op.dst)?;
            }
            for op in copy_plan.copy_and_sync_file.into_iter() {
                copy_and_sync_file(log, &op.src, &op.dst, dst_permissions)?;
            }
            for op in copy_plan.create_and_sync_dir.iter() {
                sync_path(&op.dst)?;
            }
        }
    }
    Ok(())
}
/// Recursively copies `src` to `dst` using the given permission policy for
/// files. Directories containing a file called "tombstone" are not copied to
/// the destination. If a thread-pool is provided then files are copied in
/// parallel.
///
/// NOTE: If the function returns an error, the changes to the file
/// system applied by this function are not undone.
Recursively copies `src` to `dst` using the given permission policy for
files. Directories containing a file called "tombstone" are not copied to
the destination. If a thread-pool is provided then files are copied in
parallel.

If the function returns an error, the changes to the file
system applied by this function are not undone.
Recursively copies ` src ` to ` dst ` using the given permission policy for files . Directories containing a file called " tombstone " are not copied to the destination . If a thread - pool is provided then files are copied in parallel . If the function returns an error the changes to the file system applied by this function are not undone .
fn copy_recursively_respecting_tombstones(
    log: &ReplicaLogger,
    root_src: &Path,
    root_dst: &Path,
    dst_permissions: FilePermissions,
    thread_pool: Option<&mut scoped_threadpool::Pool>,
) -> std::io::Result<()> {
    let mut copy_plan = CopyPlan {
        create_and_sync_dir: vec![],
        copy_and_sync_file: vec![],
    };
    build_copy_plan(root_src, root_dst, &mut copy_plan)?;
    // Ensure that the target root directory exists.
    // Note: all the files and directories below the target root (including the
    // target root itself) will be synced after this function returns.  However,
    // create_dir_all might create some parents that won't be synced. It's fine
    // because:
    //   1. We only care about internal consistency of checkpoints, and the
    //   parents create_dir_all might have created do not belong to a
    //   checkpoint.
    //
    //   2. We only invoke this function with DST being a child of a
    //   directory that is wiped out on replica start, so we don't care much
    //   about this temporary directory being properly synced.
    fs::create_dir_all(&root_dst)?;
    match thread_pool {
        Some(thread_pool) => {
            let results = parallel_map(thread_pool, copy_plan.create_and_sync_dir.iter(), |op| {
                fs::create_dir_all(&op.dst)
            });
            results.into_iter().try_for_each(identity)?;
            let results = parallel_map(thread_pool, copy_plan.copy_and_sync_file.iter(), |op| {
                copy_and_sync_file(log, &op.src, &op.dst, dst_permissions)
            });
            results.into_iter().try_for_each(identity)?;
            let results = parallel_map(thread_pool, copy_plan.create_and_sync_dir.iter(), |op| {
                sync_path(&op.dst)
            });
            results.into_iter().try_for_each(identity)?;
        }
        None => {
            for op in copy_plan.create_and_sync_dir.iter() {
                fs::create_dir_all(&op.dst)?;
            }
            for op in copy_plan.copy_and_sync_file.into_iter() {
                copy_and_sync_file(log, &op.src, &op.dst, dst_permissions)?;
            }
            for op in copy_plan.create_and_sync_dir.iter() {
                sync_path(&op.dst)?;
            }
        }
    }
    Ok(())
}
fn copy_recursively_respecting_tombstones ( log : & ReplicaLogger , root_src : & Path , root_dst : & Path , dst_permissions : FilePermissions , thread_pool : Option < & mut scoped_threadpool :: Pool > , ) -> std :: io :: Result < ( ) > { let mut copy_plan = CopyPlan { create_and_sync_dir : vec ! [ ] , copy_and_sync_file : vec ! [ ] , } ; build_copy_plan ( root_src , root_dst , & mut copy_plan ) ? ; // Ensure that the target root directory exists. // Note: all the files and directories below the target root (including the // target root itself) will be synced after this function returns.  However, // create_dir_all might create some parents that won't be synced. It's fine // because: //   1. We only care about internal consistency of checkpoints, and the //   parents create_dir_all might have created do not belong to a //   checkpoint. // //   2. We only invoke this function with DST being a child of a //   directory that is wiped out on replica start, so we don't care much //   about this temporary directory being properly synced. fs :: create_dir_all ( & root_dst ) ? ; match thread_pool { Some ( thread_pool ) => { let results = parallel_map ( thread_pool , copy_plan . create_and_sync_dir . iter ( ) , | op | { fs :: create_dir_all ( & op . dst ) } ) ; results . into_iter ( ) . try_for_each ( identity ) ? ; let results = parallel_map ( thread_pool , copy_plan . copy_and_sync_file . iter ( ) , | op | { copy_and_sync_file ( log , & op . src , & op . dst , dst_permissions ) } ) ; results . into_iter ( ) . try_for_each ( identity ) ? ; let results = parallel_map ( thread_pool , copy_plan . create_and_sync_dir . iter ( ) , | op | { sync_path ( & op . dst ) } ) ; results . into_iter ( ) . try_for_each ( identity ) ? ; } None => { for op in copy_plan . create_and_sync_dir . iter ( ) { fs :: create_dir_all ( & op . dst ) ? ; } for op in copy_plan . copy_and_sync_file . into_iter ( ) { copy_and_sync_file ( log , & op . src , & op . dst , dst_permissions ) ? ; } for op in copy_plan . create_and_sync_dir . iter ( ) { sync_path ( & op . dst ) ? ; } } } Ok ( ( ) ) }
Recursively copies `src` to `dst` using the given permission policy for
files.
Recursively copies ` src ` to ` dst ` using the given permission policy for files .
log
&ReplicaLogger
root_src
&Path
root_dst
&Path
dst_permissions
FilePermissions
thread_pool
Option<&mut scoped_threadpool::Pool>
log
&ReplicaLogger
root_src
&Path
root_dst
&Path
dst_permissions
FilePermissions
thread_pool
Option<&mut scoped_threadpool::Pool>