void CopyFileToBackup(VolumeSnapshotFile file)
 {
     try
     {
         if (!mOperation.CanContinue)
         {
             return;
         }
         file.Revision = file.Snapshot.Revision;
         mArchive.StoreFile(file.Snapshot.Revision, file.RelativePath, mSource.GetOnDiskPath(file.RelativePath), new ArchiveFileDelegate(Backup_ArchiveStoreFile), file);
         ulong runningSize = mFilesTotalSizeRunning + file.FileSize;
         if (runningSize > mFilesTotalSize)
         {
             runningSize = mFilesTotalSize;
         }
         if (Progress != null)
         {
             Progress(mFileRunningCount + 1, mFileTotalCount, runningSize, mFilesTotalSize);
         }
     }
     catch (System.Exception e)
     {
         mOperation.Cancel(false);
         mComparator.Cancel();
         FileSync.__LogError(this, "Copy file failed '" + file.RelativePath + "'", e);
     }
     mFileRunningCount++;
     mFilesTotalSizeRunning += file.FileSize;
 }
Esempio n. 2
0
        public bool Restore(VolumeSnapshotRevision revision, string onDiskPath)
        {
            bool success = false;

            mCancelledByUser = false;

            try
            {
                mBusy = true;

                VolumeSnapshot snapshot = mDatabase.LoadSnapshotRevision(mSource, revision);
                mRestoreOperation.Restore(snapshot, mArchive, onDiskPath);
                success = true;
            }
            catch (Exception e)
            {
                success = false;
                FileSync.__LogError(this, "BackupRestoreVolume.Restore", e);
            }
            finally
            {
                mBusy = false;
            }

            return(success);
        }
        public bool DoIncrementalBackup(VolumeSnapshot currentSnapshot, VolumeSnapshot mostRecentSnapshot, VolumeSource source, BaseArchive archive, out bool noChangesRequired)
        {
            noChangesRequired = false;
            mSource           = source;
            mArchive          = archive;

            // see if anything's changed from the last one
            currentSnapshot.Root.Revision = mostRecentSnapshot.Root.Revision;
            if (mComparator.CompareSnapshots(mostRecentSnapshot, currentSnapshot, true))
            {
                FileSync.__Log(this, "Incremental comparison complete, changes detected");
                FileSync.__Log(this, "Total file count " + mComparator.Stats.FileCount);
                FileSync.__Log(this, "Total file size " + mComparator.Stats.TotalFileSize);
                FileSync.__Log(this, "New files " + mComparator.Stats.FilesCreated);
                FileSync.__Log(this, "Removed files " + mComparator.Stats.FilesRemoved);
                FileSync.__Log(this, "Changed files " + mComparator.Stats.FilesChanged);
                FileSync.__Log(this, "New directories " + mComparator.Stats.DirectoriesCreated);
                FileSync.__Log(this, "Removed directories " + mComparator.Stats.DirectoriesRemoved);
                FileSync.__Log(this, "Files unchanged " + mComparator.Stats.FilesTheSame);
                FileSync.__Log(this, "Directories unchanged " + mComparator.Stats.DirectoriesTheSame);

                mFileTotalCount        = mComparator.Stats.FileCount;
                mFilesTotalSize        = mComparator.Stats.TotalFileSize;
                mFileRunningCount      = 0;
                mFilesTotalSizeRunning = 0;
                mComparator.CompareSnapshots(mostRecentSnapshot, currentSnapshot, false);
                return(!mOperation.Cancelled);
            }
            else
            {
                FileSync.__Log(this, "Incremental comparison complete, no changes detected");
                noChangesRequired = true;
                return(true);
            }
        }
        public void MergeSnapshotRevisionsByTimeLimit(VolumeSnapshotDatabase database, VolumeSource source, BaseArchive archive, TimeSpan timePeriodToKeep)
        {
            // only keep revisions within a certain time period (e.g. last 6 months)
            List <VolumeSnapshotRevision> revisionHistory = database.GetRevisionHistory();
            int      numRevisionsToRemove = 0;
            DateTime cutOffDate           = DateTime.Now - timePeriodToKeep;

            foreach (VolumeSnapshotRevision revision in revisionHistory)
            {
                if (revision.CreationTime >= cutOffDate)
                {
                    break;
                }
                else
                {
                    numRevisionsToRemove++;
                }
            }
            if (numRevisionsToRemove > 0)
            {
                FileSync.__Log(this, "Merge will remove " + numRevisionsToRemove + " revisions");
                MergeSnapshotRevisions(database, source, archive, numRevisionsToRemove);
            }
            else
            {
                FileSync.__Log(this, "Merge will not remove any revisions");
            }
        }
        void MergeSnapshotRevisions(VolumeSnapshotDatabase database, VolumeSource source, BaseArchive archive, int numRevisionsToRemove)
        {
            try
            {
                mDatabase = database;
                mArchive  = archive;
                mBusy     = true;

                List <VolumeSnapshotRevision> revisionHistory = database.GetRevisionHistory();
                if (numRevisionsToRemove == revisionHistory.Count)
                {
                    // Need to remove all old revisions, delete everything
                    FileSync.__Log(this, "Merge deleting all revisions");
                    database.DeleteAllRevisions();
                }
                else
                {
                    // now we know how many revisions to remove, need to rebuild the new first revision.
                    VolumeSnapshotRevision currentRevision = revisionHistory[numRevisionsToRemove];
                    VolumeSnapshot         currentSnapshot = database.LoadSnapshotRevision(source, currentRevision);

                    FileSync.__Log(this, "Merge is turning revision [" + currentRevision.ToString() + "] into baseline");
                    TurnSnapshotIntoBaseline(currentSnapshot);

                    // Now go through all existing snapshot .xml files and change any files referencing
                    // a snapshot that has been removed and change it to the current snapshot revision.
                    for (int revisionNum = numRevisionsToRemove + 1; revisionNum < revisionHistory.Count; ++revisionNum)
                    {
                        VolumeSnapshotRevision incrementalRevision = revisionHistory[revisionNum];
                        VolumeSnapshot         incrementalSnapshot = database.LoadSnapshotRevision(source, incrementalRevision);

                        FileSync.__Log(this, "Merge is reflecting revision [" + incrementalRevision.ToString() + "] into new baseline [" + currentRevision.ToString() + "]");
                        UpdateSnapshotToReflectBaselineRevision(incrementalSnapshot, currentRevision);
                    }

                    // delete old revision data
                    for (int revisionNum = 0; revisionNum < numRevisionsToRemove; ++revisionNum)
                    {
                        VolumeSnapshotRevision revisionToDelete = revisionHistory[revisionNum];
                        FileSync.__Log(this, "Merge is deleting revision [" + revisionToDelete.ToString() + "]");
                        database.DeleteSnapshotRevision(revisionToDelete);
                    }
                }
            }
            catch (System.Exception ex)
            {
                FileSync.__LogError(this, "Volume.CheckForExpiredSnapshotRevisions", ex);
            }
            finally
            {
                mBusy = false;
            }
        }
