/// <summary> /// Goes over every file in a set of restore objects and obtain information. /// </summary> /// <param name="indices">The "indices" field describes which restore /// object to collect information on.</param> /// <param name="skip_file_names">Defaults to true, so to not retrieve file /// names in order to save memory.</param> public RestoreInfo get_info(int[] indices, bool skip_file_names = true) { RestoreInfo restore_info = new RestoreInfo(); if (skip_file_names) { restore_info.file_names = null; } foreach (int i in indices) { restores[i].get_info(restore_info); } return(restore_info); }
internal void get_restore_info_done(RestoreInfo restore_info) { this.restore_info = restore_info; double total_file_size_mb = restore_info.total_file_size / (1024.0 * 1024.0); RestoreInfo_text.Text += "\nTotal file size: " + total_file_size_mb.ToString("F1") + " MB"; // show more GUI if (GetFileNames_cb.IsChecked == true && restore_info.file_names != null) { ShowFileNames_btn.Visibility = Visibility.Visible; } show_or_hide_destination_guis(); show_controls(new UIElement[] { ChooseDestination_text, MultiDestination_rbtn, SingleDestination_rbtn, FNR_Path_text, FNR_Path_tb, FNR_Path_btn, StartRestore_btn }); // Allocate mapping_list and bind to data grid mapping_list = new List <PrefixMapping>(); foreach (var prefix in restore_info.embedded_prefixes) { string destination = ""; if (app.restore_manager.default_destinations.ContainsKey(prefix)) { destination = app.restore_manager.default_destinations[prefix]; } mapping_list.Add(new PrefixMapping(prefix, destination)); } EmbeddedPrefix_datagrid.ItemsSource = mapping_list; }
/// <summary> /// Event handler for events issued by the backup manager thread. /// This function runs on the backup manager thread, so it cannot /// access the GUI elements directly. /// </summary> void handle_event(AppEventType event_type, params object[] param_array) { if (event_type == AppEventType.LOG) { string text = (string)param_array[0]; add_line_of_text(text); } else if (event_type == AppEventType.ERROR) { app_mode = AppMode.ERROR; Output_tb.Dispatcher.BeginInvoke(new Func_Icon(change_notify_icon), error_icon); var error_message = (string)param_array[0]; Output_tb.Dispatcher.BeginInvoke( new Func_string(show_error_message_box), error_message); add_line_of_text(error_message); } else if (event_type == AppEventType.CHECK_BACKUPS_DONE) { // This is the backup manager thread, so better to not call: // backup_manager.start_live_backup(); // directly. Better call it via GUI thread, for consistency. Output_tb.Dispatcher.BeginInvoke(new Func_void(start_live_backup), null); add_line_of_text("All backups are up to date."); } else if (event_type == AppEventType.GET_RESTORE_INFO_DONE) { if (app_mode == AppMode.RESTORE_GET_INFO) { RestoreInfo info = (RestoreInfo)param_array[0]; RestoreInfo_text.Dispatcher.BeginInvoke( new Func_RestoreInfo(restore_window.get_restore_info_done), info); app_mode = AppMode.RESTORE_UNDER_WAY; restore_mode_files_processed = 0; } } else if (event_type == AppEventType.FILES_PROCESSED) { int files_processed = (int)param_array[0]; restore_mode_files_processed += files_processed; string progress = "Files processed: " + restore_mode_files_processed.ToString(); if (app_mode == AppMode.RESTORE_GET_INFO) { RestoreInfo_text.Dispatcher.BeginInvoke( new Func_TextBlock_string(set_text_block_text), RestoreInfo_text, progress); } else if (app_mode == AppMode.RESTORE_UNDER_WAY) { RestoreInfo_text.Dispatcher.BeginInvoke( new Func_TextBlock_string(set_text_block_text), RestoreStatus_text, progress); } } else if (event_type == AppEventType.RESTORE_DONE) { if (app_mode == AppMode.RESTORE_UNDER_WAY) { string message = "Files processed: " + restore_mode_files_processed.ToString() + "\nRestore completed."; RestoreInfo_text.Dispatcher.BeginInvoke( new Func_TextBlock_string(set_text_block_text), RestoreStatus_text, message); app_mode = AppMode.RESTORE_DONE; } } else if (event_type == AppEventType.BM_THREAD_IDLE) { if (app_mode != AppMode.ERROR) { Output_tb.Dispatcher.BeginInvoke( new Func_Icon(change_notify_icon), ready_icon); } } else if (event_type == AppEventType.BM_THREAD_RUNNING) { if (app_mode != AppMode.ERROR) { Output_tb.Dispatcher.BeginInvoke( new Func_Icon(change_notify_icon), busy_icon); } } }
/// <summary> /// Goes over every file in this directory / bucket and download its first 1kB /// to get information. Accumulate data in the restore_info object. /// </summary> /// <param name="restore_info">The "file_names" field can be null, which causes /// file names to not get recorded. This will save memory.</param> public void get_info(RestoreInfo restore_info) { // Get a list of alt_file_names. These look like "a1000.bin" string[] alt_file_names = get_alt_file_names(); // To get information, it's only necessary to read the early part of the file. const int bytes_to_read = 1024; byte[] buffer = new byte[bytes_to_read]; int files_processed = 0; // report progress to the GUI // For each alt_file_name, extract info foreach (var alt_file_name in alt_file_names) { // Check alt_file_name format. Work only on files that has the right format. string prefix = null; UInt32 id; break_down_alt_file_name(alt_file_name, ref prefix, out id); if (prefix != null) { // Set up before getting the first bytes. decrypt_stream.reset(null, get_info_handler); handler_called = false; // Read the early bytes. if (cloud_backup == null) { using (var fs = new FileStream(alt_file_name, FileMode.Open, FileAccess.Read)) { int bytes_read = fs.Read(buffer, 0, bytes_to_read); decrypt_stream.Write(buffer, 0, bytes_read); } } else { cloud_backup.download(backup_destination_base, alt_file_name, decrypt_stream, 0, bytes_to_read); } // At this point "handler_called" should have happened. if (handler_called == false) { throw new Exception("Restore file error. While examining the file at \"" + backup_destination_name + "\\" + backup_destination_base + "\\" + alt_file_name + "\", failed to determine the true file name after reading the first " + bytes_to_read + " bytes."); } // At this point, the get_info_handler(...) handler has updated // relative_path and file_pre_encrypt_size. restore_info.total_file_size += total_file_length; // Extract embedded_prefix from relative_path. int index = relative_path.IndexOf('\\'); // If index == -1, this file has no prefix. This should be an error. // But throwing exception aborts the restore. So continue for now. // Just ignore this file. if (index > 0) { string embedded_prefix = relative_path.Substring(0, index); restore_info.embedded_prefixes.Add(embedded_prefix); // The file_names is optional, so test for null. if (restore_info.file_names != null) { if (restore_info.file_names.ContainsKey(embedded_prefix) == false) { restore_info.file_names.Add(embedded_prefix, new List <string>()); } restore_info.file_names[embedded_prefix].Add(relative_path.Substring(index + 1)); } // report progress to the user files_processed++; if (report_event != null) { if (files_processed == 10) { report_event(AppEventType.FILES_PROCESSED, files_processed); files_processed = 0; } } } } } // end of: foreach (var alt_file_name in alt_file_names) if (report_event != null) { report_event(AppEventType.FILES_PROCESSED, files_processed); files_processed = 0; } }