{"action":"created","comment":{"url":"https://api.github.com/repos/netty/netty/pulls/comments/28110789","id":28110789,"diff_hunk":"@@ -250,79 +251,168 @@ private void writePendingBytes() throws Http2Exception {\n      * @param connectionWindow The connection window this is available for use at this point in the tree.\n      * @return An object summarizing the write and allocation results.\n      */\n-    private int allocateBytesForTree(Http2Stream parent, int connectionWindow) {\n+    private static int allocateBytesForTree(Http2Stream parent, int connectionWindow) throws Http2Exception {\n         FlowState state = state(parent);\n         if (state.streamableBytesForTree() <= 0) {\n             return 0;\n         }\n-        int bytesAllocated = 0;\n         // If the number of streamable bytes for this tree will fit in the connection window\n         // then there is no need to prioritize the bytes...everyone sends what they have\n         if (state.streamableBytesForTree() <= connectionWindow) {\n-            for (Http2Stream child : parent.children()) {\n-                state = state(child);\n-                int bytesForChild = state.streamableBytes();\n-\n-                if (bytesForChild > 0 || state.hasFrame()) {\n-                    state.allocate(bytesForChild);\n-                    bytesAllocated += bytesForChild;\n-                    connectionWindow -= bytesForChild;\n+            SimpleChildFeeder childFeeder = new SimpleChildFeeder(connectionWindow);\n+            parent.forEachChild(childFeeder);\n+            return childFeeder.bytesAllocated;\n+        }\n+\n+        ChildFeeder childFeeder = new ChildFeeder(parent, connectionWindow);\n+        // Iterate once over all children of this parent and try to feed all the children.\n+        parent.forEachChild(childFeeder);\n+\n+        // Now feed any remaining children that are still hungry until the connection\n+        // window collapses.\n+        childFeeder.feedHungryChildren();\n+\n+        return childFeeder.bytesAllocated;\n+    }\n+\n+    /**\n+     * A {@link Http2StreamVisitor} that performs the HTTP/2 priority algorithm to distribute the available connection\n+     * window appropriately to the children of a given stream.\n+     */\n+    private static final class ChildFeeder implements Http2StreamVisitor {\n+        final int maxSize;\n+        int totalWeight;\n+        int connectionWindow;\n+        int nextTotalWeight;\n+        int nextConnectionWindow;\n+        int bytesAllocated;\n+        Http2Stream[] stillHungry;\n+        int nextTail;\n+\n+        ChildFeeder(Http2Stream parent, int connectionWindow) {\n+            maxSize = parent.numChildren();\n+            totalWeight = parent.totalChildWeights();\n+            this.connectionWindow = connectionWindow;\n+            this.nextConnectionWindow = connectionWindow;\n+        }\n+\n+        @Override\n+        public boolean visit(Http2Stream child) throws Http2Exception {\n+            FlowState state = state(child);\n+            int weight = child.weight();\n+            double weightRatio = weight / (double) totalWeight;\n+\n+            // In order to make progress toward the connection window due to possible rounding errors, we make sure\n+            // that each stream (with data to send) is given at least 1 byte toward the connection window.\n+            int connectionWindowChunk = Math.max(1, (int) (connectionWindow * weightRatio));\n+            int bytesForTree = Math.min(nextConnectionWindow, connectionWindowChunk);\n+            int bytesForChild = Math.min(state.streamableBytes(), bytesForTree);\n+\n+            if (bytesForChild > 0) {\n+                state.allocate(bytesForChild);\n+                bytesAllocated += bytesForChild;\n+                nextConnectionWindow -= bytesForChild;\n+                bytesForTree -= bytesForChild;\n+                // If this subtree still wants to send then re-insert into children list and re-consider for next\n+                // iteration. This is needed because we don't yet know if all the peers will be able to use\n+                // all of their \"fair share\" of the connection window, and if they don't use it then we should\n+                // divide their unused shared up for the peers who still want to send.\n+                if (nextConnectionWindow > 0 && state.streamableBytesForTree() > 0) {\n+                    stillHungry(child);\n+                    nextTotalWeight += weight;\n                 }\n-                int childBytesAllocated = allocateBytesForTree(child, connectionWindow);\n+            }\n+\n+            if (bytesForTree > 0) {\n+                int childBytesAllocated = allocateBytesForTree(child, bytesForTree);\n                 bytesAllocated += childBytesAllocated;\n-                connectionWindow -= childBytesAllocated;\n+                nextConnectionWindow -= childBytesAllocated;\n             }\n-            return bytesAllocated;\n-        }\n-\n-        // This is the priority algorithm which will divide the available bytes based\n-        // upon stream weight relative to its peers\n-        Http2Stream[] children = parent.children().toArray(new Http2Stream[parent.numChildren()]);\n-        int totalWeight = parent.totalChildWeights();\n-        for (int tail = children.length; tail > 0;) {\n-            int head = 0;\n-            int nextTail = 0;\n-            int nextTotalWeight = 0;\n-            int nextConnectionWindow = connectionWindow;\n-            for (; head < tail && nextConnectionWindow > 0; ++head) {\n-                Http2Stream child = children[head];\n-                state = state(child);\n-                int weight = child.weight();\n-                double weightRatio = weight / (double) totalWeight;\n-\n-                // In order to make progress toward the connection window due to possible rounding errors, we make sure\n-                // that each stream (with data to send) is given at least 1 byte toward the connection window.\n-                int connectionWindowChunk = Math.max(1, (int) (connectionWindow * weightRatio));\n-                int bytesForTree = Math.min(nextConnectionWindow, connectionWindowChunk);\n-                int bytesForChild = Math.min(state.streamableBytes(), bytesForTree);\n-\n-                if (bytesForChild > 0) {\n-                    state.allocate(bytesForChild);\n-                    bytesAllocated += bytesForChild;\n-                    nextConnectionWindow -= bytesForChild;\n-                    bytesForTree -= bytesForChild;\n-                    // If this subtree still wants to send then re-insert into children list and re-consider for next\n-                    // iteration. This is needed because we don't yet know if all the peers will be able to use\n-                    // all of their \"fair share\" of the connection window, and if they don't use it then we should\n-                    // divide their unused shared up for the peers who still want to send.\n-                    if (state.streamableBytesForTree() > 0) {\n-                        children[nextTail++] = child;\n-                        nextTotalWeight += weight;\n+\n+            return nextConnectionWindow > 0;\n+        }\n+\n+        void feedHungryChildren() throws Http2Exception {\n+            if (stillHungry == null) {\n+                // There are no hungry children to feed.\n+                return;\n+            }\n+\n+            totalWeight = nextTotalWeight;\n+            connectionWindow = nextConnectionWindow;\n+\n+            // Loop until there are not bytes left to stream or the connection window has collapsed.\n+            for (int tail = nextTail; tail > 0 && connectionWindow > 0;) {\n+                nextTotalWeight = 0;\n+                nextTail = 0;\n+\n+                // Iterate over the children that are currently still hungry.\n+                for (int head = 0; head < tail && nextConnectionWindow > 0; ++head) {\n+                    Http2Stream child = stillHungry[head];\n+                    if (!visit(child)) {\n+                        // The connection window has collapsed, break out of the loop.\n+                        break;\n                     }\n                 }\n+                connectionWindow = nextConnectionWindow;\n+                totalWeight = nextTotalWeight;\n+                tail = nextTail;\n+            }\n+        }\n \n-                if (bytesForTree > 0) {\n-                    int childBytesAllocated = allocateBytesForTree(child, bytesForTree);\n-                    bytesAllocated += childBytesAllocated;\n-                    nextConnectionWindow -= childBytesAllocated;\n-                }\n+        /**\n+         * Indicates that the given child is still hungry (i.e. still has streamable bytes that can\n+         * fit within the current connection window).\n+         */\n+        void stillHungry(Http2Stream child) {\n+            allocateSpace(nextTail);\n+            stillHungry[nextTail++] = child;\n+        }\n+\n+        /**\n+         * Ensures that the {@link #stillHungry} array is properly sized to hold the given index.\n+         */\n+        void allocateSpace(int index) {\n+            if (stillHungry == null) {\n+                // Initial size is 1/4 the number of children.\n+                int minSize = max(index + 1, 4);\n+                int desiredSize = maxSize / 4;\n+                int initialSize = min(max(minSize, desiredSize), maxSize);\n+                stillHungry = new Http2Stream[initialSize];\n+            } else if (index >= stillHungry.length) {","path":"codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2RemoteFlowController.java","position":216,"original_position":216,"commit_id":"14667f6501684153e8b1154ca425a6ea995185f5","original_commit_id":"14667f6501684153e8b1154ca425a6ea995185f5","user":{"login":"Scottmitch","id":7562868,"avatar_url":"https://avatars.githubusercontent.com/u/7562868?v=3","gravatar_id":"","url":"https://api.github.com/users/Scottmitch","html_url":"https://github.com/Scottmitch","followers_url":"https://api.github.com/users/Scottmitch/followers","following_url":"https://api.github.com/users/Scottmitch/following{/other_user}","gists_url":"https://api.github.com/users/Scottmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/Scottmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Scottmitch/subscriptions","organizations_url":"https://api.github.com/users/Scottmitch/orgs","repos_url":"https://api.github.com/users/Scottmitch/repos","events_url":"https://api.github.com/users/Scottmitch/events{/privacy}","received_events_url":"https://api.github.com/users/Scottmitch/received_events","type":"User","site_admin":false},"body":"This conditional may be a bit misleading.  If `nextTail > childArray.length` then the following resize operation may not be sufficient.  For example `nextTail = 20, childArray.length = 4, children.size() = 40`...the array would only be sized to `8` and we would have an array out of bounds....not that this can realistically happen but the point is I think we can check for `nextTail == childArray.length` because that is what this class is really designed for.","created_at":"2015-04-09T22:59:13Z","updated_at":"2015-04-09T22:59:13Z","html_url":"https://github.com/netty/netty/pull/3603#discussion_r28110789","pull_request_url":"https://api.github.com/repos/netty/netty/pulls/3603","_links":{"self":{"href":"https://api.github.com/repos/netty/netty/pulls/comments/28110789"},"html":{"href":"https://github.com/netty/netty/pull/3603#discussion_r28110789"},"pull_request":{"href":"https://api.github.com/repos/netty/netty/pulls/3603"}}},"pull_request":{"url":"https://api.github.com/repos/netty/netty/pulls/3603","id":32975041,"html_url":"https://github.com/netty/netty/pull/3603","diff_url":"https://github.com/netty/netty/pull/3603.diff","patch_url":"https://github.com/netty/netty/pull/3603.patch","issue_url":"https://api.github.com/repos/netty/netty/issues/3603","number":3603,"state":"open","locked":false,"title":"Removing direct access to HTTP/2 child streams.","user":{"login":"nmittler","id":6493296,"avatar_url":"https://avatars.githubusercontent.com/u/6493296?v=3","gravatar_id":"","url":"https://api.github.com/users/nmittler","html_url":"https://github.com/nmittler","followers_url":"https://api.github.com/users/nmittler/followers","following_url":"https://api.github.com/users/nmittler/following{/other_user}","gists_url":"https://api.github.com/users/nmittler/gists{/gist_id}","starred_url":"https://api.github.com/users/nmittler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmittler/subscriptions","organizations_url":"https://api.github.com/users/nmittler/orgs","repos_url":"https://api.github.com/users/nmittler/repos","events_url":"https://api.github.com/users/nmittler/events{/privacy}","received_events_url":"https://api.github.com/users/nmittler/received_events","type":"User","site_admin":false},"body":"Motivation:\r\n\r\nWe've removed access to the activeStreams collection, we should do the same for the children of a stream to provide a consistent interface.\r\n\r\nModifications:\r\n\r\nMoved Http2StreamVisitor to a top-level interface. Removed unnecessary child operations from the Http2Stream interface so that we no longer require a map structure.\r\n\r\nResult:\r\n\r\nCleaner and more consistent interface for iterating over child streams.","created_at":"2015-04-09T16:59:12Z","updated_at":"2015-04-09T22:59:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"751ddd4004d76c810f62e6074dab13eb07bfea36","assignee":{"login":"nmittler","id":6493296,"avatar_url":"https://avatars.githubusercontent.com/u/6493296?v=3","gravatar_id":"","url":"https://api.github.com/users/nmittler","html_url":"https://github.com/nmittler","followers_url":"https://api.github.com/users/nmittler/followers","following_url":"https://api.github.com/users/nmittler/following{/other_user}","gists_url":"https://api.github.com/users/nmittler/gists{/gist_id}","starred_url":"https://api.github.com/users/nmittler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmittler/subscriptions","organizations_url":"https://api.github.com/users/nmittler/orgs","repos_url":"https://api.github.com/users/nmittler/repos","events_url":"https://api.github.com/users/nmittler/events{/privacy}","received_events_url":"https://api.github.com/users/nmittler/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/netty/netty/milestones/112","html_url":"https://github.com/netty/netty/milestones/4.1.0.Beta5","labels_url":"https://api.github.com/repos/netty/netty/milestones/112/labels","id":1005380,"number":112,"title":"4.1.0.Beta5","description":"","creator":{"login":"normanmaurer","id":439362,"avatar_url":"https://avatars.githubusercontent.com/u/439362?v=3","gravatar_id":"","url":"https://api.github.com/users/normanmaurer","html_url":"https://github.com/normanmaurer","followers_url":"https://api.github.com/users/normanmaurer/followers","following_url":"https://api.github.com/users/normanmaurer/following{/other_user}","gists_url":"https://api.github.com/users/normanmaurer/gists{/gist_id}","starred_url":"https://api.github.com/users/normanmaurer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/normanmaurer/subscriptions","organizations_url":"https://api.github.com/users/normanmaurer/orgs","repos_url":"https://api.github.com/users/normanmaurer/repos","events_url":"https://api.github.com/users/normanmaurer/events{/privacy}","received_events_url":"https://api.github.com/users/normanmaurer/received_events","type":"User","site_admin":false},"open_issues":69,"closed_issues":54,"state":"open","created_at":"2015-03-04T09:22:23Z","updated_at":"2015-04-09T22:39:38Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/netty/netty/pulls/3603/commits","review_comments_url":"https://api.github.com/repos/netty/netty/pulls/3603/comments","review_comment_url":"https://api.github.com/repos/netty/netty/pulls/comments{/number}","comments_url":"https://api.github.com/repos/netty/netty/issues/3603/comments","statuses_url":"https://api.github.com/repos/netty/netty/statuses/14667f6501684153e8b1154ca425a6ea995185f5","head":{"label":"nmittler:foreachchild","ref":"foreachchild","sha":"14667f6501684153e8b1154ca425a6ea995185f5","user":{"login":"nmittler","id":6493296,"avatar_url":"https://avatars.githubusercontent.com/u/6493296?v=3","gravatar_id":"","url":"https://api.github.com/users/nmittler","html_url":"https://github.com/nmittler","followers_url":"https://api.github.com/users/nmittler/followers","following_url":"https://api.github.com/users/nmittler/following{/other_user}","gists_url":"https://api.github.com/users/nmittler/gists{/gist_id}","starred_url":"https://api.github.com/users/nmittler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmittler/subscriptions","organizations_url":"https://api.github.com/users/nmittler/orgs","repos_url":"https://api.github.com/users/nmittler/repos","events_url":"https://api.github.com/users/nmittler/events{/privacy}","received_events_url":"https://api.github.com/users/nmittler/received_events","type":"User","site_admin":false},"repo":{"id":18468502,"name":"netty","full_name":"nmittler/netty","owner":{"login":"nmittler","id":6493296,"avatar_url":"https://avatars.githubusercontent.com/u/6493296?v=3","gravatar_id":"","url":"https://api.github.com/users/nmittler","html_url":"https://github.com/nmittler","followers_url":"https://api.github.com/users/nmittler/followers","following_url":"https://api.github.com/users/nmittler/following{/other_user}","gists_url":"https://api.github.com/users/nmittler/gists{/gist_id}","starred_url":"https://api.github.com/users/nmittler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmittler/subscriptions","organizations_url":"https://api.github.com/users/nmittler/orgs","repos_url":"https://api.github.com/users/nmittler/repos","events_url":"https://api.github.com/users/nmittler/events{/privacy}","received_events_url":"https://api.github.com/users/nmittler/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nmittler/netty","description":"Netty project - an event-driven asynchronous network application framework","fork":true,"url":"https://api.github.com/repos/nmittler/netty","forks_url":"https://api.github.com/repos/nmittler/netty/forks","keys_url":"https://api.github.com/repos/nmittler/netty/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nmittler/netty/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nmittler/netty/teams","hooks_url":"https://api.github.com/repos/nmittler/netty/hooks","issue_events_url":"https://api.github.com/repos/nmittler/netty/issues/events{/number}","events_url":"https://api.github.com/repos/nmittler/netty/events","assignees_url":"https://api.github.com/repos/nmittler/netty/assignees{/user}","branches_url":"https://api.github.com/repos/nmittler/netty/branches{/branch}","tags_url":"https://api.github.com/repos/nmittler/netty/tags","blobs_url":"https://api.github.com/repos/nmittler/netty/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nmittler/netty/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nmittler/netty/git/refs{/sha}","trees_url":"https://api.github.com/repos/nmittler/netty/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nmittler/netty/statuses/{sha}","languages_url":"https://api.github.com/repos/nmittler/netty/languages","stargazers_url":"https://api.github.com/repos/nmittler/netty/stargazers","contributors_url":"https://api.github.com/repos/nmittler/netty/contributors","subscribers_url":"https://api.github.com/repos/nmittler/netty/subscribers","subscription_url":"https://api.github.com/repos/nmittler/netty/subscription","commits_url":"https://api.github.com/repos/nmittler/netty/commits{/sha}","git_commits_url":"https://api.github.com/repos/nmittler/netty/git/commits{/sha}","comments_url":"https://api.github.com/repos/nmittler/netty/comments{/number}","issue_comment_url":"https://api.github.com/repos/nmittler/netty/issues/comments{/number}","contents_url":"https://api.github.com/repos/nmittler/netty/contents/{+path}","compare_url":"https://api.github.com/repos/nmittler/netty/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nmittler/netty/merges","archive_url":"https://api.github.com/repos/nmittler/netty/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nmittler/netty/downloads","issues_url":"https://api.github.com/repos/nmittler/netty/issues{/number}","pulls_url":"https://api.github.com/repos/nmittler/netty/pulls{/number}","milestones_url":"https://api.github.com/repos/nmittler/netty/milestones{/number}","notifications_url":"https://api.github.com/repos/nmittler/netty/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nmittler/netty/labels{/name}","releases_url":"https://api.github.com/repos/nmittler/netty/releases{/id}","created_at":"2014-04-05T14:33:03Z","updated_at":"2015-02-02T15:50:48Z","pushed_at":"2015-04-09T22:38:53Z","git_url":"git://github.com/nmittler/netty.git","ssh_url":"git@github.com:nmittler/netty.git","clone_url":"https://github.com/nmittler/netty.git","svn_url":"https://github.com/nmittler/netty","homepage":"http://netty.io/","size":37430,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"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":"netty:master","ref":"master","sha":"30b711cf3d34cd3d2278f21f76ea8a199de0283a","user":{"login":"netty","id":473791,"avatar_url":"https://avatars.githubusercontent.com/u/473791?v=3","gravatar_id":"","url":"https://api.github.com/users/netty","html_url":"https://github.com/netty","followers_url":"https://api.github.com/users/netty/followers","following_url":"https://api.github.com/users/netty/following{/other_user}","gists_url":"https://api.github.com/users/netty/gists{/gist_id}","starred_url":"https://api.github.com/users/netty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/netty/subscriptions","organizations_url":"https://api.github.com/users/netty/orgs","repos_url":"https://api.github.com/users/netty/repos","events_url":"https://api.github.com/users/netty/events{/privacy}","received_events_url":"https://api.github.com/users/netty/received_events","type":"Organization","site_admin":false},"repo":{"id":1064563,"name":"netty","full_name":"netty/netty","owner":{"login":"netty","id":473791,"avatar_url":"https://avatars.githubusercontent.com/u/473791?v=3","gravatar_id":"","url":"https://api.github.com/users/netty","html_url":"https://github.com/netty","followers_url":"https://api.github.com/users/netty/followers","following_url":"https://api.github.com/users/netty/following{/other_user}","gists_url":"https://api.github.com/users/netty/gists{/gist_id}","starred_url":"https://api.github.com/users/netty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/netty/subscriptions","organizations_url":"https://api.github.com/users/netty/orgs","repos_url":"https://api.github.com/users/netty/repos","events_url":"https://api.github.com/users/netty/events{/privacy}","received_events_url":"https://api.github.com/users/netty/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/netty/netty","description":"Netty project - an event-driven asynchronous network application framework","fork":false,"url":"https://api.github.com/repos/netty/netty","forks_url":"https://api.github.com/repos/netty/netty/forks","keys_url":"https://api.github.com/repos/netty/netty/keys{/key_id}","collaborators_url":"https://api.github.com/repos/netty/netty/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/netty/netty/teams","hooks_url":"https://api.github.com/repos/netty/netty/hooks","issue_events_url":"https://api.github.com/repos/netty/netty/issues/events{/number}","events_url":"https://api.github.com/repos/netty/netty/events","assignees_url":"https://api.github.com/repos/netty/netty/assignees{/user}","branches_url":"https://api.github.com/repos/netty/netty/branches{/branch}","tags_url":"https://api.github.com/repos/netty/netty/tags","blobs_url":"https://api.github.com/repos/netty/netty/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/netty/netty/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/netty/netty/git/refs{/sha}","trees_url":"https://api.github.com/repos/netty/netty/git/trees{/sha}","statuses_url":"https://api.github.com/repos/netty/netty/statuses/{sha}","languages_url":"https://api.github.com/repos/netty/netty/languages","stargazers_url":"https://api.github.com/repos/netty/netty/stargazers","contributors_url":"https://api.github.com/repos/netty/netty/contributors","subscribers_url":"https://api.github.com/repos/netty/netty/subscribers","subscription_url":"https://api.github.com/repos/netty/netty/subscription","commits_url":"https://api.github.com/repos/netty/netty/commits{/sha}","git_commits_url":"https://api.github.com/repos/netty/netty/git/commits{/sha}","comments_url":"https://api.github.com/repos/netty/netty/comments{/number}","issue_comment_url":"https://api.github.com/repos/netty/netty/issues/comments{/number}","contents_url":"https://api.github.com/repos/netty/netty/contents/{+path}","compare_url":"https://api.github.com/repos/netty/netty/compare/{base}...{head}","merges_url":"https://api.github.com/repos/netty/netty/merges","archive_url":"https://api.github.com/repos/netty/netty/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/netty/netty/downloads","issues_url":"https://api.github.com/repos/netty/netty/issues{/number}","pulls_url":"https://api.github.com/repos/netty/netty/pulls{/number}","milestones_url":"https://api.github.com/repos/netty/netty/milestones{/number}","notifications_url":"https://api.github.com/repos/netty/netty/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/netty/netty/labels{/name}","releases_url":"https://api.github.com/repos/netty/netty/releases{/id}","created_at":"2010-11-09T09:22:21Z","updated_at":"2015-04-09T16:56:03Z","pushed_at":"2015-04-09T22:38:56Z","git_url":"git://github.com/netty/netty.git","ssh_url":"git@github.com:netty/netty.git","clone_url":"https://github.com/netty/netty.git","svn_url":"https://github.com/netty/netty","homepage":"http://netty.io/","size":114247,"stargazers_count":4393,"watchers_count":4393,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2160,"mirror_url":null,"open_issues_count":250,"forks":2160,"open_issues":250,"watchers":4393,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/netty/netty/pulls/3603"},"html":{"href":"https://github.com/netty/netty/pull/3603"},"issue":{"href":"https://api.github.com/repos/netty/netty/issues/3603"},"comments":{"href":"https://api.github.com/repos/netty/netty/issues/3603/comments"},"review_comments":{"href":"https://api.github.com/repos/netty/netty/pulls/3603/comments"},"review_comment":{"href":"https://api.github.com/repos/netty/netty/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/netty/netty/pulls/3603/commits"},"statuses":{"href":"https://api.github.com/repos/netty/netty/statuses/14667f6501684153e8b1154ca425a6ea995185f5"}}}}