-
Notifications
You must be signed in to change notification settings - Fork 1
File Loader
laforge49 edited this page Dec 9, 2011
·
2 revisions
Any time you do I/O you will likely want to do it asynchronously, as otherwise the current thread will be tied up until the operation completes and any number of Actors will also become unresponsive.
The LoadFile actor is a good case in point. This actor reads (hopefully short) files but remains oblivious to how it is being run (asynchronously/synchronously):
case class LoadFile(file: File)
class FileLoader
extends Actor {
bind(classOf[LoadFile], loadFile)
def loadFile(msg: AnyRef, rf: Any => Unit) {
val file = msg.asInstanceOf[LoadFile].file
val size = file.length
val fis = new FileInputStream(file)
val dis = new DataInputStream(fis)
val bytes = new Array[Byte](size.asInstanceOf[Int])
dis.readFully(bytes)
rf(bytes)
}
}
By defining a component and component factory for FileLoader, we can turn FileLoader into an asynchronous services that can be part of a system services composite:
class FileLoaderComponent(actor: Actor)
extends Component(actor) {
val fileLoader = new FileLoader
bindMessageLogic(classOf[LoadFile], new Forward(fileLoader))
override def open {
super.open
fileLoader.setExchangeMessenger(systemServices.newAsyncMailbox)
}
}
class FileLoaderComponentFactory
extends ComponentFactory {
override def instantiate(actor: Actor) = new FileLoaderComponent(actor)
}
Here's the test which includes the LoadFile service:
val systemServices = SystemServices(new FileLoaderComponentFactory)
try {
val shortFileLoader = new ShortFileLoader
shortFileLoader.setExchangeMessenger(systemServices.newAsyncMailbox)
val bytes = Future(shortFileLoader, DoIt()).asInstanceOf[Array[Byte]]
val bais = new ByteArrayInputStream(bytes)
val isr = new InputStreamReader(bais)
val br = new BufferedReader(isr)
val line = br.readLine
println(line)
} finally {
systemServices.close
}
And here is the driver which uses the service:
case class DoIt()
class ShortFileLoader
extends Actor {
bind(classOf[DoIt], doit)
def doit(msg: AnyRef, rf: Any => Unit) {
val cwd = new File(".")
println("cwd = " + cwd.getCanonicalPath)
val file = new File("aShortTestFile.txt")
println("test file exists = " + file.exists)
systemServices(LoadFile(file))(rf)
}
}