{"action":"created","comment":{"url":"https://api.github.com/repos/apache/zookeeper/pulls/comments/127135485","pull_request_review_id":49687036,"id":127135485,"diff_hunk":"@@ -0,0 +1,219 @@\n+/**\n+ * Licensed to the Apache Software Foundation (ASF) under one\n+ * or more contributor license agreements.  See the NOTICE file\n+ * distributed with this work for additional information\n+ * regarding copyright ownership.  The ASF licenses this file\n+ * to you under the Apache License, Version 2.0 (the\n+ * \"License\"); you may not use this file except in compliance\n+ * with the License.  You may obtain a copy of 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,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package org.apache.zookeeper.server.quorum;\n+\n+import static org.apache.zookeeper.test.ClientBase.CONNECTION_TIMEOUT;\n+import static org.junit.Assert.assertNotNull;\n+import static org.junit.Assert.assertNull;\n+\n+import java.io.IOException;\n+import java.net.SocketTimeoutException;\n+\n+import org.apache.zookeeper.CreateMode;\n+import org.apache.zookeeper.PortAssignment;\n+import org.apache.zookeeper.ZooDefs.Ids;\n+import org.apache.zookeeper.ZooKeeper;\n+import org.apache.zookeeper.data.Stat;\n+import org.apache.zookeeper.server.persistence.FileTxnSnapLog;\n+import org.apache.zookeeper.server.quorum.QuorumPeer.ServerState;\n+import org.apache.zookeeper.test.ClientBase;\n+import org.apache.zookeeper.test.ClientBase.CountdownWatcher;\n+import org.junit.After;\n+import org.junit.Assert;\n+import org.junit.Test;\n+\n+import javax.security.sasl.SaslException;\n+\n+public class EphemeralNodeDeletionTest extends QuorumPeerTestBase {\n+    private static int SERVER_COUNT = 3;\n+    private MainThread[] mt = new MainThread[SERVER_COUNT];\n+\n+    /**\n+     * Test case for https://issues.apache.org/jira/browse/ZOOKEEPER-2355.\n+     * ZooKeeper ephemeral node is never deleted if follower fail while reading\n+     * the proposal packet.\n+     */\n+\n+    @Test(timeout = 120000)\n+    public void testEphemeralNodeDeletion() throws Exception {\n+        final int clientPorts[] = new int[SERVER_COUNT];\n+        StringBuilder sb = new StringBuilder();\n+        String server;\n+\n+        for (int i = 0; i < SERVER_COUNT; i++) {\n+            clientPorts[i] = PortAssignment.unique();\n+            server = \"server.\" + i + \"=127.0.0.1:\" + PortAssignment.unique()\n+                    + \":\" + PortAssignment.unique();\n+            sb.append(server + \"\\n\");\n+        }\n+        String currentQuorumCfgSection = sb.toString();\n+        System.out.println(currentQuorumCfgSection);\n+        // start all the servers\n+        for (int i = 0; i < SERVER_COUNT; i++) {\n+            mt[i] = new MainThread(i, clientPorts[i], currentQuorumCfgSection) {\n+                @Override\n+                public TestQPMain getTestQPMain() {\n+                    return new MockTestQPMain();\n+                }\n+            };\n+            mt[i].start();\n+        }\n+\n+        // ensure all servers started\n+        for (int i = 0; i < SERVER_COUNT; i++) {\n+            Assert.assertTrue(\"waiting for server \" + i + \" being up\",\n+                    ClientBase.waitForServerUp(\"127.0.0.1:\" + clientPorts[i],\n+                            CONNECTION_TIMEOUT));\n+        }\n+\n+        CountdownWatcher watch = new CountdownWatcher();\n+        ZooKeeper zk = new ZooKeeper(\"127.0.0.1:\" + clientPorts[1],\n+                ClientBase.CONNECTION_TIMEOUT, watch);\n+        watch.waitForConnected(ClientBase.CONNECTION_TIMEOUT);\n+\n+        /**\n+         * now the problem scenario starts\n+         */\n+\n+        // 1: create ephemeral node\n+        String nodePath = \"/e1\";\n+        zk.create(nodePath, \"1\".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);\n+\n+        // 2: inject network problem in one of the follower\n+        CustomQuorumPeer follower = (CustomQuorumPeer) getByServerState(mt,\n+                ServerState.FOLLOWING);\n+        follower.setInjectError(true);\n+\n+        // 3: close the session so that ephemeral node is deleted\n+        zk.close();\n+\n+        // remove the error\n+        follower.setInjectError(false);\n+\n+        Assert.assertTrue(\"Faulted Follower should have joined quorum by now\",\n+                ClientBase.waitForServerUp(\n+                        \"127.0.0.1:\" + follower.getClientPort(),\n+                        CONNECTION_TIMEOUT));\n+\n+        QuorumPeer leader = getByServerState(mt, ServerState.LEADING);\n+        assertNotNull(\"Leader should not be null\", leader);\n+        Assert.assertTrue(\"Leader must be running\", ClientBase.waitForServerUp(\n+                \"127.0.0.1:\" + leader.getClientPort(), CONNECTION_TIMEOUT));\n+\n+        watch = new CountdownWatcher();\n+        zk = new ZooKeeper(\"127.0.0.1:\" + leader.getClientPort(),\n+                ClientBase.CONNECTION_TIMEOUT, watch);\n+        watch.waitForConnected(ClientBase.CONNECTION_TIMEOUT);\n+\n+        Stat exists = zk.exists(nodePath, false);\n+        assertNull(\"Node must have been deleted from leader\", exists);\n+\n+        CountdownWatcher followerWatch = new CountdownWatcher();\n+        ZooKeeper followerZK = new ZooKeeper(\n+                \"127.0.0.1:\" + follower.getClientPort(),\n+                ClientBase.CONNECTION_TIMEOUT, followerWatch);\n+        followerWatch.waitForConnected(ClientBase.CONNECTION_TIMEOUT);\n+        Stat nodeAtFollower = followerZK.exists(nodePath, false);\n+\n+        // Problem 1: Follower had one extra ephemeral node /e1\n+        assertNull(\"ephemeral node must not exist\", nodeAtFollower);\n+\n+        // Create the node with another session\n+        zk.create(nodePath, \"2\".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);\n+\n+        // close the session and newly created ephemeral node should be deleted\n+        zk.close();\n+\n+        nodeAtFollower = followerZK.exists(nodePath, false);\n+\n+        // Problem 2: Before fix, after session close the ephemeral node\n+        // was not getting deleted. But now after the fix after session close\n+        // ephemeral node is getting deleted.\n+        assertNull(\"After session close ephemeral node must be deleted\",\n+                nodeAtFollower);\n+        followerZK.close();\n+    }\n+\n+    @After\n+    public void tearDown() {\n+        // stop all severs\n+        for (int i = 0; i < mt.length; i++) {\n+            try {\n+                mt[i].shutdown();\n+            } catch (InterruptedException e) {\n+                LOG.warn(\"Quorum Peer interrupted while shutting it down\", e);\n+            }\n+        }\n+    }\n+\n+    private QuorumPeer getByServerState(MainThread[] mt, ServerState state) {\n+        for (int i = mt.length - 1; i >= 0; i--) {\n+            QuorumPeer quorumPeer = mt[i].getQuorumPeer();\n+            if (null != quorumPeer && state == quorumPeer.getPeerState()) {\n+                return quorumPeer;\n+            }\n+        }\n+        return null;\n+    }\n+\n+    static class CustomQuorumPeer extends QuorumPeer  {\n+        private boolean injectError = false;\n+\n+        public CustomQuorumPeer() throws SaslException {\n+        }\n+\n+        @Override\n+        protected Follower makeFollower(FileTxnSnapLog logFactory)\n+                throws IOException {\n+            return new Follower(this, new FollowerZooKeeperServer(logFactory,\n+                    this, null /*DataTreeBuilder is never used*/,\n+                    this.getZkDb())) {\n+\n+                @Override\n+                void readPacket(QuorumPacket pp) throws IOException {\n+                    /**\n+                     * In real scenario got SocketTimeoutException while reading\n+                     * the packet from leader because of network problem, but\n+                     * here throwing SocketTimeoutException based on whether\n+                     * error is injected or not\n+                     */\n+                    super.readPacket(pp);\n+                    if (injectError && pp.getType() == Leader.PROPOSAL) {\n+                        String type = LearnerHandler.packetToString(pp);\n+                        throw new SocketTimeoutException(\n+                                \"Socket timeout while reading the packet for operation \"\n+                                        + type);\n+                    }\n+                }\n+\n+            };\n+        }\n+\n+        public void setInjectError(boolean injectError) {\n+            this.injectError = injectError;\n+        }\n+\n+    }\n+\n+    static class MockTestQPMain extends TestQPMain {\n+        @Override\n+        protected QuorumPeer getQuorumPeer() throws SaslException {\n+            return new CustomQuorumPeer();\n+        }\n+    }\n+}","path":"src/java/test/org/apache/zookeeper/server/quorum/EphemeralNodeDeletionTest.java","position":219,"original_position":219,"commit_id":"007e2b37f24907c03e4e28547756b91aea4f78d4","original_commit_id":"007e2b37f24907c03e4e28547756b91aea4f78d4","user":{"login":"asdf2014","id":8108788,"avatar_url":"https://avatars0.githubusercontent.com/u/8108788?v=3","gravatar_id":"","url":"https://api.github.com/users/asdf2014","html_url":"https://github.com/asdf2014","followers_url":"https://api.github.com/users/asdf2014/followers","following_url":"https://api.github.com/users/asdf2014/following{/other_user}","gists_url":"https://api.github.com/users/asdf2014/gists{/gist_id}","starred_url":"https://api.github.com/users/asdf2014/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asdf2014/subscriptions","organizations_url":"https://api.github.com/users/asdf2014/orgs","repos_url":"https://api.github.com/users/asdf2014/repos","events_url":"https://api.github.com/users/asdf2014/events{/privacy}","received_events_url":"https://api.github.com/users/asdf2014/received_events","type":"User","site_admin":false},"body":"Thanks a lot! It will be a huge job. Look forward to!","created_at":"2017-07-13T06:14:14Z","updated_at":"2017-07-13T06:14:14Z","html_url":"https://github.com/apache/zookeeper/pull/304#discussion_r127135485","pull_request_url":"https://api.github.com/repos/apache/zookeeper/pulls/304","_links":{"self":{"href":"https://api.github.com/repos/apache/zookeeper/pulls/comments/127135485"},"html":{"href":"https://github.com/apache/zookeeper/pull/304#discussion_r127135485"},"pull_request":{"href":"https://api.github.com/repos/apache/zookeeper/pulls/304"}}},"pull_request":{"url":"https://api.github.com/repos/apache/zookeeper/pulls/304","id":129089828,"html_url":"https://github.com/apache/zookeeper/pull/304","diff_url":"https://github.com/apache/zookeeper/pull/304.diff","patch_url":"https://github.com/apache/zookeeper/pull/304.patch","issue_url":"https://api.github.com/repos/apache/zookeeper/issues/304","number":304,"state":"open","locked":false,"title":"ZOOKEEPER-2355: Ephemeral node is never deleted if follower fails while reading the proposal packet.","user":{"login":"hanm","id":1009243,"avatar_url":"https://avatars0.githubusercontent.com/u/1009243?v=3","gravatar_id":"","url":"https://api.github.com/users/hanm","html_url":"https://github.com/hanm","followers_url":"https://api.github.com/users/hanm/followers","following_url":"https://api.github.com/users/hanm/following{/other_user}","gists_url":"https://api.github.com/users/hanm/gists{/gist_id}","starred_url":"https://api.github.com/users/hanm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanm/subscriptions","organizations_url":"https://api.github.com/users/hanm/orgs","repos_url":"https://api.github.com/users/hanm/repos","events_url":"https://api.github.com/users/hanm/events{/privacy}","received_events_url":"https://api.github.com/users/hanm/received_events","type":"User","site_admin":false},"body":"This commit is a port of the commit ca22b3db19371f6b0f5507b7dd80b283cddc7700 from branch-3.5 to branch-3.4. Changes include a few interfaces that required by the test case. The test case itself is also updated so it works with 3.4 code base.\r\n\r\n@arshadmohammad @rakeshadr Could you please review this to close the loop of ZOOKEEPER-2355?","created_at":"2017-07-06T02:05:41Z","updated_at":"2017-07-13T06:14:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"fb569a939552eba68da7dd883873f16e89140fc9","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/apache/zookeeper/pulls/304/commits","review_comments_url":"https://api.github.com/repos/apache/zookeeper/pulls/304/comments","review_comment_url":"https://api.github.com/repos/apache/zookeeper/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/zookeeper/issues/304/comments","statuses_url":"https://api.github.com/repos/apache/zookeeper/statuses/007e2b37f24907c03e4e28547756b91aea4f78d4","head":{"label":"hanm:ZOOKEEPER-2355","ref":"ZOOKEEPER-2355","sha":"007e2b37f24907c03e4e28547756b91aea4f78d4","user":{"login":"hanm","id":1009243,"avatar_url":"https://avatars0.githubusercontent.com/u/1009243?v=3","gravatar_id":"","url":"https://api.github.com/users/hanm","html_url":"https://github.com/hanm","followers_url":"https://api.github.com/users/hanm/followers","following_url":"https://api.github.com/users/hanm/following{/other_user}","gists_url":"https://api.github.com/users/hanm/gists{/gist_id}","starred_url":"https://api.github.com/users/hanm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanm/subscriptions","organizations_url":"https://api.github.com/users/hanm/orgs","repos_url":"https://api.github.com/users/hanm/repos","events_url":"https://api.github.com/users/hanm/events{/privacy}","received_events_url":"https://api.github.com/users/hanm/received_events","type":"User","site_admin":false},"repo":{"id":52680929,"name":"zookeeper","full_name":"hanm/zookeeper","owner":{"login":"hanm","id":1009243,"avatar_url":"https://avatars0.githubusercontent.com/u/1009243?v=3","gravatar_id":"","url":"https://api.github.com/users/hanm","html_url":"https://github.com/hanm","followers_url":"https://api.github.com/users/hanm/followers","following_url":"https://api.github.com/users/hanm/following{/other_user}","gists_url":"https://api.github.com/users/hanm/gists{/gist_id}","starred_url":"https://api.github.com/users/hanm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanm/subscriptions","organizations_url":"https://api.github.com/users/hanm/orgs","repos_url":"https://api.github.com/users/hanm/repos","events_url":"https://api.github.com/users/hanm/events{/privacy}","received_events_url":"https://api.github.com/users/hanm/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/hanm/zookeeper","description":"Mirror of Apache Hadoop ZooKeeper","fork":true,"url":"https://api.github.com/repos/hanm/zookeeper","forks_url":"https://api.github.com/repos/hanm/zookeeper/forks","keys_url":"https://api.github.com/repos/hanm/zookeeper/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hanm/zookeeper/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hanm/zookeeper/teams","hooks_url":"https://api.github.com/repos/hanm/zookeeper/hooks","issue_events_url":"https://api.github.com/repos/hanm/zookeeper/issues/events{/number}","events_url":"https://api.github.com/repos/hanm/zookeeper/events","assignees_url":"https://api.github.com/repos/hanm/zookeeper/assignees{/user}","branches_url":"https://api.github.com/repos/hanm/zookeeper/branches{/branch}","tags_url":"https://api.github.com/repos/hanm/zookeeper/tags","blobs_url":"https://api.github.com/repos/hanm/zookeeper/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hanm/zookeeper/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hanm/zookeeper/git/refs{/sha}","trees_url":"https://api.github.com/repos/hanm/zookeeper/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hanm/zookeeper/statuses/{sha}","languages_url":"https://api.github.com/repos/hanm/zookeeper/languages","stargazers_url":"https://api.github.com/repos/hanm/zookeeper/stargazers","contributors_url":"https://api.github.com/repos/hanm/zookeeper/contributors","subscribers_url":"https://api.github.com/repos/hanm/zookeeper/subscribers","subscription_url":"https://api.github.com/repos/hanm/zookeeper/subscription","commits_url":"https://api.github.com/repos/hanm/zookeeper/commits{/sha}","git_commits_url":"https://api.github.com/repos/hanm/zookeeper/git/commits{/sha}","comments_url":"https://api.github.com/repos/hanm/zookeeper/comments{/number}","issue_comment_url":"https://api.github.com/repos/hanm/zookeeper/issues/comments{/number}","contents_url":"https://api.github.com/repos/hanm/zookeeper/contents/{+path}","compare_url":"https://api.github.com/repos/hanm/zookeeper/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hanm/zookeeper/merges","archive_url":"https://api.github.com/repos/hanm/zookeeper/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hanm/zookeeper/downloads","issues_url":"https://api.github.com/repos/hanm/zookeeper/issues{/number}","pulls_url":"https://api.github.com/repos/hanm/zookeeper/pulls{/number}","milestones_url":"https://api.github.com/repos/hanm/zookeeper/milestones{/number}","notifications_url":"https://api.github.com/repos/hanm/zookeeper/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hanm/zookeeper/labels{/name}","releases_url":"https://api.github.com/repos/hanm/zookeeper/releases{/id}","deployments_url":"https://api.github.com/repos/hanm/zookeeper/deployments","created_at":"2016-02-27T18:03:05Z","updated_at":"2016-11-29T17:39:57Z","pushed_at":"2017-07-13T03:14:49Z","git_url":"git://github.com/hanm/zookeeper.git","ssh_url":"git@github.com:hanm/zookeeper.git","clone_url":"https://github.com/hanm/zookeeper.git","svn_url":"https://github.com/hanm/zookeeper","homepage":null,"size":29505,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"apache:branch-3.4","ref":"branch-3.4","sha":"4eab48f4970d2a98594c95add6106780e5b2ea6f","user":{"login":"apache","id":47359,"avatar_url":"https://avatars3.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":160999,"name":"zookeeper","full_name":"apache/zookeeper","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars3.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/zookeeper","description":"Mirror of Apache Hadoop ZooKeeper","fork":false,"url":"https://api.github.com/repos/apache/zookeeper","forks_url":"https://api.github.com/repos/apache/zookeeper/forks","keys_url":"https://api.github.com/repos/apache/zookeeper/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/zookeeper/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/zookeeper/teams","hooks_url":"https://api.github.com/repos/apache/zookeeper/hooks","issue_events_url":"https://api.github.com/repos/apache/zookeeper/issues/events{/number}","events_url":"https://api.github.com/repos/apache/zookeeper/events","assignees_url":"https://api.github.com/repos/apache/zookeeper/assignees{/user}","branches_url":"https://api.github.com/repos/apache/zookeeper/branches{/branch}","tags_url":"https://api.github.com/repos/apache/zookeeper/tags","blobs_url":"https://api.github.com/repos/apache/zookeeper/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/zookeeper/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/zookeeper/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/zookeeper/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/zookeeper/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/zookeeper/languages","stargazers_url":"https://api.github.com/repos/apache/zookeeper/stargazers","contributors_url":"https://api.github.com/repos/apache/zookeeper/contributors","subscribers_url":"https://api.github.com/repos/apache/zookeeper/subscribers","subscription_url":"https://api.github.com/repos/apache/zookeeper/subscription","commits_url":"https://api.github.com/repos/apache/zookeeper/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/zookeeper/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/zookeeper/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/zookeeper/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/zookeeper/contents/{+path}","compare_url":"https://api.github.com/repos/apache/zookeeper/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/zookeeper/merges","archive_url":"https://api.github.com/repos/apache/zookeeper/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/zookeeper/downloads","issues_url":"https://api.github.com/repos/apache/zookeeper/issues{/number}","pulls_url":"https://api.github.com/repos/apache/zookeeper/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/zookeeper/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/zookeeper/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/zookeeper/labels{/name}","releases_url":"https://api.github.com/repos/apache/zookeeper/releases{/id}","deployments_url":"https://api.github.com/repos/apache/zookeeper/deployments","created_at":"2009-03-27T15:41:56Z","updated_at":"2017-07-13T03:51:01Z","pushed_at":"2017-07-13T03:14:50Z","git_url":"git://github.com/apache/zookeeper.git","ssh_url":"git@github.com:apache/zookeeper.git","clone_url":"https://github.com/apache/zookeeper.git","svn_url":"https://github.com/apache/zookeeper","homepage":null,"size":28695,"stargazers_count":3105,"watchers_count":3105,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2264,"mirror_url":"git://git.apache.org/zookeeper.git","open_issues_count":106,"forks":2264,"open_issues":106,"watchers":3105,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/zookeeper/pulls/304"},"html":{"href":"https://github.com/apache/zookeeper/pull/304"},"issue":{"href":"https://api.github.com/repos/apache/zookeeper/issues/304"},"comments":{"href":"https://api.github.com/repos/apache/zookeeper/issues/304/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/zookeeper/pulls/304/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/zookeeper/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/zookeeper/pulls/304/commits"},"statuses":{"href":"https://api.github.com/repos/apache/zookeeper/statuses/007e2b37f24907c03e4e28547756b91aea4f78d4"}}}}
{"actor":{"display_login":"asdf2014"}}