{"action":"created","comment":{"url":"https://api.github.com/repos/druid-io/druid/pulls/comments/170526102","pull_request_review_id":99221744,"id":170526102,"diff_hunk":"@@ -0,0 +1,168 @@\n+/*\n+ * Licensed to Metamarkets Group Inc. (Metamarkets) under one\n+ * or more contributor license agreements. See the NOTICE file\n+ * distributed with this work for additional information\n+ * regarding copyright ownership. Metamarkets 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,\n+ * software distributed under the License is distributed on an\n+ * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n+ * KIND, either express or implied. See the License for the\n+ * specific language governing permissions and limitations\n+ * under the License.\n+ */\n+\n+package io.druid.java.util.common.io;\n+\n+import java.io.File;\n+import java.io.FileDescriptor;\n+import java.io.IOException;\n+import java.io.InputStream;\n+import java.io.RandomAccessFile;\n+import java.lang.reflect.Field;\n+\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+import com.sun.jna.LastErrorException;\n+import com.sun.jna.Native;\n+import com.sun.jna.Platform;\n+\n+/**\n+ * Native I/O operations in order to minimize cache impact.\n+ */\n+public class NativeIO\n+{\n+  private static final Logger LOG = LoggerFactory.getLogger(NativeIO.class);\n+\n+  private static final int POSIX_FADV_DONTNEED = 4; /* fadvise.h */\n+\n+  private static boolean initialized = false;\n+  private static boolean fadvisePossible = true;\n+\n+  static {\n+    try {\n+      Native.register(Platform.C_LIBRARY_NAME);\n+      initialized = true;\n+    }\n+    catch (NoClassDefFoundError e) {\n+      LOG.info(\"JNA not found. Native methods will be disabled.\");\n+    }\n+    catch (UnsatisfiedLinkError e) {\n+      LOG.info(\"Unable to link C library. Native methods will be disabled.\");\n+    }\n+    catch (NoSuchMethodError e) {\n+      LOG.warn(\"Obsolete version of JNA present; unable to register C library\");\n+    }\n+  }\n+\n+  public static native int posix_fadvise(int fd, long offset, long len, int flag) throws LastErrorException;\n+\n+  private NativeIO() {}\n+\n+  private static Field getFieldByReflection(Class cls, String fieldName)\n+  {\n+    Field field = null;\n+\n+    try {\n+      field = cls.getDeclaredField(fieldName);\n+      field.setAccessible(true);\n+    }\n+    catch (Exception e) {\n+      // We don't really expect this so throw an assertion to\n+      // catch this during development\n+      assert false;\n+      LOG.warn(\"Unable to read {} field from {}\", fieldName, cls.getName());\n+    }\n+\n+    return field;\n+  }\n+  /**\n+   * Get system file descriptor (int) from FileDescriptor object.\n+   * @param descriptor - FileDescriptor object to get fd from\n+   * @return file descriptor, -1 or error\n+   */\n+  public static int getfd(FileDescriptor descriptor)\n+  {\n+    Field field = getFieldByReflection(descriptor.getClass(), \"fd\");\n+    try {\n+      return field.getInt(descriptor);\n+    }\n+    catch (Exception e) {\n+      LOG.warn(\"Unable to read fd field from java.io.FileDescriptor\");\n+    }\n+\n+    return -1;\n+  }\n+\n+  /**\n+   * Remove pages from the file system page cache when they wont\n+   * be accessed again\n+   *\n+   * @param fd     The file descriptor of the source file.\n+   * @param offset The offset within the file.\n+   * @param len    The length to be flushed.\n+   */\n+\n+  public static void trySkipCache(int fd, long offset, long len)\n+  {\n+    if (!initialized || !fadvisePossible || fd < 0) {\n+      return;\n+    }\n+    try {\n+      posix_fadvise(fd, offset, len, POSIX_FADV_DONTNEED);\n+    }\n+    catch (UnsupportedOperationException uoe) {\n+      LOG.warn(\"posix_fadvise is not supported : \", uoe);\n+      fadvisePossible = false;\n+    }\n+    catch (UnsatisfiedLinkError ule) {\n+      // if JNA is unavailable just skipping Direct I/O\n+      // instance of this class will act like normal RandomAccessFile\n+      LOG.warn(\"Unsatisfied Link error: posix_fadvise failed on file descriptor {}, offset {} : \",\n+          new Object[] {fd, offset, ule});\n+      fadvisePossible = false;\n+    }\n+    catch (Exception e) {\n+      // This is best effort anyway so lets just log that there was an\n+      // exception and forget\n+      LOG.warn(\"Unknown exception: posix_fadvise failed on file descriptor {}, offset {} : \",\n+          new Object[] {fd, offset, e});\n+    }\n+  }\n+\n+\n+  /**\n+   * Copy from an input stream to a file minimizing cache impact. This happens chunk by chunk\n+   * so only at most chunk size will be present in the OS page cache. Linux only.\n+   *\n+   * @param src Source InputStream where to copy from\n+   * @param dest Destination file to copy to\n+   * @throws IOException\n+   */\n+  public static void chunkedCopy(InputStream src, File dest) throws IOException\n+  {\n+    final RandomAccessFile raf = new RandomAccessFile(dest, \"rwd\");","path":"java-util/src/main/java/io/druid/java/util/common/io/NativeIO.java","position":149,"original_position":149,"commit_id":"6d255b6596013d52cad481f2c61c5606b9c709db","original_commit_id":"6d255b6596013d52cad481f2c61c5606b9c709db","user":{"login":"bolkedebruin","id":4282712,"avatar_url":"https://avatars2.githubusercontent.com/u/4282712?v=4","gravatar_id":"","url":"https://api.github.com/users/bolkedebruin","html_url":"https://github.com/bolkedebruin","followers_url":"https://api.github.com/users/bolkedebruin/followers","following_url":"https://api.github.com/users/bolkedebruin/following{/other_user}","gists_url":"https://api.github.com/users/bolkedebruin/gists{/gist_id}","starred_url":"https://api.github.com/users/bolkedebruin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bolkedebruin/subscriptions","organizations_url":"https://api.github.com/users/bolkedebruin/orgs","repos_url":"https://api.github.com/users/bolkedebruin/repos","events_url":"https://api.github.com/users/bolkedebruin/events{/privacy}","received_events_url":"https://api.github.com/users/bolkedebruin/received_events","type":"User","site_admin":false},"body":"Yep. This would do that right? Or is there a question behind the question.","created_at":"2018-02-26T08:57:40Z","updated_at":"2018-02-26T08:57:40Z","html_url":"https://github.com/druid-io/druid/pull/5421#discussion_r170526102","pull_request_url":"https://api.github.com/repos/druid-io/druid/pulls/5421","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/druid-io/druid/pulls/comments/170526102"},"html":{"href":"https://github.com/druid-io/druid/pull/5421#discussion_r170526102"},"pull_request":{"href":"https://api.github.com/repos/druid-io/druid/pulls/5421"}},"in_reply_to_id":170490428},"pull_request":{"url":"https://api.github.com/repos/druid-io/druid/pulls/5421","id":171237264,"html_url":"https://github.com/druid-io/druid/pull/5421","diff_url":"https://github.com/druid-io/druid/pull/5421.diff","patch_url":"https://github.com/druid-io/druid/pull/5421.patch","issue_url":"https://api.github.com/repos/druid-io/druid/issues/5421","number":5421,"state":"open","locked":false,"title":"Skip OS cache on Linux when pulling segments","user":{"login":"bolkedebruin","id":4282712,"avatar_url":"https://avatars2.githubusercontent.com/u/4282712?v=4","gravatar_id":"","url":"https://api.github.com/users/bolkedebruin","html_url":"https://github.com/bolkedebruin","followers_url":"https://api.github.com/users/bolkedebruin/followers","following_url":"https://api.github.com/users/bolkedebruin/following{/other_user}","gists_url":"https://api.github.com/users/bolkedebruin/gists{/gist_id}","starred_url":"https://api.github.com/users/bolkedebruin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bolkedebruin/subscriptions","organizations_url":"https://api.github.com/users/bolkedebruin/orgs","repos_url":"https://api.github.com/users/bolkedebruin/repos","events_url":"https://api.github.com/users/bolkedebruin/events{/privacy}","received_events_url":"https://api.github.com/users/bolkedebruin/received_events","type":"User","site_admin":false},"body":"Druid relies on the page cache of Linux in order to have memory segments.\r\nHowever when loading segments from deep storage or rebalancing the page\r\ncache can get poisoned by segments that should not be in memory yet.\r\nThis can significantly slow down Druid in case rebalancing happens\r\nas data that might not be queried often is suddenly in the page cache.\r\n\r\nThis PR implements the same logic as is in Apache Cassandra and Apache\r\nBookkeeper, but extends it slightly by copying in chunks so the cache will \r\nonly hit by max 8mb instead of the whole file.\r\n\r\nCloses #4746 \r\n\r\nFurther optimizations can happen when copying from the local filesystem. I would like to agree on the approach first and get this merged first before tackling the other issue.\r\n\r\nAs this is automatically enabled on Linux it should be covered by existing tests.\r\n\r\n@drcrallen @Fokko \r\n","created_at":"2018-02-25T16:09:43Z","updated_at":"2018-02-26T08:57:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f85ba53dab7bb2145b437fb5e888720bcedb09ad","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":641613631,"url":"https://api.github.com/repos/druid-io/druid/labels/Area%20-%20Cache","name":"Area - Cache","color":"fef2c0","default":false},{"id":120288359,"url":"https://api.github.com/repos/druid-io/druid/labels/Performance","name":"Performance","color":"fbca04","default":false}],"milestone":{"url":"https://api.github.com/repos/druid-io/druid/milestones/25","html_url":"https://github.com/druid-io/druid/milestone/25","labels_url":"https://api.github.com/repos/druid-io/druid/milestones/25/labels","id":3023864,"number":25,"title":"0.13.0","description":"","creator":{"login":"leventov","id":609240,"avatar_url":"https://avatars0.githubusercontent.com/u/609240?v=4","gravatar_id":"","url":"https://api.github.com/users/leventov","html_url":"https://github.com/leventov","followers_url":"https://api.github.com/users/leventov/followers","following_url":"https://api.github.com/users/leventov/following{/other_user}","gists_url":"https://api.github.com/users/leventov/gists{/gist_id}","starred_url":"https://api.github.com/users/leventov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leventov/subscriptions","organizations_url":"https://api.github.com/users/leventov/orgs","repos_url":"https://api.github.com/users/leventov/repos","events_url":"https://api.github.com/users/leventov/events{/privacy}","received_events_url":"https://api.github.com/users/leventov/received_events","type":"User","site_admin":false},"open_issues":19,"closed_issues":18,"state":"open","created_at":"2018-01-09T18:30:01Z","updated_at":"2018-02-26T01:54:30Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/druid-io/druid/pulls/5421/commits","review_comments_url":"https://api.github.com/repos/druid-io/druid/pulls/5421/comments","review_comment_url":"https://api.github.com/repos/druid-io/druid/pulls/comments{/number}","comments_url":"https://api.github.com/repos/druid-io/druid/issues/5421/comments","statuses_url":"https://api.github.com/repos/druid-io/druid/statuses/6d255b6596013d52cad481f2c61c5606b9c709db","head":{"label":"bolkedebruin:nativeio","ref":"nativeio","sha":"6d255b6596013d52cad481f2c61c5606b9c709db","user":{"login":"bolkedebruin","id":4282712,"avatar_url":"https://avatars2.githubusercontent.com/u/4282712?v=4","gravatar_id":"","url":"https://api.github.com/users/bolkedebruin","html_url":"https://github.com/bolkedebruin","followers_url":"https://api.github.com/users/bolkedebruin/followers","following_url":"https://api.github.com/users/bolkedebruin/following{/other_user}","gists_url":"https://api.github.com/users/bolkedebruin/gists{/gist_id}","starred_url":"https://api.github.com/users/bolkedebruin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bolkedebruin/subscriptions","organizations_url":"https://api.github.com/users/bolkedebruin/orgs","repos_url":"https://api.github.com/users/bolkedebruin/repos","events_url":"https://api.github.com/users/bolkedebruin/events{/privacy}","received_events_url":"https://api.github.com/users/bolkedebruin/received_events","type":"User","site_admin":false},"repo":{"id":102218782,"name":"druid","full_name":"bolkedebruin/druid","owner":{"login":"bolkedebruin","id":4282712,"avatar_url":"https://avatars2.githubusercontent.com/u/4282712?v=4","gravatar_id":"","url":"https://api.github.com/users/bolkedebruin","html_url":"https://github.com/bolkedebruin","followers_url":"https://api.github.com/users/bolkedebruin/followers","following_url":"https://api.github.com/users/bolkedebruin/following{/other_user}","gists_url":"https://api.github.com/users/bolkedebruin/gists{/gist_id}","starred_url":"https://api.github.com/users/bolkedebruin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bolkedebruin/subscriptions","organizations_url":"https://api.github.com/users/bolkedebruin/orgs","repos_url":"https://api.github.com/users/bolkedebruin/repos","events_url":"https://api.github.com/users/bolkedebruin/events{/privacy}","received_events_url":"https://api.github.com/users/bolkedebruin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bolkedebruin/druid","description":"Column oriented distributed data store ideal for powering interactive applications","fork":true,"url":"https://api.github.com/repos/bolkedebruin/druid","forks_url":"https://api.github.com/repos/bolkedebruin/druid/forks","keys_url":"https://api.github.com/repos/bolkedebruin/druid/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bolkedebruin/druid/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bolkedebruin/druid/teams","hooks_url":"https://api.github.com/repos/bolkedebruin/druid/hooks","issue_events_url":"https://api.github.com/repos/bolkedebruin/druid/issues/events{/number}","events_url":"https://api.github.com/repos/bolkedebruin/druid/events","assignees_url":"https://api.github.com/repos/bolkedebruin/druid/assignees{/user}","branches_url":"https://api.github.com/repos/bolkedebruin/druid/branches{/branch}","tags_url":"https://api.github.com/repos/bolkedebruin/druid/tags","blobs_url":"https://api.github.com/repos/bolkedebruin/druid/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bolkedebruin/druid/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bolkedebruin/druid/git/refs{/sha}","trees_url":"https://api.github.com/repos/bolkedebruin/druid/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bolkedebruin/druid/statuses/{sha}","languages_url":"https://api.github.com/repos/bolkedebruin/druid/languages","stargazers_url":"https://api.github.com/repos/bolkedebruin/druid/stargazers","contributors_url":"https://api.github.com/repos/bolkedebruin/druid/contributors","subscribers_url":"https://api.github.com/repos/bolkedebruin/druid/subscribers","subscription_url":"https://api.github.com/repos/bolkedebruin/druid/subscription","commits_url":"https://api.github.com/repos/bolkedebruin/druid/commits{/sha}","git_commits_url":"https://api.github.com/repos/bolkedebruin/druid/git/commits{/sha}","comments_url":"https://api.github.com/repos/bolkedebruin/druid/comments{/number}","issue_comment_url":"https://api.github.com/repos/bolkedebruin/druid/issues/comments{/number}","contents_url":"https://api.github.com/repos/bolkedebruin/druid/contents/{+path}","compare_url":"https://api.github.com/repos/bolkedebruin/druid/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bolkedebruin/druid/merges","archive_url":"https://api.github.com/repos/bolkedebruin/druid/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bolkedebruin/druid/downloads","issues_url":"https://api.github.com/repos/bolkedebruin/druid/issues{/number}","pulls_url":"https://api.github.com/repos/bolkedebruin/druid/pulls{/number}","milestones_url":"https://api.github.com/repos/bolkedebruin/druid/milestones{/number}","notifications_url":"https://api.github.com/repos/bolkedebruin/druid/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bolkedebruin/druid/labels{/name}","releases_url":"https://api.github.com/repos/bolkedebruin/druid/releases{/id}","deployments_url":"https://api.github.com/repos/bolkedebruin/druid/deployments","created_at":"2017-09-02T19:26:17Z","updated_at":"2017-09-02T19:26:32Z","pushed_at":"2018-02-25T19:09:40Z","git_url":"git://github.com/bolkedebruin/druid.git","ssh_url":"git@github.com:bolkedebruin/druid.git","clone_url":"https://github.com/bolkedebruin/druid.git","svn_url":"https://github.com/bolkedebruin/druid","homepage":"http://druid.io","size":132774,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"druid-io:master","ref":"master","sha":"ac5034e2414ab038984fc0cdb24999a2f9babd5d","user":{"login":"druid-io","id":4203474,"avatar_url":"https://avatars0.githubusercontent.com/u/4203474?v=4","gravatar_id":"","url":"https://api.github.com/users/druid-io","html_url":"https://github.com/druid-io","followers_url":"https://api.github.com/users/druid-io/followers","following_url":"https://api.github.com/users/druid-io/following{/other_user}","gists_url":"https://api.github.com/users/druid-io/gists{/gist_id}","starred_url":"https://api.github.com/users/druid-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/druid-io/subscriptions","organizations_url":"https://api.github.com/users/druid-io/orgs","repos_url":"https://api.github.com/users/druid-io/repos","events_url":"https://api.github.com/users/druid-io/events{/privacy}","received_events_url":"https://api.github.com/users/druid-io/received_events","type":"Organization","site_admin":false},"repo":{"id":6358188,"name":"druid","full_name":"druid-io/druid","owner":{"login":"druid-io","id":4203474,"avatar_url":"https://avatars0.githubusercontent.com/u/4203474?v=4","gravatar_id":"","url":"https://api.github.com/users/druid-io","html_url":"https://github.com/druid-io","followers_url":"https://api.github.com/users/druid-io/followers","following_url":"https://api.github.com/users/druid-io/following{/other_user}","gists_url":"https://api.github.com/users/druid-io/gists{/gist_id}","starred_url":"https://api.github.com/users/druid-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/druid-io/subscriptions","organizations_url":"https://api.github.com/users/druid-io/orgs","repos_url":"https://api.github.com/users/druid-io/repos","events_url":"https://api.github.com/users/druid-io/events{/privacy}","received_events_url":"https://api.github.com/users/druid-io/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/druid-io/druid","description":"Column oriented distributed data store ideal for powering interactive applications","fork":false,"url":"https://api.github.com/repos/druid-io/druid","forks_url":"https://api.github.com/repos/druid-io/druid/forks","keys_url":"https://api.github.com/repos/druid-io/druid/keys{/key_id}","collaborators_url":"https://api.github.com/repos/druid-io/druid/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/druid-io/druid/teams","hooks_url":"https://api.github.com/repos/druid-io/druid/hooks","issue_events_url":"https://api.github.com/repos/druid-io/druid/issues/events{/number}","events_url":"https://api.github.com/repos/druid-io/druid/events","assignees_url":"https://api.github.com/repos/druid-io/druid/assignees{/user}","branches_url":"https://api.github.com/repos/druid-io/druid/branches{/branch}","tags_url":"https://api.github.com/repos/druid-io/druid/tags","blobs_url":"https://api.github.com/repos/druid-io/druid/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/druid-io/druid/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/druid-io/druid/git/refs{/sha}","trees_url":"https://api.github.com/repos/druid-io/druid/git/trees{/sha}","statuses_url":"https://api.github.com/repos/druid-io/druid/statuses/{sha}","languages_url":"https://api.github.com/repos/druid-io/druid/languages","stargazers_url":"https://api.github.com/repos/druid-io/druid/stargazers","contributors_url":"https://api.github.com/repos/druid-io/druid/contributors","subscribers_url":"https://api.github.com/repos/druid-io/druid/subscribers","subscription_url":"https://api.github.com/repos/druid-io/druid/subscription","commits_url":"https://api.github.com/repos/druid-io/druid/commits{/sha}","git_commits_url":"https://api.github.com/repos/druid-io/druid/git/commits{/sha}","comments_url":"https://api.github.com/repos/druid-io/druid/comments{/number}","issue_comment_url":"https://api.github.com/repos/druid-io/druid/issues/comments{/number}","contents_url":"https://api.github.com/repos/druid-io/druid/contents/{+path}","compare_url":"https://api.github.com/repos/druid-io/druid/compare/{base}...{head}","merges_url":"https://api.github.com/repos/druid-io/druid/merges","archive_url":"https://api.github.com/repos/druid-io/druid/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/druid-io/druid/downloads","issues_url":"https://api.github.com/repos/druid-io/druid/issues{/number}","pulls_url":"https://api.github.com/repos/druid-io/druid/pulls{/number}","milestones_url":"https://api.github.com/repos/druid-io/druid/milestones{/number}","notifications_url":"https://api.github.com/repos/druid-io/druid/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/druid-io/druid/labels{/name}","releases_url":"https://api.github.com/repos/druid-io/druid/releases{/id}","deployments_url":"https://api.github.com/repos/druid-io/druid/deployments","created_at":"2012-10-23T19:08:07Z","updated_at":"2018-02-26T08:16:11Z","pushed_at":"2018-02-26T07:05:47Z","git_url":"git://github.com/druid-io/druid.git","ssh_url":"git@github.com:druid-io/druid.git","clone_url":"https://github.com/druid-io/druid.git","svn_url":"https://github.com/druid-io/druid","homepage":"http://druid.io","size":134842,"stargazers_count":6128,"watchers_count":6128,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1507,"mirror_url":null,"archived":false,"open_issues_count":913,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":1507,"open_issues":913,"watchers":6128,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/druid-io/druid/pulls/5421"},"html":{"href":"https://github.com/druid-io/druid/pull/5421"},"issue":{"href":"https://api.github.com/repos/druid-io/druid/issues/5421"},"comments":{"href":"https://api.github.com/repos/druid-io/druid/issues/5421/comments"},"review_comments":{"href":"https://api.github.com/repos/druid-io/druid/pulls/5421/comments"},"review_comment":{"href":"https://api.github.com/repos/druid-io/druid/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/druid-io/druid/pulls/5421/commits"},"statuses":{"href":"https://api.github.com/repos/druid-io/druid/statuses/6d255b6596013d52cad481f2c61c5606b9c709db"}},"author_association":"NONE"}}
{"actor":{"display_login":"bolkedebruin"}}