示例#1
0
            /// <summary>
            /// Reads an AbsolutePath (which may have been added after the serialization of the path table)
            /// </summary>
            public override AbsolutePath ReadAbsolutePath()
            {
                var absolutePathType = (BinaryLogger.AbsolutePathType)ReadByte();

                switch (absolutePathType)
                {
                case BinaryLogger.AbsolutePathType.Invalid:
                    return(AbsolutePath.Invalid);

                case BinaryLogger.AbsolutePathType.Static:
                    return(base.ReadAbsolutePath());

                case BinaryLogger.AbsolutePathType.Dynamic:
                    return(LogReader.m_capturedPaths[(uint)ReadInt32Compact()]);

                default:
                    throw Contract.AssertFailure($"Unrecognized path type: {absolutePathType}. The XLG file format has potentially changed.");
                }
            }
示例#2
0
        /// <summary>
        /// Use an existing resource if possible, else create a new one.
        /// </summary>
        /// <param name="key">Key to lookup an exisiting resource, if one exists.</param>
        public async Task <ResourceWrapper <TObject> > CreateAsync(TKey key)
        {
            ResourceWrapper <TObject> returnWrapper;

            using (Counter[ResourcePoolCounters.CreationTime].Start())
            {
                // Attempt to reuse an existing resource if it has been instantiated.
                if (_resourceDict.TryGetValue(key, out ResourceWrapper <TObject> existingWrappedResource) && existingWrappedResource.IsValueCreated && existingWrappedResource.TryAcquire(out var reused))
                {
                    returnWrapper = existingWrappedResource;
                }
                else
                {
                    var count = Interlocked.Increment(ref _resourceCount);

                    // Start resource "GC" if the cache is full and it isn't already running
                    if (count >= _maxResourceCount)
                    {
                        await EnqueueCleanupAsync(force : true, numberToRelease : 1);
                    }

                    returnWrapper = _resourceDict.GetOrAdd(
                        key,
                        (k, resourceFactory) => new ResourceWrapper <TObject>(() => resourceFactory(k), _context),
                        _resourceFactory);

                    if (_resourceDict.Count > _maxResourceCount)
                    {
                        _resourceDict.TryRemove(key, out _);
                        throw new CacheException($"Attempting to create resource to increase cached count above maximum allowed ({_maxResourceCount})");
                    }

                    if (!returnWrapper.TryAcquire(out reused))
                    {
                        throw Contract.AssertFailure($"Resource was marked for shutdown before acquired.");
                    }
                }

                Counter[reused ? ResourcePoolCounters.Reused : ResourcePoolCounters.Created].Increment();
            }

            return(returnWrapper);
        }
示例#3
0
        private static Dictionary <AbsolutePath, SpecFileWithMetadata> CreateSpecsFromModules(IReadOnlyCollection <ParsedModule> modules, bool allowDoubleOwnership)
        {
            var result = new Dictionary <AbsolutePath, SpecFileWithMetadata>();

            foreach (var m in modules)
            {
                foreach (var spec in m.Specs)
                {
                    var added = result.TryAdd(spec.Key, SpecFileWithMetadata.CreateNew(m, spec.Value));
                    // It shouldn't happen that the spec was already present when we don't allow double ownership (currently we only allow it for configuration parsing)
                    if (!added && !allowDoubleOwnership)
                    {
                        throw Contract.AssertFailure($"Spec with path {spec.Key} from module '{m.Descriptor.Name}' is already owned by module '{result[spec.Key].OwningModule.Descriptor.Name}'.");
                    }
                }
            }

            return(result);
        }
示例#4
0
        /// <summary>
        /// Advances state under big lock after chain has been computed.
        /// </summary>
        private bool ValuePromiseChainComputed(EdgeSet edgeSet)
        {
            lock (m_pendingEdgeSets)
            {
                switch (edgeSet.State)
                {
                case EdgeSetState.Adding:
                    edgeSet.State = EdgeSetState.Added;
                    return(true);

                case EdgeSetState.Abandoned:
                    edgeSet.State = EdgeSetState.Invalid;
                    Interlocked.Increment(ref m_statistics.CycleDetectionChainsAbandonedWhileProcessing);
                    return(false);

                default:
                    throw Contract.AssertFailure("unexpected edge set state");
                }
            }
        }
示例#5
0
        /// <summary>
        /// Converts a single-artifact origin to an overall pip result. This makes sense for pips with a single output.
        /// </summary>
        public static PipResultStatus ToPipResult(this PipOutputOrigin origin)
        {
            switch (origin)
            {
            case PipOutputOrigin.Produced:
                return(PipResultStatus.Succeeded);

            case PipOutputOrigin.UpToDate:
                return(PipResultStatus.UpToDate);

            case PipOutputOrigin.DeployedFromCache:
                return(PipResultStatus.DeployedFromCache);

            case PipOutputOrigin.NotMaterialized:
                return(PipResultStatus.NotMaterialized);

            default:
                throw Contract.AssertFailure("Unhandled PipOutputOrigin");
            }
        }
