{"action":"created","comment":{"url":"https://api.github.com/repos/caskdata/cdap/pulls/comments/47329371","id":47329371,"diff_hunk":"@@ -0,0 +1,90 @@\n+/*\n+ * Copyright © 2015 Cask Data, Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n+ * use this file except in compliance with the License. You may obtain a copy of\n+ * the License at\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n+ * License for the specific language governing permissions and limitations under\n+ * the License.\n+ */\n+\n+package co.cask.cdap.gateway.router.handlers;\n+\n+import org.jboss.netty.channel.Channel;\n+import org.jboss.netty.channel.ChannelHandlerContext;\n+import org.jboss.netty.channel.ChannelStateEvent;\n+import org.jboss.netty.channel.MessageEvent;\n+import org.jboss.netty.handler.codec.http.HttpChunk;\n+import org.jboss.netty.handler.codec.http.HttpRequest;\n+import org.jboss.netty.handler.codec.http.HttpResponse;\n+import org.jboss.netty.handler.timeout.IdleState;\n+import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;\n+import org.jboss.netty.handler.timeout.IdleStateEvent;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+/**\n+ * Handles states when the router has been idle for a configured time interval, by closing the channel if an\n+ * HTTP Request is not in progress.\n+ */\n+public class IdleEventProcessor extends IdleStateAwareChannelHandler {\n+  private static final Logger LOG = LoggerFactory.getLogger(IdleEventProcessor.class);\n+  private volatile boolean requestInProgress;\n+\n+  @Override\n+  public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {\n+    super.channelClosed(ctx, e);\n+  }\n+\n+  @Override\n+  public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {\n+    if (IdleState.ALL_IDLE == e.getState()) {\n+      if (requestInProgress) {\n+        LOG.trace(\"Request is in progress, so not closing channel.\");\n+      } else {\n+        // No data has been sent or received for a while. Close channel.\n+        Channel channel = ctx.getChannel();\n+        channel.close();\n+        LOG.trace(\"No data has been sent or received for channel '{}' for more than the configured idle timeout. \" +\n+                   \"Closing the channel. Local Address: {}, Remote Address: {}\",\n+                 channel, channel.getLocalAddress(), channel.getRemoteAddress());\n+      }\n+    }\n+    super.channelIdle(ctx, e);\n+  }\n+\n+  @Override\n+  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)\n+    throws Exception {\n+    Object message = e.getMessage();\n+    if (message instanceof HttpResponse) {\n+      HttpResponse response = (HttpResponse) message;\n+      if (!response.isChunked()) {\n+        requestInProgress = false;\n+      }\n+    } else if (message instanceof HttpChunk) {\n+      HttpChunk chunk = (HttpChunk) message;\n+\n+      if (chunk.isLast()) {\n+        requestInProgress = false;\n+      }\n+    }\n+\n+    ctx.sendUpstream(e);\n+  }\n+\n+  @Override\n+  public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {\n+    Object message = e.getMessage();\n+    if (message instanceof HttpRequest || message instanceof HttpChunk) {","path":"cdap-gateway/src/main/java/co/cask/cdap/gateway/router/handlers/IdleEventProcessor.java","position":85,"original_position":85,"commit_id":"ad197deca29f4954213f7cfe356b53cf7992ffe4","original_commit_id":"ad197deca29f4954213f7cfe356b53cf7992ffe4","user":{"login":"anwar6953","id":2440977,"avatar_url":"https://avatars.githubusercontent.com/u/2440977?v=3","gravatar_id":"","url":"https://api.github.com/users/anwar6953","html_url":"https://github.com/anwar6953","followers_url":"https://api.github.com/users/anwar6953/followers","following_url":"https://api.github.com/users/anwar6953/following{/other_user}","gists_url":"https://api.github.com/users/anwar6953/gists{/gist_id}","starred_url":"https://api.github.com/users/anwar6953/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anwar6953/subscriptions","organizations_url":"https://api.github.com/users/anwar6953/orgs","repos_url":"https://api.github.com/users/anwar6953/repos","events_url":"https://api.github.com/users/anwar6953/events{/privacy}","received_events_url":"https://api.github.com/users/anwar6953/received_events","type":"User","site_admin":false},"body":"I check the type of the object, and its type is occasionally `BigEndianHeapChannelBuffer`, for instance, in NettyRouterTestBase#testRouterAsync and NettyRouterTestBase#testConnectionClose. I'm not sure what significance that has, or why that is.","created_at":"2015-12-11T07:55:46Z","updated_at":"2015-12-11T07:55:46Z","html_url":"https://github.com/caskdata/cdap/pull/4741#discussion_r47329371","pull_request_url":"https://api.github.com/repos/caskdata/cdap/pulls/4741","_links":{"self":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/comments/47329371"},"html":{"href":"https://github.com/caskdata/cdap/pull/4741#discussion_r47329371"},"pull_request":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/4741"}}},"pull_request":{"url":"https://api.github.com/repos/caskdata/cdap/pulls/4741","id":53348680,"html_url":"https://github.com/caskdata/cdap/pull/4741","diff_url":"https://github.com/caskdata/cdap/pull/4741.diff","patch_url":"https://github.com/caskdata/cdap/pull/4741.patch","issue_url":"https://api.github.com/repos/caskdata/cdap/issues/4741","number":4741,"state":"open","locked":false,"title":"Feature/cdap 3887 router connection timeout","user":{"login":"anwar6953","id":2440977,"avatar_url":"https://avatars.githubusercontent.com/u/2440977?v=3","gravatar_id":"","url":"https://api.github.com/users/anwar6953","html_url":"https://github.com/anwar6953","followers_url":"https://api.github.com/users/anwar6953/followers","following_url":"https://api.github.com/users/anwar6953/following{/other_user}","gists_url":"https://api.github.com/users/anwar6953/gists{/gist_id}","starred_url":"https://api.github.com/users/anwar6953/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anwar6953/subscriptions","organizations_url":"https://api.github.com/users/anwar6953/orgs","repos_url":"https://api.github.com/users/anwar6953/repos","events_url":"https://api.github.com/users/anwar6953/events{/privacy}","received_events_url":"https://api.github.com/users/anwar6953/received_events","type":"User","site_admin":false},"body":"NettyRouter now closes connections if there has been no HTTP request in flight for a given timeout.\r\nIdleStateHandler sends an event when the connection has been idle. IdleEventProcessor gets this event and closes the channel if no HTTP Request is in progress.\r\n\r\nThe first commit is based off of Bhooshan's changes: https://github.com/caskdata/cdap/pull/4299\r\nThe remainder commits are changes that are new in this PR.\r\n\r\nhttps://issues.cask.co/browse/CDAP-3887\r\n\r\nNote: Opening this PR for review; once reviewed, these changes will be back-ported to previous releases (3.2.2 and 2.8.3).\r\nTODO: performance testing\r\n\r\nThis PR is a continuation of https://github.com/caskdata/cdap/pull/4675","created_at":"2015-12-11T03:03:55Z","updated_at":"2015-12-11T07:55:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"89a1d0dffb276bf2de649d7b559de7b55b98f72f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/caskdata/cdap/pulls/4741/commits","review_comments_url":"https://api.github.com/repos/caskdata/cdap/pulls/4741/comments","review_comment_url":"https://api.github.com/repos/caskdata/cdap/pulls/comments{/number}","comments_url":"https://api.github.com/repos/caskdata/cdap/issues/4741/comments","statuses_url":"https://api.github.com/repos/caskdata/cdap/statuses/ad197deca29f4954213f7cfe356b53cf7992ffe4","head":{"label":"caskdata:feature/CDAP-3887-router-connection-timeout","ref":"feature/CDAP-3887-router-connection-timeout","sha":"ad197deca29f4954213f7cfe356b53cf7992ffe4","user":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"repo":{"id":22542759,"name":"cdap","full_name":"caskdata/cdap","owner":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/caskdata/cdap","description":"Cask Data Application Platform (CDAP)","fork":false,"url":"https://api.github.com/repos/caskdata/cdap","forks_url":"https://api.github.com/repos/caskdata/cdap/forks","keys_url":"https://api.github.com/repos/caskdata/cdap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caskdata/cdap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caskdata/cdap/teams","hooks_url":"https://api.github.com/repos/caskdata/cdap/hooks","issue_events_url":"https://api.github.com/repos/caskdata/cdap/issues/events{/number}","events_url":"https://api.github.com/repos/caskdata/cdap/events","assignees_url":"https://api.github.com/repos/caskdata/cdap/assignees{/user}","branches_url":"https://api.github.com/repos/caskdata/cdap/branches{/branch}","tags_url":"https://api.github.com/repos/caskdata/cdap/tags","blobs_url":"https://api.github.com/repos/caskdata/cdap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caskdata/cdap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caskdata/cdap/git/refs{/sha}","trees_url":"https://api.github.com/repos/caskdata/cdap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caskdata/cdap/statuses/{sha}","languages_url":"https://api.github.com/repos/caskdata/cdap/languages","stargazers_url":"https://api.github.com/repos/caskdata/cdap/stargazers","contributors_url":"https://api.github.com/repos/caskdata/cdap/contributors","subscribers_url":"https://api.github.com/repos/caskdata/cdap/subscribers","subscription_url":"https://api.github.com/repos/caskdata/cdap/subscription","commits_url":"https://api.github.com/repos/caskdata/cdap/commits{/sha}","git_commits_url":"https://api.github.com/repos/caskdata/cdap/git/commits{/sha}","comments_url":"https://api.github.com/repos/caskdata/cdap/comments{/number}","issue_comment_url":"https://api.github.com/repos/caskdata/cdap/issues/comments{/number}","contents_url":"https://api.github.com/repos/caskdata/cdap/contents/{+path}","compare_url":"https://api.github.com/repos/caskdata/cdap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caskdata/cdap/merges","archive_url":"https://api.github.com/repos/caskdata/cdap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caskdata/cdap/downloads","issues_url":"https://api.github.com/repos/caskdata/cdap/issues{/number}","pulls_url":"https://api.github.com/repos/caskdata/cdap/pulls{/number}","milestones_url":"https://api.github.com/repos/caskdata/cdap/milestones{/number}","notifications_url":"https://api.github.com/repos/caskdata/cdap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caskdata/cdap/labels{/name}","releases_url":"https://api.github.com/repos/caskdata/cdap/releases{/id}","created_at":"2014-08-02T09:00:10Z","updated_at":"2015-12-09T19:51:54Z","pushed_at":"2015-12-11T07:43:56Z","git_url":"git://github.com/caskdata/cdap.git","ssh_url":"git@github.com:caskdata/cdap.git","clone_url":"https://github.com/caskdata/cdap.git","svn_url":"https://github.com/caskdata/cdap","homepage":"http://cdap.io","size":518405,"stargazers_count":86,"watchers_count":86,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":27,"mirror_url":null,"open_issues_count":15,"forks":27,"open_issues":15,"watchers":86,"default_branch":"develop"}},"base":{"label":"caskdata:release/3.3","ref":"release/3.3","sha":"f0eafad7508242072182697d7b044a0341a3cdfd","user":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"repo":{"id":22542759,"name":"cdap","full_name":"caskdata/cdap","owner":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/caskdata/cdap","description":"Cask Data Application Platform (CDAP)","fork":false,"url":"https://api.github.com/repos/caskdata/cdap","forks_url":"https://api.github.com/repos/caskdata/cdap/forks","keys_url":"https://api.github.com/repos/caskdata/cdap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caskdata/cdap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caskdata/cdap/teams","hooks_url":"https://api.github.com/repos/caskdata/cdap/hooks","issue_events_url":"https://api.github.com/repos/caskdata/cdap/issues/events{/number}","events_url":"https://api.github.com/repos/caskdata/cdap/events","assignees_url":"https://api.github.com/repos/caskdata/cdap/assignees{/user}","branches_url":"https://api.github.com/repos/caskdata/cdap/branches{/branch}","tags_url":"https://api.github.com/repos/caskdata/cdap/tags","blobs_url":"https://api.github.com/repos/caskdata/cdap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caskdata/cdap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caskdata/cdap/git/refs{/sha}","trees_url":"https://api.github.com/repos/caskdata/cdap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caskdata/cdap/statuses/{sha}","languages_url":"https://api.github.com/repos/caskdata/cdap/languages","stargazers_url":"https://api.github.com/repos/caskdata/cdap/stargazers","contributors_url":"https://api.github.com/repos/caskdata/cdap/contributors","subscribers_url":"https://api.github.com/repos/caskdata/cdap/subscribers","subscription_url":"https://api.github.com/repos/caskdata/cdap/subscription","commits_url":"https://api.github.com/repos/caskdata/cdap/commits{/sha}","git_commits_url":"https://api.github.com/repos/caskdata/cdap/git/commits{/sha}","comments_url":"https://api.github.com/repos/caskdata/cdap/comments{/number}","issue_comment_url":"https://api.github.com/repos/caskdata/cdap/issues/comments{/number}","contents_url":"https://api.github.com/repos/caskdata/cdap/contents/{+path}","compare_url":"https://api.github.com/repos/caskdata/cdap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caskdata/cdap/merges","archive_url":"https://api.github.com/repos/caskdata/cdap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caskdata/cdap/downloads","issues_url":"https://api.github.com/repos/caskdata/cdap/issues{/number}","pulls_url":"https://api.github.com/repos/caskdata/cdap/pulls{/number}","milestones_url":"https://api.github.com/repos/caskdata/cdap/milestones{/number}","notifications_url":"https://api.github.com/repos/caskdata/cdap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caskdata/cdap/labels{/name}","releases_url":"https://api.github.com/repos/caskdata/cdap/releases{/id}","created_at":"2014-08-02T09:00:10Z","updated_at":"2015-12-09T19:51:54Z","pushed_at":"2015-12-11T07:43:56Z","git_url":"git://github.com/caskdata/cdap.git","ssh_url":"git@github.com:caskdata/cdap.git","clone_url":"https://github.com/caskdata/cdap.git","svn_url":"https://github.com/caskdata/cdap","homepage":"http://cdap.io","size":518405,"stargazers_count":86,"watchers_count":86,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":27,"mirror_url":null,"open_issues_count":15,"forks":27,"open_issues":15,"watchers":86,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/4741"},"html":{"href":"https://github.com/caskdata/cdap/pull/4741"},"issue":{"href":"https://api.github.com/repos/caskdata/cdap/issues/4741"},"comments":{"href":"https://api.github.com/repos/caskdata/cdap/issues/4741/comments"},"review_comments":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/4741/comments"},"review_comment":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/4741/commits"},"statuses":{"href":"https://api.github.com/repos/caskdata/cdap/statuses/ad197deca29f4954213f7cfe356b53cf7992ffe4"}}}}