{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/roslyn/pulls/comments/124097962","pull_request_review_id":46358178,"id":124097962,"diff_hunk":"@@ -0,0 +1,166 @@\n+﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\n+\n+using System;\n+using System.IO;\n+using System.Threading;\n+using System.Threading.Tasks;\n+using Microsoft.CodeAnalysis;\n+using Microsoft.CodeAnalysis.Execution;\n+using Microsoft.CodeAnalysis.Remote;\n+using Roslyn.Utilities;\n+using StreamJsonRpc;\n+using Microsoft.CodeAnalysis.Internal.Log;\n+\n+namespace Microsoft.VisualStudio.LanguageServices.Remote\n+{\n+    /// <summary>\n+    /// Communication channel between remote host client and remote host.\n+    /// \n+    /// this is framework's back channel to talk to remote host\n+    /// \n+    /// for example, this will be used to deliver missing remotable data to remote host.\n+    /// \n+    /// all connection will share one remotable data channel\n+    /// </summary>\n+    internal class RemotableDataJsonRpcEx : JsonRpcEx\n+    {\n+        private readonly IRemotableDataService _remotableDataService;\n+        private readonly CancellationTokenSource _source;\n+\n+        /// <summary>\n+        /// number of shared count\n+        /// </summary>\n+        private readonly object _gate;\n+        private int _count;\n+\n+        public RemotableDataJsonRpcEx(Microsoft.CodeAnalysis.Workspace workspace, Stream stream)\n+            : base(stream, callbackTarget: null, useThisAsCallback: true, cancellationToken: CancellationToken.None)\n+        {\n+            _gate = new object();\n+            _count = 1;\n+\n+            _remotableDataService = workspace.Services.GetService<IRemotableDataService>();\n+\n+            // cancellation will be removed once I get to cancellation refactoring\n+            _source = new CancellationTokenSource();\n+\n+            StartListening();\n+        }\n+\n+        /// <summary>\n+        /// this is callback from remote host side to get asset associated with checksum from VS.\n+        /// </summary>\n+        public async Task RequestAssetAsync(int scopeId, Checksum[] checksums, string streamName)\n+        {\n+            try\n+            {\n+                using (Logger.LogBlock(FunctionId.JsonRpcSession_RequestAssetAsync, streamName, _source.Token))\n+                using (var stream = await DirectStream.GetAsync(streamName, _source.Token).ConfigureAwait(false))\n+                {\n+                    using (var writer = new ObjectWriter(stream))\n+                    {\n+                        writer.WriteInt32(scopeId);\n+\n+                        await WriteAssetAsync(writer, scopeId, checksums).ConfigureAwait(false);\n+                    }\n+\n+                    await stream.FlushAsync(_source.Token).ConfigureAwait(false);\n+                }\n+            }\n+            catch (IOException)\n+            {\n+                // remote host side is cancelled (client stream connection is closed)\n+                // can happen if pinned solution scope is disposed\n+            }\n+            catch (OperationCanceledException)\n+            {\n+                // rpc connection is closed. \n+                // can happen if pinned solution scope is disposed\n+            }\n+        }\n+\n+        private async Task WriteAssetAsync(ObjectWriter writer, int scopeId, Checksum[] checksums)\n+        {\n+            // special case\n+            if (checksums.Length == 0)\n+            {\n+                await WriteNoAssetAsync(writer).ConfigureAwait(false);\n+                return;\n+            }\n+\n+            if (checksums.Length == 1)\n+            {\n+                await WriteOneAssetAsync(writer, scopeId, checksums[0]).ConfigureAwait(false);\n+                return;\n+            }\n+\n+            await WriteMultipleAssetsAsync(writer, scopeId, checksums).ConfigureAwait(false);\n+        }\n+\n+        private Task WriteNoAssetAsync(ObjectWriter writer)\n+        {\n+            writer.WriteInt32(0);\n+            return SpecializedTasks.EmptyTask;\n+        }\n+\n+        private async Task WriteOneAssetAsync(ObjectWriter writer, int scopeId, Checksum checksum)\n+        {\n+            var remotableData = _remotableDataService.GetRemotableData(scopeId, checksum, _source.Token) ?? RemotableData.Null;\n+            writer.WriteInt32(1);\n+\n+            checksum.WriteTo(writer);\n+            writer.WriteInt32((int)remotableData.Kind);\n+\n+            await remotableData.WriteObjectToAsync(writer, _source.Token).ConfigureAwait(false);\n+        }\n+\n+        private async Task WriteMultipleAssetsAsync(ObjectWriter writer, int scopeId, Checksum[] checksums)\n+        {\n+            var remotableDataMap = _remotableDataService.GetRemotableData(scopeId, checksums, _source.Token);\n+            writer.WriteInt32(remotableDataMap.Count);\n+\n+            foreach (var kv in remotableDataMap)","path":"src/VisualStudio/Core/Next/Remote/RemotableDataJsonRpcEx.cs","position":122,"original_position":122,"commit_id":"fd2370e89239e29af34d84b74ccdf8f7006cbfda","original_commit_id":"fd2370e89239e29af34d84b74ccdf8f7006cbfda","user":{"login":"heejaechang","id":1333179,"avatar_url":"https://avatars0.githubusercontent.com/u/1333179?v=3","gravatar_id":"","url":"https://api.github.com/users/heejaechang","html_url":"https://github.com/heejaechang","followers_url":"https://api.github.com/users/heejaechang/followers","following_url":"https://api.github.com/users/heejaechang/following{/other_user}","gists_url":"https://api.github.com/users/heejaechang/gists{/gist_id}","starred_url":"https://api.github.com/users/heejaechang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heejaechang/subscriptions","organizations_url":"https://api.github.com/users/heejaechang/orgs","repos_url":"https://api.github.com/users/heejaechang/repos","events_url":"https://api.github.com/users/heejaechang/events{/privacy}","received_events_url":"https://api.github.com/users/heejaechang/received_events","type":"User","site_admin":false},"body":"sure","created_at":"2017-06-26T19:25:48Z","updated_at":"2017-06-26T19:25:48Z","html_url":"https://github.com/dotnet/roslyn/pull/20317#discussion_r124097962","pull_request_url":"https://api.github.com/repos/dotnet/roslyn/pulls/20317","_links":{"self":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/comments/124097962"},"html":{"href":"https://github.com/dotnet/roslyn/pull/20317#discussion_r124097962"},"pull_request":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/20317"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/roslyn/pulls/20317","id":126397867,"html_url":"https://github.com/dotnet/roslyn/pull/20317","diff_url":"https://github.com/dotnet/roslyn/pull/20317.diff","patch_url":"https://github.com/dotnet/roslyn/pull/20317.patch","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/20317","number":20317,"state":"open","locked":false,"title":"made remotabledata channel to be shared by all connections","user":{"login":"heejaechang","id":1333179,"avatar_url":"https://avatars0.githubusercontent.com/u/1333179?v=3","gravatar_id":"","url":"https://api.github.com/users/heejaechang","html_url":"https://github.com/heejaechang","followers_url":"https://api.github.com/users/heejaechang/followers","following_url":"https://api.github.com/users/heejaechang/following{/other_user}","gists_url":"https://api.github.com/users/heejaechang/gists{/gist_id}","starred_url":"https://api.github.com/users/heejaechang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heejaechang/subscriptions","organizations_url":"https://api.github.com/users/heejaechang/orgs","repos_url":"https://api.github.com/users/heejaechang/repos","events_url":"https://api.github.com/users/heejaechang/events{/privacy}","received_events_url":"https://api.github.com/users/heejaechang/received_events","type":"User","site_admin":false},"body":"previously, when consumer wants to connect to remote host, the engine internally created 2 channels to the remote host. one for the consumer itself, and the other to move remotable data required for the consumer in background.\r\n\r\nthis was done so that each consumer can have its own isolated connections from others. but later discovered that it can cause too much allocations since something like code lens can cause remote host to have 10+ more concurrent requests and syncing all those remotable data at once can cause too high allocation rate.\r\n\r\nso, in RTM, we throttled on how many can sync remotable data at the same time, but left 2 channels design as it was.\r\n\r\nthis change makes connection to have only 1 channel, and remotable data channel to be shared by all connections. since there is time delay to make connection to remote host, this should reduce delay required per each connection.","created_at":"2017-06-19T21:07:05Z","updated_at":"2017-06-26T19:25:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"64e5a1130911666a7c6366e2d2d1bea33b0d1cf4","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/roslyn/pulls/20317/commits","review_comments_url":"https://api.github.com/repos/dotnet/roslyn/pulls/20317/comments","review_comment_url":"https://api.github.com/repos/dotnet/roslyn/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/20317/comments","statuses_url":"https://api.github.com/repos/dotnet/roslyn/statuses/fd2370e89239e29af34d84b74ccdf8f7006cbfda","head":{"label":"heejaechang:RemoteSnapshot1","ref":"RemoteSnapshot1","sha":"fd2370e89239e29af34d84b74ccdf8f7006cbfda","user":{"login":"heejaechang","id":1333179,"avatar_url":"https://avatars0.githubusercontent.com/u/1333179?v=3","gravatar_id":"","url":"https://api.github.com/users/heejaechang","html_url":"https://github.com/heejaechang","followers_url":"https://api.github.com/users/heejaechang/followers","following_url":"https://api.github.com/users/heejaechang/following{/other_user}","gists_url":"https://api.github.com/users/heejaechang/gists{/gist_id}","starred_url":"https://api.github.com/users/heejaechang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heejaechang/subscriptions","organizations_url":"https://api.github.com/users/heejaechang/orgs","repos_url":"https://api.github.com/users/heejaechang/repos","events_url":"https://api.github.com/users/heejaechang/events{/privacy}","received_events_url":"https://api.github.com/users/heejaechang/received_events","type":"User","site_admin":false},"repo":{"id":30170221,"name":"roslyn","full_name":"heejaechang/roslyn","owner":{"login":"heejaechang","id":1333179,"avatar_url":"https://avatars0.githubusercontent.com/u/1333179?v=3","gravatar_id":"","url":"https://api.github.com/users/heejaechang","html_url":"https://github.com/heejaechang","followers_url":"https://api.github.com/users/heejaechang/followers","following_url":"https://api.github.com/users/heejaechang/following{/other_user}","gists_url":"https://api.github.com/users/heejaechang/gists{/gist_id}","starred_url":"https://api.github.com/users/heejaechang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/heejaechang/subscriptions","organizations_url":"https://api.github.com/users/heejaechang/orgs","repos_url":"https://api.github.com/users/heejaechang/repos","events_url":"https://api.github.com/users/heejaechang/events{/privacy}","received_events_url":"https://api.github.com/users/heejaechang/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/heejaechang/roslyn","description":"The .NET Compiler Platform (\"Roslyn\") provides open-source C# and Visual Basic compilers with rich code analysis APIs.","fork":true,"url":"https://api.github.com/repos/heejaechang/roslyn","forks_url":"https://api.github.com/repos/heejaechang/roslyn/forks","keys_url":"https://api.github.com/repos/heejaechang/roslyn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/heejaechang/roslyn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/heejaechang/roslyn/teams","hooks_url":"https://api.github.com/repos/heejaechang/roslyn/hooks","issue_events_url":"https://api.github.com/repos/heejaechang/roslyn/issues/events{/number}","events_url":"https://api.github.com/repos/heejaechang/roslyn/events","assignees_url":"https://api.github.com/repos/heejaechang/roslyn/assignees{/user}","branches_url":"https://api.github.com/repos/heejaechang/roslyn/branches{/branch}","tags_url":"https://api.github.com/repos/heejaechang/roslyn/tags","blobs_url":"https://api.github.com/repos/heejaechang/roslyn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/heejaechang/roslyn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/heejaechang/roslyn/git/refs{/sha}","trees_url":"https://api.github.com/repos/heejaechang/roslyn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/heejaechang/roslyn/statuses/{sha}","languages_url":"https://api.github.com/repos/heejaechang/roslyn/languages","stargazers_url":"https://api.github.com/repos/heejaechang/roslyn/stargazers","contributors_url":"https://api.github.com/repos/heejaechang/roslyn/contributors","subscribers_url":"https://api.github.com/repos/heejaechang/roslyn/subscribers","subscription_url":"https://api.github.com/repos/heejaechang/roslyn/subscription","commits_url":"https://api.github.com/repos/heejaechang/roslyn/commits{/sha}","git_commits_url":"https://api.github.com/repos/heejaechang/roslyn/git/commits{/sha}","comments_url":"https://api.github.com/repos/heejaechang/roslyn/comments{/number}","issue_comment_url":"https://api.github.com/repos/heejaechang/roslyn/issues/comments{/number}","contents_url":"https://api.github.com/repos/heejaechang/roslyn/contents/{+path}","compare_url":"https://api.github.com/repos/heejaechang/roslyn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/heejaechang/roslyn/merges","archive_url":"https://api.github.com/repos/heejaechang/roslyn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/heejaechang/roslyn/downloads","issues_url":"https://api.github.com/repos/heejaechang/roslyn/issues{/number}","pulls_url":"https://api.github.com/repos/heejaechang/roslyn/pulls{/number}","milestones_url":"https://api.github.com/repos/heejaechang/roslyn/milestones{/number}","notifications_url":"https://api.github.com/repos/heejaechang/roslyn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/heejaechang/roslyn/labels{/name}","releases_url":"https://api.github.com/repos/heejaechang/roslyn/releases{/id}","deployments_url":"https://api.github.com/repos/heejaechang/roslyn/deployments","created_at":"2015-02-02T03:54:43Z","updated_at":"2016-03-09T20:46:51Z","pushed_at":"2017-06-23T22:41:29Z","git_url":"git://github.com/heejaechang/roslyn.git","ssh_url":"git@github.com:heejaechang/roslyn.git","clone_url":"https://github.com/heejaechang/roslyn.git","svn_url":"https://github.com/heejaechang/roslyn","homepage":"","size":210034,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:dev15.6","ref":"dev15.6","sha":"d170a78d3b465904432a15823414d859ed6f2536","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars3.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":29078997,"name":"roslyn","full_name":"dotnet/roslyn","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars3.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/roslyn","description":"The .NET Compiler Platform (\"Roslyn\") provides open-source C# and Visual Basic compilers with rich code analysis APIs.","fork":false,"url":"https://api.github.com/repos/dotnet/roslyn","forks_url":"https://api.github.com/repos/dotnet/roslyn/forks","keys_url":"https://api.github.com/repos/dotnet/roslyn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/roslyn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/roslyn/teams","hooks_url":"https://api.github.com/repos/dotnet/roslyn/hooks","issue_events_url":"https://api.github.com/repos/dotnet/roslyn/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/roslyn/events","assignees_url":"https://api.github.com/repos/dotnet/roslyn/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/roslyn/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/roslyn/tags","blobs_url":"https://api.github.com/repos/dotnet/roslyn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/roslyn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/roslyn/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/roslyn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/roslyn/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/roslyn/languages","stargazers_url":"https://api.github.com/repos/dotnet/roslyn/stargazers","contributors_url":"https://api.github.com/repos/dotnet/roslyn/contributors","subscribers_url":"https://api.github.com/repos/dotnet/roslyn/subscribers","subscription_url":"https://api.github.com/repos/dotnet/roslyn/subscription","commits_url":"https://api.github.com/repos/dotnet/roslyn/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/roslyn/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/roslyn/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/roslyn/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/roslyn/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/roslyn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/roslyn/merges","archive_url":"https://api.github.com/repos/dotnet/roslyn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/roslyn/downloads","issues_url":"https://api.github.com/repos/dotnet/roslyn/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/roslyn/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/roslyn/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/roslyn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/roslyn/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/roslyn/releases{/id}","deployments_url":"https://api.github.com/repos/dotnet/roslyn/deployments","created_at":"2015-01-11T02:39:03Z","updated_at":"2017-06-26T14:49:44Z","pushed_at":"2017-06-26T18:46:04Z","git_url":"git://github.com/dotnet/roslyn.git","ssh_url":"git@github.com:dotnet/roslyn.git","clone_url":"https://github.com/dotnet/roslyn.git","svn_url":"https://github.com/dotnet/roslyn","homepage":"","size":218026,"stargazers_count":7684,"watchers_count":7684,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1882,"mirror_url":null,"open_issues_count":3770,"forks":1882,"open_issues":3770,"watchers":7684,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/20317"},"html":{"href":"https://github.com/dotnet/roslyn/pull/20317"},"issue":{"href":"https://api.github.com/repos/dotnet/roslyn/issues/20317"},"comments":{"href":"https://api.github.com/repos/dotnet/roslyn/issues/20317/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/20317/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/20317/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/roslyn/statuses/fd2370e89239e29af34d84b74ccdf8f7006cbfda"}}}}
{"actor":{"display_login":"heejaechang"}}