{"action":"created","comment":{"url":"https://api.github.com/repos/rchain/rchain/pulls/comments/186594386","pull_request_review_id":118202465,"id":186594386,"diff_hunk":"@@ -0,0 +1,411 @@\n+package coop.rchain.rspace.pure\n+\n+import java.nio.ByteBuffer\n+\n+import cats.data.{ReaderT}\n+import coop.rchain.catscontrib.Capture\n+import coop.rchain.rspace.Serialize\n+import coop.rchain.rspace.internal._\n+import org.lmdbjava.{CursorIterator, KeyRange, Txn}\n+import java.security.MessageDigest\n+\n+import cats.Monad\n+import coop.rchain.rspace.util.{ignore, withResource}\n+import coop.rchain.rspace.internal.scodecs._\n+import scodec.Codec\n+import scodec.bits.{BitVector, ByteVector}\n+\n+import scala.collection.immutable.Seq\n+import coop.rchain.rspace.util\n+\n+import scala.collection.JavaConverters._\n+\n+object StoreInstances {\n+\n+  implicit def storeLMDB[F[_]: Monad, C, P, A, K](\n+      implicit\n+      serializeC: Serialize[C],\n+      serializeP: Serialize[P],\n+      serializeA: Serialize[A],\n+      serializeK: Serialize[K],\n+      captureF: Capture[F]): Store[ReaderT[F, LMDBContext, ?], C, P, A, K] =\n+    new Store[ReaderT[F, LMDBContext, ?], C, P, A, K] {\n+\n+      private[this] def capture[X](x: X): F[X] = captureF.capture(x)\n+\n+      type T = Txn[ByteBuffer]\n+\n+      def createTxnRead(): ReaderT[F, LMDBContext, T] =\n+        ReaderT(ctx => capture(ctx.env.txnRead))\n+\n+      def createTxnWrite(): ReaderT[F, LMDBContext, T] =\n+        ReaderT(ctx => capture(ctx.env.txnWrite))\n+\n+      def withTxn[R](txn: T)(f: T => R): R =\n+        try {\n+          val ret: R = f(txn)\n+          txn.commit()\n+          ret\n+        } catch {\n+          case ex: Throwable =>\n+            txn.abort()\n+            throw ex\n+        } finally {\n+          txn.close()\n+        }\n+\n+      type H = ByteBuffer\n+\n+      private[this] def hashChannelsInner(channels: Seq[C]): ByteBuffer =\n+        hashBytes(toByteBuffer(channels))\n+\n+      override def hashChannels(channels: Seq[C]): ReaderT[F, LMDBContext, ByteBuffer] =\n+        ReaderT.pure(hashChannelsInner(channels))\n+\n+      override def getChannels(txn: T, channelsHash: H): ReaderT[F, LMDBContext, Seq[C]] =\n+        ReaderT(ctx =>\n+          capture {\n+            Option(ctx.dbKeys.get(txn, channelsHash))\n+              .map(fromByteBuffer[C])\n+              .getOrElse(Seq.empty[C])\n+        })\n+\n+      private[rspace] def putChannels(txn: T, channels: Seq[C]): ReaderT[F, LMDBContext, H] =\n+        ReaderT(ctx =>\n+          capture {\n+            val channelsBytes = toByteBuffer(channels)\n+            val channelsHash  = hashBytes(channelsBytes)\n+            ctx.dbKeys.put(txn, channelsHash, channelsBytes)\n+            channelsHash\n+        })\n+\n+      private[this] def readDatumByteses(\n+          txn: T,\n+          channelsHash: H): ReaderT[F, LMDBContext, Option[Seq[DatumBytes]]] =\n+        ReaderT(ctx =>\n+          capture {\n+            Option(ctx.dbData.get(txn, channelsHash)).map(fromByteBuffer(_, datumBytesesCodec))\n+        })\n+\n+      private[this] def writeDatumByteses(txn: T,\n+                                          channelsHash: H,\n+                                          values: Seq[DatumBytes]): ReaderT[F, LMDBContext, Unit] =\n+        ReaderT(ctx =>\n+          capture {\n+            if (values.nonEmpty) {\n+              ctx.dbData.put(txn, channelsHash, toByteBuffer(values, datumBytesesCodec))\n+            } else {\n+              ctx.dbData.delete(txn, channelsHash)\n+              collectGarbage(txn, channelsHash, dataCollected = true)\n+            }\n+            ()\n+        })\n+\n+      override def getData(txn: T, channels: Seq[C]): ReaderT[F, LMDBContext, Seq[Datum[A]]] =\n+        hashChannels(channels)\n+          .flatMap(channelsHash => readDatumByteses(txn, channelsHash))\n+          .map(\n+            datumByteses =>\n+              datumByteses\n+                .map(_.map(bytes => Datum(fromByteVector[A](bytes.datumBytes), bytes.persist)))\n+                .getOrElse(Seq.empty[Datum[A]]))\n+\n+      override def putDatum(txn: T,\n+                            channels: Seq[C],\n+                            datum: Datum[A]): ReaderT[F, LMDBContext, Unit] =\n+        putChannels(txn, channels).map(channelsHash => {","path":"rspace/src/main/scala/coop/rchain/rspace/pure/StoreInstances.scala","position":116,"original_position":116,"commit_id":"3b7e55eee9cb39cb15fbacb0760505d1e52d6733","original_commit_id":"3b7e55eee9cb39cb15fbacb0760505d1e52d6733","user":{"login":"henrytill","id":6430643,"avatar_url":"https://avatars3.githubusercontent.com/u/6430643?v=4","gravatar_id":"","url":"https://api.github.com/users/henrytill","html_url":"https://github.com/henrytill","followers_url":"https://api.github.com/users/henrytill/followers","following_url":"https://api.github.com/users/henrytill/following{/other_user}","gists_url":"https://api.github.com/users/henrytill/gists{/gist_id}","starred_url":"https://api.github.com/users/henrytill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/henrytill/subscriptions","organizations_url":"https://api.github.com/users/henrytill/orgs","repos_url":"https://api.github.com/users/henrytill/repos","events_url":"https://api.github.com/users/henrytill/events{/privacy}","received_events_url":"https://api.github.com/users/henrytill/received_events","type":"User","site_admin":false},"body":"Using a for-comprehension really cleans this up:\r\n\r\n```scala\r\n        for {\r\n          channelsHash    <- putChannels(txn, channels)\r\n          oldDatumByteses <- readDatumByteses(txn, channelsHash)\r\n          newDatumBytes   = DatumBytes(toByteVector(datum.a), datum.persist)\r\n        } yield {\r\n          writeDatumByteses(txn,\r\n                            channelsHash,\r\n                            newDatumBytes +: oldDatumByteses.getOrElse(Seq.empty[DatumBytes]))\r\n        }\r\n```","created_at":"2018-05-08T01:15:26Z","updated_at":"2018-05-08T01:39:36Z","html_url":"https://github.com/rchain/rchain/pull/706#discussion_r186594386","pull_request_url":"https://api.github.com/repos/rchain/rchain/pulls/706","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/rchain/rchain/pulls/comments/186594386"},"html":{"href":"https://github.com/rchain/rchain/pull/706#discussion_r186594386"},"pull_request":{"href":"https://api.github.com/repos/rchain/rchain/pulls/706"}}},"pull_request":{"url":"https://api.github.com/repos/rchain/rchain/pulls/706","id":186373344,"html_url":"https://github.com/rchain/rchain/pull/706","diff_url":"https://github.com/rchain/rchain/pull/706.diff","patch_url":"https://github.com/rchain/rchain/pull/706.patch","issue_url":"https://api.github.com/repos/rchain/rchain/issues/706","number":706,"state":"open","locked":false,"title":"CORE-455 LMDB instance of Store type class (rspace)","user":{"login":"ys-pyrofex","id":34450115,"avatar_url":"https://avatars2.githubusercontent.com/u/34450115?v=4","gravatar_id":"","url":"https://api.github.com/users/ys-pyrofex","html_url":"https://github.com/ys-pyrofex","followers_url":"https://api.github.com/users/ys-pyrofex/followers","following_url":"https://api.github.com/users/ys-pyrofex/following{/other_user}","gists_url":"https://api.github.com/users/ys-pyrofex/gists{/gist_id}","starred_url":"https://api.github.com/users/ys-pyrofex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ys-pyrofex/subscriptions","organizations_url":"https://api.github.com/users/ys-pyrofex/orgs","repos_url":"https://api.github.com/users/ys-pyrofex/repos","events_url":"https://api.github.com/users/ys-pyrofex/events{/privacy}","received_events_url":"https://api.github.com/users/ys-pyrofex/received_events","type":"User","site_admin":false},"body":"## Overview\r\nMTL-style API for RSpace\r\n\r\n### Does this PR relate to an RChain JIRA issue? \r\nhttps://rchain.atlassian.net/browse/CORE-455","created_at":"2018-05-07T14:48:11Z","updated_at":"2018-05-08T01:39:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6c987548a5567fc5cf9b8b3293804eadae0b8e4f","assignee":{"login":"henrytill","id":6430643,"avatar_url":"https://avatars3.githubusercontent.com/u/6430643?v=4","gravatar_id":"","url":"https://api.github.com/users/henrytill","html_url":"https://github.com/henrytill","followers_url":"https://api.github.com/users/henrytill/followers","following_url":"https://api.github.com/users/henrytill/following{/other_user}","gists_url":"https://api.github.com/users/henrytill/gists{/gist_id}","starred_url":"https://api.github.com/users/henrytill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/henrytill/subscriptions","organizations_url":"https://api.github.com/users/henrytill/orgs","repos_url":"https://api.github.com/users/henrytill/repos","events_url":"https://api.github.com/users/henrytill/events{/privacy}","received_events_url":"https://api.github.com/users/henrytill/received_events","type":"User","site_admin":false},"assignees":[{"login":"henrytill","id":6430643,"avatar_url":"https://avatars3.githubusercontent.com/u/6430643?v=4","gravatar_id":"","url":"https://api.github.com/users/henrytill","html_url":"https://github.com/henrytill","followers_url":"https://api.github.com/users/henrytill/followers","following_url":"https://api.github.com/users/henrytill/following{/other_user}","gists_url":"https://api.github.com/users/henrytill/gists{/gist_id}","starred_url":"https://api.github.com/users/henrytill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/henrytill/subscriptions","organizations_url":"https://api.github.com/users/henrytill/orgs","repos_url":"https://api.github.com/users/henrytill/repos","events_url":"https://api.github.com/users/henrytill/events{/privacy}","received_events_url":"https://api.github.com/users/henrytill/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/rchain/rchain/pulls/706/commits","review_comments_url":"https://api.github.com/repos/rchain/rchain/pulls/706/comments","review_comment_url":"https://api.github.com/repos/rchain/rchain/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rchain/rchain/issues/706/comments","statuses_url":"https://api.github.com/repos/rchain/rchain/statuses/3b7e55eee9cb39cb15fbacb0760505d1e52d6733","head":{"label":"ys-pyrofex:CORE-455","ref":"CORE-455","sha":"3b7e55eee9cb39cb15fbacb0760505d1e52d6733","user":{"login":"ys-pyrofex","id":34450115,"avatar_url":"https://avatars2.githubusercontent.com/u/34450115?v=4","gravatar_id":"","url":"https://api.github.com/users/ys-pyrofex","html_url":"https://github.com/ys-pyrofex","followers_url":"https://api.github.com/users/ys-pyrofex/followers","following_url":"https://api.github.com/users/ys-pyrofex/following{/other_user}","gists_url":"https://api.github.com/users/ys-pyrofex/gists{/gist_id}","starred_url":"https://api.github.com/users/ys-pyrofex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ys-pyrofex/subscriptions","organizations_url":"https://api.github.com/users/ys-pyrofex/orgs","repos_url":"https://api.github.com/users/ys-pyrofex/repos","events_url":"https://api.github.com/users/ys-pyrofex/events{/privacy}","received_events_url":"https://api.github.com/users/ys-pyrofex/received_events","type":"User","site_admin":false},"repo":{"id":116134750,"name":"rchain","full_name":"ys-pyrofex/rchain","owner":{"login":"ys-pyrofex","id":34450115,"avatar_url":"https://avatars2.githubusercontent.com/u/34450115?v=4","gravatar_id":"","url":"https://api.github.com/users/ys-pyrofex","html_url":"https://github.com/ys-pyrofex","followers_url":"https://api.github.com/users/ys-pyrofex/followers","following_url":"https://api.github.com/users/ys-pyrofex/following{/other_user}","gists_url":"https://api.github.com/users/ys-pyrofex/gists{/gist_id}","starred_url":"https://api.github.com/users/ys-pyrofex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ys-pyrofex/subscriptions","organizations_url":"https://api.github.com/users/ys-pyrofex/orgs","repos_url":"https://api.github.com/users/ys-pyrofex/repos","events_url":"https://api.github.com/users/ys-pyrofex/events{/privacy}","received_events_url":"https://api.github.com/users/ys-pyrofex/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ys-pyrofex/rchain","description":null,"fork":true,"url":"https://api.github.com/repos/ys-pyrofex/rchain","forks_url":"https://api.github.com/repos/ys-pyrofex/rchain/forks","keys_url":"https://api.github.com/repos/ys-pyrofex/rchain/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ys-pyrofex/rchain/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ys-pyrofex/rchain/teams","hooks_url":"https://api.github.com/repos/ys-pyrofex/rchain/hooks","issue_events_url":"https://api.github.com/repos/ys-pyrofex/rchain/issues/events{/number}","events_url":"https://api.github.com/repos/ys-pyrofex/rchain/events","assignees_url":"https://api.github.com/repos/ys-pyrofex/rchain/assignees{/user}","branches_url":"https://api.github.com/repos/ys-pyrofex/rchain/branches{/branch}","tags_url":"https://api.github.com/repos/ys-pyrofex/rchain/tags","blobs_url":"https://api.github.com/repos/ys-pyrofex/rchain/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ys-pyrofex/rchain/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ys-pyrofex/rchain/git/refs{/sha}","trees_url":"https://api.github.com/repos/ys-pyrofex/rchain/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ys-pyrofex/rchain/statuses/{sha}","languages_url":"https://api.github.com/repos/ys-pyrofex/rchain/languages","stargazers_url":"https://api.github.com/repos/ys-pyrofex/rchain/stargazers","contributors_url":"https://api.github.com/repos/ys-pyrofex/rchain/contributors","subscribers_url":"https://api.github.com/repos/ys-pyrofex/rchain/subscribers","subscription_url":"https://api.github.com/repos/ys-pyrofex/rchain/subscription","commits_url":"https://api.github.com/repos/ys-pyrofex/rchain/commits{/sha}","git_commits_url":"https://api.github.com/repos/ys-pyrofex/rchain/git/commits{/sha}","comments_url":"https://api.github.com/repos/ys-pyrofex/rchain/comments{/number}","issue_comment_url":"https://api.github.com/repos/ys-pyrofex/rchain/issues/comments{/number}","contents_url":"https://api.github.com/repos/ys-pyrofex/rchain/contents/{+path}","compare_url":"https://api.github.com/repos/ys-pyrofex/rchain/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ys-pyrofex/rchain/merges","archive_url":"https://api.github.com/repos/ys-pyrofex/rchain/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ys-pyrofex/rchain/downloads","issues_url":"https://api.github.com/repos/ys-pyrofex/rchain/issues{/number}","pulls_url":"https://api.github.com/repos/ys-pyrofex/rchain/pulls{/number}","milestones_url":"https://api.github.com/repos/ys-pyrofex/rchain/milestones{/number}","notifications_url":"https://api.github.com/repos/ys-pyrofex/rchain/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ys-pyrofex/rchain/labels{/name}","releases_url":"https://api.github.com/repos/ys-pyrofex/rchain/releases{/id}","deployments_url":"https://api.github.com/repos/ys-pyrofex/rchain/deployments","created_at":"2018-01-03T12:31:46Z","updated_at":"2018-04-30T14:28:52Z","pushed_at":"2018-05-07T16:25:34Z","git_url":"git://github.com/ys-pyrofex/rchain.git","ssh_url":"git@github.com:ys-pyrofex/rchain.git","clone_url":"https://github.com/ys-pyrofex/rchain.git","svn_url":"https://github.com/ys-pyrofex/rchain","homepage":null,"size":9278,"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},"forks":0,"open_issues":0,"watchers":0,"default_branch":"dev2"}},"base":{"label":"rchain:dev","ref":"dev","sha":"dde0cd79c39d2c76a32de8b3da4fe6f82e19d336","user":{"login":"rchain","id":20671765,"avatar_url":"https://avatars0.githubusercontent.com/u/20671765?v=4","gravatar_id":"","url":"https://api.github.com/users/rchain","html_url":"https://github.com/rchain","followers_url":"https://api.github.com/users/rchain/followers","following_url":"https://api.github.com/users/rchain/following{/other_user}","gists_url":"https://api.github.com/users/rchain/gists{/gist_id}","starred_url":"https://api.github.com/users/rchain/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rchain/subscriptions","organizations_url":"https://api.github.com/users/rchain/orgs","repos_url":"https://api.github.com/users/rchain/repos","events_url":"https://api.github.com/users/rchain/events{/privacy}","received_events_url":"https://api.github.com/users/rchain/received_events","type":"Organization","site_admin":false},"repo":{"id":84493691,"name":"rchain","full_name":"rchain/rchain","owner":{"login":"rchain","id":20671765,"avatar_url":"https://avatars0.githubusercontent.com/u/20671765?v=4","gravatar_id":"","url":"https://api.github.com/users/rchain","html_url":"https://github.com/rchain","followers_url":"https://api.github.com/users/rchain/followers","following_url":"https://api.github.com/users/rchain/following{/other_user}","gists_url":"https://api.github.com/users/rchain/gists{/gist_id}","starred_url":"https://api.github.com/users/rchain/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rchain/subscriptions","organizations_url":"https://api.github.com/users/rchain/orgs","repos_url":"https://api.github.com/users/rchain/repos","events_url":"https://api.github.com/users/rchain/events{/privacy}","received_events_url":"https://api.github.com/users/rchain/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rchain/rchain","description":null,"fork":false,"url":"https://api.github.com/repos/rchain/rchain","forks_url":"https://api.github.com/repos/rchain/rchain/forks","keys_url":"https://api.github.com/repos/rchain/rchain/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rchain/rchain/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rchain/rchain/teams","hooks_url":"https://api.github.com/repos/rchain/rchain/hooks","issue_events_url":"https://api.github.com/repos/rchain/rchain/issues/events{/number}","events_url":"https://api.github.com/repos/rchain/rchain/events","assignees_url":"https://api.github.com/repos/rchain/rchain/assignees{/user}","branches_url":"https://api.github.com/repos/rchain/rchain/branches{/branch}","tags_url":"https://api.github.com/repos/rchain/rchain/tags","blobs_url":"https://api.github.com/repos/rchain/rchain/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rchain/rchain/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rchain/rchain/git/refs{/sha}","trees_url":"https://api.github.com/repos/rchain/rchain/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rchain/rchain/statuses/{sha}","languages_url":"https://api.github.com/repos/rchain/rchain/languages","stargazers_url":"https://api.github.com/repos/rchain/rchain/stargazers","contributors_url":"https://api.github.com/repos/rchain/rchain/contributors","subscribers_url":"https://api.github.com/repos/rchain/rchain/subscribers","subscription_url":"https://api.github.com/repos/rchain/rchain/subscription","commits_url":"https://api.github.com/repos/rchain/rchain/commits{/sha}","git_commits_url":"https://api.github.com/repos/rchain/rchain/git/commits{/sha}","comments_url":"https://api.github.com/repos/rchain/rchain/comments{/number}","issue_comment_url":"https://api.github.com/repos/rchain/rchain/issues/comments{/number}","contents_url":"https://api.github.com/repos/rchain/rchain/contents/{+path}","compare_url":"https://api.github.com/repos/rchain/rchain/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rchain/rchain/merges","archive_url":"https://api.github.com/repos/rchain/rchain/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rchain/rchain/downloads","issues_url":"https://api.github.com/repos/rchain/rchain/issues{/number}","pulls_url":"https://api.github.com/repos/rchain/rchain/pulls{/number}","milestones_url":"https://api.github.com/repos/rchain/rchain/milestones{/number}","notifications_url":"https://api.github.com/repos/rchain/rchain/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rchain/rchain/labels{/name}","releases_url":"https://api.github.com/repos/rchain/rchain/releases{/id}","deployments_url":"https://api.github.com/repos/rchain/rchain/deployments","created_at":"2017-03-09T22:15:35Z","updated_at":"2018-05-07T21:53:07Z","pushed_at":"2018-05-08T00:21:13Z","git_url":"git://github.com/rchain/rchain.git","ssh_url":"git@github.com:rchain/rchain.git","clone_url":"https://github.com/rchain/rchain.git","svn_url":"https://github.com/rchain/rchain","homepage":null,"size":9206,"stargazers_count":288,"watchers_count":288,"language":"Scala","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":79,"mirror_url":null,"archived":false,"open_issues_count":15,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":79,"open_issues":15,"watchers":288,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rchain/rchain/pulls/706"},"html":{"href":"https://github.com/rchain/rchain/pull/706"},"issue":{"href":"https://api.github.com/repos/rchain/rchain/issues/706"},"comments":{"href":"https://api.github.com/repos/rchain/rchain/issues/706/comments"},"review_comments":{"href":"https://api.github.com/repos/rchain/rchain/pulls/706/comments"},"review_comment":{"href":"https://api.github.com/repos/rchain/rchain/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rchain/rchain/pulls/706/commits"},"statuses":{"href":"https://api.github.com/repos/rchain/rchain/statuses/3b7e55eee9cb39cb15fbacb0760505d1e52d6733"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"henrytill"}}