예제 #1
0
        public AssetDependencies(AssetDependencies set)
        {
            if (set == null)
            {
                throw new ArgumentNullException("set");
            }
            item = set.Item;

            // Copy Output refs
            foreach (var child in set.LinksOut)
            {
                AddLinkOut(child);
            }

            // Copy Input refs
            foreach (var child in set.LinksIn)
            {
                AddLinkIn(child);
            }

            // Copy missing refs
            foreach (var child in set.BrokenLinksOut)
            {
                AddBrokenLinkOut(child.Element, child.Type);
            }
        }
예제 #2
0
        private void CollectInputReferences(AssetDependencies dependencyRoot, AssetId assetId, HashSet <AssetId> visited, bool recursive, ContentLinkType linkTypes, ref int count)
        {
            if (visited != null)
            {
                if (visited.Contains(assetId))
                {
                    return;
                }

                visited.Add(assetId);
            }

            count++;

            AssetDependencies dependencies;

            Dependencies.TryGetValue(assetId, out dependencies);
            if (dependencies != null)
            {
                foreach (var pair in dependencies.LinksIn)
                {
                    if ((linkTypes & pair.Type) != 0)
                    {
                        dependencyRoot.AddLinkIn(pair);

                        if (visited != null && recursive)
                        {
                            CollectInputReferences(dependencyRoot, pair.Item.Id, visited, true, linkTypes, ref count);
                        }
                    }
                }
            }
        }
예제 #3
0
        private void UpdateAssetDependencies(AssetDependencies dependencies)
        {
            lock (ThisLock)
            {
                // Remove previous missing dependencies
                RemoveMissingDependencies(dependencies);

                // Remove [In] dependencies from previous children
                foreach (var referenceAsset in dependencies.LinksOut)
                {
                    var childDependencyItem = TrackAsset(referenceAsset.Item);
                    childDependencyItem?.RemoveLinkIn(dependencies.Item);
                }

                // Recalculate [Out] dependencies
                CollectDynamicOutReferences(dependencies, FindAssetFromDependencyOrSession, false, true);

                // Add [In] dependencies to new children
                foreach (var assetLink in dependencies.LinksOut)
                {
                    var childDependencyItem = TrackAsset(assetLink.Item);
                    childDependencyItem?.AddLinkIn(dependencies.Item, assetLink.Type);
                }

                // Update missing dependencies
                UpdateMissingDependencies(dependencies);
            }
        }
예제 #4
0
 private void RemoveMissingDependencies(AssetDependencies dependencies)
 {
     if (AssetsWithMissingReferences.ContainsKey(dependencies.Item.Id))
     {
         AssetsWithMissingReferences.Remove(dependencies.Item.Id);
         foreach (var assetLink in dependencies.BrokenLinksOut)
         {
             var list = MissingReferencesToParent[assetLink.Element.Id];
             list.Remove(dependencies);
             if (list.Count == 0)
             {
                 MissingReferencesToParent.Remove(assetLink.Element.Id);
             }
         }
     }
 }
