"Fossies" - the Fresh Open Source Software Archive

Member "rustc-1.72.1-src/src/librustdoc/docfs.rs" (13 Sep 2023, 2788 Bytes) of package /linux/misc/rustc-1.72.1-src.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Rust source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "docfs.rs": 1.69.0_vs_1.70.0.

    1 //! Rustdoc's FileSystem abstraction module.
    2 //!
    3 //! On Windows this indirects IO into threads to work around performance issues
    4 //! with Defender (and other similar virus scanners that do blocking operations).
    5 //!
    6 //! Only calls needed to permit this workaround have been abstracted: thus
    7 //! fs::read is still done directly via the fs module; if in future rustdoc
    8 //! needs to read-after-write from a file, then it would be added to this
    9 //! abstraction.
   10 
   11 use std::cmp::max;
   12 use std::fs;
   13 use std::io;
   14 use std::path::{Path, PathBuf};
   15 use std::string::ToString;
   16 use std::sync::mpsc::Sender;
   17 use std::thread::available_parallelism;
   18 use threadpool::ThreadPool;
   19 
   20 pub(crate) trait PathError {
   21     fn new<S, P: AsRef<Path>>(e: S, path: P) -> Self
   22     where
   23         S: ToString + Sized;
   24 }
   25 
   26 pub(crate) struct DocFS {
   27     sync_only: bool,
   28     errors: Option<Sender<String>>,
   29     pool: ThreadPool,
   30 }
   31 
   32 impl DocFS {
   33     pub(crate) fn new(errors: Sender<String>) -> DocFS {
   34         const MINIMUM_NB_THREADS: usize = 2;
   35         DocFS {
   36             sync_only: false,
   37             errors: Some(errors),
   38             pool: ThreadPool::new(
   39                 available_parallelism()
   40                     .map(|nb| max(nb.get(), MINIMUM_NB_THREADS))
   41                     .unwrap_or(MINIMUM_NB_THREADS),
   42             ),
   43         }
   44     }
   45 
   46     pub(crate) fn set_sync_only(&mut self, sync_only: bool) {
   47         self.sync_only = sync_only;
   48     }
   49 
   50     pub(crate) fn close(&mut self) {
   51         self.errors = None;
   52     }
   53 
   54     pub(crate) fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
   55         // For now, dir creation isn't a huge time consideration, do it
   56         // synchronously, which avoids needing ordering between write() actions
   57         // and directory creation.
   58         fs::create_dir_all(path)
   59     }
   60 
   61     pub(crate) fn write<E>(
   62         &self,
   63         path: PathBuf,
   64         contents: impl 'static + Send + AsRef<[u8]>,
   65     ) -> Result<(), E>
   66     where
   67         E: PathError,
   68     {
   69         if !self.sync_only {
   70             // A possible future enhancement after more detailed profiling would
   71             // be to create the file sync so errors are reported eagerly.
   72             let sender = self.errors.clone().expect("can't write after closing");
   73             self.pool.execute(move || {
   74                 fs::write(&path, contents).unwrap_or_else(|e| {
   75                     sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| {
   76                         panic!("failed to send error on \"{}\"", path.display())
   77                     })
   78                 });
   79             });
   80         } else {
   81             fs::write(&path, contents).map_err(|e| E::new(e, path))?;
   82         }
   83 
   84         Ok(())
   85     }
   86 }
   87 
   88 impl Drop for DocFS {
   89     fn drop(&mut self) {
   90         self.pool.join();
   91     }
   92 }