示例#6
0
        private IExpression Generate(PipFragment fragment)
        {
            switch (fragment.FragmentType)
            {
            case PipFragmentType.Invalid:
                return(Identifier.CreateUndefined());

            case PipFragmentType.StringLiteral:
                return(Generate(fragment.GetStringIdValue()));

            case PipFragmentType.AbsolutePath:
                return(Generate(fragment.GetPathValue()));

            case PipFragmentType.NestedFragment:
                return(Generate(fragment.GetNestedFragmentValue()));

            default:
                throw Contract.AssertFailure($"Unexpected PipFragmentType from PipFragment.FragmentType: {fragment.FragmentType}");
            }
        }
示例#7
0
        public static bool IsTerminal(this PipState current)
        {
            switch (current)
            {
            case PipState.Ignored:
            case PipState.Waiting:
            case PipState.Ready:
            case PipState.Running:
                return(false);

            case PipState.Skipped:
            case PipState.Failed:
            case PipState.Done:
            case PipState.Canceled:
                return(true);

            default:
                throw Contract.AssertFailure("Unhandled Pip State");
            }
        }
示例#8
0
        /// <nodoc />
        public static ReparsePointType ToReparsePointType(this BondReparsePointType reparsePointType)
        {
            switch (reparsePointType)
            {
            case BondReparsePointType.None:
                return(ReparsePointType.None);

            case BondReparsePointType.SymLink:
                return(ReparsePointType.SymLink);

            case BondReparsePointType.MountPoint:
                return(ReparsePointType.MountPoint);

            case BondReparsePointType.NonActionable:
                return(ReparsePointType.NonActionable);

            default:
                throw Contract.AssertFailure("Cannot convert BondReparsePointType to ReparsePointType");
            }
        }
示例#9
0
        /// <summary>
        /// Use an existing resource if possible, else create a new one.
        /// </summary>
        /// <param name="key">Key to lookup an exisiting resource, if one exists.</param>
        public async Task <ResourceWrapper <TObject> > CreateAsync(TKey key)
        {
            ResourceWrapper <TObject> returnWrapper;

            using (var sw = Counter[ResourcePoolCounters.CreationTime].Start())
            {
                // Attempt to reuse an existing resource if it has been instantiated.
                if (_resourceDict.TryGetValue(key, out ResourceWrapper <TObject> existingWrappedResource) && existingWrappedResource.IsValueCreated && existingWrappedResource.TryAcquire(out var reused))
                {
                    returnWrapper = existingWrappedResource;
                }
                else
                {
                    // Start resource "GC" if the cache is full and it isn't already running
                    await EnsureCapacityAsync();

                    returnWrapper = _resourceDict.GetOrAdd(key, k =>
                    {
                        return(new ResourceWrapper <TObject>(() => _resourceFactory(k)));
                    });

                    if (_resourceDict.Count > _maxResourceCount)
                    {
                        _resourceDict.TryRemove(key, out _);
                        throw new CacheException($"Attempting to create resource to increase cached count above maximum allowed ({_maxResourceCount})");
                    }

                    if (!returnWrapper.TryAcquire(out reused))
                    {
                        throw Contract.AssertFailure($"Resource was marked for shutdown before acquired.");
                    }
                }

                ResourcePoolCounters counter = reused ? ResourcePoolCounters.Reused : ResourcePoolCounters.Created;
                Counter[counter].Increment();

                _context.Debug($"{nameof(ResourcePool<TKey, TObject>)}.{nameof(CreateAsync)} {(reused ? "reused" : "created")} a resource with {returnWrapper.Uses} from a pool of {_resourceDict.Count}");
            }

            return(returnWrapper);
        }
示例#10
0
        /// <summary>
        /// Indicates if there is a valid state transition from <paramref name="current"/> to <paramref name="target"/>.
        /// </summary>
        public static bool CanTransitionTo(this PipState current, PipState target)
        {
            switch (target)
            {
            case PipState.Ignored:
                return(false);    // Entry state.

            case PipState.Waiting:
                // Initial state on pip addition / explicit scheduling.
                return(current == PipState.Ignored ||
                       /* fail establish pip fingerprint */ current == PipState.Running);

            case PipState.Ready:
                // Pending pips are the staging area on the way to being queued - they may have unsatisfied dependencies
                return(current == PipState.Waiting);

            case PipState.Running:
                // Queued pips can be run when they reach the queue head.
                return(current == PipState.Ready);

            case PipState.Skipped:
                return
                    // Skipping (due to failure of pre-requirements) can occur so long as the pip still has pre-requirements (i.e., Pending),
                    // or if we tentatively skipped a filter-failing pip (that was later scheduled due to a filter change).
                    (current == PipState.Waiting ||
                     // The pip may also transition from Running to Skipped if using /cacheonly mode and the pip was not a cache hit.
                     current == PipState.Running);

            case PipState.Canceled:
                // Completion / failure is the consequence of actual execution.
                return(current == PipState.Running);

            case PipState.Failed:
            case PipState.Done:
                // Completion.
                return(current == PipState.Running);

            default:
                throw Contract.AssertFailure("Unhandled Pip State");
            }
        }
示例#11
0
        /// <summary>
        /// Reports an access that - ignoring whitelisting - was unexpected. This can be due to a manifest-side or BuildXL-side denial decision.
        /// </summary>
        private FileAccessWhitelist.MatchType MatchAndReportUnexpectedFileAccess(ReportedFileAccess unexpectedFileAccess)
        {
            if (m_fileAccessWhitelist != null && m_fileAccessWhitelist.HasEntries)
            {
                Contract.Assert(
                    m_config.FailUnexpectedFileAccesses == false,
                    "Having a file-access whitelist requires that Detours failure injection is off.");

                FileAccessWhitelist.MatchType matchType = m_fileAccessWhitelist.Matches(m_loggingContext, unexpectedFileAccess, m_pip);
                switch (matchType)
                {
                case FileAccessWhitelist.MatchType.NoMatch:
                    AddUnexpectedFileAccessNotWhitelisted(unexpectedFileAccess);
                    ReportUnexpectedFileAccessNotWhitelisted(unexpectedFileAccess);
                    break;

                case FileAccessWhitelist.MatchType.MatchesButNotCacheable:
                    AddUnexpectedFileAccessWhitelisted(unexpectedFileAccess);
                    m_numWhitelistedButNotCacheableFileAccessViolations++;
                    ReportWhitelistedFileAccessNonCacheable(unexpectedFileAccess);
                    break;

                case FileAccessWhitelist.MatchType.MatchesAndCacheable:
                    AddUnexpectedFileAccessWhitelisted(unexpectedFileAccess);
                    m_numWhitelistedAndCacheableFileAccessViolations++;
                    ReportWhitelistedFileAccessCacheable(unexpectedFileAccess);
                    break;

                default:
                    throw Contract.AssertFailure("Unknown whitelist-match type.");
                }

                return(matchType);
            }
            else
            {
                AddUnexpectedFileAccessNotWhitelisted(unexpectedFileAccess);
                ReportUnexpectedFileAccessNotWhitelisted(unexpectedFileAccess);
                return(FileAccessWhitelist.MatchType.NoMatch);
            }
        }
示例#12
0
        /// <nodoc />
        public AmbientContext(PrimitiveTypes knownTypes)
            : base(ContextName, knownTypes)
        {
            var    currentHost = Host.Current;
            var    osName      = SymbolAtom.Create(StringTable, "os");
            string osValue     = currentHost.CurrentOS.GetDScriptValue();

            if (string.IsNullOrEmpty(osValue))
            {
                throw Contract.AssertFailure("Unhandled HostOS Type");
            }

            var    cpuName = SymbolAtom.Create(StringTable, "cpuArchitecture");
            string cpuValue;

            switch (currentHost.CpuArchitecture)
            {
            case HostCpuArchitecture.X86:
                cpuValue = "x86";
                break;

            case HostCpuArchitecture.X64:
                cpuValue = "x64";
                break;

            default:
                throw Contract.AssertFailure("Unhandled CpuArchitecture Type");
            }

            var isElevatedName  = SymbolAtom.Create(StringTable, "isElevated");
            var isElevatedValue = CurrentProcess.IsElevated;

            m_currentHost = ObjectLiteral.Create(
                new Binding(osName, osValue, default(LineInfo)),
                new Binding(cpuName, cpuValue, default(LineInfo)),
                new Binding(isElevatedName, isElevatedValue, default(LineInfo))
                );

            MountNameObject = Symbol("name");
            MountPathObject = Symbol("path");
        }
示例#13
0
        internal IEnumerable <MemberDeclarationSyntax> CreateSerializers(IEnumerable <INamedTypeSymbol> typesToSerialize)
        {
            var classMembers      = new List <MemberDeclarationSyntax>();
            var registrationCalls = new List <StatementSyntax>();

            foreach (var group in typesToSerialize.GroupBy(type => type.TypeKind))
            {
                switch (group.Key)
                {
                case TypeKind.Enum:
                    classMembers.Add(CreateEnumSerializers(group));
                    registrationCalls.Add(InvocationStatement(ReactNativeNames.CreateEnumSerializers));
                    break;

                case TypeKind.Class:
                case TypeKind.Struct:
                    classMembers.Add(CreateObjectSerializers(group));
                    registrationCalls.Add(InvocationStatement(ReactNativeNames.CreateObjectSerializers));
                    break;

                default:
                    throw Contract.AssertFailure("Unexpected type to serialize");
                }
            }

            // Generates:
            //    internal void CreateSerializers()
            //    {
            //       ... registrationCalls (ses above)
            //    }
            classMembers.Add(MethodDeclaration(
                                 PredefinedType(Token(SyntaxKind.VoidKeyword)),
                                 ReactNativeNames.CreateSerializers)
                             .AddModifiers(
                                 Token(SyntaxKind.InternalKeyword))
                             .WithBody(
                                 Block(
                                     registrationCalls)));

            return(classMembers);
        }
示例#14
0
        private bool IsSupportedPipType(PipType pipType)
        {
            switch (pipType)
            {
            case PipType.WriteFile:
            case PipType.CopyFile:
            case PipType.Process:
            case PipType.Ipc:
            case PipType.SealDirectory:
                return(true);

            case PipType.Value:
            case PipType.SpecFile:
            case PipType.Module:
            case PipType.HashSourceFile:
                return(false);

            default:
                throw Contract.AssertFailure($"Unknown pip type: {pipType}");
            }
        }
示例#15
0
        /// <summary>
        /// Constructs a PathFixer object
        /// </summary>
        /// <param name="lowerCaseDirectories">Whether or not to lowercase directory segments in the path</param>
        /// <param name="slashType">The slash type to validate/normalize to</param>
        public PathFixer(bool lowerCaseDirectories, SlashType slashType)
        {
            switch (slashType)
            {
            case SlashType.Default:
            case SlashType.Unix:
                ExpectedPathSeparator = '/';
                IllegalPathSeparator  = '\\';
                break;

            case SlashType.Windows:
                ExpectedPathSeparator = '\\';
                IllegalPathSeparator  = '/';
                break;

            default:
                throw Contract.AssertFailure("Unexpected enum value for SlashType");
            }

            LowerCaseDirectories = lowerCaseDirectories;
        }
示例#16
0
        /// <summary>
        /// Starts a background operation. This causes the <see cref="internalBuffer"/> to fill or flush.
        /// It must be ensured that no other background operation will be in progress, and that the stream is still usable after it.
        /// - First start an operation with <see cref="StartNewOperation"/>; this reserves the right to start the next background operation.
        /// - Then, wait for the current background operation, if any. We've established another one will not follow it due to the prior point.
        /// - Then, respond to the current stream usability (EOF, broken, etc.) as updated by the prior operation.
        /// </summary>
        private unsafe void StartBackgroundOperation(BackgroundOperationSlot slot, StreamBackgroundOperation nextOperation)
        {
            Contract.Requires(nextOperation != StreamBackgroundOperation.None);
            Analysis.IgnoreArgument(slot);

            lock (m_backgroundOperationLock)
            {
                if (m_usability != StreamUsability.Usable)
                {
                    Contract.Assume(false, "Attempting to start a background operation on an unusable stream: " + m_usability.ToString("G"));
                }

                Contract.Assume(
                    m_currentBackgroundOperation == StreamBackgroundOperation.None,
                    "Background operation already in progress; wait on it first?");
                Contract.Assume(m_currentBackgroundOperationCompletionSource == null);
                m_currentBackgroundOperation = nextOperation;
            }

            // Now actually start the async operation.
            // Note that the callback to 'this' (IIOCompletionTarget) can happen on this same stack
            byte *pinnedBuffer;
            int   operationLength;

            switch (nextOperation)
            {
            case StreamBackgroundOperation.Fill:
                internalBuffer.LockForFill(out pinnedBuffer, out operationLength);
                m_file.ReadOverlapped(this, pinnedBuffer, operationLength, m_bufferPosition);
                break;

            case StreamBackgroundOperation.Flush:
                internalBuffer.LockForFlush(out pinnedBuffer, out operationLength);
                m_file.WriteOverlapped(this, pinnedBuffer, operationLength, m_bufferPosition);
                break;

            default:
                throw Contract.AssertFailure("Unhandled StreamBackgroundOperation");
            }
        }
示例#17
0
        /// <summary>
        /// Use an existing resource if possible, else create a new one.
        /// </summary>
        /// <param name="key">Key to lookup an existing resource, if one exists.</param>
        /// <exception cref="ObjectDisposedException">If the pool has already been disposed</exception>
        public async Task <ResourceWrapper <TObject> > CreateAsync(TKey key)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(objectName: _tracer.Name, message: "Attempt to obtain resource after dispose");
            }

            using (Counter[ResourcePoolCounters.CreationTime].Start())
            {
                // NOTE: if dispose has happened at this point, we will fail to take the semaphore
                using (await _mutex.WaitTokenAsync())
                {
                    // Remove anything that has expired or been invalidated.
                    await CleanupAsync();

                    ResourceWrapper <TObject> returnWrapper;

                    // Attempt to reuse an existing resource if it has been instantiated.
                    if (_resourceDict.TryGetValue(key, out var existingWrappedResource))
                    {
                        returnWrapper = existingWrappedResource;
                    }
                    else
                    {
                        returnWrapper = CreateResourceWrapper(key);
                        _resourceDict.Add(key, returnWrapper);
                    }

                    if (!returnWrapper.TryAcquire(out var reused, _clock))
                    {
                        // Should be impossible
                        throw Contract.AssertFailure($"Failed to acquire resource. LastUseTime={returnWrapper.LastUseTime}, Uses={returnWrapper.Uses}");
                    }

                    Counter[reused ? ResourcePoolCounters.Reused : ResourcePoolCounters.Created].Increment();

                    return(returnWrapper);
                }
            }
        }
示例#18
0
        internal DisplayStackTraceEntry CreateDisplayStackTraceEntry(ImmutableContextBase context, LineInfo lastCallSite)
        {
            if (m_ambientCall != null)
            {
                var loc = new Location {
                    File = "[ambient call]", Line = -1, Position = -1
                };
                var functionName = m_ambientCall.Functor.ToDisplayString(context);
                return(new DisplayStackTraceEntry(loc, functionName, this));
            }

            if (Lambda != null)
            {
                var        location     = lastCallSite.AsLoggingLocation(Env, context);
                SymbolAtom?methodName   = Lambda?.Name;
                var        functionName = methodName?.IsValid == true?methodName.Value.ToString(context.StringTable) : "<lambda>";

                return(new DisplayStackTraceEntry(location, functionName, this));
            }

            throw Contract.AssertFailure("The code is effectively unreacheable.");
        }
示例#19
0
        private static EvaluationResult GetPathValues(Context context, EvaluationStackFrame args, Type type)
        {
            var    name      = Args.AsString(args, 0);
            var    separator = Args.AsString(args, 1);
            string strValue  = GetRawValue(context, name);

            var entry = context.TopStack;

            if (string.IsNullOrWhiteSpace(strValue))
            {
                return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(CollectionUtilities.EmptyArray <EvaluationResult>(), entry.InvocationLocation, entry.Path)));
            }

            var values       = separator.Length == 0 ? new[] { strValue } : strValue.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries);
            var pathsOrFiles = new List <EvaluationResult>();

            for (int i = 0; i < values.Length; ++i)
            {
                if (!string.IsNullOrWhiteSpace(values[i]))
                {
                    AbsolutePath path = ParsePath(context, name, values[i], 1);

                    EvaluationResult result =
                        type == typeof(AbsolutePath)      ? EvaluationResult.Create(path) :
                        type == typeof(FileArtifact)      ? EvaluationResult.Create(FileArtifact.CreateSourceFile(path)) :
                        type == typeof(DirectoryArtifact) ? EvaluationResult.Create(DirectoryArtifact.CreateWithZeroPartialSealId(path)) :
                        EvaluationResult.Undefined;

                    if (result.IsUndefined)
                    {
                        throw Contract.AssertFailure(I($"Cannot convert paths to typeof({type.Name})"));
                    }

                    pathsOrFiles.Add(result);
                }
            }

            return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(pathsOrFiles.ToArray(), entry.InvocationLocation, entry.Path)));
        }
示例#20
0
        /// <summary>
        /// Attempt to reserve the resource. Fails if marked for shutdown.
        /// </summary>
        /// <param name="reused">Whether the resource has been used previously.</param>
        /// <returns>Whether the resource is approved for use.</returns>
        public bool TryAcquire(out bool reused)
        {
            lock (this)
            {
                if (_resource.IsValueCreated && _resource.Value.ShutdownStarted)
                {
                    throw Contract.AssertFailure($"Found resource which has already begun shutdown");
                }

                _uses++;

                reused = _lastUseTime != DateTime.MinValue;
                if (_uses > 0)
                {
                    _lastUseTime = DateTime.UtcNow;
                    return(true);
                }
            }

            reused = false;
            return(false);
        }
示例#21
0
        /// <summary>
        /// <see cref="Stream.Seek(long, SeekOrigin)"/>
        /// </summary>
        public override long Seek(long offset, SeekOrigin origin)
        {
            using (StreamOperationToken token = StartNewOperation(StreamOperation.Seek))
            {
                BackgroundOperationSlot slot = token.WaitForBackgroundOperationSlot();
                if (slot.Usability == StreamUsability.Broken)
                {
                    throw slot.ThrowExceptionForBrokenStream();
                }

                long offsetFromStart;
                switch (origin)
                {
                case SeekOrigin.Begin:
                    Contract.Assume(offset >= 0, "Attempted to seek to a negative offset");
                    offsetFromStart = offset;
                    break;

                case SeekOrigin.Current:
                    Contract.Assume(m_position >= offset, "Attempted to seek (relative to current) to a negative offset");
                    offsetFromStart = m_position + offset;
                    break;

                case SeekOrigin.End:
                    throw new NotSupportedException("Seeking relative to stream end is not supported");

                default:
                    throw Contract.AssertFailure("Unknwon SeekOrigin");
                }

                if (m_position != offsetFromStart)
                {
                    FlushOrDiscardBufferAndResetPositionAsync(token, slot, offsetFromStart).GetAwaiter().GetResult();
                }

                return(offsetFromStart);
            }
        }
示例#22
0
        /// <inheritdoc/>
        protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame)
        {
            var result = m_expression.Eval(context, env, frame);

            if (result.IsErrorValue)
            {
                return(result);
            }

            if (!(result.Value is ModuleLiteral module))
            {
                var thisNodeType = nameof(ModuleToObjectLiteral);
                throw Contract.AssertFailure(
                          $"AstConverter should never create a '{thisNodeType}' node that wraps an expression that evaluates to something other than {nameof(ModuleLiteral)}. " +
                          $"Instead, this '{thisNodeType}' wraps an expression of type '{m_expression.GetType().Name}' which evaluated to an instance of type '{result.Value?.GetType().Name}'.");
            }

            var bindings = module
                           .GetAllBindings(context)
                           .Where(kvp => kvp.Key != Constants.Names.RuntimeRootNamespaceAlias)
                           .Select(kvp =>
            {
                var name       = SymbolAtom.Create(context.StringTable, kvp.Key);
                var location   = kvp.Value.Location;
                var evalResult = module.GetOrEvalFieldBinding(context, name, kvp.Value, location);
                return(new Binding(name, evalResult.Value, location));
            })
                           .ToArray();

            if (bindings.Any(b => b.Body.IsErrorValue()))
            {
                return(EvaluationResult.Error);
            }

            var objectLiteral = ObjectLiteral.Create(bindings);

            return(EvaluationResult.Create(objectLiteral));
        }
示例#23
0
        /// <summary>
        /// Returns a RetryInfo object with the default location for the given RetryReason.
        /// </summary>
        public static RetryInfo GetDefault(RetryReason reason)
        {
            switch (reason)
            {
            case RetryReason.ResourceExhaustion:
            case RetryReason.ProcessStartFailure:
            case RetryReason.TempDirectoryCleanupFailure:
            case RetryReason.StoppedWorker:
                return(RetryOnDifferentWorker(reason));

            case RetryReason.OutputWithNoFileAccessFailed:
            case RetryReason.MismatchedMessageCount:
            case RetryReason.AzureWatsonExitCode:
            case RetryReason.UserSpecifiedExitCode:
                return(RetryOnSameWorker(reason));

            case RetryReason.VmExecutionError:
                return(RetryOnSameAndDifferentWorkers(reason));

            default:
                throw Contract.AssertFailure("Default not defined for RetryReason: " + reason.ToString());
            }
        }
示例#24
0
        /// <summary>
        /// Analyze the <paramref name="sourceFile"/>.
        /// </summary>
        /// <remarks>
        /// This method will compute the type of the file and will call appropriate analisys function.
        /// </remarks>
        public void AnalyzeFile(ISourceFile sourceFile, Logger logger, LoggingContext loggingContext, PathTable pathTable, Workspace workspace)
        {
            var scope = GetFileScope(sourceFile);

            switch (scope)
            {
            case RuleAnalysisScope.BuildListFile:
            case RuleAnalysisScope.SpecFile:
                AnalyzeSpecFile(sourceFile, logger, loggingContext, pathTable, workspace);
                break;

            case RuleAnalysisScope.RootConfig:
                AnalyzeRootConfigurationFile(sourceFile, logger, loggingContext, pathTable);
                break;

            case RuleAnalysisScope.PackageConfig:
                AnalyzePackageConfigurationFile(sourceFile, logger, loggingContext, pathTable);
                break;

            default:
                throw Contract.AssertFailure($"Unknown file scope '{scope}'.");
            }
        }
示例#25
0
        /// <summary>
        /// Indicates that edge set should no longer be considered for cycle detection, and advances state under big lock accordingly.
        /// </summary>
        private void Remove(EdgeSet edgeSet)
        {
            lock (m_pendingEdgeSets)
            {
                switch (edgeSet.State)
                {
                case EdgeSetState.PendingAdd:
                    edgeSet.State = EdgeSetState.Invalid;
                    Contract.Assume(edgeSet.PendingEdgeSetNode != null);
                    m_pendingEdgeSets.Remove(edgeSet.PendingEdgeSetNode);
                    Interlocked.Increment(ref m_statistics.CycleDetectionChainsRemovedBeforeProcessing);
                    break;

                case EdgeSetState.Adding:
                    edgeSet.State = EdgeSetState.Abandoned;
                    break;

                case EdgeSetState.Added:
                    edgeSet.State = EdgeSetState.PendingRemove;
                    m_pendingEdgeSets.AddFirst(edgeSet);

                    // We don't need to set EdgeSet.PendingEdgeSetNode, as the edge set will now eventually be processed for removal, and it will never be dropped from the middle of m_pendingEdgeSets.
                    Interlocked.Increment(ref m_statistics.CycleDetectionChainsRemovedAfterProcessing);
                    break;

                case EdgeSetState.Invalid:
                case EdgeSetState.Abandoned:
                case EdgeSetState.PendingRemove:
                    // could happen if edge set gets disposed multiple times
                    break;

                default:
                    throw Contract.AssertFailure("unexpected edge set state");
                }
            }
        }
示例#26
0
        public static bool IndicatesFailure(this PipState current)
        {
            Contract.Ensures(ContractUtilities.Static(IsTerminal(current)));

            switch (current)
            {
            case PipState.Ignored:
            case PipState.Waiting:
            case PipState.Ready:
            case PipState.Running:
                return(false);    // Non-terminal

            case PipState.Done:
                return(false);    // Terminal but successful

            case PipState.Skipped:
            case PipState.Failed:
            case PipState.Canceled:
                return(true);    // Oh no!

            default:
                throw Contract.AssertFailure("Unhandled Pip State");
            }
        }
示例#27
0
        public static PipExecutionLevel ToExecutionLevel(this PipResultStatus result)
        {
            Contract.Requires(result.IndicatesExecution());

            switch (result)
            {
            case PipResultStatus.Succeeded:
                return(PipExecutionLevel.Executed);

            case PipResultStatus.Failed:
            case PipResultStatus.Canceled:
                return(PipExecutionLevel.Failed);

            case PipResultStatus.DeployedFromCache:
            case PipResultStatus.NotMaterialized:     // TODO: This is misleading; should account for eventual materialization.
                return(PipExecutionLevel.Cached);

            case PipResultStatus.UpToDate:
                return(PipExecutionLevel.UpToDate);

            default:
                throw Contract.AssertFailure("Unhandled Pip Result that indicates execution");
            }
        }
示例#28
0
        private SymbolAtom GetConfigKeyword(ISourceFile sourceFile)
        {
            string configKeywordString = sourceFile.Statements[0].TryGetFunctionNameInCallExpression();

            Contract.Assert(configKeywordString != null, I($"Configuration validation for '{Kind}' should have caught that the first statement is not a call expression"));

            switch (Kind)
            {
            case ConfigurationKind.PrimaryConfig:
                Contract.Assert(
                    configKeywordString == Script.Constants.Names.ConfigurationFunctionCall,
                    I($"Configuration validation for '{Kind}' should have caught that a wrong configuration keyword was used ('{configKeywordString}' instead of '{Script.Constants.Names.ConfigurationFunctionCall}')"));
                return(SymbolAtom.Create(Context.StringTable, configKeywordString));

            case ConfigurationKind.ModuleConfig:
                Contract.Assert(
                    configKeywordString == Script.Constants.Names.ModuleConfigurationFunctionCall || configKeywordString == Script.Constants.Names.LegacyModuleConfigurationFunctionCall,
                    I($"Configuration validation for '{Kind}' should have caught that a wrong configuration keyword was used ('{configKeywordString}' instead of either '{Script.Constants.Names.ModuleConfigurationFunctionCall}' or '{Script.Constants.Names.LegacyModuleConfigurationFunctionCall}')"));
                return(SymbolAtom.Create(Context.StringTable, configKeywordString));

            default:
                throw Contract.AssertFailure(UnimplementedOperationForConfigKindErrorMessage);
            }
        }
