{"action":"created","comment":{"url":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments/78404010","id":78404010,"diff_hunk":"@@ -0,0 +1,390 @@\n+package org.broadinstitute.hellbender.utils.nio;\n+\n+import com.google.common.base.Stopwatch;\n+\n+import java.io.Closeable;\n+import java.io.IOException;\n+import java.nio.ByteBuffer;\n+import java.nio.channels.ClosedChannelException;\n+import java.nio.channels.NonWritableChannelException;\n+import java.nio.channels.SeekableByteChannel;\n+import java.nio.file.StandardOpenOption;\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.concurrent.Callable;\n+import java.util.concurrent.ExecutionException;\n+import java.util.concurrent.ExecutorService;\n+import java.util.concurrent.Executors;\n+import java.util.concurrent.Future;\n+import java.util.concurrent.TimeUnit;\n+\n+/**\n+ * SeekableByteChannelPrefetcher wraps an existing SeekableByteChannel to add prefetching.\n+ * The prefetching is done on a different thread, so you can write simple code that repeatedly\n+ * calls read() to get data, processes it, and then calls read again -- and yet this\n+ * simple code overlaps computation and communication for you.\n+ * (Of course this is only worthwhile if the underlying SeekableByteChannel doesn't already\n+ * implement prefetching).\n+ */\n+public final class SeekableByteChannelPrefetcher implements SeekableByteChannel {\n+\n+    final SeekableByteChannel chan;\n+    final int bufSize;\n+    final ExecutorService exec;\n+    final long size;\n+    List<WorkUnit> full = new ArrayList<>();\n+    WorkUnit fetching = null;\n+    // total number of buffers\n+    final int BUF_COUNT = 2;\n+    // where we pretend to be, wrt returning bytes from read()\n+    long position = 0;\n+    boolean open;\n+    Stopwatch betweenCallsToRead = Stopwatch.createUnstarted();\n+\n+    // statistics, for profiling\n+    // time spent blocking the user because we're waiting on the network\n+    public long msWaitingForData = 0;\n+    // time spent blocking the user because we're copying bytes\n+    public long msCopyingData = 0;\n+    // total number of bytes returned by read (if the user asks for the same bytes multiple times, they count)\n+    public long bytesReturned = 0;\n+    // total number of bytes read over the network (whether returned to the user or not)\n+    public long bytesRead = 0;\n+    // time spend in between calls to Read, ie. presumably while the user is processing the data we returned.\n+    public long msBetweenCallsToRead = 0;\n+    // number of times we had the user's data already ready, didn't have to grab it from the net.\n+    public long nbHit = 0;\n+    // number of times we had already started to prefetch the user's data (but it hadn't arrived yet).\n+    public long nbNearHit = 0;\n+    // number of times we don't have what the user's asking for, we have to wait for a prefetch to finish,\n+    // and the prefetch didn't return what the user wanted (either they are going backward, or jumping forward)\n+    public long nbMiss = 0;\n+    // number of times the user asks for data with a lower index than what we already have\n+    // (so they're not following the expected pattern of increasing indexes)\n+    public long nbGoingBack = 0;\n+\n+    /**\n+     * WorkUnit holds a buffer and the instructions for what to put in it.\n+     *\n+     * <p>Use it like this:\n+     * <ol>\n+     *   <li> call()\n+     *   <li> the data is now in buf, you can access it directly\n+     *   <li> if need more, call resetForIndex(...) and go back to the top.\n+     *   <li> else, call close()\n+     * </ol>\n+     */\n+    private static class WorkUnit implements Callable<ByteBuffer>, Closeable {\n+        public final ByteBuffer buf;\n+        public long blockIndex;\n+        final SeekableByteChannel chan;\n+        final int blockSize;\n+        Future<ByteBuffer> futureBuf;\n+\n+        public WorkUnit(SeekableByteChannel chan, int blockSize, long blockIndex) {\n+            this.chan = chan;\n+            this.buf = ByteBuffer.allocate(blockSize);\n+            this.futureBuf = null;\n+            this.blockSize = blockSize;\n+            this.blockIndex = blockIndex;\n+        }\n+\n+        @Override\n+        public ByteBuffer call() throws IOException {\n+            long pos = ((long)blockSize) * blockIndex;\n+            if (pos > chan.size()) {\n+                return null;\n+            }\n+            chan.position(pos);\n+            // read until buffer is full, or EOF\n+            while (chan.read(buf) > 0) {};\n+            return buf;\n+        }\n+\n+        public ByteBuffer getBuf() throws ExecutionException, InterruptedException {\n+            return futureBuf.get();\n+        }\n+\n+        public WorkUnit resetForIndex(long blockIndex) {\n+            this.blockIndex = blockIndex;\n+            buf.flip();\n+            futureBuf = null;\n+            return this;\n+        }\n+\n+\n+        public void close() throws IOException {\n+            chan.close();\n+        }\n+    }\n+\n+    public SeekableByteChannelPrefetcher(SeekableByteChannel chan, int bufSize) throws IOException {\n+        if (!chan.isOpen()) {\n+            throw new IllegalArgumentException(\"channel must be open\");\n+        }\n+        this.chan = chan;\n+        if (bufSize <= 0) {\n+            throw new IllegalArgumentException(\"bufSize must be positive\");\n+        }\n+        this.bufSize = bufSize;\n+        this.size = chan.size();\n+        this.open = true;\n+        exec = Executors.newFixedThreadPool(1);\n+    }\n+\n+    // if we don't already have that block and the fetching thread is idle,\n+    // make sure it now goes looking for that block index.\n+    private void ensureFetching(long blockIndex) {\n+        if (null != fetching) {\n+            if (fetching.futureBuf.isDone()) {\n+                full.add(fetching);\n+                fetching = null;\n+            } else {\n+                return;\n+            }\n+        }\n+        for (WorkUnit w : full) {\n+            if (w.blockIndex == blockIndex) {\n+                return;\n+            }\n+        }\n+        if (full.size() < BUF_COUNT) {\n+            fetching = new WorkUnit(chan, bufSize, blockIndex);\n+            bytesRead += bufSize;\n+            fetching.futureBuf = exec.submit(fetching);\n+        } else {\n+            // reuse the oldest full buffer\n+            fetching = full.remove(0);\n+            fetching.resetForIndex(blockIndex);\n+            bytesRead += bufSize;\n+            fetching.futureBuf = exec.submit(fetching);\n+        }\n+    }\n+\n+    // Return a buffer at this position, blocking if necessary.\n+    // Start a background read of the buffer after this one (if there isn't one already).\n+    public ByteBuffer fetch(long position) throws InterruptedException, ExecutionException {\n+        long blockIndex = position / bufSize;\n+        boolean goingBack = false;\n+        for (WorkUnit w : full) {\n+            if (w.blockIndex == blockIndex) {\n+                ensureFetching(blockIndex+1);\n+                nbHit++;\n+                return w.buf;\n+            } else if (w.blockIndex > blockIndex) {\n+                goingBack = true;\n+            }\n+        }\n+        if (goingBack) {\n+            // user is asking for a block with a lower index than we've already fetched -\n+            // in other words they are not following the expected pattern of increasing indexes.\n+            nbGoingBack++;\n+        }\n+        if (null == fetching) {\n+            ensureFetching(blockIndex);\n+        }\n+        WorkUnit candidate = fetching;\n+        // block until we have the buffer\n+        ByteBuffer buf = candidate.getBuf();\n+        full.add(candidate);\n+        fetching = null;\n+        if (candidate.blockIndex == blockIndex) {\n+            // this is who we were waiting for\n+            nbNearHit++;\n+            ensureFetching(blockIndex+1);\n+            return buf;\n+        } else {\n+            // wrong block. Let's fetch the right one now.\n+            nbMiss++;\n+            ensureFetching(blockIndex);\n+            candidate = fetching;\n+            buf = candidate.getBuf();\n+            full.add(candidate);\n+            fetching = null;\n+            ensureFetching(blockIndex+1);\n+            return buf;\n+        }\n+    }\n+\n+\n+    /**\n+     * Reads a sequence of bytes from this channel into the given buffer.\n+     * <p>\n+     * <p> Bytes are read starting at this channel's current position, and\n+     * then the position is updated with the number of bytes actually read.\n+     * Otherwise this method behaves exactly as specified in the {@link\n+     * ReadableByteChannel} interface.\n+     *\n+     * @param dst\n+     */\n+    @Override\n+    public int read(ByteBuffer dst) throws IOException {\n+        if (!open) throw new ClosedChannelException();\n+        msBetweenCallsToRead += betweenCallsToRead.elapsed(TimeUnit.MILLISECONDS);\n+        ByteBuffer src;\n+        try {\n+            Stopwatch waitingForData = Stopwatch.createStarted();\n+            src = fetch(position);\n+            msWaitingForData += waitingForData.elapsed(TimeUnit.MILLISECONDS);\n+        } catch (InterruptedException e) {\n+            return 0;\n+        } catch (ExecutionException e) {\n+            throw new RuntimeException(e);\n+        }\n+        Stopwatch copyingData = Stopwatch.createStarted();\n+        int bytesToCopy = dst.remaining();\n+        byte[] array = src.array();\n+        // src.position is how far we've written into the array\n+        long blockIndex = position / bufSize;\n+        int offset = (int)(position - (blockIndex * bufSize));\n+        int availableToCopy = src.position() - offset;\n+        if (availableToCopy < bytesToCopy) {\n+            bytesToCopy = availableToCopy;\n+        }\n+        dst.put(array, offset, bytesToCopy);\n+        position += bytesToCopy;\n+        msCopyingData += copyingData.elapsed(TimeUnit.MILLISECONDS);\n+        bytesReturned += bytesToCopy;\n+        betweenCallsToRead.reset();\n+        betweenCallsToRead.start();\n+        return bytesToCopy;\n+    }\n+\n+    /**\n+     * Writes a sequence of bytes to this channel from the given buffer.\n+     * <p>\n+     * <p> Bytes are written starting at this channel's current position, unless\n+     * the channel is connected to an entity such as a file that is opened with\n+     * the {@link StandardOpenOption#APPEND APPEND} option, in\n+     * which case the position is first advanced to the end. The entity to which\n+     * the channel is connected is grown, if necessary, to accommodate the\n+     * written bytes, and then the position is updated with the number of bytes\n+     * actually written. Otherwise this method behaves exactly as specified by\n+     * the {@link WritableByteChannel} interface.\n+     *\n+     * @param src\n+     */\n+    @Override","path":"src/main/java/org/broadinstitute/hellbender/utils/nio/SeekableByteChannelPrefetcher.java","position":267,"original_position":267,"commit_id":"7541496279c73cff79f5c710b914a574c8f455b9","original_commit_id":"7541496279c73cff79f5c710b914a574c8f455b9","user":{"login":"jean-philippe-martin","id":10458949,"avatar_url":"https://avatars.githubusercontent.com/u/10458949?v=3","gravatar_id":"","url":"https://api.github.com/users/jean-philippe-martin","html_url":"https://github.com/jean-philippe-martin","followers_url":"https://api.github.com/users/jean-philippe-martin/followers","following_url":"https://api.github.com/users/jean-philippe-martin/following{/other_user}","gists_url":"https://api.github.com/users/jean-philippe-martin/gists{/gist_id}","starred_url":"https://api.github.com/users/jean-philippe-martin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jean-philippe-martin/subscriptions","organizations_url":"https://api.github.com/users/jean-philippe-martin/orgs","repos_url":"https://api.github.com/users/jean-philippe-martin/repos","events_url":"https://api.github.com/users/jean-philippe-martin/events{/privacy}","received_events_url":"https://api.github.com/users/jean-philippe-martin/received_events","type":"User","site_admin":false},"body":"Fixed :)","created_at":"2016-09-12T16:17:18Z","updated_at":"2016-09-12T16:17:18Z","html_url":"https://github.com/broadinstitute/gatk/pull/2101#discussion_r78404010","pull_request_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101","_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments/78404010"},"html":{"href":"https://github.com/broadinstitute/gatk/pull/2101#discussion_r78404010"},"pull_request":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101"}}},"pull_request":{"url":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101","id":81720468,"html_url":"https://github.com/broadinstitute/gatk/pull/2101","diff_url":"https://github.com/broadinstitute/gatk/pull/2101.diff","patch_url":"https://github.com/broadinstitute/gatk/pull/2101.patch","issue_url":"https://api.github.com/repos/broadinstitute/gatk/issues/2101","number":2101,"state":"open","locked":false,"title":"NIO countreads and supporting code","user":{"login":"jean-philippe-martin","id":10458949,"avatar_url":"https://avatars.githubusercontent.com/u/10458949?v=3","gravatar_id":"","url":"https://api.github.com/users/jean-philippe-martin","html_url":"https://github.com/jean-philippe-martin","followers_url":"https://api.github.com/users/jean-philippe-martin/followers","following_url":"https://api.github.com/users/jean-philippe-martin/following{/other_user}","gists_url":"https://api.github.com/users/jean-philippe-martin/gists{/gist_id}","starred_url":"https://api.github.com/users/jean-philippe-martin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jean-philippe-martin/subscriptions","organizations_url":"https://api.github.com/users/jean-philippe-martin/orgs","repos_url":"https://api.github.com/users/jean-philippe-martin/repos","events_url":"https://api.github.com/users/jean-philippe-martin/events{/privacy}","received_events_url":"https://api.github.com/users/jean-philippe-martin/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-08-17T21:31:17Z","updated_at":"2016-09-12T16:17:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8f9a752469598bb6272abc59a994d1d434cfbfcc","assignee":{"login":"lbergelson","id":4700332,"avatar_url":"https://avatars.githubusercontent.com/u/4700332?v=3","gravatar_id":"","url":"https://api.github.com/users/lbergelson","html_url":"https://github.com/lbergelson","followers_url":"https://api.github.com/users/lbergelson/followers","following_url":"https://api.github.com/users/lbergelson/following{/other_user}","gists_url":"https://api.github.com/users/lbergelson/gists{/gist_id}","starred_url":"https://api.github.com/users/lbergelson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lbergelson/subscriptions","organizations_url":"https://api.github.com/users/lbergelson/orgs","repos_url":"https://api.github.com/users/lbergelson/repos","events_url":"https://api.github.com/users/lbergelson/events{/privacy}","received_events_url":"https://api.github.com/users/lbergelson/received_events","type":"User","site_admin":false},"assignees":[{"login":"lbergelson","id":4700332,"avatar_url":"https://avatars.githubusercontent.com/u/4700332?v=3","gravatar_id":"","url":"https://api.github.com/users/lbergelson","html_url":"https://github.com/lbergelson","followers_url":"https://api.github.com/users/lbergelson/followers","following_url":"https://api.github.com/users/lbergelson/following{/other_user}","gists_url":"https://api.github.com/users/lbergelson/gists{/gist_id}","starred_url":"https://api.github.com/users/lbergelson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lbergelson/subscriptions","organizations_url":"https://api.github.com/users/lbergelson/orgs","repos_url":"https://api.github.com/users/lbergelson/repos","events_url":"https://api.github.com/users/lbergelson/events{/privacy}","received_events_url":"https://api.github.com/users/lbergelson/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101/commits","review_comments_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101/comments","review_comment_url":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments{/number}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/issues/2101/comments","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/7541496279c73cff79f5c710b914a574c8f455b9","head":{"label":"broadinstitute:jp_nio-countreads","ref":"jp_nio-countreads","sha":"7541496279c73cff79f5c710b914a574c8f455b9","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":27452807,"name":"gatk","full_name":"broadinstitute/gatk","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/gatk","description":"GATK4 development","fork":false,"url":"https://api.github.com/repos/broadinstitute/gatk","forks_url":"https://api.github.com/repos/broadinstitute/gatk/forks","keys_url":"https://api.github.com/repos/broadinstitute/gatk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/gatk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/gatk/teams","hooks_url":"https://api.github.com/repos/broadinstitute/gatk/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/gatk/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/gatk/events","assignees_url":"https://api.github.com/repos/broadinstitute/gatk/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/gatk/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/gatk/tags","blobs_url":"https://api.github.com/repos/broadinstitute/gatk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/gatk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/gatk/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/gatk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/gatk/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/gatk/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/gatk/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/gatk/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/gatk/subscription","commits_url":"https://api.github.com/repos/broadinstitute/gatk/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/gatk/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/gatk/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/gatk/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/gatk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/gatk/merges","archive_url":"https://api.github.com/repos/broadinstitute/gatk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/gatk/downloads","issues_url":"https://api.github.com/repos/broadinstitute/gatk/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/gatk/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/gatk/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/gatk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/gatk/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/gatk/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/gatk/deployments","created_at":"2014-12-02T20:50:36Z","updated_at":"2016-09-08T15:57:36Z","pushed_at":"2016-09-12T14:15:25Z","git_url":"git://github.com/broadinstitute/gatk.git","ssh_url":"git@github.com:broadinstitute/gatk.git","clone_url":"https://github.com/broadinstitute/gatk.git","svn_url":"https://github.com/broadinstitute/gatk","homepage":"","size":125059,"stargazers_count":86,"watchers_count":86,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":33,"mirror_url":null,"open_issues_count":435,"forks":33,"open_issues":435,"watchers":86,"default_branch":"master"}},"base":{"label":"broadinstitute:master","ref":"master","sha":"f4ca2198912e9662229f46a52bd847cb11870247","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":27452807,"name":"gatk","full_name":"broadinstitute/gatk","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/gatk","description":"GATK4 development","fork":false,"url":"https://api.github.com/repos/broadinstitute/gatk","forks_url":"https://api.github.com/repos/broadinstitute/gatk/forks","keys_url":"https://api.github.com/repos/broadinstitute/gatk/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/gatk/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/gatk/teams","hooks_url":"https://api.github.com/repos/broadinstitute/gatk/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/gatk/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/gatk/events","assignees_url":"https://api.github.com/repos/broadinstitute/gatk/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/gatk/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/gatk/tags","blobs_url":"https://api.github.com/repos/broadinstitute/gatk/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/gatk/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/gatk/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/gatk/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/gatk/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/gatk/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/gatk/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/gatk/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/gatk/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/gatk/subscription","commits_url":"https://api.github.com/repos/broadinstitute/gatk/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/gatk/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/gatk/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/gatk/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/gatk/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/gatk/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/gatk/merges","archive_url":"https://api.github.com/repos/broadinstitute/gatk/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/gatk/downloads","issues_url":"https://api.github.com/repos/broadinstitute/gatk/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/gatk/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/gatk/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/gatk/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/gatk/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/gatk/releases{/id}","deployments_url":"https://api.github.com/repos/broadinstitute/gatk/deployments","created_at":"2014-12-02T20:50:36Z","updated_at":"2016-09-08T15:57:36Z","pushed_at":"2016-09-12T14:15:25Z","git_url":"git://github.com/broadinstitute/gatk.git","ssh_url":"git@github.com:broadinstitute/gatk.git","clone_url":"https://github.com/broadinstitute/gatk.git","svn_url":"https://github.com/broadinstitute/gatk","homepage":"","size":125059,"stargazers_count":86,"watchers_count":86,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":33,"mirror_url":null,"open_issues_count":435,"forks":33,"open_issues":435,"watchers":86,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101"},"html":{"href":"https://github.com/broadinstitute/gatk/pull/2101"},"issue":{"href":"https://api.github.com/repos/broadinstitute/gatk/issues/2101"},"comments":{"href":"https://api.github.com/repos/broadinstitute/gatk/issues/2101/comments"},"review_comments":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101/comments"},"review_comment":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/broadinstitute/gatk/pulls/2101/commits"},"statuses":{"href":"https://api.github.com/repos/broadinstitute/gatk/statuses/7541496279c73cff79f5c710b914a574c8f455b9"}}}}
{"actor":{"display_login":"jean-philippe-martin"}}