2009-08-17 20:46:05 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright 2007 WorldWide Conferencing, LLC
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
2009-09-02 09:10:21 +02:00
|
|
|
package se.scalablesolutions.akka.util
|
2009-08-17 18:42:41 +02:00
|
|
|
|
|
|
|
|
import java.util.concurrent._
|
2009-09-02 09:10:21 +02:00
|
|
|
import actor.{OneForOneStrategy, Actor}
|
2009-09-04 08:03:34 +02:00
|
|
|
import config.ScalaConfig._
|
2009-08-17 18:42:41 +02:00
|
|
|
|
|
|
|
|
import org.scala_tools.javautils.Imports._
|
|
|
|
|
|
|
|
|
|
case object UnSchedule
|
|
|
|
|
case class SchedulerException(msg: String, e: Throwable) extends RuntimeException(msg, e)
|
|
|
|
|
|
|
|
|
|
/**
|
2009-08-17 20:39:14 +02:00
|
|
|
* Rework of David Pollak's ActorPing class in the Lift Project
|
|
|
|
|
* which is licensed under the Apache 2 License.
|
2009-08-17 18:42:41 +02:00
|
|
|
*/
|
|
|
|
|
class ScheduleActor(val receiver: Actor, val future: ScheduledFuture[AnyRef]) extends Actor with Logging {
|
2009-09-02 12:26:27 +02:00
|
|
|
lifeCycleConfig = Some(LifeCycle(Permanent, 100))
|
|
|
|
|
|
2009-08-17 18:42:41 +02:00
|
|
|
def receive: PartialFunction[Any, Unit] = {
|
|
|
|
|
case UnSchedule =>
|
|
|
|
|
Scheduler.stopSupervising(this)
|
|
|
|
|
future.cancel(true)
|
|
|
|
|
stop
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object Scheduler extends Actor {
|
|
|
|
|
private var service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory)
|
|
|
|
|
private val schedulers = new ConcurrentHashMap[Actor, Actor]
|
|
|
|
|
faultHandler = Some(OneForOneStrategy(5, 5000))
|
|
|
|
|
trapExit = true
|
2009-08-17 20:39:14 +02:00
|
|
|
start
|
2009-08-17 18:42:41 +02:00
|
|
|
|
|
|
|
|
def schedule(receiver: Actor, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit) = {
|
|
|
|
|
try {
|
|
|
|
|
startLink(new ScheduleActor(
|
|
|
|
|
receiver,
|
|
|
|
|
service.scheduleAtFixedRate(new java.lang.Runnable {
|
|
|
|
|
def run = receiver ! message;
|
|
|
|
|
}, initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]]))
|
|
|
|
|
} catch {
|
|
|
|
|
case e => throw SchedulerException(message + " could not be scheduled on " + receiver, e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def restart = service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory)
|
|
|
|
|
|
|
|
|
|
def stopSupervising(actor: Actor) = {
|
|
|
|
|
unlink(actor)
|
|
|
|
|
schedulers.remove(actor)
|
|
|
|
|
}
|
2009-08-17 20:46:05 +02:00
|
|
|
|
2009-08-17 18:42:41 +02:00
|
|
|
override def shutdown = {
|
|
|
|
|
schedulers.values.asScala.foreach(_ ! UnSchedule)
|
|
|
|
|
service.shutdown
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def receive: PartialFunction[Any, Unit] = {
|
|
|
|
|
case _ => {} // ignore all messages
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private object SchedulerThreadFactory extends ThreadFactory {
|
|
|
|
|
private var count = 0
|
|
|
|
|
val threadFactory = Executors.defaultThreadFactory()
|
2009-08-17 20:46:05 +02:00
|
|
|
|
2009-08-17 18:42:41 +02:00
|
|
|
def newThread(r: Runnable): Thread = {
|
|
|
|
|
val thread = threadFactory.newThread(r)
|
|
|
|
|
thread.setName("Scheduler-" + count)
|
|
|
|
|
thread.setDaemon(true)
|
|
|
|
|
thread
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-17 20:39:14 +02:00
|
|
|
|
|
|
|
|
|