From 51ea522580fb6cda0f1f15f44bc53c9ad13fc8bb Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 28 Feb 2012 12:28:03 +0100 Subject: [PATCH 01/46] Removing reduntant reduntancy. --- akka-actor/src/main/scala/akka/actor/Actor.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala index e583180af7..9adff5594e 100644 --- a/akka-actor/src/main/scala/akka/actor/Actor.scala +++ b/akka-actor/src/main/scala/akka/actor/Actor.scala @@ -189,8 +189,6 @@ trait Actor { "\n\tYou cannot create an instance of [" + getClass.getName + "] explicitly using the constructor (new)." + "\n\tYou have to use one of the factory methods to create a new actor. Either use:" + "\n\t\t'val actor = context.actorOf(Props[MyActor])' (to create a supervised child actor from within an actor), or" + - "\n\t\t'val actor = system.actorOf(Props(new MyActor(..)))' (to create a top level actor from the ActorSystem), or" + - "\n\t\t'val actor = context.actorOf(Props[MyActor])' (to create a supervised child actor from within an actor), or" + "\n\t\t'val actor = system.actorOf(Props(new MyActor(..)))' (to create a top level actor from the ActorSystem)") if (contextStack.isEmpty) noContextError From 8a5db512f316088256103775e350ef6034f76188 Mon Sep 17 00:00:00 2001 From: Roland Date: Tue, 28 Feb 2012 15:48:02 +0100 Subject: [PATCH 02/46] fix shutdown of remote routers, see #1872 - ActorCell.stop(actor) removed the actor from childrenRefs before handleChildTerminated, leading to removing from Locker immediately after adding it in - intercept ChildTerminated message in RemoteTransport.receive if destination is not found (i.e. isTerminate==true) and re-route to Locker, which was changed to support path-based lookup to find the parent and funnel the ChildTerminated to its intended destination - add Locker.shutdown() to detach remaining actors from their dispatchers upon system termination. --- .../src/main/scala/akka/actor/ActorCell.scala | 5 ++-- .../main/scala/akka/actor/ActorSystem.scala | 1 + .../src/main/scala/akka/actor/Locker.scala | 29 +++++++++++++++---- .../akka/dispatch/AbstractDispatcher.scala | 26 +++++++++++++++++ .../scala/akka/remote/RemoteTransport.scala | 2 ++ 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index e659928743..227030fe10 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -256,10 +256,9 @@ private[akka] class ActorCell( final def stop(actor: ActorRef): Unit = { val a = actor.asInstanceOf[InternalActorRef] - if (childrenRefs contains actor.path.name) { + if (a.getParent == self && (childrenRefs contains actor.path.name)) { system.locker ! a - childrenRefs -= actor.path.name - handleChildTerminated(actor) + handleChildTerminated(actor) // will remove child from childrenRefs } a.stop() } diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index de1689e730..1daad13963 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -497,6 +497,7 @@ class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Conf private lazy val _start: this.type = { // the provider is expected to start default loggers, LocalActorRefProvider does this provider.init(this) + registerOnTermination(locker.shutdown()) registerOnTermination(stopScheduler()) loadExtensions() if (LogConfigOnStart) logConfiguration() diff --git a/akka-actor/src/main/scala/akka/actor/Locker.scala b/akka-actor/src/main/scala/akka/actor/Locker.scala index 4f9caaeedc..a9eb0ff2e6 100644 --- a/akka-actor/src/main/scala/akka/actor/Locker.scala +++ b/akka-actor/src/main/scala/akka/actor/Locker.scala @@ -23,8 +23,8 @@ private[akka] class Locker( val iter = heap.entrySet.iterator while (iter.hasNext) { val soul = iter.next() - deathWatch.subscribe(Locker.this, soul.getKey) // in case Terminated got lost somewhere - soul.getKey match { + deathWatch.subscribe(Locker.this, soul.getValue) // in case Terminated got lost somewhere + soul.getValue match { case _: LocalRef ⇒ // nothing to do, they know what they signed up for case nonlocal ⇒ nonlocal.stop() // try again in case it was due to a communications failure } @@ -32,17 +32,17 @@ private[akka] class Locker( } } - private val heap = new ConcurrentHashMap[InternalActorRef, Long] + private val heap = new ConcurrentHashMap[ActorPath, InternalActorRef] scheduler.schedule(period, period, new DavyJones) override def sendSystemMessage(msg: SystemMessage): Unit = this.!(msg) override def !(msg: Any)(implicit sender: ActorRef = null): Unit = msg match { - case Terminated(soul) ⇒ heap.remove(soul) - case ChildTerminated(soul) ⇒ heap.remove(soul) + case Terminated(soul) ⇒ heap.remove(soul.path) + case ChildTerminated(soul) ⇒ heap.remove(soul.path) case soul: InternalActorRef ⇒ - heap.put(soul, 0l) // wanted to put System.nanoTime and do something intelligent, but forgot what that was + heap.put(soul.path, soul) deathWatch.subscribe(this, soul) // now re-bind the soul so that it does not drown its parent soul match { @@ -54,4 +54,21 @@ private[akka] class Locker( case _ ⇒ // ignore } + def childTerminated(parent: ActorRef, ct: ChildTerminated): Unit = { + heap.get(parent.path) match { + case null ⇒ + case ref ⇒ ref.sendSystemMessage(ct) + } + } + + def shutdown(): Unit = { + import scala.collection.JavaConverters._ + for (soul ← heap.values.asScala) { + soul match { + case l: LocalActorRef ⇒ l.underlying.dispatcher.detach(l.underlying) + case _ ⇒ + } + } + } + } diff --git a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala index e8389c69fc..6ba3c4e14e 100644 --- a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala +++ b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala @@ -16,6 +16,7 @@ import akka.serialization.SerializationExtension import akka.util.NonFatal import akka.event.Logging.LogEventException import akka.jsr166y.{ ForkJoinTask, ForkJoinPool } +import akka.util.Index final case class Envelope(val message: Any, val sender: ActorRef)(system: ActorSystem) { if (message.isInstanceOf[AnyRef]) { @@ -180,6 +181,29 @@ object MessageDispatcher { val SCHEDULED = 1 val RESCHEDULED = 2 + // dispatcher debugging helper using println (see below) + // since this is a compile-time constant, scalac will elide code behind if (MessageDispatcher.debug) (RK checked with 2.9.1) + final val debug = false + lazy val actors = new Index[MessageDispatcher, ActorRef](16, _ compareTo _) + def printActors: Unit = if (debug) { + for { + d ← actors.keys + val c = println(d + " inhabitants: " + d.inhabitants) + a ← actors.valueIterator(d) + } { + val status = if (a.isTerminated) " (terminated)" else " (alive)" + val messages = a match { + case l: LocalActorRef ⇒ " " + l.underlying.mailbox.numberOfMessages + " messages" + case _ ⇒ " " + a.getClass + } + val parent = a match { + case i: InternalActorRef ⇒ ", parent: " + i.getParent + case _ ⇒ "" + } + println(" -> " + a + status + messages + parent) + } + } + implicit def defaultDispatcher(implicit system: ActorSystem): MessageDispatcher = system.dispatcher } @@ -267,6 +291,7 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext * If you override it, you must call it. But only ever once. See "attach" for only invocation. */ protected[akka] def register(actor: ActorCell) { + if (debug) actors.put(this, actor.self) inhabitantsUpdater.incrementAndGet(this) } @@ -274,6 +299,7 @@ abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) ext * If you override it, you must call it. But only ever once. See "detach" for the only invocation */ protected[akka] def unregister(actor: ActorCell) { + if (debug) actors.remove(this, actor.self) inhabitantsUpdater.decrementAndGet(this) val mailBox = actor.mailbox mailBox.becomeClosed() // FIXME reschedule in tell if possible race with cleanUp is detected in order to properly clean up diff --git a/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala b/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala index 0a5088adcd..1af4a6103b 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala @@ -11,6 +11,7 @@ import akka.event.{ LoggingAdapter, Logging } import akka.AkkaException import akka.serialization.Serialization import akka.remote.RemoteProtocol._ +import akka.dispatch.ChildTerminated /** * Remote life-cycle events. @@ -273,6 +274,7 @@ trait RemoteMarshallingOps { case l: LocalRef ⇒ if (provider.remoteSettings.LogReceive) log.debug("received local message {}", remoteMessage) remoteMessage.payload match { + case ct: ChildTerminated if l.isTerminated ⇒ provider.locker.childTerminated(l, ct) case msg: SystemMessage ⇒ if (useUntrustedMode) throw new SecurityException("RemoteModule server is operating is untrusted mode, can not send system message") From fc78ebcf34eb842689adbad4dfe5cc286f32e9bb Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 29 Feb 2012 11:49:30 +0100 Subject: [PATCH 03/46] Removing wasteful repos --- project/AkkaBuild.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index 43a34e640c..fc97437db0 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -345,8 +345,6 @@ object AkkaBuild extends Build { lazy val defaultSettings = baseSettings ++ formatSettings ++ Seq( resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/", - resolvers += "Twitter Public Repo" at "http://maven.twttr.com", // This will be going away with com.mongodb.async's next release - resolvers += "Typesafe Snapshot Repo" at "http://repo.typesafe.com/typesafe/snapshots/", // Used while play-mini is still on RC // compile options scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked") ++ ( From f654d5d808a1d05a27c236dfb87f8b0916d0115e Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 29 Feb 2012 13:55:09 +0100 Subject: [PATCH 04/46] Re-adding the twitter repo since it is needed, sigh --- project/AkkaBuild.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index fc97437db0..d7053b0394 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -328,7 +328,8 @@ object AkkaBuild extends Build { // Settings override lazy val settings = super.settings ++ buildSettings ++ Seq( - resolvers += "Sonatype Snapshot Repo" at "https://oss.sonatype.org/content/repositories/snapshots/" + resolvers += "Sonatype Snapshot Repo" at "https://oss.sonatype.org/content/repositories/snapshots/", + resolvers += "Twitter Public Repo" at "http://maven.twttr.com" // This will be going away with com.mongodb.async's next release ) lazy val baseSettings = Defaults.defaultSettings ++ Publish.settings From 9df60801965e3e0255e8bd7b5ae2f51109b0e5b6 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 29 Feb 2012 13:50:08 -0500 Subject: [PATCH 05/46] Cherry-pick ConfigFactory class loader fixes to com.typesafe.config This is commit 9733578ebbce6fc00b9e611540c3f24b76289911 and commit 30bdac884b4ef256242db7e4fcee44df9f9921de from typesafehub/config. Default and reference configs are no longer cached, and use the thread's context class loader instead of ConfigImpl.class.getClassLoader(). --- .../com/typesafe/config/ConfigFactory.java | 298 ++++++++++++++---- .../com/typesafe/config/impl/ConfigImpl.java | 31 +- 2 files changed, 261 insertions(+), 68 deletions(-) diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java index 1b819ab4c5..49cff71d57 100755 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java @@ -11,7 +11,6 @@ import java.util.Map; import java.util.Properties; import com.typesafe.config.impl.ConfigImpl; -import com.typesafe.config.impl.ConfigImplUtil; import com.typesafe.config.impl.Parseable; /** @@ -41,6 +40,12 @@ public final class ConfigFactory { * {@link Class#getResource}). * *

+ * Resources are loaded from the current thread's + * {@link Thread#getContextClassLoader()}. In general, a library needs its + * configuration to come from the class loader used to load that library, so + * the proper "reference.conf" are present. + * + *

