Skip to content

[Next] simplify AsyncTask code and use RsyncTask to estimate Snapshot size #428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 43 additions & 105 deletions src/Core/Main.vala
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,6 @@ public class Main : GLib.Object{
//global vars for controlling threads
public bool thr_success = false;

public bool thread_estimate_running = false;
public bool thread_estimate_success = false;

public bool thread_restore_running = false;
public bool thread_restore_success = false;

Expand Down Expand Up @@ -227,7 +224,7 @@ public class Main : GLib.Object{
file.delete ();
}

dos_log = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION));
TeeJee.Logging.dos_log = new DataOutputStream (file.create(FileCreateFlags.REPLACE_DESTINATION));
if (LOG_DEBUG || gui_mode){
log_debug(_("Session log file") + ": %s".printf(log_file));
}
Expand Down Expand Up @@ -885,7 +882,8 @@ public class Main : GLib.Object{
}


public bool save_exclude_list_for_backup(string output_path){
// returns the file path on success, null on failure
private string? save_exclude_list_for_backup(string output_path){

log_debug("Main: save_exclude_list_for_backup()");

Expand All @@ -899,7 +897,10 @@ public class Main : GLib.Object{
}

string list_file = path_combine(output_path, "exclude.list");
return file_write(list_file, txt);
if (file_write(list_file, txt)) {
return list_file;
}
return null;
}

public bool save_exclude_list_for_restore(string output_path){
Expand Down Expand Up @@ -1411,11 +1412,9 @@ public class Main : GLib.Object{

// save exclude list ----------------

bool ok = save_exclude_list_for_backup(snapshot_path);

string exclude_from_file = path_combine(snapshot_path, "exclude.list");
string? exclude_from_file = save_exclude_list_for_backup(snapshot_path);

if (!ok){
if (null == exclude_from_file){
log_error("Failed to save exclude list");
return 0;
}
Expand Down Expand Up @@ -1526,11 +1525,9 @@ public class Main : GLib.Object{

// save exclude list ----------------

bool ok = save_exclude_list_for_backup(snapshot_path);

string exclude_from_file = path_combine(snapshot_path, "exclude.list");
string? exclude_from_file = save_exclude_list_for_backup(snapshot_path);

if (!ok){
if (null == exclude_from_file){
log_error(_("Failed to save exclude list"));
return null;
}
Expand All @@ -1557,7 +1554,7 @@ public class Main : GLib.Object{
task.delete_extra = true;
task.delete_excluded = true;
task.delete_after = false;

if (app_mode.length > 0){
// console mode
task.io_nice = true;
Expand All @@ -1578,7 +1575,7 @@ public class Main : GLib.Object{

stdout.printf("\r");
stdout.flush();

if (task.total_size == 0){
log_error(_("rsync returned an error"));
log_error(_("Failed to create new snapshot"));
Expand Down Expand Up @@ -3872,8 +3869,9 @@ public class Main : GLib.Object{

return ok;
}

public uint64 estimate_system_size(){

public delegate void progressCallback();
public uint64 estimate_system_size(progressCallback? callback = null) {

log_debug("estimate_system_size()");

Expand All @@ -3884,105 +3882,45 @@ public class Main : GLib.Object{
return 0;
}

try {
thread_estimate_running = true;
thr_success = false;
new Thread<void>.try ("estimate-system-size", () => {estimate_system_size_thread();});
} catch (Error e) {
thread_estimate_running = false;
thr_success = false;
log_error (e.message);
}

while (thread_estimate_running){
gtk_do_events ();
Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 100);
}

save_app_config();

log_debug("estimate_system_size(): ok");

return Main.first_snapshot_size;
}

public void estimate_system_size_thread(){
thread_estimate_running = true;

string cmd = "";
string std_out;
string std_err;
int ret_val;
uint64 required_space = 0;
int64 file_count = 0;

try{
// create a RsyncTask in dry_run mode to estimate the amount of work needed to do
string dir_empty = path_combine(TEMP_DIR, "empty");
dir_create(dir_empty);

log_debug("Using temp dir '%s'".printf(TEMP_DIR));
task = new RsyncTask();

string file_exclude_list = path_combine(TEMP_DIR, "exclude.list");
var f = File.new_for_path(file_exclude_list);
if (f.query_exists()){
f.delete();
}
task.dest_path = dir_empty;
task.exclude_from_file = save_exclude_list_for_backup(TEMP_DIR) ?? "";;

string file_log = path_combine(TEMP_DIR, "rsync.log");
f = File.new_for_path(file_log);
if (f.query_exists()){
f.delete();
}

string dir_empty = path_combine(TEMP_DIR, "empty");
f = File.new_for_path(dir_empty);
if (!f.query_exists()){
dir_create(dir_empty);
}
task.delete_extra = true;
task.delete_excluded = true;
task.delete_after = false;

save_exclude_list_for_backup(TEMP_DIR);
if (app_mode.length > 0){
// console mode
task.io_nice = true;
}

cmd = "export LC_ALL=C.UTF-8 ; rsync -ai --delete --numeric-ids --relative --stats --dry-run --delete-excluded --exclude-from='%s' /. '%s' &> '%s'".printf(file_exclude_list, dir_empty, file_log);
task.dry_run = true;

log_debug(cmd);
ret_val = exec_script_sync(cmd, out std_out, out std_err);
task.execute();

if (file_exists(file_log)){
cmd = "cat '%s' | awk '/Total file size/ {print $4}'".printf(file_log);
ret_val = exec_script_sync(cmd, out std_out, out std_err);
if (ret_val == 0){
required_space = long.parse(std_out.replace(",","").strip());
file_count = file_line_count(file_log) ?? 0;

thr_success = true;
}
else{
log_error (_("Failed to estimate system size"));
log_error (std_err);
thr_success = false;
}
}
else{
log_error (_("Failed to estimate system size"));
log_error (std_err);
log_error (std_out);
thr_success = false;
}
}
catch(Error e){
log_error (e.message);
thr_success = false;
while (task.status == AppStatus.RUNNING){
Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 16); // ~60fps
if(callback != null) callback();
gtk_do_events();
}

if ((required_space == 0) && (sys_root != null)){
required_space = sys_root.used_bytes;
Main.first_snapshot_size = task.total_size;
Main.first_snapshot_count = task.count_created;
if ((task.total_size == 0) && (sys_root != null)) {
Main.first_snapshot_size = sys_root.used_bytes;
}

Main.first_snapshot_size = required_space;
Main.first_snapshot_count = file_count;

log_debug("First snapshot size: %s".printf(format_file_size(required_space)));
log_debug("File count: %lld".printf(first_snapshot_count));
save_app_config();

thread_estimate_running = false;
log_debug("estimate_system_size(): ok");

return Main.first_snapshot_size;
}

// btrfs
Expand Down
49 changes: 9 additions & 40 deletions src/Gtk/EstimateBox.vala
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ class EstimateBox : Gtk.Box{
private Gtk.ProgressBar progressbar;
private Gtk.Window parent_window;

private bool thread_is_running = false;

public EstimateBox (Gtk.Window _parent_window) {

log_debug("EstimateBox: EstimateBox()");
Expand Down Expand Up @@ -70,62 +68,33 @@ class EstimateBox : Gtk.Box{

//progressbar
progressbar = new Gtk.ProgressBar();
progressbar.pulse_step = 0.01;
//progressbar.set_size_request(-1,25);
//progressbar.pulse_step = 0.1;
add (progressbar);

log_debug("EstimateBox: EstimateBox(): exit");
}

public void estimate_system_size(){
public void estimate_system_size() {

if (Main.first_snapshot_size > 0){
log_debug("EstimateBox: size > 0");
return;
}

progressbar.fraction = 0.0;

// start the estimation if not already running
if (!App.thread_estimate_running){

log_debug("EstimateBox: thread started");

try {
thread_is_running = true;
new Thread<void>.try ("estimate-system-size", () => {estimate_system_size_thread();});
}
catch (Error e) {
thread_is_running = false;
log_error (e.message);
}
}
log_debug("EstimateBox: thread started");

// wait for completion and increment progressbar
while (thread_is_running){

if (progressbar.fraction < 98.0){

progressbar.fraction += 0.005;
#if XAPP
XApp.set_window_progress_pulse(parent_window, true);
#endif
progressbar.pulse();

#if XAPP
XApp.set_window_progress(parent_window, (int)(progressbar.fraction * 100.0));
#endif
}

gtk_do_events();
sleep(100);
}
App.estimate_system_size(progressbar.pulse);

#if XAPP
XApp.set_window_progress(parent_window, 0);
XApp.set_window_progress_pulse(parent_window, false);
#endif
}

private void estimate_system_size_thread(){

App.estimate_system_size();
log_debug("EstimateBox: thread finished");
thread_is_running = false;
}
}
Loading
Loading