// This updates cached XML, will still need flushing to disk afterwards in OutputToXml()
        public void SaveSnapshotRevision(VolumeSnapshot snapshot)
        {
            VolumeSnapshotRevision revision = snapshot.Revision;

            if (mSnapshotDictionary.ContainsKey(revision))
            {
                mSnapshotDictionary[revision] = snapshot;
            }
            else
            {
                mSnapshotDictionary.Add(revision, snapshot);
            }

            System.IO.StringWriter stringWriter = new System.IO.StringWriter();
            XmlTextWriter          xmlWriter    = new XmlTextWriter(stringWriter);

            xmlWriter.Formatting = Formatting.Indented;

            snapshot.OutputToXml(xmlWriter);

            string xmlFragment = stringWriter.ToString();

            xmlWriter.Close();
            stringWriter.Close();

            if (mSnapshotXmlCache.ContainsKey(revision))
            {
                mSnapshotXmlCache[revision] = xmlFragment;
            }
            else
            {
                mSnapshotXmlCache.Add(revision, xmlFragment);
            }
        }
        // This updates cached XML, will still need flushing to disk afterwards in OutputToXml()
        public void SaveSnapshotRevision(VolumeSnapshot snapshot)
        {
            VolumeSnapshotRevision revision = snapshot.Revision;

            if (mSnapshotDictionary.ContainsKey(revision))
            {
                mSnapshotDictionary[revision] = snapshot;
            }
            else
            {
                mSnapshotDictionary.Add(revision, snapshot);
            }
            if (!mSnapshotsStored.Contains(revision))
            {
                mSnapshotsStored.Add(revision);
            }

            PWLib.Platform.Windows.Directory.CreateDirectory(mXmlRootDir);
            XmlTextWriter xmlWriter = new XmlTextWriter(GetRevisionFileName(revision), Encoding.Unicode);

            xmlWriter.Formatting = Formatting.Indented;
            xmlWriter.WriteStartDocument();

            snapshot.OutputToXml(xmlWriter);

            xmlWriter.Close();
        }
示例#3
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);
        }
        void TurnSnapshotIntoBaselinePrivate(VolumeSnapshotDirectory parentDir, ref List <VolumeSnapshotRevision> revisionsThatCanBeRemoved)
        {
            VolumeSnapshotRevision currentRevision = parentDir.Snapshot.Revision;

            foreach (VolumeSnapshotFile file in parentDir.Files)
            {
                if (file.Revision.Value < currentRevision.Value)
                {
                    revisionsThatCanBeRemoved.Add(file.Revision);

                    // file is older than current snapshot, copy it into the current snapshot
                    // Use Move for speed - the file will be deleted in the next step anyway and
                    // will no longer be needed
                    mArchive.MoveFileFromRevision(file.Revision, currentRevision, file.RelativePath);

                    // update revision id in .xml file
                    file.Revision = currentRevision;
                }
            }

            foreach (VolumeSnapshotDirectory dir in parentDir.Directories)
            {
                if (dir.Revision.Value < currentRevision.Value)
                {
                    dir.Revision = currentRevision;
                }
                TurnSnapshotIntoBaselinePrivate(dir, ref revisionsThatCanBeRemoved);
            }
        }
示例#5
0
 public override void RestoreFile(VolumeSnapshotRevision revision, string fileRelativePath, string onDiskOutputPath, ArchiveFileDelegate archiveFileDelegate, object userData)
 {
     if (onDiskOutputPath[onDiskOutputPath.Length - 1] == PWLib.Platform.Windows.Path.DirectorySeparatorChar)
     {
         onDiskOutputPath = onDiskOutputPath.Substring(0, onDiskOutputPath.Length - 1);
     }
     CopyFile(RelativePathToOnDiskPath(revision, fileRelativePath), onDiskOutputPath, archiveFileDelegate, userData);
 }
示例#6
0
 private VolumeSnapshotFile(VolumeSnapshot snapshot, VolumeSource source, string relativePath)
 {
     mSnapshot     = snapshot;
     mRevision     = null;
     mRelativePath = relativePath;
     mFileName     = PWLib.Platform.Windows.Path.GetFileName(relativePath);
     mLastModified = source.GetLastWriteTimeUtc(relativePath);
     mFileSize     = source.GetFileSize(relativePath);
 }
