diff options
Diffstat (limited to 'src/files.rs')
| -rw-r--r-- | src/files.rs | 108 |
1 files changed, 48 insertions, 60 deletions
diff --git a/src/files.rs b/src/files.rs index 46d7727..6b5c20e 100644 --- a/src/files.rs +++ b/src/files.rs @@ -1,15 +1,13 @@ use anyhow::{Result, anyhow}; #[cfg(not(test))] use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}; -use r2d2::Pool; -use r2d2_sqlite::SqliteConnectionManager; -use rayon::prelude::*; +use rusqlite::Connection; use std::{ error::Error, fmt::Display, path::{Path, PathBuf}, sync::{ - Arc, + Arc, Mutex, atomic::{AtomicBool, Ordering}, }, time::UNIX_EPOCH, @@ -51,7 +49,7 @@ impl Display for FileError { impl Error for FileError {} -fn handle_file(file: impl AsRef<Path>, conn: &Database) -> Result<()> { +fn handle_file(file: impl AsRef<Path>, conn: &Connection) -> Result<()> { if conn.check_file(&file)? { let modtime = file .as_ref() @@ -77,7 +75,7 @@ fn handle_file(file: impl AsRef<Path>, conn: &Database) -> Result<()> { pub fn index_files_recursively( path: impl AsRef<Path>, - pool: &Pool<SqliteConnectionManager>, + conn: &Connection, handler: Arc<AtomicBool>, ) -> Result<()> { if !path.as_ref().is_dir() { @@ -105,7 +103,6 @@ pub fn index_files_recursively( } } - let conn = Database::new(pool.get()?); for entry in WalkDir::new(abspath) { if handler.load(Ordering::SeqCst) { let path = entry.unwrap().into_path(); @@ -113,7 +110,7 @@ pub fn index_files_recursively( continue; } if path.extension().is_some_and(|x| x == "flac") { - if let Err(error) = handle_file(&path, &conn) { + if let Err(error) = handle_file(&path, conn) { eprintln!("{}", FileError::new(path, error)); } else { #[cfg(not(test))] @@ -136,11 +133,7 @@ pub fn index_files_recursively( Ok(()) } -pub fn reencode_files( - pool: &Pool<SqliteConnectionManager>, - handler: Arc<AtomicBool>, -) -> Result<()> { - let conn = Database::new(pool.get()?); +pub fn reencode_files(conn: Connection, handler: Arc<AtomicBool>, threads: usize) -> Result<()> { #[cfg(not(test))] let bar = ProgressBar::with_draw_target( Some(conn.get_toencode_number()?), @@ -150,33 +143,42 @@ pub fn reencode_files( .with_message("Reencoding"); let files = conn.get_toencode_files()?; - drop(conn); - files.par_iter().for_each(|file| { - if handler.load(Ordering::SeqCst) { - let conn = match pool.get() { - Ok(conn) => Database::new(conn), - Err(error) => { - eprintln!("{}", FileError::new(file, error.into())); - return; - } - }; + let pool = rayon::ThreadPoolBuilder::new() + .num_threads(threads) + .build()?; - if !file.exists() { - let _ = conn.remove_file(file); - #[cfg(not(test))] - bar.dec_length(1); - return; - } + let lock = Arc::new(Mutex::new(conn)); + + pool.scope(|scope| { + for file in files { + if handler.load(Ordering::SeqCst) { + scope.spawn(|_| { + let newconn = if let Ok(conn) = lock.lock() { + conn + } else { + eprintln!("Error setting up lock on file:\t{}", file.to_string_lossy()); + return; + }; + if !file.exists() { + let _ = newconn.remove_file(&file); + #[cfg(not(test))] + bar.dec_length(1); + return; + } - if let Err(error) = handle_encode(file) { - eprintln!("{}", FileError::new(file, error)); + if let Err(error) = handle_encode(&file) { + eprintln!("{}", FileError::new(&file, error)); + } else { + if let Err(error) = newconn.update_file(&file) { + eprintln!("{}", FileError::new(file, error)); + } + #[cfg(not(test))] + bar.inc(1) + } + }); } else { - if let Err(error) = conn.update_file(file) { - eprintln!("{}", FileError::new(file, error)); - } - #[cfg(not(test))] - bar.inc(1) + break; } } }); @@ -192,10 +194,8 @@ pub fn reencode_files( Ok(()) } -pub fn clean_files(pool: &Pool<SqliteConnectionManager>, handler: Arc<AtomicBool>) -> Result<()> { - let conn = Database::new(pool.get()?); +pub fn clean_files(conn: &Connection, handler: Arc<AtomicBool>) -> Result<()> { let files = conn.init_clean_files()?; - drop(conn); #[cfg(not(test))] let spinner = ProgressBar::with_draw_target(None, ProgressDrawTarget::stdout_with_hz(60)) @@ -203,13 +203,6 @@ pub fn clean_files(pool: &Pool<SqliteConnectionManager>, handler: Arc<AtomicBool files.iter().for_each(|file| { if handler.load(Ordering::SeqCst) && !file.exists() { - let conn = match pool.get() { - Ok(conn) => Database::new(conn), - Err(error) => { - eprintln!("{}", FileError::new(file, error.into())); - return; - } - }; if let Err(error) = conn.remove_file(file) { eprintln!("{}", FileError::new(file, error)) }; @@ -220,8 +213,7 @@ pub fn clean_files(pool: &Pool<SqliteConnectionManager>, handler: Arc<AtomicBool #[cfg(not(test))] spinner.finish(); - let conn = Database::new(pool.get()?); - conn.vaccum()?; + conn.vacuum()?; Ok(()) } @@ -229,14 +221,13 @@ pub fn clean_files(pool: &Pool<SqliteConnectionManager>, handler: Arc<AtomicBool #[cfg(test)] mod tests { use super::*; - use crate::db::*; #[test] fn test_index_lots_of_files() { let dbname = "temp3.db"; let handler = Arc::new(AtomicBool::new(true)); - let pool = open_db(Some(dbname), 10).unwrap(); - index_files_recursively(Path::new("./testfiles"), &pool, handler).unwrap(); + let conn = Connection::new(Some(&dbname)).unwrap(); + index_files_recursively(Path::new("./testfiles"), &conn, handler).unwrap(); std::fs::remove_file(dbname).unwrap(); } @@ -244,8 +235,7 @@ mod tests { fn test_clean_files() { let dbname = "temp4.db"; let handler = Arc::new(AtomicBool::new(true)); - let pool = open_db(Some(dbname), 10).unwrap(); - let conn = Database::new(pool.get().unwrap()); + let conn = Connection::new(Some(&dbname)).unwrap(); let filenames = ["16bit.flac", "24bit.flac", "32bit.flac", "nonexisting.flac"]; std::fs::copy("32bit.flac", "nonexisting.flac").unwrap(); for file in filenames { @@ -254,7 +244,7 @@ mod tests { std::fs::remove_file("nonexisting.flac").unwrap(); - clean_files(&pool, handler).unwrap(); + clean_files(&conn, handler).unwrap(); let counter = conn.init_clean_files().unwrap().len(); std::fs::remove_file(dbname).unwrap(); assert!(counter == 3) @@ -264,14 +254,12 @@ mod tests { fn test_reencode_lots_of_files() { let dbname = "temp5.db"; let handler = Arc::new(AtomicBool::new(true)); - let pool = open_db(Some(dbname), 10).unwrap(); + let conn = Connection::new(Some(&dbname)).unwrap(); let temp = handler.clone(); - index_files_recursively(Path::new("./testfiles"), &pool, temp).unwrap(); - let conn = Database::new(pool.get().unwrap()); + index_files_recursively(Path::new("./testfiles"), &conn, temp).unwrap(); println!("\n{}", conn.get_toencode_number().unwrap()); - drop(conn); - reencode_files(&pool, handler).unwrap(); - let conn = Database::new(pool.get().unwrap()); + reencode_files(conn, handler, 2).unwrap(); + let conn = Connection::new(Some(&dbname)).unwrap(); println!("\n{}", conn.get_toencode_number().unwrap()); std::fs::remove_file(dbname).unwrap(); } |
