Fixed problem with PersistentVector.slice : Issue #161

This commit is contained in:
Debasish Ghosh 2010-05-01 11:40:57 +05:30
parent ac7cd72e99
commit 058cbc15ce
7 changed files with 52 additions and 23 deletions

View file

@ -218,9 +218,9 @@ trait PersistentVector[T] extends IndexedSeq[T] with Transactional with Committa
else storage.getVectorStorageEntryFor(uuid, index)
}
override def slice(start: Int, count: Int): IndexedSeq[T] = slice(Some(start), None, count)
override def slice(start: Int, finish: Int): IndexedSeq[T] = slice(Some(start), Some(finish))
def slice(start: Option[Int], finish: Option[Int], count: Int): IndexedSeq[T] = {
def slice(start: Option[Int], finish: Option[Int], count: Int = 0): IndexedSeq[T] = {
val buffer = new scala.collection.mutable.ArrayBuffer[T]
storage.getVectorStorageRangeFor(uuid, start, finish, count).foreach(buffer.append(_))
buffer

View file

@ -248,9 +248,17 @@ private[akka] object MongoStorageBackend extends
dbo.get(VALUE).asInstanceOf[JList[AnyRef]]
}
val s = if (start.isDefined) start.get else 0
val cnt =
if (finish.isDefined) {
val f = finish.get
if (f >= s) (f - s) else count
}
else count
// pick the subrange and make a Scala list
val l =
List(o.subList(start.get, start.get + count).toArray: _*)
List(o.subList(s, s + cnt).toArray: _*)
for(e <- l)
yield serializer.in[AnyRef](e.asInstanceOf[Array[Byte]])

View file

@ -1,9 +1,8 @@
package se.scalablesolutions.akka.persistence.mongo
import junit.framework.TestCase
import org.junit.{Test, Before}
import org.junit.Assert._
import org.scalatest.junit.JUnitSuite
import _root_.dispatch.json.{JsNumber, JsValue}
import _root_.dispatch.json.Js._
@ -27,6 +26,7 @@ case class Balance(accountNo: String)
case class Debit(accountNo: String, amount: BigInt, failer: Actor)
case class MultiDebit(accountNo: String, amounts: List[BigInt], failer: Actor)
case class Credit(accountNo: String, amount: BigInt)
case class Log(start: Int, finish: Int)
case object LogSize
class BankAccountActor extends Transactor {
@ -88,6 +88,9 @@ class BankAccountActor extends Transactor {
case LogSize =>
reply(txnLog.length.asInstanceOf[AnyRef])
case Log(start, finish) =>
reply(txnLog.slice(start, finish))
}
}
@ -98,7 +101,7 @@ class BankAccountActor extends Transactor {
}
}
class MongoPersistentActorSpec extends TestCase {
class MongoPersistentActorSpec extends JUnitSuite {
@Test
def testSuccessfulDebit = {
val bactor = new BankAccountActor
@ -121,7 +124,14 @@ class MongoPersistentActorSpec extends TestCase {
val JsNumber(b2) = (bactor !! Balance("a-123")).get.asInstanceOf[JsValue]
assertEquals(BigInt(1000), BigInt(b2.intValue))
assertEquals(7, (bactor !! LogSize).get)
assert(7 == (bactor !! LogSize).get.asInstanceOf[Int])
import scala.collection.mutable.ArrayBuffer
assert((bactor !! Log(0, 7)).get.asInstanceOf[ArrayBuffer[String]].size == 7)
assert((bactor !! Log(0, 0)).get.asInstanceOf[ArrayBuffer[String]].size == 0)
assert((bactor !! Log(1, 2)).get.asInstanceOf[ArrayBuffer[String]].size == 1)
assert((bactor !! Log(6, 7)).get.asInstanceOf[ArrayBuffer[String]].size == 1)
assert((bactor !! Log(0, 1)).get.asInstanceOf[ArrayBuffer[String]].size == 1)
}
@Test
@ -144,7 +154,7 @@ class MongoPersistentActorSpec extends TestCase {
assertEquals(BigInt(5000), BigInt(b1.intValue))
// should not count the failed one
assertEquals(3, (bactor !! LogSize).get)
assert(3 == (bactor !! LogSize).get.asInstanceOf[Int])
}
@Test
@ -167,6 +177,6 @@ class MongoPersistentActorSpec extends TestCase {
assertEquals(BigInt(5000), BigInt(b1.intValue))
// should not count the failed one
assertEquals(3, (bactor !! LogSize).get)
assert(3 == (bactor !! LogSize).get.asInstanceOf[Int])
}
}

View file

@ -1,20 +1,19 @@
package se.scalablesolutions.akka.persistence.mongo
import junit.framework.TestCase
import org.junit.{Test, Before}
import org.junit.Assert._
import org.scalatest.junit.JUnitSuite
import _root_.dispatch.json._
import _root_.dispatch.json.Js._
import java.util.NoSuchElementException
@scala.reflect.BeanInfo case class Foo(no: Int, name: String)
class MongoStorageSpec extends TestCase {
class MongoStorageSpec extends JUnitSuite {
val changeSetV = new scala.collection.mutable.ArrayBuffer[AnyRef]
val changeSetM = new scala.collection.mutable.HashMap[AnyRef, AnyRef]
override def setUp = {
@Before def initialize() = {
MongoStorageBackend.coll.drop
}

View file

@ -228,17 +228,21 @@ private [akka] object RedisStorageBackend extends
def getVectorStorageRangeFor(name: String, start: Option[Int], finish: Option[Int], count: Int): List[Array[Byte]] = withErrorHandling {
/**
* <tt>count</tt> is the max number of results to return. Start with
* <tt>start</tt> or 0 (if <tt>start</tt> is not defined) and go until
* you hit <tt>finish</tt> or <tt>count</tt>.
* if <tt>start</tt> and <tt>finish</tt> both are defined, ignore <tt>count</tt> and
* report the range [start, finish)
* if <tt>start</tt> is not defined, assume <tt>start</tt> = 0
* if <tt>start</tt> == 0 and <tt>finish</tt> == 0, return an empty collection
*/
val s = if (start.isDefined) start.get else 0
val cnt =
if (finish.isDefined) {
val f = finish.get
if (f >= s) Math.min(count, (f - s)) else count
// if (f >= s) Math.min(count, (f - s)) else count
if (f >= s) (f - s) else count
}
else count
if (s == 0 && cnt == 0) List()
else
db.lrange(new String(encode(name.getBytes)), s, s + cnt - 1) match {
case None =>
throw new NoSuchElementException(name + " does not have elements in the range specified")

View file

@ -1,7 +1,5 @@
package se.scalablesolutions.akka.persistence.redis
import junit.framework.TestCase
import org.junit.{Test, Before}
import org.junit.Assert._
@ -24,6 +22,7 @@ case class Balance(accountNo: String)
case class Debit(accountNo: String, amount: BigInt, failer: Actor)
case class MultiDebit(accountNo: String, amounts: List[BigInt], failer: Actor)
case class Credit(accountNo: String, amount: BigInt)
case class Log(start: Int, finish: Int)
case object LogSize
class AccountActor extends Transactor {
@ -83,6 +82,9 @@ class AccountActor extends Transactor {
case LogSize =>
reply(txnLog.length.asInstanceOf[AnyRef])
case Log(start, finish) =>
reply(txnLog.slice(start, finish))
}
}
@ -94,7 +96,8 @@ class AccountActor extends Transactor {
}
}
class RedisPersistentActorSpec extends TestCase {
import org.scalatest.junit.JUnitSuite
class RedisPersistentActorSpec extends JUnitSuite {
@Test
def testSuccessfulDebit = {
val bactor = new AccountActor
@ -113,6 +116,12 @@ class RedisPersistentActorSpec extends TestCase {
val c: Int = (bactor !! LogSize).get
assertTrue(7 == c)
import scala.collection.mutable.ArrayBuffer
assert((bactor !! Log(0, 7)).get.asInstanceOf[ArrayBuffer[String]].size == 7)
assert((bactor !! Log(0, 0)).get.asInstanceOf[ArrayBuffer[String]].size == 0)
assert((bactor !! Log(1, 2)).get.asInstanceOf[ArrayBuffer[String]].size == 1)
assert((bactor !! Log(6, 7)).get.asInstanceOf[ArrayBuffer[String]].size == 1)
assert((bactor !! Log(0, 1)).get.asInstanceOf[ArrayBuffer[String]].size == 1)
}
@Test

View file

@ -1,7 +1,5 @@
package se.scalablesolutions.akka.persistence.redis
import junit.framework.TestCase
import org.junit.{Test, Before}
import org.junit.Assert._
@ -50,7 +48,8 @@ class QueueActor extends Transactor {
}
}
class RedisPersistentQSpec extends TestCase {
import org.scalatest.junit.JUnitSuite
class RedisPersistentQSpec extends JUnitSuite {
@Test
def testSuccessfulNQ = {
val qa = new QueueActor