/// <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);
        }
Пример #2
0
        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;
            }
        }