예제 #5
0
        private void UpdateMissingDependencies(AssetDependencies dependencies)
        {
            HashSet <AssetDependencies> parentDependencyItems;

            // If the asset has any missing dependencies, update the fast lookup tables
            if (dependencies.HasMissingDependencies)
            {
                AssetsWithMissingReferences[dependencies.Item.Id] = dependencies;

                foreach (var assetLink in dependencies.BrokenLinksOut)
                {
                    if (!MissingReferencesToParent.TryGetValue(assetLink.Element.Id, out parentDependencyItems))
                    {
                        parentDependencyItems = new HashSet <AssetDependencies>();
                        MissingReferencesToParent.Add(assetLink.Element.Id, parentDependencyItems);
                    }

                    parentDependencyItems.Add(dependencies);
                }
            }

            var item = dependencies.Item;

            // If the new asset was a missing reference, remove all missing references for this asset
            if (MissingReferencesToParent.TryGetValue(item.Id, out parentDependencyItems))
            {
                MissingReferencesToParent.Remove(item.Id);
                foreach (var parentDependencies in parentDependencyItems)
                {
                    // Remove missing dependency from parent
                    var oldBrokenLink = parentDependencies.RemoveBrokenLinkOut(item.Id);

                    // Update [Out] dependency to parent
                    parentDependencies.AddLinkOut(item, oldBrokenLink.Type);

                    // Update [In] dependency to current
                    dependencies.AddLinkIn(parentDependencies.Item, oldBrokenLink.Type);

                    // Remove global cache for assets with missing references
                    if (!parentDependencies.HasMissingDependencies)
                    {
                        AssetsWithMissingReferences.Remove(parentDependencies.Item.Id);
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// This method is called when an asset needs to be tracked
        /// </summary>
        /// <returns>AssetDependencies.</returns>
        private AssetDependencies TrackAsset(AssetId assetId)
        {
            lock (ThisLock)
            {
                AssetDependencies dependencies;
                if (Dependencies.TryGetValue(assetId, out dependencies))
                {
                    return(dependencies);
                }

                // TODO provide an optimized version of TrackAsset method
                // taking directly a well known asset (loaded from a Package...etc.)
                // to avoid session.FindAsset
                var assetItem = session.FindAsset(assetId);
                if (assetItem == null)
                {
                    return(null);
                }

                // Clone the asset before using it in this instance to make sure that
                // we have some kind of immutable state
                // TODO: This is not handling shadow registry

                // No need to clone assets from readonly package
                var assetItemCloned = assetItem.Package.IsSystem
                    ? assetItem
                    : new AssetItem(assetItem.Location, AssetCloner.Clone(assetItem.Asset), assetItem.Package)
                {
                    SourceFolder  = assetItem.SourceFolder,
                    SourceProject = assetItem.SourceProject
                };

                dependencies = new AssetDependencies(assetItemCloned);

                // Adds to global list
                Dependencies.Add(assetId, dependencies);

                // Update dependencies
                UpdateAssetDependencies(dependencies);
                CheckAllDependencies();

                return(dependencies);
            }
        }
예제 #7
0
        private void CollectOutputReferences(AssetDependencies dependencyRoot, AssetId assetId, HashSet <AssetId> visited, bool recursive, ContentLinkType linkTypes, ref int count)
        {
            if (visited != null)
            {
                if (visited.Contains(assetId))
                {
                    return;
                }

                visited.Add(assetId);
            }

            count++;

            var dependencies = CalculateDependencies(assetId);

            if (dependencies == null)
            {
                return;
            }

            // Add missing references
            foreach (var missingRef in dependencies.BrokenLinksOut)
            {
                dependencyRoot.AddBrokenLinkOut(missingRef);
            }

            // Add output references
            foreach (var child in dependencies.LinksOut)
            {
                if ((linkTypes & child.Type) != 0)
                {
                    dependencyRoot.AddLinkOut(child);

                    if (visited != null && recursive)
                    {
                        CollectOutputReferences(dependencyRoot, child.Item.Id, visited, true, linkTypes, ref count);
                    }
                }
            }
        }
예제 #8
0
        /// <inheritdoc />
        public AssetDependencies ComputeDependencies(AssetId assetId, AssetDependencySearchOptions dependenciesOptions = AssetDependencySearchOptions.All, ContentLinkType linkTypes = ContentLinkType.Reference, HashSet <AssetId> visited = null)
        {
            bool recursive = (dependenciesOptions & AssetDependencySearchOptions.Recursive) != 0;

            if (visited == null && recursive)
            {
                visited = new HashSet <AssetId>();
            }

            //var clock = Stopwatch.StartNew();

            lock (Initialize())
            {
                AssetDependencies dependencies;
                if (!Dependencies.TryGetValue(assetId, out dependencies))
                {
                    return(null);
                }

                dependencies = new AssetDependencies(dependencies.Item);

                int inCount = 0, outCount = 0;

                if ((dependenciesOptions & AssetDependencySearchOptions.In) != 0)
                {
                    CollectInputReferences(dependencies, assetId, visited, recursive, linkTypes, ref inCount);
                }

                if ((dependenciesOptions & AssetDependencySearchOptions.Out) != 0)
                {
                    visited?.Clear();
                    CollectOutputReferences(dependencies, assetId, visited, recursive, linkTypes, ref outCount);
                }

                //Console.WriteLine("Time to compute dependencies: {0}ms in: {1} out:{2}", clock.ElapsedMilliseconds, inCount, outCount);

                return(dependencies);
            }
        }
예제 #9
0
 public IEnumerable <IContentLink> GetDependencies(AssetItem item)
 {
     dependencies = new AssetDependencies(item);
     Visit(item.Asset);
     return(dependencies.BrokenLinksOut);
 }
예제 #10
0
        /// <summary>
        /// Collects all references of an asset dynamically.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="assetResolver">The asset resolver.</param>
        /// <param name="isRecursive">if set to <c>true</c> collects references recursively.</param>
        /// <param name="keepParents">Indicate if the parent of the provided <paramref name="result"/> should be kept or not</param>
        /// <exception cref="System.ArgumentNullException">
        /// result
        /// or
        /// assetResolver
        /// </exception>
        private static void CollectDynamicOutReferences(AssetDependencies result, Func <AssetId, AssetItem> assetResolver, bool isRecursive, bool keepParents)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }
            if (assetResolver == null)
            {
                throw new ArgumentNullException(nameof(assetResolver));
            }

            var addedReferences    = new HashSet <AssetId>();
            var itemsToAnalyze     = new Queue <AssetItem>();
            var referenceCollector = new DependenciesCollector();

            // Reset the dependencies/parts.
            result.Reset(keepParents);

            var assetItem = result.Item;

            // marked as processed to not add it again
            addedReferences.Add(assetItem.Id);
            itemsToAnalyze.Enqueue(assetItem);

            while (itemsToAnalyze.Count > 0)
            {
                var item = itemsToAnalyze.Dequeue();

                foreach (var link in referenceCollector.GetDependencies(item))
                {
                    if (addedReferences.Contains(link.Element.Id))
                    {
                        continue;
                    }

                    // marked as processed to not add it again
                    addedReferences.Add(link.Element.Id);

                    // add the location to the reference location list
                    var nextItem = assetResolver(link.Element.Id);
                    if (nextItem != null)
                    {
                        result.AddLinkOut(nextItem, link.Type);

                        // add current element to analyze list, to analyze dependencies recursively
                        if (isRecursive)
                        {
                            itemsToAnalyze.Enqueue(nextItem);
                        }
                    }
                    else
                    {
                        result.AddBrokenLinkOut(link);
                    }
                }

                if (!isRecursive)
                {
                    break;
                }
            }
        }