![JAR search and dependency download from the Maven repository](/logo.png)
io.reactors.debugger.DeltaDebugger.scala Maven / Gradle / Ivy
package io.reactors
package debugger
import io.reactors.common.UnrolledRing
import io.reactors.concurrent.Frame
import org.json4s._
import org.json4s.JsonDSL._
import scala.collection._
class DeltaDebugger(val system: ReactorSystem, val sessionuid: String) {
private val monitor = system.monitor
private val oldstate = new DeltaDebugger.State()
private var oldtimestamp = 0L
private var curstate: DeltaDebugger.State = null
private var curtimestamp = 0L
private val deltas = new UnrolledRing[DeltaDebugger.Delta]
private var pendingSends = mutable.Map[(Long, Long), Long]()
private val windowSize =
system.bundle.config.int("debug-api.delta-debugger.window-size")
{
monitor.synchronized {
for ((id, name, _) <- system.frames.values) {
oldstate.reactors(id) = name
}
}
curstate = oldstate.copy()
}
private def commitPendingSends() = monitor.synchronized {
if (pendingSends.nonEmpty) {
val delta = DeltaDebugger.EventsSent(pendingSends.toList.toMap)
deltas.enqueue(delta)
delta.apply(curstate)
curtimestamp += 1
pendingSends.clear()
}
}
private def enqueue(delta: DeltaDebugger.Delta) {
monitor.synchronized {
commitPendingSends()
deltas.enqueue(delta)
delta.apply(curstate)
curtimestamp += 1
while (deltas.size > windowSize) {
val oldestdelta = deltas.dequeue()
oldestdelta.apply(oldstate)
oldtimestamp += 1
}
}
}
def state(suid: String, reqts: Long): JObject = {
monitor.synchronized {
commitPendingSends()
if (suid != sessionuid || reqts < oldtimestamp) {
DeltaDebugger.toJson(sessionuid, curtimestamp, Some(curstate.copy()), None)
} else {
val newdeltas = mutable.Buffer[DeltaDebugger.Delta]()
var ts = oldtimestamp
for (delta <- deltas) {
ts += 1
if (ts > reqts) newdeltas += delta
}
DeltaDebugger.toJson(sessionuid, curtimestamp, None, Some(newdeltas))
}
}
}
def isEnabled = true
def eventSent[@spec(Int, Long, Double) T](c: Channel[T], x: T) {
monitor.synchronized {
val f = Reactor.currentFrame
val cuid = c match {
case c: Channel.Local[_] => Some(c.frame.uid)
case _ => None
}
if (f != null && cuid.nonEmpty) {
val senderUid = f.uid
val targetUid = cuid.get
val pair = (senderUid, targetUid)
val count = pendingSends.getOrElse(pair, 0L)
pendingSends(pair) = count + 1
}
}
}
def eventDelivered[@spec(Int, Long, Double) T](c: Channel[T], x: T) {}
def reactorStarted(f: Frame) = enqueue(DeltaDebugger.ReactorStarted(f))
def reactorScheduled(r: Reactor[_]) {}
def reactorPreempted(r: Reactor[_]) {}
def reactorDied(r: Reactor[_]) = enqueue(DeltaDebugger.ReactorDied(r))
def reactorTerminated(r: Reactor[_]) = enqueue(DeltaDebugger.ReactorTerminated(r))
def connectorOpened[T](c: Connector[T]) = enqueue(DeltaDebugger.ConnectorOpened(c))
def connectorSealed[T](c: Connector[T]) = enqueue(DeltaDebugger.ConnectorSealed(c))
def log(x: Any) {}
}
object DeltaDebugger {
def toJson(
suid: String, ts: Long, state: Option[State], deltas: Option[Seq[Delta]]
): JObject = (
("ts" -> ts) ~
("suid" -> suid) ~
("state" -> state.map(_.toJson)) ~
("deltas" -> deltas.map(_.map(_.toJson)))
)
private def sendsToArray(sends: Map[(Long, Long), Long]): JArray =
JArray(sends.map {
case (pair, count) => JArray(List(pair._1, pair._2, count))
} toList)
class State() {
val reactors = mutable.Map[Long, String]()
val sends = mutable.Map[(Long, Long), Long]()
def copy(): State = {
val s = new State()
for ((id, name) <- reactors) s.reactors(id) = name
for ((pair, count) <- sends) s.sends(pair) = count
s
}
def toJson: JValue = {
val rs = for ((uid, r) <- reactors) yield
JField(uid.toString, JObject("uid" -> uid, "name" -> JString(r)))
("reactors" -> JObject(rs.toList)) ~
("sends" -> sendsToArray(sends))
}
}
abstract class Delta {
def toJson: JValue
def apply(s: State): Unit
}
case class ReactorStarted(f: Frame) extends Delta {
def toJson = JArray(List("start", f.uid, f.name))
def apply(s: State) {
s.reactors(f.uid) = f.name
}
}
case class ReactorDied(r: Reactor[_]) extends Delta {
def toJson = JArray(List("die", r.uid))
def apply(s: State) {
}
}
case class ReactorTerminated(r: Reactor[_]) extends Delta {
def toJson = JArray(List("term", r.uid))
def apply(s: State) {
s.reactors.remove(r.uid)
}
}
case class ConnectorOpened(c: Connector[_]) extends Delta {
def toJson = JArray(List("open", c.uid))
def apply(s: State) {
}
}
case class ConnectorSealed(c: Connector[_]) extends Delta {
def toJson = JArray(List("seal", c.uid))
def apply(s: State) {
}
}
case class EventsSent(sends: Map[(Long, Long), Long]) extends Delta {
def toJson = {
val sendsArray = sendsToArray(sends)
JArray(List("sent", sendsArray))
}
def apply(s: State) {
for ((pair, count) <- sends) {
val current = s.sends.getOrElse(pair, 0L)
s.sends(pair) = current + count
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy