internal static IEnumerable<IThreadPoolWorkItem> EnumerateQueuedWorkItems(ThreadPoolWorkQueue.WorkStealingQueue[] wsQueues, ThreadPoolWorkQueue.QueueSegment globalQueueTail)
 {
     if (wsQueues != null)
     {
         foreach (ThreadPoolWorkQueue.WorkStealingQueue iteratorVariable0 in wsQueues)
         {
             if ((iteratorVariable0 != null) && (iteratorVariable0.m_array != null))
             {
                 foreach (IThreadPoolWorkItem iteratorVariable3 in iteratorVariable0.m_array)
                 {
                     if (iteratorVariable3 != null)
                     {
                         yield return iteratorVariable3;
                     }
                 }
             }
         }
     }
     if (globalQueueTail != null)
     {
         for (ThreadPoolWorkQueue.QueueSegment iteratorVariable4 = globalQueueTail; iteratorVariable4 != null; iteratorVariable4 = iteratorVariable4.Next)
         {
             foreach (IThreadPoolWorkItem iteratorVariable7 in iteratorVariable4.nodes)
             {
                 if (iteratorVariable7 != null)
                 {
                     yield return iteratorVariable7;
                 }
             }
         }
     }
 }
Example #2
0
        /// <summary>
        /// Finds all the rules of the given type under a given directory
        /// </summary>
        /// <param name="Directory">Directory to search</param>
        /// <param name="Type">Type of rules to return</param>
        /// <returns>List of rules files of the given type</returns>
        private static IReadOnlyList <FileReference> FindAllRulesFiles(DirectoryReference Directory, RulesFileType Type)
        {
            // Check to see if we've already cached source files for this folder
            RulesFileCache Cache;

            if (!RootFolderToRulesFileCache.TryGetValue(Directory, out Cache))
            {
                Cache = new RulesFileCache();
                using (ThreadPoolWorkQueue Queue = new ThreadPoolWorkQueue())
                {
                    DirectoryItem BaseDirectory = DirectoryItem.GetItemByDirectoryReference(Directory);
                    Queue.Enqueue(() => FindAllRulesFilesRecursively(BaseDirectory, Cache, Queue));
                }
                Cache.ModuleRules.Sort((A, B) => A.FullName.CompareTo(B.FullName));
                Cache.TargetRules.Sort((A, B) => A.FullName.CompareTo(B.FullName));
                Cache.AutomationModules.Sort((A, B) => A.FullName.CompareTo(B.FullName));
                RootFolderToRulesFileCache[Directory] = Cache;
            }

            // Get the list of files of the type we're looking for
            if (Type == RulesCompiler.RulesFileType.Module)
            {
                return(Cache.ModuleRules);
            }
            else if (Type == RulesCompiler.RulesFileType.Target)
            {
                return(Cache.TargetRules);
            }
            else if (Type == RulesCompiler.RulesFileType.AutomationModule)
            {
                return(Cache.AutomationModules);
            }
            else
            {
                throw new BuildException("Unhandled rules type: {0}", Type);
            }
        }
