diff options
author | Grzegorz Kossakowski <grek@google.com> | 2009-09-21 20:36:48 -0700 |
---|---|---|
committer | Grzegorz Kossakowski <grek@google.com> | 2009-09-21 20:36:48 -0700 |
commit | 679080789acdea738e6c802a1caf90f507da5c97 (patch) | |
tree | 930e4a1c1cd5ff51d998d349a77412329d5f80ff | |
parent | 60899f7d9e134d780f4ba34a4a97b982ce1fb640 (diff) | |
download | gimd-679080789acdea738e6c802a1caf90f507da5c97.tar.gz |
Added modifyAndReturn method to Database trait.
Method modifyAndReturn allows to modify a database and return back a value
once transaction is committed.
Made modify method to be implemented in terms of modifyAndReturn.
Signed-off-by: Grzegorz Kossakowski <grek@google.com>
Change-Id: Ic5cedf499eebcd23e5563c0e0c729b5e4452bb06
-rw-r--r-- | src/main/scala/com/google/gimd/Database.scala | 19 | ||||
-rw-r--r-- | src/main/scala/com/google/gimd/jgit/JGitDatabase.scala | 28 | ||||
-rw-r--r-- | src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala | 16 |
3 files changed, 46 insertions, 17 deletions
diff --git a/src/main/scala/com/google/gimd/Database.scala b/src/main/scala/com/google/gimd/Database.scala index 9047606..5570e63 100644 --- a/src/main/scala/com/google/gimd/Database.scala +++ b/src/main/scala/com/google/gimd/Database.scala @@ -33,21 +33,32 @@ trait Database { latestSnapshot.query(ft, p).map(_._2) /** + * <p>The same as modifyAndReturn method but always returns Unit.</p> + * + * @see #modifyAndReturn + */ + @throws(classOf[GimdException]) + def modify(modification: Snapshot => DatabaseModification): Unit = + modifyAndReturn{ s => (modification(s), ()) } + + /** * <p>Method that allows modification of latest Snapshot of Database.</p> * * <p>For single DatabaseModification derived from Snapshot READ COMMITTED level of isolation is * guaranteed. <strong>The level of isolation might be changed in a future but only to level which * provides better isolation.</strong></p> * - * @param modification A function <code>Snapshot => DatabaseModification</code> that should + * @param modification A function <code>Snapshot => (DatabaseModification, T)</code> that should * follow referential transparency rule as it can be called an arbitrary - * number of times. Result of this function is an object that specifies what - * kind of modifications should be performed on top of passed Snapshot. + * number of times. Result of this function is a tuple consisting of an object + * that specifies what kind of modifications should be performed on top of + * passed Snapshot and arbitrary value of type T that is returned as result. + * @returns a value returned by modification function * * @throws GimdException */ @throws(classOf[GimdException]) - def modify(modification: Snapshot => DatabaseModification) + def modifyAndReturn[T](modification: Snapshot => (DatabaseModification, T)): T /** * Factory method returning latest Snapshot of Database. diff --git a/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala b/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala index ad40c9f..bd100ab 100644 --- a/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala +++ b/src/main/scala/com/google/gimd/jgit/JGitDatabase.scala @@ -53,19 +53,21 @@ final class JGitDatabase(branch: JGitBranch) extends Database { } } - def modify(modification: Snapshot => DatabaseModification) = { - val successful = try { + def modifyAndReturn[T](modification: Snapshot => (DatabaseModification, T)): T = { + val result = try { retry(MERGE_RETRIES) { val snapshot = latestSnapshot - val dbModification = modification(snapshot) - applyModification(dbModification, snapshot.commit) + val (dbModification, result) = modification(snapshot) + applyModification(dbModification, snapshot.commit) match { + case true => Some(result) + case false => None + } } } catch { case e: IOException => throw new JGitDatabaseException(branch, e) } - if (!successful) - throw new JGitMergeRetriesExceededException(branch, MERGE_RETRIES) + result getOrElse { throw new JGitMergeRetriesExceededException(branch, MERGE_RETRIES) } } def applyModification(modification: DatabaseModification, onto: RevCommit): @@ -156,15 +158,15 @@ final class JGitDatabase(branch: JGitBranch) extends Database { } private def tryMerging(commitToBeMerged: ObjectId) = - retry(MERGE_RETRIES)(merge(commitToBeMerged)) + retry(MERGE_RETRIES){ Some(merge(commitToBeMerged)) } getOrElse false - private def retry(howManyTimes: Int)(what: => Boolean): Boolean = + private def retry[T](howManyTimes: Int)(what: => Option[T]): Option[T] = if (howManyTimes > 0) - if (what) - true - else - retry(howManyTimes-1)(what) + what match { + case Some(x) => Some(x) + case None => retry(howManyTimes-1)(what) + } else - false + None } diff --git a/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala b/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala index d2f7c48..5cad05c 100644 --- a/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala +++ b/src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala @@ -189,6 +189,22 @@ final class JGitDatabaseTestCase extends AbstractJGitTestCase { assertEquals(expected, foundFiles.map(_.userObject)) } + @Test + def emptyModificationAndReturn { + val expected = 100 + + val path = "sm/first.sm" + val blobId = writeMessage(SimpleMessageType, SimpleMessage("first", 1)) + + commit(List(path -> blobId)) + + val db = new JGitDatabase(masterBranch) + + val result = db.modifyAndReturn { _ => (DatabaseModification.empty, expected) } + + assertEquals(expected, result) + } + private def commit(files: List[(String, ObjectId)]) { val treeId = addFiles(files) val commitId = createCommit("Test", treeId) |