{"action":"created","comment":{"url":"https://api.github.com/repos/akka/akka/pulls/comments/63708980","id":63708980,"diff_hunk":"@@ -0,0 +1,218 @@\n+/**\n+ * Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>\n+ */\n+\n+package akka.remote.artery\n+\n+import java.nio.charset.Charset\n+import java.nio.{ ByteBuffer, ByteOrder }\n+import java.util.concurrent.atomic.AtomicInteger\n+\n+import akka.actor.{ ActorRef, Address, AddressFromURIString }\n+import akka.io.DirectByteBufferPool\n+import akka.remote.RemoteActorRef\n+import org.agrona.concurrent.ManyToManyConcurrentArrayQueue\n+\n+/**\n+ * INTERNAL API\n+ */\n+private[remote] class OutOfBuffersException extends RuntimeException(\"Out of usable ByteBuffers\")\n+\n+/**\n+ * INTERNAL API\n+ */\n+private[remote] class PayloadBufferPool(maximumPayload: Int, maximumBuffers: Int) {\n+\n+  private val allocateBudget = new AtomicInteger(maximumBuffers)\n+\n+  private val directByteBufferPool = new DirectByteBufferPool(maximumPayload, maximumBuffers)\n+  private val availableBuffers = new ManyToManyConcurrentArrayQueue[EnvelopeBuffer](maximumBuffers)\n+\n+  def acquire(): EnvelopeBuffer = {\n+    val buf = availableBuffers.poll()\n+\n+    if (buf ne null) {\n+      buf\n+    } else if (allocateBudget.decrementAndGet() >= 0) {\n+      val newBuf = new EnvelopeBuffer(directByteBufferPool.acquire())\n+      newBuf.byteBuffer.order(ByteOrder.LITTLE_ENDIAN)\n+      newBuf\n+    } else\n+      throw new OutOfBuffersException\n+  }\n+\n+  def release(buffer: EnvelopeBuffer) = {\n+    availableBuffers.add(buffer)\n+  }\n+\n+}\n+\n+/**\n+ * INTERNAL API\n+ */\n+private[remote] object EnvelopeBuffer {\n+\n+  val TagTypeMask = 0xFF000000\n+  val TagValueMask = 0x0000FFFF\n+\n+  val VersionOffset = 0\n+  val UidOffset = 4\n+  val SenderActorRefTagOffset = 8\n+  val RecipientActorRefTagOffset = 12\n+  val LiteralsSectionOffset = 16\n+\n+  val UsAscii = Charset.forName(\"US-ASCII\")\n+}\n+\n+/**\n+ * INTERNAL API\n+ */\n+private[remote] trait LiteralCompressionTable {\n+\n+  def compressActorRef(ref: String): Int\n+  def decompressActorRef(idx: Int): String\n+\n+}\n+\n+object HeaderBuilder {\n+  def apply(compressionTable: LiteralCompressionTable): HeaderBuilder = new HeaderBuilderImpl(compressionTable)\n+}\n+\n+/**\n+ * INTERNAL API\n+ */\n+sealed trait HeaderBuilder {\n+  def version_=(v: Int): Unit\n+  def version: Int\n+\n+  def uid_=(u: Int): Unit\n+  def uid: Int\n+\n+  def senderActorRef_=(ref: String): Unit\n+  def senderActorRef: String\n+\n+  def recipientActorRef_=(ref: String): Unit\n+  def recipientActorRef: String\n+}\n+\n+/**\n+ * INTERNAL API\n+ */\n+private[remote] final class HeaderBuilderImpl(val compressionTable: LiteralCompressionTable) extends HeaderBuilder {\n+  var version: Int = _\n+  var uid: Int = _\n+\n+  // Fields only available for EnvelopeBuffer\n+  var _senderActorRef: String = null\n+  var _senderActorRefIdx: Int = -1\n+  var _recipientActorRef: String = null\n+  var _recipientActorRefIdx: Int = -1\n+\n+  def senderActorRef_=(ref: String): Unit = {\n+    _senderActorRef = ref\n+    _senderActorRefIdx = compressionTable.compressActorRef(ref)\n+  }\n+\n+  def senderActorRef: String = {\n+    if (_senderActorRef ne null) _senderActorRef\n+    else {\n+      _senderActorRef = compressionTable.decompressActorRef(_senderActorRefIdx)\n+      _senderActorRef\n+    }\n+  }\n+\n+  def recipientActorRef_=(ref: String): Unit = {\n+    _recipientActorRef = ref\n+    _recipientActorRefIdx = compressionTable.compressActorRef(ref)\n+  }\n+\n+  def recipientActorRef: String = {\n+    if (_recipientActorRef ne null) _recipientActorRef\n+    else {\n+      _recipientActorRef = compressionTable.decompressActorRef(_recipientActorRefIdx)\n+      _recipientActorRef\n+    }\n+  }\n+\n+}\n+\n+/**\n+ * INTERNAL API\n+ */\n+private[remote] final class EnvelopeBuffer(val byteBuffer: ByteBuffer) {\n+  import EnvelopeBuffer._\n+\n+  def writeHeader(h: HeaderBuilder): Unit = {\n+    val header = h.asInstanceOf[HeaderBuilderImpl]\n+    byteBuffer.clear()\n+\n+    // Write fixed length parts\n+    byteBuffer.putInt(header.version)\n+    byteBuffer.putInt(header.uid)\n+\n+    // Write compressable, variable-length parts always to the actual position of the buffer\n+    // Write tag values explicitly in their proper offset\n+    byteBuffer.position(LiteralsSectionOffset)\n+\n+    // Serialize sender\n+    if (header._senderActorRefIdx != -1)\n+      byteBuffer.putInt(SenderActorRefTagOffset, header._senderActorRefIdx | TagTypeMask)\n+    else\n+      writeLiteral(SenderActorRefTagOffset, header.senderActorRef)\n+\n+    // Serialize recipient\n+    if (header._recipientActorRefIdx != -1)\n+      byteBuffer.putInt(RecipientActorRefTagOffset, header._recipientActorRefIdx | TagTypeMask)\n+    else\n+      writeLiteral(RecipientActorRefTagOffset, header.recipientActorRef)\n+  }\n+\n+  def parseHeader(h: HeaderBuilder): Unit = {\n+    val header = h.asInstanceOf[HeaderBuilderImpl]\n+    byteBuffer.flip()\n+\n+    // Read fixed length parts\n+    header.version = byteBuffer.getInt\n+    header.uid = byteBuffer.getInt\n+\n+    // Read compressable, variable-length parts always from the actual position of the buffer\n+    // Read tag values explicitly from their proper offset\n+    byteBuffer.position(LiteralsSectionOffset)\n+\n+    // Deserialize sender\n+    val senderTag = byteBuffer.getInt(SenderActorRefTagOffset)\n+    if ((senderTag & TagTypeMask) != 0) {\n+      val idx = senderTag & TagValueMask\n+      header._senderActorRef = null\n+      header._senderActorRefIdx = idx\n+    } else {\n+      header._senderActorRef = readLiteral()\n+    }\n+\n+    // Deserialize recipient\n+    val recipientTag = byteBuffer.getInt(RecipientActorRefTagOffset)\n+    if ((recipientTag & TagTypeMask) != 0) {\n+      val idx = recipientTag & TagValueMask\n+      header._recipientActorRef = null\n+      header._recipientActorRefIdx = idx\n+    } else {\n+      header._recipientActorRef = readLiteral()\n+    }\n+  }\n+\n+  private def readLiteral(): String = {\n+    val length = byteBuffer.getShort\n+    val bytes = Array.ofDim[Byte](length)\n+    byteBuffer.get(bytes)\n+    new String(bytes, UsAscii)\n+  }\n+\n+  private def writeLiteral(tagOffset: Int, literal: String): Unit = {\n+    require(literal.length < 65536, \"Literals longer than 65535 cannot be encoded in the envelope\")","path":"akka-remote/src/main/scala/akka/remote/artery/BufferPool.scala","position":290,"original_position":211,"commit_id":"50841cc7ad1b64ef001158817d4e3e2218b6fe3b","original_commit_id":"4e77e3ba57670782e11808615f4badfbee0aef79","user":{"login":"drewhk","id":932285,"avatar_url":"https://avatars.githubusercontent.com/u/932285?v=3","gravatar_id":"","url":"https://api.github.com/users/drewhk","html_url":"https://github.com/drewhk","followers_url":"https://api.github.com/users/drewhk/followers","following_url":"https://api.github.com/users/drewhk/following{/other_user}","gists_url":"https://api.github.com/users/drewhk/gists{/gist_id}","starred_url":"https://api.github.com/users/drewhk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drewhk/subscriptions","organizations_url":"https://api.github.com/users/drewhk/orgs","repos_url":"https://api.github.com/users/drewhk/repos","events_url":"https://api.github.com/users/drewhk/events{/privacy}","received_events_url":"https://api.github.com/users/drewhk/received_events","type":"User","site_admin":false},"body":"meh, stupid require. I think we should create our own version that does not allocate.","created_at":"2016-05-18T14:08:36Z","updated_at":"2016-05-18T14:08:36Z","html_url":"https://github.com/akka/akka/pull/20457#discussion_r63708980","pull_request_url":"https://api.github.com/repos/akka/akka/pulls/20457","_links":{"self":{"href":"https://api.github.com/repos/akka/akka/pulls/comments/63708980"},"html":{"href":"https://github.com/akka/akka/pull/20457#discussion_r63708980"},"pull_request":{"href":"https://api.github.com/repos/akka/akka/pulls/20457"}}},"pull_request":{"url":"https://api.github.com/repos/akka/akka/pulls/20457","id":69006340,"html_url":"https://github.com/akka/akka/pull/20457","diff_url":"https://github.com/akka/akka/pull/20457.diff","patch_url":"https://github.com/akka/akka/pull/20457.patch","issue_url":"https://api.github.com/repos/akka/akka/issues/20457","number":20457,"state":"open","locked":false,"title":"Buffer and header parsing support","user":{"login":"drewhk","id":932285,"avatar_url":"https://avatars.githubusercontent.com/u/932285?v=3","gravatar_id":"","url":"https://api.github.com/users/drewhk","html_url":"https://github.com/drewhk","followers_url":"https://api.github.com/users/drewhk/followers","following_url":"https://api.github.com/users/drewhk/following{/other_user}","gists_url":"https://api.github.com/users/drewhk/gists{/gist_id}","starred_url":"https://api.github.com/users/drewhk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drewhk/subscriptions","organizations_url":"https://api.github.com/users/drewhk/orgs","repos_url":"https://api.github.com/users/drewhk/repos","events_url":"https://api.github.com/users/drewhk/events{/privacy}","received_events_url":"https://api.github.com/users/drewhk/received_events","type":"User","site_admin":false},"body":"First stab at an efficient, ByteBuffer based, envelope codec that is allocation-free for compressed literals.\r\n\r\nNot all fields are there, and we need to do something about origin address.","created_at":"2016-05-05T13:26:14Z","updated_at":"2016-05-18T14:08:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"acd7abd21f44176997a4bb75ebea40b7f21926c4","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/akka/akka/pulls/20457/commits","review_comments_url":"https://api.github.com/repos/akka/akka/pulls/20457/comments","review_comment_url":"https://api.github.com/repos/akka/akka/pulls/comments{/number}","comments_url":"https://api.github.com/repos/akka/akka/issues/20457/comments","statuses_url":"https://api.github.com/repos/akka/akka/statuses/50841cc7ad1b64ef001158817d4e3e2218b6fe3b","head":{"label":"drewhk:wip-artery-envelope-buffers-drewhk","ref":"wip-artery-envelope-buffers-drewhk","sha":"50841cc7ad1b64ef001158817d4e3e2218b6fe3b","user":{"login":"drewhk","id":932285,"avatar_url":"https://avatars.githubusercontent.com/u/932285?v=3","gravatar_id":"","url":"https://api.github.com/users/drewhk","html_url":"https://github.com/drewhk","followers_url":"https://api.github.com/users/drewhk/followers","following_url":"https://api.github.com/users/drewhk/following{/other_user}","gists_url":"https://api.github.com/users/drewhk/gists{/gist_id}","starred_url":"https://api.github.com/users/drewhk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drewhk/subscriptions","organizations_url":"https://api.github.com/users/drewhk/orgs","repos_url":"https://api.github.com/users/drewhk/repos","events_url":"https://api.github.com/users/drewhk/events{/privacy}","received_events_url":"https://api.github.com/users/drewhk/received_events","type":"User","site_admin":false},"repo":{"id":4322312,"name":"akka","full_name":"drewhk/akka","owner":{"login":"drewhk","id":932285,"avatar_url":"https://avatars.githubusercontent.com/u/932285?v=3","gravatar_id":"","url":"https://api.github.com/users/drewhk","html_url":"https://github.com/drewhk","followers_url":"https://api.github.com/users/drewhk/followers","following_url":"https://api.github.com/users/drewhk/following{/other_user}","gists_url":"https://api.github.com/users/drewhk/gists{/gist_id}","starred_url":"https://api.github.com/users/drewhk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drewhk/subscriptions","organizations_url":"https://api.github.com/users/drewhk/orgs","repos_url":"https://api.github.com/users/drewhk/repos","events_url":"https://api.github.com/users/drewhk/events{/privacy}","received_events_url":"https://api.github.com/users/drewhk/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/drewhk/akka","description":"Akka Project","fork":true,"url":"https://api.github.com/repos/drewhk/akka","forks_url":"https://api.github.com/repos/drewhk/akka/forks","keys_url":"https://api.github.com/repos/drewhk/akka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/drewhk/akka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/drewhk/akka/teams","hooks_url":"https://api.github.com/repos/drewhk/akka/hooks","issue_events_url":"https://api.github.com/repos/drewhk/akka/issues/events{/number}","events_url":"https://api.github.com/repos/drewhk/akka/events","assignees_url":"https://api.github.com/repos/drewhk/akka/assignees{/user}","branches_url":"https://api.github.com/repos/drewhk/akka/branches{/branch}","tags_url":"https://api.github.com/repos/drewhk/akka/tags","blobs_url":"https://api.github.com/repos/drewhk/akka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/drewhk/akka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/drewhk/akka/git/refs{/sha}","trees_url":"https://api.github.com/repos/drewhk/akka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/drewhk/akka/statuses/{sha}","languages_url":"https://api.github.com/repos/drewhk/akka/languages","stargazers_url":"https://api.github.com/repos/drewhk/akka/stargazers","contributors_url":"https://api.github.com/repos/drewhk/akka/contributors","subscribers_url":"https://api.github.com/repos/drewhk/akka/subscribers","subscription_url":"https://api.github.com/repos/drewhk/akka/subscription","commits_url":"https://api.github.com/repos/drewhk/akka/commits{/sha}","git_commits_url":"https://api.github.com/repos/drewhk/akka/git/commits{/sha}","comments_url":"https://api.github.com/repos/drewhk/akka/comments{/number}","issue_comment_url":"https://api.github.com/repos/drewhk/akka/issues/comments{/number}","contents_url":"https://api.github.com/repos/drewhk/akka/contents/{+path}","compare_url":"https://api.github.com/repos/drewhk/akka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/drewhk/akka/merges","archive_url":"https://api.github.com/repos/drewhk/akka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/drewhk/akka/downloads","issues_url":"https://api.github.com/repos/drewhk/akka/issues{/number}","pulls_url":"https://api.github.com/repos/drewhk/akka/pulls{/number}","milestones_url":"https://api.github.com/repos/drewhk/akka/milestones{/number}","notifications_url":"https://api.github.com/repos/drewhk/akka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/drewhk/akka/labels{/name}","releases_url":"https://api.github.com/repos/drewhk/akka/releases{/id}","deployments_url":"https://api.github.com/repos/drewhk/akka/deployments","created_at":"2012-05-14T09:57:34Z","updated_at":"2015-02-17T12:40:08Z","pushed_at":"2016-05-18T13:53:39Z","git_url":"git://github.com/drewhk/akka.git","ssh_url":"git@github.com:drewhk/akka.git","clone_url":"https://github.com/drewhk/akka.git","svn_url":"https://github.com/drewhk/akka","homepage":"http://akka.io","size":190278,"stargazers_count":1,"watchers_count":1,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"akka:artery-dev","ref":"artery-dev","sha":"e36a13d48a50dc35371d97a944e226aa0a3a3be1","user":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","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":130013,"name":"akka","full_name":"akka/akka","owner":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","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/akka","description":"Akka Project","fork":false,"url":"https://api.github.com/repos/akka/akka","forks_url":"https://api.github.com/repos/akka/akka/forks","keys_url":"https://api.github.com/repos/akka/akka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akka/akka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akka/akka/teams","hooks_url":"https://api.github.com/repos/akka/akka/hooks","issue_events_url":"https://api.github.com/repos/akka/akka/issues/events{/number}","events_url":"https://api.github.com/repos/akka/akka/events","assignees_url":"https://api.github.com/repos/akka/akka/assignees{/user}","branches_url":"https://api.github.com/repos/akka/akka/branches{/branch}","tags_url":"https://api.github.com/repos/akka/akka/tags","blobs_url":"https://api.github.com/repos/akka/akka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akka/akka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akka/akka/git/refs{/sha}","trees_url":"https://api.github.com/repos/akka/akka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akka/akka/statuses/{sha}","languages_url":"https://api.github.com/repos/akka/akka/languages","stargazers_url":"https://api.github.com/repos/akka/akka/stargazers","contributors_url":"https://api.github.com/repos/akka/akka/contributors","subscribers_url":"https://api.github.com/repos/akka/akka/subscribers","subscription_url":"https://api.github.com/repos/akka/akka/subscription","commits_url":"https://api.github.com/repos/akka/akka/commits{/sha}","git_commits_url":"https://api.github.com/repos/akka/akka/git/commits{/sha}","comments_url":"https://api.github.com/repos/akka/akka/comments{/number}","issue_comment_url":"https://api.github.com/repos/akka/akka/issues/comments{/number}","contents_url":"https://api.github.com/repos/akka/akka/contents/{+path}","compare_url":"https://api.github.com/repos/akka/akka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akka/akka/merges","archive_url":"https://api.github.com/repos/akka/akka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akka/akka/downloads","issues_url":"https://api.github.com/repos/akka/akka/issues{/number}","pulls_url":"https://api.github.com/repos/akka/akka/pulls{/number}","milestones_url":"https://api.github.com/repos/akka/akka/milestones{/number}","notifications_url":"https://api.github.com/repos/akka/akka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akka/akka/labels{/name}","releases_url":"https://api.github.com/repos/akka/akka/releases{/id}","deployments_url":"https://api.github.com/repos/akka/akka/deployments","created_at":"2009-02-16T12:51:54Z","updated_at":"2016-05-18T13:26:20Z","pushed_at":"2016-05-18T13:53:39Z","git_url":"git://github.com/akka/akka.git","ssh_url":"git@github.com:akka/akka.git","clone_url":"https://github.com/akka/akka.git","svn_url":"https://github.com/akka/akka","homepage":"http://akka.io","size":238891,"stargazers_count":5519,"watchers_count":5519,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1714,"mirror_url":null,"open_issues_count":707,"forks":1714,"open_issues":707,"watchers":5519,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/akka/akka/pulls/20457"},"html":{"href":"https://github.com/akka/akka/pull/20457"},"issue":{"href":"https://api.github.com/repos/akka/akka/issues/20457"},"comments":{"href":"https://api.github.com/repos/akka/akka/issues/20457/comments"},"review_comments":{"href":"https://api.github.com/repos/akka/akka/pulls/20457/comments"},"review_comment":{"href":"https://api.github.com/repos/akka/akka/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/akka/akka/pulls/20457/commits"},"statuses":{"href":"https://api.github.com/repos/akka/akka/statuses/50841cc7ad1b64ef001158817d4e3e2218b6fe3b"}}}}