Example #3
0
        /// <summary>
        /// Find paths to all the plugins under a given parent directory (recursively)
        /// </summary>
        /// <param name="ParentDirectory">Parent directory to look in. Plugins will be found in any *subfolders* of this directory.</param>
        public static IEnumerable <FileReference> EnumeratePlugins(DirectoryReference ParentDirectory)
        {
            List <FileReference> FileNames;

            if (!PluginFileCache.TryGetValue(ParentDirectory, out FileNames))
            {
                FileNames = new List <FileReference>();

                DirectoryItem ParentDirectoryItem = DirectoryItem.GetItemByDirectoryReference(ParentDirectory);
                if (ParentDirectoryItem.Exists)
                {
                    using (ThreadPoolWorkQueue Queue = new ThreadPoolWorkQueue())
                    {
                        EnumeratePluginsInternal(ParentDirectoryItem, FileNames, Queue);
                    }
                }

                // Sort the filenames to ensure that the plugin order is deterministic; otherwise response files will change with each build.
                FileNames = FileNames.OrderBy(x => x.FullName, StringComparer.OrdinalIgnoreCase).ToList();

                PluginFileCache.Add(ParentDirectory, FileNames);
            }
            return(FileNames);
        }
 public void DoSetup()
 {
     mQueue = new ThreadPoolWorkQueue();
       mThreadID = Thread.CurrentThread.ManagedThreadId;
 }
            private static void WorkerThreadStart()
            {
                Thread.CurrentThread.SetThreadPoolWorkerThreadName();

                PortableThreadPool threadPoolInstance = ThreadPoolInstance;

                if (PortableThreadPoolEventSource.Log.IsEnabled())
                {
                    PortableThreadPoolEventSource.Log.ThreadPoolWorkerThreadStart(
                        (uint)threadPoolInstance._separated.counts.VolatileRead().NumExistingThreads);
                }

                LowLevelLock          hillClimbingThreadAdjustmentLock = threadPoolInstance._hillClimbingThreadAdjustmentLock;
                LowLevelLifoSemaphore semaphore = s_semaphore;

                while (true)
                {
                    bool spinWait = true;
                    while (semaphore.Wait(ThreadPoolThreadTimeoutMs, spinWait))
                    {
                        bool alreadyRemovedWorkingWorker = false;
                        while (TakeActiveRequest(threadPoolInstance))
                        {
                            Volatile.Write(ref threadPoolInstance._separated.lastDequeueTime, Environment.TickCount);
                            if (!ThreadPoolWorkQueue.Dispatch())
                            {
                                // ShouldStopProcessingWorkNow() caused the thread to stop processing work, and it would have
                                // already removed this working worker in the counts. This typically happens when hill climbing
                                // decreases the worker thread count goal.
                                alreadyRemovedWorkingWorker = true;
                                break;
                            }
                        }

                        // Don't spin-wait on the semaphore next time if the thread was actively stopped from processing work,
                        // as it's unlikely that the worker thread count goal would be increased again so soon afterwards that
                        // the semaphore would be released within the spin-wait window
                        spinWait = !alreadyRemovedWorkingWorker;

                        if (!alreadyRemovedWorkingWorker)
                        {
                            // If we woke up but couldn't find a request, or ran out of work items to process, we need to update
                            // the number of working workers to reflect that we are done working for now
                            RemoveWorkingWorker(threadPoolInstance);
                        }
                    }

                    hillClimbingThreadAdjustmentLock.Acquire();
                    try
                    {
                        // At this point, the thread's wait timed out. We are shutting down this thread.
                        // We are going to decrement the number of exisiting threads to no longer include this one
                        // and then change the max number of threads in the thread pool to reflect that we don't need as many
                        // as we had. Finally, we are going to tell hill climbing that we changed the max number of threads.
                        ThreadCounts counts = threadPoolInstance._separated.counts.VolatileRead();
                        while (true)
                        {
                            // Since this thread is currently registered as an existing thread, if more work comes in meanwhile,
                            // this thread would be expected to satisfy the new work. Ensure that NumExistingThreads is not
                            // decreased below NumProcessingWork, as that would be indicative of such a case.
                            short numExistingThreads = counts.NumExistingThreads;
                            if (numExistingThreads <= counts.NumProcessingWork)
                            {
                                // In this case, enough work came in that this thread should not time out and should go back to work.
                                break;
                            }

                            ThreadCounts newCounts = counts;
                            newCounts.SubtractNumExistingThreads(1);
                            short newNumExistingThreads = (short)(numExistingThreads - 1);
                            short newNumThreadsGoal     = Math.Max(threadPoolInstance._minThreads, Math.Min(newNumExistingThreads, newCounts.NumThreadsGoal));
                            newCounts.NumThreadsGoal = newNumThreadsGoal;

                            ThreadCounts oldCounts = threadPoolInstance._separated.counts.InterlockedCompareExchange(newCounts, counts);
                            if (oldCounts == counts)
                            {
                                HillClimbing.ThreadPoolHillClimber.ForceChange(newNumThreadsGoal, HillClimbing.StateOrTransition.ThreadTimedOut);

                                if (PortableThreadPoolEventSource.Log.IsEnabled())
                                {
                                    PortableThreadPoolEventSource.Log.ThreadPoolWorkerThreadStop((uint)newNumExistingThreads);
                                }
                                return;
                            }

                            counts = oldCounts;
                        }
                    }
                    finally
                    {
                        hillClimbingThreadAdjustmentLock.Release();
                    }
                }
            }