示例#7
0
        public override void CreateDirectory(VolumeSnapshotRevision revision, string relativePath)
        {
            string absPath = RelativePathToOnDiskPath(revision, relativePath);

            if (!PWLib.Platform.Windows.Directory.Exists(absPath))
            {
                PWLib.Platform.Windows.Directory.CreateDirectory(absPath);
            }
        }
 public void DeleteSnapshotRevision(VolumeSnapshotRevision revision)
 {
     if (mSnapshotXmlCache.ContainsKey(revision))
     {
         mSnapshotXmlCache.Remove(revision);
     }
     if (mSnapshotDictionary.ContainsKey(revision))
     {
         mSnapshotDictionary.Remove(revision);
     }
 }
示例#9
0
 public override void DeleteRevision(VolumeSnapshotRevision revision)
 {
     try
     {
         string revisionPath = RelativePathToOnDiskPath(revision, "");
         PWLib.Platform.Windows.Path.DeletePath(revisionPath, true);
         PWLib.Platform.Windows.Directory.Remove(revisionPath, true);
     }
     catch (Exception)
     { }
 }
        private VolumeSnapshot(VolumeSource source, XmlNode parentNode)
        {
            mRevision = VolumeSnapshotRevision.Create(PWLib.XmlHelp.GetAttribute(parentNode, VolumeSnapshotXml.XmlRevisionElement, ""));
            if (mRevision == null)
            {
                throw new Exception("Could not read revision from snapshot xml '" + parentNode.Name + "'");
            }

            mRoot      = VolumeSnapshotDirectory.BuildFromXml(this, PWLib.XmlHelp.GetFirstChildWithName(parentNode, "directory"));
            mFileCount = mRoot.CountAllFiles(ref mTotalFileSize);
        }
        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;
            }
        }
        public void DeleteSnapshotRevision(VolumeSnapshotRevision revision)
        {
            PWLib.Platform.Windows.File.Delete(GetRevisionFileName(revision));

            if (mSnapshotsStored.Contains(revision))
            {
                mSnapshotsStored.Remove(revision);
            }
            if (mSnapshotDictionary.ContainsKey(revision))
            {
                mSnapshotDictionary.Remove(revision);
            }
        }
        private VolumeSnapshotDatabase(XmlNode parentNode)
        {
            XmlNode element = PWLib.XmlHelp.GetFirstChildWithName(parentNode, "snapshots");

            foreach (XmlNode childNode in element.ChildNodes)
            {
                string lowerName = childNode.Name.ToLower();
                if (lowerName == VolumeSnapshotXml.XmlSnapshotElement)
                {
                    string revisionTicks            = PWLib.XmlHelp.GetAttribute(childNode, VolumeSnapshotXml.XmlRevisionElement, "");
                    VolumeSnapshotRevision revision = VolumeSnapshotRevision.Create(revisionTicks);
                    mSnapshotXmlCache.Add(revision, childNode.OuterXml);
                }
            }
        }
示例#14
0
        private VolumeSnapshotFile(VolumeSnapshot snapshot, XmlNode node)
        {
            mSnapshot     = snapshot;
            mFileName     = PWLib.XmlHelp.DirtyString(PWLib.XmlHelp.GetAttribute(node, VolumeSnapshotXml.XmlFilenameElement, ""));
            mRelativePath = PWLib.XmlHelp.DirtyString(PWLib.XmlHelp.GetAttribute(node, VolumeSnapshotXml.XmlRelativePathElement, ""));
            mRevision     = VolumeSnapshotRevision.Create(PWLib.XmlHelp.GetAttribute(node, VolumeSnapshotXml.XmlRevisionElement, ""));

            ulong.TryParse(PWLib.XmlHelp.GetAttribute(node, VolumeSnapshotXml.XmlSizeElement, "0"), out mFileSize);

            long ticks;

            if (long.TryParse(PWLib.XmlHelp.GetAttribute(node, VolumeSnapshotXml.XmlLastModifiedElement, "0"), out ticks))
            {
                mLastModified = new DateTime(ticks);
            }
        }
        public VolumeSnapshot LoadSnapshotRevision(VolumeSource source, VolumeSnapshotRevision revision)
        {
            if (mSnapshotDictionary.ContainsKey(revision))
            {
                return(mSnapshotDictionary[revision]);
            }
            else
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(GetRevisionFileName(revision));

                XmlNode        snapshotXmlNode = PWLib.XmlHelp.GetFirstChildWithName(doc, VolumeSnapshotXml.XmlSnapshotElement);
                VolumeSnapshot snapshot        = VolumeSnapshot.BuildFromXml(source, snapshotXmlNode);
                mSnapshotDictionary.Add(revision, snapshot);
                return(snapshot);
            }
        }
