Skip to content
laforge49 edited this page Sep 15, 2011 · 8 revisions

Given the RandomIO service, we should be able to read and write serialized blocks. We will implement two operations: Writeit, which writes an IncDesString set to the string "abc" and Readit, which returns the string held by the IncDesString. The block that is serialized and written to disk is set to the IncDesString. Here are the messages:

case class Writeit()
case class Readit()

We will write a driver which binds these messages:

class Driver extends Actor {
  bind(classOf[Writeit], writeit)
  bind(classOf[Readit], readit)
  ...
}

Here then is the code for the writeit method:

def writeit(msg: AnyRef, rf: Any => Unit) {
  val block = Block(mailbox)
  block.setSystemServices(systemServices)
  val incDesString = IncDesString(null)
  val blockLength = IncDesInt(null)
  val results = new Results
  val chain = new Chain(results)
  chain.op(block, Set(null, incDesString))
  chain.op(incDesString, Set(null, "abc"))
  chain.op(block, Bytes(), "bytes")
  chain.op(blockLength,
    Unit => {
      val blkLen = results("bytes").asInstanceOf[Array[Byte]].length
      Set(null, blkLen)
    })
  chain.op(blockLength, Bytes(), "header")
  chain.op(systemServices,
    Unit => WriteBytes(0L, results("header").asInstanceOf[Array[Byte]]))
  chain.op(systemServices,
    Unit => WriteBytes(4L, results("bytes").asInstanceOf[Array[Byte]]))
  this(chain)(rf)
}

The above code does the following:

  1. Create a Block, block, with the same mailbox and system services as the driver.
  2. Create an IncDesString, incDesString to hold the string.
  3. Create an IncDesInt, blockLength, for serializing the length of the block.
  4. Set block to incDesString. The Block now contains the IncDesString.
  5. Set incDesString to "abc".
  6. Serialize block.
  7. Set blockLength to the length of the serialized block.
  8. Serialize blockLength.
  9. Write the serialized blockLength to the file.
  10. Write the serialized block to the file.

And here is the code for the readit method:

def readit(msg: AnyRef, rf: Any => Unit) {
  val block = Block(mailbox)
  block.setSystemServices(systemServices)
  val blockLength = IncDesInt(null)
  val results = new Results
  val chain = new Chain(results)
  chain.op(systemServices, ReadBytes(0L, 4), "header")
  chain.op(blockLength,
    Unit => {
      blockLength.load(results("header").asInstanceOf[Array[Byte]])
      Value()
    }, "length")
  chain.op(systemServices,
    Unit => {
      val blkLen = results("length").asInstanceOf[Int]
      ReadBytes(4L, blkLen)
    }, "bytes")
  chain.op(block,
    Unit => {
      block.load(results("bytes").asInstanceOf[Array[Byte]])
      Value()
    }, "incDesString")
  chain.op(Unit => results("incDesString").asInstanceOf[Actor], Value())
  this(chain)(rf)
}

The above code does the following:

  1. Create a Block, Block, with the same mailbox and system services as the driver.
  2. Create an IncDesInt, blockLength, for deserializing the length of the serialized block.
  3. Read the serialized block length.
  4. Load blockLength with the serialized block length and extract its value, an Int.
  5. Read the serialized block.
  6. Load the block with the serialized block and extract its value, an IncDesString.
  7. Extract the value of the IncDesString and return its value.

Here is the code for testing writeit:

val dbName = "BlockIOTest.db"
val file = new java.io.File(dbName)
file.delete
val properties = new Properties
properties.put("dbPathname", dbName)
val systemServices = SystemServices(new BlockIOComponentFactory, properties = properties)
val driver = new Driver
driver.setMailbox(systemServices.mailbox)
driver.setSystemServices(systemServices)
Future(driver, Writeit())
systemServices.close

The above code does the following:

  1. Delete the file, BlockIOTest.db, if it exists.
  2. Assign the file pathname to the dbPathname property.
  3. Create the system services with the BlockIO service.
  4. Create the driver, initialize it, and send it a Writeit message.
  5. Close the system services actor, which in turn closes the file.

The final piece of code tests Readit:

val dbName = "BlockIOTest.db"
val properties = new Properties
properties.put("dbPathname", dbName)
val systemServices = SystemServices(new BlockIOComponentFactory, properties = properties)
val driver = new Driver
driver.setMailbox(systemServices.mailbox)
driver.setSystemServices(systemServices)
Future(driver, Readit()) must be equalTo("abc")
systemServices.close

The above code does the following:

  1. Assign the dbPathname property the pathname of the file.
  2. Create a system services actor with the BlockIO service.
  3. Create and initialize the driver.
  4. Send the Readit message to the driver. The result must be "abc".
  5. Close the system services, and consequently close the file.

BlockIOTest

tutorial

Clone this wiki locally