Esempio n. 1
0
        void Run(ref Continuation Continuation)
        {
            // Setup progress UI...
            Progress      = new ProgressForm();
            Progress.Text = "Verifying archived files for project '" + Project.Name + "'.";
            Progress.OverallProgressBar.Maximum = 10000;
            Progress.OverallProgressBar.Minimum = 0;
            Progress.OverallProgressBar.Value   = 0;
            Progress.CancelPrompt = "Are you sure you wish to cancel this verification operation?";
            Progress.Show();

            try
            {
                System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.BelowNormal;

                ZippyForm.LogWriteLine(LogLevel.Information, "Starting verification of backup '" + Project.Name + "'.");

                string UserTempFolder = Path.GetTempPath();
                TempRoot = new DirectoryInfo(Utility.StripTrailingSlash(UserTempFolder) + "\\ZippyBackup_Verification");
                Directory.CreateDirectory(TempRoot.FullName);

                try
                {
                    Progress.label1.Text = "Retrieving latest archive manifest...";
                    DoEvents();
                    ArchiveFilename LatestBackup;
                    Manifest        LatestManifest;
                    try
                    {
                        using (NetworkConnection newself = new NetworkConnection(Project.CompleteBackupFolder, Project.BackupCredentials))
                        {
                            // Locate latest backup (either complete or incremental.)
                            lock (Project.ArchiveFileList) LatestBackup = Project.ArchiveFileList.FindMostRecent();
                            if (LatestBackup == ArchiveFilename.MaxValue)
                            {
                                throw new NoCompleteBackupException();
                            }

                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "Loading most recent manifest from '" + LatestBackup.ToString() + "' of project '" + Project.Name + "'.");

                            LatestManifest = LatestBackup.LoadArchiveManifest(Project, true);
                        }
                    }
                    catch (CancelException ce) { throw ce; }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message + "  Error while loading last backup for incremental update.", ex);
                    }

                    int StartTick = Environment.TickCount;

                    if (Continuation.Starting)
                    {
                        ZippyForm.LogWriteLine(LogLevel.LightDebug, "Continuing from previous run.  Searching for starting point '" + Continuation.LastRelativePath + "'.");
                    }

                    Continuation MapContinuation = new Continuation();
                    MapContinuation.Starting         = Continuation.Starting;
                    MapContinuation.LastRelativePath = Continuation.LastRelativePath;

                    Continuation.Required = false;
                    while (!Continuation.Required)
                    {
                        /** Operate on a single zip file at a time.  This requires planning which files are
                         *  coming from where.  Also, we count how many total bytes we'll be extracting.  **/
                        Progress.label1.Text = "Identifying required archive files...";
                        DoEvents();
                        List <Manifest.File>   FileList         = new List <Manifest.File>();
                        List <ArchiveFilename> ArchivesRequired = new List <ArchiveFilename>();
                        TotalBytes = 0;

                        /** For extremely large archives, it can happen that even just scanning through the manifest can be very time consuming.  We don't want
                         *  to spend too much time on this step, so we have a time limit for coming up with file/archive list.  But we also have a time limit
                         *  for the overall verify operation.  We use a pattern of spending N minutes coming up with filenames and then processing that bunch,
                         *  then repeating as long as the overall M minute limit hasn't yet been reached.  This requires keeping track of "where we left off"
                         *  for both the scanning operation and the overall verify operation.  If a file hasn't yet been extracted and verified and we have to
                         *  quit because of time or cancellation, then we need the overall "where we left off" to point to the last extracted file, potentially
                         *  repeating a little bit of the mapping time when we startup again.
                         */

                        int MapStartTick = Environment.TickCount;
                        // If the last loop ran into a mapping time limit, initiate a continuation on the mapping.  If the last verification ran into a time limit,
                        // we are also doing a mapping continuation because there is no need to map anything before the first file of the new set.
                        if (MapContinuation.Required)
                        {
                            MapContinuation.Starting = true;
                        }
                        MapContinuation.Required = false;

                        if (MapContinuation.Starting)
                        {
                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "Identifying required archive files, beginning at '" + MapContinuation.LastRelativePath + "'...");
                        }
                        else
                        {
                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "Identifying required archive files...");
                        }

                        MapManifest(LatestManifest.ArchiveRoot, ref FileList, ref ArchivesRequired, ref TotalBytes, ref MapContinuation, ref MapStartTick);

                        if (MapContinuation.Starting)
                        {
                            // We have the case where we never found the continuation marker.  This can happen if the latest archive mismatches
                            // the one where the continuation marker was made.  We just restart from the beginning of the archive.
                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "Continuation marker not found.  Starting verification from beginning.");
                            MapContinuation.Starting = false;
                            Debug.Assert(FileList.Count == 0 && ArchivesRequired.Count == 0);
                            MapStartTick = Environment.TickCount;
                            MapManifest(LatestManifest.ArchiveRoot, ref FileList, ref ArchivesRequired, ref TotalBytes, ref MapContinuation, ref MapStartTick);
                        }

                        ZippyForm.LogWriteLine(LogLevel.LightDebug, "Archives requiring verification (" + ArchivesRequired.Count + "):");
                        foreach (ArchiveFilename Archive in ArchivesRequired)
                        {
                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "\t" + Archive.ToString());
                        }
                        ZippyForm.LogWriteLine(LogLevel.LightDebug, "Starting individual verifications of " + FileList.Count + " files...");

                        // Begin extracting each file and then immediately deleting if successful.
                        int FilesVerified = 0;
                        foreach (ArchiveFilename Archive in ArchivesRequired)
                        {
                            Progress.label1.Text = "Extracting from archive:  " + Archive.ToString();
                            DoEvents();
                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "Verifying archive: " + Archive.ToString());
                            try
                            {
                                using (ZipFile zip = ZipFile.Read(Project.CompleteBackupFolder + "\\" + Archive.ToString()))
                                {
                                    zip.ZipError        += new EventHandler <ZipErrorEventArgs>(OnZipError);
                                    zip.ExtractProgress += new EventHandler <ExtractProgressEventArgs>(OnZipExtractProgress);
                                    foreach (Manifest.File Entry in FileList)
                                    {
                                        ArchiveFilename NeededArchive = ArchiveFilename.Parse(Entry.ArchiveFile);
                                        if (NeededArchive != Archive)
                                        {
                                            continue;
                                        }

                                        RunEntry(zip, Archive, Entry, Utility.StripTrailingSlash(TempRoot.FullName));
                                        FilesVerified++;

                                        if (AutomaticVerify && (Environment.TickCount - StartTick) > MaxAutomaticDurationInTicks)
                                        {
                                            Continuation.Required         = true;
                                            Continuation.Starting         = true;
                                            Continuation.LastRelativePath = Entry.RelativePath;
                                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "New verification continuation marker set to '" + Continuation.LastRelativePath + "'.");
                                            ZippyForm.LogWriteLine(LogLevel.Information, "Verify terminating early due to individual scan time limit.");
                                            break;
                                        }
                                    }
                                }
                            }
                            catch (FileNotFoundException fe)
                            {
                                StringBuilder Msg = new StringBuilder();
                                Msg.Append("Unable to locate file(s) in archive '" + Archive.ToString() + "'.  Do you want to delete this archive so that it will be reconstructed on your next backup?\n\nThe error was: " + fe.Message);
                                switch (MessageBox.Show(Msg.ToString(), "Error", MessageBoxButtons.YesNoCancel))
                                {
                                case DialogResult.Yes: File.Delete(Project.CompleteBackupFolder + "\\" + Archive.ToString()); break;

                                case DialogResult.No: break;

                                case DialogResult.Cancel: throw new CancelException();

                                default: throw new NotSupportedException();
                                }
                            }
                            catch (Ionic.Zip.ZipException ze)
                            {
                                StringBuilder Msg = new StringBuilder();
                                Msg.Append("Unable to extract file(s) from archive '" + Archive.ToString() + "'.  Do you want to delete this archive so that it will be reconstructed on your next backup?\n\nThe error was: " + ze.Message);
                                switch (MessageBox.Show(Msg.ToString(), "Error", MessageBoxButtons.YesNoCancel))
                                {
                                case DialogResult.Yes: File.Delete(Project.CompleteBackupFolder + "\\" + Archive.ToString()); break;

                                case DialogResult.No: break;

                                case DialogResult.Cancel: throw new CancelException();

                                default: throw new NotSupportedException();
                                }
                            }
                            catch (Ionic.Zlib.ZlibException ze)
                            {
                                StringBuilder Msg = new StringBuilder();
                                Msg.Append("Unable to extract file(s) from archive '" + Archive.ToString() + "'.  Do you want to delete this archive so that it will be reconstructed on your next backup?\n\nThe error was: " + ze.Message);
                                switch (MessageBox.Show(Msg.ToString(), "Error", MessageBoxButtons.YesNoCancel))
                                {
                                case DialogResult.Yes: File.Delete(Project.CompleteBackupFolder + "\\" + Archive.ToString()); break;

                                case DialogResult.No: break;

                                case DialogResult.Cancel: throw new CancelException();

                                default: throw new NotSupportedException();
                                }
                            }

                            ZippyForm.LogWriteLine(LogLevel.LightDebug, "Verified " + FilesVerified + " of " + FileList.Count + " files.");

                            if (Continuation.Required)
                            {
                                break;
                            }
                        }

                        if (!MapContinuation.Required)
                        {
                            break;
                        }
                    }

                    string       BackupStatusFile = Project.CompleteBackupFolder + "\\Backup_Status.xml";
                    BackupStatus bs = new BackupStatus();
                    try { bs = BackupStatus.Load(BackupStatusFile); }
                    catch (Exception) { }
                    bs.LastVerify = DateTime.UtcNow;
                    if (!Continuation.Required)
                    {
                        bs.LastCompletedVerify = DateTime.UtcNow;
                    }
                    if (!Continuation.Required)
                    {
                        bs.LastVerifyRelativePath = "";
                    }
                    else
                    {
                        bs.LastVerifyRelativePath = Continuation.LastRelativePath;
                    }
                    bs.Save(BackupStatusFile);

                    ZippyForm.LogWriteLine(LogLevel.Information, "Verification complete.");
                }
                finally
                {
                    Directory.Delete(TempRoot.FullName);
                }
            }
            catch (CancelException ce)
            {
                ZippyForm.LogWriteLine(LogLevel.Information, "Verification cancelled by user before completion.");
                throw ce;
            }
            catch (Exception ex)
            {
                ZippyForm.LogWriteLine(LogLevel.LightDebug, "Verification interrupted by error: " + ex.Message);
                throw ex;
            }
            finally
            {
                Progress.Dispose();
                Progress = null;

                System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Normal;
            }
        }
