Alexander Botero-Lowry
unread,Mar 6, 2009, 3:32:41 AM3/6/09Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Naga Users
Hi guys,
Today I started looking for an asynchronous memcache client in Java,
and all I could find was these huge byzantine monstrosities (which is
of course the norm for java libraries), and so I decided that I should
give a go to writing my own using NIO, but when I went to look at how
to use the NIO api I went back to looking for a memcache client :D
After some more exploring down that avenue I went back to the NIO
street ,and I found a few frameworks that seemed to make it more
reasonable but they were all massive, and then I ran into Naga!
I wrote up a little wrapper around naga for Scala to make it a little
more language appropriate, and I've just started to write my little
Memcache library.
I still have a long way to go, and I need to cleanup the apis a bunch
more, but I think I will have a nice, albeit simple wrapper for Scala
when I'm done (and a nice Memcache library).
Thanks for the great project!
++++++ Naga Wrapper for scala and a really horrible and incomplete
client impl ontop of it +++++
object TCPMagic {
sealed trait TCPAction {
val socket: NIOSocket
}
case class ConnectionOpened(socket: NIOSocket) extends TCPAction
case class PacketReceived(socket: NIOSocket, bytes: Array[Byte])
extends TCPAction
case class ConnectionBroken(socket: NIOSocket, exc: Exception)
extends TCPAction
trait TCPMatcher { def match_action(match_on: TCPAction):Unit }
def run(host: String, port: Int, client: TCPMatcher) {
val service = new NIOService();
val sock = service.openSocket(host, port)
sock listen(new SocketObserver() {
def connectionOpened(socket: NIOSocket) {
client.match_action(ConnectionOpened(socket))
}
def packetReceived(socket: NIOSocket, bytes: Array[Byte]) {
client.match_action(PacketReceived(socket, bytes))
}
def connectionBroken(socket: NIOSocket, exc: Exception) {
client.match_action(ConnectionBroken(socket, exc))
}
})
while (true) {
service.selectBlocking();
}
}
}
class MemcacheClient extends TCPMagic.TCPMatcher {
import TCPMagic._
trait MemcacheCommand {
val msg: String
val callback: (Any => Unit)
queue = queue enqueue this
if (sock != null && handling == null) next_command
def handle(data: Array[Byte]) : Unit
}
var sock: NIOSocket = null;
val EOL = "\r\n";
var queue: Queue[MemcacheCommand] = new Queue()
var handling: MemcacheCommand = null;
protected def next_command() {
if (!queue.isEmpty) {
// XXX fulhack, maybe a nicer way to do this
val tpl = queue dequeue
var cmd = tpl._1
queue = tpl._2
handling = cmd
sock.write(cmd.msg.getBytes)
}
}
class GetCommand(msgx: String, callbackx: (Any=>Unit)) extends
MemcacheCommand {
val msg:String = msgx
val callback:(Any => Unit) = callbackx
def handle(data: Array[Byte]) = {
callback(new String(data))
}
}
def get(key: String, callback: (Any => Unit)) {
new GetCommand("get "+key+EOL, callback)
}
def match_action(match_on: TCPAction) {
match_on match {
case PacketReceived(s, b) => {
handling.handle(b)
handling = null
next_command
}
case ConnectionBroken(s, e) => println("Broken")
case ConnectionOpened(s) => {
println("connection")
sock = s;
next_command
}
}
}
}
val mcc = new MemcacheClient()
mcc.get("x", { a => println("OUT "+a) })
TCPMagic.run("127.0.0.1", 11211, mcc)