示例#16
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 VolumeSnapshot LoadSnapshotRevision(VolumeSource source, VolumeSnapshotRevision revision)
        {
            if (mSnapshotDictionary.ContainsKey(revision))
            {
                return(mSnapshotDictionary[revision]);
            }
            else
            {
                if (!mSnapshotXmlCache.ContainsKey(revision))
                {
                    throw new Exception("Could not locate snapshot revision '" + revision.ToString() + "' in database");
                }
                string xmlFragment = mSnapshotXmlCache[revision];

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlFragment);

                XmlNode        snapshotXmlNode = PWLib.XmlHelp.GetFirstChildWithName(doc, VolumeSnapshotXml.XmlSnapshotElement);
                VolumeSnapshot snapshot        = VolumeSnapshot.BuildFromXml(source, snapshotXmlNode);
                mSnapshotDictionary.Add(revision, snapshot);
                return(snapshot);
            }
        }
 private VolumeSnapshot(VolumeSource source)
 {
     mRevision  = VolumeSnapshotRevision.CreateNew();
     mRoot      = VolumeSnapshotDirectory.BuildFromSource(this, source, "");
     mFileCount = mRoot.CountAllFiles(ref mTotalFileSize);
 }
示例#19
0
 public abstract void CreateDirectory(VolumeSnapshotRevision revision, string relativePath);
示例#20
0
 public abstract void MoveFileFromRevision(VolumeSnapshotRevision sourceRevision, VolumeSnapshotRevision targetRevision, string fileRelativePath);
示例#21
0
 public abstract void CopyFileFromRevision(VolumeSnapshotRevision sourceRevision, VolumeSnapshotRevision targetRevision, string fileRelativePath, ArchiveFileDelegate archiveFileDelegate, object userData);
示例#22
0
 public abstract void RestoreFile(VolumeSnapshotRevision revision, string fileRelativePath, string onDiskOutputPath, ArchiveFileDelegate archiveFileDelegate, object userData);
示例#23
0
 public abstract void DeleteRevision(VolumeSnapshotRevision revision);
示例#24
0
        private string RelativePathToOnDiskPath(VolumeSnapshotRevision revision, string relativePath)
        {
            string path = mStoragePath + PWLib.Platform.Windows.Path.DirectorySeparatorChar + revision.ToString() + relativePath;

            return(path);
        }
示例#25
0
 public override void StoreFile(VolumeSnapshotRevision revision, string relativePath, string onDiskPath, ArchiveFileDelegate archiveFileDelegate, object userData)
 {
     CopyFile(onDiskPath, RelativePathToOnDiskPath(revision, relativePath), archiveFileDelegate, userData);
 }
示例#26
0
 public override void CopyFileFromRevision(VolumeSnapshotRevision sourceRevision, VolumeSnapshotRevision targetRevision, string fileRelativePath, ArchiveFileDelegate archiveFileDelegate, object userData)
 {
     CopyFile(RelativePathToOnDiskPath(sourceRevision, fileRelativePath), RelativePathToOnDiskPath(targetRevision, fileRelativePath), archiveFileDelegate, userData);
 }
示例#27
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);
        }
示例#28
0
 public abstract void StoreFile(VolumeSnapshotRevision revision, string relativePath, string onDiskPath, ArchiveFileDelegate archiveFileDelegate, object userData);
 string GetRevisionFileName(VolumeSnapshotRevision revision)
 {
     return(mXmlRootDir + PWLib.Platform.Windows.Path.DirectorySeparatorChar + revision.Value.ToString() + ".xml");
 }
示例#30
0
 public override void MoveFileFromRevision(VolumeSnapshotRevision sourceRevision, VolumeSnapshotRevision targetRevision, string fileRelativePath)
 {
     PWLib.Platform.Windows.File.Move(RelativePathToOnDiskPath(sourceRevision, fileRelativePath), RelativePathToOnDiskPath(targetRevision, fileRelativePath));
 }