{"action":"created","comment":{"url":"https://api.github.com/repos/akka/alpakka/pulls/comments/211162953","pull_request_review_id":147526802,"id":211162953,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMTE2Mjk1Mw==","diff_hunk":"@@ -0,0 +1,350 @@\n+/*\n+ * Copyright (C) 2008 Wayne Meissner\n+ *\n+ * This file is part of the JNR project.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * 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+\n+// FIXME: This file can be removed once https://github.com/jnr/jnr-enxio/pull/28 is in.\n+\n+package jnr.enxio.channels;\n+\n+import jnr.constants.platform.Errno;\n+import jnr.ffi.Memory;\n+import jnr.ffi.Pointer;\n+import jnr.ffi.StructLayout;\n+import jnr.ffi.TypeAlias;\n+import jnr.ffi.provider.jffi.NativeRuntime;\n+\n+import java.io.IOException;\n+import java.nio.channels.SelectionKey;\n+import java.nio.channels.Selector;\n+import java.nio.channels.spi.AbstractSelectableChannel;\n+import java.util.*;\n+import java.util.concurrent.ConcurrentHashMap;\n+import java.util.concurrent.TimeUnit;\n+\n+/**\n+ * An implementation of a {@link java.nio.channels.Selector} that uses the BSD (including MacOS)\n+ * kqueue(2) mechanism\n+ */\n+class KQSelector extends java.nio.channels.spi.AbstractSelector {\n+  private static final boolean DEBUG = false;\n+  private static final int MAX_EVENTS = 100;\n+  private static final int EVFILT_READ = -1;\n+  private static final int EVFILT_WRITE = -2;\n+  private static final int EV_ADD = 0x0001;\n+  private static final int EV_DELETE = 0x0002;\n+  private static final int EV_ENABLE = 0x0004;\n+  private static final int EV_DISABLE = 0x0008;\n+  private static final int EV_CLEAR = 0x0020;\n+\n+  private int kqfd = -1;\n+  private final jnr.ffi.Runtime runtime = NativeRuntime.getSystemRuntime();\n+  private final Pointer changebuf;\n+  private final Pointer eventbuf;\n+  private final EventIO io = EventIO.getInstance();\n+  private final int[] pipefd = {-1, -1};\n+  private final Object regLock = new Object();\n+  private final Map<Integer, Descriptor> descriptors = new ConcurrentHashMap<Integer, Descriptor>();\n+  private final Set<SelectionKey> selected = new LinkedHashSet<SelectionKey>();\n+  private final Native.Timespec ZERO_TIMESPEC = new Native.Timespec(0, 0);\n+\n+  public KQSelector(NativeSelectorProvider provider) {\n+    super(provider);\n+    changebuf = Memory.allocateDirect(runtime, MAX_EVENTS * io.size());\n+    eventbuf = Memory.allocateDirect(runtime, MAX_EVENTS * io.size());\n+\n+    Native.libc().pipe(pipefd);\n+\n+    kqfd = Native.libc().kqueue();\n+    io.put(changebuf, 0, pipefd[0], EVFILT_READ, EV_ADD);\n+    Native.libc().kevent(kqfd, changebuf, 1, null, 0, ZERO_TIMESPEC);\n+  }\n+\n+  private static class Descriptor {\n+    private final int fd;\n+    private final Set<KQSelectionKey> keys = new HashSet<KQSelectionKey>();\n+    private boolean write = false, read = false;\n+\n+    public Descriptor(int fd) {\n+      this.fd = fd;\n+    }\n+  }\n+\n+  @Override\n+  protected void implCloseSelector() throws IOException {\n+    if (kqfd != -1) {\n+      Native.close(kqfd);\n+    }\n+    if (pipefd[0] != -1) {\n+      Native.close(pipefd[0]);\n+    }\n+    if (pipefd[1] != -1) {\n+      Native.close(pipefd[1]);\n+    }\n+    pipefd[0] = pipefd[1] = kqfd = -1;\n+\n+    // deregister all keys\n+    for (Map.Entry<Integer, Descriptor> entry : descriptors.entrySet()) {\n+      for (KQSelectionKey k : entry.getValue().keys) {\n+        deregister(k);\n+      }\n+    }\n+  }\n+\n+  @Override\n+  protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object att) {\n+    KQSelectionKey k = new KQSelectionKey(this, (NativeSelectableChannel) ch, ops);\n+    synchronized (regLock) {\n+      Descriptor d = new Descriptor(k.getFD());\n+      descriptors.put(k.getFD(), d);\n+      d.keys.add(k);\n+      handleChangedKey(d);\n+    }","path":"unix-domain-socket/src/main/java/jnr/enxio/channels/KQSelector.java","position":115,"original_position":115,"commit_id":"c9aef7d88dcb6004bef3b2928c90d82e4ef4995a","original_commit_id":"c9aef7d88dcb6004bef3b2928c90d82e4ef4995a","user":{"login":"huntc","id":694893,"node_id":"MDQ6VXNlcjY5NDg5Mw==","avatar_url":"https://avatars2.githubusercontent.com/u/694893?v=4","gravatar_id":"","url":"https://api.github.com/users/huntc","html_url":"https://github.com/huntc","followers_url":"https://api.github.com/users/huntc/followers","following_url":"https://api.github.com/users/huntc/following{/other_user}","gists_url":"https://api.github.com/users/huntc/gists{/gist_id}","starred_url":"https://api.github.com/users/huntc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/huntc/subscriptions","organizations_url":"https://api.github.com/users/huntc/orgs","repos_url":"https://api.github.com/users/huntc/repos","events_url":"https://api.github.com/users/huntc/events{/privacy}","received_events_url":"https://api.github.com/users/huntc/received_events","type":"User","site_admin":false},"body":"For reference, the synchronized block is what changed in the JNR PR.","created_at":"2018-08-20T07:27:01Z","updated_at":"2018-08-20T07:27:01Z","html_url":"https://github.com/akka/alpakka/pull/1142#discussion_r211162953","pull_request_url":"https://api.github.com/repos/akka/alpakka/pulls/1142","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/akka/alpakka/pulls/comments/211162953"},"html":{"href":"https://github.com/akka/alpakka/pull/1142#discussion_r211162953"},"pull_request":{"href":"https://api.github.com/repos/akka/alpakka/pulls/1142"}}},"pull_request":{"url":"https://api.github.com/repos/akka/alpakka/pulls/1142","id":206840801,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA2ODQwODAx","html_url":"https://github.com/akka/alpakka/pull/1142","diff_url":"https://github.com/akka/alpakka/pull/1142.diff","patch_url":"https://github.com/akka/alpakka/pull/1142.patch","issue_url":"https://api.github.com/repos/akka/alpakka/issues/1142","number":1142,"state":"open","locked":false,"title":"[WIP, DON'T MERGE] - Unix Domain Socket - Improve halfClose handling","user":{"login":"longshorej","id":515201,"node_id":"MDQ6VXNlcjUxNTIwMQ==","avatar_url":"https://avatars1.githubusercontent.com/u/515201?v=4","gravatar_id":"","url":"https://api.github.com/users/longshorej","html_url":"https://github.com/longshorej","followers_url":"https://api.github.com/users/longshorej/followers","following_url":"https://api.github.com/users/longshorej/following{/other_user}","gists_url":"https://api.github.com/users/longshorej/gists{/gist_id}","starred_url":"https://api.github.com/users/longshorej/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/longshorej/subscriptions","organizations_url":"https://api.github.com/users/longshorej/orgs","repos_url":"https://api.github.com/users/longshorej/repos","events_url":"https://api.github.com/users/longshorej/events{/privacy}","received_events_url":"https://api.github.com/users/longshorej/received_events","type":"User","site_admin":false},"body":"This PR includes a number of improvements to the `halfClose` handling of the Unix Domain Socket. `halfClose` is particularly relevant for clients (and enabled by default), as they will close their write side to signal end of input, but will still wish to read data from the server.\r\n\r\nThe main changes here are to call `shutdownOutput` and `shutdownInput` where appropriate, instead of closing the channel.\r\n\r\nIt's currently WIP - tests are intermittently failing (at least) on macOS. That being said, we believe it's an improvement over the connector that is currently in master.\r\n\r\nIntended to fix https://github.com/akka/alpakka/issues/1139","created_at":"2018-08-07T22:08:47Z","updated_at":"2018-08-20T07:27:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d3e1085cd0b0fc4fab573ce8216d10d9bbba44e7","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/akka/alpakka/pulls/1142/commits","review_comments_url":"https://api.github.com/repos/akka/alpakka/pulls/1142/comments","review_comment_url":"https://api.github.com/repos/akka/alpakka/pulls/comments{/number}","comments_url":"https://api.github.com/repos/akka/alpakka/issues/1142/comments","statuses_url":"https://api.github.com/repos/akka/alpakka/statuses/c9aef7d88dcb6004bef3b2928c90d82e4ef4995a","head":{"label":"longshorej:uds-half-close","ref":"uds-half-close","sha":"c9aef7d88dcb6004bef3b2928c90d82e4ef4995a","user":{"login":"longshorej","id":515201,"node_id":"MDQ6VXNlcjUxNTIwMQ==","avatar_url":"https://avatars1.githubusercontent.com/u/515201?v=4","gravatar_id":"","url":"https://api.github.com/users/longshorej","html_url":"https://github.com/longshorej","followers_url":"https://api.github.com/users/longshorej/followers","following_url":"https://api.github.com/users/longshorej/following{/other_user}","gists_url":"https://api.github.com/users/longshorej/gists{/gist_id}","starred_url":"https://api.github.com/users/longshorej/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/longshorej/subscriptions","organizations_url":"https://api.github.com/users/longshorej/orgs","repos_url":"https://api.github.com/users/longshorej/repos","events_url":"https://api.github.com/users/longshorej/events{/privacy}","received_events_url":"https://api.github.com/users/longshorej/received_events","type":"User","site_admin":false},"repo":{"id":127961160,"node_id":"MDEwOlJlcG9zaXRvcnkxMjc5NjExNjA=","name":"alpakka","full_name":"longshorej/alpakka","owner":{"login":"longshorej","id":515201,"node_id":"MDQ6VXNlcjUxNTIwMQ==","avatar_url":"https://avatars1.githubusercontent.com/u/515201?v=4","gravatar_id":"","url":"https://api.github.com/users/longshorej","html_url":"https://github.com/longshorej","followers_url":"https://api.github.com/users/longshorej/followers","following_url":"https://api.github.com/users/longshorej/following{/other_user}","gists_url":"https://api.github.com/users/longshorej/gists{/gist_id}","starred_url":"https://api.github.com/users/longshorej/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/longshorej/subscriptions","organizations_url":"https://api.github.com/users/longshorej/orgs","repos_url":"https://api.github.com/users/longshorej/repos","events_url":"https://api.github.com/users/longshorej/events{/privacy}","received_events_url":"https://api.github.com/users/longshorej/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/longshorej/alpakka","description":"Reactive Enterprise Integration — Alpakka","fork":true,"url":"https://api.github.com/repos/longshorej/alpakka","forks_url":"https://api.github.com/repos/longshorej/alpakka/forks","keys_url":"https://api.github.com/repos/longshorej/alpakka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/longshorej/alpakka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/longshorej/alpakka/teams","hooks_url":"https://api.github.com/repos/longshorej/alpakka/hooks","issue_events_url":"https://api.github.com/repos/longshorej/alpakka/issues/events{/number}","events_url":"https://api.github.com/repos/longshorej/alpakka/events","assignees_url":"https://api.github.com/repos/longshorej/alpakka/assignees{/user}","branches_url":"https://api.github.com/repos/longshorej/alpakka/branches{/branch}","tags_url":"https://api.github.com/repos/longshorej/alpakka/tags","blobs_url":"https://api.github.com/repos/longshorej/alpakka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/longshorej/alpakka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/longshorej/alpakka/git/refs{/sha}","trees_url":"https://api.github.com/repos/longshorej/alpakka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/longshorej/alpakka/statuses/{sha}","languages_url":"https://api.github.com/repos/longshorej/alpakka/languages","stargazers_url":"https://api.github.com/repos/longshorej/alpakka/stargazers","contributors_url":"https://api.github.com/repos/longshorej/alpakka/contributors","subscribers_url":"https://api.github.com/repos/longshorej/alpakka/subscribers","subscription_url":"https://api.github.com/repos/longshorej/alpakka/subscription","commits_url":"https://api.github.com/repos/longshorej/alpakka/commits{/sha}","git_commits_url":"https://api.github.com/repos/longshorej/alpakka/git/commits{/sha}","comments_url":"https://api.github.com/repos/longshorej/alpakka/comments{/number}","issue_comment_url":"https://api.github.com/repos/longshorej/alpakka/issues/comments{/number}","contents_url":"https://api.github.com/repos/longshorej/alpakka/contents/{+path}","compare_url":"https://api.github.com/repos/longshorej/alpakka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/longshorej/alpakka/merges","archive_url":"https://api.github.com/repos/longshorej/alpakka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/longshorej/alpakka/downloads","issues_url":"https://api.github.com/repos/longshorej/alpakka/issues{/number}","pulls_url":"https://api.github.com/repos/longshorej/alpakka/pulls{/number}","milestones_url":"https://api.github.com/repos/longshorej/alpakka/milestones{/number}","notifications_url":"https://api.github.com/repos/longshorej/alpakka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/longshorej/alpakka/labels{/name}","releases_url":"https://api.github.com/repos/longshorej/alpakka/releases{/id}","deployments_url":"https://api.github.com/repos/longshorej/alpakka/deployments","created_at":"2018-04-03T19:53:24Z","updated_at":"2018-04-03T19:53:27Z","pushed_at":"2018-08-20T07:18:31Z","git_url":"git://github.com/longshorej/alpakka.git","ssh_url":"git@github.com:longshorej/alpakka.git","clone_url":"https://github.com/longshorej/alpakka.git","svn_url":"https://github.com/longshorej/alpakka","homepage":"https://developer.lightbend.com/docs/alpakka/current/","size":9901,"stargazers_count":0,"watchers_count":0,"language":"Scala","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":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"akka:master","ref":"master","sha":"f86fd143e5ea5fdeb1eb2bcecc1bff2ab90b1b9d","user":{"login":"akka","id":1496237,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0OTYyMzc=","avatar_url":"https://avatars2.githubusercontent.com/u/1496237?v=4","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"repo":{"id":70807477,"node_id":"MDEwOlJlcG9zaXRvcnk3MDgwNzQ3Nw==","name":"alpakka","full_name":"akka/alpakka","owner":{"login":"akka","id":1496237,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0OTYyMzc=","avatar_url":"https://avatars2.githubusercontent.com/u/1496237?v=4","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/akka/alpakka","description":"Alpakka is a Reactive Enterprise Integration library for Java and Scala, based on Reactive Streams and Akka.","fork":false,"url":"https://api.github.com/repos/akka/alpakka","forks_url":"https://api.github.com/repos/akka/alpakka/forks","keys_url":"https://api.github.com/repos/akka/alpakka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akka/alpakka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akka/alpakka/teams","hooks_url":"https://api.github.com/repos/akka/alpakka/hooks","issue_events_url":"https://api.github.com/repos/akka/alpakka/issues/events{/number}","events_url":"https://api.github.com/repos/akka/alpakka/events","assignees_url":"https://api.github.com/repos/akka/alpakka/assignees{/user}","branches_url":"https://api.github.com/repos/akka/alpakka/branches{/branch}","tags_url":"https://api.github.com/repos/akka/alpakka/tags","blobs_url":"https://api.github.com/repos/akka/alpakka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akka/alpakka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akka/alpakka/git/refs{/sha}","trees_url":"https://api.github.com/repos/akka/alpakka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akka/alpakka/statuses/{sha}","languages_url":"https://api.github.com/repos/akka/alpakka/languages","stargazers_url":"https://api.github.com/repos/akka/alpakka/stargazers","contributors_url":"https://api.github.com/repos/akka/alpakka/contributors","subscribers_url":"https://api.github.com/repos/akka/alpakka/subscribers","subscription_url":"https://api.github.com/repos/akka/alpakka/subscription","commits_url":"https://api.github.com/repos/akka/alpakka/commits{/sha}","git_commits_url":"https://api.github.com/repos/akka/alpakka/git/commits{/sha}","comments_url":"https://api.github.com/repos/akka/alpakka/comments{/number}","issue_comment_url":"https://api.github.com/repos/akka/alpakka/issues/comments{/number}","contents_url":"https://api.github.com/repos/akka/alpakka/contents/{+path}","compare_url":"https://api.github.com/repos/akka/alpakka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akka/alpakka/merges","archive_url":"https://api.github.com/repos/akka/alpakka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akka/alpakka/downloads","issues_url":"https://api.github.com/repos/akka/alpakka/issues{/number}","pulls_url":"https://api.github.com/repos/akka/alpakka/pulls{/number}","milestones_url":"https://api.github.com/repos/akka/alpakka/milestones{/number}","notifications_url":"https://api.github.com/repos/akka/alpakka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akka/alpakka/labels{/name}","releases_url":"https://api.github.com/repos/akka/alpakka/releases{/id}","deployments_url":"https://api.github.com/repos/akka/alpakka/deployments","created_at":"2016-10-13T13:08:14Z","updated_at":"2018-08-18T14:19:40Z","pushed_at":"2018-08-20T07:18:32Z","git_url":"git://github.com/akka/alpakka.git","ssh_url":"git@github.com:akka/alpakka.git","clone_url":"https://github.com/akka/alpakka.git","svn_url":"https://github.com/akka/alpakka","homepage":"https://developer.lightbend.com/docs/alpakka/current/","size":9934,"stargazers_count":777,"watchers_count":777,"language":"Scala","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":340,"mirror_url":null,"archived":false,"open_issues_count":192,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":340,"open_issues":192,"watchers":777,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/akka/alpakka/pulls/1142"},"html":{"href":"https://github.com/akka/alpakka/pull/1142"},"issue":{"href":"https://api.github.com/repos/akka/alpakka/issues/1142"},"comments":{"href":"https://api.github.com/repos/akka/alpakka/issues/1142/comments"},"review_comments":{"href":"https://api.github.com/repos/akka/alpakka/pulls/1142/comments"},"review_comment":{"href":"https://api.github.com/repos/akka/alpakka/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/akka/alpakka/pulls/1142/commits"},"statuses":{"href":"https://api.github.com/repos/akka/alpakka/statuses/c9aef7d88dcb6004bef3b2928c90d82e4ef4995a"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"huntc"}}