summaryrefslogtreecommitdiff
path: root/src/files.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/files.rs')
-rw-r--r--src/files.rs108
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();
}