* The loaded object will already be resolved (substitutions have already * been processed). As a result, if you add more fallbacks then they won't * be seen by substitutions. Substitutions are the "${foo.bar}" syntax. If @@ -49,16 +54,29 @@ public final class ConfigFactory { * * @param resourceBasename * name (optionally without extension) of a resource on classpath - * @return configuration for an application + * @return configuration for an application relative to context class loader */ public static Config load(String resourceBasename) { - return load(resourceBasename, ConfigParseOptions.defaults(), + return load(Thread.currentThread().getContextClassLoader(), resourceBasename); + } + + /** + * Like {@link #load(String)} but uses the supplied class loader instead of + * the current thread's context class loader. + * + * @param loader + * @param resourceBasename + * @return configuration for an application relative to given class loader + */ + public static Config load(ClassLoader loader, String resourceBasename) { + return load(loader, resourceBasename, ConfigParseOptions.defaults(), ConfigResolveOptions.defaults()); } /** * Like {@link #load(String)} but allows you to specify parse and resolve * options. + * * @param resourceBasename * the classpath resource name with optional extension * @param parseOptions @@ -69,9 +87,29 @@ public final class ConfigFactory { */ public static Config load(String resourceBasename, ConfigParseOptions parseOptions, ConfigResolveOptions resolveOptions) { - Config appConfig = ConfigFactory.parseResourcesAnySyntax(ConfigFactory.class, "/" - + resourceBasename, parseOptions); - return load(appConfig, resolveOptions); + return load(Thread.currentThread().getContextClassLoader(), resourceBasename, parseOptions, + resolveOptions); + } + + /** + * Like {@link #load(String,ConfigParseOptions,ConfigResolveOptions)} but + * allows you to specify a class loader + * + * @param loader + * class loader in which to find resources + * @param resourceBasename + * the classpath resource name with optional extension + * @param parseOptions + * options to use when parsing the resource + * @param resolveOptions + * options to use when resolving the stack + * @return configuration for an application + */ + public static Config load(ClassLoader loader, String resourceBasename, + ConfigParseOptions parseOptions, ConfigResolveOptions resolveOptions) { + Config appConfig = ConfigFactory.parseResourcesAnySyntax(loader, resourceBasename, + parseOptions); + return load(loader, appConfig, resolveOptions); } /** @@ -85,7 +123,11 @@ public final class ConfigFactory { * @return resolved configuration with overrides and fallbacks added */ public static Config load(Config config) { - return load(config, ConfigResolveOptions.defaults()); + return load(Thread.currentThread().getContextClassLoader(), config); + } + + public static Config load(ClassLoader loader, Config config) { + return load(loader, config, ConfigResolveOptions.defaults()); } /** @@ -99,53 +141,64 @@ public final class ConfigFactory { * @return resolved configuration with overrides and fallbacks added */ public static Config load(Config config, ConfigResolveOptions resolveOptions) { - return defaultOverrides().withFallback(config).withFallback(defaultReference()) + return load(Thread.currentThread().getContextClassLoader(), config, resolveOptions); + } + + /** + * Like {@link #load(Config,ConfigResolveOptions)} but allows you to specify + * a class loader other than the context class loader. + * + * @param loader + * class loader to use when looking up override and reference + * configs + * @param config + * the application's portion of the configuration + * @param resolveOptions + * options for resolving the assembled config stack + * @return resolved configuration with overrides and fallbacks added + */ + public static Config load(ClassLoader loader, Config config, ConfigResolveOptions resolveOptions) { + return defaultOverrides(loader).withFallback(config).withFallback(defaultReference(loader)) .resolve(resolveOptions); } - private static class DefaultConfigHolder { + private static Config loadDefaultConfig(ClassLoader loader) { + int specified = 0; - private static Config loadDefaultConfig() { - int specified = 0; + // override application.conf with config.file, config.resource, + // config.url if requested. + String resource = System.getProperty("config.resource"); + if (resource != null) + specified += 1; + String file = System.getProperty("config.file"); + if (file != null) + specified += 1; + String url = System.getProperty("config.url"); + if (url != null) + specified += 1; - // override application.conf with config.file, config.resource, - // config.url if requested. - String resource = System.getProperty("config.resource"); - if (resource != null) - specified += 1; - String file = System.getProperty("config.file"); - if (file != null) - specified += 1; - String url = System.getProperty("config.url"); - if (url != null) - specified += 1; - - if (specified == 0) { - return load("application"); - } else if (specified > 1) { - throw new ConfigException.Generic("You set more than one of config.file='" + file - + "', config.url='" + url + "', config.resource='" + resource - + "'; don't know which one to use!"); + if (specified == 0) { + return load(loader, "application"); + } else if (specified > 1) { + throw new ConfigException.Generic("You set more than one of config.file='" + file + + "', config.url='" + url + "', config.resource='" + resource + + "'; don't know which one to use!"); + } else { + if (resource != null) { + // this deliberately does not parseResourcesAnySyntax; if + // people want that they can use an include statement. + return load(loader, parseResources(loader, resource)); + } else if (file != null) { + return load(loader, parseFile(new File(file))); } else { - if (resource != null) { - // this deliberately does not parseResourcesAnySyntax; if - // people want that they can use an include statement. - return load(parseResources(ConfigFactory.class, resource)); - } else if (file != null) { - return load(parseFile(new File(file))); - } else { - try { - return load(parseURL(new URL(url))); - } catch (MalformedURLException e) { - throw new ConfigException.Generic( - "Bad URL in config.url system property: '" + url + "': " - + e.getMessage(), e); - } + try { + return load(loader, parseURL(new URL(url))); + } catch (MalformedURLException e) { + throw new ConfigException.Generic("Bad URL in config.url system property: '" + + url + "': " + e.getMessage(), e); } } } - - static final Config defaultConfig = loadDefaultConfig(); } /** @@ -176,11 +229,19 @@ public final class ConfigFactory { * @return configuration for an application */ public static Config load() { - try { - return DefaultConfigHolder.defaultConfig; - } catch (ExceptionInInitializerError e) { - throw ConfigImplUtil.extractInitializerError(e); - } + return load(Thread.currentThread().getContextClassLoader()); + } + + /** + * Like {@link #load()} but allows specifying a class loader other than the + * thread's current context class loader. + * + * @param loader + * class loader for finding resources + * @return configuration for an application + */ + public static Config load(ClassLoader loader) { + return loadDefaultConfig(loader); } /** @@ -194,6 +255,13 @@ public final class ConfigFactory { * jar. * *

+ * The reference config must be looked up in the class loader that contains + * the libraries that you want to use with this config, so the + * "reference.conf" for each library can be found. Use + * {@link #defaultReference(ClassLoader)} if the context class loader is not + * suitable. + * + *

* The {@link #load()} methods merge this configuration for you * automatically. * @@ -202,10 +270,21 @@ public final class ConfigFactory { * is not guaranteed that this method only looks at * "reference.conf". * - * @return the default reference config + * @return the default reference config for context class loader */ public static Config defaultReference() { - return ConfigImpl.defaultReference(); + return defaultReference(Thread.currentThread().getContextClassLoader()); + } + + /** + * Like {@link #defaultReference()} but allows you to specify a class loader + * to use rather than the current context class loader. + * + * @param loader + * @return the default reference config for this class loader + */ + public static Config defaultReference(ClassLoader loader) { + return ConfigImpl.defaultReference(loader); } /** @@ -227,6 +306,17 @@ public final class ConfigFactory { return systemProperties(); } + /** + * Like {@link #defaultOverrides()} but allows you to specify a class loader + * to use rather than the current context class loader. + * + * @param loader + * @return the default override configuration + */ + public static Config defaultOverrides(ClassLoader loader) { + return systemProperties(); + } + /** * Gets an empty configuration. See also {@link #empty(String)} to create an * empty configuration with a description, which may improve user-visible @@ -301,12 +391,12 @@ public final class ConfigFactory { * string values. If you have both "a=foo" and "a.b=bar" in your properties * file, so "a" is both the object containing "b" and the string "foo", then * the string value is dropped. - * + * *

* If you want to have System.getProperties() as a * ConfigObject, it's better to use the {@link #systemProperties()} method * which returns a cached global singleton. - * + * * @param properties * a Java Properties object * @param options @@ -465,6 +555,106 @@ public final class ConfigFactory { return parseResourcesAnySyntax(klass, resourceBasename, ConfigParseOptions.defaults()); } + /** + * Parses all resources on the classpath with the given name and merges them + * into a single Config. + * + *

+ * This works like {@link java.lang.ClassLoader#getResource}, not like + * {@link java.lang.Class#getResource}, so the name never begins with a + * slash. + * + *

+ * See {@link #parseResources(Class,String,ConfigParseOptions)} for full + * details. + * + * @param loader + * will be used to load resources + * @param resource + * resource to look up + * @param options + * parse options + * @return the parsed configuration + */ + public static Config parseResources(ClassLoader loader, String resource, + ConfigParseOptions options) { + return Parseable.newResources(loader, resource, options).parse().toConfig(); + } + + public static Config parseResources(ClassLoader loader, String resource) { + return parseResources(loader, resource, ConfigParseOptions.defaults()); + } + + /** + * Parses classpath resources with a flexible extension. In general, this + * method has the same behavior as + * {@link #parseFileAnySyntax(File,ConfigParseOptions)} but for classpath + * resources instead, as in + * {@link #parseResources(ClassLoader,String,ConfigParseOptions)}. + * + *

+ * {@link #parseResourcesAnySyntax(Class,String,ConfigParseOptions)} differs + * in the syntax for the resource name, but otherwise see + * {@link #parseResourcesAnySyntax(Class,String,ConfigParseOptions)} for + * some details and caveats on this method. + * + * @param loader + * class loader to look up resources in + * @param resourceBasename + * a resource name as in + * {@link java.lang.ClassLoader#getResource}, with or without + * extension + * @param options + * parse options + * @return the parsed configuration + */ + public static Config parseResourcesAnySyntax(ClassLoader loader, String resourceBasename, + ConfigParseOptions options) { + return ConfigImpl.parseResourcesAnySyntax(loader, resourceBasename, options).toConfig(); + } + + public static Config parseResourcesAnySyntax(ClassLoader loader, String resourceBasename) { + return parseResourcesAnySyntax(loader, resourceBasename, ConfigParseOptions.defaults()); + } + + /** + * Like {@link #parseResources(ClassLoader,String,ConfigParseOptions)} but + * uses thread's current context class loader. + */ + public static Config parseResources(String resource, ConfigParseOptions options) { + return Parseable + .newResources(Thread.currentThread().getContextClassLoader(), resource, options) + .parse().toConfig(); + } + + /** + * Like {@link #parseResources(ClassLoader,String)} but uses thread's + * current context class loader. + */ + public static Config parseResources(String resource) { + return parseResources(Thread.currentThread().getContextClassLoader(), resource, + ConfigParseOptions.defaults()); + } + + /** + * Like + * {@link #parseResourcesAnySyntax(ClassLoader,String,ConfigParseOptions)} + * but uses thread's current context class loader. + */ + public static Config parseResourcesAnySyntax(String resourceBasename, ConfigParseOptions options) { + return ConfigImpl.parseResourcesAnySyntax(Thread.currentThread().getContextClassLoader(), + resourceBasename, options).toConfig(); + } + + /** + * Like {@link #parseResourcesAnySyntax(ClassLoader,String)} but uses + * thread's current context class loader. + */ + public static Config parseResourcesAnySyntax(String resourceBasename) { + return parseResourcesAnySyntax(Thread.currentThread().getContextClassLoader(), + resourceBasename, ConfigParseOptions.defaults()); + } + public static Config parseString(String s, ConfigParseOptions options) { return Parseable.newString(s, options).parse().toConfig(); } diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java index 73ddfdce5a..fd41dda6a4 100755 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java @@ -118,6 +118,18 @@ public class ConfigImpl { return fromBasename(source, resourceBasename, baseOptions); } + /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ + public static ConfigObject parseResourcesAnySyntax(final ClassLoader loader, + String resourceBasename, final ConfigParseOptions baseOptions) { + NameSource source = new NameSource() { + @Override + public ConfigParseable nameToParseable(String name) { + return Parseable.newResources(loader, name, baseOptions); + } + }; + return fromBasename(source, resourceBasename, baseOptions); + } + /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ public static ConfigObject parseFileAnySyntax(final File basename, final ConfigParseOptions baseOptions) { @@ -397,20 +409,11 @@ public class ConfigImpl { return envVariablesAsConfigObject().toConfig(); } - private static class ReferenceHolder { - private static final Config unresolvedResources = Parseable - .newResources(ConfigImpl.class, "/reference.conf", ConfigParseOptions.defaults()) - .parse().toConfig(); - static final Config referenceConfig = systemPropertiesAsConfig().withFallback( - unresolvedResources).resolve(); - } - /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ - public static Config defaultReference() { - try { - return ReferenceHolder.referenceConfig; - } catch (ExceptionInInitializerError e) { - throw ConfigImplUtil.extractInitializerError(e); - } + public static Config defaultReference(ClassLoader loader) { + Config unresolvedResources = Parseable + .newResources(loader, "reference.conf", ConfigParseOptions.defaults()).parse() + .toConfig(); + return systemPropertiesAsConfig().withFallback(unresolvedResources).resolve(); } } From 64b523638e37aa941916f7efdea652523982d5e4 Mon Sep 17 00:00:00 2001 From: Roland Date: Wed, 29 Feb 2012 21:10:31 +0100 Subject: [PATCH 06/46] rework childrenRefs to make context.stop(child) fully asynchronous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - replace TreeMap with custom ChildrenContainer, which has three implementations: empty, normal and “terminating” (i.e. waiting for some child to terminate) - split recreate() in the same way as terminate(), so that there is a phase during which the suspended actor waits for termination of all children which were stopped in preRestart - do not null out “actor” in ActorCell during restart, because we do need the supervisionStrategy and nulling it out does not buy us much in this case anyway - provide new ActorContext.suspendForChildTermination(), which enters limbo for as long there are outstanding termination requests; this enables code which is very similar to previously (half-working) setups with “synchronous” context.stop(child) docs are still missing, plus a little polishing here and there; oh, and before I forget: ActorCell NOW is 64 bytes again ;-) --- .../scala/akka/actor/SupervisorMiscSpec.scala | 77 +++++ .../scala/akka/event/LoggingReceiveSpec.scala | 7 +- .../test/scala/akka/routing/RoutingSpec.scala | 2 + .../src/main/scala/akka/actor/ActorCell.scala | 272 +++++++++++++----- .../src/main/scala/akka/actor/ActorRef.scala | 11 +- .../scala/akka/actor/ActorRefProvider.scala | 8 - .../main/scala/akka/actor/ActorSystem.scala | 3 - .../src/main/scala/akka/actor/Locker.scala | 74 ----- .../main/scala/akka/dispatch/Mailbox.scala | 5 +- .../code/akka/docs/actor/ActorDocSpec.scala | 2 +- .../akka/remote/RemoteActorRefProvider.scala | 1 - .../scala/akka/remote/RemoteTransport.scala | 1 - .../akka/remote/RemoteCommunicationSpec.scala | 3 + 13 files changed, 292 insertions(+), 174 deletions(-) delete mode 100644 akka-actor/src/main/scala/akka/actor/Locker.scala diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala index f644842591..43a5b97990 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala @@ -10,6 +10,7 @@ import akka.testkit.AkkaSpec import akka.testkit.DefaultTimeout import akka.pattern.ask import akka.util.duration._ +import akka.util.NonFatal object SupervisorMiscSpec { val config = """ @@ -77,5 +78,81 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul expectMsg("preStart") a.isTerminated must be(false) } + + "be able to recreate child when old child is Terminated" in { + val parent = system.actorOf(Props(new Actor { + val kid = context.watch(context.actorOf(Props.empty, "foo")) + def receive = { + case Terminated(`kid`) ⇒ + try { + val newKid = context.actorOf(Props.empty, "foo") + val result = + if (newKid eq kid) "Failure: context.actorOf returned the same instance!" + else if (!kid.isTerminated) "Kid is zombie" + else if (newKid.isTerminated) "newKid was stillborn" + else if (kid.path != newKid.path) "The kids do not share the same path" + else "green" + testActor ! result + } catch { + case NonFatal(e) ⇒ testActor ! e + } + case "engage" ⇒ context.stop(kid) + } + })) + parent ! "engage" + expectMsg("green") + } + + "not be able to recreate child when old child is alive" in { + val parent = system.actorOf(Props(new Actor { + def receive = { + case "engage" ⇒ + try { + val kid = context.actorOf(Props.empty, "foo") + context.stop(kid) + context.actorOf(Props.empty, "foo") + testActor ! "red" + } catch { + case e: InvalidActorNameException ⇒ testActor ! "green" + } + } + })) + parent ! "engage" + expectMsg("green") + } + + "be able to create a similar kid in the fault handling strategy" in { + val parent = system.actorOf(Props(new Actor { + + override val supervisorStrategy = new OneForOneStrategy()(SupervisorStrategy.defaultStrategy.decider) { + override def handleChildTerminated(context: ActorContext, child: ActorRef, children: Iterable[ActorRef]): Unit = { + val newKid = context.actorOf(Props.empty, child.path.name) + testActor ! { + if ((newKid ne child) && newKid.path == child.path) "green" + else "red" + } + } + } + + def receive = { + case "engage" ⇒ context.stop(context.actorOf(Props.empty, "Robert")) + } + })) + parent ! "engage" + expectMsg("green") + } + + "support suspending until all dying children have properly expired" in { + val parent = system.actorOf(Props(new Actor { + val child = context.actorOf(Props.empty, "bob") + def receive = { + case "engage" ⇒ context.stop(child); context.suspendForChildTermination(); self ! "next" + case "next" ⇒ context.actorOf(Props.empty, "bob"); testActor ! "green" + } + })) + parent ! "engage" + expectMsg("green") + } + } } diff --git a/akka-actor-tests/src/test/scala/akka/event/LoggingReceiveSpec.scala b/akka-actor-tests/src/test/scala/akka/event/LoggingReceiveSpec.scala index a7218230e4..787f29f93a 100644 --- a/akka-actor-tests/src/test/scala/akka/event/LoggingReceiveSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/event/LoggingReceiveSpec.scala @@ -200,9 +200,10 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterEach with BeforeAnd } system.stop(supervisor) - expectMsg(Logging.Debug(sname, `sclass`, "stopping")) - expectMsg(Logging.Debug(aname, `aclass`, "stopped")) - expectMsg(Logging.Debug(sname, `sclass`, "stopped")) + expectMsgAllOf( + Logging.Debug(aname, aclass, "stopped"), + Logging.Debug(sname, sclass, "stopping"), + Logging.Debug(sname, sclass, "stopped")) } } } diff --git a/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala b/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala index 89b6f5274a..2ae32cfcf5 100644 --- a/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala @@ -118,7 +118,9 @@ class RoutingSpec extends AkkaSpec(RoutingSpec.config) with DefaultTimeout with "use configured nr-of-instances when FromConfig" in { val router = system.actorOf(Props[TestActor].withRouter(FromConfig), "router1") Await.result(router ? CurrentRoutees, 5 seconds).asInstanceOf[RouterRoutees].routees.size must be(3) + watch(router) system.stop(router) + expectMsgType[Terminated] } "use configured nr-of-instances when router is specified" in { diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 227030fe10..0dbdeac599 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -134,6 +134,14 @@ trait ActorContext extends ActorRefFactory { */ def unwatch(subject: ActorRef): ActorRef + /** + * Suspend this actor (after finishing processing of the current message) + * until all children for which stop(child) has been called have actually + * terminated. This is useful if a new child with the same name needs to + * be created before processing can continue. + */ + def suspendForChildTermination(): Unit + final protected def writeObject(o: ObjectOutputStream): Unit = throw new NotSerializableException("ActorContext is not serializable!") } @@ -166,14 +174,98 @@ private[akka] object ActorCell { override def initialValue = Stack[ActorContext]() } - val emptyChildrenRefs = TreeMap[String, ChildRestartStats]() - final val emptyCancellable: Cancellable = new Cancellable { def isCancelled = false def cancel() {} } final val emptyReceiveTimeoutData: (Long, Cancellable) = (-1, emptyCancellable) + + trait SuspendReason + case object UserRequest extends SuspendReason + case class Recreation(cause: Throwable) extends SuspendReason + case object Termination extends SuspendReason + + trait ChildrenContainer { + def add(child: ActorRef): ChildrenContainer + def remove(child: ActorRef): ChildrenContainer + def getByName(name: String): Option[ChildRestartStats] + def getByRef(actor: ActorRef): Option[ChildRestartStats] + def children: Iterable[ActorRef] + def stats: Iterable[ChildRestartStats] + def shallDie(actor: ActorRef): ChildrenContainer + } + + object EmptyChildrenContainer extends ChildrenContainer { + def add(child: ActorRef): ChildrenContainer = + new NormalChildrenContainer(TreeMap.empty[String, ChildRestartStats].updated(child.path.name, ChildRestartStats(child))) + def remove(child: ActorRef): ChildrenContainer = this + def getByName(name: String): Option[ChildRestartStats] = None + def getByRef(actor: ActorRef): Option[ChildRestartStats] = None + def children: Iterable[ActorRef] = Nil + def stats: Iterable[ChildRestartStats] = Nil + def shallDie(actor: ActorRef): ChildrenContainer = this + override def toString = "no children" + } + + class NormalChildrenContainer(c: TreeMap[String, ChildRestartStats]) extends ChildrenContainer { + + def add(child: ActorRef): ChildrenContainer = new NormalChildrenContainer(c.updated(child.path.name, ChildRestartStats(child))) + + def remove(child: ActorRef): ChildrenContainer = NormalChildrenContainer(c - child.path.name) + + def getByName(name: String): Option[ChildRestartStats] = c get name + + def getByRef(actor: ActorRef): Option[ChildRestartStats] = c get actor.path.name match { + case c @ Some(crs) if (crs.child == actor) ⇒ c + case _ ⇒ None + } + + def children: Iterable[ActorRef] = c.values.view.map(_.child) + + def stats: Iterable[ChildRestartStats] = c.values + + def shallDie(actor: ActorRef): ChildrenContainer = TerminatingChildrenContainer(c, Set(actor), UserRequest) + + override def toString = + if (c.size > 20) c.size + " children" + else c.mkString("children:\n ", "\n ", "") + } + + object NormalChildrenContainer { + def apply(c: TreeMap[String, ChildRestartStats]): ChildrenContainer = + if (c.isEmpty) EmptyChildrenContainer + else new NormalChildrenContainer(c) + } + + case class TerminatingChildrenContainer(c: TreeMap[String, ChildRestartStats], toDie: Set[ActorRef], reason: SuspendReason) + extends ChildrenContainer { + + def add(child: ActorRef): ChildrenContainer = copy(c.updated(child.path.name, ChildRestartStats(child))) + + def remove(child: ActorRef): ChildrenContainer = + if (toDie contains child) + if (toDie.size == 1) NormalChildrenContainer(c - child.path.name) + else copy(c - child.path.name, toDie - child) + else copy(c - child.path.name) + + def getByName(name: String): Option[ChildRestartStats] = c get name + + def getByRef(actor: ActorRef): Option[ChildRestartStats] = c get actor.path.name match { + case c @ Some(crs) if (crs.child == actor) ⇒ c + case _ ⇒ None + } + + def children: Iterable[ActorRef] = c.values.view.map(_.child) + + def stats: Iterable[ChildRestartStats] = c.values + + def shallDie(actor: ActorRef): ChildrenContainer = copy(toDie = toDie + actor) + + override def toString = + if (c.size > 20) c.size + " children" + else c.mkString("children (" + toDie.size + " terminating):\n ", "\n ", "") + } } //ACTORCELL IS 64bytes and should stay that way unless very good reason not to (machine sympathy, cache line fit) @@ -221,7 +313,8 @@ private[akka] class ActorCell( var receiveTimeoutData: (Long, Cancellable) = if (_receiveTimeout.isDefined) (_receiveTimeout.get.toMillis, emptyCancellable) else emptyReceiveTimeoutData - var childrenRefs: TreeMap[String, ChildRestartStats] = emptyChildrenRefs + @volatile + var childrenRefs: ChildrenContainer = EmptyChildrenContainer private def _actorOf(props: Props, name: String): ActorRef = { if (system.settings.SerializeAllCreators && !props.creator.isInstanceOf[NoSerializationVerificationNeeded]) { @@ -235,7 +328,7 @@ private[akka] class ActorCell( } } val actor = provider.actorOf(systemImpl, props, self, self.path / name, false, None, true) - childrenRefs = childrenRefs.updated(name, ChildRestartStats(actor)) + childrenRefs = childrenRefs.add(actor) actor } @@ -249,26 +342,20 @@ private[akka] class ActorCell( case ElementRegex() ⇒ // this is fine case _ ⇒ throw new InvalidActorNameException("illegal actor name '" + name + "', must conform to " + ElementRegex) } - if (childrenRefs contains name) + if (childrenRefs.getByName(name).isDefined) throw new InvalidActorNameException("actor name " + name + " is not unique!") _actorOf(props, name) } final def stop(actor: ActorRef): Unit = { - val a = actor.asInstanceOf[InternalActorRef] - if (a.getParent == self && (childrenRefs contains actor.path.name)) { - system.locker ! a - handleChildTerminated(actor) // will remove child from childrenRefs - } - a.stop() + if (childrenRefs.getByRef(actor).isDefined) childrenRefs = childrenRefs.shallDie(actor) + actor.asInstanceOf[InternalActorRef].stop() } var currentMessage: Envelope = null var actor: Actor = _ - var stopping = false - @volatile //This must be volatile since it isn't protected by the mailbox status var mailbox: Mailbox = _ @@ -328,7 +415,12 @@ private[akka] class ActorCell( subject } - final def children: Iterable[ActorRef] = childrenRefs.values.view.map(_.child) + final def suspendForChildTermination(): Unit = childrenRefs match { + case _: TerminatingChildrenContainer ⇒ dispatcher suspend this + case _ ⇒ + } + + final def children: Iterable[ActorRef] = childrenRefs.children /** * Impl UntypedActorContext @@ -391,19 +483,18 @@ private[akka] class ActorCell( if (failedActor ne null) { val c = currentMessage //One read only plz try { - failedActor.preRestart(cause, if (c ne null) Some(c.message) else None) + if (failedActor.context ne null) failedActor.preRestart(cause, if (c ne null) Some(c.message) else None) } finally { clearActorFields() } } - val freshActor = newActor() // this must happen after failedActor.preRestart (to scrap those children) - actor = freshActor // this must happen before postRestart has a chance to fail - freshActor.postRestart(cause) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(freshActor), "restarted")) - - dispatcher.resume(this) //FIXME should this be moved down? - - actor.supervisorStrategy.handleSupervisorRestarted(cause, self, children) + childrenRefs match { + case ct: TerminatingChildrenContainer ⇒ + childrenRefs = ct.copy(reason = Recreation(cause)) + dispatcher suspend this + case _ ⇒ + doRecreate(cause) + } } catch { case NonFatal(e) ⇒ try { dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e)) @@ -422,51 +513,58 @@ private[akka] class ActorCell( setReceiveTimeout(None) cancelReceiveTimeout - val c = children - if (c.isEmpty) doTerminate() - else { - // do not process normal messages while waiting for all children to terminate - dispatcher suspend this - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopping")) - // do not use stop(child) because that would dissociate the children from us, but we still want to wait for them - for (child ← c) child.asInstanceOf[InternalActorRef].stop() - stopping = true + // stop all children, which will turn childrenRefs into TerminatingChildrenContainer (if there are children) + for (child ← children) stop(child) + + childrenRefs match { + case ct: TerminatingChildrenContainer ⇒ + childrenRefs = ct.copy(reason = Termination) + // do not process normal messages while waiting for all children to terminate + dispatcher suspend this + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopping")) + case x ⇒ doTerminate() } } def supervise(child: ActorRef): Unit = { - childrenRefs.get(child.path.name) match { - case None ⇒ - childrenRefs = childrenRefs.updated(child.path.name, ChildRestartStats(child)) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now supervising " + child)) - case Some(ChildRestartStats(`child`, _, _)) ⇒ - // this is the nominal case where we created the child and entered it in actorCreated() above - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now supervising " + child)) - case Some(ChildRestartStats(c, _, _)) ⇒ - system.eventStream.publish(Warning(self.path.toString, clazz(actor), "Already supervising other child with same name '" + child.path.name + "', old: " + c + " new: " + child)) - } + if (childrenRefs.getByRef(child).isEmpty) childrenRefs = childrenRefs.add(child) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now supervising " + child)) } try { - if (stopping) message match { - case Terminate() ⇒ terminate() // to allow retry - case ChildTerminated(child) ⇒ handleChildTerminated(child) - case _ ⇒ - } - else message match { - case Create() ⇒ create() - case Recreate(cause) ⇒ recreate(cause) - case Link(subject) ⇒ - system.deathWatch.subscribe(self, subject) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now monitoring " + subject)) - case Unlink(subject) ⇒ - system.deathWatch.unsubscribe(self, subject) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped monitoring " + subject)) - case Suspend() ⇒ suspend() - case Resume() ⇒ resume() - case Terminate() ⇒ terminate() - case Supervise(child) ⇒ supervise(child) - case ChildTerminated(child) ⇒ handleChildTerminated(child) + childrenRefs match { + case TerminatingChildrenContainer(_, _, Termination) ⇒ message match { + case Terminate() ⇒ terminate() // to allow retry + case ChildTerminated(child) ⇒ handleChildTerminated(child) + case _ ⇒ + } + case TerminatingChildrenContainer(_, _, _: Recreation) ⇒ message match { + case Link(subject) ⇒ + system.deathWatch.subscribe(self, subject) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now monitoring " + subject)) + case Unlink(subject) ⇒ + system.deathWatch.unsubscribe(self, subject) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped monitoring " + subject)) + case Terminate() ⇒ terminate() + case Supervise(child) ⇒ supervise(child) + case ChildTerminated(child) ⇒ handleChildTerminated(child) + case _ ⇒ + } + case _ ⇒ message match { + case Create() ⇒ create() + case Recreate(cause) ⇒ recreate(cause) + case Link(subject) ⇒ + system.deathWatch.subscribe(self, subject) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now monitoring " + subject)) + case Unlink(subject) ⇒ + system.deathWatch.unsubscribe(self, subject) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped monitoring " + subject)) + case Suspend() ⇒ suspend() + case Resume() ⇒ resume() + case Terminate() ⇒ terminate() + case Supervise(child) ⇒ supervise(child) + case ChildTerminated(child) ⇒ handleChildTerminated(child) + } } } catch { case NonFatal(e) ⇒ @@ -544,7 +642,7 @@ private[akka] class ActorCell( case Kill ⇒ throw new ActorKilledException("Kill") case PoisonPill ⇒ self.stop() case SelectParent(m) ⇒ parent.tell(m, msg.sender) - case SelectChildName(name, m) ⇒ if (childrenRefs contains name) childrenRefs(name).child.tell(m, msg.sender) + case SelectChildName(name, m) ⇒ childrenRefs getByName name foreach (_.child.tell(m, msg.sender)) case SelectChildPattern(p, m) ⇒ for (c ← children if p.matcher(c.path.name).matches) c.tell(m, msg.sender) } } @@ -566,22 +664,52 @@ private[akka] class ActorCell( } finally { if (a ne null) a.clearBehaviorStack() clearActorFields() + actor = null } } } - final def handleFailure(child: ActorRef, cause: Throwable): Unit = childrenRefs.get(child.path.name) match { - case Some(stats) if stats.child == child ⇒ if (!actor.supervisorStrategy.handleFailure(this, child, cause, stats, childrenRefs.values)) throw cause - case Some(stats) ⇒ system.eventStream.publish(Warning(self.path.toString, clazz(actor), "dropping Failed(" + cause + ") from unknown child " + child + " matching names but not the same, was: " + stats.child)) - case None ⇒ system.eventStream.publish(Warning(self.path.toString, clazz(actor), "dropping Failed(" + cause + ") from unknown child " + child)) + private def doRecreate(cause: Throwable): Unit = try { + // after all killed children have terminated, recreate the rest, then go on to start the new instance + actor.supervisorStrategy.handleSupervisorRestarted(cause, self, children) + + val freshActor = newActor() + actor = freshActor // this must happen before postRestart has a chance to fail + + freshActor.postRestart(cause) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(freshActor), "restarted")) + + dispatcher.resume(this) + } catch { + case NonFatal(e) ⇒ try { + dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e)) + // prevent any further messages to be processed until the actor has been restarted + dispatcher.suspend(this) + } finally { + parent.tell(Failed(ActorInitializationException(self, "exception during re-creation", e)), self) + } + } + + final def handleFailure(child: ActorRef, cause: Throwable): Unit = childrenRefs.getByRef(child) match { + case Some(stats) ⇒ if (!actor.supervisorStrategy.handleFailure(this, child, cause, stats, childrenRefs.stats)) throw cause + case None ⇒ system.eventStream.publish(Warning(self.path.toString, clazz(actor), "dropping Failed(" + cause + ") from unknown child " + child)) } final def handleChildTerminated(child: ActorRef): Unit = { - if (childrenRefs contains child.path.name) { - childrenRefs -= child.path.name - actor.supervisorStrategy.handleChildTerminated(this, child, children) - if (stopping && childrenRefs.isEmpty) doTerminate() - } else system.locker ! ChildTerminated(child) + childrenRefs match { + case tc @ TerminatingChildrenContainer(_, _, reason) ⇒ + val n = tc.remove(child) + childrenRefs = n + actor.supervisorStrategy.handleChildTerminated(this, child, children) + if (!n.isInstanceOf[TerminatingChildrenContainer]) reason match { + case UserRequest ⇒ if (mailbox.isSuspended) dispatcher resume this + case Recreation(cause) ⇒ doRecreate(cause) + case Termination ⇒ doTerminate() + } + case _ ⇒ + childrenRefs = childrenRefs.remove(child) + actor.supervisorStrategy.handleChildTerminated(this, child, children) + } } // ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅ @@ -608,7 +736,6 @@ private[akka] class ActorCell( final def clearActorFields(): Unit = { setActorFields(context = null, self = system.deadLetters) currentMessage = null - actor = null } final def setActorFields(context: ActorContext, self: ActorRef) { @@ -639,3 +766,4 @@ private[akka] class ActorCell( private final def clazz(o: AnyRef): Class[_] = if (o eq null) this.getClass else o.getClass } + diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index bd2c0cf196..668731e4bb 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -284,14 +284,11 @@ private[akka] class LocalActorRef private[akka] ( * Method for looking up a single child beneath this actor. Override in order * to inject “synthetic” actor paths like “/temp”. */ - protected def getSingleChild(name: String): InternalActorRef = { - if (actorCell.isTerminated) Nobody // read of the mailbox status ensures we get the latest childrenRefs - else { - val children = actorCell.childrenRefs - if (children contains name) children(name).child.asInstanceOf[InternalActorRef] - else Nobody + protected def getSingleChild(name: String): InternalActorRef = + actorCell.childrenRefs.getByName(name) match { + case Some(crs) ⇒ crs.child.asInstanceOf[InternalActorRef] + case None ⇒ Nobody } - } def getChild(names: Iterator[String]): InternalActorRef = { /* diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index 255a42d87c..60ce12f4b8 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -44,12 +44,6 @@ trait ActorRefProvider { */ def deathWatch: DeathWatch - /** - * Care-taker of actor refs which await final termination but cannot be kept - * in their parent’s children list because the name shall be freed. - */ - def locker: Locker - /** * The root path for all actors within this actor system, including remote * address if enabled. @@ -333,8 +327,6 @@ class LocalActorRefProvider( val deathWatch = new LocalDeathWatch(1024) //TODO make configrable - val locker: Locker = new Locker(scheduler, settings.ReaperInterval, this, rootPath / "locker", deathWatch) - /* * generate name for temporary actor refs */ diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index 1daad13963..071a26e212 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -478,8 +478,6 @@ class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Conf def hasSystemMessages = false } - def locker: Locker = provider.locker - val dispatchers: Dispatchers = new Dispatchers(settings, DefaultDispatcherPrerequisites( threadFactory, eventStream, deadLetterMailbox, scheduler, dynamicAccess, settings)) @@ -497,7 +495,6 @@ class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Conf private lazy val _start: this.type = { // the provider is expected to start default loggers, LocalActorRefProvider does this provider.init(this) - registerOnTermination(locker.shutdown()) registerOnTermination(stopScheduler()) loadExtensions() if (LogConfigOnStart) logConfiguration() diff --git a/akka-actor/src/main/scala/akka/actor/Locker.scala b/akka-actor/src/main/scala/akka/actor/Locker.scala deleted file mode 100644 index a9eb0ff2e6..0000000000 --- a/akka-actor/src/main/scala/akka/actor/Locker.scala +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ -package akka.actor - -import akka.dispatch._ -import akka.util.Duration -import java.util.concurrent.ConcurrentHashMap -import akka.event.DeathWatch - -/** - * Internal implementation detail for disposing of orphaned actors. - */ -private[akka] class Locker( - scheduler: Scheduler, - period: Duration, - val provider: ActorRefProvider, - val path: ActorPath, - val deathWatch: DeathWatch) extends MinimalActorRef { - - class DavyJones extends Runnable { - def run = { - val iter = heap.entrySet.iterator - while (iter.hasNext) { - val soul = iter.next() - deathWatch.subscribe(Locker.this, soul.getValue) // in case Terminated got lost somewhere - soul.getValue match { - case _: LocalRef ⇒ // nothing to do, they know what they signed up for - case nonlocal ⇒ nonlocal.stop() // try again in case it was due to a communications failure - } - } - } - } - - private val heap = new ConcurrentHashMap[ActorPath, InternalActorRef] - - scheduler.schedule(period, period, new DavyJones) - - override def sendSystemMessage(msg: SystemMessage): Unit = this.!(msg) - - override def !(msg: Any)(implicit sender: ActorRef = null): Unit = msg match { - case Terminated(soul) ⇒ heap.remove(soul.path) - case ChildTerminated(soul) ⇒ heap.remove(soul.path) - case soul: InternalActorRef ⇒ - heap.put(soul.path, soul) - deathWatch.subscribe(this, soul) - // now re-bind the soul so that it does not drown its parent - soul match { - case local: LocalActorRef ⇒ - val cell = local.underlying - cell.parent = this - case _ ⇒ - } - case _ ⇒ // ignore - } - - def childTerminated(parent: ActorRef, ct: ChildTerminated): Unit = { - heap.get(parent.path) match { - case null ⇒ - case ref ⇒ ref.sendSystemMessage(ct) - } - } - - def shutdown(): Unit = { - import scala.collection.JavaConverters._ - for (soul ← heap.values.asScala) { - soul match { - case l: LocalActorRef ⇒ l.underlying.dispatcher.detach(l.underlying) - case _ ⇒ - } - } - } - -} diff --git a/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala b/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala index 2d929cdded..322b50b900 100644 --- a/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala +++ b/akka-actor/src/main/scala/akka/dispatch/Mailbox.scala @@ -187,10 +187,7 @@ private[akka] abstract class Mailbox(val actor: ActorCell, val messageQueue: Mes var nextMessage = systemDrain() try { while ((nextMessage ne null) && !isClosed) { - if (debug) println(actor.self + " processing system message " + nextMessage + " with " + - (if (actor.childrenRefs.isEmpty) "no children" - else if (actor.childrenRefs.size > 20) actor.childrenRefs.size + " children" - else actor.childrenRefs.mkString("children:\n ", "\n ", ""))) + if (debug) println(actor.self + " processing system message " + nextMessage + " with " + actor.childrenRefs) actor systemInvoke nextMessage nextMessage = nextMessage.next // don’t ever execute normal message when system message present! diff --git a/akka-docs/scala/code/akka/docs/actor/ActorDocSpec.scala b/akka-docs/scala/code/akka/docs/actor/ActorDocSpec.scala index aee30e3c56..0bc540f970 100644 --- a/akka-docs/scala/code/akka/docs/actor/ActorDocSpec.scala +++ b/akka-docs/scala/code/akka/docs/actor/ActorDocSpec.scala @@ -233,7 +233,7 @@ class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) { "creating actor with Props" in { //#creating-props import akka.actor.Props - val myActor = system.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), name = "myactor") + val myActor = system.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), name = "myactor2") //#creating-props system.stop(myActor) diff --git a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala index 89c35115ef..5870af9f95 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala @@ -40,7 +40,6 @@ class RemoteActorRefProvider( def log: LoggingAdapter = _log def rootPath = local.rootPath - def locker = local.locker def deadLetters = local.deadLetters val deathWatch = new RemoteDeathWatch(local.deathWatch, this) diff --git a/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala b/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala index 1af4a6103b..0d55f17915 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteTransport.scala @@ -274,7 +274,6 @@ trait RemoteMarshallingOps { case l: LocalRef ⇒ if (provider.remoteSettings.LogReceive) log.debug("received local message {}", remoteMessage) remoteMessage.payload match { - case ct: ChildTerminated if l.isTerminated ⇒ provider.locker.childTerminated(l, ct) case msg: SystemMessage ⇒ if (useUntrustedMode) throw new SecurityException("RemoteModule server is operating is untrusted mode, can not send system message") diff --git a/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala b/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala index 73f8a98030..4475998c4e 100644 --- a/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemoteCommunicationSpec.scala @@ -31,6 +31,7 @@ object RemoteCommunicationSpec { } } +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class RemoteCommunicationSpec extends AkkaSpec(""" akka { actor.provider = "akka.remote.RemoteActorRefProvider" @@ -123,6 +124,8 @@ akka { myref ! 43 expectMsg(43) lastSender must be theSameInstanceAs remref + r.asInstanceOf[RemoteActorRef].getParent must be(l) + system.actorFor("/user/looker/child") must be theSameInstanceAs r Await.result(l ? "child/..", timeout.duration).asInstanceOf[AnyRef] must be theSameInstanceAs l Await.result(system.actorFor(system / "looker" / "child") ? "..", timeout.duration).asInstanceOf[AnyRef] must be theSameInstanceAs l } From 150b6b011053b5f3b8f0a9788dcf4953a1f97440 Mon Sep 17 00:00:00 2001 From: Roland Date: Wed, 29 Feb 2012 21:31:50 +0100 Subject: [PATCH 07/46] little polish for TerminatingChildrenContainer --- akka-actor/src/main/scala/akka/actor/ActorCell.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 0dbdeac599..247aef8b40 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -243,11 +243,11 @@ private[akka] object ActorCell { def add(child: ActorRef): ChildrenContainer = copy(c.updated(child.path.name, ChildRestartStats(child))) - def remove(child: ActorRef): ChildrenContainer = - if (toDie contains child) - if (toDie.size == 1) NormalChildrenContainer(c - child.path.name) - else copy(c - child.path.name, toDie - child) - else copy(c - child.path.name) + def remove(child: ActorRef): ChildrenContainer = { + val t = toDie - child + if (t.isEmpty) NormalChildrenContainer(c - child.path.name) + else copy(c - child.path.name, t) + } def getByName(name: String): Option[ChildRestartStats] = c get name @@ -264,7 +264,7 @@ private[akka] object ActorCell { override def toString = if (c.size > 20) c.size + " children" - else c.mkString("children (" + toDie.size + " terminating):\n ", "\n ", "") + else c.mkString("children (" + toDie.size + " terminating):\n ", "\n ", "\n") + toDie } } From bad77feac9b674b00da60701450850a28e471ad3 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 00:55:50 +0100 Subject: [PATCH 08/46] Artistic reinterpretation --- .../src/main/scala/akka/actor/ActorCell.scala | 151 +++++++++--------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 247aef8b40..3343ad03ac 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -460,61 +460,84 @@ private[akka] class ActorCell( //Memory consistency is handled by the Mailbox (reading mailbox status then processing messages, then writing mailbox status final def systemInvoke(message: SystemMessage) { - def create(): Unit = try { - val created = newActor() - actor = created - created.preStart() - checkReceiveTimeout - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(created), "started (" + created + ")")) - } catch { - case NonFatal(e) ⇒ - try { + def isTerminating = childrenRefs match { + case TerminatingChildrenContainer(_, _, Termination) ⇒ true + case _ ⇒ false + } + def isNormal = childrenRefs match { + case TerminatingChildrenContainer(_, _, Termination | _: Recreation) ⇒ false + case _ ⇒ true + } + + def create(): Unit = if (isNormal) { + try { + val created = newActor() + actor = created + created.preStart() + checkReceiveTimeout + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(created), "started (" + created + ")")) + } catch { + case NonFatal(e) ⇒ + try { + dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e)) + // prevent any further messages to be processed until the actor has been restarted + dispatcher.suspend(this) + } finally { + parent.tell(Failed(ActorInitializationException(self, "exception during creation", e)), self) + } + } + } + + def recreate(cause: Throwable): Unit = if (isNormal) { + try { + val failedActor = actor + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(failedActor), "restarting")) + if (failedActor ne null) { + val c = currentMessage //One read only plz + try { + if (failedActor.context ne null) failedActor.preRestart(cause, if (c ne null) Some(c.message) else None) + } finally { + clearActorFields() + } + } + childrenRefs match { + case ct: TerminatingChildrenContainer ⇒ + childrenRefs = ct.copy(reason = Recreation(cause)) + dispatcher suspend this + case _ ⇒ + doRecreate(cause) + } + } catch { + case NonFatal(e) ⇒ try { dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e)) // prevent any further messages to be processed until the actor has been restarted dispatcher.suspend(this) } finally { - parent.tell(Failed(ActorInitializationException(self, "exception during creation", e)), self) + parent.tell(Failed(ActorInitializationException(self, "exception during re-creation", e)), self) } - } - - def recreate(cause: Throwable): Unit = try { - val failedActor = actor - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(failedActor), "restarting")) - if (failedActor ne null) { - val c = currentMessage //One read only plz - try { - if (failedActor.context ne null) failedActor.preRestart(cause, if (c ne null) Some(c.message) else None) - } finally { - clearActorFields() - } - } - childrenRefs match { - case ct: TerminatingChildrenContainer ⇒ - childrenRefs = ct.copy(reason = Recreation(cause)) - dispatcher suspend this - case _ ⇒ - doRecreate(cause) - } - } catch { - case NonFatal(e) ⇒ try { - dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e)) - // prevent any further messages to be processed until the actor has been restarted - dispatcher.suspend(this) - } finally { - parent.tell(Failed(ActorInitializationException(self, "exception during re-creation", e)), self) } } - def suspend(): Unit = dispatcher suspend this + def suspend(): Unit = if (isNormal) dispatcher suspend this - def resume(): Unit = dispatcher resume this + def resume(): Unit = if (isNormal) dispatcher resume this + + def link(subject: ActorRef): Unit = if (!isTerminating) { + system.deathWatch.subscribe(self, subject) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now monitoring " + subject)) + } + + def unlink(subject: ActorRef): Unit = if (!isTerminating) { + system.deathWatch.unsubscribe(self, subject) + if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped monitoring " + subject)) + } def terminate() { setReceiveTimeout(None) cancelReceiveTimeout // stop all children, which will turn childrenRefs into TerminatingChildrenContainer (if there are children) - for (child ← children) stop(child) + children foreach stop childrenRefs match { case ct: TerminatingChildrenContainer ⇒ @@ -522,54 +545,30 @@ private[akka] class ActorCell( // do not process normal messages while waiting for all children to terminate dispatcher suspend this if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopping")) - case x ⇒ doTerminate() + case _ ⇒ doTerminate() } } - def supervise(child: ActorRef): Unit = { + def supervise(child: ActorRef): Unit = if (!isTerminating) { if (childrenRefs.getByRef(child).isEmpty) childrenRefs = childrenRefs.add(child) if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now supervising " + child)) } try { - childrenRefs match { - case TerminatingChildrenContainer(_, _, Termination) ⇒ message match { - case Terminate() ⇒ terminate() // to allow retry - case ChildTerminated(child) ⇒ handleChildTerminated(child) - case _ ⇒ - } - case TerminatingChildrenContainer(_, _, _: Recreation) ⇒ message match { - case Link(subject) ⇒ - system.deathWatch.subscribe(self, subject) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now monitoring " + subject)) - case Unlink(subject) ⇒ - system.deathWatch.unsubscribe(self, subject) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped monitoring " + subject)) - case Terminate() ⇒ terminate() - case Supervise(child) ⇒ supervise(child) - case ChildTerminated(child) ⇒ handleChildTerminated(child) - case _ ⇒ - } - case _ ⇒ message match { - case Create() ⇒ create() - case Recreate(cause) ⇒ recreate(cause) - case Link(subject) ⇒ - system.deathWatch.subscribe(self, subject) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "now monitoring " + subject)) - case Unlink(subject) ⇒ - system.deathWatch.unsubscribe(self, subject) - if (system.settings.DebugLifecycle) system.eventStream.publish(Debug(self.path.toString, clazz(actor), "stopped monitoring " + subject)) - case Suspend() ⇒ suspend() - case Resume() ⇒ resume() - case Terminate() ⇒ terminate() - case Supervise(child) ⇒ supervise(child) - case ChildTerminated(child) ⇒ handleChildTerminated(child) - } + message match { + case Create() ⇒ create() + case Recreate(cause) ⇒ recreate(cause) + case Link(subject) ⇒ link(subject) + case Unlink(subject) ⇒ unlink(subject) + case Suspend() ⇒ suspend() + case Resume() ⇒ resume() + case Terminate() ⇒ terminate() + case Supervise(child) ⇒ supervise(child) + case ChildTerminated(child) ⇒ handleChildTerminated(child) } } catch { case NonFatal(e) ⇒ dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while processing " + message), e)) - //TODO FIXME How should problems here be handled??? throw e } } From 4cea8ee83ea9da397dea750eba979b3e846b5e2a Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 01:16:43 +0100 Subject: [PATCH 09/46] Sprinkling stardust --- akka-actor/src/main/scala/akka/actor/ActorCell.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 3343ad03ac..7c899df7cd 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -197,8 +197,9 @@ private[akka] object ActorCell { } object EmptyChildrenContainer extends ChildrenContainer { + val emptyStats = TreeMap.empty[String, ChildRestartStats] def add(child: ActorRef): ChildrenContainer = - new NormalChildrenContainer(TreeMap.empty[String, ChildRestartStats].updated(child.path.name, ChildRestartStats(child))) + new NormalChildrenContainer(emptyStats.updated(child.path.name, ChildRestartStats(child))) def remove(child: ActorRef): ChildrenContainer = this def getByName(name: String): Option[ChildRestartStats] = None def getByRef(actor: ActorRef): Option[ChildRestartStats] = None @@ -342,9 +343,10 @@ private[akka] class ActorCell( case ElementRegex() ⇒ // this is fine case _ ⇒ throw new InvalidActorNameException("illegal actor name '" + name + "', must conform to " + ElementRegex) } - if (childrenRefs.getByName(name).isDefined) - throw new InvalidActorNameException("actor name " + name + " is not unique!") - _actorOf(props, name) + childrenRefs.getByName(name) match { + case None ⇒ _actorOf(props, name) + case _ ⇒ throw new InvalidActorNameException("actor name " + name + " is not unique!") + } } final def stop(actor: ActorRef): Unit = { @@ -641,7 +643,7 @@ private[akka] class ActorCell( case Kill ⇒ throw new ActorKilledException("Kill") case PoisonPill ⇒ self.stop() case SelectParent(m) ⇒ parent.tell(m, msg.sender) - case SelectChildName(name, m) ⇒ childrenRefs getByName name foreach (_.child.tell(m, msg.sender)) + case SelectChildName(name, m) ⇒ for (c ← childrenRefs getByName name) c.child.tell(m, msg.sender) case SelectChildPattern(p, m) ⇒ for (c ← children if p.matcher(c.path.name).matches) c.tell(m, msg.sender) } } From 2bc78e1026b4ad4d11486f3c06f1b8e0a02d102a Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 10:14:23 +0100 Subject: [PATCH 10/46] Fixing broken link in docs --- akka-docs/scala/actors.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 01ef6ade83..c2499b8bc7 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -580,7 +580,7 @@ Here is another little cute example of ``become`` and ``unbecome`` in action: Encoding Scala Actors nested receives without accidentally leaking memory ------------------------------------------------------------------------- -See this `Unnested receive example `_. +See this `Unnested receive example `_. Downgrade From 4876eb037f3f8b2618c0a06f25f56003fc47fe2e Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 11:31:50 +0100 Subject: [PATCH 11/46] Removing legacy section of documentation --- akka-docs/intro/deployment-scenarios.rst | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/akka-docs/intro/deployment-scenarios.rst b/akka-docs/intro/deployment-scenarios.rst index f8d6f6b197..b2d0334c7d 100644 --- a/akka-docs/intro/deployment-scenarios.rst +++ b/akka-docs/intro/deployment-scenarios.rst @@ -23,18 +23,6 @@ This is most likely what you want if you are building Web applications. There are several ways you can use Akka in Library mode by adding more and more modules to the stack. -Actors as services -^^^^^^^^^^^^^^^^^^ - -The simplest way you can use Akka is to use the actors as services in your Web -application. All that’s needed to do that is to put the Akka jars as well as -its dependency jars into ``WEB-INF/lib``. You also need to put the :ref:`configuration` -file in the ``$AKKA_HOME/config`` directory. Now you can create your -Actors as regular services referenced from your Web application. You should also -be able to use the Remoting service, e.g. be able to make certain Actors remote -on other hosts. Please note that remoting service does not speak HTTP over port -80, but a custom protocol over the port is specified in :ref:`configuration`. - Using Akka as a stand alone microkernel ---------------------------------------- From 8b02a20d7561957f033fc230005cd30148adbb4e Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 16:09:46 +0100 Subject: [PATCH 12/46] #1878 - whippin' up some badass ClassLoader magicks --- .../scala/akka/actor/GlobalActorSystem.scala | 7 +- .../scala/akka/actor/ActorRefProvider.scala | 1 - .../main/scala/akka/actor/ActorSystem.scala | 70 ++++++++++--------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala b/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala index e08883c6ed..0eae8797d8 100644 --- a/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala +++ b/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala @@ -11,7 +11,7 @@ import akka.util.Timeout import akka.util.duration._ @deprecated("use ActorSystem instead", "2.0") -object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfigurationLoader.defaultConfig) { +object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfigurationLoader.defaultConfig, OldConfigurationLoader.oldClassLoader) { start() /** @@ -26,11 +26,12 @@ object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfiguratio */ @deprecated("use default config location or write your own configuration loader", "2.0") object OldConfigurationLoader { + val oldClassLoader: ClassLoader = ActorSystem.findClassLoader(1) val defaultConfig: Config = { val cfg = fromProperties orElse fromClasspath orElse fromHome getOrElse emptyConfig - val config = cfg.withFallback(ConfigFactory.defaultReference) - config.checkValid(ConfigFactory.defaultReference, "akka") + val config = cfg.withFallback(ConfigFactory.defaultReference(oldClassLoader)) + config.checkValid(ConfigFactory.defaultReference(oldClassLoader), "akka") config } diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index 255a42d87c..f997c36623 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -10,7 +10,6 @@ import akka.routing._ import akka.AkkaException import akka.util.{ Switch, Helpers } import akka.event._ -import com.typesafe.config.ConfigFactory /** * Interface for all ActorRef providers to implement. diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index 1daad13963..557a62133c 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -37,27 +37,30 @@ object ActorSystem { val GlobalHome = SystemHome orElse EnvHome - def create(name: String, config: Config): ActorSystem = apply(name, config) - def apply(name: String, config: Config): ActorSystem = new ActorSystemImpl(name, config).start() - + def create(): ActorSystem = apply() /** * Uses the standard default Config from ConfigFactory.load(), since none is provided. */ def create(name: String): ActorSystem = apply(name) + def create(name: String, config: Config): ActorSystem = apply(name, config) + def create(name: String, config: Config, classLoader: ClassLoader): ActorSystem = apply(name, config, classLoader) /** * Uses the standard default Config from ConfigFactory.load(), since none is provided. */ - def apply(name: String): ActorSystem = apply(name, ConfigFactory.load()) - - def create(): ActorSystem = apply() def apply(): ActorSystem = apply("default") + def apply(name: String): ActorSystem = { + val classLoader = findClassLoader(1) + apply(name, ConfigFactory.load(classLoader), classLoader) + } + def apply(name: String, config: Config): ActorSystem = apply(name, config, findClassLoader(1)) + def apply(name: String, config: Config, classLoader: ClassLoader): ActorSystem = new ActorSystemImpl(name, config, classLoader).start() - class Settings(cfg: Config, final val name: String) { + class Settings(classLoader: ClassLoader, cfg: Config, final val name: String) { final val config: Config = { - val config = cfg.withFallback(ConfigFactory.defaultReference) - config.checkValid(ConfigFactory.defaultReference, "akka") + val config = cfg.withFallback(ConfigFactory.defaultReference(classLoader)) + config.checkValid(ConfigFactory.defaultReference(classLoader), "akka") config } @@ -98,6 +101,27 @@ object ActorSystem { override def toString: String = config.root.render } + + /** + * INTERNAL + */ + private[akka] def findClassLoader(depth: Int): ClassLoader = { + def findCaller(get: Int ⇒ Class[_]): ClassLoader = + Iterator.from(depth).map(get) dropWhile { c ⇒ + c != null && + (c.getName.startsWith("akka.actor.ActorSystem") || + c.getName.startsWith("scala.Option") || + c.getName.startsWith("scala.collection.Iterator") || + c.getName.startsWith("akka.util.Reflect")) + } next () match { + case null ⇒ getClass.getClassLoader + case c ⇒ c.getClassLoader + } + + Option(Thread.currentThread.getContextClassLoader) orElse + (Reflect.getCallerClass map findCaller) getOrElse + getClass.getClassLoader + } } /** @@ -344,14 +368,14 @@ abstract class ExtendedActorSystem extends ActorSystem { def dynamicAccess: DynamicAccess } -class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Config) extends ExtendedActorSystem { +class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Config, classLoader: ClassLoader) extends ExtendedActorSystem { if (!name.matches("""^\w+$""")) throw new IllegalArgumentException("invalid ActorSystem name [" + name + "], must contain only word characters (i.e. [a-zA-Z_0-9])") import ActorSystem._ - final val settings: Settings = new Settings(applicationConfig, name) + final val settings: Settings = new Settings(classLoader, applicationConfig, name) protected def uncaughtExceptionHandler: Thread.UncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() { @@ -366,33 +390,13 @@ class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Conf } final val threadFactory: MonitorableThreadFactory = - MonitorableThreadFactory(name, settings.Daemonicity, Option(Thread.currentThread.getContextClassLoader), uncaughtExceptionHandler) + MonitorableThreadFactory(name, settings.Daemonicity, Option(classLoader), uncaughtExceptionHandler) /** * This is an extension point: by overriding this method, subclasses can * control all reflection activities of an actor system. */ - protected def createDynamicAccess(): DynamicAccess = new ReflectiveDynamicAccess(findClassLoader) - - protected def findClassLoader: ClassLoader = { - def findCaller(get: Int ⇒ Class[_]): ClassLoader = { - val frames = Iterator.from(2).map(get) - frames dropWhile { c ⇒ - c != null && - (c.getName.startsWith("akka.actor.ActorSystem") || - c.getName.startsWith("scala.Option") || - c.getName.startsWith("scala.collection.Iterator") || - c.getName.startsWith("akka.util.Reflect")) - } next () match { - case null ⇒ getClass.getClassLoader - case c ⇒ c.getClassLoader - } - } - - Option(Thread.currentThread.getContextClassLoader) orElse - (Reflect.getCallerClass map findCaller) getOrElse - getClass.getClassLoader - } + protected def createDynamicAccess(): DynamicAccess = new ReflectiveDynamicAccess(classLoader) private val _pm: DynamicAccess = createDynamicAccess() def dynamicAccess: DynamicAccess = _pm From 2c6d4ec960a41d095dfd4699dad090de947e608e Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 16:59:33 +0100 Subject: [PATCH 13/46] Reinstating the magic number 2 into the stack-hack by Roland --- .../src/main/scala/akka/actor/GlobalActorSystem.scala | 2 +- akka-actor/src/main/scala/akka/actor/ActorSystem.scala | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala b/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala index 0eae8797d8..93787d43a6 100644 --- a/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala +++ b/akka-actor-migration/src/main/scala/akka/actor/GlobalActorSystem.scala @@ -26,7 +26,7 @@ object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfiguratio */ @deprecated("use default config location or write your own configuration loader", "2.0") object OldConfigurationLoader { - val oldClassLoader: ClassLoader = ActorSystem.findClassLoader(1) + val oldClassLoader: ClassLoader = ActorSystem.findClassLoader() val defaultConfig: Config = { val cfg = fromProperties orElse fromClasspath orElse fromHome getOrElse emptyConfig diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index 557a62133c..c8ac8dbb7c 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -50,10 +50,10 @@ object ActorSystem { */ def apply(): ActorSystem = apply("default") def apply(name: String): ActorSystem = { - val classLoader = findClassLoader(1) + val classLoader = findClassLoader() apply(name, ConfigFactory.load(classLoader), classLoader) } - def apply(name: String, config: Config): ActorSystem = apply(name, config, findClassLoader(1)) + def apply(name: String, config: Config): ActorSystem = apply(name, config, findClassLoader()) def apply(name: String, config: Config, classLoader: ClassLoader): ActorSystem = new ActorSystemImpl(name, config, classLoader).start() class Settings(classLoader: ClassLoader, cfg: Config, final val name: String) { @@ -105,9 +105,9 @@ object ActorSystem { /** * INTERNAL */ - private[akka] def findClassLoader(depth: Int): ClassLoader = { + private[akka] def findClassLoader(): ClassLoader = { def findCaller(get: Int ⇒ Class[_]): ClassLoader = - Iterator.from(depth).map(get) dropWhile { c ⇒ + Iterator.from(2 /*is the magic number, promise*/ ).map(get) dropWhile { c ⇒ c != null && (c.getName.startsWith("akka.actor.ActorSystem") || c.getName.startsWith("scala.Option") || From cc5e675f22bd663b50bc58f886db48a8d1807243 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 17:24:29 +0100 Subject: [PATCH 14/46] Fixing a couple of places where the classloader wasn't specified to load the config --- akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala | 3 ++- .../src/multi-jvm/scala/akka/remote/AkkaRemoteSpec.scala | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala b/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala index 127907412e..a2aed20c6c 100644 --- a/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala @@ -9,9 +9,10 @@ import com.typesafe.config.ConfigFactory import scala.collection.JavaConverters._ import akka.util.duration._ import akka.util.Duration +import akka.actor.ActorSystem @org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) -class ConfigSpec extends AkkaSpec(ConfigFactory.defaultReference) { +class ConfigSpec extends AkkaSpec(ConfigFactory.defaultReference(ActorSystem.findClassLoader())) { "The default configuration file (i.e. reference.conf)" must { "contain all configuration properties for akka-actor that are used in code with their correct defaults" in { diff --git a/akka-remote/src/multi-jvm/scala/akka/remote/AkkaRemoteSpec.scala b/akka-remote/src/multi-jvm/scala/akka/remote/AkkaRemoteSpec.scala index 9a6dd08226..c1a2109bc0 100644 --- a/akka-remote/src/multi-jvm/scala/akka/remote/AkkaRemoteSpec.scala +++ b/akka-remote/src/multi-jvm/scala/akka/remote/AkkaRemoteSpec.scala @@ -5,12 +5,12 @@ package akka.remote import akka.testkit._ -import akka.actor.ActorSystemImpl import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigParseOptions import com.typesafe.config.ConfigResolveOptions import java.io.File +import akka.actor.{ActorSystem, ActorSystemImpl} object AkkaRemoteSpec { private def configParseOptions = ConfigParseOptions.defaults.setAllowMissing(false) @@ -21,7 +21,7 @@ object AkkaRemoteSpec { case location ⇒ ConfigFactory.systemProperties .withFallback(ConfigFactory.parseFileAnySyntax(new File(location), configParseOptions)) - .withFallback(ConfigFactory.defaultReference).resolve(ConfigResolveOptions.defaults) + .withFallback(ConfigFactory.defaultReference(ActorSystem.findClassLoader())).resolve(ConfigResolveOptions.defaults) } } From 3630850ddef7171a90bab6378e3049ab553e83ff Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 1 Mar 2012 17:33:00 +0100 Subject: [PATCH 15/46] Adding decent ScalaDoc to the apply and create methods of ActorSystem --- .../main/scala/akka/actor/ActorSystem.scala | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index c8ac8dbb7c..c10965fd66 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -37,23 +37,69 @@ object ActorSystem { val GlobalHome = SystemHome orElse EnvHome - def create(): ActorSystem = apply() /** - * Uses the standard default Config from ConfigFactory.load(), since none is provided. + * Creates a new ActorSystem with the name "default", + * obtains the current ClassLoader by first inspecting the current threads' getContextClassLoader, + * then tries to walk the stack to find the callers class loader, then falls back to the ClassLoader + * associated with the ActorSystem class. + * Then it loads the default reference configuration using the ClassLoader. + */ + def create(): ActorSystem = apply() + + /** + * Creates a new ActorSystem with the specified name, + * obtains the current ClassLoader by first inspecting the current threads' getContextClassLoader, + * then tries to walk the stack to find the callers class loader, then falls back to the ClassLoader + * associated with the ActorSystem class. + * Then it loads the default reference configuration using the ClassLoader. */ def create(name: String): ActorSystem = apply(name) + + /** + * Creates a new ActorSystem with the name "default", and the specified Config, then + * obtains the current ClassLoader by first inspecting the current threads' getContextClassLoader, + * then tries to walk the stack to find the callers class loader, then falls back to the ClassLoader + * associated with the ActorSystem class. + */ def create(name: String, config: Config): ActorSystem = apply(name, config) + + /** + * Creates a new ActorSystem with the name "default", the specified Config, and specified ClassLoader + */ def create(name: String, config: Config, classLoader: ClassLoader): ActorSystem = apply(name, config, classLoader) /** - * Uses the standard default Config from ConfigFactory.load(), since none is provided. + * Creates a new ActorSystem with the name "default", + * obtains the current ClassLoader by first inspecting the current threads' getContextClassLoader, + * then tries to walk the stack to find the callers class loader, then falls back to the ClassLoader + * associated with the ActorSystem class. + * Then it loads the default reference configuration using the ClassLoader. */ def apply(): ActorSystem = apply("default") + + /** + * Creates a new ActorSystem with the specified name, + * obtains the current ClassLoader by first inspecting the current threads' getContextClassLoader, + * then tries to walk the stack to find the callers class loader, then falls back to the ClassLoader + * associated with the ActorSystem class. + * Then it loads the default reference configuration using the ClassLoader. + */ def apply(name: String): ActorSystem = { val classLoader = findClassLoader() apply(name, ConfigFactory.load(classLoader), classLoader) } + + /** + * Creates a new ActorSystem with the name "default", and the specified Config, then + * obtains the current ClassLoader by first inspecting the current threads' getContextClassLoader, + * then tries to walk the stack to find the callers class loader, then falls back to the ClassLoader + * associated with the ActorSystem class. + */ def apply(name: String, config: Config): ActorSystem = apply(name, config, findClassLoader()) + + /** + * Creates a new ActorSystem with the name "default", the specified Config, and specified ClassLoader + */ def apply(name: String, config: Config, classLoader: ClassLoader): ActorSystem = new ActorSystemImpl(name, config, classLoader).start() class Settings(classLoader: ClassLoader, cfg: Config, final val name: String) { From 37284bab4f23855b7b8e32e711b142a84dcd7d80 Mon Sep 17 00:00:00 2001 From: Roland Date: Thu, 1 Mar 2012 17:36:05 +0100 Subject: [PATCH 16/46] remove ActorContext.suspendForChildTermination, handle exceptions, add docs --- .../scala/akka/actor/SupervisorMiscSpec.scala | 12 --------- .../src/main/scala/akka/actor/ActorCell.scala | 26 ++++++++----------- akka-docs/java/typed-actors.rst | 10 +++---- akka-docs/java/untyped-actors.rst | 18 +++++-------- akka-docs/scala/actors.rst | 20 ++++++-------- 5 files changed, 31 insertions(+), 55 deletions(-) diff --git a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala index 43a5b97990..92af540a9a 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SupervisorMiscSpec.scala @@ -142,17 +142,5 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul expectMsg("green") } - "support suspending until all dying children have properly expired" in { - val parent = system.actorOf(Props(new Actor { - val child = context.actorOf(Props.empty, "bob") - def receive = { - case "engage" ⇒ context.stop(child); context.suspendForChildTermination(); self ! "next" - case "next" ⇒ context.actorOf(Props.empty, "bob"); testActor ! "green" - } - })) - parent ! "engage" - expectMsg("green") - } - } } diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 7c899df7cd..e0423d075c 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -134,14 +134,6 @@ trait ActorContext extends ActorRefFactory { */ def unwatch(subject: ActorRef): ActorRef - /** - * Suspend this actor (after finishing processing of the current message) - * until all children for which stop(child) has been called have actually - * terminated. This is useful if a new child with the same name needs to - * be created before processing can continue. - */ - def suspendForChildTermination(): Unit - final protected def writeObject(o: ObjectOutputStream): Unit = throw new NotSerializableException("ActorContext is not serializable!") } @@ -417,11 +409,6 @@ private[akka] class ActorCell( subject } - final def suspendForChildTermination(): Unit = childrenRefs match { - case _: TerminatingChildrenContainer ⇒ dispatcher suspend this - case _ ⇒ - } - final def children: Iterable[ActorRef] = childrenRefs.children /** @@ -686,6 +673,7 @@ private[akka] class ActorCell( dispatcher.reportFailure(new LogEventException(Error(e, self.path.toString, clazz(actor), "error while creating actor"), e)) // prevent any further messages to be processed until the actor has been restarted dispatcher.suspend(this) + actor.supervisorStrategy.handleSupervisorFailing(self, children) } finally { parent.tell(Failed(ActorInitializationException(self, "exception during re-creation", e)), self) } @@ -696,21 +684,29 @@ private[akka] class ActorCell( case None ⇒ system.eventStream.publish(Warning(self.path.toString, clazz(actor), "dropping Failed(" + cause + ") from unknown child " + child)) } - final def handleChildTerminated(child: ActorRef): Unit = { + final def handleChildTerminated(child: ActorRef): Unit = try { childrenRefs match { case tc @ TerminatingChildrenContainer(_, _, reason) ⇒ val n = tc.remove(child) childrenRefs = n actor.supervisorStrategy.handleChildTerminated(this, child, children) if (!n.isInstanceOf[TerminatingChildrenContainer]) reason match { - case UserRequest ⇒ if (mailbox.isSuspended) dispatcher resume this case Recreation(cause) ⇒ doRecreate(cause) case Termination ⇒ doTerminate() + case _ ⇒ } case _ ⇒ childrenRefs = childrenRefs.remove(child) actor.supervisorStrategy.handleChildTerminated(this, child, children) } + } catch { + case NonFatal(e) ⇒ + try { + dispatcher suspend this + actor.supervisorStrategy.handleSupervisorFailing(self, children) + } finally { + parent.tell(Failed(e), self) + } } // ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅ diff --git a/akka-docs/java/typed-actors.rst b/akka-docs/java/typed-actors.rst index 0a78a122a1..6f59fc4ebb 100644 --- a/akka-docs/java/typed-actors.rst +++ b/akka-docs/java/typed-actors.rst @@ -179,10 +179,10 @@ By having your Typed Actor implementation class implement any and all of the fol * ``TypedActor.PreRestart`` * ``TypedActor.PostRestart`` - You can hook into the lifecycle of your Typed Actor. +You can hook into the lifecycle of your Typed Actor. - Proxying - -------- +Proxying +-------- - You can use the ``typedActorOf`` that takes a TypedProps and an ActorRef to proxy the given ActorRef as a TypedActor. - This is usable if you want to communicate remotely with TypedActors on other machines, just look them up with ``actorFor`` and pass the ``ActorRef`` to ``typedActorOf``. +You can use the ``typedActorOf`` that takes a TypedProps and an ActorRef to proxy the given ActorRef as a TypedActor. +This is usable if you want to communicate remotely with TypedActors on other machines, just look them up with ``actorFor`` and pass the ``ActorRef`` to ``typedActorOf``. diff --git a/akka-docs/java/untyped-actors.rst b/akka-docs/java/untyped-actors.rst index 5120bb908d..b898cb7dbe 100644 --- a/akka-docs/java/untyped-actors.rst +++ b/akka-docs/java/untyped-actors.rst @@ -453,17 +453,6 @@ actors does not respond (i.e. processing a message for extended periods of time and therefore not receiving the stop command), this whole process will be stuck. -It is possible to disregard specific children with respect to shutdown -confirmation by stopping them explicitly before issuing the -``context.stop(self)``:: - - context.stop(someChild); - context.stop(self); - -In this case ``someChild`` will be stopped asynchronously and re-parented to -the :class:`Locker`, where :class:`DavyJones` will keep tabs and dispose of it -eventually. - Upon :meth:`ActorSystem.shutdown()`, the system guardian actors will be stopped, and the aforementioned process will ensure proper termination of the whole system. @@ -478,6 +467,13 @@ enables cleaning up of resources: // close some file or database connection } +.. note:: + + Since stopping an actor is asynchronous, you cannot immediately reuse the + name of the child you just stopped; this will result in an + :class:`InvalidActorNameException`. Instead, :meth:`watch()` the terminating + actor and create its replacement in response to the :class:`Terminated` + message which will eventually arrive. PoisonPill ---------- diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 01ef6ade83..b7ff85c31f 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -502,17 +502,6 @@ actors does not respond (i.e. processing a message for extended periods of time and therefore not receiving the stop command), this whole process will be stuck. -It is possible to disregard specific children with respect to shutdown -confirmation by stopping them explicitly before issuing the -``context.stop(self)``:: - - context.stop(someChild) - context.stop(self) - -In this case ``someChild`` will be stopped asynchronously and re-parented to -the :class:`Locker`, where :class:`DavyJones` will keep tabs and dispose of it -eventually. - Upon :meth:`ActorSystem.shutdown()`, the system guardian actors will be stopped, and the aforementioned process will ensure proper termination of the whole system. @@ -526,6 +515,13 @@ enables cleaning up of resources: // close some file or database connection } +.. note:: + + Since stopping an actor is asynchronous, you cannot immediately reuse the + name of the child you just stopped; this will result in an + :class:`InvalidActorNameException`. Instead, :meth:`watch()` the terminating + actor and create its replacement in response to the :class:`Terminated` + message which will eventually arrive. PoisonPill ---------- @@ -660,4 +656,4 @@ extend that, either through inheritance or delegation, is to use Or: -.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#receive-orElse2 \ No newline at end of file +.. includecode:: code/akka/docs/actor/ActorDocSpec.scala#receive-orElse2 From 51c0e3be2dda70d97d77f74b5bc8dc836a862a23 Mon Sep 17 00:00:00 2001 From: Roland Date: Thu, 1 Mar 2012 19:39:16 +0100 Subject: [PATCH 17/46] disallow actor creation while shutting down --- .../src/main/scala/akka/actor/ActorCell.scala | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index e0423d075c..8443fc7c4b 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -188,7 +188,7 @@ private[akka] object ActorCell { def shallDie(actor: ActorRef): ChildrenContainer } - object EmptyChildrenContainer extends ChildrenContainer { + trait EmptyChildrenContainer extends ChildrenContainer { val emptyStats = TreeMap.empty[String, ChildRestartStats] def add(child: ActorRef): ChildrenContainer = new NormalChildrenContainer(emptyStats.updated(child.path.name, ChildRestartStats(child))) @@ -201,6 +201,11 @@ private[akka] object ActorCell { override def toString = "no children" } + object EmptyChildrenContainer extends EmptyChildrenContainer + object TerminatedChildrenContainer extends EmptyChildrenContainer { + override def add(child: ActorRef): ChildrenContainer = this + } + class NormalChildrenContainer(c: TreeMap[String, ChildRestartStats]) extends ChildrenContainer { def add(child: ActorRef): ChildrenContainer = new NormalChildrenContainer(c.updated(child.path.name, ChildRestartStats(child))) @@ -238,7 +243,10 @@ private[akka] object ActorCell { def remove(child: ActorRef): ChildrenContainer = { val t = toDie - child - if (t.isEmpty) NormalChildrenContainer(c - child.path.name) + if (t.isEmpty) reason match { + case Termination ⇒ TerminatedChildrenContainer + case _ ⇒ NormalChildrenContainer(c - child.path.name) + } else copy(c - child.path.name, t) } @@ -309,6 +317,16 @@ private[akka] class ActorCell( @volatile var childrenRefs: ChildrenContainer = EmptyChildrenContainer + private def isTerminating = childrenRefs match { + case TerminatingChildrenContainer(_, _, Termination) ⇒ true + case TerminatedChildrenContainer ⇒ true + case _ ⇒ false + } + private def isNormal = childrenRefs match { + case TerminatingChildrenContainer(_, _, Termination | _: Recreation) ⇒ false + case _ ⇒ true + } + private def _actorOf(props: Props, name: String): ActorRef = { if (system.settings.SerializeAllCreators && !props.creator.isInstanceOf[NoSerializationVerificationNeeded]) { val ser = SerializationExtension(system) @@ -320,9 +338,12 @@ private[akka] class ActorCell( } } } - val actor = provider.actorOf(systemImpl, props, self, self.path / name, false, None, true) - childrenRefs = childrenRefs.add(actor) - actor + if (isTerminating) provider.actorFor(self, Seq(name)) + else { + val actor = provider.actorOf(systemImpl, props, self, self.path / name, false, None, true) + childrenRefs = childrenRefs.add(actor) + actor + } } def actorOf(props: Props): ActorRef = _actorOf(props, randomName()) @@ -449,15 +470,6 @@ private[akka] class ActorCell( //Memory consistency is handled by the Mailbox (reading mailbox status then processing messages, then writing mailbox status final def systemInvoke(message: SystemMessage) { - def isTerminating = childrenRefs match { - case TerminatingChildrenContainer(_, _, Termination) ⇒ true - case _ ⇒ false - } - def isNormal = childrenRefs match { - case TerminatingChildrenContainer(_, _, Termination | _: Recreation) ⇒ false - case _ ⇒ true - } - def create(): Unit = if (isNormal) { try { val created = newActor() From 000098016aca4920f08ae8415a1af457b846d7a1 Mon Sep 17 00:00:00 2001 From: Roland Date: Thu, 1 Mar 2012 19:54:37 +0100 Subject: [PATCH 18/46] add some scaladoc for ActorCell.ChildrenContainers --- .../src/main/scala/akka/actor/ActorCell.scala | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 8443fc7c4b..9063d953a9 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -161,6 +161,11 @@ trait UntypedActorContext extends ActorContext { } +/** + * Everything in here is completely Akka PRIVATE. You will not find any + * supported APIs in this place. This is not the API you were looking + * for! (waves hand) + */ private[akka] object ActorCell { val contextStack = new ThreadLocal[Stack[ActorContext]] { override def initialValue = Stack[ActorContext]() @@ -201,11 +206,26 @@ private[akka] object ActorCell { override def toString = "no children" } + /** + * This is the empty container, shared among all leaf actors. + */ object EmptyChildrenContainer extends EmptyChildrenContainer + + /** + * This is the empty container which is installed after the last child has + * terminated while stopping; it is necessary to distinguish from the normal + * empty state while calling handleChildTerminated() for the last time. + */ object TerminatedChildrenContainer extends EmptyChildrenContainer { override def add(child: ActorRef): ChildrenContainer = this } + /** + * Normal children container: we do have at least one child, but none of our + * children are currently terminating (which is the time period between + * calling context.stop(child) and processing the ChildTerminated() system + * message). + */ class NormalChildrenContainer(c: TreeMap[String, ChildRestartStats]) extends ChildrenContainer { def add(child: ActorRef): ChildrenContainer = new NormalChildrenContainer(c.updated(child.path.name, ChildRestartStats(child))) @@ -236,6 +256,16 @@ private[akka] object ActorCell { else new NormalChildrenContainer(c) } + /** + * Waiting state: there are outstanding termination requests (i.e. context.stop(child) + * was called but the corresponding ChildTerminated() system message has not yet been + * processed). There could be no specific reason (UserRequested), we could be Restarting + * or Terminating. + * + * Removing the last child which was supposed to be terminating will return a different + * type of container, depending on whether or not children are left and whether or not + * the reason was “Terminating”. + */ case class TerminatingChildrenContainer(c: TreeMap[String, ChildRestartStats], toDie: Set[ActorRef], reason: SuspendReason) extends ChildrenContainer { @@ -338,6 +368,7 @@ private[akka] class ActorCell( } } } + // in case we are currently terminating, swallow creation requests and return EmptyLocalActorRef if (isTerminating) provider.actorFor(self, Seq(name)) else { val actor = provider.actorOf(systemImpl, props, self, self.path / name, false, None, true) From f3938f719d0c1cc7bc5527b56fafa044e83ff659 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 2 Mar 2012 16:19:40 +0100 Subject: [PATCH 19/46] Scalariform --- akka-actor/src/main/scala/akka/actor/ActorCell.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 9063d953a9..fb394fac2e 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -163,7 +163,7 @@ trait UntypedActorContext extends ActorContext { /** * Everything in here is completely Akka PRIVATE. You will not find any - * supported APIs in this place. This is not the API you were looking + * supported APIs in this place. This is not the API you were looking * for! (waves hand) */ private[akka] object ActorCell { @@ -210,9 +210,9 @@ private[akka] object ActorCell { * This is the empty container, shared among all leaf actors. */ object EmptyChildrenContainer extends EmptyChildrenContainer - + /** - * This is the empty container which is installed after the last child has + * This is the empty container which is installed after the last child has * terminated while stopping; it is necessary to distinguish from the normal * empty state while calling handleChildTerminated() for the last time. */ @@ -222,7 +222,7 @@ private[akka] object ActorCell { /** * Normal children container: we do have at least one child, but none of our - * children are currently terminating (which is the time period between + * children are currently terminating (which is the time period between * calling context.stop(child) and processing the ChildTerminated() system * message). */ @@ -257,11 +257,11 @@ private[akka] object ActorCell { } /** - * Waiting state: there are outstanding termination requests (i.e. context.stop(child) + * Waiting state: there are outstanding termination requests (i.e. context.stop(child) * was called but the corresponding ChildTerminated() system message has not yet been * processed). There could be no specific reason (UserRequested), we could be Restarting * or Terminating. - * + * * Removing the last child which was supposed to be terminating will return a different * type of container, depending on whether or not children are left and whether or not * the reason was “Terminating”. From 65629f3314a637c6443ca4a423d5c01527ad9a49 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 2 Mar 2012 16:20:12 +0100 Subject: [PATCH 20/46] Fix to support initial slash in resource path, regression from RC3 --- akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java index 49cff71d57..981708ae55 100755 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java @@ -185,6 +185,8 @@ public final class ConfigFactory { + "'; don't know which one to use!"); } else { if (resource != null) { + if (resource.startsWith("/")) + resource = resource.substring(1); // this deliberately does not parseResourcesAnySyntax; if // people want that they can use an include statement. return load(loader, parseResources(loader, resource)); From 3a785b906535a689a0a8cfb4827765f694db5220 Mon Sep 17 00:00:00 2001 From: Roland Date: Fri, 2 Mar 2012 17:13:22 +0100 Subject: [PATCH 21/46] fix implementation of PromiseStream.<<(elem1,elem2,elems) - was doing the first two item specially and the sequencing the rest, which makes for some weird semantics - was giving the type inferencer a hard time for some reason --- .../test/scala/akka/dispatch/PromiseStreamSpec.scala | 11 +++++++++++ .../src/main/scala/akka/dispatch/PromiseStream.scala | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala b/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala index b3ce0108dd..7ac129e254 100644 --- a/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/dispatch/PromiseStreamSpec.scala @@ -95,6 +95,17 @@ class PromiseStreamSpec extends AkkaSpec with DefaultTimeout { assert(Await.result(c, timeout.duration) === 4) } + "map futures" in { + val q = PromiseStream[String]() + flow { + q << (Future("a"), Future("b"), Future("c")) + } + val a, b, c = q.dequeue + Await.result(a, timeout.duration) must be("a") + Await.result(b, timeout.duration) must be("b") + Await.result(c, timeout.duration) must be("c") + } + "not fail under concurrent stress" in { implicit val timeout = Timeout(60 seconds) val q = PromiseStream[Long](timeout.duration.toMillis) diff --git a/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala b/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala index b1c25f55e1..882219f84d 100644 --- a/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala +++ b/akka-actor/src/main/scala/akka/dispatch/PromiseStream.scala @@ -246,7 +246,10 @@ class PromiseStream[A](implicit val dispatcher: MessageDispatcher, val timeout: shift { cont: (PromiseStream[A] ⇒ Future[Any]) ⇒ elem map (a ⇒ cont(this += a)) } final def <<(elem1: Future[A], elem2: Future[A], elems: Future[A]*): PromiseStream[A] @cps[Future[Any]] = - shift { cont: (PromiseStream[A] ⇒ Future[Any]) ⇒ Future.flow(this << elem1 << elem2 <<< Future.sequence(elems.toSeq)) map cont } + shift { cont: (PromiseStream[A] ⇒ Future[Any]) ⇒ + val seq = Future.sequence(elem1 +: elem2 +: elems) + seq map (a ⇒ cont(this ++= a)) + } final def <<<(elems: Traversable[A]): PromiseStream[A] @cps[Future[Any]] = shift { cont: (PromiseStream[A] ⇒ Future[Any]) ⇒ cont(this ++= elems) } From fa1cd02eb135a8b2bcb76889798deeb676acde70 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Sun, 4 Mar 2012 20:47:26 +0100 Subject: [PATCH 22/46] Switching to Scala 2.9.1-1 --- project/AkkaBuild.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index d7053b0394..0822c57bf5 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -19,7 +19,7 @@ object AkkaBuild extends Build { lazy val buildSettings = Seq( organization := "com.typesafe.akka", version := "2.0-SNAPSHOT", - scalaVersion := "2.9.1-1-RC1" + scalaVersion := "2.9.1-1" ) lazy val akka = Project( From 1fd28e429e49fe8e883a141d0527c5451a269b69 Mon Sep 17 00:00:00 2001 From: Peter Vlugter Date: Mon, 5 Mar 2012 10:50:54 +1300 Subject: [PATCH 23/46] Update version to 2.1-SNAPSHOT --- .../test/scala/akka/config/ConfigSpec.scala | 4 +-- akka-actor/src/main/resources/reference.conf | 2 +- .../main/scala/akka/actor/ActorSystem.scala | 2 +- akka-docs/conf.py | 4 +-- akka-docs/dev/multi-jvm-testing.rst | 4 +-- .../intro/getting-started-first-java.rst | 26 +++++++-------- .../getting-started-first-scala-eclipse.rst | 16 +++++----- .../intro/getting-started-first-scala.rst | 32 +++++++++---------- akka-docs/intro/getting-started.rst | 18 +++++------ akka-docs/java/remoting.rst | 2 +- akka-docs/modules/camel.rst | 2 +- akka-docs/modules/spring.rst | 2 +- .../project/migration-guide-1.3.x-2.0.x.rst | 2 +- akka-docs/scala/remoting.rst | 2 +- akka-kernel/src/main/dist/README | 2 +- .../src/main/dist/config/application.conf | 2 +- akka-sbt-plugin/sample/project/Build.scala | 4 +-- akka-sbt-plugin/sample/project/plugins.sbt | 2 +- .../main/resources/META-INF/spring.schemas | 2 +- ...2.0-SNAPSHOT.xsd => akka-2.1-SNAPSHOT.xsd} | 0 akka-spring/src/test/resources/akka-test.conf | 2 +- akka-spring/src/test/resources/appContext.xml | 2 +- .../appContextCamelServiceCustom.xml | 2 +- .../appContextCamelServiceDefault.xml | 2 +- .../src/test/resources/dispatcher-config.xml | 2 +- .../src/test/resources/failing-appContext.xml | 2 +- .../src/test/resources/property-config.xml | 2 +- .../test/resources/server-managed-config.xml | 2 +- .../src/test/resources/supervisor-config.xml | 2 +- .../src/test/resources/typed-actor-config.xml | 2 +- .../test/resources/untyped-actor-config.xml | 2 +- akka-tutorials/akka-tutorial-first/pom.xml | 4 +-- .../project/TutorialBuild.scala | 8 ++--- project/AkkaBuild.scala | 2 +- src/main/ls/2.0.json | 4 +-- src/main/ls/2.1.json | 15 +++++++++ 36 files changed, 100 insertions(+), 85 deletions(-) rename akka-spring/src/main/resources/akka/spring/{akka-2.0-SNAPSHOT.xsd => akka-2.1-SNAPSHOT.xsd} (100%) create mode 100644 src/main/ls/2.1.json diff --git a/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala b/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala index a2aed20c6c..d24b2c4806 100644 --- a/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/config/ConfigSpec.scala @@ -23,8 +23,8 @@ class ConfigSpec extends AkkaSpec(ConfigFactory.defaultReference(ActorSystem.fin { import config._ - getString("akka.version") must equal("2.0-SNAPSHOT") - settings.ConfigVersion must equal("2.0-SNAPSHOT") + getString("akka.version") must equal("2.1-SNAPSHOT") + settings.ConfigVersion must equal("2.1-SNAPSHOT") getBoolean("akka.daemonic") must equal(false) getBoolean("akka.actor.serialize-messages") must equal(false) diff --git a/akka-actor/src/main/resources/reference.conf b/akka-actor/src/main/resources/reference.conf index 480826763f..6e747f8121 100644 --- a/akka-actor/src/main/resources/reference.conf +++ b/akka-actor/src/main/resources/reference.conf @@ -7,7 +7,7 @@ akka { # Akka version, checked against the runtime version of Akka. - version = "2.0-SNAPSHOT" + version = "2.1-SNAPSHOT" # Home directory of Akka, modules in the deploy directory will be loaded home = "" diff --git a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala index 58c2393c56..2c217a9109 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSystem.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSystem.scala @@ -23,7 +23,7 @@ import collection.immutable.Stack object ActorSystem { - val Version = "2.0-SNAPSHOT" + val Version = "2.1-SNAPSHOT" val EnvHome = System.getenv("AKKA_HOME") match { case null | "" | "." ⇒ None diff --git a/akka-docs/conf.py b/akka-docs/conf.py index 8a9e8c3240..28e3fe1591 100644 --- a/akka-docs/conf.py +++ b/akka-docs/conf.py @@ -17,8 +17,8 @@ exclude_patterns = ['_build', 'pending', 'disabled'] project = u'Akka' copyright = u'2011, Typesafe Inc' -version = '2.0-SNAPSHOT' -release = '2.0-SNAPSHOT' +version = '2.1-SNAPSHOT' +release = '2.1-SNAPSHOT' pygments_style = 'simple' highlight_language = 'scala' diff --git a/akka-docs/dev/multi-jvm-testing.rst b/akka-docs/dev/multi-jvm-testing.rst index 18154b6c27..3b6fd44f6c 100644 --- a/akka-docs/dev/multi-jvm-testing.rst +++ b/akka-docs/dev/multi-jvm-testing.rst @@ -48,7 +48,7 @@ multi-JVM testing:: lazy val buildSettings = Defaults.defaultSettings ++ Seq( organization := "com.typesafe.akka", - version := "2.0-SNAPSHOT", + version := "2.1-SNAPSHOT", scalaVersion := "2.9.1", crossPaths := false ) @@ -381,4 +381,4 @@ same machine at the same time. The machines that are used for testing (slaves) should have ssh access to the outside world and be able to talk to each other with the internal addresses given. On the master machine ssh client is required. Obviosly git -and sbt should be installed on both master and slave machines. \ No newline at end of file +and sbt should be installed on both master and slave machines. diff --git a/akka-docs/intro/getting-started-first-java.rst b/akka-docs/intro/getting-started-first-java.rst index 0a048a050f..a943555d4e 100644 --- a/akka-docs/intro/getting-started-first-java.rst +++ b/akka-docs/intro/getting-started-first-java.rst @@ -66,7 +66,7 @@ To build and run the tutorial sample from the command line, you have to download Akka. If you prefer to use SBT to build and run the sample then you can skip this section and jump to the next one. -Let's get the ``akka-2.0-SNAPSHOT.zip`` distribution of Akka from +Let's get the ``akka-2.1-SNAPSHOT.zip`` distribution of Akka from http://akka.io/downloads/ which includes everything we need for this tutorial. Once you have downloaded the distribution unzip it in the folder you would like to have Akka installed in. In my case I choose to install it in @@ -77,10 +77,10 @@ You need to do one more thing in order to install Akka properly: set the I'm opening up a shell, navigating down to the distribution, and setting the ``AKKA_HOME`` variable:: - $ cd /Users/jboner/tools/akka-2.0-SNAPSHOT + $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT $ export AKKA_HOME=`pwd` $ echo $AKKA_HOME - /Users/jboner/tools/akka-2.0-SNAPSHOT + /Users/jboner/tools/akka-2.1-SNAPSHOT The distribution looks like this:: @@ -100,7 +100,7 @@ The distribution looks like this:: - In the ``src`` directory we have the source JARs for Akka. The only JAR we will need for this tutorial (apart from the -``scala-library.jar`` JAR) is the ``akka-actor-2.0-SNAPSHOT.jar`` JAR in the ``lib/akka`` +``scala-library.jar`` JAR) is the ``akka-actor-2.1-SNAPSHOT.jar`` JAR in the ``lib/akka`` directory. This is a self-contained JAR with zero dependencies and contains everything we need to write a system using Actors. @@ -120,10 +120,10 @@ modules are: - ``akka-durable-mailboxes`` -- Durable mailboxes: file-based, MongoDB, Redis, Beanstalk and Zookeeper .. - ``akka-amqp`` -- AMQP integration -.. - ``akka-stm-2.0-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures -.. - ``akka-camel-2.0-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) -.. - ``akka-camel-typed-2.0-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration -.. - ``akka-spring-2.0-SNAPSHOT.jar`` -- Spring framework integration +.. - ``akka-stm-2.1-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures +.. - ``akka-camel-2.1-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) +.. - ``akka-camel-typed-2.1-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration +.. - ``akka-spring-2.1-SNAPSHOT.jar`` -- Spring framework integration @@ -192,7 +192,7 @@ repositories, including akka.io. It should now look something like this: com.typesafe.akka akka-actor - 2.0-SNAPSHOT + 2.1-SNAPSHOT @@ -360,19 +360,19 @@ time. When that's done open up a shell and step in to the Akka distribution (``cd $AKKA_HOME``). First we need to compile the source file. That is done with Java's compiler -``javac``. Our application depends on the ``akka-actor-2.0-SNAPSHOT.jar`` and the +``javac``. Our application depends on the ``akka-actor-2.1-SNAPSHOT.jar`` and the ``scala-library.jar`` JAR files, so let's add them to the compiler classpath when we compile the source:: - $ javac -cp lib/scala-library.jar:lib/akka/akka-actor-2.0-SNAPSHOT.jar tutorial/akka/tutorial/first/java/Pi.java + $ javac -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar tutorial/akka/tutorial/first/java/Pi.java When we have compiled the source file we are ready to run the application. This -is done with ``java`` but yet again we need to add the ``akka-actor-2.0-SNAPSHOT.jar`` +is done with ``java`` but yet again we need to add the ``akka-actor-2.1-SNAPSHOT.jar`` and the ``scala-library.jar`` JAR files to the classpath as well as the classes we compiled ourselves:: $ java \ - -cp lib/scala-library.jar:lib/akka/akka-actor-2.0-SNAPSHOT.jar:. \ + -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar:. \ akka.tutorial.java.first.Pi Pi approximation: 3.1435501812459323 diff --git a/akka-docs/intro/getting-started-first-scala-eclipse.rst b/akka-docs/intro/getting-started-first-scala-eclipse.rst index 9e02f99a71..96707b4eb3 100644 --- a/akka-docs/intro/getting-started-first-scala-eclipse.rst +++ b/akka-docs/intro/getting-started-first-scala-eclipse.rst @@ -88,7 +88,7 @@ To build and run the tutorial sample from the command line, you have to download Akka. If you prefer to use SBT to build and run the sample then you can skip this section and jump to the next one. -Let's get the ``akka-2.0-SNAPSHOT.zip`` distribution of Akka from +Let's get the ``akka-2.1-SNAPSHOT.zip`` distribution of Akka from http://akka.io/downloads/ which includes everything we need for this tutorial. Once you have downloaded the distribution unzip it in the folder you would like to have Akka installed in. In my case I choose to install it in @@ -99,10 +99,10 @@ You need to do one more thing in order to install Akka properly: set the I'm opening up a shell, navigating down to the distribution, and setting the ``AKKA_HOME`` variable:: - $ cd /Users/jboner/tools/akka-2.0-SNAPSHOT + $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT $ export AKKA_HOME=`pwd` $ echo $AKKA_HOME - /Users/jboner/tools/akka-2.0-SNAPSHOT + /Users/jboner/tools/akka-2.1-SNAPSHOT The distribution looks like this:: @@ -122,7 +122,7 @@ The distribution looks like this:: - In the ``src`` directory we have the source JARs for Akka. The only JAR we will need for this tutorial (apart from the -``scala-library.jar`` JAR) is the ``akka-actor-2.0-SNAPSHOT.jar`` JAR in the ``lib/akka`` +``scala-library.jar`` JAR) is the ``akka-actor-2.1-SNAPSHOT.jar`` JAR in the ``lib/akka`` directory. This is a self-contained JAR with zero dependencies and contains everything we need to write a system using Actors. @@ -142,10 +142,10 @@ modules are: - ``akka-durable-mailboxes`` -- Durable mailboxes: file-based, MongoDB, Redis, Zookeeper .. - ``akka-amqp`` -- AMQP integration -.. - ``akka-stm-2.0-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures -.. - ``akka-camel-2.0-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) -.. - ``akka-camel-typed-2.0-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration -.. - ``akka-spring-2.0-SNAPSHOT.jar`` -- Spring framework integration +.. - ``akka-stm-2.1-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures +.. - ``akka-camel-2.1-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) +.. - ``akka-camel-typed-2.1-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration +.. - ``akka-spring-2.1-SNAPSHOT.jar`` -- Spring framework integration Downloading and installing the Scala IDE for Eclipse diff --git a/akka-docs/intro/getting-started-first-scala.rst b/akka-docs/intro/getting-started-first-scala.rst index 0d66c11eea..702c996291 100644 --- a/akka-docs/intro/getting-started-first-scala.rst +++ b/akka-docs/intro/getting-started-first-scala.rst @@ -89,7 +89,7 @@ To build and run the tutorial sample from the command line, you have to download Akka. If you prefer to use SBT to build and run the sample then you can skip this section and jump to the next one. -Let's get the ``akka-2.0-SNAPSHOT.zip`` distribution of Akka from +Let's get the ``akka-2.1-SNAPSHOT.zip`` distribution of Akka from http://akka.io/downloads/ which includes everything we need for this tutorial. Once you have downloaded the distribution unzip it in the folder you would like to have Akka installed in. In my case I choose to install it in @@ -100,10 +100,10 @@ You need to do one more thing in order to install Akka properly: set the I'm opening up a shell, navigating down to the distribution, and setting the ``AKKA_HOME`` variable:: - $ cd /Users/jboner/tools/akka-2.0-SNAPSHOT + $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT $ export AKKA_HOME=`pwd` $ echo $AKKA_HOME - /Users/jboner/tools/akka-2.0-SNAPSHOT + /Users/jboner/tools/akka-2.1-SNAPSHOT The distribution looks like this:: @@ -123,7 +123,7 @@ The distribution looks like this:: - In the ``src`` directory we have the source JARs for Akka. The only JAR we will need for this tutorial (apart from the -``scala-library.jar`` JAR) is the ``akka-actor-2.0-SNAPSHOT.jar`` JAR in the ``lib/akka`` +``scala-library.jar`` JAR) is the ``akka-actor-2.1-SNAPSHOT.jar`` JAR in the ``lib/akka`` directory. This is a self-contained JAR with zero dependencies and contains everything we need to write a system using Actors. @@ -144,10 +144,10 @@ modules are: - ``akka-amqp`` -- AMQP integration -.. - ``akka-stm-2.0-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures -.. - ``akka-camel-2.0-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) -.. - ``akka-camel-typed-2.0-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration -.. - ``akka-spring-2.0-SNAPSHOT.jar`` -- Spring framework integration +.. - ``akka-stm-2.1-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures +.. - ``akka-camel-2.1-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) +.. - ``akka-camel-typed-2.1-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration +.. - ``akka-spring-2.1-SNAPSHOT.jar`` -- Spring framework integration Downloading and installing Scala @@ -216,7 +216,7 @@ in the directory you want to create your project in:: resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" - libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.0-SNAPSHOT" + libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.1-SNAPSHOT" Create a directory ``src/main/scala`` in which you will store the Scala source files. @@ -226,14 +226,14 @@ modules beyond ``akka-actor``, you can add these as ``libraryDependencies`` in ``build.sbt``. Note that there must be a blank line between each. Here is an example adding ``akka-remote``:: - libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.0-SNAPSHOT" + libraryDependencies += "com.typesafe.akka" % "akka-actor" % "2.1-SNAPSHOT" - libraryDependencies += "com.typesafe.akka" % "akka-remote" % "2.0-SNAPSHOT" + libraryDependencies += "com.typesafe.akka" % "akka-remote" % "2.1-SNAPSHOT" So, now we are all set. SBT itself needs a whole bunch of dependencies but our project will only need -one; ``akka-actor-2.0-SNAPSHOT.jar``. SBT will download that as well. +one; ``akka-actor-2.1-SNAPSHOT.jar``. SBT will download that as well. Start writing the code @@ -403,19 +403,19 @@ If you have not typed in (or copied) the code for the tutorial as in When that's done open up a shell and step in to the Akka distribution (``cd $AKKA_HOME``). First we need to compile the source file. That is done with Scala's compiler -``scalac``. Our application depends on the ``akka-actor-2.0-SNAPSHOT.jar`` JAR +``scalac``. Our application depends on the ``akka-actor-2.1-SNAPSHOT.jar`` JAR file, so let's add that to the compiler classpath when we compile the source:: - $ scalac -cp lib/akka/akka-actor-2.0-SNAPSHOT.jar Pi.scala + $ scalac -cp lib/akka/akka-actor-2.1-SNAPSHOT.jar Pi.scala When we have compiled the source file we are ready to run the application. This is done with ``java`` but yet again we need to add the -``akka-actor-2.0-SNAPSHOT.jar`` JAR file to the classpath, and this time we also +``akka-actor-2.1-SNAPSHOT.jar`` JAR file to the classpath, and this time we also need to add the Scala runtime library ``scala-library.jar`` and the classes we compiled ourselves:: $ java \ - -cp lib/scala-library.jar:lib/akka/akka-actor-2.0-SNAPSHOT.jar:. \ + -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar:. \ akka.tutorial.first.scala.Pi Pi approximation: 3.1435501812459323 diff --git a/akka-docs/intro/getting-started.rst b/akka-docs/intro/getting-started.rst index 16a4a46c2f..75f62a39d9 100644 --- a/akka-docs/intro/getting-started.rst +++ b/akka-docs/intro/getting-started.rst @@ -44,12 +44,12 @@ Modules Akka is very modular and has many JARs for containing different features. -- ``akka-actor-2.0-SNAPSHOT.jar`` -- Standard Actors, Typed Actors and much more -- ``akka-remote-2.0-SNAPSHOT.jar`` -- Remote Actors -- ``akka-slf4j-2.0-SNAPSHOT.jar`` -- SLF4J Event Handler Listener -- ``akka-testkit-2.0-SNAPSHOT.jar`` -- Toolkit for testing Actors -- ``akka-kernel-2.0-SNAPSHOT.jar`` -- Akka microkernel for running a bare-bones mini application server -- ``akka--mailbox-2.0-SNAPSHOT.jar`` -- Akka durable mailboxes +- ``akka-actor-2.1-SNAPSHOT.jar`` -- Standard Actors, Typed Actors and much more +- ``akka-remote-2.1-SNAPSHOT.jar`` -- Remote Actors +- ``akka-slf4j-2.1-SNAPSHOT.jar`` -- SLF4J Event Handler Listener +- ``akka-testkit-2.1-SNAPSHOT.jar`` -- Toolkit for testing Actors +- ``akka-kernel-2.1-SNAPSHOT.jar`` -- Akka microkernel for running a bare-bones mini application server +- ``akka--mailbox-2.1-SNAPSHOT.jar`` -- Akka durable mailboxes How to see the JARs dependencies of each Akka module is described in the :ref:`dependencies` section. Worth noting is that ``akka-actor`` has zero @@ -105,14 +105,14 @@ Summary of the essential parts for using Akka with Maven: http://repo.typesafe.com/typesafe/releases/ -2) Add the Akka dependencies. For example, here is the dependency for Akka Actor 2.0-SNAPSHOT: +2) Add the Akka dependencies. For example, here is the dependency for Akka Actor 2.1-SNAPSHOT: .. code-block:: xml com.typesafe.akka akka-actor - 2.0-SNAPSHOT + 2.1-SNAPSHOT **Note**: for snapshot versions both ``SNAPSHOT`` and timestamped versions are published. @@ -138,7 +138,7 @@ SBT installation instructions on `https://github.com/harrah/xsbt/wiki/Setup com.typesafe.akka akka-remote - 2.0-SNAPSHOT + 2.1-SNAPSHOT To enable remote capabilities in your Akka project you should, at a minimum, add the following changes diff --git a/akka-docs/modules/camel.rst b/akka-docs/modules/camel.rst index 9891a94de8..68686ce586 100644 --- a/akka-docs/modules/camel.rst +++ b/akka-docs/modules/camel.rst @@ -6,7 +6,7 @@ ####### .. note:: - The Akka Camel module has not been migrated to Akka 2.0-SNAPSHOT yet. + The Akka Camel module has not been migrated to Akka 2.1-SNAPSHOT yet. It might not make it into Akka 2.0 final but will then hopefully be re-introduce in an upcoming release. It might also be backported to diff --git a/akka-docs/modules/spring.rst b/akka-docs/modules/spring.rst index 5a626e779b..e7ec2de313 100644 --- a/akka-docs/modules/spring.rst +++ b/akka-docs/modules/spring.rst @@ -6,7 +6,7 @@ #################### .. note:: - The Akka Spring module has not been migrated to Akka 2.0-SNAPSHOT yet. + The Akka Spring module has not been migrated to Akka 2.1-SNAPSHOT yet. It might not make it into Akka 2.0 final but will then hopefully be re-introduce in an upcoming release. It might also be backported to diff --git a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst index e933d6bca8..2440068d36 100644 --- a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst +++ b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst @@ -33,7 +33,7 @@ be removed in Akka 2.1. The migration kit is provided in separate jar files. Add the following dependency:: - "com.typesafe.akka" % "akka-actor-migration" % "2.0-SNAPSHOT" + "com.typesafe.akka" % "akka-actor-migration" % "2.0" The first step of the migration is to do some trivial replacements. Search and replace the following (be careful with the non qualified names): diff --git a/akka-docs/scala/remoting.rst b/akka-docs/scala/remoting.rst index 5e613dd7e4..9ccd41366a 100644 --- a/akka-docs/scala/remoting.rst +++ b/akka-docs/scala/remoting.rst @@ -16,7 +16,7 @@ Preparing your ActorSystem for Remoting The Akka remoting is a separate jar file. Make sure that you have the following dependency in your project:: - "com.typesafe.akka" % "akka-remote" % "2.0-SNAPSHOT" + "com.typesafe.akka" % "akka-remote" % "2.1-SNAPSHOT" To enable remote capabilities in your Akka project you should, at a minimum, add the following changes to your ``application.conf`` file:: diff --git a/akka-kernel/src/main/dist/README b/akka-kernel/src/main/dist/README index 179f3c97a9..b531da6164 100644 --- a/akka-kernel/src/main/dist/README +++ b/akka-kernel/src/main/dist/README @@ -2,7 +2,7 @@ Akka ==== -This is the Akka 2.0-SNAPSHOT download. +This is the Akka 2.1-SNAPSHOT download. Included are all libraries, documentation, and sources for Akka. diff --git a/akka-kernel/src/main/dist/config/application.conf b/akka-kernel/src/main/dist/config/application.conf index 682d41e484..4abcd7e7f8 100644 --- a/akka-kernel/src/main/dist/config/application.conf +++ b/akka-kernel/src/main/dist/config/application.conf @@ -1,3 +1,3 @@ # In this file you can override any option defined in the 'reference.conf' files. # Copy in all or parts of the 'reference.conf' files and modify as you please. -# For more info about config, please visit the Akka Documentation: http://akka.io/docs/akka/2.0-SNAPSHOT/ +# For more info about config, please visit the Akka Documentation: http://akka.io/docs/akka/2.1-SNAPSHOT/ diff --git a/akka-sbt-plugin/sample/project/Build.scala b/akka-sbt-plugin/sample/project/Build.scala index 60c83740f8..959f98511e 100644 --- a/akka-sbt-plugin/sample/project/Build.scala +++ b/akka-sbt-plugin/sample/project/Build.scala @@ -6,7 +6,7 @@ import akka.sbt.AkkaKernelPlugin.{ Dist, outputDirectory, distJvmOptions} object HelloKernelBuild extends Build { val Organization = "akka.sample" - val Version = "2.0-SNAPSHOT" + val Version = "2.1-SNAPSHOT" val ScalaVersion = "2.9.1" lazy val HelloKernel = Project( @@ -49,7 +49,7 @@ object Dependencies { object Dependency { // Versions object V { - val Akka = "2.0-SNAPSHOT" + val Akka = "2.1-SNAPSHOT" } val akkaKernel = "com.typesafe.akka" % "akka-kernel" % V.Akka diff --git a/akka-sbt-plugin/sample/project/plugins.sbt b/akka-sbt-plugin/sample/project/plugins.sbt index a44d2ee72f..3f814e328e 100644 --- a/akka-sbt-plugin/sample/project/plugins.sbt +++ b/akka-sbt-plugin/sample/project/plugins.sbt @@ -1,3 +1,3 @@ resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/" -addSbtPlugin("com.typesafe.akka" % "akka-sbt-plugin" % "2.0-SNAPSHOT") +addSbtPlugin("com.typesafe.akka" % "akka-sbt-plugin" % "2.1-SNAPSHOT") diff --git a/akka-spring/src/main/resources/META-INF/spring.schemas b/akka-spring/src/main/resources/META-INF/spring.schemas index 68e55a2fb4..ae3fc27472 100644 --- a/akka-spring/src/main/resources/META-INF/spring.schemas +++ b/akka-spring/src/main/resources/META-INF/spring.schemas @@ -1 +1 @@ -http\://akka.io/akka-2.0-SNAPSHOT.xsd=akka/spring/akka-2.0-SNAPSHOT.xsd +http\://akka.io/akka-2.1-SNAPSHOT.xsd=akka/spring/akka-2.1-SNAPSHOT.xsd diff --git a/akka-spring/src/main/resources/akka/spring/akka-2.0-SNAPSHOT.xsd b/akka-spring/src/main/resources/akka/spring/akka-2.1-SNAPSHOT.xsd similarity index 100% rename from akka-spring/src/main/resources/akka/spring/akka-2.0-SNAPSHOT.xsd rename to akka-spring/src/main/resources/akka/spring/akka-2.1-SNAPSHOT.xsd diff --git a/akka-spring/src/test/resources/akka-test.conf b/akka-spring/src/test/resources/akka-test.conf index a4838f6cc7..bf3cc890b2 100644 --- a/akka-spring/src/test/resources/akka-test.conf +++ b/akka-spring/src/test/resources/akka-test.conf @@ -6,7 +6,7 @@ # Modify as needed. akka { - version = "2.0-SNAPSHOT" # Akka version, checked against the runtime version of Akka. + version = "2.1-SNAPSHOT" # Akka version, checked against the runtime version of Akka. enabled-modules = ["remote"] # Comma separated list of the enabled modules. Options: ["remote", "camel", "http"] diff --git a/akka-spring/src/test/resources/appContext.xml b/akka-spring/src/test/resources/appContext.xml index ee2f011b6b..c865719bbb 100644 --- a/akka-spring/src/test/resources/appContext.xml +++ b/akka-spring/src/test/resources/appContext.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://akka.io/schema/akka - http://akka.io/akka-2.0-SNAPSHOT.xsd"> + http://akka.io/akka-2.1-SNAPSHOT.xsd"> diff --git a/akka-spring/src/test/resources/appContextCamelServiceDefault.xml b/akka-spring/src/test/resources/appContextCamelServiceDefault.xml index 12c12b39f5..b115f35dd2 100644 --- a/akka-spring/src/test/resources/appContextCamelServiceDefault.xml +++ b/akka-spring/src/test/resources/appContextCamelServiceDefault.xml @@ -6,7 +6,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://akka.io/schema/akka -http://akka.io/akka-2.0-SNAPSHOT.xsd +http://akka.io/akka-2.1-SNAPSHOT.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> diff --git a/akka-spring/src/test/resources/dispatcher-config.xml b/akka-spring/src/test/resources/dispatcher-config.xml index 591070ac9f..c0e2e857fc 100644 --- a/akka-spring/src/test/resources/dispatcher-config.xml +++ b/akka-spring/src/test/resources/dispatcher-config.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://akka.io/schema/akka -http://akka.io/akka-2.0-SNAPSHOT.xsd"> +http://akka.io/akka-2.1-SNAPSHOT.xsd"> + http://akka.io/akka-2.1-SNAPSHOT.xsd"> +http://akka.io/akka-2.1-SNAPSHOT.xsd"> diff --git a/akka-spring/src/test/resources/server-managed-config.xml b/akka-spring/src/test/resources/server-managed-config.xml index f6ccafba93..8bb7e3874c 100644 --- a/akka-spring/src/test/resources/server-managed-config.xml +++ b/akka-spring/src/test/resources/server-managed-config.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://akka.io/schema/akka -http://akka.io/akka-2.0-SNAPSHOT.xsd"> +http://akka.io/akka-2.1-SNAPSHOT.xsd"> +http://akka.io/akka-2.1-SNAPSHOT.xsd"> diff --git a/akka-spring/src/test/resources/typed-actor-config.xml b/akka-spring/src/test/resources/typed-actor-config.xml index 1fd1d5f561..fb8af30747 100644 --- a/akka-spring/src/test/resources/typed-actor-config.xml +++ b/akka-spring/src/test/resources/typed-actor-config.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://akka.io/schema/akka -http://akka.io/akka-2.0-SNAPSHOT.xsd"> +http://akka.io/akka-2.1-SNAPSHOT.xsd"> +http://akka.io/akka-2.1-SNAPSHOT.xsd"> diff --git a/akka-tutorials/akka-tutorial-first/pom.xml b/akka-tutorials/akka-tutorial-first/pom.xml index 1cec835a9c..01000a5896 100644 --- a/akka-tutorials/akka-tutorial-first/pom.xml +++ b/akka-tutorials/akka-tutorial-first/pom.xml @@ -8,14 +8,14 @@ akka.tutorial.first.java akka-tutorial-first-java jar - 2.0-SNAPSHOT + 2.1-SNAPSHOT http://akka.io com.typesafe.akka akka-actor - 2.0-SNAPSHOT + 2.1-SNAPSHOT diff --git a/akka-tutorials/akka-tutorial-first/project/TutorialBuild.scala b/akka-tutorials/akka-tutorial-first/project/TutorialBuild.scala index 5e5ef32493..d468b69324 100644 --- a/akka-tutorials/akka-tutorial-first/project/TutorialBuild.scala +++ b/akka-tutorials/akka-tutorial-first/project/TutorialBuild.scala @@ -4,7 +4,7 @@ import Keys._ object TutorialBuild extends Build { lazy val buildSettings = Seq( organization := "com.typesafe.akka", - version := "2.0-SNAPSHOT", + version := "2.1-SNAPSHOT", scalaVersion := "2.9.1" ) @@ -13,10 +13,10 @@ object TutorialBuild extends Build { base = file("."), settings = Defaults.defaultSettings ++ Seq( libraryDependencies ++= Seq( - "com.typesafe.akka" % "akka-actor" % "2.0-SNAPSHOT", + "com.typesafe.akka" % "akka-actor" % "2.1-SNAPSHOT", "junit" % "junit" % "4.5" % "test", "org.scalatest" % "scalatest_2.9.0" % "1.6.1" % "test", - "com.typesafe.akka" % "akka-testkit" % "2.0-SNAPSHOT" % "test") + "com.typesafe.akka" % "akka-testkit" % "2.1-SNAPSHOT" % "test") ) ) -} \ No newline at end of file +} diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index 0822c57bf5..e2468ff26e 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -18,7 +18,7 @@ object AkkaBuild extends Build { lazy val buildSettings = Seq( organization := "com.typesafe.akka", - version := "2.0-SNAPSHOT", + version := "2.1-SNAPSHOT", scalaVersion := "2.9.1-1" ) diff --git a/src/main/ls/2.0.json b/src/main/ls/2.0.json index 067332ed73..ff726ab2c0 100644 --- a/src/main/ls/2.0.json +++ b/src/main/ls/2.0.json @@ -2,7 +2,7 @@ { "organization":"com.typesafe.akka", "name":"akka", - "version":"2.0-SNAPSHOT", + "version":"2.0", "description":"Akka is the platform for the next generation of event-driven, scalable and fault-tolerant architectures on the JVM.", "site":"", "tags":["actors","stm","concurrency","distributed","fault-tolerance","scala","java","futures","dataflow","remoting"], @@ -12,4 +12,4 @@ "dependencies": [], "scalas": ["2.9.1"], "sbt": false -} \ No newline at end of file +} diff --git a/src/main/ls/2.1.json b/src/main/ls/2.1.json new file mode 100644 index 0000000000..0ec5cad9e2 --- /dev/null +++ b/src/main/ls/2.1.json @@ -0,0 +1,15 @@ + +{ + "organization":"com.typesafe.akka", + "name":"akka", + "version":"2.1-SNAPSHOT", + "description":"Akka is the platform for the next generation of event-driven, scalable and fault-tolerant architectures on the JVM.", + "site":"", + "tags":["actors","stm","concurrency","distributed","fault-tolerance","scala","java","futures","dataflow","remoting"], + "docs":"", + "licenses": [], + "resolvers": ["http://akka.io/repository/"], + "dependencies": [], + "scalas": ["2.9.1"], + "sbt": false +} From 43cb56929dfd178acd67bdcc71229f3798003750 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 5 Mar 2012 10:15:50 +0100 Subject: [PATCH 24/46] Fixing #1876 --- akka-docs/intro/getting-started-first-scala-eclipse.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/akka-docs/intro/getting-started-first-scala-eclipse.rst b/akka-docs/intro/getting-started-first-scala-eclipse.rst index 9e02f99a71..4e66163f28 100644 --- a/akka-docs/intro/getting-started-first-scala-eclipse.rst +++ b/akka-docs/intro/getting-started-first-scala-eclipse.rst @@ -162,9 +162,6 @@ the URL you just copied. You should see something similar to the following image .. image:: ../images/install-beta2-updatesite.png -Make sure you select both the ``JDT Weaving for Scala`` and the ``Scala IDE for Eclipse`` plugins. -The other plugin is optional, and contains the source code of the plugin itself. - Once the installation is finished, you need to restart Eclipse. The first time the plugin starts it will open a diagnostics window and offer to fix several settings, such as the delay for content assist (code-completion) or the shown completion proposal types. From c9b768af7fae32a0e84293b3d54d789a3139bc81 Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 5 Mar 2012 10:27:00 +0100 Subject: [PATCH 25/46] move to github.com/akka/akka in docs --- akka-docs/dev/building-akka.rst | 4 ++-- akka-docs/dev/developer-guidelines.rst | 4 ++-- akka-docs/disabled/external-sample-projects.rst | 2 +- akka-docs/index.rst | 2 +- akka-docs/intro/getting-started-first-java.rst | 6 +++--- akka-docs/intro/getting-started-first-scala-eclipse.rst | 6 +++--- akka-docs/intro/getting-started-first-scala.rst | 6 +++--- akka-docs/intro/getting-started.rst | 2 +- akka-docs/java/event-bus.rst | 2 +- akka-docs/java/remoting.rst | 2 +- akka-docs/java/routing.rst | 2 +- akka-docs/project/licenses.rst | 2 +- akka-docs/project/links.rst | 4 ++-- akka-docs/scala/actors.rst | 4 ++-- akka-docs/scala/event-bus.rst | 2 +- akka-docs/scala/fsm.rst | 4 ++-- akka-docs/scala/remoting.rst | 2 +- akka-docs/scala/routing.rst | 4 ++-- 18 files changed, 30 insertions(+), 30 deletions(-) diff --git a/akka-docs/dev/building-akka.rst b/akka-docs/dev/building-akka.rst index 495d8ba5ed..d0cffbac86 100644 --- a/akka-docs/dev/building-akka.rst +++ b/akka-docs/dev/building-akka.rst @@ -21,11 +21,11 @@ Akka uses `Git`_ and is hosted at `Github`_. .. _Github: http://github.com You first need Git installed on your machine. You can then clone the source -repository from http://github.com/jboner/akka. +repository from http://github.com/akka/akka. For example:: - git clone git://github.com/jboner/akka.git + git clone git://github.com/akka/akka.git If you have already cloned the repository previously then you can update the code with ``git pull``:: diff --git a/akka-docs/dev/developer-guidelines.rst b/akka-docs/dev/developer-guidelines.rst index 138d774619..bc52613d47 100644 --- a/akka-docs/dev/developer-guidelines.rst +++ b/akka-docs/dev/developer-guidelines.rst @@ -44,12 +44,12 @@ All code that is checked in **should** have tests. All testing is done with ``Sc * Name tests as **Test.scala** if they do not depend on any external stuff. That keeps surefire happy. * Name tests as **Spec.scala** if they have external dependencies. -There is a testing standard that should be followed: `Ticket001Spec `_ +There is a testing standard that should be followed: `Ticket001Spec `_ Actor TestKit ^^^^^^^^^^^^^ -There is a useful test kit for testing actors: `akka.util.TestKit `_. It enables assertions concerning replies received and their timing, there is more documentation in the :ref:`akka-testkit` module. +There is a useful test kit for testing actors: `akka.util.TestKit `_. It enables assertions concerning replies received and their timing, there is more documentation in the :ref:`akka-testkit` module. Multi-JVM Testing ^^^^^^^^^^^^^^^^^ diff --git a/akka-docs/disabled/external-sample-projects.rst b/akka-docs/disabled/external-sample-projects.rst index 80e56823af..3d9aeddba6 100644 --- a/akka-docs/disabled/external-sample-projects.rst +++ b/akka-docs/disabled/external-sample-projects.rst @@ -139,7 +139,7 @@ Akka Benchmark project ^^^^^^^^^^^^^^^^^^^^^^ Benches Akka against various other actors and concurrency tools -``_ +``_ Typed Actor (Java API) sample project ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/akka-docs/index.rst b/akka-docs/index.rst index 5bd1b7ed80..f631987945 100644 --- a/akka-docs/index.rst +++ b/akka-docs/index.rst @@ -22,7 +22,7 @@ Links * `Downloads `_ -* `Source Code `_ +* `Source Code `_ * :ref:`scaladoc` diff --git a/akka-docs/intro/getting-started-first-java.rst b/akka-docs/intro/getting-started-first-java.rst index a943555d4e..0a090d02bd 100644 --- a/akka-docs/intro/getting-started-first-java.rst +++ b/akka-docs/intro/getting-started-first-java.rst @@ -30,12 +30,12 @@ Tutorial source code If you want don't want to type in the code and/or set up a Maven project then you can check out the full tutorial from the Akka GitHub repository. It is in the ``akka-tutorials/akka-tutorial-first`` module. You can also browse it online `here`__, with the actual source code `here`__. -__ https://github.com/jboner/akka/tree/master/akka-tutorials/akka-tutorial-first -__ https://github.com/jboner/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/first/java/Pi.java +__ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first +__ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/first/java/Pi.java To check out the code using Git invoke the following:: - $ git clone git://github.com/jboner/akka.git + $ git clone git://github.com/akka/akka.git Then you can navigate down to the tutorial:: diff --git a/akka-docs/intro/getting-started-first-scala-eclipse.rst b/akka-docs/intro/getting-started-first-scala-eclipse.rst index 8cb0e531ae..635a3710fd 100644 --- a/akka-docs/intro/getting-started-first-scala-eclipse.rst +++ b/akka-docs/intro/getting-started-first-scala-eclipse.rst @@ -46,12 +46,12 @@ check out the full tutorial from the Akka GitHub repository. It is in the ``akka-tutorials/akka-tutorial-first`` module. You can also browse it online `here`__, with the actual source code `here`__. -__ https://github.com/jboner/akka/tree/master/akka-tutorials/akka-tutorial-first -__ https://github.com/jboner/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala +__ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first +__ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala To check out the code using Git invoke the following:: - $ git clone git://github.com/jboner/akka.git + $ git clone git://github.com/akka/akka.git Then you can navigate down to the tutorial:: diff --git a/akka-docs/intro/getting-started-first-scala.rst b/akka-docs/intro/getting-started-first-scala.rst index 702c996291..85dd29cbc9 100644 --- a/akka-docs/intro/getting-started-first-scala.rst +++ b/akka-docs/intro/getting-started-first-scala.rst @@ -48,12 +48,12 @@ check out the full tutorial from the Akka GitHub repository. It is in the ``akka-tutorials/akka-tutorial-first`` module. You can also browse it online `here`__, with the actual source code `here`__. -__ https://github.com/jboner/akka/tree/master/akka-tutorials/akka-tutorial-first -__ https://github.com/jboner/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala +__ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first +__ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala To check out the code using Git invoke the following:: - $ git clone git://github.com/jboner/akka.git + $ git clone git://github.com/akka/akka.git Then you can navigate down to the tutorial:: diff --git a/akka-docs/intro/getting-started.rst b/akka-docs/intro/getting-started.rst index 75f62a39d9..748ebbc6b0 100644 --- a/akka-docs/intro/getting-started.rst +++ b/akka-docs/intro/getting-started.rst @@ -159,7 +159,7 @@ Build from sources Akka uses Git and is hosted at `Github `_. -* Akka: clone the Akka repository from ``_ +* Akka: clone the Akka repository from ``_ Continue reading the page on :ref:`building-akka` diff --git a/akka-docs/java/event-bus.rst b/akka-docs/java/event-bus.rst index f97156e9e3..cb5bd5644b 100644 --- a/akka-docs/java/event-bus.rst +++ b/akka-docs/java/event-bus.rst @@ -48,7 +48,7 @@ The classifiers presented here are part of the Akka distribution, but rolling your own in case you do not find a perfect match is not difficult, check the implementation of the existing ones on `github`_. -.. _github: https://github.com/jboner/akka/blob/master/akka-actor/src/main/scala/akka/event/EventBus.scala +.. _github: https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/event/EventBus.scala Lookup Classification --------------------- diff --git a/akka-docs/java/remoting.rst b/akka-docs/java/remoting.rst index 427e81c58c..376eab2584 100644 --- a/akka-docs/java/remoting.rst +++ b/akka-docs/java/remoting.rst @@ -149,7 +149,7 @@ Description of the Remoting Sample There is a more extensive remote example that comes with the Akka distribution. Please have a look here for more information: `Remote Sample -`_ +`_ This sample demonstrates both, remote deployment and look-up of remote actors. First, let us have a look at the common setup for both scenarios (this is ``common.conf``): diff --git a/akka-docs/java/routing.rst b/akka-docs/java/routing.rst index aeb89c2506..9c61779063 100644 --- a/akka-docs/java/routing.rst +++ b/akka-docs/java/routing.rst @@ -327,7 +327,7 @@ from incoming sender/message to a ``List`` of ``Destination(sender, routee)``. The sender is what "parent" the routee should see - changing this could be useful if you for example want another actor than the original sender to intermediate the result of the routee (if there is a result). For more information about how to alter the original sender we refer to the source code of -`ScatterGatherFirstCompletedRouter `_ +`ScatterGatherFirstCompletedRouter `_ All in all the custom router looks like this: diff --git a/akka-docs/project/licenses.rst b/akka-docs/project/licenses.rst index 0d7417e44e..d7d9865b31 100644 --- a/akka-docs/project/licenses.rst +++ b/akka-docs/project/licenses.rst @@ -196,4 +196,4 @@ Licenses for Dependency Libraries --------------------------------- Each dependency and its license can be seen in the project build file (the comment on the side of each dependency): -``_ +``_ diff --git a/akka-docs/project/links.rst b/akka-docs/project/links.rst index 8b387eceb5..f9ea25bac7 100644 --- a/akka-docs/project/links.rst +++ b/akka-docs/project/links.rst @@ -20,12 +20,12 @@ Akka is now part of the `Typesafe Stack `_. ``_ -`Source Code `_ +`Source Code `_ ============================================== Akka uses Git and is hosted at `Github `_. -* Akka: clone the Akka repository from ``_ +* Akka: clone the Akka repository from ``_ `Releases Repository `_ diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index eb8bab25ed..7c0553fea7 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -567,7 +567,7 @@ The ``become`` method is useful for many different things, but a particular nice example of it is in example where it is used to implement a Finite State Machine (FSM): `Dining Hakkers`_. -.. _Dining Hakkers: http://github.com/jboner/akka/blob/master/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnBecome.scala +.. _Dining Hakkers: http://github.com/akka/akka/blob/master/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnBecome.scala Here is another little cute example of ``become`` and ``unbecome`` in action: @@ -576,7 +576,7 @@ Here is another little cute example of ``become`` and ``unbecome`` in action: Encoding Scala Actors nested receives without accidentally leaking memory ------------------------------------------------------------------------- -See this `Unnested receive example `_. +See this `Unnested receive example `_. Downgrade diff --git a/akka-docs/scala/event-bus.rst b/akka-docs/scala/event-bus.rst index 633bd0ca64..65e476fb9a 100644 --- a/akka-docs/scala/event-bus.rst +++ b/akka-docs/scala/event-bus.rst @@ -49,7 +49,7 @@ The classifiers presented here are part of the Akka distribution, but rolling your own in case you do not find a perfect match is not difficult, check the implementation of the existing ones on `github`_. -.. _github: https://github.com/jboner/akka/blob/master/akka-actor/src/main/scala/akka/event/EventBus.scala +.. _github: https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/event/EventBus.scala Lookup Classification --------------------- diff --git a/akka-docs/scala/fsm.rst b/akka-docs/scala/fsm.rst index f0f2758e89..f9e95105ce 100644 --- a/akka-docs/scala/fsm.rst +++ b/akka-docs/scala/fsm.rst @@ -493,5 +493,5 @@ Examples A bigger FSM example contrasted with Actor's :meth:`become`/:meth:`unbecome` can be found in the sources: - * `Dining Hakkers using FSM `_ - * `Dining Hakkers using become `_ + * `Dining Hakkers using FSM `_ + * `Dining Hakkers using become `_ diff --git a/akka-docs/scala/remoting.rst b/akka-docs/scala/remoting.rst index 9ccd41366a..6beda42871 100644 --- a/akka-docs/scala/remoting.rst +++ b/akka-docs/scala/remoting.rst @@ -166,7 +166,7 @@ Description of the Remoting Sample There is a more extensive remote example that comes with the Akka distribution. Please have a look here for more information: `Remote Sample -`_ +`_ This sample demonstrates both, remote deployment and look-up of remote actors. First, let us have a look at the common setup for both scenarios (this is ``common.conf``): diff --git a/akka-docs/scala/routing.rst b/akka-docs/scala/routing.rst index 92776fa73f..541ed5c525 100644 --- a/akka-docs/scala/routing.rst +++ b/akka-docs/scala/routing.rst @@ -328,14 +328,14 @@ As you can see above what's returned in the partial function is a ``List`` of `` The sender is what "parent" the routee should see - changing this could be useful if you for example want another actor than the original sender to intermediate the result of the routee (if there is a result). For more information about how to alter the original sender we refer to the source code of -`ScatterGatherFirstCompletedRouter `_ +`ScatterGatherFirstCompletedRouter `_ All in all the custom router looks like this: .. includecode:: ../../akka-actor-tests/src/test/scala/akka/routing/RoutingSpec.scala#CustomRouter If you are interested in how to use the VoteCountRouter you can have a look at the test class -`RoutingSpec `_ +`RoutingSpec `_ Configured Custom Router ************************ From b7947ca77281df6c30b90650191b2d8e85249bf2 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 5 Mar 2012 11:30:21 +0100 Subject: [PATCH 26/46] #1885 - Adding section on serializing ActorRefs --- .../SerializationDocTestBase.java | 39 +++++++++++++++---- akka-docs/java/serialization.rst | 9 +++++ .../serialization/SerializationDocSpec.scala | 29 +++++++++++++- akka-docs/scala/serialization.rst | 9 +++++ 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/akka-docs/java/code/akka/docs/serialization/SerializationDocTestBase.java b/akka-docs/java/code/akka/docs/serialization/SerializationDocTestBase.java index fa0f5fcce3..aa24c92249 100644 --- a/akka-docs/java/code/akka/docs/serialization/SerializationDocTestBase.java +++ b/akka-docs/java/code/akka/docs/serialization/SerializationDocTestBase.java @@ -3,17 +3,11 @@ */ package akka.docs.serialization; -import akka.japi.Option; -import akka.serialization.JSerializer; -import akka.serialization.Serialization; -import akka.serialization.SerializationExtension; -import akka.serialization.Serializer; import org.junit.Test; import static org.junit.Assert.*; //#imports - +import akka.actor.*; import akka.serialization.*; -import akka.actor.ActorSystem; import com.typesafe.config.*; //#imports @@ -54,6 +48,37 @@ public class SerializationDocTestBase { } //#my-own-serializer + @Test public void serializeActorRefs() { + final ActorSystem theActorSystem = + ActorSystem.create("whatever"); + final ActorRef theActorRef = + theActorSystem.deadLetters(); // Of course this should be you + + //#actorref-serializer + // Serialize + // (beneath toBinary) + final Address transportAddress = + Serialization.currentTransportAddress().value(); + String identifier; + + // If there is no transportAddress, + // it means that either this Serializer isn't called + // within a piece of code that sets it, + // so either you need to supply your own, + // or simply use the local path. + if (transportAddress == null) identifier = theActorRef.path().toString(); + else identifier = theActorRef.path().toStringWithAddress(transportAddress); + // Then just serialize the identifier however you like + + + // Deserialize + // (beneath fromBinary) + final ActorRef deserializedActorRef = theActorSystem.actorFor(identifier); + // Then just use the ActorRef + //#actorref-serializer + theActorSystem.shutdown(); + } + @Test public void demonstrateTheProgrammaticAPI() { //#programmatic diff --git a/akka-docs/java/serialization.rst b/akka-docs/java/serialization.rst index e4815d0ea2..3f523463e9 100644 --- a/akka-docs/java/serialization.rst +++ b/akka-docs/java/serialization.rst @@ -104,6 +104,15 @@ which is done by extending ``akka.serialization.JSerializer``, like this: Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then list which classes that should be serialized using it. +Serializing ActorRefs +--------------------- + +All ActorRefs are serializable using JavaSerializer, but in case you are writing your own serializer, +you might want to know how to serialize and deserialize them properly, here's the magic incantation: + +.. includecode:: code/akka/docs/serialization/SerializationDocTestBase.java + :include: imports,actorref-serializer + A Word About Java Serialization =============================== diff --git a/akka-docs/scala/code/akka/docs/serialization/SerializationDocSpec.scala b/akka-docs/scala/code/akka/docs/serialization/SerializationDocSpec.scala index 38054594cd..e614cc9903 100644 --- a/akka-docs/scala/code/akka/docs/serialization/SerializationDocSpec.scala +++ b/akka-docs/scala/code/akka/docs/serialization/SerializationDocSpec.scala @@ -5,8 +5,9 @@ package akka.docs.serialization import org.scalatest.matchers.MustMatchers import akka.testkit._ +import akka.actor.{ ActorRef, ActorSystem } + //#imports -import akka.actor.ActorSystem import akka.serialization._ import com.typesafe.config.ConfigFactory @@ -150,4 +151,30 @@ class SerializationDocSpec extends AkkaSpec { //#programmatic system.shutdown() } + + "demonstrate serialization of ActorRefs" in { + val theActorRef: ActorRef = system.deadLetters + val theActorSystem: ActorSystem = system + + //#actorref-serializer + // Serialize + // (beneath toBinary) + + // If there is no transportAddress, + // it means that either this Serializer isn't called + // within a piece of code that sets it, + // so either you need to supply your own, + // or simply use the local path. + val identifier: String = Serialization.currentTransportAddress.value match { + case null ⇒ theActorRef.path.toString + case address ⇒ theActorRef.path.toStringWithAddress(address) + } + // Then just serialize the identifier however you like + + // Deserialize + // (beneath fromBinary) + val deserializedActorRef = theActorSystem actorFor identifier + // Then just use the ActorRef + //#actorref-serializer + } } diff --git a/akka-docs/scala/serialization.rst b/akka-docs/scala/serialization.rst index 9bdfa2d2c8..594cc2a1cd 100644 --- a/akka-docs/scala/serialization.rst +++ b/akka-docs/scala/serialization.rst @@ -102,6 +102,15 @@ First you need to create a class definition of your ``Serializer`` like so: Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then list which classes that should be serialized using it. +Serializing ActorRefs +--------------------- + +All ActorRefs are serializable using JavaSerializer, but in case you are writing your own serializer, +you might want to know how to serialize and deserialize them properly, here's the magic incantation: + +.. includecode:: code/akka/docs/serialization/SerializationDocSpec.scala + :include: imports,actorref-serializer + A Word About Java Serialization =============================== From e555d2a0734c4d02d002be4e0428347ea07332f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bone=CC=81r?= Date: Mon, 5 Mar 2012 15:01:40 +0100 Subject: [PATCH 27/46] Added docs about Push/Pull and Rep/Req ZeroMQ support. Added Windows versions for all command line samples in the Getting Started Guides. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Bonér --- .../intro/getting-started-first-java.rst | 118 +++++++++++++++--- .../getting-started-first-scala-eclipse.rst | 92 +++++++++++--- .../intro/getting-started-first-scala.rst | 102 +++++++++++++-- akka-docs/java/zeromq.rst | 35 +++++- akka-docs/scala/zeromq.rst | 35 +++++- 5 files changed, 337 insertions(+), 45 deletions(-) diff --git a/akka-docs/intro/getting-started-first-java.rst b/akka-docs/intro/getting-started-first-java.rst index 0a090d02bd..300b381b72 100644 --- a/akka-docs/intro/getting-started-first-java.rst +++ b/akka-docs/intro/getting-started-first-java.rst @@ -33,22 +33,30 @@ If you want don't want to type in the code and/or set up a Maven project then yo __ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first __ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/first/java/Pi.java -To check out the code using Git invoke the following:: +To check out the code using Git invoke the following command and you can then you can navigate down to the tutorial. + +On Linux/Unix/Mac systems:: $ git clone git://github.com/akka/akka.git - -Then you can navigate down to the tutorial:: - $ cd akka/akka-tutorials/akka-tutorial-first +On Windows systems:: + + C:\Users\jboner\src> git clone git://github.com/akka/akka.git + C:\Users\jboner\src> cd akka\akka-tutorials\akka-tutorial-first + Prerequisites ------------- This tutorial assumes that you have Java 1.6 or later installed on you machine and ``java`` on your ``PATH``. You also need to know how to run commands in a shell (ZSH, Bash, DOS etc.) and a decent text editor or IDE to type in the Java code. -You need to make sure that ``$JAVA_HOME`` environment variable is set to the root of the Java distribution. You also need to make sure that the ``$JAVA_HOME/bin`` is on your ``PATH``:: +You need to make sure that ``$JAVA_HOME`` environment variable is set to the +root of the Java distribution. You also need to make sure that the +``$JAVA_HOME/bin`` is on your ``PATH``. - $ export JAVA_HOME=..root of java distribution.. +On Linux/Unix/Mac systems:: + + $ export JAVA_HOME=..root of Java distribution.. $ export PATH=$PATH:$JAVA_HOME/bin You can test your installation by invoking ``java``:: @@ -58,6 +66,17 @@ You can test your installation by invoking ``java``:: Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) +On Windows systems:: + + C:\Users\jboner\src\akka> set JAVA_HOME=..root of Java distribution.. + C:\Users\jboner\src\akka> set PATH=%PATH%;%JAVA_HOME%/bin + +You can test your installation by invoking ``java``:: + + C:\Users\jboner\src\akka> java -version + java version "1.6.0_24" + Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) + Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) Downloading and installing Akka ------------------------------- @@ -75,14 +94,25 @@ would like to have Akka installed in. In my case I choose to install it in You need to do one more thing in order to install Akka properly: set the ``AKKA_HOME`` environment variable to the root of the distribution. In my case I'm opening up a shell, navigating down to the distribution, and setting the -``AKKA_HOME`` variable:: +``AKKA_HOME`` variable. + +On Linux/Unix/Mac systems:: $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT $ export AKKA_HOME=`pwd` $ echo $AKKA_HOME /Users/jboner/tools/akka-2.1-SNAPSHOT -The distribution looks like this:: +On Windows systems:: + + C:\Users\jboner\src\akka> cd akka-2.1-SNAPSHOT + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set AKKA_HOME=%cd% + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> echo %AKKA_HOME% + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT + +The distribution looks like this. + +On Linux/Unix/Mac systems:: $ ls -1 bin @@ -92,6 +122,16 @@ The distribution looks like this:: lib src +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> dir + bin + config + deploy + doc + lib + src + - In the ``bin`` directory we have scripts for starting the Akka Microkernel. - In the ``config`` directory we have the Akka conf files. - In the ``deploy`` directory we can place applications to be run with the microkernel. @@ -139,7 +179,9 @@ To install Maven it is easiest to follow the instructions on `http://maven.apach Creating an Akka Maven project ------------------------------ -If you have not already done so, now is the time to create a Maven project for our tutorial. You do that by stepping into the directory you want to create your project in and invoking the ``mvn`` command:: +If you have not already done so, now is the time to create a Maven project for our tutorial. You do that by stepping into the directory you want to create your project in and invoking the ``mvn`` command. + +On Linux/Unix/Mac systems:: $ mvn archetype:generate \ -DgroupId=akka.tutorial.first.java \ @@ -147,10 +189,24 @@ If you have not already done so, now is the time to create a Maven project for o -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> mvn archetype:generate \ + -DgroupId=akka.tutorial.first.java \ + -DartifactId=akka-tutorial-first-java \ + -DarchetypeArtifactId=maven-archetype-quickstart \ + -DinteractiveMode=false + Now we have the basis for our Maven-based Akka project. Let's step into the project directory:: +On Linux/Unix/Mac systems:: + $ cd akka-tutorial-first-java +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> cd akka-tutorial-first-java + Here is the layout that Maven created:: akka-tutorial-first-jboner @@ -362,39 +418,73 @@ time. When that's done open up a shell and step in to the Akka distribution First we need to compile the source file. That is done with Java's compiler ``javac``. Our application depends on the ``akka-actor-2.1-SNAPSHOT.jar`` and the ``scala-library.jar`` JAR files, so let's add them to the compiler classpath -when we compile the source:: +when we compile the source. + +On Linux/Unix/Mac systems:: $ javac -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar tutorial/akka/tutorial/first/java/Pi.java +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> javac -cp \ + lib/scala-library.jar;lib/akka/akka-actor-2.1-SNAPSHOT.jar \ + tutorial/akka/tutorial/first/java/Pi.java + When we have compiled the source file we are ready to run the application. This is done with ``java`` but yet again we need to add the ``akka-actor-2.1-SNAPSHOT.jar`` and the ``scala-library.jar`` JAR files to the classpath as well as the classes -we compiled ourselves:: +we compiled ourselves. + +On Linux/Unix/Mac systems:: $ java \ -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar:. \ - akka.tutorial.java.first.Pi + akka.tutorial.first.scala.Pi + + Pi approximation: 3.1435501812459323 + Calculation time: 359 millis + +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> java \ + -cp lib/scala-library.jar;lib\akka\akka-actor-2.1-SNAPSHOT.jar;. \ + akka.tutorial.first.scala.Pi Pi approximation: 3.1435501812459323 Calculation time: 359 millis Yippee! It is working. - Run it inside Maven ------------------- -If you used Maven, then you can run the application directly inside Maven. First you need to compile the project:: +If you used Maven, then you can run the application directly inside Maven. First you need to compile the project. + +On Linux/Unix/Mac systems:: $ mvn compile +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> mvn compile + When this in done we can run our application directly inside Maven:: +On Linux/Unix/Mac systems:: + $ mvn exec:java -Dexec.mainClass="akka.tutorial.first.java.Pi" ... Pi approximation: 3.1435501812459323 Calculation time: 359 millis +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> mvn exec:java \ + -Dexec.mainClass="akka.tutorial.first.java.Pi" + ... + Pi approximation: 3.1435501812459323 + Calculation time: 359 millis + Yippee! It is working. Overriding Configuration Externally (Optional) diff --git a/akka-docs/intro/getting-started-first-scala-eclipse.rst b/akka-docs/intro/getting-started-first-scala-eclipse.rst index 635a3710fd..ef68ff01ff 100644 --- a/akka-docs/intro/getting-started-first-scala-eclipse.rst +++ b/akka-docs/intro/getting-started-first-scala-eclipse.rst @@ -49,14 +49,17 @@ check out the full tutorial from the Akka GitHub repository. It is in the __ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first __ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala -To check out the code using Git invoke the following:: +To check out the code using Git invoke the following command and you can then you can navigate down to the tutorial. + +On Linux/Unix/Mac systems:: $ git clone git://github.com/akka/akka.git - -Then you can navigate down to the tutorial:: - $ cd akka/akka-tutorials/akka-tutorial-first +On Windows systems:: + + C:\Users\jboner\src> git clone git://github.com/akka/akka.git + C:\Users\jboner\src> cd akka\akka-tutorials\akka-tutorial-first Prerequisites ------------- @@ -68,9 +71,11 @@ code. You need to make sure that ``$JAVA_HOME`` environment variable is set to the root of the Java distribution. You also need to make sure that the -``$JAVA_HOME/bin`` is on your ``PATH``:: +``$JAVA_HOME/bin`` is on your ``PATH``. - $ export JAVA_HOME=..root of java distribution.. +On Linux/Unix/Mac systems:: + + $ export JAVA_HOME=..root of Java distribution.. $ export PATH=$PATH:$JAVA_HOME/bin You can test your installation by invoking ``java``:: @@ -80,6 +85,17 @@ You can test your installation by invoking ``java``:: Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) +On Windows systems:: + + C:\Users\jboner\src\akka> set JAVA_HOME=..root of Java distribution.. + C:\Users\jboner\src\akka> set PATH=%PATH%;%JAVA_HOME%/bin + +You can test your installation by invoking ``java``:: + + C:\Users\jboner\src\akka> java -version + java version "1.6.0_24" + Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) + Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) Downloading and installing Akka ------------------------------- @@ -97,14 +113,26 @@ would like to have Akka installed in. In my case I choose to install it in You need to do one more thing in order to install Akka properly: set the ``AKKA_HOME`` environment variable to the root of the distribution. In my case I'm opening up a shell, navigating down to the distribution, and setting the -``AKKA_HOME`` variable:: +``AKKA_HOME`` variable. + + +On Linux/Unix/Mac systems:: $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT $ export AKKA_HOME=`pwd` $ echo $AKKA_HOME /Users/jboner/tools/akka-2.1-SNAPSHOT -The distribution looks like this:: +On Windows systems:: + + C:\Users\jboner\src\akka> cd akka-2.1-SNAPSHOT + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set AKKA_HOME=%cd% + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> echo %AKKA_HOME% + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT + +The distribution looks like this. + +On Linux/Unix/Mac systems:: $ ls -1 bin @@ -114,6 +142,16 @@ The distribution looks like this:: lib src +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> dir + bin + config + deploy + doc + lib + src + - In the ``bin`` directory we have scripts for starting the Akka Microkernel. - In the ``config`` directory we have the Akka conf files. - In the ``deploy`` directory we can place applications to be run with the microkernel. @@ -156,7 +194,7 @@ This plugin comes with its own version of Scala, so if you don't plan to run the you don't need to download the Scala distribution (and you can skip the next section). You can install this plugin using the regular update mechanism. First choose a version of the IDE from -`http://download.scala-ide.org `_. We recommend you choose 2.0.x, which +`http://download.scala-ide.org `_. We recommend you choose 2.1.x, which comes with Scala 2.9. Copy the corresponding URL and then choose ``Help/Install New Software`` and paste the URL you just copied. You should see something similar to the following image. @@ -191,15 +229,27 @@ distribution then just unzip it where you want it installed. If you pick the IzPack Installer then double click on it and follow the instructions. You also need to make sure that the ``scala-2.9.1/bin`` (if that is the -directory where you installed Scala) is on your ``PATH``:: +directory where you installed Scala) is on your ``PATH``. +On Linux/Unix/Mac systems:: $ export PATH=$PATH:scala-2.9.1/bin -You can test your installation by invoking scala:: +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set PATH=%PATH%;scala-2.9.1\bin + +You can test your installation by invoking scala. + +On Linux/Unix/Mac systems:: $ scala -version Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> scala -version + Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL + Looks like we are all good. Finally let's create a source file ``Pi.scala`` for the tutorial and put it in the root of the Akka distribution in the ``tutorial`` directory (you have to create it first). @@ -228,16 +278,30 @@ instruction and additionally install the ``sbteclipse`` plugin. This adds suppor from your SBT project. You need to install the plugin as described in the `README of sbteclipse `_ -Then run the ``eclipse`` target to generate the Eclipse project:: +Then run the ``eclipse`` target to generate the Eclipse project. + +On Linux/Unix/Mac systems:: $ sbt > eclipse -The options `create-src` and `with-sources` are useful:: +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> sbt + > eclipse + +The options `create-src` and `with-sources` are useful: + +On Linux/Unix/Mac systems:: $ sbt > eclipse create-src with-sources +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> sbt + > eclipse create-src with-sources + * create-src to create the common source directories, e.g. src/main/scala, src/main/test * with-sources to create source attachments for the library dependencies @@ -410,7 +474,7 @@ If everything works fine, you should see:: Calculation time: 359 millis You can also define a new Run configuration, by going to ``Run/Run Configurations``. Create a new ``Scala application`` -and choose the tutorial project and the main class to be ``akkatutorial.Pi``. You can pass additional command line +and choose the tutorial project and the main class to be ``akka/tutorial.Pi``. You can pass additional command line arguments to the JVM on the ``Arguments`` page, for instance to define where :ref:`configuration` is: .. image:: ../images/run-config.png diff --git a/akka-docs/intro/getting-started-first-scala.rst b/akka-docs/intro/getting-started-first-scala.rst index 85dd29cbc9..3721af57ff 100644 --- a/akka-docs/intro/getting-started-first-scala.rst +++ b/akka-docs/intro/getting-started-first-scala.rst @@ -51,14 +51,18 @@ check out the full tutorial from the Akka GitHub repository. It is in the __ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first __ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala -To check out the code using Git invoke the following:: +To check out the code using Git invoke the following command and you can then you can navigate down to the tutorial. + +On Linux/Unix/Mac systems:: $ git clone git://github.com/akka/akka.git - -Then you can navigate down to the tutorial:: - $ cd akka/akka-tutorials/akka-tutorial-first +On Windows systems:: + + C:\Users\jboner\src> git clone git://github.com/akka/akka.git + C:\Users\jboner\src> cd akka\akka-tutorials\akka-tutorial-first + Prerequisites ============= @@ -69,9 +73,11 @@ code. You need to make sure that ``$JAVA_HOME`` environment variable is set to the root of the Java distribution. You also need to make sure that the -``$JAVA_HOME/bin`` is on your ``PATH``:: +``$JAVA_HOME/bin`` is on your ``PATH``. - $ export JAVA_HOME=..root of java distribution.. +On Linux/Unix/Mac systems:: + + $ export JAVA_HOME=..root of Java distribution.. $ export PATH=$PATH:$JAVA_HOME/bin You can test your installation by invoking ``java``:: @@ -81,6 +87,17 @@ You can test your installation by invoking ``java``:: Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) +On Windows systems:: + + C:\Users\jboner\src\akka> set JAVA_HOME=..root of Java distribution.. + C:\Users\jboner\src\akka> set PATH=%PATH%;%JAVA_HOME%/bin + +You can test your installation by invoking ``java``:: + + C:\Users\jboner\src\akka> java -version + java version "1.6.0_24" + Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) + Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) Downloading and installing Akka =============================== @@ -98,14 +115,25 @@ would like to have Akka installed in. In my case I choose to install it in You need to do one more thing in order to install Akka properly: set the ``AKKA_HOME`` environment variable to the root of the distribution. In my case I'm opening up a shell, navigating down to the distribution, and setting the -``AKKA_HOME`` variable:: +``AKKA_HOME`` variable. + +On Linux/Unix/Mac systems:: $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT $ export AKKA_HOME=`pwd` $ echo $AKKA_HOME /Users/jboner/tools/akka-2.1-SNAPSHOT -The distribution looks like this:: +On Windows systems:: + + C:\Users\jboner\src\akka> cd akka-2.1-SNAPSHOT + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set AKKA_HOME=%cd% + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> echo %AKKA_HOME% + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT + +The distribution looks like this. + +On Linux/Unix/Mac systems:: $ ls -1 bin @@ -115,6 +143,16 @@ The distribution looks like this:: lib src +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> dir + bin + config + deploy + doc + lib + src + - In the ``bin`` directory we have scripts for starting the Akka Microkernel. - In the ``config`` directory we have the Akka conf files. - In the ``deploy`` directory we can place applications to be run with the microkernel. @@ -163,15 +201,28 @@ distribution then just unzip it where you want it installed. If you pick the IzPack Installer then double click on it and follow the instructions. You also need to make sure that the ``scala-2.9.1/bin`` (if that is the -directory where you installed Scala) is on your ``PATH``:: +directory where you installed Scala) is on your ``PATH``. + +On Linux/Unix/Mac systems:: $ export PATH=$PATH:scala-2.9.1/bin -You can test your installation by invoking scala:: +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set PATH=%PATH%;scala-2.9.1\bin + +You can test your installation by invoking scala. + +On Linux/Unix/Mac systems:: $ scala -version Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> scala -version + Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL + Looks like we are all good. Finally let's create a source file ``Pi.scala`` for the tutorial and put it in the root of the Akka distribution in the ``tutorial`` directory (you have to create it first). @@ -404,15 +455,23 @@ When that's done open up a shell and step in to the Akka distribution (``cd $AKK First we need to compile the source file. That is done with Scala's compiler ``scalac``. Our application depends on the ``akka-actor-2.1-SNAPSHOT.jar`` JAR -file, so let's add that to the compiler classpath when we compile the source:: +file, so let's add that to the compiler classpath when we compile the source. + +On Linux/Unix/Mac systems:: $ scalac -cp lib/akka/akka-actor-2.1-SNAPSHOT.jar Pi.scala +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> scalac -cp lib\akka\akka-actor-2.1-SNAPSHOT.jar Pi.scala + When we have compiled the source file we are ready to run the application. This is done with ``java`` but yet again we need to add the ``akka-actor-2.1-SNAPSHOT.jar`` JAR file to the classpath, and this time we also need to add the Scala runtime library ``scala-library.jar`` and the classes we -compiled ourselves:: +compiled ourselves. + +On Linux/Unix/Mac systems:: $ java \ -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar:. \ @@ -421,18 +480,35 @@ compiled ourselves:: Pi approximation: 3.1435501812459323 Calculation time: 359 millis +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> java \ + -cp lib/scala-library.jar;lib\akka\akka-actor-2.1-SNAPSHOT.jar;. \ + akka.tutorial.first.scala.Pi + + Pi approximation: 3.1435501812459323 + Calculation time: 359 millis + Yippee! It is working. Run it inside SBT ================= If you used SBT, then you can run the application directly inside SBT. First you -need to compile the project:: +need to compile the project. + +On Linux/Unix/Mac systems:: $ sbt > compile ... +On Windows systems:: + + C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> sbt + > compile + ... + When this in done we can run our application directly inside SBT:: > run diff --git a/akka-docs/java/zeromq.rst b/akka-docs/java/zeromq.rst index e24dd28796..2d136d77b5 100644 --- a/akka-docs/java/zeromq.rst +++ b/akka-docs/java/zeromq.rst @@ -34,7 +34,7 @@ Similarly you can create a subscription socket, with a listener, that subscribes The following sub-sections describe the supported connection patterns and how they can be used in an Akka environment. However, for a comprehensive discussion of connection patterns, please refer to `ZeroMQ -- The Guide `_. -Publisher-subscriber connection +Publisher-Subscriber Connection ------------------------------- In a publisher-subscriber (pub-sub) connection, the publisher accepts one or more subscribers. Each subscriber shall @@ -84,7 +84,7 @@ Another subscriber keep track of used heap and warns if too much heap is used. I .. includecode:: code/akka/docs/zeromq/ZeromqDocTestBase.java#alerter2 -Router-Dealer connection +Router-Dealer Connection ------------------------ While Pub/Sub is nice the real advantage of zeromq is that it is a "lego-box" for reliable messaging. And because there are so many integrations the multi-language support is fantastic. @@ -96,3 +96,34 @@ To create a Router socket that has a high watermark configured, you would do: .. includecode:: code/akka/docs/zeromq/ZeromqDocTestBase.java#high-watermark The akka-zeromq module accepts most if not all the available configuration options for a zeromq socket. + +Push-Pull Connection +-------------------- + +Akka ZeroMQ module supports ``Push-Pull`` connections. + +You can create a ``Push`` connection through the:: + + ActorRef newPushSocket(SocketOption[] socketParameters); + +You can create a ``Pull`` connection through the:: + + ActorRef newPullSocket(SocketOption[] socketParameters); + +More documentation and examples will follow soon. + +Rep-Req Connection +------------------ + +Akka ZeroMQ module supports ``Rep-Req`` connections. + +You can create a ``Rep`` connection through the:: + + ActorRef newRepSocket(SocketOption[] socketParameters); + +You can create a ``Req`` connection through the:: + + ActorRef newReqSocket(SocketOption[] socketParameters); + +More documentation and examples will follow soon. + diff --git a/akka-docs/scala/zeromq.rst b/akka-docs/scala/zeromq.rst index fa1160ee6d..13f563d18d 100644 --- a/akka-docs/scala/zeromq.rst +++ b/akka-docs/scala/zeromq.rst @@ -38,7 +38,7 @@ Similarly you can create a subscription socket, with a listener, that subscribes The following sub-sections describe the supported connection patterns and how they can be used in an Akka environment. However, for a comprehensive discussion of connection patterns, please refer to `ZeroMQ -- The Guide `_. -Publisher-subscriber connection +Publisher-Subscriber Connection ------------------------------- In a publisher-subscriber (pub-sub) connection, the publisher accepts one or more subscribers. Each subscriber shall @@ -82,7 +82,7 @@ Another subscriber keep track of used heap and warns if too much heap is used. I .. includecode:: code/akka/docs/zeromq/ZeromqDocSpec.scala#alerter -Router-Dealer connection +Router-Dealer Connection ------------------------ While Pub/Sub is nice the real advantage of zeromq is that it is a "lego-box" for reliable messaging. And because there are so many integrations the multi-language support is fantastic. @@ -94,3 +94,34 @@ To create a Router socket that has a high watermark configured, you would do: .. includecode:: code/akka/docs/zeromq/ZeromqDocSpec.scala#high-watermark The akka-zeromq module accepts most if not all the available configuration options for a zeromq socket. + +Push-Pull Connection +-------------------- + +Akka ZeroMQ module supports ``Push-Pull`` connections. + +You can create a ``Push`` connection through the:: + + def newPushSocket(socketParameters: Array[SocketOption]): ActorRef + +You can create a ``Pull`` connection through the:: + + def newPullSocket(socketParameters: Array[SocketOption]): ActorRef + +More documentation and examples will follow soon. + +Rep-Req Connection +------------------ + +Akka ZeroMQ module supports ``Rep-Req`` connections. + +You can create a ``Rep`` connection through the:: + + def newReqSocket(socketParameters: Array[SocketOption]): ActorRef + +You can create a ``Req`` connection through the:: + + def newRepSocket(socketParameters: Array[SocketOption]): ActorRef + +More documentation and examples will follow soon. + From 56ce7a0ecd9107bdaef7be31ef18663f6829494f Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 5 Mar 2012 15:39:46 +0100 Subject: [PATCH 28/46] rewrite configuration.rst, see #1823 and #1838 --- akka-docs/general/configuration.rst | 131 +++++++++++++++++++--------- 1 file changed, 91 insertions(+), 40 deletions(-) diff --git a/akka-docs/general/configuration.rst b/akka-docs/general/configuration.rst index 649a6abc04..0353f60173 100644 --- a/akka-docs/general/configuration.rst +++ b/akka-docs/general/configuration.rst @@ -8,41 +8,101 @@ Configuration .. contents:: :local: -Specifying the configuration file ---------------------------------- +Akka uses the `Typesafe Config Library +`_, which might also be a good choice +for the configuration of your own application or library built with or without +Akka. This library is implemented in Java with no external dependencies; you +should have a look at its documentation (in particular about `ConfigFactory +`_), +which is only summarized in the following. -If you don't specify a configuration file then Akka uses default values, corresponding to the reference -configuration files that you see below. You can specify your own configuration file to override any -property in the reference config. You only have to define the properties that differ from the default -configuration. +Where configuration is read from +-------------------------------- -By default the ``ConfigFactory.load`` method is used, which will load all ``application.conf`` (and -``application.json`` and ``application.properties``) from the root of the classpath, if they exists. -It uses ``ConfigFactory.defaultOverrides``, i.e. system properties, before falling back to -application and reference configuration. - -Note that *all* ``application.{conf,json,properties}`` classpath resources, from all directories and -jar files, are loaded and merged. Therefore it is a good practice to define separate sub-trees in the -configuration for each actor system, and grab the specific configuration when instantiating the ActorSystem. - -:: - - myapp1 { - akka.loglevel = WARNING - } - myapp2 { - akka.loglevel = ERROR - } +All configuration for Akka is held within instances of :class:`ActorSystem`, or +put differently, as viewed from the outside, :class:`ActorSystem` is the only +consumer of configuration information. While constructing an actor system, you +can either pass in a :class:`Config` object or not, where the second case is +equivalent to passing ``ConfigFactory.load()`` (with the right class loader). +This means roughly that the default is to parse all ``application.conf``, +``application.json`` and ``application.properties`` found at the root of the +class path—please refer to the aforementioned documentation for details. The +actor system then merges in all ``reference.conf`` resources found at the root +of the class path to form the fallback configuration, i.e. it internally uses .. code-block:: scala - val app1 = ActorSystem("MyApp1", ConfigFactory.load.getConfig("myapp1")) - val app2 = ActorSystem("MyApp2", ConfigFactory.load.getConfig("myapp2")) + appConfig.withFallback(ConfigFactory.defaultReference(classLoader)) + +The philosophy is that code never contains default values, but instead relies +upon their presence in the ``reference.conf`` supplied with the library in +question. -If the system properties ``config.resource``, ``config.file``, or ``config.url`` are set, then the -classpath resource, file, or URL specified in those properties will be used rather than the default -``application.{conf,json,properties}`` classpath resources. Note that classpath resource names start -with ``/``. ``-Dconfig.resource=/dev.conf`` will load the ``dev.conf`` from the root of the classpath. +Highest precedence is given to overrides given as system properties, see `the +HOCON specification +`_ (near the +bottom). Also noteworthy is that the application configuration—which defaults +to ``application``—may be overridden using the ``config.resource`` property +(there are more, please refer to the `Config docs +`_). + +.. note:: + + If you are writing an Akka application, keep you configuration in + ``application.conf`` at the root of the class path. If you are writing an + Akka-based library, keep its configuration in ``reference.conf`` at the root + of the JAR file. + +How to structure your configuration +----------------------------------- + +Given that ``ConfigFactory.load()`` merges all resources with matching name +from the whole class path, it is easiest to utilize that functionality and +differenciate actor systems within the hierarchy of the configuration:: + + myapp1 { + akka.loglevel = WARNING + my.own.setting = 43 + } + myapp2 { + akka.loglevel = ERROR + app2.setting = "appname" + } + my.own.setting = 42 + my.other.setting = "hello" + +.. code-block:: scala + + val config = ConfigFactory.load() + val app1 = ActorSystem("MyApp1", config.getConfig("myapp1").withFallback(config)) + val app2 = ActorSystem("MyApp2", config.getConfig("myapp2").withOnlyPath("akka").withFallback(config)) + +These two samples demonstrate different variations of the “lift-a-subtree” +trick: in the first case, the configuration accessible from within the actor +system is this + +.. code-block:: ruby + + akka.loglevel = WARNING + my.own.setting = 43 + my.other.setting = "hello" + // plus myapp1 and myapp2 subtrees + +while in the second one, only the “akka” subtree is lifted, with the following +result:: + + akka.loglevel = ERROR + my.own.setting = 42 + my.other.setting = "hello" + // plus myapp1 and myapp2 subtrees + +.. note:: + + The configuration library is really powerful, explaining all features exceeds + the scope affordable here. In particular not covered are how to include other + configuration files within other files (see a small example at `Including + files`_) and copying parts of the configuration tree by way of path + substitutions. You may also specify and parse the configuration programmatically in other ways when instantiating the ``ActorSystem``. @@ -50,10 +110,8 @@ the ``ActorSystem``. .. includecode:: code/akka/docs/config/ConfigDocSpec.scala :include: imports,custom-config -The ``ConfigFactory`` provides several methods to parse the configuration from various sources. - -Defining the configuration file -------------------------------- +Listing of the Reference Configuration +-------------------------------------- Each Akka module has a reference configuration file with the default values. @@ -161,13 +219,6 @@ A custom ``application.conf`` might look like this:: } -Config file format ------------------- - -The configuration file syntax is described in the `HOCON `_ -specification. Note that it supports three formats; conf, json, and properties. - - Including files --------------- From 3699c6856eea13240c058c469b58fcaeca688ff7 Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 5 Mar 2012 17:48:38 +0100 Subject: [PATCH 29/46] add docs for durMbx settings, see #1863 --- .../src/main/resources/reference.conf | 16 +++++++++++- .../actor/mailbox/BeanstalkBasedMailbox.scala | 2 +- .../BeanstalkBasedMailboxSettings.scala | 1 - .../src/main/resources/reference.conf | 26 ++++++++++++++++++- .../src/main/resources/reference.conf | 5 ++++ .../src/main/resources/reference.conf | 8 +++++- .../actor/mailbox/ZooKeeperBasedMailbox.scala | 2 +- .../ZooKeeperBasedMailboxSettings.scala | 1 - 8 files changed, 54 insertions(+), 7 deletions(-) diff --git a/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/resources/reference.conf b/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/resources/reference.conf index 6ec98a2114..d9a45dd548 100644 --- a/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/resources/reference.conf +++ b/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/resources/reference.conf @@ -4,16 +4,30 @@ # This is the reference config file that contains all the default settings. # Make your edits/overrides in your application.conf. +# +# for more information see akka { actor { mailbox { beanstalk { + # hostname to connect to hostname = "127.0.0.1" + + # port to connect to port = 11300 + + # wait period in case of a connection failure before reconnect reconnect-window = 5s + + # integer number of seconds to wait before putting the job in + # the ready queue. The job will be in the "delayed" state during this time. message-submit-delay = 0s - message-submit-timeout = 5s + + # time to run -- is an integer number of seconds to allow a worker + # to run this job. This time is counted from the moment a worker reserves + # this job. If the worker does not delete, release, or bury the job within + # seconds, the job will time out and the server will release the job. message-time-to-live = 120s } } diff --git a/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailbox.scala b/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailbox.scala index 35a09303fa..45600f1587 100644 --- a/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailbox.scala +++ b/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailbox.scala @@ -41,7 +41,7 @@ class BeanstalkBasedMessageQueue(_owner: ActorContext, val settings: BeanstalkMa // ===== For MessageQueue ===== def enqueue(receiver: ActorRef, envelope: Envelope) { - Some(queue.get.put(65536, messageSubmitDelaySeconds, messageTimeToLiveSeconds, serialize(envelope)).toInt) + queue.get.put(65536, messageSubmitDelaySeconds, messageTimeToLiveSeconds, serialize(envelope)).toInt } def dequeue(): Envelope = try { diff --git a/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailboxSettings.scala b/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailboxSettings.scala index 0450b2c172..4f0ef3a578 100644 --- a/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailboxSettings.scala +++ b/akka-durable-mailboxes/akka-beanstalk-mailbox/src/main/scala/akka/actor/mailbox/BeanstalkBasedMailboxSettings.scala @@ -21,7 +21,6 @@ class BeanstalkMailboxSettings(val systemSettings: ActorSystem.Settings, val use val Port = getInt("port") val ReconnectWindow = Duration(getMilliseconds("reconnect-window"), MILLISECONDS) val MessageSubmitDelay = Duration(getMilliseconds("message-submit-delay"), MILLISECONDS) - val MessageSubmitTimeout = Duration(getMilliseconds("message-submit-timeout"), MILLISECONDS) val MessageTimeToLive = Duration(getMilliseconds("message-time-to-live"), MILLISECONDS) } \ No newline at end of file diff --git a/akka-durable-mailboxes/akka-file-mailbox/src/main/resources/reference.conf b/akka-durable-mailboxes/akka-file-mailbox/src/main/resources/reference.conf index 9e7069f296..1a1b7b721b 100644 --- a/akka-durable-mailboxes/akka-file-mailbox/src/main/resources/reference.conf +++ b/akka-durable-mailboxes/akka-file-mailbox/src/main/resources/reference.conf @@ -4,23 +4,47 @@ # This is the reference config file that contains all the default settings. # Make your edits/overrides in your application.conf. +# +# For more information see akka { actor { mailbox { file-based { + # directory below which this queue resides directory-path = "./_mb" + + # attempting to add an item after the queue reaches this size (in items) will fail. max-items = 2147483647 + + # attempting to add an item after the queue reaches this size (in bytes) will fail. max-size = 2147483647 bytes - max-items = 2147483647 + + # attempting to add an item larger than this size (in bytes) will fail. max-item-size = 2147483647 bytes + + # maximum expiration time for this queue (seconds). max-age = 0s + + # maximum journal size before the journal should be rotated. max-journal-size = 16 MiB + + # maximum size of a queue before it drops into read-behind mode. max-memory-size = 128 MiB + + # maximum overflow (multiplier) of a journal file before we re-create it. max-journal-overflow = 10 + + # absolute maximum size of a journal file until we rebuild it, no matter what. max-journal-size-absolute = 9223372036854775807 bytes + + # whether to drop older items (instead of newer) when the queue is full discard-old-when-full = on + + # whether to keep a journal file at all keep-journal = on + + # whether to sync the journal after each transaction sync-journal = off } } diff --git a/akka-durable-mailboxes/akka-redis-mailbox/src/main/resources/reference.conf b/akka-durable-mailboxes/akka-redis-mailbox/src/main/resources/reference.conf index 93c11a2975..714b0b2dfe 100644 --- a/akka-durable-mailboxes/akka-redis-mailbox/src/main/resources/reference.conf +++ b/akka-durable-mailboxes/akka-redis-mailbox/src/main/resources/reference.conf @@ -4,12 +4,17 @@ # This is the reference config file that contains all the default settings. # Make your edits/overrides in your application.conf. +# +# for more information see akka { actor { mailbox { redis { + # hostname of where the redis queue resides hostname = "127.0.0.1" + + # port at which the redis queue resides port = 6379 } } diff --git a/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/resources/reference.conf b/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/resources/reference.conf index 4f9a47b084..322d5cc612 100644 --- a/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/resources/reference.conf +++ b/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/resources/reference.conf @@ -4,15 +4,21 @@ # This is the reference config file that contains all the default settings. # Make your edits/overrides in your application.conf. +# +# For more information see akka { actor { mailbox { zookeeper { + # host and port to connect to ZooKeeper server-addresses = "127.0.0.1:2181" + + # timeout after which an unreachable client is considered dead and its session is closed session-timeout = 60s + + # maximum wait period while connecting to ZooKeeper service connection-timeout = 60s - blocking-queue = on } } } diff --git a/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailbox.scala b/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailbox.scala index e54423d0e0..9b867fdfd9 100644 --- a/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailbox.scala +++ b/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailbox.scala @@ -38,7 +38,7 @@ class ZooKeeperBasedMessageQueue(_owner: ActorContext, val settings: ZooKeeperBa settings.ZkServerAddresses, settings.SessionTimeout, settings.ConnectionTimeout) - private val queue = new ZooKeeperQueue[Array[Byte]](zkClient, queuePathTemplate.format(name), settings.BlockingQueue) + private val queue = new ZooKeeperQueue[Array[Byte]](zkClient, queuePathTemplate.format(name), true) def enqueue(receiver: ActorRef, envelope: Envelope) { queue.enqueue(serialize(envelope)) diff --git a/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailboxSettings.scala b/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailboxSettings.scala index 58cd67c3c1..6ecdb65af4 100644 --- a/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailboxSettings.scala +++ b/akka-durable-mailboxes/akka-zookeeper-mailbox/src/main/scala/akka/actor/mailbox/ZooKeeperBasedMailboxSettings.scala @@ -20,6 +20,5 @@ class ZooKeeperBasedMailboxSettings(val systemSettings: ActorSystem.Settings, va val ZkServerAddresses = getString("server-addresses") val SessionTimeout = Duration(getMilliseconds("session-timeout"), MILLISECONDS) val ConnectionTimeout = Duration(getMilliseconds("connection-timeout"), MILLISECONDS) - val BlockingQueue = getBoolean("blocking-queue") } \ No newline at end of file From 49b1bf9c755f80e41a740a690bb9ac1d573817c6 Mon Sep 17 00:00:00 2001 From: Henrik Engstrom Date: Mon, 5 Mar 2012 20:36:34 +0100 Subject: [PATCH 30/46] Removed the getting started with Eclipse tutorial. Fixes #1887 --- .../getting-started-first-scala-eclipse.rst | 518 ------------------ akka-docs/intro/getting-started.rst | 5 - 2 files changed, 523 deletions(-) delete mode 100644 akka-docs/intro/getting-started-first-scala-eclipse.rst diff --git a/akka-docs/intro/getting-started-first-scala-eclipse.rst b/akka-docs/intro/getting-started-first-scala-eclipse.rst deleted file mode 100644 index ef68ff01ff..0000000000 --- a/akka-docs/intro/getting-started-first-scala-eclipse.rst +++ /dev/null @@ -1,518 +0,0 @@ -.. _getting-started-first-scala-eclipse: - -Getting Started Tutorial (Scala with Eclipse): First Chapter -============================================================ - -Introduction ------------- - -Welcome to the first tutorial on how to get started with Akka and Scala. We -assume that you already know what Akka and Scala are and will now focus on the -steps necessary to start your first project. - -There are two variations of this first tutorial: - -- creating a standalone project and run it from the command line -- creating a SBT (Simple Build Tool) project and running it from within SBT - -Since they are so similar we will present them both. - -The sample application that we will create is using actors to calculate the -value of Pi. Calculating Pi is a CPU intensive operation and we will utilize -Akka Actors to write a concurrent solution that scales out to multi-core -processors. This sample will be extended in future tutorials to use Akka Remote -Actors to scale out on multiple machines in a cluster. - -We will be using an algorithm that is called "embarrassingly parallel" which -just means that each job is completely isolated and not coupled with any other -job. Since this algorithm is so parallelizable it suits the actor model very -well. - -Here is the formula for the algorithm we will use: - -.. image:: ../images/pi-formula.png - -In this particular algorithm the master splits the series into chunks which are -sent out to each worker actor to be processed. When each worker has processed -its chunk it sends a result back to the master which aggregates the total -result. - - -Tutorial source code --------------------- - -If you want don't want to type in the code and/or set up an SBT project then you can -check out the full tutorial from the Akka GitHub repository. It is in the -``akka-tutorials/akka-tutorial-first`` module. You can also browse it online -`here`__, with the actual source code `here`__. - -__ https://github.com/akka/akka/tree/master/akka-tutorials/akka-tutorial-first -__ https://github.com/akka/akka/blob/master/akka-tutorials/akka-tutorial-first/src/main/scala/Pi.scala - -To check out the code using Git invoke the following command and you can then you can navigate down to the tutorial. - -On Linux/Unix/Mac systems:: - - $ git clone git://github.com/akka/akka.git - $ cd akka/akka-tutorials/akka-tutorial-first - -On Windows systems:: - - C:\Users\jboner\src> git clone git://github.com/akka/akka.git - C:\Users\jboner\src> cd akka\akka-tutorials\akka-tutorial-first - -Prerequisites -------------- - -This tutorial assumes that you have Java 1.6 or later installed on you machine -and ``java`` on your ``PATH``. You also need to know how to run commands in a -shell (ZSH, Bash, DOS etc.) and a decent text editor or IDE to type in the Scala -code. - -You need to make sure that ``$JAVA_HOME`` environment variable is set to the -root of the Java distribution. You also need to make sure that the -``$JAVA_HOME/bin`` is on your ``PATH``. - -On Linux/Unix/Mac systems:: - - $ export JAVA_HOME=..root of Java distribution.. - $ export PATH=$PATH:$JAVA_HOME/bin - -You can test your installation by invoking ``java``:: - - $ java -version - java version "1.6.0_24" - Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) - Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) - -On Windows systems:: - - C:\Users\jboner\src\akka> set JAVA_HOME=..root of Java distribution.. - C:\Users\jboner\src\akka> set PATH=%PATH%;%JAVA_HOME%/bin - -You can test your installation by invoking ``java``:: - - C:\Users\jboner\src\akka> java -version - java version "1.6.0_24" - Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326) - Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode) - -Downloading and installing Akka -------------------------------- - -To build and run the tutorial sample from the command line, you have to download -Akka. If you prefer to use SBT to build and run the sample then you can skip this -section and jump to the next one. - -Let's get the ``akka-2.1-SNAPSHOT.zip`` distribution of Akka from -http://akka.io/downloads/ which includes everything we need for this -tutorial. Once you have downloaded the distribution unzip it in the folder you -would like to have Akka installed in. In my case I choose to install it in -``/Users/jboner/tools/``, simply by unzipping it to this directory. - -You need to do one more thing in order to install Akka properly: set the -``AKKA_HOME`` environment variable to the root of the distribution. In my case -I'm opening up a shell, navigating down to the distribution, and setting the -``AKKA_HOME`` variable. - - -On Linux/Unix/Mac systems:: - - $ cd /Users/jboner/tools/akka-2.1-SNAPSHOT - $ export AKKA_HOME=`pwd` - $ echo $AKKA_HOME - /Users/jboner/tools/akka-2.1-SNAPSHOT - -On Windows systems:: - - C:\Users\jboner\src\akka> cd akka-2.1-SNAPSHOT - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set AKKA_HOME=%cd% - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> echo %AKKA_HOME% - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT - -The distribution looks like this. - -On Linux/Unix/Mac systems:: - - $ ls -1 - bin - config - deploy - doc - lib - src - -On Windows systems:: - - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> dir - bin - config - deploy - doc - lib - src - -- In the ``bin`` directory we have scripts for starting the Akka Microkernel. -- In the ``config`` directory we have the Akka conf files. -- In the ``deploy`` directory we can place applications to be run with the microkernel. -- In the ``doc`` directory we have the documentation, API, and doc JARs. -- In the ``lib`` directory we have the Scala and Akka JARs. -- In the ``src`` directory we have the source JARs for Akka. - -The only JAR we will need for this tutorial (apart from the -``scala-library.jar`` JAR) is the ``akka-actor-2.1-SNAPSHOT.jar`` JAR in the ``lib/akka`` -directory. This is a self-contained JAR with zero dependencies and contains -everything we need to write a system using Actors. - -Akka is very modular and has many JARs for containing different features. The -modules are: - -- ``akka-actor`` -- Actors - -- ``akka-remote`` -- Remote Actors - -- ``akka-slf4j`` -- SLF4J Event Handler Listener for logging with SLF4J - -- ``akka-testkit`` -- Toolkit for testing Actors - -- ``akka-kernel`` -- Akka microkernel for running a bare-bones mini application server - -- ``akka-durable-mailboxes`` -- Durable mailboxes: file-based, MongoDB, Redis, Zookeeper - -.. - ``akka-amqp`` -- AMQP integration -.. - ``akka-stm-2.1-SNAPSHOT.jar`` -- STM (Software Transactional Memory), transactors and transactional datastructures -.. - ``akka-camel-2.1-SNAPSHOT.jar`` -- Apache Camel Actors integration (it's the best way to have your Akka application communicate with the rest of the world) -.. - ``akka-camel-typed-2.1-SNAPSHOT.jar`` -- Apache Camel Typed Actors integration -.. - ``akka-spring-2.1-SNAPSHOT.jar`` -- Spring framework integration - - -Downloading and installing the Scala IDE for Eclipse ----------------------------------------------------- - -If you want to use Eclipse for coding your Akka tutorial, you need to install the Scala plugin for Eclipse. -This plugin comes with its own version of Scala, so if you don't plan to run the example from the command line, -you don't need to download the Scala distribution (and you can skip the next section). - -You can install this plugin using the regular update mechanism. First choose a version of the IDE from -`http://download.scala-ide.org `_. We recommend you choose 2.1.x, which -comes with Scala 2.9. Copy the corresponding URL and then choose ``Help/Install New Software`` and paste -the URL you just copied. You should see something similar to the following image. - -.. image:: ../images/install-beta2-updatesite.png - -Once the installation is finished, you need to restart Eclipse. The first time the plugin starts it will -open a diagnostics window and offer to fix several settings, such as the delay for content assist (code-completion) -or the shown completion proposal types. - -.. image:: ../images/diagnostics-window.png - -Accept the recommended settings, and follow the instructions if you need to increase the heap size of Eclipse. - -Check that the installation succeeded by creating a new Scala project (``File/New>Scala Project``), and typing some code. -You should have content-assist, hyperlinking to definitions, instant error reporting, and so on. - -.. image:: ../images/example-code.png - -You are ready to code now! - - -Downloading and installing Scala --------------------------------- - -To build and run the tutorial sample from the command line, you have to install -the Scala distribution. If you prefer to use SBT to build and run the sample -then you can skip this section and jump to the next one. - -Scala can be downloaded from http://www.scala-lang.org/downloads. Browse there -and download the Scala 2.9.1 release. If you pick the ``tgz`` or ``zip`` -distribution then just unzip it where you want it installed. If you pick the -IzPack Installer then double click on it and follow the instructions. - -You also need to make sure that the ``scala-2.9.1/bin`` (if that is the -directory where you installed Scala) is on your ``PATH``. -On Linux/Unix/Mac systems:: - - $ export PATH=$PATH:scala-2.9.1/bin - -On Windows systems:: - - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> set PATH=%PATH%;scala-2.9.1\bin - -You can test your installation by invoking scala. - -On Linux/Unix/Mac systems:: - - $ scala -version - Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL - -On Windows systems:: - - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> scala -version - Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL - -Looks like we are all good. Finally let's create a source file ``Pi.scala`` for -the tutorial and put it in the root of the Akka distribution in the ``tutorial`` -directory (you have to create it first). - -Some tools require you to set the ``SCALA_HOME`` environment variable to the -root of the Scala distribution, however Akka does not require that. - - -Creating an Akka project in Eclipse ------------------------------------ - -If you have not already done so, now is the time to create an Eclipse project for our tutorial. -Use the ``New Scala Project`` wizard and accept the default settings. Once the project is open, -we need to add the akka libraries to the *build path*. Right click on the project and choose ``Properties``, -then click on ``Java Build Path``. Go to ``Libraries`` and click on ``Add External Jars..``, then navigate -to the location where you installed akka and choose ``akka-actor.jar``. You should see something similar to this: - -.. image:: ../images/build-path.png - - -Using SBT in Eclipse -^^^^^^^^^^^^^^^^^^^^ - -If you are an `SBT `_ user, you can follow the :ref:`getting-started-first-scala-download-sbt` -instruction and additionally install the ``sbteclipse`` plugin. This adds support for generating Eclipse project files -from your SBT project. You need to install the plugin as described in the `README of sbteclipse -`_ - -Then run the ``eclipse`` target to generate the Eclipse project. - -On Linux/Unix/Mac systems:: - - $ sbt - > eclipse - -On Windows systems:: - - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> sbt - > eclipse - -The options `create-src` and `with-sources` are useful: - -On Linux/Unix/Mac systems:: - - $ sbt - > eclipse create-src with-sources - -On Windows systems:: - - C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> sbt - > eclipse create-src with-sources - -* create-src to create the common source directories, e.g. src/main/scala, src/main/test -* with-sources to create source attachments for the library dependencies - -Next you need to import this project in Eclipse, by choosing ``Eclipse/Import.. Existing Projects into Workspace``. -Navigate to the directory where you defined your SBT project and choose import: - -.. image:: ../images/import-project.png - -Now we have the basis for an Akka Eclipse application, so we can.. - - -Start writing the code ----------------------- - -The design we are aiming for is to have one ``Master`` actor initiating the computation, creating a set of ``Worker`` actors. Then it splits up the work into discrete chunks, and sends these chunks to the different workers in a round-robin fashion. The master waits until all the workers have completed their work and sent back results for aggregation. When computation is completed the master prints out the result, shuts down all workers and then itself. - -With this in mind, let's now create the messages that we want to have flowing in the system. - - -Creating the messages ---------------------- - -We start by creating a package for our application, let's call it ``akka.tutorial.first.scala``. -We start by creating case classes for each type of message in our application, so we can place them in a hierarchy, -call it ``PiMessage``. Right click on the package and choose ``New Scala Class``, and enter ``PiMessage`` as -the name of the class. - -We need four different messages: - -- ``Calculate`` -- sent to the ``Master`` actor to start the calculation -- ``Work`` -- sent from the ``Master`` actor to the ``Worker`` actors containing - the work assignment -- ``Result`` -- sent from the ``Worker`` actors to the ``Master`` actor - containing the result from the worker's calculation -- ``PiApproximation`` -- sent from the ``Master`` actor to the - ``Listener`` actor containing the the final pi result and how long time - the calculation took - -Messages sent to actors should always be immutable to avoid sharing mutable state. -In Scala we have 'case classes' which make excellent messages. So let's start by creating three messages as case classes. -We also create a common base trait for our messages (that we define as being ``sealed`` in order to prevent creating messages -outside our control): - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#messages - - -Creating the worker -------------------- - -Now we can create the worker actor. This is done by mixing in the ``Actor`` -trait and defining the ``receive`` method. The ``receive`` method defines our -message handler. We expect it to be able to handle the ``Work`` message so we -need to add a handler for this message: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#worker - :exclude: calculatePiFor - -The ``Actor`` trait is defined in ``akka.actor`` and you can either import it explicitly, -or let Eclipse do it for you when it cannot resolve the ``Actor`` trait. -The quick fix option (``Ctrl-F1``) will offer two options: - -.. image:: ../images/quickfix.png - -Choose the Akka Actor and move on. - -As you can see we have now created an ``Actor`` with a ``receive`` method as a -handler for the ``Work`` message. In this handler we invoke the -``calculatePiFor(..)`` method, wrap the result in a ``Result`` message and send -it back asynchronously to the original sender using the ``sender`` reference. -In Akka the sender reference is implicitly passed along with the message so that -the receiver can always reply or store away the sender reference for future use. - -The only thing missing in our ``Worker`` actor is the implementation on the -``calculatePiFor(..)`` method. While there are many ways we can implement this -algorithm in Scala, in this introductory tutorial we have chosen an imperative -style using a for comprehension and an accumulator: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#calculatePiFor - - -Creating the master -------------------- - -Now create a new class for the master actor. The master actor is a little bit -more involved. In its constructor we create a round-robin router to make it easier -to spread out the work evenly between the workers. First we need to add some imports: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#imports - -and then we can create the router: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#create-router - -Now we have a router that is representing all our workers in a single -abstraction. So now let's create the master actor. We pass it three integer variables: - -- ``nrOfWorkers`` -- defining how many workers we should start up -- ``nrOfMessages`` -- defining how many number chunks to send out to the workers -- ``nrOfElements`` -- defining how big the number chunks sent to each worker should be - -Here is the master actor: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#master - :exclude: handle-messages - -A couple of things are worth explaining further. - -Note that we are passing in a ``ActorRef`` to the ``Master`` actor. This is used to -report the the final result to the outside world. - -But we are not done yet. We are missing the message handler for the ``Master`` -actor. This message handler needs to be able to react to two different messages: - -- ``Calculate`` -- which should start the calculation -- ``Result`` -- which should aggregate the different results - -The ``Calculate`` handler is sending out work to all the ``Worker`` via its router. - -The ``Result`` handler gets the value from the ``Result`` message and aggregates it to -our ``pi`` member variable. We also keep track of how many results we have received back, -and if that matches the number of tasks sent out, the ``Master`` actor considers itself done and -sends the final result to the ``listener``. When done it also invokes the ``context.stop(self)`` -method to stop itself *and* all its supervised actors. -In this case it has one supervised actor, the router, and this in turn has ``nrOfWorkers`` supervised actors. -All of them will be stopped automatically as the invocation of any supervisor's ``stop`` method -will propagate down to all its supervised 'children'. - -Let's capture this in code: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#master-receive - -Creating the result listener ----------------------------- - -The listener is straightforward. When it receives the ``PiApproximation`` from the ``Master`` it -prints the result and shuts down the ``ActorSystem``. - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#result-listener - -Bootstrap the calculation -------------------------- - -Now the only thing that is left to implement is the runner that should bootstrap and run the calculation for us. -We do that by creating an object that we call ``Pi``, here we can extend the ``App`` trait in Scala, -which means that we will be able to run this as an application directly from the command line or using the Eclipse Runner. - -The ``Pi`` object is a perfect container module for our actors and messages, so let's put them all there. -We also create a method ``calculate`` in which we start up the ``Master`` actor and wait for it to finish: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala#app - :exclude: actors-and-messages - -As you can see the *calculate* method above it creates an ``ActorSystem`` and this is the Akka container which -will contain all actors created in that "context". An example of how to create actors in the container -is the *'system.actorOf(...)'* line in the calculate method. In this case we create two top level actors. -If you instead where in an actor context, i.e. inside an actor creating other actors, you should use -*context.actorOf(...)*. This is illustrated in the Master code above. - -That's it. Now we are done. - -Run it from Eclipse -------------------- - -Eclipse builds your project on every save when ``Project/Build Automatically`` is set. -If not, bring you project up to date by clicking ``Project/Build Project``. If there are no compilation errors, -you can right-click in the editor where ``Pi`` is defined, and choose ``Run as.. /Scala application``. -If everything works fine, you should see:: - - Pi approximation: 3.1435501812459323 - Calculation time: 359 millis - -You can also define a new Run configuration, by going to ``Run/Run Configurations``. Create a new ``Scala application`` -and choose the tutorial project and the main class to be ``akka/tutorial.Pi``. You can pass additional command line -arguments to the JVM on the ``Arguments`` page, for instance to define where :ref:`configuration` is: - -.. image:: ../images/run-config.png - -Once you finished your run configuration, click ``Run``. You should see the same output in the ``Console`` window. -You can use the same configuration for debugging the application, by choosing ``Run/Debug History`` or just ``Debug As``. - -Overriding Configuration Externally (Optional) ----------------------------------------------- - -The sample project includes an ``application.conf`` file in the resources directory: - -.. includecode:: ../../akka-tutorials/akka-tutorial-first/src/main/resources/application.conf - -If you uncomment the two lines, you should see a change in performance, -hopefully for the better (you might want to increase the number of messages in -the code to prolong the time the application runs). It should be noted that -overriding only works if a router type is given, so just uncommenting -``nr-of-instances`` does not work; see :ref:`routing-scala` for more details. - -.. note:: - - Make sure that your ``application.conf`` is on the class path when you run - the application. If running from inside SBT that should already be the case, - otherwise you need to add the directory containing this file to the JVM’s - ``-classpath`` option. - -Conclusion ----------- - -We have learned how to create our first Akka project using Akka's actors to -speed up a computation-intensive problem by scaling out on multi-core processors -(also known as scaling up). We have also learned to compile and run an Akka -project using either the tools on the command line or the SBT build system. - -If you have a multi-core machine then I encourage you to try out different -number of workers (number of working actors) by tweaking the ``nrOfWorkers`` -variable to for example; 2, 4, 6, 8 etc. to see performance improvement by -scaling up. - -Happy hakking. diff --git a/akka-docs/intro/getting-started.rst b/akka-docs/intro/getting-started.rst index 748ebbc6b0..2c40bc6c55 100644 --- a/akka-docs/intro/getting-started.rst +++ b/akka-docs/intro/getting-started.rst @@ -19,8 +19,6 @@ preferences: - as standalone project, running from the command line, - or as SBT (Simple Build Tool) project and running it from within SBT -- :ref:`getting-started-first-scala-eclipse` for Scala development with Eclipse - The Getting Started Tutorial describes everything you need to get going, and you don't need to read the rest of this page if you study the tutorial. For later look back reference this page describes the essential parts for getting started @@ -144,9 +142,6 @@ SBT installation instructions on `https://github.com/harrah/xsbt/wiki/Setup `_ to generate Eclipse project. Using Akka with IntelliJ IDEA From 74ad848983ec1d9538f8fcf7dfbebef1c2a563a5 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 5 Mar 2012 21:05:21 +0100 Subject: [PATCH 31/46] Consistently using 'terminate' in supervision docs --- akka-docs/general/supervision.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/akka-docs/general/supervision.rst b/akka-docs/general/supervision.rst index 99efb0378d..a8a1c21582 100644 --- a/akka-docs/general/supervision.rst +++ b/akka-docs/general/supervision.rst @@ -29,9 +29,9 @@ It is important to always view an actor as part of a supervision hierarchy, which explains the existence of the fourth choice (as a supervisor also is subordinate to another supervisor higher up) and has implications on the first three: resuming an actor resumes all its subordinates, restarting an actor -entails restarting all its subordinates, similarly stopping an actor will also -stop all its subordinates. It should be noted that the default behavior of an -actor is to stop all its children before restarting, but this can be overridden +entails restarting all its subordinates, similarly terminating an actor will also +terminating all its subordinates. It should be noted that the default behavior of an +actor is to terminate all its children before restarting, but this can be overridden using the :meth:`preRestart` hook; the recursive restart applies to all children left after this hook has been executed. @@ -103,7 +103,7 @@ which the monitoring request and target’s termination occur, i.e. you still ge the message even if at the time of registration the target is already dead. Monitoring is particularly useful if a supervisor cannot simply restart its -children and has to stop them, e.g. in case of errors during actor +children and has to terminate them, e.g. in case of errors during actor initialization. In that case it should monitor those children and re-create them or schedule itself to retry this at a later time. @@ -128,7 +128,7 @@ explicitly. The :class:`AllForOneStrategy` is applicable in cases where the ensemble of children has so tight dependencies among them, that a failure of one child affects the function of the others, i.e. they are intricably linked. Since a -restart does not clear out the mailbox, it often is best to stop the children +restart does not clear out the mailbox, it often is best to terminate the children upon failure and re-create them explicitly from the supervisor (by watching the children’s lifecycle); otherwise you have to make sure that it is no problem for any of the actors to receive a message which was queued before the restart From a86468114723b85f727c6add181c3cb8b81b7590 Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 5 Mar 2012 21:47:19 +0100 Subject: [PATCH 32/46] clarify restart sequence in supervision.rst --- akka-docs/general/supervision.rst | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/akka-docs/general/supervision.rst b/akka-docs/general/supervision.rst index a8a1c21582..e36e5c7fd4 100644 --- a/akka-docs/general/supervision.rst +++ b/akka-docs/general/supervision.rst @@ -18,7 +18,7 @@ therefore must respond to their failures. When a subordinate detects a failure (i.e. throws an exception), it suspends itself and all its subordinates and sends a message to its supervisor, signaling failure. Depending on the nature of the work to be supervised and the nature of the failure, the supervisor has -four basic choices: +a choice of the following four options: #. Resume the subordinate, keeping its accumulated internal state #. Restart the subordinate, clearing out its accumulated internal state @@ -29,11 +29,12 @@ It is important to always view an actor as part of a supervision hierarchy, which explains the existence of the fourth choice (as a supervisor also is subordinate to another supervisor higher up) and has implications on the first three: resuming an actor resumes all its subordinates, restarting an actor -entails restarting all its subordinates, similarly terminating an actor will also -terminating all its subordinates. It should be noted that the default behavior of an -actor is to terminate all its children before restarting, but this can be overridden -using the :meth:`preRestart` hook; the recursive restart applies to all -children left after this hook has been executed. +entails restarting all its subordinates (but see below for more details), +similarly terminating an actor will also terminating all its subordinates. It +should be noted that the default behavior of the :meth:`preRestart` hook of the +:class:`Actor` class is to terminate all its children before restarting, but +this hook can be overridden; the recursive restart applies to all children left +after this hook has been executed. Each supervisor is configured with a function translating all possible failure causes (i.e. exceptions) into one of the four choices given above; notably, @@ -77,12 +78,19 @@ that the restart is not visible outside of the actor itself with the notable exception that the message during which the failure occurred is not re-processed. -Restarting an actor in this way recursively terminates all its children. If -this is not the right approach for certain sub-trees of the supervision -hierarchy, you may choose to retain the children, in which case they will be -recursively restarted in the same fashion as the failed parent (with the same -default to terminate children, which must be overridden on a per-actor basis, -see :class:`Actor` for details). +The precise sequence of events during a restart is the following: + +* suspend the actor +* call the old instance’s :meth:`supervisionStrategy.handleSupervisorFailing` + method (defaults to suspending all children) +* call the old instance’s :meth:`preRestart` hook (defaults to sending + termination requests to all children and calling :meth:`postStop`) +* wait for all children stopped during :meth:`preRestart` to actually terminate +* call the old instance’s :meth:`supervisionStrategy.handleSupervisorRestarted` + method (defaults to sending restart request to all remaining children) +* create new actor instance by invoking the originally provided factory again +* invoke :meth:`postRestart` on the new instance +* resume the actor What Lifecycle Monitoring Means ------------------------------- From b2a4422a0f35f181cdf0a8e4080581fc8577d6f7 Mon Sep 17 00:00:00 2001 From: Roland Date: Mon, 5 Mar 2012 21:51:10 +0100 Subject: [PATCH 33/46] remove stale link to getting-started-first-scala-eclipse.rst --- akka-docs/intro/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/akka-docs/intro/index.rst b/akka-docs/intro/index.rst index b04b877827..f474e07d8b 100644 --- a/akka-docs/intro/index.rst +++ b/akka-docs/intro/index.rst @@ -8,7 +8,6 @@ Introduction why-akka getting-started getting-started-first-scala - getting-started-first-scala-eclipse getting-started-first-java deployment-scenarios use-cases From 4b759a18c89d9f322a70ddeefd399f334daa1c35 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 5 Mar 2012 23:09:06 +0100 Subject: [PATCH 34/46] Changing from jboner/akka to akka/akka --- akka-docs/dev/multi-jvm-testing.rst | 4 ++-- project/scripts/release | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/akka-docs/dev/multi-jvm-testing.rst b/akka-docs/dev/multi-jvm-testing.rst index 3b6fd44f6c..50786c52bf 100644 --- a/akka-docs/dev/multi-jvm-testing.rst +++ b/akka-docs/dev/multi-jvm-testing.rst @@ -361,13 +361,13 @@ machines using schoir (read the same as ``esquire``) plugin. The plugin is inclu The interaction with the plugin is through ``schoir:master`` input task. This input task optionally accepts the path to the file with the following properties:: - git.url=git@github.com:jboner/akka.git + git.url=git@github.com:akka/akka.git external.addresses.for.ssh=host1:port1,...,hostN:portN internal.host.names=host1,...,hostN Alternative to specifying the property file, one can set respective settings in the build file:: - gitUrl := "git@github.com:jboner/akka.git", + gitUrl := "git@github.com:akka/akka.git", machinesExt := List(InetAddress("host1", port1)), machinesInt := List("host1") diff --git a/project/scripts/release b/project/scripts/release index b716a484bd..480eefdfea 100755 --- a/project/scripts/release +++ b/project/scripts/release @@ -3,7 +3,7 @@ # Release script for Akka. # # To run this script you need a user account on akka.io and contributor access -# to github.com/jboner/akka. +# to github.com/akka/akka. # # If your username on akka.io is different from your local username then you can # configure ssh to always associate a particular username with akka.io by adding From 2de49aa1d62e88461e369092e23178fadf3af3a9 Mon Sep 17 00:00:00 2001 From: Peter Vlugter Date: Tue, 6 Mar 2012 11:51:55 +1300 Subject: [PATCH 35/46] Fix kernel start script. See #1889 --- akka-kernel/src/main/dist/bin/akka | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/akka-kernel/src/main/dist/bin/akka b/akka-kernel/src/main/dist/bin/akka index 84ae2e5d78..95bad347b3 100755 --- a/akka-kernel/src/main/dist/bin/akka +++ b/akka-kernel/src/main/dist/bin/akka @@ -17,8 +17,8 @@ done declare AKKA_HOME="$(cd "$(cd "$(dirname "$0")"; pwd -P)"/..; pwd)" -[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xmx1024M -Xms1024M -Xss1M -XX:MaxPermSize=256M -XX:+UseParallelGC -XX:OnOutOfMemoryError=\"kill -9 %p\"" +[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xms1024M -Xmx1024M -Xss1M -XX:MaxPermSize=256M -XX:+UseParallelGC" [ -n "$AKKA_CLASSPATH" ] || AKKA_CLASSPATH="$AKKA_HOME/lib/scala-library.jar:$AKKA_HOME/config:$AKKA_HOME/lib/akka/*" -java "$JAVA_OPTS" -cp "$AKKA_CLASSPATH" -Dakka.home="$AKKA_HOME" -Dakka.kernel.quiet=$quiet akka.kernel.Main "$@" +java $JAVA_OPTS -cp "$AKKA_CLASSPATH" -Dakka.home="$AKKA_HOME" -Dakka.kernel.quiet=$quiet akka.kernel.Main "$@" From f51afb9b4746e3b6aae59794d8edfaa0ef0341dd Mon Sep 17 00:00:00 2001 From: Peter Vlugter Date: Tue, 6 Mar 2012 11:57:55 +1300 Subject: [PATCH 36/46] Fix pi output in getting started docs. See #1890 --- akka-docs/intro/getting-started-first-java.rst | 8 ++++---- akka-docs/intro/getting-started-first-scala.rst | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/akka-docs/intro/getting-started-first-java.rst b/akka-docs/intro/getting-started-first-java.rst index 300b381b72..5fef51e5ef 100644 --- a/akka-docs/intro/getting-started-first-java.rst +++ b/akka-docs/intro/getting-started-first-java.rst @@ -441,7 +441,7 @@ On Linux/Unix/Mac systems:: -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar:. \ akka.tutorial.first.scala.Pi - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis On Windows systems:: @@ -450,7 +450,7 @@ On Windows systems:: -cp lib/scala-library.jar;lib\akka\akka-actor-2.1-SNAPSHOT.jar;. \ akka.tutorial.first.scala.Pi - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis Yippee! It is working. @@ -474,7 +474,7 @@ On Linux/Unix/Mac systems:: $ mvn exec:java -Dexec.mainClass="akka.tutorial.first.java.Pi" ... - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis On Windows systems:: @@ -482,7 +482,7 @@ On Windows systems:: C:\Users\jboner\src\akka\akka-2.1-SNAPSHOT> mvn exec:java \ -Dexec.mainClass="akka.tutorial.first.java.Pi" ... - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis Yippee! It is working. diff --git a/akka-docs/intro/getting-started-first-scala.rst b/akka-docs/intro/getting-started-first-scala.rst index 3721af57ff..91bed34b78 100644 --- a/akka-docs/intro/getting-started-first-scala.rst +++ b/akka-docs/intro/getting-started-first-scala.rst @@ -477,7 +477,7 @@ On Linux/Unix/Mac systems:: -cp lib/scala-library.jar:lib/akka/akka-actor-2.1-SNAPSHOT.jar:. \ akka.tutorial.first.scala.Pi - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis On Windows systems:: @@ -486,7 +486,7 @@ On Windows systems:: -cp lib/scala-library.jar;lib\akka\akka-actor-2.1-SNAPSHOT.jar;. \ akka.tutorial.first.scala.Pi - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis Yippee! It is working. @@ -513,7 +513,7 @@ When this in done we can run our application directly inside SBT:: > run ... - Pi approximation: 3.1435501812459323 + Pi approximation: 3.1415926435897883 Calculation time: 359 millis Yippee! It is working. From d7fe025fa22e6e6903b5c08eeaa25dbc3894d6ee Mon Sep 17 00:00:00 2001 From: Peter Vlugter Date: Tue, 6 Mar 2012 13:20:00 +1300 Subject: [PATCH 37/46] Update docs theme --- akka-docs/_sphinx/static/favicon.ico | Bin 0 -> 1203 bytes akka-docs/_sphinx/themes/akka/layout.html | 164 +++-- .../_sphinx/themes/akka/static/akka.css_t | 359 ----------- .../themes/akka/static/alert_info_32.png | Bin 1168 -> 0 bytes .../themes/akka/static/alert_warning_32.png | Bin 1060 -> 0 bytes akka-docs/_sphinx/themes/akka/static/base.css | 92 +++ .../_sphinx/themes/akka/static/bg-page.png | Bin 164 -> 0 bytes .../themes/akka/static/bullet_orange.png | Bin 365 -> 0 bytes .../_sphinx/themes/akka/static/contentsFix.js | 10 + .../themes/akka/static/dark-blue-bg-main.jpg | Bin 0 -> 82746 bytes .../themes/akka/static/dark-blue-bg.png | Bin 0 -> 4309 bytes akka-docs/_sphinx/themes/akka/static/docs.css | 139 ++++ .../themes/akka/static/effects.core.js | 509 +++++++++++++++ .../themes/akka/static/effects.highlight.js | 48 ++ .../_sphinx/themes/akka/static/footer-bg.png | Bin 0 -> 926 bytes .../themes/akka/static/highlightCode.js | 13 + .../_sphinx/themes/akka/static/jquery.js | 4 + .../_sphinx/themes/akka/static/logo-small.png | Bin 0 -> 2271 bytes .../_sphinx/themes/akka/static/pdf-icon.png | Bin 0 -> 15170 bytes .../_sphinx/themes/akka/static/prettify.css | 43 ++ .../_sphinx/themes/akka/static/prettify.js | 28 + .../_sphinx/themes/akka/static/scrollTo.js | 9 + .../_sphinx/themes/akka/static/style.css | 610 ++++++++++++++++++ akka-docs/_sphinx/themes/akka/static/toc.js | 131 ++++ .../_sphinx/themes/akka/static/watermark.png | Bin 0 -> 43590 bytes akka-docs/_sphinx/themes/akka/theme.conf | 10 +- akka-docs/cluster/cluster.rst | 4 - akka-docs/conf.py | 6 +- akka-docs/dev/building-akka.rst | 2 - akka-docs/dev/documentation.rst | 4 - akka-docs/dev/multi-jvm-testing.rst | 2 - akka-docs/disabled/spring.rst | 4 - akka-docs/general/addressing.rst | 4 - akka-docs/general/configuration.rst | 5 - .../intro/getting-started-first-java.rst | 4 +- akka-docs/intro/getting-started.rst | 4 - akka-docs/intro/what-is-akka.rst | 4 - akka-docs/java/agents.rst | 4 - akka-docs/java/dispatchers.rst | 4 - akka-docs/java/event-bus.rst | 4 - akka-docs/java/extending-akka.rst | 3 - akka-docs/java/fault-tolerance.rst | 4 - akka-docs/java/fsm.rst | 3 - akka-docs/java/futures.rst | 4 - akka-docs/java/logging.rst | 3 - akka-docs/java/routing.rst | 4 - akka-docs/java/serialization.rst | 4 - akka-docs/java/transactors.rst | 4 - akka-docs/java/typed-actors.rst | 4 - akka-docs/java/untyped-actors.rst | 5 - akka-docs/java/zeromq.rst | 3 - akka-docs/modules/durable-mailbox.rst | 3 - akka-docs/modules/http.rst | 6 +- .../project/migration-guide-1.3.x-2.0.x.rst | 6 - akka-docs/project/other-doc.rst | 45 +- akka-docs/project/release-notes.rst | 4 +- akka-docs/project/scaladoc.rst | 36 +- akka-docs/scala/actors.rst | 5 - akka-docs/scala/agents.rst | 4 - akka-docs/scala/dataflow.rst | 4 - akka-docs/scala/dispatchers.rst | 4 - akka-docs/scala/event-bus.rst | 3 - akka-docs/scala/extending-akka.rst | 4 - akka-docs/scala/fault-tolerance.rst | 4 - akka-docs/scala/fsm.rst | 3 - akka-docs/scala/futures.rst | 3 - akka-docs/scala/io.rst | 3 - akka-docs/scala/logging.rst | 3 - akka-docs/scala/remoting.rst | 4 - akka-docs/scala/routing.rst | 4 - akka-docs/scala/serialization.rst | 4 - akka-docs/scala/testing.rst | 4 - akka-docs/scala/transactors.rst | 4 - akka-docs/scala/typed-actors.rst | 4 - akka-docs/scala/zeromq.rst | 4 - 75 files changed, 1795 insertions(+), 638 deletions(-) create mode 100644 akka-docs/_sphinx/static/favicon.ico delete mode 100644 akka-docs/_sphinx/themes/akka/static/akka.css_t delete mode 100644 akka-docs/_sphinx/themes/akka/static/alert_info_32.png delete mode 100644 akka-docs/_sphinx/themes/akka/static/alert_warning_32.png create mode 100644 akka-docs/_sphinx/themes/akka/static/base.css delete mode 100644 akka-docs/_sphinx/themes/akka/static/bg-page.png delete mode 100644 akka-docs/_sphinx/themes/akka/static/bullet_orange.png create mode 100644 akka-docs/_sphinx/themes/akka/static/contentsFix.js create mode 100644 akka-docs/_sphinx/themes/akka/static/dark-blue-bg-main.jpg create mode 100644 akka-docs/_sphinx/themes/akka/static/dark-blue-bg.png create mode 100644 akka-docs/_sphinx/themes/akka/static/docs.css create mode 100644 akka-docs/_sphinx/themes/akka/static/effects.core.js create mode 100644 akka-docs/_sphinx/themes/akka/static/effects.highlight.js create mode 100644 akka-docs/_sphinx/themes/akka/static/footer-bg.png create mode 100644 akka-docs/_sphinx/themes/akka/static/highlightCode.js create mode 100644 akka-docs/_sphinx/themes/akka/static/jquery.js create mode 100644 akka-docs/_sphinx/themes/akka/static/logo-small.png create mode 100644 akka-docs/_sphinx/themes/akka/static/pdf-icon.png create mode 100644 akka-docs/_sphinx/themes/akka/static/prettify.css create mode 100644 akka-docs/_sphinx/themes/akka/static/prettify.js create mode 100644 akka-docs/_sphinx/themes/akka/static/scrollTo.js create mode 100644 akka-docs/_sphinx/themes/akka/static/style.css create mode 100644 akka-docs/_sphinx/themes/akka/static/toc.js create mode 100644 akka-docs/_sphinx/themes/akka/static/watermark.png diff --git a/akka-docs/_sphinx/static/favicon.ico b/akka-docs/_sphinx/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..858e2dbebda17d0c25eef4cbefdc74bae71bbad1 GIT binary patch literal 1203 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7wKJWa12U7785k;VP3_<7 zbvQw!ZN5H-SZkDFN3*k9V1Q3Fdw1}qX-XW|UQI~Jz7(+3gfrf*zDlq!Pd4VxUM6*S zcE^ugdzg=|Y<6zp;ahtC%be+lAMRN&Gwg6)ma2rCS6S4yhdbsO{`YEh4O>xkf%npp ztnK{_i!8W)9zV~{^dR?m)(zjZWJQl9Oll5G#g{R12usAQc4?Gg-evD0(&6qfJ$^9k zWz6Xd66FhiY`~Q?^T?*vhvX*wWj|1~?MCL!V`)3XZr`7^@q38Obz`I7R*nowUscZ+ zHF;NlUGB8nZ~kZL$EFr_4Ld#Oy}f(rubIx>r#Iasy>@>v`Nw*AeL(&j|0RDJ7#P@+ zyxm-E@3|}cb-$V- z%OsVL*UCKZpKoH=e)ZXM`F*a_RNndMPm*}Ebie=o`3DMbpZWK3N<_%w4RJ@m*S0jA zXJ1tF-Iu9B{if+Af9^jOKTTp|W#9AVjoT5;Z*H6NdERyuCi9ax_%93Wbilz8o$?z$KY*NE4*J}-N` zZRhvfMt!&4EU#2siM|N1{Pj{XPHeTz%d0Qny<4&+F#XA$>o3@Mf1kQq%c%Ky^@dfv zOMXq$ZJMjKvu5UnMn1kQ$1|6t_gRQNKcGH$OO&q7d1VQnP5VF8N8P`=cXzq#r(?Vq zbIi(bp82w6$4not#m*T;XhnSS`Q&8n+fU5gTCsqOqO;h-XP zaFb5fR;jMgl}j$YG+}0D&dJM5nx*#l?_VDuAAwGn6<4#SoKCI!{cFaK((c0-HJ%1_ z&OWKa&CPvc@#4if`T3i-Y-!Osy~oHmX!2xD#a@@wVCH@by6&A}5}Io@2oC?AfyuditNub5ECeU%S4m zfq{WRwZt`|BqgyV)hf9tHL)a>!N|bSP}k5%*U&P=(8$Wf%*xbK*TBrmz`&z1c{PfL d-29Zxv`X9>EbrVFXJBAp@O1TaS?83{1OUMkC?Nm< literal 0 HcmV?d00001 diff --git a/akka-docs/_sphinx/themes/akka/layout.html b/akka-docs/_sphinx/themes/akka/layout.html index 0d46ef708e..c92fa9b9c3 100644 --- a/akka-docs/_sphinx/themes/akka/layout.html +++ b/akka-docs/_sphinx/themes/akka/layout.html @@ -4,60 +4,132 @@ #} {% extends "basic/layout.html" %} -{% set script_files = script_files + ['_static/theme_extras.js'] %} -{% set css_files = css_files + ['_static/print.css'] %} +{% set script_files = script_files + ['_static/toc.js'] %} +{% set script_files = script_files + ['_static/prettify.js'] %} +{% set script_files = script_files + ['_static/highlightCode.js'] %} +{% set script_files = script_files + ['_static/effects.core.js'] %} +{% set script_files = script_files + ['_static/effects.highlight.js'] %} +{% set script_files = script_files + ['_static/scrollTo.js'] %} +{% set script_files = script_files + ['_static/contentsFix.js'] %} +{% set css_files = css_files + ['_static/prettify.css'] %} +{% set css_files = css_files + ['_static/base.css'] %} +{% set css_files = css_files + ['_static/docs.css'] %} +{% set css_files = css_files + ['http://fonts.googleapis.com/css?family=Exo:300,400,600,700'] %} {% set is_snapshot = version.endswith("-SNAPSHOT") %} {# do not display relbars #} {% block relbar1 %}{% endblock %} {% block relbar2 %}{% endblock %} -{% macro nav() %} -

- {%- block akkarel1 %} - {%- endblock %} - {%- if prev %} - «  {{ prev.title }} -   ::   - {%- endif %} - {{ _('Contents') }} - {%- if next %} -   ::   - {{ next.title }}  » - {%- endif %} - {%- block akkarel2 %} - {%- endblock %} -

-{% endmacro %} - {% block content %} -
- {%- block akkaheader %} - {%- if logo -%} - - {%- endif -%} -

{{ shorttitle|e }}

-

Version {{ version|e }}

- {%- if is_snapshot -%} -

PDF

- {%- else -%} -

PDF

- {%- endif -%} - {%- endblock %} + {%- block akkaheader %} +