Esempio n. 6
0
        private VolumeSnapshotDirectory(VolumeSnapshot snapshot, XmlNode parentNode)
        {
            mSnapshot     = snapshot;
            mName         = PWLib.XmlHelp.DirtyString(PWLib.XmlHelp.GetAttribute(parentNode, VolumeSnapshotXml.XmlNameElement, ""));
            mRelativePath = PWLib.XmlHelp.DirtyString(PWLib.XmlHelp.GetAttribute(parentNode, VolumeSnapshotXml.XmlRelativePathElement, ""));
            mRevision     = VolumeSnapshotRevision.Create(PWLib.XmlHelp.GetAttribute(parentNode, VolumeSnapshotXml.XmlRevisionElement, ""));

            long ticks;

            if (long.TryParse(PWLib.XmlHelp.GetAttribute(parentNode, VolumeSnapshotXml.XmlLastModifiedElement, "0"), out ticks))
            {
                mLastModified = new DateTime(ticks);
            }

            foreach (XmlNode childNode in parentNode.ChildNodes)
            {
                string lowerName = childNode.Name.ToLower();
                if (lowerName == VolumeSnapshotXml.XmlDirectoryElement)                   // Sub directories
                {
                    try
                    {
                        VolumeSnapshotDirectory subDirEntry = new VolumeSnapshotDirectory(mSnapshot, childNode);
                        mDirectories.Add(subDirEntry);
                    }
                    catch (System.Exception e)
                    {
                        FileSync.__LogError(this, "VolumeSnapshotDirectory.BuildFromXml failed in directory '" + mName + "' '" + mRelativePath + "'", e);
                    }
                }
                else if (lowerName == VolumeSnapshotXml.XmlFileElement)                   // Files
                {
                    try
                    {
                        VolumeSnapshotFile fileEntry = VolumeSnapshotFile.BuildFromXml(mSnapshot, childNode);
                        mFiles.Add(fileEntry);
                    }
                    catch (System.Exception e)
                    {
                        FileSync.__LogError(this, "VolumeSnapshotDirectory.BuildFromXml failed in directory on a file '" + mName + "' '" + mRelativePath + "'", e);
                    }
                }
            }
        }
        public void MergeSnapshotRevisionsByLimitedRevisionCount(VolumeSnapshotDatabase database, VolumeSource source, BaseArchive archive, int maxRevisions)
        {
            // only keep a specific number of revisions
            List <VolumeSnapshotRevision> revisionHistory = database.GetRevisionHistory();
            int numRevisionsToRemove = 0;

            if (revisionHistory.Count > maxRevisions)
            {
                numRevisionsToRemove = revisionHistory.Count - maxRevisions;
            }
            if (numRevisionsToRemove > 0)
            {
                FileSync.__Log(this, "Merge will remove " + numRevisionsToRemove + " revisions");
                MergeSnapshotRevisions(database, source, archive, numRevisionsToRemove);
            }
            else
            {
                FileSync.__Log(this, "Merge will not remove any revisions");
            }
        }
