public FileScanner(string startDir, Database database, Logger logger, string name, BackendBase[] backends, string fileIgnorePattern, HashSet<string> ignoredFiles, HashSet<string> ignoredFolders) { this.Database = database; this.treeTraverser = new TreeTraverser(startDir, fileIgnorePattern, ignoredFiles, ignoredFolders); this.fileDatabase = new FileDatabase(database); this.backends = backends; foreach (BackendBase backend in this.backends) { backend.CopyProgress += new BackendBase.CopyProgressEventHandler(Backend_CopyProgress); } this.Logger = logger; this.Name = name; }
public FileScanner(string startDir, Database database, Logger logger, string name, BackendBase[] backends, string fileIgnorePattern, HashSet <string> ignoredFiles, HashSet <string> ignoredFolders) { this.Database = database; this.treeTraverser = new TreeTraverser(startDir, fileIgnorePattern, ignoredFiles, ignoredFolders); this.fileDatabase = new FileDatabase(database); this.backends = backends; foreach (BackendBase backend in this.backends) { backend.CopyProgress += new BackendBase.CopyProgressEventHandler(Backend_CopyProgress); } this.Logger = logger; this.Name = name; }
public FolderEntry(TreeTraverser parent, int level, string relPath) { this.parent = parent; this.Level = level; this.RelPath = relPath; this.attributes = new Lazy <FileAttributes>(() => { try { return(new DirectoryInfo(this.FullPath).Attributes); } catch (IOException e) { throw new BackupOperationException(this.RelPath, e.Message); } catch (UnauthorizedAccessException e) { throw new BackupOperationException(this.RelPath, e.Message); } }); }
public override IEnumerable <EntityRecord> ListFilesFolders() { // Just use a TreeTraverser here TreeTraverser treeTraverser = new TreeTraverser(this.Dest); foreach (TreeTraverser.FolderEntry folder in treeTraverser.ListFolders()) { yield return(new EntityRecord(folder.RelPath, Entity.Folder)); foreach (TreeTraverser.FileEntry file in folder.GetFiles()) { yield return(new EntityRecord(file.RelPath, Entity.File)); } } }
public override void PurgeFiles(IEnumerable <string> filesIn, IEnumerable <string> foldersIn, PurgeProgressHandler handler = null) { HashSet <string> files = new HashSet <string>(filesIn); HashSet <string> folders = new HashSet <string>(foldersIn); // Just use a TreeTraverser here TreeTraverser treeTraverser = new TreeTraverser(this.Dest); foreach (TreeTraverser.FolderEntry folder in treeTraverser.ListFolders()) { try { if (folders.Contains(folder.RelPath)) { if (handler != null && !handler(Entity.Folder, folder.RelPath, false)) { return; } foreach (TreeTraverser.FileEntry file in folder.GetFiles()) { if (!files.Contains(file.RelPath)) { File.Delete(file.FullPath); if (handler != null && !handler(Entity.File, file.RelPath, true)) { return; } } else { if (handler != null && !handler(Entity.File, file.RelPath, false)) { return; } } } } else { Directory.Delete(folder.FullPath); if (handler != null && !handler(Entity.Folder, folder.RelPath, true)) { return; } } } // Don't yet have a way of logging from in here catch (BackupOperationException) { } } }
public void Populate(string startDir, string ignoreRules) { // Get rid of anything there before this.tree.Nodes.Clear(); // aaand start again! TreeTraverser treeTraverser = new TreeTraverser(startDir, ignoreRules); TreeNodeTri node; TreeTraverser.FolderEntry root = treeTraverser.ListFolders(0).First(); foreach (TreeTraverser.FolderEntry folder in root.GetFolders()) { node = new TreeNodeTri(folder, this.tree.ImageList, this.IgnoredFiles, this.IgnoredFolders, this.tree); node.Populate(); this.tree.Nodes.Add(node); } foreach (TreeTraverser.FileEntry file in root.GetFiles()) { this.tree.Nodes.Add(new TreeNodeTri(file, this.tree.ImageList, this.IgnoredFiles, this.IgnoredFolders, this.tree)); } }
public FileEntry(TreeTraverser parent, string relPath) { this.parent = parent; this.RelPath = relPath; this.lastModified = new Lazy <DateTime>(() => { try { return(File.GetLastWriteTimeUtc(this.FullPath)); } catch (IOException e) { throw new BackupOperationException(this.RelPath, e.Message); } catch (UnauthorizedAccessException e) { throw new BackupOperationException(this.RelPath, e.Message); } }); this.attributes = new Lazy <FileAttributes>(() => { try { return(new FileInfo(this.FullPath).Attributes); } catch (IOException e) { throw new BackupOperationException(this.RelPath, e.Message); } catch (UnauthorizedAccessException e) { throw new BackupOperationException(this.RelPath, e.Message); } }); }
public FileEntry(TreeTraverser parent, string relPath) { this.parent = parent; this.RelPath = relPath; this.lastModified = new Lazy<DateTime>(() => { try { return File.GetLastWriteTimeUtc(this.FullPath); } catch (IOException e) { throw new BackupOperationException(this.RelPath, e.Message); } catch (UnauthorizedAccessException e) { throw new BackupOperationException(this.RelPath, e.Message); } }); this.attributes = new Lazy<FileAttributes>(() => { try { return new FileInfo(this.FullPath).Attributes; } catch (IOException e) { throw new BackupOperationException(this.RelPath, e.Message); } catch (UnauthorizedAccessException e) { throw new BackupOperationException(this.RelPath, e.Message); } }); }
public FolderEntry(TreeTraverser parent, int level, string relPath) { this.parent = parent; this.Level = level; this.RelPath = relPath; this.attributes = new Lazy<FileAttributes>(() => { try { return new DirectoryInfo(this.FullPath).Attributes; } catch (IOException e) { throw new BackupOperationException(this.RelPath, e.Message); } catch (UnauthorizedAccessException e) { throw new BackupOperationException(this.RelPath, e.Message); } }); }
private int addFolder(TreeTraverser.FolderEntry folder) { foreach (BackendBase backend in this.backends) { this.reportBackupAction(new BackupActionItem(null, folder.RelPath, BackupActionEntity.Folder, BackupActionOperation.Add, backend.Name)); backend.CreateFolder(folder.RelPath, folder.Attributes); this.Logger.Info("{0}: Added folder: {1}", backend.Name, folder.RelPath); } int insertedId = this.fileDatabase.AddFolder(folder.RelPath); return insertedId; }
public TreeNodeTri(TreeTraverser.FileEntry fileEntry, ImageList imageList, HashSet<string> ignoredFiles, HashSet<string> ignoredFolders, TreeView parentTree, CheckedState defaultState=CheckedState.Checked) : base(fileEntry.Filename) { this.imageList = imageList; if (ignoredFiles.Contains(fileEntry.FullPath)) this.State = CheckedState.Unchecked; else this.State = defaultState; this.StateImageIndex = (int)this.State; this.ignoredFiles = ignoredFiles; this.ignoredFolders = ignoredFolders; this.parentTree = parentTree; this.fileEntry = fileEntry; if (!imageList.Images.ContainsKey(fileEntry.Extension)) { Icon icon = Icon.ExtractAssociatedIcon(fileEntry.FullPath); imageList.Images.Add(fileEntry.Extension, icon); } this.ImageKey = fileEntry.Extension; this.SelectedImageKey = fileEntry.Extension; }
public TreeNodeTri(TreeTraverser.FolderEntry folderEntry, ImageList imageList, HashSet<string> ignoredFiles, HashSet<string> ignoredFolders, TreeView parentTree, CheckedState defaultState=CheckedState.Checked) : base(folderEntry.Name) { this.imageList = imageList; if (ignoredFolders.Contains(folderEntry.FullPath)) { this.State = CheckedState.Unchecked; // No children yet to update } else this.State = defaultState; this.StateImageIndex = (int)this.State; this.ignoredFiles = ignoredFiles; this.ignoredFolders = ignoredFolders; this.parentTree = parentTree; this.folderEntry = folderEntry; this.ImageIndex = 0; this.SelectedImageIndex = 0; }
public override void PurgeFiles(IEnumerable<string> filesIn, IEnumerable<string> foldersIn, PurgeProgressHandler handler=null) { HashSet<string> files = new HashSet<string>(filesIn); HashSet<string> folders = new HashSet<string>(foldersIn); // Just use a TreeTraverser here TreeTraverser treeTraverser = new TreeTraverser(this.Dest); foreach (TreeTraverser.FolderEntry folder in treeTraverser.ListFolders()) { try { if (folders.Contains(folder.RelPath)) { if (handler != null && !handler(Entity.Folder, folder.RelPath, false)) return; foreach (TreeTraverser.FileEntry file in folder.GetFiles()) { if (!files.Contains(file.RelPath)) { File.Delete(file.FullPath); if (handler != null && !handler(Entity.File, file.RelPath, true)) return; } else { if (handler != null && !handler(Entity.File, file.RelPath, false)) return; } } } else { Directory.Delete(folder.FullPath); if (handler != null && !handler(Entity.Folder, folder.RelPath, true)) return; } } // Don't yet have a way of logging from in here catch (BackupOperationException) { } } }
public override IEnumerable<EntityRecord> ListFilesFolders() { // Just use a TreeTraverser here TreeTraverser treeTraverser = new TreeTraverser(this.Dest); foreach(TreeTraverser.FolderEntry folder in treeTraverser.ListFolders()) { yield return new EntityRecord(folder.RelPath, Entity.Folder); foreach (TreeTraverser.FileEntry file in folder.GetFiles()) { yield return new EntityRecord(file.RelPath, Entity.File); } } }
private void checkFolder(TreeTraverser.FolderEntry folder) { foreach (BackendBase backend in this.backends) { if (!backend.FolderExists(folder.RelPath)) { this.reportBackupAction(new BackupActionItem(null, folder.RelPath, BackupActionEntity.Folder, BackupActionOperation.Add, backend.Name)); backend.CreateFolder(folder.RelPath, folder.Attributes); this.Logger.Info("{0}: Folder missing from backend, so re-creating: {1}", backend.Name, folder.RelPath); } } }
private void testFile(TreeTraverser.FileEntry file, string fileMD5) { foreach (BackendBase backend in this.backends) { if (!backend.TestFile(file.RelPath, file.LastModified, fileMD5)) { // Aha! File's gone missing from the backend this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Add, backend.Name)); if (!this.createFromAlternate(file, fileMD5, true, backend)) { if (backend.CreateFile(file.RelPath, file.FullPath, file.LastModified, fileMD5, file.Attributes)) this.Logger.Info("{0}: File on backend missing or modified, so re-creating: {1}", backend.Name, file.RelPath); } } else this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Nothing)); } }
private void updatefile(int fileId, TreeTraverser.FileEntry file, string remoteMD5) { this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Hash)); // Only copy if the file has actually changed string fileMD5 = file.GetMD5((percent) => { this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Hash, null, percent)); return !this.Cancelled; }); if (this.Cancelled) return; if (remoteMD5 == fileMD5) { foreach (BackendBase backend in this.backends) { backend.TouchFile(file.RelPath, file.LastModified); } //this.Logger.Info("File mtime changed, but file unchanged. Touching: {0}", file); return; } foreach (BackendBase backend in this.backends) { if (this.createFromAlternate(file, fileMD5, true, backend)) continue; this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Update, backend.Name)); if (backend.CreateFile(file.RelPath, file.FullPath, file.LastModified, fileMD5, file.Attributes)) this.Logger.Info("{0}: Updated file: {1}", backend.Name, file.RelPath); else this.Logger.Info("{0}: Skipped file {1} (mtime changed but file up-to-date)", backend.Name, file.RelPath); } // But update the last modified time either way this.fileDatabase.UpdateFile(fileId, file.LastModified, fileMD5); }
private void addFile(int folderId, TreeTraverser.FileEntry file) { string fileMD5 = file.GetMD5((percent) => { this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Hash, null, percent)); return !this.Cancelled; }); if (this.Cancelled) return; foreach (BackendBase backend in this.backends) { // Search for alternates if (this.createFromAlternate(file, fileMD5, false, backend)) continue; this.reportBackupAction(new BackupActionItem(null, file.RelPath, BackupActionEntity.File, BackupActionOperation.Add, backend.Name)); backend.CreateFile(file.RelPath, file.FullPath, file.LastModified, fileMD5, file.Attributes); this.Logger.Info("{0}: Added file: {1}", backend.Name, file.RelPath); } this.fileDatabase.AddFile(folderId, file.RelPath, file.LastModified, fileMD5); }
private bool createFromAlternate(TreeTraverser.FileEntry file, string fileMD5, bool update, BackendBase backend) { // if update is true, we're updating the dest file. otherwise we're adding it // Return true if we made use of an alternate, or false if we did nothing string logAction = update ? "Updated" : "Added"; FileDatabase.FileRecord[] alternates = this.fileDatabase.SearchForAlternates(fileMD5).ToArray(); if (alternates.Length == 0) return false; // Now, each alternate may not in fact exist on the backend, or may be changed. We can't assume stuff like this // So, loop through them all, and attempt to use it. Bail after the first successful one bool foundGoodAlternate = false; foreach (FileDatabase.FileRecord alternate in alternates) { // First, does it even exist on the backend? Skip to the next one if not if (!backend.TestFile(alternate.Path, file.LastModified, fileMD5)) continue; // Next: Is is a copy or a move? if (this.treeTraverser.FileExists(alternate.Path)) { // It's a copy this.reportBackupAction(new BackupActionItem(alternate.Path, file.RelPath, BackupActionEntity.File, BackupActionOperation.Copy, backend.Name)); if (backend.CreateFromAlternateCopy(file.RelPath, alternate.Path)) this.Logger.Info("{0}: {1} file: {2} from alternate {3} (copy)", backend.Name, logAction, file.RelPath, alternate.Path); else { backend.CreateFile(file.RelPath, file.FullPath, file.LastModified, fileMD5, file.Attributes); this.Logger.Info("{0}: {1} file: {2} (backend refused alternate {3})", backend.Name, logAction, file.RelPath, alternate.Path); } } else { // It's a move this.reportBackupAction(new BackupActionItem(alternate.Path, file.RelPath, BackupActionEntity.File, BackupActionOperation.Move, backend.Name)); backend.CreateFromAlternateMove(file.RelPath, alternate.Path); this.Logger.Info("{0}: {1} file: {2} from alternate {3} (move)", backend.Name, logAction, file.RelPath, alternate.Path); this.fileDatabase.DeleteFile(alternate.Id); } // We're all golden foundGoodAlternate = true; break; } return foundGoodAlternate; }