merged osgi-refactoring and sbt branch
This commit is contained in:
commit
073c0cbe72
74 changed files with 740 additions and 363 deletions
|
|
@ -1,15 +1,17 @@
|
||||||
package se.scalablesolutions.akka.remote
|
package se.scalablesolutions.akka.cluster.jgroups
|
||||||
|
|
||||||
import org.jgroups.{JChannel, View => JG_VIEW, Address, Message => JG_MSG, ExtendedMembershipListener, Receiver}
|
import org.jgroups.{JChannel, View => JG_VIEW, Address, Message => JG_MSG, ExtendedMembershipListener, Receiver}
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.remote.ClusterActor._
|
||||||
|
import se.scalablesolutions.akka.remote.BasicClusterActor
|
||||||
|
|
||||||
|
import org.scala_tools.javautils.Imports._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clustering support via JGroups.
|
* Clustering support via JGroups.
|
||||||
* @Author Viktor Klang
|
* @Author Viktor Klang
|
||||||
*/
|
*/
|
||||||
class JGroupsClusterActor extends BasicClusterActor {
|
class JGroupsClusterActor extends BasicClusterActor {
|
||||||
import ClusterActor._
|
|
||||||
import org.scala_tools.javautils.Imports._
|
|
||||||
|
|
||||||
type ADDR_T = Address
|
type ADDR_T = Address
|
||||||
|
|
||||||
@volatile private var isActive = false
|
@volatile private var isActive = false
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,16 @@
|
||||||
/**
|
/**
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
package se.scalablesolutions.akka.remote
|
package se.scalablesolutions.akka.cluster.shoal
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config.config
|
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
import com.sun.enterprise.ee.cms.core.{CallBack,
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
GMSConstants,
|
import se.scalablesolutions.akka.remote.{ClusterActor, BasicClusterActor, RemoteServer}
|
||||||
GMSFactory,
|
|
||||||
GroupManagementService,
|
import com.sun.enterprise.ee.cms.core._
|
||||||
MessageSignal,
|
import com.sun.enterprise.ee.cms.impl.client._
|
||||||
Signal,
|
|
||||||
GMSException,
|
|
||||||
SignalAcquireException,
|
|
||||||
SignalReleaseException,
|
|
||||||
JoinNotificationSignal,
|
|
||||||
FailureSuspectedSignal,
|
|
||||||
FailureNotificationSignal }
|
|
||||||
import com.sun.enterprise.ee.cms.impl.client.{FailureNotificationActionFactoryImpl,
|
|
||||||
FailureSuspectedActionFactoryImpl,
|
|
||||||
JoinNotificationActionFactoryImpl,
|
|
||||||
MessageActionFactoryImpl,
|
|
||||||
PlannedShutdownActionFactoryImpl
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Clustering support via Shoal.
|
* Clustering support via Shoal.
|
||||||
*/
|
*/
|
||||||
|
|
@ -67,9 +54,9 @@ class ShoalClusterActor extends BasicClusterActor {
|
||||||
* Adds callbacks and boots up the cluster
|
* Adds callbacks and boots up the cluster
|
||||||
*/
|
*/
|
||||||
protected def createGMS : GroupManagementService = {
|
protected def createGMS : GroupManagementService = {
|
||||||
|
val g = GMSFactory
|
||||||
val g = GMSFactory.startGMSModule(serverName,name, GroupManagementService.MemberType.CORE, properties()).asInstanceOf[GroupManagementService]
|
.startGMSModule(serverName,name, GroupManagementService.MemberType.CORE, properties())
|
||||||
|
.asInstanceOf[GroupManagementService]
|
||||||
val callback = createCallback
|
val callback = createCallback
|
||||||
g.addActionFactory(new JoinNotificationActionFactoryImpl(callback))
|
g.addActionFactory(new JoinNotificationActionFactoryImpl(callback))
|
||||||
g.addActionFactory(new FailureSuspectedActionFactoryImpl(callback))
|
g.addActionFactory(new FailureSuspectedActionFactoryImpl(callback))
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.comet
|
package se.scalablesolutions.akka.comet
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.{Actor}
|
import se.scalablesolutions.akka.actor.Actor
|
||||||
import se.scalablesolutions.akka.remote.{Cluster}
|
import se.scalablesolutions.akka.remote.Cluster
|
||||||
import scala.reflect.{BeanProperty}
|
import scala.reflect.BeanProperty
|
||||||
import org.atmosphere.cpr.{BroadcastFilter, ClusterBroadcastFilter, Broadcaster}
|
import org.atmosphere.cpr.{BroadcastFilter, ClusterBroadcastFilter, Broadcaster}
|
||||||
|
|
||||||
sealed trait ClusterCometMessageType
|
sealed trait ClusterCometMessageType
|
||||||
case class ClusterCometBroadcast(val name : String, val msg : AnyRef) extends ClusterCometMessageType
|
case class ClusterCometBroadcast(name: String, msg: AnyRef) extends ClusterCometMessageType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables explicit clustering of Atmosphere (Comet) resources
|
* Enables explicit clustering of Atmosphere (Comet) resources
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka
|
package se.scalablesolutions.akka.comet
|
||||||
|
|
||||||
import com.sun.grizzly.http.SelectorThread
|
import com.sun.grizzly.http.SelectorThread
|
||||||
import com.sun.grizzly.http.servlet.ServletAdapter
|
import com.sun.grizzly.http.servlet.ServletAdapter
|
||||||
import com.sun.grizzly.standalone.StaticStreamAlgorithm
|
import com.sun.grizzly.standalone.StaticStreamAlgorithm
|
||||||
|
|
||||||
import javax.ws.rs.core.UriBuilder
|
import javax.ws.rs.core.UriBuilder
|
||||||
import se.scalablesolutions.akka.comet.AkkaServlet
|
|
||||||
import se.scalablesolutions.akka.actor.BootableActorLoaderService
|
import se.scalablesolutions.akka.actor.BootableActorLoaderService
|
||||||
import se.scalablesolutions.akka.util.{Bootable,Logging}
|
import se.scalablesolutions.akka.util.{Bootable, Logging}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the Akka Comet Support (load/unload)
|
* Handles the Akka Comet Support (load/unload)
|
||||||
|
|
@ -19,16 +19,17 @@ import se.scalablesolutions.akka.util.{Bootable,Logging}
|
||||||
trait BootableCometActorService extends Bootable with Logging {
|
trait BootableCometActorService extends Bootable with Logging {
|
||||||
self : BootableActorLoaderService =>
|
self : BootableActorLoaderService =>
|
||||||
|
|
||||||
import Config._
|
import config.Config._
|
||||||
|
|
||||||
val REST_HOSTNAME = config.getString("akka.rest.hostname", "localhost")
|
val REST_HOSTNAME = config.getString("akka.rest.hostname", "localhost")
|
||||||
val REST_URL = "http://" + REST_HOSTNAME
|
val REST_URL = "http://" + REST_HOSTNAME
|
||||||
val REST_PORT = config.getInt("akka.rest.port", 9998)
|
val REST_PORT = config.getInt("akka.rest.port", 9998)
|
||||||
|
|
||||||
protected var jerseySelectorThread: Option[SelectorThread] = None
|
protected var jerseySelectorThread: Option[SelectorThread] = None
|
||||||
|
|
||||||
abstract override def onLoad = {
|
abstract override def onLoad = {
|
||||||
super.onLoad
|
super.onLoad
|
||||||
if(config.getBool("akka.rest.service", true)){
|
if (config.getBool("akka.rest.service", true)) {
|
||||||
|
|
||||||
val uri = UriBuilder.fromUri(REST_URL).port(REST_PORT).build()
|
val uri = UriBuilder.fromUri(REST_URL).port(REST_PORT).build()
|
||||||
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.actor
|
package se.scalablesolutions.akka.actor
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config._
|
|
||||||
import se.scalablesolutions.akka.dispatch._
|
import se.scalablesolutions.akka.dispatch._
|
||||||
|
import se.scalablesolutions.akka.config.Config._
|
||||||
import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy}
|
import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy}
|
||||||
import se.scalablesolutions.akka.config.ScalaConfig._
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import se.scalablesolutions.akka.stm.Transaction._
|
import se.scalablesolutions.akka.stm.Transaction._
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ package se.scalablesolutions.akka.actor
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
|
||||||
import se.scalablesolutions.akka.util.{Bootable,Logging}
|
import se.scalablesolutions.akka.util.{Bootable, Logging}
|
||||||
import se.scalablesolutions.akka.Config._
|
import se.scalablesolutions.akka.config.Config._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles all modules in the deploy directory (load and unload)
|
* Handles all modules in the deploy directory (load and unload)
|
||||||
|
|
@ -31,11 +31,7 @@ trait BootableActorLoaderService extends Bootable with Logging {
|
||||||
val toDeploy = for (f <- DEPLOY_DIR.listFiles().toArray.toList.asInstanceOf[List[File]]) yield f.toURL
|
val toDeploy = for (f <- DEPLOY_DIR.listFiles().toArray.toList.asInstanceOf[List[File]]) yield f.toURL
|
||||||
log.info("Deploying applications from [%s]: [%s]", DEPLOY, toDeploy.toArray.toList)
|
log.info("Deploying applications from [%s]: [%s]", DEPLOY, toDeploy.toArray.toList)
|
||||||
new URLClassLoader(toDeploy.toArray, ClassLoader.getSystemClassLoader)
|
new URLClassLoader(toDeploy.toArray, ClassLoader.getSystemClassLoader)
|
||||||
} else if (getClass.getClassLoader.getResourceAsStream("aop.xml") ne null) {
|
} else getClass.getClassLoader)
|
||||||
getClass.getClassLoader
|
|
||||||
} else throw new IllegalStateException(
|
|
||||||
"AKKA_HOME is not defined and akka-<version>.jar can not be found on the classpath; aborting...")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract override def onLoad = {
|
abstract override def onLoad = {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import java.util.concurrent._
|
||||||
|
|
||||||
import se.scalablesolutions.akka.config.ScalaConfig._
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy}
|
import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy}
|
||||||
import se.scalablesolutions.akka.util.{Logging}
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
import org.scala_tools.javautils.Imports._
|
import org.scala_tools.javautils.Imports._
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka
|
package se.scalablesolutions.akka.config
|
||||||
|
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ package se.scalablesolutions.akka.config
|
||||||
|
|
||||||
import scala.collection.mutable.HashSet
|
import scala.collection.mutable.HashSet
|
||||||
|
|
||||||
import util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
object ConfiguratorRepository extends Logging {
|
object ConfiguratorRepository extends Logging {
|
||||||
|
|
||||||
|
|
|
||||||
234
akka-core/src/main/scala/config/SupervisionConfig.scala
Normal file
234
akka-core/src/main/scala/config/SupervisionConfig.scala
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.scalablesolutions.akka.config
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.actor.Actor
|
||||||
|
import se.scalablesolutions.akka.dispatch.MessageDispatcher
|
||||||
|
|
||||||
|
sealed abstract class FaultHandlingStrategy
|
||||||
|
case class AllForOneStrategy(maxNrOfRetries: Int, withinTimeRange: Int) extends FaultHandlingStrategy
|
||||||
|
case class OneForOneStrategy(maxNrOfRetries: Int, withinTimeRange: Int) extends FaultHandlingStrategy
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration classes - not to be used as messages.
|
||||||
|
*
|
||||||
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||||
|
*/
|
||||||
|
object ScalaConfig {
|
||||||
|
sealed abstract class ConfigElement
|
||||||
|
|
||||||
|
abstract class Server extends ConfigElement
|
||||||
|
abstract class FailOverScheme extends ConfigElement
|
||||||
|
abstract class Scope extends ConfigElement
|
||||||
|
|
||||||
|
case class SupervisorConfig(restartStrategy: RestartStrategy, worker: List[Server]) extends Server
|
||||||
|
|
||||||
|
class Supervise(val actor: Actor, val lifeCycle: LifeCycle, _remoteAddress: RemoteAddress) extends Server {
|
||||||
|
val remoteAddress: Option[RemoteAddress] = if (_remoteAddress eq null) None else Some(_remoteAddress)
|
||||||
|
}
|
||||||
|
object Supervise {
|
||||||
|
def apply(actor: Actor, lifeCycle: LifeCycle, remoteAddress: RemoteAddress) = new Supervise(actor, lifeCycle, remoteAddress)
|
||||||
|
def apply(actor: Actor, lifeCycle: LifeCycle) = new Supervise(actor, lifeCycle, null)
|
||||||
|
def unapply(supervise: Supervise) = Some((supervise.actor, supervise.lifeCycle, supervise.remoteAddress))
|
||||||
|
}
|
||||||
|
|
||||||
|
case class RestartStrategy(
|
||||||
|
scheme: FailOverScheme,
|
||||||
|
maxNrOfRetries: Int,
|
||||||
|
withinTimeRange: Int,
|
||||||
|
trapExceptions: List[Class[_ <: Throwable]]) extends ConfigElement
|
||||||
|
|
||||||
|
case object AllForOne extends FailOverScheme
|
||||||
|
case object OneForOne extends FailOverScheme
|
||||||
|
|
||||||
|
case class LifeCycle(scope: Scope, callbacks: Option[RestartCallbacks]) extends ConfigElement
|
||||||
|
object LifeCycle {
|
||||||
|
def apply(scope: Scope) = new LifeCycle(scope, None)
|
||||||
|
}
|
||||||
|
case class RestartCallbacks(preRestart: String, postRestart: String) {
|
||||||
|
if ((preRestart eq null) || (postRestart eq null)) throw new IllegalArgumentException("Restart callback methods can't be null")
|
||||||
|
}
|
||||||
|
|
||||||
|
case object Permanent extends Scope
|
||||||
|
case object Temporary extends Scope
|
||||||
|
|
||||||
|
case class RemoteAddress(val hostname: String, val port: Int) extends ConfigElement
|
||||||
|
|
||||||
|
class Component(_intf: Class[_],
|
||||||
|
val target: Class[_],
|
||||||
|
val lifeCycle: LifeCycle,
|
||||||
|
val timeout: Int,
|
||||||
|
val transactionRequired: Boolean,
|
||||||
|
_dispatcher: MessageDispatcher, // optional
|
||||||
|
_remoteAddress: RemoteAddress // optional
|
||||||
|
) extends Server {
|
||||||
|
val intf: Option[Class[_]] = if (_intf eq null) None else Some(_intf)
|
||||||
|
val dispatcher: Option[MessageDispatcher] = if (_dispatcher eq null) None else Some(_dispatcher)
|
||||||
|
val remoteAddress: Option[RemoteAddress] = if (_remoteAddress eq null) None else Some(_remoteAddress)
|
||||||
|
}
|
||||||
|
object Component {
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, false, null, null)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, false, null, null)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, false, dispatcher, null)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, false, dispatcher, null)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, false, null, remoteAddress)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, false, null, remoteAddress)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, false, dispatcher, remoteAddress)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, false, dispatcher, remoteAddress)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, transactionRequired, null, null)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, transactionRequired, null, null)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, transactionRequired, dispatcher, null)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, transactionRequired, dispatcher, null)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, transactionRequired, null, remoteAddress)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, transactionRequired, null, remoteAddress)
|
||||||
|
|
||||||
|
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(intf, target, lifeCycle, timeout, transactionRequired, dispatcher, remoteAddress)
|
||||||
|
|
||||||
|
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) =
|
||||||
|
new Component(null, target, lifeCycle, timeout, transactionRequired, dispatcher, remoteAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||||
|
*/
|
||||||
|
object JavaConfig {
|
||||||
|
import scala.reflect.BeanProperty
|
||||||
|
|
||||||
|
sealed abstract class ConfigElement
|
||||||
|
|
||||||
|
class RestartStrategy(
|
||||||
|
@BeanProperty val scheme: FailOverScheme,
|
||||||
|
@BeanProperty val maxNrOfRetries: Int,
|
||||||
|
@BeanProperty val withinTimeRange: Int,
|
||||||
|
@BeanProperty val trapExceptions: Array[Class[_ <: Throwable]]) extends ConfigElement {
|
||||||
|
def transform = se.scalablesolutions.akka.config.ScalaConfig.RestartStrategy(
|
||||||
|
scheme.transform, maxNrOfRetries, withinTimeRange, trapExceptions.toList)
|
||||||
|
}
|
||||||
|
|
||||||
|
class LifeCycle(@BeanProperty val scope: Scope, @BeanProperty val callbacks: RestartCallbacks) extends ConfigElement {
|
||||||
|
def this(scope: Scope) = this(scope, null)
|
||||||
|
def transform = {
|
||||||
|
val callbackOption = if (callbacks eq null) None else Some(callbacks.transform)
|
||||||
|
se.scalablesolutions.akka.config.ScalaConfig.LifeCycle(scope.transform, callbackOption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RestartCallbacks(@BeanProperty val preRestart: String, @BeanProperty val postRestart: String) {
|
||||||
|
def transform = se.scalablesolutions.akka.config.ScalaConfig.RestartCallbacks(preRestart, postRestart)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Scope extends ConfigElement {
|
||||||
|
def transform: se.scalablesolutions.akka.config.ScalaConfig.Scope
|
||||||
|
}
|
||||||
|
class Permanent extends Scope {
|
||||||
|
override def transform = se.scalablesolutions.akka.config.ScalaConfig.Permanent
|
||||||
|
}
|
||||||
|
class Temporary extends Scope {
|
||||||
|
override def transform = se.scalablesolutions.akka.config.ScalaConfig.Temporary
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FailOverScheme extends ConfigElement {
|
||||||
|
def transform: se.scalablesolutions.akka.config.ScalaConfig.FailOverScheme
|
||||||
|
}
|
||||||
|
class AllForOne extends FailOverScheme {
|
||||||
|
override def transform = se.scalablesolutions.akka.config.ScalaConfig.AllForOne
|
||||||
|
}
|
||||||
|
class OneForOne extends FailOverScheme {
|
||||||
|
override def transform = se.scalablesolutions.akka.config.ScalaConfig.OneForOne
|
||||||
|
}
|
||||||
|
|
||||||
|
class RemoteAddress(@BeanProperty val hostname: String, @BeanProperty val port: Int)
|
||||||
|
|
||||||
|
abstract class Server extends ConfigElement
|
||||||
|
class Component(@BeanProperty val intf: Class[_],
|
||||||
|
@BeanProperty val target: Class[_],
|
||||||
|
@BeanProperty val lifeCycle: LifeCycle,
|
||||||
|
@BeanProperty val timeout: Int,
|
||||||
|
@BeanProperty val transactionRequired: Boolean, // optional
|
||||||
|
@BeanProperty val dispatcher: MessageDispatcher, // optional
|
||||||
|
@BeanProperty val remoteAddress: RemoteAddress // optional
|
||||||
|
) extends Server {
|
||||||
|
|
||||||
|
def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
|
||||||
|
this(intf, target, lifeCycle, timeout, false, null, null)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
|
||||||
|
this(null, target, lifeCycle, timeout, false, null, null)
|
||||||
|
|
||||||
|
def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) =
|
||||||
|
this(intf, target, lifeCycle, timeout, false, null, remoteAddress)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, remoteAddress: RemoteAddress) =
|
||||||
|
this(null, target, lifeCycle, timeout, false, null, remoteAddress)
|
||||||
|
|
||||||
|
def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) =
|
||||||
|
this(intf, target, lifeCycle, timeout, false, dispatcher, null)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher) =
|
||||||
|
this(null, target, lifeCycle, timeout, false, dispatcher, null)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) =
|
||||||
|
this(null, target, lifeCycle, timeout, false, dispatcher, remoteAddress)
|
||||||
|
|
||||||
|
def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) =
|
||||||
|
this(intf, target, lifeCycle, timeout, transactionRequired, null, null)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean) =
|
||||||
|
this(null, target, lifeCycle, timeout, transactionRequired, null, null)
|
||||||
|
|
||||||
|
def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) =
|
||||||
|
this(intf, target, lifeCycle, timeout, transactionRequired, null, remoteAddress)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, remoteAddress: RemoteAddress) =
|
||||||
|
this(null, target, lifeCycle, timeout, transactionRequired, null, remoteAddress)
|
||||||
|
|
||||||
|
def this(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) =
|
||||||
|
this(intf, target, lifeCycle, timeout, transactionRequired, dispatcher, null)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher) =
|
||||||
|
this(null, target, lifeCycle, timeout, transactionRequired, dispatcher, null)
|
||||||
|
|
||||||
|
def this(target: Class[_], lifeCycle: LifeCycle, timeout: Int, transactionRequired: Boolean, dispatcher: MessageDispatcher, remoteAddress: RemoteAddress) =
|
||||||
|
this(null, target, lifeCycle, timeout, transactionRequired, dispatcher, remoteAddress)
|
||||||
|
|
||||||
|
def transform =
|
||||||
|
se.scalablesolutions.akka.config.ScalaConfig.Component(
|
||||||
|
intf, target, lifeCycle.transform, timeout, transactionRequired, dispatcher,
|
||||||
|
if (remoteAddress ne null) se.scalablesolutions.akka.config.ScalaConfig.RemoteAddress(remoteAddress.hostname, remoteAddress.port) else null)
|
||||||
|
|
||||||
|
def newSupervised(actor: Actor) =
|
||||||
|
se.scalablesolutions.akka.config.ScalaConfig.Supervise(actor, lifeCycle.transform)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
package se.scalablesolutions.akka.remote
|
package se.scalablesolutions.akka.remote
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.BootableActorLoaderService
|
import se.scalablesolutions.akka.actor.BootableActorLoaderService
|
||||||
import se.scalablesolutions.akka.util.{Bootable,Logging}
|
import se.scalablesolutions.akka.util.{Bootable, Logging}
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This bundle/service is responsible for booting up and shutting down the remote actors facility
|
* This bundle/service is responsible for booting up and shutting down the remote actors facility
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.remote
|
package se.scalablesolutions.akka.remote
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
import se.scalablesolutions.akka.config.ScalaConfig._
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import se.scalablesolutions.akka.serialization.Serializer
|
import se.scalablesolutions.akka.serialization.Serializer
|
||||||
import se.scalablesolutions.akka.actor.{Supervisor, SupervisorFactory, Actor, ActorRegistry}
|
import se.scalablesolutions.akka.actor.{Supervisor, SupervisorFactory, Actor, ActorRegistry}
|
||||||
|
|
@ -44,20 +44,20 @@ trait ClusterActor extends Actor with Cluster {
|
||||||
*
|
*
|
||||||
* @author Viktor Klang
|
* @author Viktor Klang
|
||||||
*/
|
*/
|
||||||
private[remote] object ClusterActor {
|
private[akka] object ClusterActor {
|
||||||
sealed trait ClusterMessage
|
sealed trait ClusterMessage
|
||||||
|
|
||||||
private[remote] case class RelayedMessage(actorClassFQN: String, msg: AnyRef) extends ClusterMessage
|
private[akka] case class RelayedMessage(actorClassFQN: String, msg: AnyRef) extends ClusterMessage
|
||||||
private[remote] case class Message[ADDR_T](sender: ADDR_T, msg: Array[Byte])
|
private[akka] case class Message[ADDR_T](sender: ADDR_T, msg: Array[Byte])
|
||||||
private[remote] case object PapersPlease extends ClusterMessage
|
private[akka] case object PapersPlease extends ClusterMessage
|
||||||
private[remote] case class Papers(addresses: List[RemoteAddress]) extends ClusterMessage
|
private[akka] case class Papers(addresses: List[RemoteAddress]) extends ClusterMessage
|
||||||
private[remote] case object Block extends ClusterMessage
|
private[akka] case object Block extends ClusterMessage
|
||||||
private[remote] case object Unblock extends ClusterMessage
|
private[akka] case object Unblock extends ClusterMessage
|
||||||
private[remote] case class View[ADDR_T](othersPresent: Set[ADDR_T]) extends ClusterMessage
|
private[akka] case class View[ADDR_T](othersPresent: Set[ADDR_T]) extends ClusterMessage
|
||||||
private[remote] case class Zombie[ADDR_T](address: ADDR_T) extends ClusterMessage
|
private[akka] case class Zombie[ADDR_T](address: ADDR_T) extends ClusterMessage
|
||||||
private[remote] case class RegisterLocalNode(server: RemoteAddress) extends ClusterMessage
|
private[akka] case class RegisterLocalNode(server: RemoteAddress) extends ClusterMessage
|
||||||
private[remote] case class DeregisterLocalNode(server: RemoteAddress) extends ClusterMessage
|
private[akka] case class DeregisterLocalNode(server: RemoteAddress) extends ClusterMessage
|
||||||
private[remote] case class Node(endpoints: List[RemoteAddress])
|
private[akka] case class Node(endpoints: List[RemoteAddress])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -205,16 +205,16 @@ abstract class BasicClusterActor extends ClusterActor {
|
||||||
object Cluster extends Cluster with Logging {
|
object Cluster extends Cluster with Logging {
|
||||||
lazy val DEFAULT_SERIALIZER_CLASS_NAME = Serializer.Java.getClass.getName
|
lazy val DEFAULT_SERIALIZER_CLASS_NAME = Serializer.Java.getClass.getName
|
||||||
|
|
||||||
@volatile private[remote] var clusterActor: Option[ClusterActor] = None
|
@volatile private[akka] var clusterActor: Option[ClusterActor] = None
|
||||||
|
|
||||||
// FIXME Use the supervisor member field
|
// FIXME Use the supervisor member field
|
||||||
@volatile private[remote] var supervisor: Option[Supervisor] = None
|
@volatile private[akka] var supervisor: Option[Supervisor] = None
|
||||||
|
|
||||||
private[remote] lazy val serializer: Serializer =
|
private[akka] lazy val serializer: Serializer =
|
||||||
Class.forName(config.getString("akka.remote.cluster.serializer", DEFAULT_SERIALIZER_CLASS_NAME))
|
Class.forName(config.getString("akka.remote.cluster.serializer", DEFAULT_SERIALIZER_CLASS_NAME))
|
||||||
.newInstance.asInstanceOf[Serializer]
|
.newInstance.asInstanceOf[Serializer]
|
||||||
|
|
||||||
private[remote] def createClusterActor: Option[ClusterActor] = {
|
private[akka] def createClusterActor: Option[ClusterActor] = {
|
||||||
val name = config.getString("akka.remote.cluster.actor")
|
val name = config.getString("akka.remote.cluster.actor")
|
||||||
if (name.isEmpty) throw new IllegalArgumentException(
|
if (name.isEmpty) throw new IllegalArgumentException(
|
||||||
"Can't start cluster since the 'akka.remote.cluster.actor' configuration option is not defined")
|
"Can't start cluster since the 'akka.remote.cluster.actor' configuration option is not defined")
|
||||||
|
|
@ -229,7 +229,7 @@ object Cluster extends Cluster with Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private[remote] def createSupervisor(actor: ClusterActor): Option[Supervisor] = {
|
private[akka] def createSupervisor(actor: ClusterActor): Option[Supervisor] = {
|
||||||
val sup = SupervisorFactory(
|
val sup = SupervisorFactory(
|
||||||
SupervisorConfig(
|
SupervisorConfig(
|
||||||
RestartStrategy(OneForOne, 5, 1000, List(classOf[Exception])),
|
RestartStrategy(OneForOne, 5, 1000, List(classOf[Exception])),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import se.scalablesolutions.akka.remote.protobuf.RemoteProtocol.{RemoteRequest,
|
||||||
import se.scalablesolutions.akka.actor.{Exit, Actor}
|
import se.scalablesolutions.akka.actor.{Exit, Actor}
|
||||||
import se.scalablesolutions.akka.dispatch.{DefaultCompletableFuture, CompletableFuture}
|
import se.scalablesolutions.akka.dispatch.{DefaultCompletableFuture, CompletableFuture}
|
||||||
import se.scalablesolutions.akka.util.{UUID, Logging}
|
import se.scalablesolutions.akka.util.{UUID, Logging}
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import org.jboss.netty.channel._
|
import org.jboss.netty.channel._
|
||||||
import group.DefaultChannelGroup
|
import group.DefaultChannelGroup
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import java.util.{Map => JMap}
|
||||||
import se.scalablesolutions.akka.actor._
|
import se.scalablesolutions.akka.actor._
|
||||||
import se.scalablesolutions.akka.util._
|
import se.scalablesolutions.akka.util._
|
||||||
import se.scalablesolutions.akka.remote.protobuf.RemoteProtocol.{RemoteReply, RemoteRequest}
|
import se.scalablesolutions.akka.remote.protobuf.RemoteProtocol.{RemoteReply, RemoteRequest}
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import org.jboss.netty.bootstrap.ServerBootstrap
|
import org.jboss.netty.bootstrap.ServerBootstrap
|
||||||
import org.jboss.netty.channel._
|
import org.jboss.netty.channel._
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,15 @@
|
||||||
package se.scalablesolutions.akka.serialization
|
package se.scalablesolutions.akka.serialization
|
||||||
|
|
||||||
import org.codehaus.jackson.map.ObjectMapper
|
import org.codehaus.jackson.map.ObjectMapper
|
||||||
|
|
||||||
import com.google.protobuf.Message
|
import com.google.protobuf.Message
|
||||||
import reflect.Manifest
|
|
||||||
|
import scala.reflect.Manifest
|
||||||
|
|
||||||
import sbinary.DefaultProtocol
|
import sbinary.DefaultProtocol
|
||||||
|
|
||||||
import java.io.{StringWriter, ByteArrayOutputStream, ObjectOutputStream}
|
import java.io.{StringWriter, ByteArrayOutputStream, ObjectOutputStream}
|
||||||
|
|
||||||
import sjson.json.{Serializer=>SJSONSerializer}
|
import sjson.json.{Serializer=>SJSONSerializer}
|
||||||
|
|
||||||
object SerializationProtocol {
|
object SerializationProtocol {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.stm
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import java.util.concurrent.{ConcurrentLinkedQueue, LinkedBlockingQueue}
|
import java.util.concurrent.{ConcurrentLinkedQueue, LinkedBlockingQueue}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.collection
|
package se.scalablesolutions.akka.stm
|
||||||
|
|
||||||
trait PersistentDataStructure
|
trait PersistentDataStructure
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ object HashTrie {
|
||||||
// nodes
|
// nodes
|
||||||
|
|
||||||
@serializable
|
@serializable
|
||||||
private[collection] sealed trait Node[K, +V] {
|
private[stm] sealed trait Node[K, +V] {
|
||||||
val size: Int
|
val size: Int
|
||||||
|
|
||||||
def apply(key: K, hash: Int): Option[V]
|
def apply(key: K, hash: Int): Option[V]
|
||||||
|
|
@ -90,7 +90,7 @@ private[collection] sealed trait Node[K, +V] {
|
||||||
}
|
}
|
||||||
|
|
||||||
@serializable
|
@serializable
|
||||||
private[collection] class EmptyNode[K] extends Node[K, Nothing] {
|
private[stm] class EmptyNode[K] extends Node[K, Nothing] {
|
||||||
val size = 0
|
val size = 0
|
||||||
|
|
||||||
def apply(key: K, hash: Int) = None
|
def apply(key: K, hash: Int) = None
|
||||||
|
|
@ -106,12 +106,12 @@ private[collection] class EmptyNode[K] extends Node[K, Nothing] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private[collection] abstract class SingleNode[K, +V] extends Node[K, V] {
|
private[stm] abstract class SingleNode[K, +V] extends Node[K, V] {
|
||||||
val hash: Int
|
val hash: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private[collection] class LeafNode[K, +V](key: K, val hash: Int, value: V) extends SingleNode[K, V] {
|
private[stm] class LeafNode[K, +V](key: K, val hash: Int, value: V) extends SingleNode[K, V] {
|
||||||
val size = 1
|
val size = 1
|
||||||
|
|
||||||
def apply(key: K, hash: Int) = if (this.key == key) Some(value) else None
|
def apply(key: K, hash: Int) = if (this.key == key) Some(value) else None
|
||||||
|
|
@ -141,7 +141,7 @@ private[collection] class LeafNode[K, +V](key: K, val hash: Int, value: V) exten
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private[collection] class CollisionNode[K, +V](val hash: Int, bucket: List[(K, V)]) extends SingleNode[K, V] {
|
private[stm] class CollisionNode[K, +V](val hash: Int, bucket: List[(K, V)]) extends SingleNode[K, V] {
|
||||||
lazy val size = bucket.length
|
lazy val size = bucket.length
|
||||||
|
|
||||||
def this(hash: Int, pairs: (K, V)*) = this(hash, pairs.toList)
|
def this(hash: Int, pairs: (K, V)*) = this(hash, pairs.toList)
|
||||||
|
|
@ -185,7 +185,7 @@ private[collection] class CollisionNode[K, +V](val hash: Int, bucket: List[(K, V
|
||||||
override def toString = "CollisionNode(" + bucket.toString + ")"
|
override def toString = "CollisionNode(" + bucket.toString + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
private[collection] class BitmappedNode[K, +V](shift: Int)(table: Array[Node[K, V]], bits: Int) extends Node[K, V] {
|
private[stm] class BitmappedNode[K, +V](shift: Int)(table: Array[Node[K, V]], bits: Int) extends Node[K, V] {
|
||||||
lazy val size = {
|
lazy val size = {
|
||||||
val sizes = for {
|
val sizes = for {
|
||||||
n <- table
|
n <- table
|
||||||
|
|
@ -284,7 +284,7 @@ private[collection] class BitmappedNode[K, +V](shift: Int)(table: Array[Node[K,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private[collection] object BitmappedNode {
|
private[stm] object BitmappedNode {
|
||||||
def apply[K, V](shift: Int)(node: SingleNode[K, V], key: K, hash: Int, value: V) = {
|
def apply[K, V](shift: Int)(node: SingleNode[K, V], key: K, hash: Int, value: V) = {
|
||||||
val table = new Array[Node[K, V]](Math.max((hash >>> shift) & 0x01f, (node.hash >>> shift) & 0x01f) + 1)
|
val table = new Array[Node[K, V]](Math.max((hash >>> shift) & 0x01f, (node.hash >>> shift) & 0x01f) + 1)
|
||||||
|
|
||||||
|
|
@ -312,7 +312,7 @@ private[collection] object BitmappedNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private[collection] class FullNode[K, +V](shift: Int)(table: Array[Node[K, V]]) extends Node[K, V] {
|
private[stm] class FullNode[K, +V](shift: Int)(table: Array[Node[K, V]]) extends Node[K, V] {
|
||||||
lazy val size = table.foldLeft(0) { _ + _.size }
|
lazy val size = table.foldLeft(0) { _ + _.size }
|
||||||
|
|
||||||
def apply(key: K, hash: Int) = table((hash >>> shift) & 0x01f)(key, hash)
|
def apply(key: K, hash: Int) = table((hash >>> shift) & 0x01f)(key, hash)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.util
|
package se.scalablesolutions.akka.stm
|
||||||
|
|
||||||
import stm.Transaction
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference that can hold either a typed value or an exception.
|
* Reference that can hold either a typed value or an exception.
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ package se.scalablesolutions.akka.stm
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import scala.collection.mutable.HashMap
|
import scala.collection.mutable.HashMap
|
||||||
|
|
||||||
import se.scalablesolutions.akka.state.Committable
|
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
import org.multiverse.api.{Transaction => MultiverseTransaction}
|
import org.multiverse.api.{Transaction => MultiverseTransaction}
|
||||||
|
|
@ -18,7 +18,6 @@ import org.multiverse.api.ThreadLocalTransaction._
|
||||||
import org.multiverse.templates.{TransactionTemplate, OrElseTemplate}
|
import org.multiverse.templates.{TransactionTemplate, OrElseTemplate}
|
||||||
import org.multiverse.utils.backoff.ExponentialBackoffPolicy
|
import org.multiverse.utils.backoff.ExponentialBackoffPolicy
|
||||||
import org.multiverse.stms.alpha.AlphaStm
|
import org.multiverse.stms.alpha.AlphaStm
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class NoTransactionInScopeException extends RuntimeException
|
class NoTransactionInScopeException extends RuntimeException
|
||||||
class TransactionRetryException(message: String) extends RuntimeException(message)
|
class TransactionRetryException(message: String) extends RuntimeException(message)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class TransactionAwareWrapperException(val cause: Throwable, val tx: Option[Tran
|
||||||
}
|
}
|
||||||
|
|
||||||
object TransactionManagement extends TransactionManagement {
|
object TransactionManagement extends TransactionManagement {
|
||||||
import se.scalablesolutions.akka.Config._
|
import se.scalablesolutions.akka.config.Config._
|
||||||
|
|
||||||
val TRANSACTION_ENABLED = new AtomicBoolean(config.getBool("akka.stm.service", false))
|
val TRANSACTION_ENABLED = new AtomicBoolean(config.getBool("akka.stm.service", false))
|
||||||
val FAIR_TRANSACTIONS = config.getBool("akka.stm.fair", true)
|
val FAIR_TRANSACTIONS = config.getBool("akka.stm.fair", true)
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.stm
|
||||||
|
|
||||||
import se.scalablesolutions.akka.stm.Transaction.atomic
|
import se.scalablesolutions.akka.stm.Transaction.atomic
|
||||||
import se.scalablesolutions.akka.stm.NoTransactionInScopeException
|
|
||||||
import se.scalablesolutions.akka.collection._
|
|
||||||
import se.scalablesolutions.akka.util.UUID
|
import se.scalablesolutions.akka.util.UUID
|
||||||
|
|
||||||
import org.multiverse.stms.alpha.AlphaRef
|
import org.multiverse.stms.alpha.AlphaRef
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.collection
|
package se.scalablesolutions.akka.stm
|
||||||
|
|
||||||
import Vector._
|
import Vector._
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ class Vector[+T] private (val length: Int, shift: Int, root: Array[AnyRef], tail
|
||||||
* (somewhat dynamically-typed) implementation in place.
|
* (somewhat dynamically-typed) implementation in place.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private[collection] def this() = this(0, 5, EmptyArray, EmptyArray)
|
private[stm] def this() = this(0, 5, EmptyArray, EmptyArray)
|
||||||
|
|
||||||
def apply(i: Int): T = {
|
def apply(i: Int): T = {
|
||||||
if (i >= 0 && i < length) {
|
if (i >= 0 && i < length) {
|
||||||
|
|
@ -317,14 +317,14 @@ class Vector[+T] private (val length: Int, shift: Int, root: Array[AnyRef], tail
|
||||||
}
|
}
|
||||||
|
|
||||||
object Vector {
|
object Vector {
|
||||||
private[collection] val EmptyArray = new Array[AnyRef](0)
|
private[stm] val EmptyArray = new Array[AnyRef](0)
|
||||||
|
|
||||||
def apply[T](elems: T*) = elems.foldLeft(EmptyVector:Vector[T]) { _ + _ }
|
def apply[T](elems: T*) = elems.foldLeft(EmptyVector:Vector[T]) { _ + _ }
|
||||||
|
|
||||||
def unapplySeq[T](vec: Vector[T]): Option[Seq[T]] = Some(vec)
|
def unapplySeq[T](vec: Vector[T]): Option[Seq[T]] = Some(vec)
|
||||||
|
|
||||||
@inline
|
@inline
|
||||||
private[collection] def array(elems: AnyRef*) = {
|
private[stm] def array(elems: AnyRef*) = {
|
||||||
val back = new Array[AnyRef](elems.length)
|
val back = new Array[AnyRef](elems.length)
|
||||||
Array.copy(elems, 0, back, 0, back.length)
|
Array.copy(elems, 0, back, 0, back.length)
|
||||||
|
|
||||||
|
|
@ -334,7 +334,7 @@ object Vector {
|
||||||
|
|
||||||
object EmptyVector extends Vector[Nothing]
|
object EmptyVector extends Vector[Nothing]
|
||||||
|
|
||||||
private[collection] abstract class VectorProjection[+T] extends Vector[T] {
|
private[stm] abstract class VectorProjection[+T] extends Vector[T] {
|
||||||
override val length: Int
|
override val length: Int
|
||||||
override def apply(i: Int): T
|
override def apply(i: Int): T
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class RemoteActorSpecActorAsyncSender extends Actor {
|
||||||
class ClientInitiatedRemoteActorTest extends JUnitSuite {
|
class ClientInitiatedRemoteActorTest extends JUnitSuite {
|
||||||
import Actor.Sender.Self
|
import Actor.Sender.Self
|
||||||
|
|
||||||
akka.Config.config
|
akka.config.Config.config
|
||||||
|
|
||||||
val HOSTNAME = "localhost"
|
val HOSTNAME = "localhost"
|
||||||
val PORT1 = 9990
|
val PORT1 = 9990
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package se.scalablesolutions.akka.actor
|
||||||
import org.scalatest.junit.JUnitSuite
|
import org.scalatest.junit.JUnitSuite
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
import se.scalablesolutions.akka.state.{TransactionalState, TransactionalMap, TransactionalRef, TransactionalVector}
|
import se.scalablesolutions.akka.stm.{TransactionalState, TransactionalMap, TransactionalRef, TransactionalVector}
|
||||||
|
|
||||||
case class GetMapState(key: String)
|
case class GetMapState(key: String)
|
||||||
case object GetVectorState
|
case object GetVectorState
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ object Log {
|
||||||
class RemoteSupervisorTest extends JUnitSuite {
|
class RemoteSupervisorTest extends JUnitSuite {
|
||||||
import Actor.Sender.Self
|
import Actor.Sender.Self
|
||||||
|
|
||||||
akka.Config.config
|
akka.config.Config.config
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
def run = {
|
def run = {
|
||||||
RemoteNode.start
|
RemoteNode.start
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class ServerInitiatedRemoteActorTest extends JUnitSuite {
|
||||||
import ServerInitiatedRemoteActorTest._
|
import ServerInitiatedRemoteActorTest._
|
||||||
|
|
||||||
import Actor.Sender.Self
|
import Actor.Sender.Self
|
||||||
akka.Config.config
|
akka.config.Config.config
|
||||||
|
|
||||||
private val unit = TimeUnit.MILLISECONDS
|
private val unit = TimeUnit.MILLISECONDS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import com.google.inject.Scopes;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config;
|
import se.scalablesolutions.akka.config.Config;
|
||||||
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
||||||
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
||||||
import se.scalablesolutions.akka.dispatch.*;
|
import se.scalablesolutions.akka.dispatch.*;
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.api;
|
package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config;
|
|
||||||
import se.scalablesolutions.akka.config.*;
|
import se.scalablesolutions.akka.config.*;
|
||||||
|
import se.scalablesolutions.akka.config.Config;
|
||||||
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
||||||
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
||||||
import se.scalablesolutions.akka.actor.*;
|
import se.scalablesolutions.akka.actor.*;
|
||||||
import se.scalablesolutions.akka.Kernel;
|
import se.scalablesolutions.akka.kernel.Kernel;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
public class InMemNestedStateTest extends TestCase {
|
public class InMemNestedStateTest extends TestCase {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import se.scalablesolutions.akka.annotation.transactionrequired;
|
||||||
import se.scalablesolutions.akka.annotation.prerestart;
|
import se.scalablesolutions.akka.annotation.prerestart;
|
||||||
import se.scalablesolutions.akka.annotation.postrestart;
|
import se.scalablesolutions.akka.annotation.postrestart;
|
||||||
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
||||||
import se.scalablesolutions.akka.state.*;
|
import se.scalablesolutions.akka.stm.*;
|
||||||
|
|
||||||
@transactionrequired
|
@transactionrequired
|
||||||
public class InMemStateful {
|
public class InMemStateful {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.annotation.transactionrequired;
|
import se.scalablesolutions.akka.annotation.transactionrequired;
|
||||||
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
||||||
import se.scalablesolutions.akka.state.*;
|
import se.scalablesolutions.akka.stm.*;
|
||||||
|
|
||||||
@transactionrequired
|
@transactionrequired
|
||||||
public class InMemStatefulNested {
|
public class InMemStatefulNested {
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,14 @@ package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config;
|
import se.scalablesolutions.akka.config.Config;
|
||||||
import se.scalablesolutions.akka.config.*;
|
import se.scalablesolutions.akka.config.*;
|
||||||
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
||||||
|
|
||||||
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.*;
|
import se.scalablesolutions.akka.actor.*;
|
||||||
import se.scalablesolutions.akka.Kernel;
|
import se.scalablesolutions.akka.kernel.Kernel;
|
||||||
|
|
||||||
public class InMemoryStateTest extends TestCase {
|
public class InMemoryStateTest extends TestCase {
|
||||||
static String messageLog = "";
|
static String messageLog = "";
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ public class PersistenceManager {
|
||||||
private static volatile boolean isRunning = false;
|
private static volatile boolean isRunning = false;
|
||||||
public static void init() {
|
public static void init() {
|
||||||
if (!isRunning) {
|
if (!isRunning) {
|
||||||
se.scalablesolutions.akka.Kernel$.MODULE$.startRemoteService();
|
se.scalablesolutions.akka.kernel.Kernel$.MODULE$.startRemoteService();
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package se.scalablesolutions.akka.api;
|
package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.state.*;
|
import se.scalablesolutions.akka.persistence.common.*;
|
||||||
|
import se.scalablesolutions.akka.persistence.cassandra.*;
|
||||||
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
||||||
|
|
||||||
public class PersistentClasher {
|
public class PersistentClasher {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import se.scalablesolutions.akka.config.*;
|
||||||
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
||||||
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
import static se.scalablesolutions.akka.config.JavaConfig.*;
|
||||||
import se.scalablesolutions.akka.actor.*;
|
import se.scalablesolutions.akka.actor.*;
|
||||||
import se.scalablesolutions.akka.Kernel;
|
import se.scalablesolutions.akka.kernel.Kernel;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
||||||
import se.scalablesolutions.akka.annotation.transactionrequired;
|
import se.scalablesolutions.akka.annotation.transactionrequired;
|
||||||
import se.scalablesolutions.akka.state.*;
|
import se.scalablesolutions.akka.persistence.common.*;
|
||||||
|
import se.scalablesolutions.akka.persistence.cassandra.*;
|
||||||
|
|
||||||
@transactionrequired
|
@transactionrequired
|
||||||
public class PersistentStateful {
|
public class PersistentStateful {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
import se.scalablesolutions.akka.annotation.inittransactionalstate;
|
||||||
import se.scalablesolutions.akka.annotation.transactionrequired;
|
import se.scalablesolutions.akka.annotation.transactionrequired;
|
||||||
import se.scalablesolutions.akka.state.*;
|
import se.scalablesolutions.akka.persistence.common.*;
|
||||||
|
import se.scalablesolutions.akka.persistence.cassandra.*;
|
||||||
|
|
||||||
@transactionrequired
|
@transactionrequired
|
||||||
public class PersistentStatefulNested {
|
public class PersistentStatefulNested {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.api;
|
package se.scalablesolutions.akka.api;
|
||||||
|
|
||||||
import se.scalablesolutions.akka.Config;
|
import se.scalablesolutions.akka.config.Config;
|
||||||
import se.scalablesolutions.akka.actor.ActiveObject;
|
import se.scalablesolutions.akka.actor.ActiveObject;
|
||||||
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
import se.scalablesolutions.akka.config.ActiveObjectConfigurator;
|
||||||
import se.scalablesolutions.akka.remote.RemoteNode;
|
import se.scalablesolutions.akka.remote.RemoteNode;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka
|
package se.scalablesolutions.akka.kernel
|
||||||
|
|
||||||
import se.scalablesolutions.akka.remote.BootableRemoteActorService
|
import se.scalablesolutions.akka.remote.BootableRemoteActorService
|
||||||
|
import se.scalablesolutions.akka.comet.BootableCometActorService
|
||||||
import se.scalablesolutions.akka.actor.BootableActorLoaderService
|
import se.scalablesolutions.akka.actor.BootableActorLoaderService
|
||||||
import se.scalablesolutions.akka.util.{Logging,Bootable}
|
import se.scalablesolutions.akka.config.Config
|
||||||
|
import se.scalablesolutions.akka.util.{Logging, Bootable}
|
||||||
|
|
||||||
import javax.servlet.{ServletContextListener, ServletContextEvent}
|
import javax.servlet.{ServletContextListener, ServletContextEvent}
|
||||||
|
|
||||||
|
|
@ -27,12 +29,15 @@ object Kernel extends Logging {
|
||||||
/**
|
/**
|
||||||
* Holds a reference to the services that has been booted
|
* Holds a reference to the services that has been booted
|
||||||
*/
|
*/
|
||||||
@volatile private var bundles : Option[Bootable] = None
|
@volatile private var bundles: Option[Bootable] = None
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boots up the Kernel with default bootables
|
* Boots up the Kernel with default bootables
|
||||||
*/
|
*/
|
||||||
def boot : Unit = boot(true, new BootableActorLoaderService with BootableRemoteActorService with BootableCometActorService)
|
def boot: Unit = boot(true,
|
||||||
|
new BootableActorLoaderService
|
||||||
|
with BootableRemoteActorService
|
||||||
|
with BootableCometActorService)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boots up the Kernel.
|
* Boots up the Kernel.
|
||||||
|
|
@ -63,8 +68,8 @@ object Kernel extends Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
//For testing purposes only
|
//For testing purposes only
|
||||||
def startRemoteService : Unit = bundles.foreach( _ match {
|
def startRemoteService: Unit = bundles.foreach( _ match {
|
||||||
case x : BootableRemoteActorService => x.startRemoteService
|
case x: BootableRemoteActorService => x.startRemoteService
|
||||||
case _ =>
|
case _ =>
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -84,11 +89,13 @@ object Kernel extends Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
And this one can be added to web.xml mappings as a listener to boot and shutdown Akka
|
* This class can be added to web.xml mappings as a listener to boot and shutdown Akka.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Kernel extends ServletContextListener {
|
class Kernel extends ServletContextListener {
|
||||||
def contextDestroyed(e : ServletContextEvent) : Unit = Kernel.shutdown
|
def contextDestroyed(e: ServletContextEvent): Unit =
|
||||||
def contextInitialized(e : ServletContextEvent) : Unit = Kernel.boot(true,new BootableActorLoaderService with BootableRemoteActorService)
|
Kernel.shutdown
|
||||||
|
|
||||||
|
def contextInitialized(e: ServletContextEvent): Unit =
|
||||||
|
Kernel.boot(true, new BootableActorLoaderService with BootableRemoteActorService)
|
||||||
}
|
}
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
// ScalaAgent
|
|
||||||
//
|
|
||||||
// Copyright © 2008-9 The original author or authors
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
package se.scalablesolutions.akka.actor
|
|
||||||
|
|
||||||
import se.scalablesolutions.akka.state.TransactionalState
|
|
||||||
import se.scalablesolutions.akka.stm.Transaction.atomic
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
|
||||||
import java.util.concurrent.{CountDownLatch}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Agent class was strongly inspired by the agent principle in Clojure. Essentially, an agent wraps a shared mutable state
|
|
||||||
* and hides it behind a message-passing interface. Agents accept messages and process them on behalf of the wrapped state.
|
|
||||||
* Typically agents accept functions / commands as messages and ensure the submitted commands are executed against the internal
|
|
||||||
* agent's state in a thread-safe manner (sequentially).
|
|
||||||
* The submitted functions / commands take the internal state as a parameter and their output becomes the new internal state value.
|
|
||||||
* The code that is submitted to an agent doesn't need to pay attention to threading or synchronization, the agent will
|
|
||||||
* provide such guarantees by itself.
|
|
||||||
* See the examples of use for more details.
|
|
||||||
*
|
|
||||||
* @author Vaclav Pech
|
|
||||||
* Date: Oct 18, 2009
|
|
||||||
*
|
|
||||||
* AKKA retrofit by
|
|
||||||
* @author Viktor Klang
|
|
||||||
* Date: Jan 24 2010
|
|
||||||
*/
|
|
||||||
sealed class Agent[T] private (initialValue: T) extends Actor {
|
|
||||||
import Agent._
|
|
||||||
|
|
||||||
private val value = TransactionalState.newRef[T]
|
|
||||||
|
|
||||||
updateData(initialValue)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Periodically handles incoming messages
|
|
||||||
*/
|
|
||||||
def receive = {
|
|
||||||
case FunctionHolder(fun: (T => T)) => updateData(fun(value.getOrWait))
|
|
||||||
|
|
||||||
case ValueHolder(x: T) => updateData(x)
|
|
||||||
|
|
||||||
case ProcedureHolder(fun: (T => Unit)) => fun(copyStrategy(value.getOrWait))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies how a copy of the value is made, defaults to using identity
|
|
||||||
*/
|
|
||||||
protected def copyStrategy(t: T): T = t
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the internal state with the value provided as a by-name parameter
|
|
||||||
*/
|
|
||||||
private final def updateData(newData: => T): Unit = value.swap(newData)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits a request to read the internal state.
|
|
||||||
* A copy of the internal state will be returned, depending on the underlying effective copyStrategy.
|
|
||||||
* Internally leverages the asynchronous getValue() method and then waits for its result on a CountDownLatch.
|
|
||||||
*/
|
|
||||||
final def get: T = {
|
|
||||||
val ref = new AtomicReference[T]
|
|
||||||
val latch = new CountDownLatch(1)
|
|
||||||
get((x: T) => {ref.set(x); latch.countDown})
|
|
||||||
latch.await
|
|
||||||
ref.get
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronously submits a request to read the internal state. The supplied function will be executed on the returned internal state value.
|
|
||||||
* A copy of the internal state will be used, depending on the underlying effective copyStrategy.
|
|
||||||
*/
|
|
||||||
final def get(message: (T => Unit)): Unit = this ! ProcedureHolder(message)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits a request to read the internal state.
|
|
||||||
* A copy of the internal state will be returned, depending on the underlying effective copyStrategy.
|
|
||||||
* Internally leverages the asynchronous getValue() method and then waits for its result on a CountDownLatch.
|
|
||||||
*/
|
|
||||||
final def apply(): T = get
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronously submits a request to read the internal state. The supplied function will be executed on the returned internal state value.
|
|
||||||
* A copy of the internal state will be used, depending on the underlying effective copyStrategy.
|
|
||||||
*/
|
|
||||||
// final def apply(message: (T => Unit)) : Unit = get(message)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits the provided function for execution against the internal agent's state
|
|
||||||
*/
|
|
||||||
final def apply(message: (T => T)): Unit = this ! FunctionHolder(message)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits a new value to be set as the new agent's internal state
|
|
||||||
*/
|
|
||||||
final def apply(message: T): Unit = this ! ValueHolder(message)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits the provided function for execution against the internal agent's state
|
|
||||||
*/
|
|
||||||
final def update(message: (T => T)): Unit = this ! FunctionHolder(message)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits a new value to be set as the new agent's internal state
|
|
||||||
*/
|
|
||||||
final def update(message: T): Unit = this ! ValueHolder(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides factory methods to create Agents.
|
|
||||||
*/
|
|
||||||
object Agent {
|
|
||||||
/**
|
|
||||||
* The internal messages for passing around requests
|
|
||||||
*/
|
|
||||||
private case class ProcedureHolder[T](val fun: ((T) => Unit))
|
|
||||||
private case class FunctionHolder[T](val fun: ((T) => T))
|
|
||||||
private case class ValueHolder[T](val value: T)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Agent of type T with the initial value of value
|
|
||||||
*/
|
|
||||||
def apply[T](value:T): Agent[T] = new Agent(value)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Agent of type T with the initial value of value and with the specified copy function
|
|
||||||
*/
|
|
||||||
def apply[T](value:T, newCopyStrategy: (T) => T) = new Agent(value) {
|
|
||||||
override def copyStrategy(t : T) = newCopyStrategy(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.actor.patterns
|
package se.scalablesolutions.akka.patterns
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.Actor
|
import se.scalablesolutions.akka.actor.Actor
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package se.scalablesolutions.akka.actor
|
package se.scalablesolutions.akka.patterns
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import config.ScalaConfig._
|
import se.scalablesolutions.akka.actor.Actor
|
||||||
|
import se.scalablesolutions.akka.actor.Actor._
|
||||||
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
import org.scalatest.Suite
|
import org.scalatest.Suite
|
||||||
import patterns.Patterns
|
|
||||||
import se.scalablesolutions.akka.util.Logging
|
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.scalatest.junit.JUnitRunner
|
import org.scalatest.junit.JUnitRunner
|
||||||
import org.scalatest.matchers.MustMatchers
|
import org.scalatest.matchers.MustMatchers
|
||||||
|
|
@ -14,7 +14,6 @@ import scala.collection.mutable.HashSet
|
||||||
|
|
||||||
@RunWith(classOf[JUnitRunner])
|
@RunWith(classOf[JUnitRunner])
|
||||||
class ActorPatternsTest extends junit.framework.TestCase with Suite with MustMatchers with ActorTestUtil with Logging {
|
class ActorPatternsTest extends junit.framework.TestCase with Suite with MustMatchers with ActorTestUtil with Logging {
|
||||||
import Actor._
|
|
||||||
import Patterns._
|
import Patterns._
|
||||||
@Test def testDispatcher = verify(new TestActor {
|
@Test def testDispatcher = verify(new TestActor {
|
||||||
def test = {
|
def test = {
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.cassandra
|
||||||
|
|
||||||
import java.io.{Flushable, Closeable}
|
import java.io.{Flushable, Closeable}
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import se.scalablesolutions.akka.util.Helpers._
|
import se.scalablesolutions.akka.util.Helpers._
|
||||||
import se.scalablesolutions.akka.serialization.Serializer
|
import se.scalablesolutions.akka.serialization.Serializer
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import scala.collection.mutable.Map
|
import scala.collection.mutable.Map
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,18 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.cassandra
|
||||||
|
|
||||||
import org.codehaus.aspectwerkz.proxy.Uuid
|
import se.scalablesolutions.akka.util.UUID
|
||||||
|
import se.scalablesolutions.akka.stm._
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
|
|
||||||
object CassandraStorage extends Storage {
|
object CassandraStorage extends Storage {
|
||||||
type ElementType = Array[Byte]
|
type ElementType = Array[Byte]
|
||||||
|
|
||||||
def newMap: PersistentMap[ElementType, ElementType] = newMap(Uuid.newUuid.toString)
|
def newMap: PersistentMap[ElementType, ElementType] = newMap(UUID.newUuid.toString)
|
||||||
def newVector: PersistentVector[ElementType] = newVector(Uuid.newUuid.toString)
|
def newVector: PersistentVector[ElementType] = newVector(UUID.newUuid.toString)
|
||||||
def newRef: PersistentRef[ElementType] = newRef(Uuid.newUuid.toString)
|
def newRef: PersistentRef[ElementType] = newRef(UUID.newUuid.toString)
|
||||||
|
|
||||||
def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id)
|
def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id)
|
||||||
def getVector(id: String): PersistentVector[ElementType] = newVector(id)
|
def getVector(id: String): PersistentVector[ElementType] = newVector(id)
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.cassandra
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.stm._
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import se.scalablesolutions.akka.util.Helpers._
|
import se.scalablesolutions.akka.util.Helpers._
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import org.apache.cassandra.service._
|
import org.apache.cassandra.service._
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.cassandra
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.{Actor, Transactor}
|
import se.scalablesolutions.akka.actor.{Actor, Transactor}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.common
|
||||||
|
|
||||||
import org.apache.commons.pool._
|
import org.apache.commons.pool._
|
||||||
import org.apache.commons.pool.impl._
|
import org.apache.commons.pool.impl._
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.common
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.stm._
|
||||||
import se.scalablesolutions.akka.stm.TransactionManagement.transaction
|
import se.scalablesolutions.akka.stm.TransactionManagement.transaction
|
||||||
import se.scalablesolutions.akka.collection._
|
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
// FIXME move to 'stm' package + add message with more info
|
// FIXME move to 'stm' package + add message with more info
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.common
|
||||||
|
|
||||||
// abstracts persistence storage
|
// abstracts persistence storage
|
||||||
trait StorageBackend
|
trait StorageBackend
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,18 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.mongo
|
||||||
|
|
||||||
import org.codehaus.aspectwerkz.proxy.Uuid
|
import se.scalablesolutions.akka.stm._
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
|
import se.scalablesolutions.akka.util.UUID
|
||||||
|
|
||||||
object MongoStorage extends Storage {
|
object MongoStorage extends Storage {
|
||||||
type ElementType = AnyRef
|
type ElementType = AnyRef
|
||||||
|
|
||||||
def newMap: PersistentMap[ElementType, ElementType] = newMap(Uuid.newUuid.toString)
|
def newMap: PersistentMap[ElementType, ElementType] = newMap(UUID.newUuid.toString)
|
||||||
def newVector: PersistentVector[ElementType] = newVector(Uuid.newUuid.toString)
|
def newVector: PersistentVector[ElementType] = newVector(UUID.newUuid.toString)
|
||||||
def newRef: PersistentRef[ElementType] = newRef(Uuid.newUuid.toString)
|
def newRef: PersistentRef[ElementType] = newRef(UUID.newUuid.toString)
|
||||||
|
|
||||||
def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id)
|
def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id)
|
||||||
def getVector(id: String): PersistentVector[ElementType] = newVector(id)
|
def getVector(id: String): PersistentVector[ElementType] = newVector(id)
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.mongo
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.stm._
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import sjson.json.Serializer._
|
import sjson.json.Serializer._
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.mongo
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.mongo
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,19 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.redis
|
||||||
|
|
||||||
import org.codehaus.aspectwerkz.proxy.Uuid
|
import se.scalablesolutions.akka.util.UUID
|
||||||
|
import se.scalablesolutions.akka.stm._
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
|
|
||||||
object RedisStorage extends Storage {
|
object RedisStorage extends Storage {
|
||||||
type ElementType = Array[Byte]
|
type ElementType = Array[Byte]
|
||||||
|
|
||||||
def newMap: PersistentMap[ElementType, ElementType] = newMap(Uuid.newUuid.toString)
|
def newMap: PersistentMap[ElementType, ElementType] = newMap(UUID.newUuid.toString)
|
||||||
def newVector: PersistentVector[ElementType] = newVector(Uuid.newUuid.toString)
|
def newVector: PersistentVector[ElementType] = newVector(UUID.newUuid.toString)
|
||||||
def newRef: PersistentRef[ElementType] = newRef(Uuid.newUuid.toString)
|
def newRef: PersistentRef[ElementType] = newRef(UUID.newUuid.toString)
|
||||||
override def newQueue: PersistentQueue[ElementType] = newQueue(Uuid.newUuid.toString)
|
override def newQueue: PersistentQueue[ElementType] = newQueue(UUID.newUuid.toString)
|
||||||
|
|
||||||
def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id)
|
def getMap(id: String): PersistentMap[ElementType, ElementType] = newMap(id)
|
||||||
def getVector(id: String): PersistentVector[ElementType] = newVector(id)
|
def getVector(id: String): PersistentVector[ElementType] = newVector(id)
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.redis
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.stm._
|
||||||
|
import se.scalablesolutions.akka.persistence.common._
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import se.scalablesolutions.akka.Config.config
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import com.redis._
|
import com.redis._
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.redis
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.redis
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
|
||||||
|
|
@ -15,9 +15,9 @@ import se.scalablesolutions.akka.actor.{Actor, Transactor}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case class NQ(accountNo: String)
|
case class NQ(accountNo: String)
|
||||||
case class DQ
|
case object DQ
|
||||||
case class MNDQ(accountNos: List[String], noOfDQs: Int, failer: Actor)
|
case class MNDQ(accountNos: List[String], noOfDQs: Int, failer: Actor)
|
||||||
case class SZ
|
case object SZ
|
||||||
|
|
||||||
class QueueActor extends Transactor {
|
class QueueActor extends Transactor {
|
||||||
private lazy val accounts = RedisStorage.newQueue
|
private lazy val accounts = RedisStorage.newQueue
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package se.scalablesolutions.akka.state
|
package se.scalablesolutions.akka.persistence.redis
|
||||||
|
|
||||||
import org.scalatest.Spec
|
import org.scalatest.Spec
|
||||||
import org.scalatest.matchers.ShouldMatchers
|
import org.scalatest.matchers.ShouldMatchers
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ package se.scalablesolutions.akka.rest
|
||||||
import com.sun.jersey.core.spi.component.ComponentScope
|
import com.sun.jersey.core.spi.component.ComponentScope
|
||||||
import com.sun.jersey.core.spi.component.ioc.IoCFullyManagedComponentProvider
|
import com.sun.jersey.core.spi.component.ioc.IoCFullyManagedComponentProvider
|
||||||
|
|
||||||
import config.Configurator
|
import se.scalablesolutions.akka.config.Configurator
|
||||||
import util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
|
||||||
class ActorComponentProvider(val clazz: Class[_], val configurators: List[Configurator])
|
class ActorComponentProvider(val clazz: Class[_], val configurators: List[Configurator])
|
||||||
extends IoCFullyManagedComponentProvider with Logging {
|
extends IoCFullyManagedComponentProvider with Logging {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package se.scalablesolutions.akka.rest
|
package se.scalablesolutions.akka.rest
|
||||||
|
|
||||||
import se.scalablesolutions.akka.config.ConfiguratorRepository
|
import se.scalablesolutions.akka.config.ConfiguratorRepository
|
||||||
|
import se.scalablesolutions.akka.config.Config.config
|
||||||
|
|
||||||
import com.sun.jersey.api.core.ResourceConfig
|
import com.sun.jersey.api.core.ResourceConfig
|
||||||
import com.sun.jersey.spi.container.servlet.ServletContainer
|
import com.sun.jersey.spi.container.servlet.ServletContainer
|
||||||
|
|
@ -20,14 +21,12 @@ class AkkaServlet extends ServletContainer {
|
||||||
import org.scala_tools.javautils.Imports._
|
import org.scala_tools.javautils.Imports._
|
||||||
|
|
||||||
override def initiate(resourceConfig: ResourceConfig, webApplication: WebApplication) = {
|
override def initiate(resourceConfig: ResourceConfig, webApplication: WebApplication) = {
|
||||||
//Kernel.boot // will boot if not already booted by 'main'
|
|
||||||
|
|
||||||
val configurators = ConfiguratorRepository.getConfigurators
|
val configurators = ConfiguratorRepository.getConfigurators
|
||||||
|
|
||||||
resourceConfig.getClasses.addAll(configurators.flatMap(_.getComponentInterfaces).asJava)
|
resourceConfig.getClasses.addAll(configurators.flatMap(_.getComponentInterfaces).asJava)
|
||||||
resourceConfig.getProperties.put(
|
resourceConfig.getProperties.put(
|
||||||
"com.sun.jersey.spi.container.ResourceFilters",
|
"com.sun.jersey.spi.container.ResourceFilters",
|
||||||
Config.config.getList("akka.rest.filters").mkString(","))
|
config.getList("akka.rest.filters").mkString(","))
|
||||||
|
|
||||||
webApplication.initiate(resourceConfig, new ActorComponentProviderFactory(configurators))
|
webApplication.initiate(resourceConfig, new ActorComponentProviderFactory(configurators))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,207 @@
|
||||||
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>.
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package se.scalablesolutions.akka.sample.chat
|
||||||
|
|
||||||
|
import se.scalablesolutions.akka.actor.{SupervisorFactory, Actor, RemoteActor}
|
||||||
|
import se.scalablesolutions.akka.stm.Transaction._
|
||||||
|
import se.scalablesolutions.akka.persistence.common.PersistentVector
|
||||||
|
import se.scalablesolutions.akka.persistence.redis.RedisStorage
|
||||||
|
import se.scalablesolutions.akka.remote.RemoteServer
|
||||||
|
import se.scalablesolutions.akka.util.Logging
|
||||||
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
|
import se.scalablesolutions.akka.config.OneForOneStrategy
|
||||||
|
|
||||||
|
import scala.collection.mutable.HashMap
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
To run the sample:
|
||||||
|
1. Run 'mvn install' (builds and deploys jar to AKKA_HOME/deploy)
|
||||||
|
2. In another shell run 'java -jar ./dist/akka-0.6.jar' to start up Akka microkernel
|
||||||
|
3. In the first shell run 'mvn scala:console -o'
|
||||||
|
4. In the REPL you get execute:
|
||||||
|
- scala> import se.scalablesolutions.akka.sample.chat._
|
||||||
|
- scala> Runner.run
|
||||||
|
5. See the chat simulation run
|
||||||
|
6. Run it again to see full speed after first initialization
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChatServer's internal events.
|
||||||
|
*/
|
||||||
|
sealed trait Event
|
||||||
|
case class Login(user: String) extends Event
|
||||||
|
case class Logout(user: String) extends Event
|
||||||
|
case class GetChatLog(from: String) extends Event
|
||||||
|
case class ChatLog(log: List[String]) extends Event
|
||||||
|
case class ChatMessage(from: String, message: String) extends Event
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat client.
|
||||||
|
*/
|
||||||
|
class ChatClient(val name: String) {
|
||||||
|
import Actor.Sender.Self
|
||||||
|
def login = ChatService ! Login(name)
|
||||||
|
def logout = ChatService ! Logout(name)
|
||||||
|
def post(message: String) = ChatService ! ChatMessage(name, name + ": " + message)
|
||||||
|
def chatLog: ChatLog = (ChatService !! GetChatLog(name)).getOrElse(throw new Exception("Couldn't get the chat log from ChatServer"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal chat client session.
|
||||||
|
*/
|
||||||
|
class Session(user: String, storage: Actor) extends Actor {
|
||||||
|
private val loginTime = System.currentTimeMillis
|
||||||
|
private var userLog: List[String] = Nil
|
||||||
|
|
||||||
|
log.info("New session for user [%s] has been created at [%s]", user, loginTime)
|
||||||
|
|
||||||
|
def receive = {
|
||||||
|
case msg @ ChatMessage(from, message) =>
|
||||||
|
userLog ::= message
|
||||||
|
storage ! msg
|
||||||
|
|
||||||
|
case msg @ GetChatLog(_) =>
|
||||||
|
storage forward msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction of chat storage holding the chat log.
|
||||||
|
*/
|
||||||
|
trait ChatStorage extends Actor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis-backed chat storage implementation.
|
||||||
|
*/
|
||||||
|
class RedisChatStorage extends ChatStorage {
|
||||||
|
lifeCycle = Some(LifeCycle(Permanent))
|
||||||
|
|
||||||
|
private var chatLog = atomic { RedisStorage.getVector("akka.chat.log") }
|
||||||
|
|
||||||
|
log.info("Redis-based chat storage is starting up...")
|
||||||
|
|
||||||
|
def receive = {
|
||||||
|
case msg @ ChatMessage(from, message) =>
|
||||||
|
log.debug("New chat message [%s]", message)
|
||||||
|
atomic {
|
||||||
|
chatLog + message.getBytes("UTF-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
case GetChatLog(_) =>
|
||||||
|
val messageList = atomic {
|
||||||
|
chatLog.map(bytes => new String(bytes, "UTF-8")).toList
|
||||||
|
}
|
||||||
|
reply(ChatLog(messageList))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def postRestart(reason: Throwable) = chatLog = RedisStorage.getVector("akka.chat.log")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements user session management.
|
||||||
|
* <p/>
|
||||||
|
* Uses self-type annotation (this: Actor =>) to declare that it needs to be mixed in with an Actor.
|
||||||
|
*/
|
||||||
|
trait SessionManagement { this: Actor =>
|
||||||
|
|
||||||
|
val storage: ChatStorage // needs someone to provide the ChatStorage
|
||||||
|
val sessions = new HashMap[String, Actor]
|
||||||
|
|
||||||
|
protected def sessionManagement: PartialFunction[Any, Unit] = {
|
||||||
|
case Login(username) =>
|
||||||
|
log.info("User [%s] has logged in", username)
|
||||||
|
val session = new Session(username, storage)
|
||||||
|
session.start
|
||||||
|
sessions += (username -> session)
|
||||||
|
|
||||||
|
case Logout(username) =>
|
||||||
|
log.info("User [%s] has logged out", username)
|
||||||
|
val session = sessions(username)
|
||||||
|
session.stop
|
||||||
|
sessions -= username
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def shutdownSessions =
|
||||||
|
sessions.foreach { case (_, session) => session.stop }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements chat management, e.g. chat message dispatch.
|
||||||
|
* <p/>
|
||||||
|
* Uses self-type annotation (this: Actor =>) to declare that it needs to be mixed in with an Actor.
|
||||||
|
*/
|
||||||
|
trait ChatManagement { this: Actor =>
|
||||||
|
val sessions: HashMap[String, Actor] // needs someone to provide the Session map
|
||||||
|
|
||||||
|
protected def chatManagement: PartialFunction[Any, Unit] = {
|
||||||
|
case msg @ ChatMessage(from, _) => sessions(from) ! msg
|
||||||
|
case msg @ GetChatLog(from) => sessions(from) forward msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and links a RedisChatStorage.
|
||||||
|
*/
|
||||||
|
trait RedisChatStorageFactory { this: Actor =>
|
||||||
|
val storage: ChatStorage = spawnLink(classOf[RedisChatStorage]) // starts and links ChatStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat server. Manages sessions and redirects all other messages to the Session for the client.
|
||||||
|
*/
|
||||||
|
trait ChatServer extends Actor {
|
||||||
|
faultHandler = Some(OneForOneStrategy(5, 5000))
|
||||||
|
trapExit = List(classOf[Exception])
|
||||||
|
|
||||||
|
val storage: ChatStorage
|
||||||
|
|
||||||
|
log.info("Chat service is starting up...")
|
||||||
|
|
||||||
|
// actor message handler
|
||||||
|
def receive = sessionManagement orElse chatManagement
|
||||||
|
|
||||||
|
// abstract methods to be defined somewhere else
|
||||||
|
protected def chatManagement: PartialFunction[Any, Unit]
|
||||||
|
protected def sessionManagement: PartialFunction[Any, Unit]
|
||||||
|
protected def shutdownSessions: Unit
|
||||||
|
|
||||||
|
override def shutdown = {
|
||||||
|
log.info("Chat server is shutting down...")
|
||||||
|
shutdownSessions
|
||||||
|
unlink(storage)
|
||||||
|
storage.stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object encapsulating the full Chat Service.
|
||||||
|
*/
|
||||||
|
object ChatService extends
|
||||||
|
ChatServer with
|
||||||
|
SessionManagement with
|
||||||
|
ChatManagement with
|
||||||
|
RedisChatStorageFactory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test runner emulating a chat session.
|
||||||
|
*/
|
||||||
|
object Runner {
|
||||||
|
// create a handle to the remote ChatService
|
||||||
|
ChatService.makeRemote("localhost", 9999)
|
||||||
|
ChatService.start
|
||||||
|
|
||||||
|
def run = {
|
||||||
|
val client = new ChatClient("jonas")
|
||||||
|
|
||||||
|
client.login
|
||||||
|
|
||||||
|
client.post("Hi there")
|
||||||
|
println("CHAT LOG:\n\t" + client.chatLog.log.mkString("\n\t"))
|
||||||
|
|
||||||
|
client.post("Hi again")
|
||||||
|
println("CHAT LOG:\n\t" + client.chatLog.log.mkString("\n\t"))
|
||||||
|
|
||||||
|
client.logout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ package sample.lift
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.{Transactor, Actor}
|
import se.scalablesolutions.akka.actor.{Transactor, Actor}
|
||||||
import se.scalablesolutions.akka.config.ScalaConfig._
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import se.scalablesolutions.akka.state.{CassandraStorage, TransactionalState}
|
import se.scalablesolutions.akka.stm.TransactionalState
|
||||||
|
import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage
|
||||||
|
|
||||||
import java.lang.Integer
|
import java.lang.Integer
|
||||||
import javax.ws.rs.{GET, Path, Produces}
|
import javax.ws.rs.{GET, Path, Produces}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import javax.ws.rs.Produces;
|
||||||
import se.scalablesolutions.akka.annotation.transactionrequired;
|
import se.scalablesolutions.akka.annotation.transactionrequired;
|
||||||
import se.scalablesolutions.akka.annotation.prerestart;
|
import se.scalablesolutions.akka.annotation.prerestart;
|
||||||
import se.scalablesolutions.akka.annotation.postrestart;
|
import se.scalablesolutions.akka.annotation.postrestart;
|
||||||
import se.scalablesolutions.akka.state.PersistentMap;
|
import se.scalablesolutions.akka.persistence.common.PersistentMap;
|
||||||
import se.scalablesolutions.akka.state.CassandraStorage;
|
import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import javax.ws.rs.Produces;
|
||||||
import se.scalablesolutions.akka.annotation.transactionrequired;
|
import se.scalablesolutions.akka.annotation.transactionrequired;
|
||||||
import se.scalablesolutions.akka.annotation.prerestart;
|
import se.scalablesolutions.akka.annotation.prerestart;
|
||||||
import se.scalablesolutions.akka.annotation.postrestart;
|
import se.scalablesolutions.akka.annotation.postrestart;
|
||||||
import se.scalablesolutions.akka.state.TransactionalState;
|
import se.scalablesolutions.akka.stm.TransactionalState;
|
||||||
import se.scalablesolutions.akka.state.TransactionalMap;
|
import se.scalablesolutions.akka.stm.TransactionalMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try service out by invoking (multiple times):
|
* Try service out by invoking (multiple times):
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@
|
||||||
package sample.scala
|
package sample.scala
|
||||||
|
|
||||||
import se.scalablesolutions.akka.actor.{Transactor, SupervisorFactory, Actor}
|
import se.scalablesolutions.akka.actor.{Transactor, SupervisorFactory, Actor}
|
||||||
import se.scalablesolutions.akka.state.{CassandraStorage, TransactionalState}
|
import se.scalablesolutions.akka.stm.TransactionalState
|
||||||
|
import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage
|
||||||
import se.scalablesolutions.akka.config.ScalaConfig._
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import se.scalablesolutions.akka.comet.{AkkaClusterBroadcastFilter}
|
import se.scalablesolutions.akka.comet.AkkaClusterBroadcastFilter
|
||||||
|
|
||||||
import java.lang.Integer
|
import java.lang.Integer
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import se.scalablesolutions.akka.actor.{SupervisorFactory, Actor}
|
||||||
import se.scalablesolutions.akka.config.ScalaConfig._
|
import se.scalablesolutions.akka.config.ScalaConfig._
|
||||||
import se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import se.scalablesolutions.akka.security.{DigestAuthenticationActor, UserInfo}
|
import se.scalablesolutions.akka.security.{DigestAuthenticationActor, UserInfo}
|
||||||
import se.scalablesolutions.akka.state.TransactionalState
|
import se.scalablesolutions.akka.stm.TransactionalState
|
||||||
|
|
||||||
class Boot {
|
class Boot {
|
||||||
val factory = SupervisorFactory(
|
val factory = SupervisorFactory(
|
||||||
|
|
|
||||||
|
|
@ -22,20 +22,21 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.security
|
package se.scalablesolutions.akka.security
|
||||||
|
|
||||||
import _root_.se.scalablesolutions.akka.actor.{Scheduler, Actor, ActorRegistry}
|
import se.scalablesolutions.akka.actor.{Scheduler, Actor, ActorRegistry}
|
||||||
import _root_.se.scalablesolutions.akka.util.Logging
|
import se.scalablesolutions.akka.util.Logging
|
||||||
import _root_.se.scalablesolutions.akka.Config
|
import se.scalablesolutions.akka.config.Config
|
||||||
|
|
||||||
import _root_.com.sun.jersey.api.model.AbstractMethod
|
import com.sun.jersey.api.model.AbstractMethod
|
||||||
import _root_.com.sun.jersey.spi.container.{ResourceFilterFactory, ContainerRequest, ContainerRequestFilter, ContainerResponse, ContainerResponseFilter, ResourceFilter}
|
import com.sun.jersey.spi.container.{ResourceFilterFactory, ContainerRequest, ContainerRequestFilter, ContainerResponse, ContainerResponseFilter, ResourceFilter}
|
||||||
import _root_.com.sun.jersey.core.util.Base64
|
import com.sun.jersey.core.util.Base64
|
||||||
import _root_.javax.ws.rs.core.{SecurityContext, Context, Response}
|
|
||||||
import _root_.javax.ws.rs.WebApplicationException
|
|
||||||
import _root_.javax.annotation.security.{DenyAll, PermitAll, RolesAllowed}
|
|
||||||
import _root_.java.security.Principal
|
|
||||||
import _root_.java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
import _root_.net.liftweb.util.{SecurityHelpers, StringHelpers, IoHelpers}
|
import javax.ws.rs.core.{SecurityContext, Context, Response}
|
||||||
|
import javax.ws.rs.WebApplicationException
|
||||||
|
import javax.annotation.security.{DenyAll, PermitAll, RolesAllowed}
|
||||||
|
import java.security.Principal
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
import net.liftweb.util.{SecurityHelpers, StringHelpers, IoHelpers}
|
||||||
|
|
||||||
object Enc extends SecurityHelpers with StringHelpers with IoHelpers
|
object Enc extends SecurityHelpers with StringHelpers with IoHelpers
|
||||||
|
|
||||||
|
|
@ -329,19 +330,19 @@ trait DigestAuthenticationActor extends AuthenticationActor[DigestCredentials] {
|
||||||
def noncePurgeInterval = 2 * 60 * 1000 //ms
|
def noncePurgeInterval = 2 * 60 * 1000 //ms
|
||||||
}
|
}
|
||||||
|
|
||||||
import _root_.java.security.Principal
|
import java.security.Principal
|
||||||
import _root_.java.security.PrivilegedActionException
|
import java.security.PrivilegedActionException
|
||||||
import _root_.java.security.PrivilegedExceptionAction
|
import java.security.PrivilegedExceptionAction
|
||||||
|
|
||||||
import _root_.javax.security.auth.login.AppConfigurationEntry
|
import javax.security.auth.login.AppConfigurationEntry
|
||||||
import _root_.javax.security.auth.login.Configuration
|
import javax.security.auth.login.Configuration
|
||||||
import _root_.javax.security.auth.login.LoginContext
|
import javax.security.auth.login.LoginContext
|
||||||
import _root_.javax.security.auth.Subject
|
import javax.security.auth.Subject
|
||||||
import _root_.javax.security.auth.kerberos.KerberosPrincipal
|
import javax.security.auth.kerberos.KerberosPrincipal
|
||||||
|
|
||||||
import _root_.org.ietf.jgss.GSSContext
|
import org.ietf.jgss.GSSContext
|
||||||
import _root_.org.ietf.jgss.GSSCredential
|
import org.ietf.jgss.GSSCredential
|
||||||
import _root_.org.ietf.jgss.GSSManager
|
import org.ietf.jgss.GSSManager
|
||||||
|
|
||||||
trait SpnegoAuthenticationActor extends AuthenticationActor[SpnegoCredentials] {
|
trait SpnegoAuthenticationActor extends AuthenticationActor[SpnegoCredentials] {
|
||||||
override def unauthorized =
|
override def unauthorized =
|
||||||
|
|
@ -349,7 +350,7 @@ trait SpnegoAuthenticationActor extends AuthenticationActor[SpnegoCredentials] {
|
||||||
|
|
||||||
// for some reason the jersey Base64 class does not work with kerberos
|
// for some reason the jersey Base64 class does not work with kerberos
|
||||||
// but the commons Base64 does
|
// but the commons Base64 does
|
||||||
import _root_.org.apache.commons.codec.binary.Base64
|
import org.apache.commons.codec.binary.Base64
|
||||||
override def extractCredentials(r: Req): Option[SpnegoCredentials] = {
|
override def extractCredentials(r: Req): Option[SpnegoCredentials] = {
|
||||||
val AuthHeader = """Negotiate\s(.*)""".r
|
val AuthHeader = """Negotiate\s(.*)""".r
|
||||||
|
|
||||||
|
|
|
||||||
74
akka-security/src/test/scala/SecuritySpec.scala
Normal file
74
akka-security/src/test/scala/SecuritySpec.scala
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.scalablesolutions.akka.security
|
||||||
|
|
||||||
|
import config.ScalaConfig._
|
||||||
|
|
||||||
|
import org.scalatest.Suite
|
||||||
|
import org.scalatest.junit.JUnitSuite
|
||||||
|
import org.scalatest.matchers.MustMatchers
|
||||||
|
import org.scalatest.mock.MockitoSugar
|
||||||
|
import org.mockito.Mockito._
|
||||||
|
import org.mockito.Matchers._
|
||||||
|
import org.junit.{Before, After, Test}
|
||||||
|
|
||||||
|
import javax.ws.rs.core.{SecurityContext, Context, Response}
|
||||||
|
import com.sun.jersey.spi.container.{ResourceFilterFactory, ContainerRequest, ContainerRequestFilter, ContainerResponse, ContainerResponseFilter, ResourceFilter}
|
||||||
|
import com.sun.jersey.core.util.Base64
|
||||||
|
|
||||||
|
class BasicAuthenticatorSpec extends junit.framework.TestCase
|
||||||
|
with Suite with MockitoSugar with MustMatchers {
|
||||||
|
val authenticator = new BasicAuthenticator
|
||||||
|
authenticator.start
|
||||||
|
|
||||||
|
@Test def testChallenge = {
|
||||||
|
val req = mock[ContainerRequest]
|
||||||
|
|
||||||
|
val result: Response = (authenticator !! (Authenticate(req, List("foo")), 10000)).get
|
||||||
|
|
||||||
|
// the actor replies with a challenge for the browser
|
||||||
|
result.getStatus must equal(Response.Status.UNAUTHORIZED.getStatusCode)
|
||||||
|
result.getMetadata.get("WWW-Authenticate").get(0).toString must startWith("Basic")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test def testAuthenticationSuccess = {
|
||||||
|
val req = mock[ContainerRequest]
|
||||||
|
// fake a basic auth header -> this will authenticate the user
|
||||||
|
when(req.getHeaderValue("Authorization")).thenReturn("Basic " + new String(Base64.encode("foo:bar")))
|
||||||
|
|
||||||
|
// fake a request authorization -> this will authorize the user
|
||||||
|
when(req.isUserInRole("chef")).thenReturn(true)
|
||||||
|
|
||||||
|
val result: AnyRef = (authenticator !! (Authenticate(req, List("chef")), 10000)).get
|
||||||
|
|
||||||
|
result must be(OK)
|
||||||
|
// the authenticator must have set a security context
|
||||||
|
verify(req).setSecurityContext(any[SecurityContext])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test def testUnauthorized = {
|
||||||
|
val req = mock[ContainerRequest]
|
||||||
|
|
||||||
|
// fake a basic auth header -> this will authenticate the user
|
||||||
|
when(req.getHeaderValue("Authorization")).thenReturn("Basic " + new String(Base64.encode("foo:bar")))
|
||||||
|
when(req.isUserInRole("chef")).thenReturn(false) // this will deny access
|
||||||
|
|
||||||
|
val result: Response = (authenticator !! (Authenticate(req, List("chef")), 10000)).get
|
||||||
|
|
||||||
|
result.getStatus must equal(Response.Status.FORBIDDEN.getStatusCode)
|
||||||
|
|
||||||
|
// the authenticator must have set a security context
|
||||||
|
verify(req).setSecurityContext(any[SecurityContext])
|
||||||
|
}
|
||||||
|
|
||||||
|
class BasicAuthenticator extends BasicAuthenticationActor {
|
||||||
|
def verify(odc: Option[BasicCredentials]): Option[UserInfo] = odc match {
|
||||||
|
case Some(dc) => Some(UserInfo("foo", "bar", "ninja" :: "chef" :: Nil))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
override def realm = "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
package se.scalablesolutions.akka.util
|
package se.scalablesolutions.akka.util
|
||||||
|
|
||||||
trait Bootable {
|
trait Bootable {
|
||||||
def onLoad : Unit = ()
|
def onLoad {}
|
||||||
def onUnload : Unit = ()
|
def onUnload {}
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,6 @@ object Helpers extends Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================
|
// ================================================
|
||||||
@serializable
|
|
||||||
class ReadWriteLock {
|
class ReadWriteLock {
|
||||||
private val rwl = new ReentrantReadWriteLock
|
private val rwl = new ReentrantReadWriteLock
|
||||||
private val readLock = rwl.readLock
|
private val readLock = rwl.readLock
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ package se.scalablesolutions.akka.util
|
||||||
|
|
||||||
import net.lag.logging.Logger
|
import net.lag.logging.Logger
|
||||||
|
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base trait for all classes that wants to be able use the logging infrastructure.
|
* Base trait for all classes that wants to be able use the logging infrastructure.
|
||||||
|
|
@ -30,6 +30,7 @@ trait Logging {
|
||||||
*
|
*
|
||||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||||
*/
|
*/
|
||||||
|
// FIXME make use of LoggableException
|
||||||
class LoggableException extends Exception with Logging {
|
class LoggableException extends Exception with Logging {
|
||||||
private val uniqueId = getExceptionID
|
private val uniqueId = getExceptionID
|
||||||
private var originalException: Option[Exception] = None
|
private var originalException: Option[Exception] = None
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
service = on
|
service = on
|
||||||
fair = on # should transactions be fair or non-fair (non fair yield better performance)
|
fair = on # should transactions be fair or non-fair (non fair yield better performance)
|
||||||
max-nr-of-retries = 1000 # max nr of retries of a failing transaction before giving up
|
max-nr-of-retries = 1000 # max nr of retries of a failing transaction before giving up
|
||||||
timeout = 10000 # transaction timeout; if transaction have not committed within the timeout then it is aborted
|
timeout = 10000 # transaction timeout; if transaction has not committed within the timeout then it is aborted
|
||||||
distributed = off # not implemented yet
|
distributed = off # not implemented yet
|
||||||
</stm>
|
</stm>
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
<cluster>
|
<cluster>
|
||||||
service = on # FIXME add 'service = on' for <cluster>
|
service = on # FIXME add 'service = on' for <cluster>
|
||||||
name = "default" # The name of the cluster
|
name = "default" # The name of the cluster
|
||||||
actor = "se.scalablesolutions.akka.remote.JGroupsClusterActor" # FQN of an implementation of ClusterActor
|
actor = "se.scalablesolutions.akka.cluster.jgroups.JGroupsClusterActor" # FQN of an implementation of ClusterActor
|
||||||
serializer = "se.scalablesolutions.akka.serialization.Serializer$Java" # FQN of the serializer class
|
serializer = "se.scalablesolutions.akka.serialization.Serializer$Java" # FQN of the serializer class
|
||||||
</cluster>
|
</cluster>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# This config import the Akka reference configuration.
|
# This config imports the Akka reference configuration.
|
||||||
include "akka-reference.conf"
|
include "akka-reference.conf"
|
||||||
|
|
||||||
# In this file you can override any option defined in the 'akka-reference.conf' file.
|
# In this file you can override any option defined in the 'akka-reference.conf' file.
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) {
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// create executable jar
|
// create executable jar
|
||||||
override def mainClass = Some("se.scalablesolutions.akka.Main")
|
override def mainClass = Some("se.scalablesolutions.akka.kernel.Main")
|
||||||
|
|
||||||
override def packageOptions =
|
override def packageOptions =
|
||||||
manifestClassPath.map(cp => ManifestAttributes((Attributes.Name.CLASS_PATH, cp))).toList :::
|
manifestClassPath.map(cp => ManifestAttributes((Attributes.Name.CLASS_PATH, cp))).toList :::
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue