public async Task<PinnedRemotableDataScope> CreatePinnedRemotableDataScopeAsync(Solution solution, CancellationToken cancellationToken)
            {
                using (Logger.LogBlock(FunctionId.SolutionSynchronizationServiceFactory_CreatePinnedRemotableDataScopeAsync, cancellationToken))
                {
                    var storage = _assetStorages.CreateStorage(solution.State);
                    var checksum = await solution.State.GetChecksumAsync(cancellationToken).ConfigureAwait(false);

                    var snapshot = new PinnedRemotableDataScope(_assetStorages, storage, checksum);
                    return snapshot;
                }
            }
        protected override async Task<Session> CreateServiceSessionAsync(string serviceName, PinnedRemotableDataScope snapshot, object callbackTarget, CancellationToken cancellationToken)
        {
            // get stream from service hub to communicate snapshot/asset related information
            // this is the back channel the system uses to move data between VS and remote host
            var snapshotStream = await RequestServiceAsync(_hubClient, WellKnownServiceHubServices.SnapshotService, _hostGroup, cancellationToken).ConfigureAwait(false);

            // get stream from service hub to communicate service specific information
            // this is what consumer actually use to communicate information
            var serviceStream = await RequestServiceAsync(_hubClient, serviceName, _hostGroup, cancellationToken).ConfigureAwait(false);

            return await JsonRpcSession.CreateAsync(snapshot, snapshotStream, callbackTarget, serviceStream, cancellationToken).ConfigureAwait(false);
        }
Esempio n. 3
0
        public RemotableData GetRemotableData(PinnedRemotableDataScope scope, Checksum checksum, CancellationToken cancellationToken)
        {
            if (checksum == Checksum.Null)
            {
                // check nil case
                return RemotableData.Null;
            }

            // search snapshots we have
            foreach (var storage in GetStorages(scope))
            {
                var syncObject = storage.TryGetRemotableData(checksum, cancellationToken);
                if (syncObject != null)
                {
                    return syncObject;
                }
            }

            // search global assets
            foreach (var kv in _globalAssets)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var asset = kv.Value;
                if (asset.Checksum == checksum)
                {
                    return asset;
                }
            }

            // if it reached here, it means things get cancelled. due to involving 2 processes,
            // current design can make slightly staled requests to running even when things cancelled.
            // if it is other case, remote host side will throw and close connection which will cause
            // vs to crash.
            // this should be changed once I address this design issue
            cancellationToken.ThrowIfCancellationRequested();

            return null;
        }
Esempio n. 4
0
        private IEnumerable<Storage> GetStorages(PinnedRemotableDataScope scope)
        {
            if (scope != null)
            {
                yield return _storages[scope];
                yield break;
            }

            using (var solutionProcessed = Creator.CreateChecksumSet())
            {
                foreach (var kv in _storages)
                {
                    if (!solutionProcessed.Object.Add(kv.Key.SolutionChecksum))
                    {
                        continue;
                    }

                    yield return kv.Value;
                }
            }
        }
Esempio n. 5
0
 public void UnregisterSnapshot(PinnedRemotableDataScope snapshot)
 {
     // calling it multiple times for same snapshot is not allowed.
     Storage dummy;
     Contract.ThrowIfFalse(_storages.TryRemove(snapshot, out dummy));
 }
Esempio n. 6
0
 public void RegisterSnapshot(PinnedRemotableDataScope snapshot, AssetStorages.Storage storage)
 {
     // duplicates are not allowed, there can be multiple snapshots to same solution, so no ref counting.
     Contract.ThrowIfFalse(_storages.TryAdd(snapshot, storage));
 }
Esempio n. 7
0
        public IReadOnlyDictionary<Checksum, RemotableData> GetRemotableData(PinnedRemotableDataScope scope, IEnumerable<Checksum> checksums, CancellationToken cancellationToken)
        {
            using (var searchingChecksumsLeft = Creator.CreateChecksumSet(checksums))
            {
                var numberOfChecksumsToSearch = searchingChecksumsLeft.Object.Count;
                var result = new Dictionary<Checksum, RemotableData>(numberOfChecksumsToSearch);

                // check nil case
                if (searchingChecksumsLeft.Object.Remove(Checksum.Null))
                {
                    result[Checksum.Null] = RemotableData.Null;
                }

                // search checksum trees we have
                foreach (var storage in GetStorages(scope))
                {
                    storage.AppendRemotableData(searchingChecksumsLeft.Object, result, cancellationToken);
                    if (result.Count == numberOfChecksumsToSearch)
                    {
                        // no checksum left to find
                        Contract.Requires(searchingChecksumsLeft.Object.Count == 0);
                        return result;
                    }
                }

                // search global assets
                foreach (var kv in _globalAssets)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var asset = kv.Value;
                    if (searchingChecksumsLeft.Object.Remove(asset.Checksum))
                    {
                        result[asset.Checksum] = asset;

                        if (result.Count == numberOfChecksumsToSearch)
                        {
                            // no checksum left to find
                            Contract.Requires(searchingChecksumsLeft.Object.Count == 0);
                            return result;
                        }
                    }
                }

                // if it reached here, it means things get cancelled. due to involving 2 processes,
                // current design can make slightly staled requests to running even when things cancelled.
                // if it is other case, remote host side will throw and close connection which will cause
                // vs to crash.
                // this should be changed once I address this design issue
                cancellationToken.ThrowIfCancellationRequested();

                return result;
            }
        }
Esempio n. 8
0
        private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService service, PinnedRemotableDataScope syncScope)
        {
            var workspace = new AdhocWorkspace();

            var solutionObject = await service.GetValueAsync<SolutionStateChecksums>(syncScope.SolutionChecksum);
            var solutionInfo = await service.GetValueAsync<SolutionInfo.SolutionAttributes>(solutionObject.Info).ConfigureAwait(false);

            var projects = new List<ProjectInfo>();
            foreach (var projectObject in solutionObject.Projects.ToProjectObjects(service))
            {
                var projectInfo = await service.GetValueAsync<ProjectInfo.ProjectAttributes>(projectObject.Info).ConfigureAwait(false);
                if (!workspace.Services.IsSupported(projectInfo.Language))
                {
                    continue;
                }

                var documents = new List<DocumentInfo>();
                foreach (var documentObject in projectObject.Documents.ToDocumentObjects(service))
                {
                    var documentInfo = await service.GetValueAsync<DocumentInfo.DocumentAttributes>(documentObject.Info).ConfigureAwait(false);
                    var text = await service.GetValueAsync<SourceText>(documentObject.Text).ConfigureAwait(false);

                    // TODO: do we need version?
                    documents.Add(
                        DocumentInfo.Create(
                            documentInfo.Id,
                            documentInfo.Name,
                            documentInfo.Folders,
                            documentInfo.SourceCodeKind,
                            TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create())),
                            documentInfo.FilePath,
                            documentInfo.IsGenerated));
                }

                var p2p = new List<ProjectReference>();
                foreach (var checksum in projectObject.ProjectReferences)
                {
                    var reference = await service.GetValueAsync<ProjectReference>(checksum).ConfigureAwait(false);
                    p2p.Add(reference);
                }

                var metadata = new List<MetadataReference>();
                foreach (var checksum in projectObject.MetadataReferences)
                {
                    var reference = await service.GetValueAsync<MetadataReference>(checksum).ConfigureAwait(false);
                    metadata.Add(reference);
                }

                var analyzers = new List<AnalyzerReference>();
                foreach (var checksum in projectObject.AnalyzerReferences)
                {
                    var reference = await service.GetValueAsync<AnalyzerReference>(checksum).ConfigureAwait(false);
                    analyzers.Add(reference);
                }

                var additionals = new List<DocumentInfo>();
                foreach (var documentObject in projectObject.AdditionalDocuments.ToDocumentObjects(service))
                {
                    var documentInfo = await service.GetValueAsync<DocumentInfo.DocumentAttributes>(documentObject.Info).ConfigureAwait(false);
                    var text = await service.GetValueAsync<SourceText>(documentObject.Text).ConfigureAwait(false);

                    // TODO: do we need version?
                    additionals.Add(
                        DocumentInfo.Create(
                            documentInfo.Id,
                            documentInfo.Name,
                            documentInfo.Folders,
                            documentInfo.SourceCodeKind,
                            TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create())),
                            documentInfo.FilePath,
                            documentInfo.IsGenerated));
                }

                var compilationOptions = await service.GetValueAsync<CompilationOptions>(projectObject.CompilationOptions).ConfigureAwait(false);
                var parseOptions = await service.GetValueAsync<ParseOptions>(projectObject.ParseOptions).ConfigureAwait(false);

                projects.Add(
                    ProjectInfo.Create(
                        projectInfo.Id, projectInfo.Version, projectInfo.Name, projectInfo.AssemblyName,
                        projectInfo.Language, projectInfo.FilePath, projectInfo.OutputFilePath,
                        compilationOptions, parseOptions,
                        documents, p2p, metadata, analyzers, additionals, projectInfo.IsSubmission));
            }

            return workspace.AddSolution(SolutionInfo.Create(solutionInfo.Id, solutionInfo.Version, solutionInfo.FilePath, projects));
        }
Esempio n. 9
0
 public void RegisterSnapshot(PinnedRemotableDataScope snapshot, AssetStorages.Storage storage)
 {
     // duplicates are not allowed, there can be multiple snapshots to same solution, so no ref counting.
     Contract.ThrowIfFalse(_storages.TryAdd(snapshot, storage));
 }
Esempio n. 10
0
 public void UnregisterSnapshot(PinnedRemotableDataScope snapshot)
 {
     // calling it multiple times for same snapshot is not allowed.
     Contract.ThrowIfFalse(_storages.TryRemove(snapshot, out var dummy));
 }