Example #6
0
        /// <summary>
        /// Finds all the source files under a directory that contain reflection markup
        /// </summary>
        /// <param name="Directory">The directory to search</param>
        /// <param name="MetadataCache">Cache of source file metadata</param>
        /// <param name="ExcludedFolderNames">Set of folder names to ignore when recursing the directory tree</param>
        /// <param name="FilesWithMarkup">Receives the set of files which contain reflection markup</param>
        /// <param name="Queue">Queue to add sub-tasks to</param>
        static void FindFilesWithMarkup(DirectoryItem Directory, SourceFileMetadataCache MetadataCache, ReadOnlyHashSet <string> ExcludedFolderNames, ConcurrentBag <FileItem> FilesWithMarkup, ThreadPoolWorkQueue Queue)
        {
            // Search through all the subfolders
            foreach (DirectoryItem SubDirectory in Directory.EnumerateDirectories())
            {
                if (!ExcludedFolderNames.Contains(SubDirectory.Name))
                {
                    Queue.Enqueue(() => FindFilesWithMarkup(SubDirectory, MetadataCache, ExcludedFolderNames, FilesWithMarkup, Queue));
                }
            }

            // Check for all the headers in this folder
            foreach (FileItem File in Directory.EnumerateFiles())
            {
                if (File.HasExtension(".h") && MetadataCache.ContainsReflectionMarkup(File))
                {
                    FilesWithMarkup.Add(File);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Checks if the makefile is valid for the current set of source files. This is done separately to the Load() method to allow pre-build steps to modify source files.
        /// </summary>
        /// <param name="Makefile">The makefile that has been loaded</param>
        /// <param name="ProjectFile">Path to the project file</param>
        /// <param name="Platform">The platform being built</param>
        /// <param name="WorkingSet">The current working set of source files</param>
        /// <param name="ReasonNotLoaded">If the makefile is not valid, is set to a message describing why</param>
        /// <returns>True if the makefile is valid, false otherwise</returns>
        public static bool IsValidForSourceFiles(TargetMakefile Makefile, FileReference ProjectFile, UnrealTargetPlatform Platform, ISourceFileWorkingSet WorkingSet, out string ReasonNotLoaded)
        {
            using (Timeline.ScopeEvent("TargetMakefile.IsValidForSourceFiles()"))
            {
                // Get the list of excluded folder names for this platform
                ReadOnlyHashSet <string> ExcludedFolderNames = UEBuildPlatform.GetBuildPlatform(Platform).GetExcludedFolderNames();

                // Check if any source files have been added or removed
                foreach (KeyValuePair <DirectoryItem, FileItem[]> Pair in Makefile.DirectoryToSourceFiles)
                {
                    DirectoryItem InputDirectory = Pair.Key;
                    if (!InputDirectory.Exists || InputDirectory.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        FileItem[] SourceFiles = UEBuildModuleCPP.GetSourceFiles(InputDirectory);
                        if (SourceFiles.Length < Pair.Value.Length)
                        {
                            ReasonNotLoaded = "source file removed";
                            return(false);
                        }
                        else if (SourceFiles.Length > Pair.Value.Length)
                        {
                            ReasonNotLoaded = "source file added";
                            return(false);
                        }
                        else if (SourceFiles.Intersect(Pair.Value).Count() != SourceFiles.Length)
                        {
                            ReasonNotLoaded = "source file modified";
                            return(false);
                        }

                        foreach (DirectoryItem Directory in InputDirectory.EnumerateDirectories())
                        {
                            if (!Makefile.DirectoryToSourceFiles.ContainsKey(Directory) && ContainsSourceFiles(Directory, ExcludedFolderNames))
                            {
                                ReasonNotLoaded = "directory added";
                                return(false);
                            }
                        }
                    }
                }

                // Check if any external dependencies have changed. These comparisons are done against the makefile creation time.
                foreach (FileItem ExternalDependency in Makefile.ExternalDependencies)
                {
                    if (!ExternalDependency.Exists)
                    {
                        Log.TraceLog("{0} has been deleted since makefile was built.", ExternalDependency.Location);
                        ReasonNotLoaded = string.Format("{0} deleted", ExternalDependency.Location.GetFileName());
                        return(false);
                    }
                    if (ExternalDependency.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        Log.TraceLog("{0} has been modified since makefile was built.", ExternalDependency.Location);
                        ReasonNotLoaded = string.Format("{0} modified", ExternalDependency.Location.GetFileName());
                        return(false);
                    }
                }

                // Check if any internal dependencies has changed. These comparisons are done against the makefile modified time.
                foreach (FileItem InternalDependency in Makefile.InternalDependencies)
                {
                    if (!InternalDependency.Exists)
                    {
                        Log.TraceLog("{0} has been deleted since makefile was written.", InternalDependency.Location);
                        ReasonNotLoaded = string.Format("{0} deleted", InternalDependency.Location.GetFileName());
                        return(false);
                    }
                    if (InternalDependency.LastWriteTimeUtc > Makefile.ModifiedTimeUtc)
                    {
                        Log.TraceLog("{0} has been modified since makefile was written.", InternalDependency.Location);
                        ReasonNotLoaded = string.Format("{0} modified", InternalDependency.Location.GetFileName());
                        return(false);
                    }
                }

                // Check that no new plugins have been added
                foreach (FileReference PluginFile in Plugins.EnumeratePlugins(ProjectFile))
                {
                    FileItem PluginFileItem = FileItem.GetItemByFileReference(PluginFile);
                    if (!Makefile.PluginFiles.Contains(PluginFileItem))
                    {
                        Log.TraceLog("{0} has been added", PluginFile.GetFileName());
                        ReasonNotLoaded = string.Format("{0} has been added", PluginFile.GetFileName());
                        return(false);
                    }
                }

                // Load the metadata cache
                SourceFileMetadataCache MetadataCache = SourceFileMetadataCache.CreateHierarchy(ProjectFile);

                // Find the set of files that contain reflection markup
                ConcurrentBag <FileItem> NewFilesWithMarkupBag = new ConcurrentBag <FileItem>();
                using (ThreadPoolWorkQueue Queue = new ThreadPoolWorkQueue())
                {
                    foreach (DirectoryItem SourceDirectory in Makefile.SourceDirectories)
                    {
                        Queue.Enqueue(() => FindFilesWithMarkup(SourceDirectory, MetadataCache, ExcludedFolderNames, NewFilesWithMarkupBag, Queue));
                    }
                }

                // Check whether the list has changed
                List <FileItem> PrevFilesWithMarkup = Makefile.UObjectModuleHeaders.Where(x => !x.bUsePrecompiled).SelectMany(x => x.HeaderFiles).ToList();
                List <FileItem> NextFilesWithMarkup = NewFilesWithMarkupBag.ToList();
                if (NextFilesWithMarkup.Count != PrevFilesWithMarkup.Count || NextFilesWithMarkup.Intersect(PrevFilesWithMarkup).Count() != PrevFilesWithMarkup.Count)
                {
                    ReasonNotLoaded = "UHT files changed";
                    return(false);
                }

                // If adaptive unity build is enabled, do a check to see if there are any source files that became part of the
                // working set since the Makefile was created (or, source files were removed from the working set.)  If anything
                // changed, then we'll force a new Makefile to be created so that we have fresh unity build blobs.  We always
                // want to make sure that source files in the working set are excluded from those unity blobs (for fastest possible
                // iteration times.)

                // Check if any source files in the working set no longer belong in it
                foreach (FileItem SourceFile in Makefile.WorkingSet)
                {
                    if (!WorkingSet.Contains(SourceFile) && SourceFile.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        Log.TraceLog("{0} was part of source working set and now is not; invalidating makefile", SourceFile.AbsolutePath);
                        ReasonNotLoaded = string.Format("working set of source files changed");
                        return(false);
                    }
                }

                // Check if any source files that are eligible for being in the working set have been modified
                foreach (FileItem SourceFile in Makefile.CandidatesForWorkingSet)
                {
                    if (WorkingSet.Contains(SourceFile) && SourceFile.LastWriteTimeUtc > Makefile.CreateTimeUtc)
                    {
                        Log.TraceLog("{0} was part of source working set and now is not", SourceFile.AbsolutePath);
                        ReasonNotLoaded = string.Format("working set of source files changed");
                        return(false);
                    }
                }
            }

            ReasonNotLoaded = null;
            return(true);
        }
Example #8
0
        /// <summary>
        /// Find paths to all the plugins under a given parent directory (recursively)
        /// </summary>
        /// <param name="ParentDirectory">Parent directory to look in. Plugins will be found in any *subfolders* of this directory.</param>
        /// <param name="FileNames">List of filenames. Will have all the discovered .uplugin files appended to it.</param>
        /// <param name="Queue">Queue for tasks to be executed</param>
        static void EnumeratePluginsInternal(DirectoryItem ParentDirectory, List <FileReference> FileNames, ThreadPoolWorkQueue Queue)
        {
            foreach (DirectoryItem ChildDirectory in ParentDirectory.EnumerateDirectories())
            {
                bool bSearchSubDirectories = true;
                foreach (FileItem PluginFile in ChildDirectory.EnumerateFiles())
                {
                    if (PluginFile.HasExtension(".uplugin"))
                    {
                        lock (FileNames)
                        {
                            FileNames.Add(PluginFile.Location);
                        }
                        bSearchSubDirectories = false;
                    }
                }

                if (bSearchSubDirectories)
                {
                    Queue.Enqueue(() => EnumeratePluginsInternal(ChildDirectory, FileNames, Queue));
                }
            }
        }
 public void DoSetup()
 {
     mQueue    = new ThreadPoolWorkQueue();
     mThreadID = Thread.CurrentThread.ManagedThreadId;
 }
        private void Refresh(DirectoryInfo Info, ConcurrentBag <FileInfo> FilesToDelete, ConcurrentBag <DirectoryInfo> DirectoriesToDelete, ThreadPoolWorkQueue Queue)
        {
            // Recurse through subdirectories
            Dictionary <string, WorkspaceDirectoryInfo> NewNameToSubDirectory = new Dictionary <string, WorkspaceDirectoryInfo>(NameToSubDirectory.Count, NameToSubDirectory.Comparer);

            foreach (DirectoryInfo SubDirectoryInfo in Info.EnumerateDirectories())
            {
                WorkspaceDirectoryInfo SubDirectory;
                if (NameToSubDirectory.TryGetValue(SubDirectoryInfo.Name, out SubDirectory))
                {
                    NewNameToSubDirectory.Add(SubDirectory.Name, SubDirectory);
                    Queue.Enqueue(() => SubDirectory.Refresh(SubDirectoryInfo, FilesToDelete, DirectoriesToDelete, Queue));
                }
                else
                {
                    DirectoriesToDelete.Add(SubDirectoryInfo);
                }
            }
            NameToSubDirectory = NewNameToSubDirectory;

            // Figure out which files have changed.
            Dictionary <string, WorkspaceFileInfo> NewNameToFile = new Dictionary <string, WorkspaceFileInfo>(NameToFile.Count, NameToFile.Comparer);

            foreach (FileInfo File in Info.EnumerateFiles())
            {
                WorkspaceFileInfo StagedFile;
                if (NameToFile.TryGetValue(File.Name, out StagedFile) && StagedFile.MatchesAttributes(File))
                {
                    NewNameToFile.Add(StagedFile.Name, StagedFile);
                }
                else
                {
                    FilesToDelete.Add(File);
                }
            }
            NameToFile = NewNameToFile;
        }
Example #11
0
		public DedicatedThreadPool(DedicatedThreadPoolSettings settings)
		{
			_workQueue = new ThreadPoolWorkQueue();
			Settings = settings;
			_workers = Enumerable.Range(1, settings.NumThreads).Select(workerId => new PoolWorker(this, workerId)).ToArray();

			// Note:
			// The DedicatedThreadPoolSupervisor was removed because aborting thread could lead to unexpected behavior
			// If a new implementation is done, it should spawn a new thread when a worker is not making progress and
			// try to keep {settings.NumThreads} active threads.
		}
Example #12
0
            private static void WorkerThreadStart()
            {
                PortableThreadPoolEventSource log = PortableThreadPoolEventSource.Log;

                if (log.IsEnabled())
                {
                    log.WorkerThreadStart(ThreadCounts.VolatileReadCounts(ref ThreadPoolInstance._separated.counts).numExistingThreads);
                }

                while (true)
                {
                    while (WaitForRequest())
                    {
                        if (TakeActiveRequest())
                        {
                            Volatile.Write(ref ThreadPoolInstance._separated.lastDequeueTime, Environment.TickCount);
                            if (ThreadPoolWorkQueue.Dispatch())
                            {
                                // If the queue runs out of work for us, we need to update the number of working workers to reflect that we are done working for now
                                RemoveWorkingWorker();
                            }
                        }
                        else
                        {
                            // If we woke up but couldn't find a request, we need to update the number of working workers to reflect that we are done working for now
                            RemoveWorkingWorker();
                        }
                    }

                    ThreadPoolInstance._hillClimbingThreadAdjustmentLock.Acquire();
                    try
                    {
                        // At this point, the thread's wait timed out. We are shutting down this thread.
                        // We are going to decrement the number of exisiting threads to no longer include this one
                        // and then change the max number of threads in the thread pool to reflect that we don't need as many
                        // as we had. Finally, we are going to tell hill climbing that we changed the max number of threads.
                        ThreadCounts counts = ThreadCounts.VolatileReadCounts(ref ThreadPoolInstance._separated.counts);
                        while (true)
                        {
                            if (counts.numExistingThreads == counts.numProcessingWork)
                            {
                                // In this case, enough work came in that this thread should not time out and should go back to work.
                                break;
                            }

                            ThreadCounts newCounts = counts;
                            newCounts.numExistingThreads--;
                            newCounts.numThreadsGoal = Math.Max(ThreadPoolInstance._minThreads, Math.Min(newCounts.numExistingThreads, newCounts.numThreadsGoal));
                            ThreadCounts oldCounts = ThreadCounts.CompareExchangeCounts(ref ThreadPoolInstance._separated.counts, newCounts, counts);
                            if (oldCounts == counts)
                            {
                                HillClimbing.ThreadPoolHillClimber.ForceChange(newCounts.numThreadsGoal, HillClimbing.StateOrTransition.ThreadTimedOut);

                                if (log.IsEnabled())
                                {
                                    log.WorkerThreadStop(newCounts.numExistingThreads);
                                }
                                return;
                            }
                        }
                    }
                    finally
                    {
                        ThreadPoolInstance._hillClimbingThreadAdjustmentLock.Release();
                    }
                }
            }
        void MergeDirectory(WorkspaceDirectoryInfo WorkspaceDir, WorkspaceDirectoryInfo NewWorkspaceDir, StreamDirectoryInfo StreamDir, ThreadPoolWorkQueue Queue)
        {
            // Make sure the directory exists
            Directory.CreateDirectory(WorkspaceDir.GetFullName());

            // Update all the subdirectories
            foreach (StreamDirectoryInfo StreamSubDir in StreamDir.NameToSubDirectory.Values)
            {
                WorkspaceDirectoryInfo WorkspaceSubDir;
                if (WorkspaceDir.NameToSubDirectory.TryGetValue(StreamSubDir.Name, out WorkspaceSubDir))
                {
                    MergeSubDirectory(WorkspaceSubDir, StreamSubDir, NewWorkspaceDir, Queue);
                }
                else
                {
                    AddSubDirectory(NewWorkspaceDir, StreamSubDir, Queue);
                }
            }

            // Move files into this folder
            foreach (StreamFileInfo StreamFile in StreamDir.NameToFile.Values)
            {
                WorkspaceFileInfo WorkspaceFile;
                if (WorkspaceDir.NameToFile.TryGetValue(StreamFile.Name, out WorkspaceFile))
                {
                    NewWorkspaceDir.NameToFile.Add(WorkspaceFile.Name, WorkspaceFile);
                }
                else
                {
                    AddFile(NewWorkspaceDir, StreamFile);
                }
            }
        }
        void AddSubDirectory(WorkspaceDirectoryInfo NewWorkspaceDir, StreamDirectoryInfo StreamSubDir, ThreadPoolWorkQueue Queue)
        {
            WorkspaceDirectoryInfo NewWorkspaceSubDir = new WorkspaceDirectoryInfo(NewWorkspaceDir, StreamSubDir.Name);

            NewWorkspaceDir.NameToSubDirectory.Add(StreamSubDir.Name, NewWorkspaceSubDir);
            Queue.Enqueue(() => AddDirectory(NewWorkspaceSubDir, StreamSubDir, Queue));
        }
        void AddDirectory(WorkspaceDirectoryInfo NewWorkspaceDir, StreamDirectoryInfo StreamDir, ThreadPoolWorkQueue Queue)
        {
            // Make sure the directory exists
            Directory.CreateDirectory(NewWorkspaceDir.GetFullName());

            // Add all the sub directories and files
            foreach (StreamDirectoryInfo StreamSubDir in StreamDir.NameToSubDirectory.Values)
            {
                AddSubDirectory(NewWorkspaceDir, StreamSubDir, Queue);
            }
            foreach (StreamFileInfo StreamFile in StreamDir.NameToFile.Values)
            {
                AddFile(NewWorkspaceDir, StreamFile);
            }
        }
        private void FindDifferences(DirectoryInfo Directory, string Path, ConcurrentBag <string> Paths, ThreadPoolWorkQueue Queue)
        {
            // Recurse through subdirectories
            HashSet <string> RemainingSubDirectoryNames = new HashSet <string>(NameToSubDirectory.Keys);

            foreach (DirectoryInfo SubDirectory in Directory.EnumerateDirectories())
            {
                WorkspaceDirectoryInfo StagedSubDirectory;
                if (NameToSubDirectory.TryGetValue(SubDirectory.Name, out StagedSubDirectory))
                {
                    RemainingSubDirectoryNames.Remove(SubDirectory.Name);
                    Queue.Enqueue(() => StagedSubDirectory.FindDifferences(SubDirectory, String.Format("{0}{1}/", Path, SubDirectory.Name), Paths, Queue));
                    continue;
                }
                Paths.Add(String.Format("+{0}{1}/...", Path, SubDirectory.Name));
            }
            foreach (string RemainingSubDirectoryName in RemainingSubDirectoryNames)
            {
                Paths.Add(String.Format("-{0}{1}/...", Path, RemainingSubDirectoryName));
            }

            // Search through files
            HashSet <string> RemainingFileNames = new HashSet <string>(NameToFile.Keys);

            foreach (FileInfo File in Directory.EnumerateFiles())
            {
                WorkspaceFileInfo StagedFile;
                if (!NameToFile.TryGetValue(File.Name, out StagedFile))
                {
                    Paths.Add(String.Format("+{0}{1}", Path, File.Name));
                }
                else if (!StagedFile.MatchesAttributes(File))
                {
                    Paths.Add(String.Format("!{0}{1}", Path, File.Name));
                    RemainingFileNames.Remove(File.Name);
                }
                else
                {
                    RemainingFileNames.Remove(File.Name);
                }
            }
            foreach (string RemainingFileName in RemainingFileNames)
            {
                Paths.Add(String.Format("-{0}{1}", Path, RemainingFileName));
            }
        }
Example #17
0
        /// <summary>
        /// Search through a directory tree for any rules files
        /// </summary>
        /// <param name="Directory">The root directory to search from</param>
        /// <param name="Cache">Receives all the discovered rules files</param>
        /// <param name="Queue">Queue for adding additional tasks to</param>
        private static void FindAllRulesFilesRecursively(DirectoryItem Directory, RulesFileCache Cache, ThreadPoolWorkQueue Queue)
        {
            // Scan all the files in this directory
            bool bSearchSubFolders = true;

            foreach (FileItem File in Directory.EnumerateFiles())
            {
                if (File.HasExtension(".build.cs"))
                {
                    lock (Cache.ModuleRules)
                    {
                        Cache.ModuleRules.Add(File.Location);
                    }
                    bSearchSubFolders = false;
                }
                else if (File.HasExtension(".target.cs"))
                {
                    lock (Cache.TargetRules)
                    {
                        Cache.TargetRules.Add(File.Location);
                    }
                }
                else if (File.HasExtension(".automation.csproj"))
                {
                    lock (Cache.AutomationModules)
                    {
                        Cache.AutomationModules.Add(File.Location);
                    }
                    bSearchSubFolders = false;
                }
            }

            // If we didn't find anything to stop the search, search all the subdirectories too
            if (bSearchSubFolders)
            {
                foreach (DirectoryItem SubDirectory in Directory.EnumerateDirectories())
                {
                    Queue.Enqueue(() => FindAllRulesFilesRecursively(SubDirectory, Cache, Queue));
                }
            }
        }
Example #18
0
        void Merge(WorkspaceDirectoryInfo WorkspaceDir, WorkspaceDirectoryInfo NewWorkspaceDir, StreamDirectoryInfo StreamDir, ThreadPoolWorkQueue Queue)
        {
            // Update all the subdirectories
            foreach (WorkspaceDirectoryInfo WorkspaceSubDir in WorkspaceDir.NameToSubDirectory.Values)
            {
                StreamDirectoryInfo StreamSubDir;
                if (StreamDir.NameToSubDirectory.TryGetValue(WorkspaceSubDir.Name, out StreamSubDir))
                {
                    MergeSubDirectory(NewWorkspaceDir, WorkspaceSubDir, StreamSubDir, Queue);
                }
                else
                {
                    RemoveDirectory(WorkspaceSubDir, Queue);
                }
            }

            // Update the staged files
            foreach (WorkspaceFileInfo WorkspaceFile in WorkspaceDir.NameToFile.Values)
            {
                StreamFileInfo StreamFile;
                if (StreamDir != null && StreamDir.NameToFile.TryGetValue(WorkspaceFile.Name, out StreamFile) && StreamFile.ContentId.Equals(WorkspaceFile.ContentId))
                {
                    NewWorkspaceDir.NameToFile.Add(WorkspaceFile.Name, WorkspaceFile);
                }
                else
                {
                    RemoveFile(WorkspaceFile);
                }
            }
        }