Esempio n. 8
0
        private VolumeSnapshotDirectory(VolumeSnapshot snapshot, VolumeSource source, string relativePath)
        {
            mSnapshot     = snapshot;
            mRelativePath = relativePath;
            mName         = mRelativePath.Length <= 1 ? "" : PWLib.Platform.Windows.Path.GetLeafName(relativePath);
            mLastModified = source.GetLastWriteTimeUtc(relativePath);              // PWLib.Platform.Windows.Directory.GetLastWriteTimeUtc( rootDir );

            foreach (string filename in source.GetRelativePathFiles(relativePath) /* PWLib.Platform.Windows.Directory.GetFiles( rootDir ) */)
            {
                try
                {
                    VolumeSnapshotFile fileEntry = VolumeSnapshotFile.BuildFromSource(mSnapshot, source, filename);
                    mFiles.Add(fileEntry);
                }
                catch (System.Exception e)
                {
                    FileSync.__LogError(this, "VolumeSnapshotDirectory.BuildFromFileSystem failed on file '" + filename + "'", e);
                }
            }

            foreach (string subDir in source.GetRelativePathDirectories(relativePath))
            {
                try
                {
                    if (!IsIgnoredDirectoryName(PWLib.Platform.Windows.Path.GetLeafName(subDir)))
                    {
                        VolumeSnapshotDirectory subDirEntry = new VolumeSnapshotDirectory(mSnapshot, source, subDir);
                        mDirectories.Add(subDirEntry);
                    }
                }
                catch (System.Exception e)
                {
                    FileSync.__LogError(this, "VolumeSnapshotDirectory.BuildFromFileSystem failed on directory '" + subDir + "'", e);
                }
            }
        }
