summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grek@google.com>2009-09-21 20:36:48 -0700
committerGrzegorz Kossakowski <grek@google.com>2009-09-21 20:36:48 -0700
commit679080789acdea738e6c802a1caf90f507da5c97 (patch)
tree930e4a1c1cd5ff51d998d349a77412329d5f80ff
parent60899f7d9e134d780f4ba34a4a97b982ce1fb640 (diff)
downloadgimd-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.scala19
-rw-r--r--src/main/scala/com/google/gimd/jgit/JGitDatabase.scala28
-rw-r--r--src/test/scala/com/google/gimd/jgit/JGitDatabaseTestCase.scala16
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)