/// <summary> /// Initializes a new instance of the <see cref="NamespaceEnumerator" /> class. /// </summary> /// <param name="listeners">The listeners.</param> public NamespaceEnumerator(IList <INamespaceEnumeratorListener> listeners) { _listeners = listeners; _namespaceInfo = new NamespaceInfo(); }
/// <summary> /// implementation of post-order traversal of directory tree /// it is done this way to guarantee that by the time we finish any directory /// all of its subdirectories/files had been visited /// Note: /// if operaiton is cancelled - not all notifications will be emited, /// and namespace information will be partial. /// </summary> /// <param name="root">directory to scan</param> /// <param name="cancelationCallback">function to consult with for cancelation</param> /// <exception cref="System.IO.DirectoryNotFoundException">Cannot access directory: {root.FullName}</exception> private void EnumeratePostOrderNonRecursive(IDirectoryInfo root, Func <bool> cancelationCallback = null) { // handle the case than this is actually network share. if (!root.Exists()) { throw new System.IO.DirectoryNotFoundException(string.Format(StorageSyncResources.NamespaceEnumeratorErrorFormat, root.FullName)); } _namespaceInfo = new NamespaceInfo { Path = root.FullName, IsComplete = false }; Stack <IDirectoryInfo> stack1 = new Stack <IDirectoryInfo>(5000); Stack <IDirectoryInfo> stack2 = new Stack <IDirectoryInfo>(5000); Func <bool> shouldCancel = () => { if (System.Diagnostics.Debugger.IsAttached) { return(false); } return(cancelationCallback == null ? false : cancelationCallback.Invoke()); }; stack1.Push(root); _namespaceInfo.NumberOfDirectories++; while (stack1.Count > 0) { if (shouldCancel()) { return; } IDirectoryInfo currentDirectory = stack1.Pop(); stack2.Push(currentDirectory); // notify we have started processing directory // processing means accessing subdirectories and files NotifyBeginDir(currentDirectory); IList <IDirectoryInfo> subdirs = null; try { subdirs = new List <IDirectoryInfo>(currentDirectory.EnumerateDirectories()); } catch (UnauthorizedAccessException) { NotifyUnauthorizedDir(currentDirectory); continue; } NotifyNamespaceHints(subdirs.Count, 0); foreach (IDirectoryInfo subdir in subdirs) { stack1.Push(subdir); _namespaceInfo.NumberOfDirectories++; } } while (stack2.Count > 0) { if (shouldCancel()) { return; } IDirectoryInfo currentDirectory = stack2.Pop(); IList <IFileInfo> files = new List <IFileInfo>(currentDirectory.EnumerateFiles()); NotifyNamespaceHints(0, files.Count); foreach (IFileInfo file in files) { _namespaceInfo.NumberOfFiles++; _namespaceInfo.TotalFileSizeInBytes += file.Length; NotifyNextFile(file); } // notify we have finished processing directory NotifyEndDir(currentDirectory); } _namespaceInfo.IsComplete = true; }