Esempio n. 9
0
        public bool DoBackup(ref bool outputToXmlRequired)
        {
            VolumeSnapshot currentSnapshot   = null;
            bool           backupSuccess     = false;
            bool           noChangesRequired = false;

            outputToXmlRequired = false;
            mCancelledByUser    = false;

            try
            {
                mBusy = true;

                FileSync.__Log(this, "Building standing on disk snapshot...");

                // Take a snapshot of the volume as it stands on disk
                currentSnapshot = VolumeSnapshot.BuildFromSource(mSource);

                if (!currentSnapshot.Empty)
                {
                    FileSync.__Log(this, "Snapshot built, " + currentSnapshot.FileCount + " files found");

                    VolumeSnapshotRevision mostRecentRevision = mDatabase.GetMostRecentRevision();

                    // Compare to previous snapshot
                    if (mostRecentRevision != null)
                    {
                        FileSync.__Log(this, "Starting incremental backup, " + mDatabase.GetRevisionHistory().Count
                                       + " revisions existing [Most recent: " + mostRecentRevision.ToString() + "]");

                        // Only do an incremental backup to backup whats changed since last full snapshot
                        VolumeSnapshot mostRecentSnapshot = mDatabase.LoadSnapshotRevision(mSource, mostRecentRevision);
                        backupSuccess = mBackupOperation.DoIncrementalBackup(currentSnapshot, mostRecentSnapshot, mSource, mArchive, out noChangesRequired);

                        FileSync.__Log(this, "Incremental backup " + (backupSuccess ? "completed successfully" : "failed")
                                       + " " + (noChangesRequired ? "no changes required" : "changes detected"));
                    }
                    else
                    {
                        FileSync.__Log(this, "Starting full initial backup");

                        // Brand new volume backup, do a full backup of the volume
                        backupSuccess = mBackupOperation.DoFullBackup(currentSnapshot, mSource, mArchive);

                        FileSync.__Log(this, "Full backup " + (backupSuccess ? "completed successfully" : "failed"));
                    }

                    if (backupSuccess)
                    {
                        if (!noChangesRequired)
                        {
                            FileSync.__Log(this, "Saving snapshot revision file [" + currentSnapshot.Revision.ToString() + "]");

                            mDatabase.SaveSnapshotRevision(currentSnapshot);
                            outputToXmlRequired = true;

                            FileSync.__Log(this, "Snapshot file saved");
                        }
                        else
                        {
                            FileSync.__Log(this, "No changes required, not saving revision [" + currentSnapshot.Revision.ToString() + "]");
                        }
                    }
                    else
                    {
                        FileSync.__Log(this, "Backup failed, deleting temporary files for revision [" + currentSnapshot.Revision.ToString() + "]");
                        mDatabase.DeleteSnapshotRevision(currentSnapshot.Revision);                           // remove half-copied data
                        mArchive.DeleteRevision(currentSnapshot.Revision);
                        outputToXmlRequired = true;
                    }
                }
                else
                {
                    FileSync.__Log(this, "Built snapshot is empty, aborting backup");
                }
            }
            catch (Exception e)
            {
                backupSuccess = false;
                FileSync.__LogError(this, "BackupRestoreVolume.DoBackup", e);

                if (currentSnapshot != null)
                {
                    FileSync.__Log(this, "Backup failed due to exception caught, deleting temporary files for revision [" + currentSnapshot.Revision.ToString() + "]");
                    mDatabase.DeleteSnapshotRevision(currentSnapshot.Revision);                       // remove half-copied data
                    mArchive.DeleteRevision(currentSnapshot.Revision);
                }
                outputToXmlRequired = true;
            }
            finally
            {
                mBusy = false;
            }

            return(backupSuccess);
        }