public BlockedCollector(BlockingQueue<string> queue, string rootpath, FilenameFilter filter, FileSystemInteraction folderList, FileSystemInteraction fileList) { m_queue = queue; System.Threading.Thread t = new System.Threading.Thread(BlockedThreadRunner); t.Start(new object[] { rootpath, filter, folderList, fileList}); }
public PathCollector(bool includeFolders, bool includeFiles, FilenameFilter filter) { m_files = new List<string>(); m_filter = filter; m_includeFolders = includeFolders; m_includeFiles = includeFiles; }
/// <summary> /// Calculates the size of files in a given folder /// </summary> /// <param name="folder">The folder to examine</param> /// <param name="filter">A filter to apply</param> /// <returns>The combined size of all files that match the filter</returns> public static long GetDirectorySize(string folder, FilenameFilter filter) { PathSizeCalculator c = new PathSizeCalculator(filter); EnumerateFileSystemEntries(folder, new EnumerationCallbackDelegate(c.Callback)); return c.Size; }
/// <summary> /// Returns a list of folder names found in the given folder. /// The search is recursive. /// </summary> /// <param name="basepath">The folder to look in</param> /// <param name="filter">The filter to apply.</param> /// <returns>A list of the full paths</returns> public static List<string> EnumerateFolders(string basepath, FilenameFilter filter) { PathCollector c = new PathCollector(true, false, filter); EnumerateFileSystemEntries(basepath, new EnumerationCallbackDelegate(c.Callback)); return c.Files; }
/// <summary> /// Returns an IEnumerable with all filesystem entries, recursive /// </summary> /// <param name="rootpath">The folder to look in</param> /// <param name="filter">An optional filter to apply to the filenames</param> /// <param name="callback">The function to call with the filenames</param> /// <param name="folderList">A function to call that lists all folders in the supplied folder</param> /// <param name="fileList">A function to call that lists all files in the supplied folder</param> /// <param name="attributeReader">A function to call that obtains the attributes for an element, set to null to skip symlink detection</param> /// <returns>The file system entries</returns> public static IEnumerable<string> EnumerateFileSystemEntriesBlocked(string rootpath, FilenameFilter filter, FileSystemInteraction folderList, FileSystemInteraction fileList, ExtractFileAttributes attributeReader) { BlockingQueue<string> queue = new BlockingQueue<string>(); new BlockedCollector(queue, rootpath, filter, folderList, fileList); return new BlockingQueueAsEnumerable<string>(queue); }
public PathSizeCalculator(FilenameFilter filter) { m_filter = filter; }
public string Restore(string[] target) { RestoreStatistics rs = new RestoreStatistics(XervBackupOperationMode.Restore); SetupCommonOptions(rs); m_progress = 0; BackendWrapper backend = null; m_restorePatches = 0; using (new Logging.Timer("Restore from " + m_backend + " to " + string.Join(System.IO.Path.PathSeparator.ToString(), target))) { try { if (OperationStarted != null) OperationStarted(this, XervBackupOperation.Restore, rs.OperationMode, -1, -1, Strings.Interface.StatusStarted, ""); OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, -1, -1, Strings.Interface.StatusStarted, ""); Utility.FilenameFilter filter = m_options.Filter; //Filter is prefered, if both file and filter is specified if (!m_options.HasFilter && !string.IsNullOrEmpty(m_options.FileToRestore)) { List<Utility.IFilenameFilter> list = new List<XervBackup.Library.Utility.IFilenameFilter>(); list.Add(new Utility.FilelistFilter(true, m_options.FileToRestore.Split(System.IO.Path.PathSeparator))); list.Add(new Utility.RegularExpressionFilter(false, ".*")); filter = new XervBackup.Library.Utility.FilenameFilter(list); } backend = new BackendWrapper(rs, m_backend, m_options); backend.ProgressEvent += new XervBackup.Library.Main.RSync.RSyncDir.ProgressEventDelegate(BackupTransfer_ProgressEvent); OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, Strings.Interface.StatusReadingIncrementals, ""); ManifestEntry bestFit = backend.GetBackupSet(m_options.RestoreTime); //We will need all the manifests downloaded anyway if (!m_options.DontReadManifests) { if (bestFit.Incrementals.Count > 0) VerifyManifestChain(backend, bestFit.Incrementals[bestFit.Incrementals.Count - 1]); else VerifyManifestChain(backend, bestFit); OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, Strings.Interface.StatusReadingIncrementals, ""); } m_progress = INCREMENAL_COST; List<ManifestEntry> entries = new List<ManifestEntry>(); entries.Add(bestFit); entries.AddRange(bestFit.Incrementals); int patchno = 0; foreach (ManifestEntry be in entries) m_restorePatches += be.Volumes.Count; Manifestfile rootManifest = GetManifest(backend, bestFit); int sourceDirCount = (rootManifest.SourceDirs == null || rootManifest.SourceDirs.Length == 0) ? 1 : rootManifest.SourceDirs.Length; //After reading the first manifest, we know the source folder count if ((rootManifest.SourceDirs == null || rootManifest.SourceDirs.Length == 0) && target.Length > 1) { //V1 support rs.LogWarning(string.Format(Strings.Interface.TooManyTargetFoldersWarning, 1, target.Length), null); Array.Resize(ref target, 1); } else if (target.Length > sourceDirCount) { //If we get too many, we can just cut them off rs.LogWarning(string.Format(Strings.Interface.TooManyTargetFoldersWarning, sourceDirCount, target.Length), null); Array.Resize(ref target, rootManifest.SourceDirs.Length); } else if (target.Length != 1 && target.Length < sourceDirCount) { //If we get too few, we have to bail throw new Exception(string.Format(Strings.Interface.TooFewTargetFoldersError, sourceDirCount, target.Length)); } else if (target.Length == 1 && sourceDirCount > 1) { //If there is just one target folder, we automatically compose target subfolders string[] newtargets = new string[rootManifest.SourceDirs.Length]; List<string> suggestions = new List<string>(); for (int i = 0; i < rootManifest.SourceDirs.Length; i++) { string s = rootManifest.SourceDirs[i]; //HACK: We use a leading / in the path name to detect source OS // all paths are absolute, so this detects all unix like systems string dirSepChar = s.StartsWith("/") ? "/" : "\\"; if (s.EndsWith(dirSepChar)) s = s.Substring(0, s.Length - 1); int lix = s.LastIndexOf(dirSepChar); if (lix < 0 || lix + 1 >= s.Length) s = i.ToString(); else s = s.Substring(lix + 1); foreach (char c in System.IO.Path.GetInvalidFileNameChars()) s = s.Replace(c, '_'); suggestions.Add(s); } Dictionary<string, int> duplicates = new Dictionary<string, int>(Library.Utility.Utility.ClientFilenameStringComparer); for (int i = 0; i < suggestions.Count; i++) if (duplicates.ContainsKey(suggestions[i])) duplicates[suggestions[i]]++; else duplicates[suggestions[i]] = 1; for (int i = 0; i < newtargets.Length; i++) { string suffix = duplicates[suggestions[i]] > 1 ? i.ToString() : suggestions[i]; newtargets[i] = System.IO.Path.Combine(target[0], suffix); } target = newtargets; } //Make sure all targets exist foreach(string s in target) if (!System.IO.Directory.Exists(s)) System.IO.Directory.CreateDirectory(s); using (RSync.RSyncDir sync = new XervBackup.Library.Main.RSync.RSyncDir(target, rs, filter)) { sync.ProgressEvent += new XervBackup.Library.Main.RSync.RSyncDir.ProgressEventDelegate(RestoreRSyncDir_ProgressEvent); foreach (ManifestEntry be in entries) { m_progress = ((1.0 - INCREMENAL_COST) * (patchno / (double)m_restorePatches)) + INCREMENAL_COST; CheckLiveControl(); Manifestfile manifest = be == bestFit ? rootManifest : GetManifest(backend, be); CheckLiveControl(); foreach (KeyValuePair<SignatureEntry, ContentEntry> vol in be.Volumes) { ContentEntry contentVol = vol.Value; SignatureEntry signatureVol = vol.Key; m_progress = ((1.0 - INCREMENAL_COST) * (patchno / (double)m_restorePatches)) + INCREMENAL_COST; //Skip nonlisted if (manifest.ContentHashes != null && contentVol.Volumenumber > manifest.ContentHashes.Count) { Logging.Log.WriteMessage(string.Format(Strings.Interface.SkippedContentVolumeLogMessage, contentVol.Volumenumber), XervBackup.Library.Logging.LogMessageType.Warning); rs.LogWarning(string.Format(Strings.Interface.SkippedContentVolumeLogMessage, contentVol.Volumenumber), null); patchno++; continue; } using (Utility.TempFile patchzip = new XervBackup.Library.Utility.TempFile()) { OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusPatching, patchno + 1), ""); CheckLiveControl(); if (m_options.HasFilter || !string.IsNullOrEmpty(m_options.FileToRestore)) { bool hasFiles = false; using (Utility.TempFile sigFile = new XervBackup.Library.Utility.TempFile()) { OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusDownloadingSignatureVolume, patchno + 1), ""); try { using (new Logging.Timer("Get " + signatureVol.Filename)) backend.Get(signatureVol, manifest, sigFile, manifest.SignatureHashes == null ? null : manifest.SignatureHashes[signatureVol.Volumenumber - 1]); } catch (BackendWrapper.HashMismathcException hme) { hasFiles = true; rs.LogError(string.Format(Strings.Interface.FileHashFailure, hme.Message), hme); } if (!hasFiles) using (Library.Interface.ICompression patch = DynamicLoader.CompressionLoader.GetModule(signatureVol.Compression, sigFile, m_options.RawOptions)) { foreach(KeyValuePair<RSync.RSyncDir.PatchFileType, string> k in sync.ListPatchFiles(patch)) if (filter.ShouldInclude("", System.IO.Path.DirectorySeparatorChar.ToString() + k.Value)) { //TODO: Perhaps a bit much to download the content archive // if the file is only marked for deletion? hasFiles = true; break; } } } if (!hasFiles) { //Avoid downloading the content file patchno++; continue; } } OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusDownloadingContentVolume, patchno + 1), ""); using (new Logging.Timer("Get " + contentVol.Filename)) backend.Get(contentVol, manifest, patchzip, manifest.ContentHashes == null ? null : manifest.ContentHashes[contentVol.Volumenumber - 1]); OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusPatching, patchno + 1), ""); using (new Logging.Timer((patchno == 0 ? "Full restore to: " : "Incremental restore " + patchno.ToString() + " to: ") + string.Join(System.IO.Path.PathSeparator.ToString(), target))) using (Library.Interface.ICompression patch = DynamicLoader.CompressionLoader.GetModule(contentVol.Compression, patchzip, m_options.RawOptions)) sync.Patch(target, patch); } patchno++; } //Make sure there are no partial files, as partial files are not allowed to span backup sets sync.FinalizeRestore(); } } } finally { if (backend != null) backend.Dispose(); if (OperationCompleted != null) OperationCompleted(this, XervBackupOperation.Restore, rs.OperationMode, 100, -1, Strings.Interface.StatusCompleted, ""); OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, 100, -1, Strings.Interface.StatusCompleted, ""); } } rs.EndTime = DateTime.Now; return rs.ToString(); }