Esempio n. 2
0
        public void Run()
        {
            // Setup progress UI...
            Progress      = new ProgressForm();
            Progress.Text = "Synchronizing files";
            Progress.OverallProgressBar.Maximum = 10000;
            Progress.OverallProgressBar.Minimum = 0;
            Progress.OverallProgressBar.Value   = 0;
            Progress.Show();

            try
            {
                System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.BelowNormal;

                ZippyForm.LogWriteLine(LogLevel.Information, "Starting synchronize operation for project '" + Project.Name + "'.");

                /** Retrieve newest manifest **/
                ArchiveFilename LatestBackup;
                Manifest        LatestManifest;
                try
                {
                    using (Impersonator newself = new Impersonator(Project.BackupCredentials))
                    {
                        // Locate latest backup (either complete or incremental.)
                        lock (Project.ArchiveFileList) LatestBackup = Project.ArchiveFileList.FindMostRecent();
                        if (LatestBackup == ArchiveFilename.MaxValue)
                        {
                            throw new NoCompleteBackupException();
                        }

                        ZippyForm.LogWriteLine(LogLevel.LightDebug, "Loading most recent manifest from '" + LatestBackup.ToString() + "'.");

                        LatestManifest = LatestBackup.LoadArchiveManifest(Project, true);
                    }
                }
                catch (CancelException ce) { throw ce; }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message + "  Error while loading last backup for sync.", ex);
                }

                SourceRoot = Project.SourceFolder;

                SyncFolder(new DirectoryInfo(Project.SourceFolder), LatestManifest.ArchiveRoot);

                // Update Backup Status file.
                using (Impersonator newself = new Impersonator(Project.BackupCredentials))
                {
                    string       BackupStatusFile = Project.CompleteBackupFolder + "\\Backup_Status.xml";
                    BackupStatus bs = BackupStatus.Load(BackupStatusFile);
                    bs.LastSync = DateTime.UtcNow;
                    bs.Save(BackupStatusFile);
                }
            }
            finally
            {
                Progress.Dispose();
                Progress = null;

                System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Normal;
            }
        }