示例#29
0
        void IIOCompletionTarget.OnCompletion(FileAsyncIOResult result)
        {
            // Note that this may be called on the same stack as StartBackgroundOperation (sync completion),
            Contract.Assume(result.Status != FileAsyncIOStatus.Pending);

            bool failed = result.Status == FileAsyncIOStatus.Failed;

            if (!failed)
            {
                // Note, that FileAsyncIOResult constructor can't enforce this check because in some other cases
                // 0 transfered bytes is ok for a successful IO operation.
                Contract.Assert(result.BytesTransferred > 0, "Zero bytes transferred is a failure indication (otherwise can be confused with EOF)");
            }

            TaskCompletionSource <BackgroundOperationSlot> completionSource;

            lock (m_backgroundOperationLock)
            {
                // Capture the completion source to use outside of the lock.
                completionSource = m_currentBackgroundOperationCompletionSource;

                switch (m_currentBackgroundOperation)
                {
                case StreamBackgroundOperation.Fill:
                    m_bufferPosition += result.BytesTransferred;
                    internalBuffer.FinishFillAndUnlock(numberOfBytesFilled: result.BytesTransferred);
                    break;

                case StreamBackgroundOperation.Flush:
                    m_bufferPosition += result.BytesTransferred;
                    internalBuffer.FinishFlushAndUnlock(numberOfBytesFlushed: result.BytesTransferred);
                    break;

                case StreamBackgroundOperation.None:
                    Contract.Assume(false, "Unexpected I/O completion (no background operation in progress)");
                    throw new InvalidOperationException("Unreachable");

                default:
                    throw Contract.AssertFailure("Unhandled StreamBackgroundOperation");
                }

                if (failed)
                {
                    StreamUsability newUsability;
                    if (result.ErrorIndicatesEndOfFile)
                    {
                        newUsability = StreamUsability.EndOfFileReached;
                    }
                    else
                    {
                        newUsability = StreamUsability.Broken;

                        m_brokenStreamException = new IOException(
                            "An error occurred while reading or writing to a file stream. The stream will no longer be usable.",
                            new NativeWin32Exception(result.Error));
                    }

                    m_usability = newUsability;
                }
                else
                {
                    Contract.Assume(m_usability == StreamUsability.Usable);
                }

                m_currentBackgroundOperation = StreamBackgroundOperation.None;
                m_currentBackgroundOperationCompletionSource = null;
            }

            // Since the lock is no longer held, it is safe to resume any waiters (note that they may run on this stack).
            if (completionSource != null)
            {
                completionSource.SetResult(new BackgroundOperationSlot(this));
            }
        }
示例#30
0
        /// <summary>
        /// Dynamically inspects the object and returns the RuntimeTypeId
        /// </summary>
        public static RuntimeTypeId ComputeTypeOfKind(object value)
        {
            Contract.Assume(value != null);

            // In the future we'd like to use C# 7's Switch statements with patterns https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
            // Checking runtime type per pattern of: https://blogs.msdn.microsoft.com/vancem/2006/10/01/drilling-into-net-runtime-microbenchmarks-typeof-optimizations/
            if (value == UndefinedValue.Instance)
            {
                return(RuntimeTypeId.Undefined);
            }

            var runtimeType = value.GetType();

            // Need to handle both cases: ArrayLiteral itself, and generic version.
            // In latter case, checking that runtimeType is assignable to ArrayLiteral.
            if (runtimeType == typeof(ArrayLiteral) || typeof(ArrayLiteral).IsAssignableFrom(runtimeType))
            {
                return(RuntimeTypeId.Array);
            }

            if (runtimeType.IsObjectLikeLiteralType())
            {
                return(RuntimeTypeId.Object);
            }

            if (runtimeType.IsModuleLiteral())
            {
                // We want to expand this to proper namespace node in the future when we deprecate moduleliteral
                return(RuntimeTypeId.ModuleLiteral);
            }

            if (runtimeType == typeof(AbsolutePath))
            {
                return(RuntimeTypeId.Path);
            }

            if (runtimeType == typeof(FileArtifact))
            {
                return(RuntimeTypeId.File);
            }

            if (runtimeType == typeof(DirectoryArtifact))
            {
                return(RuntimeTypeId.Directory);
            }

            if (runtimeType == typeof(StaticDirectory))
            {
                return(GetRuntimeTypeForStaticDirectory(value as StaticDirectory));
            }

            if (runtimeType == typeof(RelativePath))
            {
                return(RuntimeTypeId.RelativePath);
            }

            if (runtimeType == typeof(PathAtom))
            {
                return(RuntimeTypeId.PathAtom);
            }

            if (runtimeType == typeof(string))
            {
                return(RuntimeTypeId.String);
            }

            if (runtimeType == typeof(bool))
            {
                return(RuntimeTypeId.Boolean);
            }

            if (runtimeType == typeof(int))
            {
                // We only support integers during evaluation, we'll have to expand this when we support more.
                return(RuntimeTypeId.Number);
            }

            if (runtimeType == typeof(Closure))
            {
                return(RuntimeTypeId.Function);
            }

            if (runtimeType == typeof(EnumValue))
            {
                return(RuntimeTypeId.Enum);
            }

            if (runtimeType == typeof(OrderedSet))
            {
                return(RuntimeTypeId.Set);
            }

            if (runtimeType == typeof(OrderedMap))
            {
                return(RuntimeTypeId.Map);
            }

            throw Contract.AssertFailure(I($"Unexpected runtime value with type '{runtimeType}' encountered."));
        }