Skip to content

Commit

Permalink
Fix database locking issues setting set_busy_timeout().
Browse files Browse the repository at this point in the history
- Ref: https://www.sqlite.org/c3ref/busy_timeout.html
- Only stablish an initial connection.
  • Loading branch information
Edu4rdSHL committed Apr 17, 2021
1 parent 6572255 commit ce44bf6
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 41 deletions.
32 changes: 28 additions & 4 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,34 @@ pub fn get_args() -> Args {
} else {
return_value_or_default(&settings, "source_dir", String::new())
},
database_file: if matches.is_present("database-file") {
value_t!(matches, "database-file", String).unwrap_or_else(|_| String::new())
} else {
return_value_or_default(&settings, "database_file", String::new())
database_connection: {
let db_file_path = if matches.is_present("database-file") {
value_t!(matches, "database-file", String).unwrap_or_else(|_| String::new())
} else {
return_value_or_default(&settings, "database_file", String::new())
};
if db_file_path.is_empty() {
eprintln!(
"Please specify a database file with -d/--dfile or the database_file option in the config file, it's required for all the operations, leaving."
);
std::process::exit(1)
} else {
match sqlite::open(&db_file_path) {
Ok(mut connection) => {
connection
.set_busy_timeout(5000)
.expect("Failed to set database timeout");
connection
}
Err(e) => {
eprintln!(
"Error while trying to stablish the database connection. Error: {}",
e
);
std::process::exit(1)
}
}
}
},
snapshot_name: String::new(),
snapshot_id: value_t!(matches, "snapshot-id", String).unwrap_or_else(|_| String::new()),
Expand Down
21 changes: 6 additions & 15 deletions src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,21 @@ use {
};

pub fn manage_creation(args: &mut Args) -> Result<()> {
let connection = sqlite::open(&args.database_file)?;
args.snapshot_name = format!(
"{}-{}",
args.snapshot_prefix,
Utc::now().format("%Y-%m-%d-%H-%M-%S-%6f")
);
args.snapshot_id = format!("{:?}", md5::compute(&args.snapshot_name));
if operations::take_snapshot(args) {
database::commit_to_database(&connection, args)?
database::commit_to_database(&args.database_connection, args)?
}
drop(connection);

Ok(())
}

pub fn manage_deletion(args: &mut Args) -> Result<()> {
let connection = sqlite::open(&args.database_file)?;
let snapshot_data = database::return_snapshot_data(&connection, args)?;
let snapshot_data = database::return_snapshot_data(&args.database_connection, args)?;
if !snapshot_data.snap_id.is_empty() {
args.snapshot_name = snapshot_data.destination + &snapshot_data.name;
} else {
Expand All @@ -33,16 +30,14 @@ pub fn manage_deletion(args: &mut Args) -> Result<()> {
)
}
if !args.snapshot_name.is_empty() && operations::del_snapshot(args) {
database::delete_from_database(&connection, args)?
database::delete_from_database(&args.database_connection, args)?
}
drop(connection);

Ok(())
}

pub fn manage_restoring(args: &mut Args) -> Result<()> {
let connection = sqlite::open(&args.database_file)?;
let snapshot_data = database::return_snapshot_data(&connection, args)?;
let snapshot_data = database::return_snapshot_data(&args.database_connection, args)?;
if !snapshot_data.snap_id.is_empty() {
args.snapshot_name = snapshot_data.destination + &snapshot_data.name;
if args.source_dir.is_empty() {
Expand All @@ -60,14 +55,12 @@ pub fn manage_restoring(args: &mut Args) -> Result<()> {
args.snapshot_id, args.source_dir
)
}
drop(connection);

Ok(())
}

pub fn manage_listing(args: &mut Args) -> Result<()> {
let connection = sqlite::open(&args.database_file)?;
let snaps_data = database::return_all_data(&connection)?;
let snaps_data = database::return_all_data(&args.database_connection)?;

let mut table = Table::new();
table.set_titles(row![
Expand All @@ -92,14 +85,12 @@ pub fn manage_listing(args: &mut Args) -> Result<()> {
]);
}
table.printstd();
drop(connection);

Ok(())
}

pub fn keep_only_x(args: &mut Args) -> Result<()> {
let connection = sqlite::open(&args.database_file)?;
let snaps_data = database::return_only_x_items(&connection, args)?;
let snaps_data = database::return_only_x_items(&args.database_connection, args)?;
for data in &snaps_data {
args.snapshot_name = data.destination.clone() + &data.name;
args.snapshot_id = data.snap_id.clone();
Expand Down
7 changes: 0 additions & 7 deletions src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ use {
sqlite::{Connection, State, Statement},
};

pub fn test_database(connection_str: &str) -> Result<()> {
let connection = sqlite::open(&connection_str)?;
drop(connection);

Ok(())
}

pub fn setup_initial_database(connection: &Connection) -> Result<()> {
connection.execute("CREATE TABLE IF NOT EXISTS snapshots (name TEXT NOT NULL, snap_id TEXT NOT NULL, kind TEXT NOT NULL, source TEXT NOT NULL, destination TEXT NOT NULL, ro_rw TEXT NOT NULL, date TEXT DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(name, snap_id))")?;
connection.execute("PRAGMA journal_mode=WAL")?;
Expand Down
15 changes: 2 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
use {
rusnapshot::{args, controller, database, errors::*},
sqlite,
};
use rusnapshot::{args, controller, database, errors::*};

fn run() -> Result<()> {
let mut arguments = args::get_args();

if arguments.database_file.is_empty() {
eprintln!(
"Please specify a database file with -d/--dfile or the database_file option in the config file, it's required for all the operations, leaving."
);
std::process::exit(1)
}

database::test_database(&arguments.database_file)?;
database::setup_initial_database(&sqlite::open(&arguments.database_file)?)?;
database::setup_initial_database(&arguments.database_connection)?;

if arguments.create_snapshot {
controller::manage_creation(&mut arguments)?
Expand Down
5 changes: 3 additions & 2 deletions src/structs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#[derive(Clone, Debug)]
use sqlite::Connection;

pub struct Args {
pub create_snapshot: bool,
pub delete_snapshot: bool,
Expand All @@ -8,7 +9,7 @@ pub struct Args {
pub rw_snapshots: bool,
pub dest_dir: String,
pub source_dir: String,
pub database_file: String,
pub database_connection: Connection,
pub snapshot_name: String,
pub snapshot_id: String,
pub snapshot_prefix: String,
Expand Down

0 comments on commit ce44bf6

Please sign in to comment.