Swapped out Scala Actors to a reactor based impl (still restart and linking to do) + finalized transactional persisted cassandra based vector (ref to go)

This commit is contained in:
Jonas Boner 2009-06-10 20:04:33 +02:00
parent 167b724671
commit ac52556595
22 changed files with 726 additions and 404 deletions

554
akka.iws
View file

@ -2,14 +2,25 @@
<project relativePaths="false" version="4">
<component name="ChangeListManager">
<list default="true" name="Default" comment="&#10;# Brief commit desciption here&#10;&#10;# Full commit description here (comment lines starting with '#' will not be included)&#10;&#10;">
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/test/scala/ActorTest.scala" afterPath="$PROJECT_DIR$/kernel/src/test/scala/ActorTest.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/Kernel.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/Kernel.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/EventBasedDispatcher.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/EventBasedDispatcher.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala" />
<change type="DELETED" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/EventDrivenDispatcher.scala" afterPath="" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/test/scala/ThreadBasedDispatcherTest.scala" afterPath="$PROJECT_DIR$/kernel/src/test/scala/ThreadBasedDispatcherTest.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iws" afterPath="$PROJECT_DIR$/akka.iws" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/test/scala/EventBasedDispatcherTest.scala" afterPath="$PROJECT_DIR$/kernel/src/test/scala/EventBasedDispatcherTest.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/ThreadBasedDispatcher.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/ThreadBasedDispatcher.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/CassandraNode.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/CassandraNode.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/Actor.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/Actor.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateful.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateful.java" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/State.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/State.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/DataFlowVariable.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/DataFlowVariable.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/Logging.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/Logging.scala" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala" />
</list>
<ignored path="akka.iws" />
@ -30,59 +41,7 @@
</component>
<component name="DebuggerManager">
<line_breakpoints>
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="152" class="Class at State.scala:152" package="">
<option name="ENABLED" value="true" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="153" class="Class at State.scala:153" package="">
<option name="ENABLED" value="true" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="157" class="Class at State.scala:157" package="">
<option name="ENABLED" value="true" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="158" class="Class at State.scala:158" package="">
<option name="ENABLED" value="true" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="155" class="Class at State.scala:155" package="">
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala" line="142" class="Class at ActiveObject.scala:141" package="">
<option name="ENABLED" value="true" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
@ -153,37 +112,46 @@
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="Transaction.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="86" column="0" selection-start="2898" selection-end="2898" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Reactor.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="4" selection-start="3" selection-end="3" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="PersistentStateful.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateful.java">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="51" selection-start="364" selection-end="364" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Seq.scala" pinned="false" current="false" current-in-tab="false">
<entry file="jar://$PROJECT_DIR$/../../../bin/scala-2.7.3.final/src/scala-library-src.jar!/scala/Seq.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="197" column="6" selection-start="6523" selection-end="6523" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ActiveObject.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="112" column="52" selection-start="4116" selection-end="4116" vertical-scroll-proportion="-13.5">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ResultOrFailure.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="56" column="6" selection-start="1411" selection-end="1411" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="GenericServer.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/GenericServer.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="188" column="6" selection-start="6146" selection-end="6146" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="InMemStateful.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java">
<provider selected="true" editor-type-id="text-editor">
<state line="52" column="17" selection-start="1441" selection-end="1441" vertical-scroll-proportion="0.0">
<state line="0" column="109" selection-start="3" selection-end="3" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
@ -192,28 +160,44 @@
<file leaf-file-name="State.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="158" column="0" selection-start="5462" selection-end="5462" vertical-scroll-proportion="0.0">
<state line="204" column="66" selection-start="7094" selection-end="7094" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="Transaction.scala" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala">
<file leaf-file-name="RandomAccessSeq.scala" pinned="false" current="false" current-in-tab="false">
<entry file="jar://$MAVEN_REPOSITORY$/org/scala-lang/scala-library/2.7.3/scala-library-2.7.3-sources.jar!/scala/RandomAccessSeq.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="43" column="0" selection-start="1313" selection-end="1313" vertical-scroll-proportion="0.0">
<state line="245" column="6" selection-start="10181" selection-end="10181" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="InMemoryStateTest.java" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
<file leaf-file-name="Transaction.class" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/WEB-INF/classes/se/scalablesolutions/akka/kernel/Transaction.class">
<provider selected="true" editor-type-id="text-editor">
<state line="88" column="46" selection-start="4602" selection-end="4602" vertical-scroll-proportion="0.7783933">
<folding>
<element signature="imports" expanded="true" />
</folding>
<state line="16" column="0" selection-start="1321" selection-end="1321" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="PersistentStateTest.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java">
<provider selected="true" editor-type-id="text-editor">
<state line="58" column="14" selection-start="2649" selection-end="2649" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="CassandraNode.scala" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/CassandraNode.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="4" selection-start="3" selection-end="3" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
@ -273,32 +257,6 @@
<option name="myItemId" value="akka-kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.LibraryGroupNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka-kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.LibraryGroupNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Maven: org.scala-lang:scala-library:2.7.3" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.NamedLibraryElementNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="scala-library-2.7.3.jar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
@ -331,14 +289,6 @@
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="test" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="scala" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
@ -366,66 +316,6 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka-kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="scala" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="reactor" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka-kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="scala" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="config" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
@ -532,7 +422,7 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="InMemoryStateTest" />
<option name="myItemId" value="PersistentStateTest" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ClassTreeNode" />
</PATH_ELEMENT>
</PATH>
@ -566,10 +456,128 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="InMemStateful" />
<option name="myItemId" value="PersistentStateful" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ClassTreeNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="WEB-INF" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="classes" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="se" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="scalablesolutions" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="WEB-INF" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="classes" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="se" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="scalablesolutions" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="kernel" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="akka" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="WEB-INF" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="classes" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</component>
<component name="ProjectReloadState">
@ -628,7 +636,7 @@
<recent name="se.scalablesolutions.akka.api" />
</key>
</component>
<component name="RunManager" selected="JUnit.InMemoryStateTest">
<component name="RunManager" selected="JUnit.PersistentStateTest">
<tempConfiguration default="false" name="Scala Console" type="ScalaScriptConsoleRunConfiguration" factoryName="Scala Console">
<module name="" />
<setting name="vmparams" value="" />
@ -907,7 +915,37 @@
<option name="Make" value="false" />
</method>
</configuration>
<list size="8">
<configuration default="false" name="ThreadBasedDispatcherTest" type="JUnit" factoryName="JUnit" enabled="false" merge="false" sample_coverage="true" runner="emma">
<module name="akka-kernel" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="se.scalablesolutions.akka.kernel.reactor.ThreadBasedDispatcherTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="ADDITIONAL_CLASS_PATH" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="49238" />
<option name="TRANSPORT" value="0" />
<option name="LOCAL" value="true" />
</RunnerSettings>
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" value="false" />
</method>
</configuration>
<list size="9">
<item index="0" class="java.lang.String" itemvalue="Application.Kernel" />
<item index="1" class="java.lang.String" itemvalue="JUnit.CamelSpec" />
<item index="2" class="java.lang.String" itemvalue="JUnit.InMemoryStateTest" />
@ -915,7 +953,8 @@
<item index="4" class="java.lang.String" itemvalue="JUnit.ActiveObjectGuiceConfiguratorTest" />
<item index="5" class="java.lang.String" itemvalue="JUnit.JerseySpec" />
<item index="6" class="java.lang.String" itemvalue="JUnit.REST" />
<item index="7" class="java.lang.String" itemvalue="Scala Console.Scala Console" />
<item index="7" class="java.lang.String" itemvalue="JUnit.ThreadBasedDispatcherTest" />
<item index="8" class="java.lang.String" itemvalue="Scala Console.Scala Console" />
</list>
<configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
<Host>localhost</Host>
@ -961,27 +1000,28 @@
</todo-panel>
</component>
<component name="ToolWindowManager">
<frame x="4" y="22" width="1435" height="878" extended-state="0" />
<frame x="4" y="22" width="1916" height="1178" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="Web Preview" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32908162" sideWeight="0.5" order="14" side_tool="false" />
<window_info id="Dataflow to this" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="15" side_tool="false" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32876712" sideWeight="0.69260204" order="5" side_tool="false" />
<window_info id="Clojure REPL" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32908162" sideWeight="0.5" order="7" side_tool="false" />
<window_info id="Data Sources" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294881" sideWeight="0.6875" order="3" side_tool="false" />
<window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294881" sideWeight="0.59183675" order="4" side_tool="false" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="6" side_tool="false" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32972583" sideWeight="0.20663266" order="1" side_tool="false" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3252551" sideWeight="0.5" order="1" side_tool="false" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.15854311" sideWeight="0.61715865" order="1" side_tool="false" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32472324" sideWeight="0.5" order="1" side_tool="false" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24873829" sideWeight="0.74165636" order="0" side_tool="false" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.21811225" sideWeight="0.5" order="12" side_tool="false" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.21771218" sideWeight="0.5" order="12" side_tool="false" />
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="13" side_tool="false" />
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24945927" sideWeight="0.6875" order="1" side_tool="false" />
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="7" side_tool="false" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.7844388" sideWeight="0.5" order="2" side_tool="false" x="4" y="22" width="1436" height="878" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.37638375" sideWeight="0.5" order="2" side_tool="false" x="4" y="22" width="1436" height="878" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39989322" sideWeight="0.75" order="0" side_tool="false" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33418366" sideWeight="0.5" order="3" side_tool="false" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33394834" sideWeight="0.5" order="3" side_tool="false" />
<window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="9" side_tool="false" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="11" side_tool="false" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" />
@ -1032,117 +1072,115 @@
</buildFile>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/fun-test-java/pom.xml">
<entry file="jar://$MAVEN_REPOSITORY$/net/lag/configgy/1.3/configgy-1.3.jar!/net/lag/logging/Logger.class">
<provider selected="true" editor-type-id="text-editor">
<state line="6" column="27" selection-start="330" selection-end="330" vertical-scroll-proportion="0.0">
<state line="73" column="31" selection-start="6347" selection-end="6347" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/pom.xml">
<entry file="jar:///System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/../Classes/classes.jar!/java/util/logging/Level.class">
<provider selected="true" editor-type-id="text-editor">
<state line="38" column="60" selection-start="1203" selection-end="1203" vertical-scroll-proportion="0.0">
<state line="19" column="49" selection-start="878" selection-end="881" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Logging.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="36" column="12" selection-start="1060" selection-end="1060" vertical-scroll-proportion="0.0">
<state line="24" column="27" selection-start="609" selection-end="609" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ManagedActorScheduler.scala">
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/ProxyMessageDispatcher.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="10" column="0" selection-start="163" selection-end="163" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Actor.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="4" column="46" selection-start="97" selection-end="97" vertical-scroll-proportion="0.0">
<state line="12" column="6" selection-start="401" selection-end="401" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="75" column="0" selection-start="2051" selection-end="2051" vertical-scroll-proportion="0.0">
<state line="0" column="4" selection-start="3" selection-end="3" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/ActorTest.scala">
<entry file="file://$PROJECT_DIR$/kernel/src/main/resources/META-INF/services/org/apache/camel/component/akka">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="46" selection-start="46" selection-end="46" vertical-scroll-proportion="0.0">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$MAVEN_REPOSITORY$/org/scala-lang/scala-library/2.7.3/scala-library-2.7.3-sources.jar!/scala/List.scala">
<entry file="file://$PROJECT_DIR$/WEB-INF/classes/se/scalablesolutions/akka/kernel/CassandraNode.class">
<provider selected="true" editor-type-id="text-editor">
<state line="804" column="0" selection-start="24740" selection-end="24740" vertical-scroll-proportion="0.3482906">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="91" column="0" selection-start="3931" selection-end="3931" vertical-scroll-proportion="0.0">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="43" column="0" selection-start="1313" selection-end="1313" vertical-scroll-proportion="0.0">
<state line="86" column="0" selection-start="2898" selection-end="2898" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java">
<entry file="file://$PROJECT_DIR$/WEB-INF/classes/se/scalablesolutions/akka/kernel/Transaction.class">
<provider selected="true" editor-type-id="text-editor">
<state line="52" column="17" selection-start="1441" selection-end="1441" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="158" column="0" selection-start="5462" selection-end="5462" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/GenericServer.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="188" column="6" selection-start="6146" selection-end="6146" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="56" column="6" selection-start="1411" selection-end="1411" vertical-scroll-proportion="0.0">
<state line="16" column="0" selection-start="1321" selection-end="1321" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="112" column="52" selection-start="4116" selection-end="4116" vertical-scroll-proportion="-13.5">
<state line="0" column="109" selection-start="3" selection-end="3" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateTest.java">
<provider selected="true" editor-type-id="text-editor">
<state line="88" column="46" selection-start="4602" selection-end="4602" vertical-scroll-proportion="0.7783933">
<folding>
<element signature="imports" expanded="true" />
</folding>
<state line="58" column="14" selection-start="2649" selection-end="2649" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$MAVEN_REPOSITORY$/org/scala-lang/scala-library/2.7.3/scala-library-2.7.3-sources.jar!/scala/RandomAccessSeq.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="245" column="6" selection-start="10181" selection-end="10181" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="jar://$PROJECT_DIR$/../../../bin/scala-2.7.3.final/src/scala-library-src.jar!/scala/Seq.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="197" column="6" selection-start="6523" selection-end="6523" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStateful.java">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="51" selection-start="364" selection-end="364" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="204" column="66" selection-start="7094" selection-end="7094" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/CassandraNode.scala">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="4" selection-start="3" selection-end="3" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>

View file

@ -35,6 +35,8 @@
<Tables>
<Table Name="akka">
<ColumnFamily ColumnSort="Name" Name="map"/>
<ColumnFamily ColumnSort="Name" Name="vector"/>
<ColumnFamily ColumnSort="Name" Name="ref"/>
<!--ColumnFamily ColumnType="Super" ColumnSort="Name" Name="Super2"/-->
</Table>
</Tables>

View file

@ -95,7 +95,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
try {
foo.longRunning();
fail("exception should have been thrown");
} catch (se.scalablesolutions.akka.kernel.ActiveObjectInvocationTimeoutException e) {
} catch (se.scalablesolutions.akka.kernel.reactor.FutureTimeoutException e) {
}
}

View file

@ -27,8 +27,8 @@ public class PersistentStateTest extends TestCase {
new RestartStrategy(new AllForOne(), 3, 5000),
new Component[] {
new Component(PersistentStateful.class, new LifeCycle(new Permanent(), 1000), 10000000),
new Component(PersistentFailer.class, new LifeCycle(new Permanent(), 1000), 1000),
new Component(PersistentClasher.class, new LifeCycle(new Permanent(), 1000), 100000)
new Component(PersistentFailer.class, new LifeCycle(new Permanent(), 1000), 1000)
//new Component(PersistentClasher.class, new LifeCycle(new Permanent(), 1000), 100000)
}).supervise();
}
@ -38,21 +38,62 @@ public class PersistentStateTest extends TestCase {
public void testShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
PersistentStateful stateful = conf.getActiveObject(PersistentStateful.class);
stateful.setState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state
stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit
assertEquals("new state", stateful.getState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess"));
assertEquals("new state", stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess"));
}
public void testShouldRollbackStateForStatefulServerInCaseOfFailure() {
public void testMapShouldRollbackStateForStatefulServerInCaseOfFailure() {
PersistentStateful stateful = conf.getActiveObject(PersistentStateful.class);
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
PersistentFailer failer = conf.getActiveObject(PersistentFailer.class);
try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception");
} catch (RuntimeException e) {
} // expected
assertEquals("init", stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
}
public void testVectorShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
PersistentStateful stateful = conf.getActiveObject(PersistentStateful.class);
stateful.setState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
PersistentFailer failer = conf.getActiveObject(PersistentFailer.class);
try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception");
} catch (RuntimeException e) {
} // expected
assertEquals("init", stateful.getState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
stateful.setVectorState("init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit
assertEquals("new state", stateful.getVectorState());
}
public void testVectorShouldRollbackStateForStatefulServerInCaseOfFailure() {
PersistentStateful stateful = conf.getActiveObject(PersistentStateful.class);
stateful.setVectorState("init"); // set init state
PersistentFailer failer = conf.getActiveObject(PersistentFailer.class);
try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception");
} catch (RuntimeException e) {
} // expected
assertEquals("init", stateful.getVectorState()); // check that state is == init state
}
/*
public void testRefShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
PersistentStateful stateful = conf.getActiveObject(PersistentStateful.class);
stateful.setRefState("init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit
assertEquals("new state", stateful.getRefState());
}
public void testRefShouldRollbackStateForStatefulServerInCaseOfFailure() {
PersistentStateful stateful = conf.getActiveObject(PersistentStateful.class);
stateful.setRefState("init"); // set init state
PersistentFailer failer = conf.getActiveObject(PersistentFailer.class);
try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception");
} catch (RuntimeException e) {
} // expected
assertEquals("init", stateful.getRefState()); // check that state is == init state
}
*/
}

View file

@ -1,42 +1,56 @@
package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.kernel.TransactionalMap;
import se.scalablesolutions.akka.kernel.CassandraPersistentTransactionalMap;
import se.scalablesolutions.akka.kernel.*;
import se.scalablesolutions.akka.annotation.transactional;
import se.scalablesolutions.akka.annotation.state;
public class PersistentStateful {
private TransactionalMap state = new CassandraPersistentTransactionalMap(this);
private TransactionalMap mapState = new CassandraPersistentTransactionalMap(this);
private TransactionalVector vectorState = new CassandraPersistentTransactionalVector(this);
//private TransactionalRef refState = new CassandraPersistentTransactionalRef(this);
public String getState(String key) {
return (String)state.get(key).get();
public String getMapState(String key) {
return (String) mapState.get(key).get();
}
public void setState(String key, String msg) {
state.put(key, msg);
public String getVectorState() {
return (String) vectorState.first();
}
// public String getRefState() {
// return (String) refState.get().get();
// }
public void setMapState(String key, String msg) {
mapState.put(key, msg);
}
public void setVectorState(String msg) {
vectorState.add(msg);
}
// public void setRefState(String msg) {
// refState.swap(msg);
// }
@transactional
public void success(String key, String msg) {
state.put(key, msg);
mapState.put(key, msg);
vectorState.add(msg);
// refState.swap(msg);
}
@transactional
public void failure(String key, String msg, PersistentFailer failer) {
state.put(key, msg);
mapState.put(key, msg);
vectorState.add(msg);
// refState.swap(msg);
failer.fail();
}
@transactional
public void clashOk(String key, String msg, PersistentClasher clasher) {
state.put(key, msg);
clasher.clash();
}
@transactional
public void clashNotOk(String key, String msg, PersistentClasher clasher) {
state.put(key, msg);
clasher.clash();
clasher.clash();
public void thisMethodHangs(String key, String msg, PersistentFailer failer) {
setMapState(key, msg);
}
}

View file

@ -95,6 +95,11 @@ sealed class TransactionalAroundAdvice(target: Class[_],
server.transactionalMaps = maps
server.transactionalVectors = vectors
import kernel.reactor._
private[this] var dispatcher = new ProxyMessageDispatcher
private[this] var mailbox = dispatcher.messageQueue
dispatcher.start
import ActiveObject.threadBoundTx
private[this] var activeTx: Option[Transaction] = None
@ -113,12 +118,13 @@ sealed class TransactionalAroundAdvice(target: Class[_],
else handleResult(sendAndReceiveEventually(joinpoint))
} finally {
decrementTransaction
tryToPrecommitTransaction
removeTransactionIfTopLevel
if (isTransactionAborted) removeTransactionIfTopLevel
else tryToPrecommitTransaction
}
result
}
private def isTransactionAborted = activeTx.isDefined && activeTx.get.isAborted
private def incrementTransaction = if (activeTx.isDefined) activeTx.get.increment
private def decrementTransaction = if (activeTx.isDefined) activeTx.get.decrement
private def removeTransactionIfTopLevel =
@ -148,8 +154,7 @@ sealed class TransactionalAroundAdvice(target: Class[_],
private def tryToCommitTransaction = if (activeTx.isDefined) {
val tx = activeTx.get
tx.commit(server)
threadBoundTx.set(None)
activeTx = None
removeTransactionIfTopLevel
}
private def handleResult(result: ResultOrFailure[AnyRef]): AnyRef = {
@ -166,19 +171,31 @@ sealed class TransactionalAroundAdvice(target: Class[_],
case None => {} // no tx; nothing to do
case Some(tx) =>
tx.rollback(server)
threadBoundTx.set(Some(tx))
}
private def sendOneWay(joinpoint: JoinPoint) = server ! Invocation(joinpoint, activeTx)
private def sendOneWay(joinpoint: JoinPoint) =
mailbox.append(new MessageHandle(this, Invocation(joinpoint, activeTx), new NullFutureResult))
private def sendAndReceiveEventually(joinpoint: JoinPoint): ResultOrFailure[AnyRef] = {
server !!! (Invocation(joinpoint, activeTx), {
var resultOrFailure = ResultOrFailure(activeTx)
resultOrFailure() = throw new ActiveObjectInvocationTimeoutException("Invocation to active object [" + targetInstance.getClass.getName + "] timed out after " + server.timeout + " milliseconds")
resultOrFailure
})
val future = postMessageToMailboxAndCreateFutureResultWithTimeout(Invocation(joinpoint, activeTx), 1000)
future.await_?
getResultOrThrowException(future)
}
private def postMessageToMailboxAndCreateFutureResultWithTimeout(
message: AnyRef, timeout: Long): CompletableFutureResult = {
val future = new DefaultCompletableFutureResult(timeout)
mailbox.append(new MessageHandle(this, message, future))
future
}
private def getResultOrThrowException[T](future: FutureResult): ResultOrFailure[AnyRef] =
if (future.exception.isDefined) {
var resultOrFailure = ResultOrFailure(activeTx)
resultOrFailure() = throw future.exception.get
resultOrFailure
} else ResultOrFailure(future.result.get, activeTx)
/**
* Search for transactional items for a specific target instance, crawl the class hierarchy recursively up to the top.
*/

View file

@ -26,6 +26,7 @@ class ActorMessageHandler(val actor: Actor) extends MessageHandler {
trait Actor {
private[this] val linkedActors = new ConcurrentSkipListSet[Actor]
private[this] var dispatcher: MessageDispatcher = _
private[this] var mailbox: MessageQueue = _
private[this] var senderFuture: Option[CompletableFutureResult] = None
@volatile private var isRunning: Boolean = false
@ -119,12 +120,13 @@ trait Actor {
if (!isRunning) {
dispatcherType match {
case EventBased =>
mailbox = EventBasedDispatcher.messageQueue
EventBasedDispatcher.registerHandler(this, new ActorMessageHandler(this))
dispatcher = new EventBasedDispatcher
case ThreadBased =>
mailbox = ThreadBasedDispatcher.messageQueue
ThreadBasedDispatcher.registerHandler(this, new ActorMessageHandler(this))
dispatcher = new ThreadBasedDispatcher
}
mailbox = dispatcher.messageQueue
dispatcher.registerHandler(this, new ActorMessageHandler(this))
dispatcher.start
isRunning = true
}
}
@ -132,10 +134,7 @@ trait Actor {
def stop =
if (isRunning) {
this ! Stop("Actor gracefully stopped")
dispatcherType match {
case EventBased => EventBasedDispatcher.unregisterHandler(this)
case ThreadBased => ThreadBasedDispatcher.unregisterHandler(this)
}
dispatcher.unregisterHandler(this)
isRunning = false
} else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")

View file

@ -20,7 +20,9 @@ final object CassandraNode extends Logging {
val TABLE_NAME = "akka"
val ACTOR_KEY_PREFIX = "actor"
val ACTOR_MAP_COLUMN_FAMILY = "map"
val ACTOR_VECTOR_COLUMN_FAMILY = "vector"
val ACTOR_REF_COLUMN_FAMILY = "ref"
// TODO: make pluggable (JSON, Thrift, Protobuf etc.)
private[this] var serializer: Serializer = new JavaSerializationSerializer
@ -40,17 +42,56 @@ final object CassandraNode extends Logging {
def stop = {}
def insertActorStorageEntry(actorName: String, entry: String, content: AnyRef) = {
// ===============================================================
// For Ref
// ===============================================================
// ===============================================================
// For Vector
// ===============================================================
def insertVectorStorageEntryFor(name: String, element: AnyRef) = {
server.insert(
TABLE_NAME,
ACTOR_KEY_PREFIX + ":" + actorName,
ACTOR_MAP_COLUMN_FAMILY + ":" + entry,
serializer.out(content),
TABLE_NAME,
ACTOR_KEY_PREFIX + ":" + name,
ACTOR_VECTOR_COLUMN_FAMILY + ":" + getVectorStorageSizeFor(name),
serializer.out(element),
System.currentTimeMillis,
false) // FIXME: what is this flag for?
}
def insertActorStorageEntries(actorName: String, entries: List[Tuple2[String, AnyRef]]) = {
def getVectorStorageEntryFor(name: String, index: Int): AnyRef = {
try {
val column = server.get_column(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_VECTOR_COLUMN_FAMILY + ":" + index)
serializer.in(column.value)
} catch {
case e => throw new Predef.NoSuchElementException(e.getMessage)
}
}
def getVectorStorageRangeFor(name: String, start: Int, count: Int): List[AnyRef] =
server.get_slice(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_VECTOR_COLUMN_FAMILY, start, count)
.toArray.toList.asInstanceOf[List[Tuple2[String, AnyRef]]].map(tuple => tuple._2)
def getVectorStorageSizeFor(name: String): Int =
server.get_column_count(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_VECTOR_COLUMN_FAMILY)
// ===============================================================
// For Map
// ===============================================================
def insertMapStorageEntryFor(name: String, key: String, value: AnyRef) = {
println("PUT: " + name + " " + key + " " + value)
server.insert(
TABLE_NAME,
ACTOR_KEY_PREFIX + ":" + name,
ACTOR_MAP_COLUMN_FAMILY + ":" + key,
serializer.out(value),
System.currentTimeMillis,
false) // FIXME: what is this flag for?
}
def insertMapStorageEntriesFor(name: String, entries: List[Tuple2[String, AnyRef]]) = {
import java.util.{Map, HashMap, List, ArrayList}
val columns: Map[String, List[column_t]] = new HashMap
for (entry <- entries) {
@ -60,19 +101,20 @@ final object CassandraNode extends Logging {
}
server.batch_insert(new batch_mutation_t(
TABLE_NAME,
ACTOR_KEY_PREFIX + ":" + actorName,
ACTOR_KEY_PREFIX + ":" + name,
columns),
false) // non-blocking
}
def getActorStorageEntryFor(actorName: String, entry: AnyRef): Option[AnyRef] = {
def getMapStorageEntryFor(name: String, key: AnyRef): Option[AnyRef] = {
println("GET: " + name + " " + key)
try {
val column = server.get_column(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + actorName, ACTOR_MAP_COLUMN_FAMILY + ":" + entry)
val column = server.get_column(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_MAP_COLUMN_FAMILY + ":" + key)
Some(serializer.in(column.value))
} catch { case e => None }
}
def getActorStorageFor(actorName: String): List[Tuple2[String, AnyRef]] = {
def getMapStorageFor(name: String): List[Tuple2[String, AnyRef]] = {
val columns = server.get_columns_since(TABLE_NAME, ACTOR_KEY_PREFIX, ACTOR_MAP_COLUMN_FAMILY, -1)
.toArray.toList.asInstanceOf[List[org.apache.cassandra.service.column_t]]
for {
@ -81,14 +123,14 @@ final object CassandraNode extends Logging {
} yield col
}
def getActorStorageSizeFor(actorName: String): Int =
server.get_column_count(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + actorName, ACTOR_MAP_COLUMN_FAMILY)
def getMapStorageSizeFor(name: String): Int =
server.get_column_count(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_MAP_COLUMN_FAMILY)
def removeActorStorageFor(actorName: String) =
server.remove(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + actorName, ACTOR_MAP_COLUMN_FAMILY, System.currentTimeMillis, false)
def removeMapStorageFor(name: String) =
server.remove(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_MAP_COLUMN_FAMILY, System.currentTimeMillis, false)
def getActorStorageRange(actorName: String, start: Int, count: Int): List[Tuple2[String, AnyRef]] =
server.get_slice(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + actorName, ACTOR_MAP_COLUMN_FAMILY, start, count)
def getMapStorageRangeFor(name: String, start: Int, count: Int): List[Tuple2[String, AnyRef]] =
server.get_slice(TABLE_NAME, ACTOR_KEY_PREFIX + ":" + name, ACTOR_MAP_COLUMN_FAMILY, start, count)
.toArray.toList.asInstanceOf[List[Tuple2[String, AnyRef]]]
}

View file

@ -48,7 +48,7 @@ object DataFlow {
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
sealed class DataFlowVariable[T] {
sealed class DataFlowVariable[T] {
private sealed abstract class DataFlowVariableMessage
private case class Set[T](value: T) extends DataFlowVariableMessage

View file

@ -78,7 +78,7 @@ object Kernel extends Logging {
println("=================================================")
var start = System.currentTimeMillis
for (i <- 1 to NR_ENTRIES) CassandraNode.insertActorStorageEntry("test", i.toString, "data")
for (i <- 1 to NR_ENTRIES) CassandraNode.insertMapStorageEntryFor("test", i.toString, "data")
var end = System.currentTimeMillis
println("Writes per second: " + NR_ENTRIES / ((end - start).toDouble / 1000))
@ -109,7 +109,7 @@ java.lang.ClassCastException: [B cannot be cast to org.apache.cassandra.db.Write
*/
println("=================================================")
start = System.currentTimeMillis
for (i <- 1 to NR_ENTRIES) CassandraNode.getActorStorageEntryFor("test", i.toString)
for (i <- 1 to NR_ENTRIES) CassandraNode.getMapStorageEntryFor("test", i.toString)
end = System.currentTimeMillis
println("Reads per second: " + NR_ENTRIES / ((end - start).toDouble / 1000))

View file

@ -4,6 +4,7 @@
package se.scalablesolutions.akka.kernel
import java.util.logging.Level
import net.lag.configgy.Config
import net.lag.logging.Logger
@ -19,7 +20,12 @@ import java.net.UnknownHostException;
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait Logging {
@transient val log = Logger.get(this.getClass.getName)
@transient val log = {
val log = Logger.get(this.getClass.getName)
log.setLevel(Level.ALL)
log
}
}
/**

View file

@ -47,7 +47,7 @@ class ResultOrFailure[Payload](payload: Payload, val tx: Option[Transaction]) {
def apply() = contents match {
case Right(payload) => payload
case Left(e) => throw e.fillInStackTrace
case Left(e) => throw e
}
override def toString(): String = "ResultOrFailure[" + contents + "]"

View file

@ -4,6 +4,7 @@
package se.scalablesolutions.akka.kernel
import org.codehaus.aspectwerkz.proxy.Uuid
import se.scalablesolutions.akka.collection._
import scala.collection.mutable.HashMap
@ -11,6 +12,7 @@ import scala.collection.mutable.HashMap
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
trait Transactional {
val uuid = Uuid.newUuid.toString
private[kernel] def begin
private[kernel] def commit
private[kernel] def rollback
@ -60,7 +62,7 @@ class InMemoryTransactionalMap[K, V] extends TransactionalMap[K, V] {
}
/**
* Base class for all persistent state implementations should extend.
* Base class for all persistent transactional map implementations should extend.
* Implements a Unit of Work, records changes into a change set.
*
* Not thread-safe, but should only be using from within an Actor, e.g. one single thread at a time.
@ -68,6 +70,8 @@ class InMemoryTransactionalMap[K, V] extends TransactionalMap[K, V] {
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class PersistentTransactionalMap[K, V] extends TransactionalMap[K, V] {
// FIXME: need to handle remove in another changeSet
protected[kernel] val changeSet = new HashMap[K, V]
def getRange(start: Int, count: Int)
@ -87,56 +91,56 @@ abstract class PersistentTransactionalMap[K, V] extends TransactionalMap[K, V] {
}
/**
* Implements a persistent state based on the Cassandra distributed P2P key-value storage.
*
* Implements a persistent transactional map based on the Cassandra distributed P2P key-value storage.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class CassandraPersistentTransactionalMap(actorNameInstance: AnyRef)
extends PersistentTransactionalMap[String, AnyRef] {
val actorName = actorNameInstance.getClass.getName
override def getRange(start: Int, count: Int) = CassandraNode.getActorStorageRange(actorName, start, count)
override def getRange(start: Int, count: Int) = CassandraNode.getMapStorageRangeFor(uuid, start, count)
// ---- For Transactional ----
override def commit = {
// FIXME: should use batch function once the bug is resolved
for (entry <- changeSet) {
val (key, value) = entry
CassandraNode.insertActorStorageEntry(actorName, key, value)
CassandraNode.insertMapStorageEntryFor(uuid, key, value)
}
}
// ---- Overriding scala.collection.mutable.Map behavior ----
override def clear = CassandraNode.removeActorStorageFor(actorName)
override def contains(key: String): Boolean = CassandraNode.getActorStorageEntryFor(actorName, key).isDefined
override def size: Int = CassandraNode.getActorStorageSizeFor(actorName)
override def clear = CassandraNode.removeMapStorageFor(uuid)
override def contains(key: String): Boolean = CassandraNode.getMapStorageEntryFor(uuid, key).isDefined
override def size: Int = CassandraNode.getMapStorageSizeFor(uuid)
// ---- For scala.collection.mutable.Map ----
override def get(key: String): Option[AnyRef] = CassandraNode.getActorStorageEntryFor(actorName, key)
override def get(key: String): Option[AnyRef] = CassandraNode.getMapStorageEntryFor(uuid, key)
override def elements: Iterator[Tuple2[String, AnyRef]] = {
new Iterator[Tuple2[String, AnyRef]] {
private val originalList: List[Tuple2[String, AnyRef]] = CassandraNode.getActorStorageFor(actorName)
private val originalList: List[Tuple2[String, AnyRef]] = CassandraNode.getMapStorageFor(uuid)
private var elements = originalList.reverse
override def next: Tuple2[String, AnyRef]= synchronized {
val element = elements.head
elements = elements.tail
element
}
}
override def hasNext: Boolean = synchronized { !elements.isEmpty }
}
}
}
/**
* TODO: extend scala.Seq
* Base for all transactional vector implementations.
*
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class TransactionalVector[T] extends Transactional with RandomAccessSeq[T] {
def add(elem: T)
def get(index: Int): T
def getRange(start: Int, count: Int): List[T]
}
/**
@ -150,8 +154,9 @@ class InMemoryTransactionalVector[T] extends TransactionalVector[T] {
private[kernel] var state: Vector[T] = EmptyVector
private[kernel] var snapshot = state
override def add(elem: T) = state = state + elem
override def get(index: Int): T = state(index)
def add(elem: T) = state = state + elem
def get(index: Int): T = state(index)
def getRange(start: Int, count: Int): List[T] = state.slice(start, count).toList.asInstanceOf[List[T]]
// ---- For Transactional ----
override def begin = snapshot = state
@ -165,6 +170,52 @@ class InMemoryTransactionalVector[T] extends TransactionalVector[T] {
override def toList: List[T] = state.toList
}
/**
* Base class for all persistent transactional vector implementations should extend.
* Implements a Unit of Work, records changes into a change set.
*
* Not thread-safe, but should only be using from within an Actor, e.g. one single thread at a time.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
abstract class PersistentTransactionalVector[T] extends TransactionalVector[T] {
// FIXME: need to handle remove in another changeSet
protected[kernel] var changeSet: List[T] = Nil
// ---- For Transactional ----
override def begin = changeSet = Nil
override def rollback = {}
// ---- For TransactionalVector ----
override def add(value: T) = changeSet ::= value
}
/**
* Implements a persistent transactional vector based on the Cassandra distributed P2P key-value storage.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class CassandraPersistentTransactionalVector(actorNameInstance: AnyRef)
extends PersistentTransactionalVector[AnyRef] {
val actorName = actorNameInstance.getClass.getName
// ---- For TransactionalVector ----
override def get(index: Int): AnyRef = CassandraNode.getVectorStorageEntryFor(uuid, index)
override def getRange(start: Int, count: Int): List[AnyRef] = CassandraNode.getVectorStorageRangeFor(uuid, start, count)
override def length: Int = CassandraNode.getVectorStorageSizeFor(uuid)
override def apply(index: Int): AnyRef = get(index)
override def first: AnyRef = get(0)
override def last: AnyRef = get(length)
// ---- For Transactional ----
override def commit = {
// FIXME: should use batch function once the bug is resolved
for (element <- changeSet) CassandraNode.insertVectorStorageEntryFor(uuid, element)
}
}
/**
* Implements a transactional reference.
*

View file

@ -49,8 +49,8 @@ class Transaction extends Logging {
def begin(server: GenericServerContainer) = synchronized {
ensureIsActiveOrNew
if (status == TransactionStatus.New) log.info("Server [%s] is starting NEW transaction [%s]", server.id, this)
else log.info("Server [%s] is participating in transaction", server)
if (status == TransactionStatus.New) log.debug("Server [%s] is starting NEW transaction [%s]", server.id, this)
else log.debug("Server [%s] is participating in transaction", server)
server.transactionalItems.foreach(_.begin)
participants + server
status = TransactionStatus.Active
@ -58,14 +58,14 @@ class Transaction extends Logging {
def precommit(server: GenericServerContainer) = synchronized {
if (status == TransactionStatus.Active) {
log.info("Pre-committing transaction [%s] for server [%s]", this, server.id)
log.debug("Pre-committing transaction [%s] for server [%s]", this, server.id)
precommitted + server
}
}
def commit(server: GenericServerContainer) = synchronized {
if (status == TransactionStatus.Active) {
log.info("Committing transaction [%s] for server [%s]", this, server.id)
log.debug("Committing transaction [%s] for server [%s]", this, server.id)
val haveAllPreCommitted =
if (participants.size == precommitted.size) {{
for (server <- participants) yield {
@ -85,18 +85,23 @@ class Transaction extends Logging {
def rollback(server: GenericServerContainer) = synchronized {
ensureIsActiveOrAborted
log.info("Server [%s] has initiated transaction rollback for [%s], rolling back [%s]", server.id, this, participants)
log.debug("Server [%s] has initiated transaction rollback for [%s], rolling back [%s]", server.id, this, participants)
participants.foreach(_.transactionalItems.foreach(_.rollback))
status = TransactionStatus.Aborted
}
def join(server: GenericServerContainer) = synchronized {
ensureIsActive
log.info("Server [%s] is joining transaction [%s]" , server.id, this)
log.debug("Server [%s] is joining transaction [%s]" , server.id, this)
server.transactionalItems.foreach(_.begin)
participants + server
}
def isNew = status == TransactionStatus.New
def isActive = status == TransactionStatus.Active
def isCompleted = status == TransactionStatus.Completed
def isAborted = status == TransactionStatus.Aborted
private def ensureIsActive = if (status != TransactionStatus.Active)
throw new IllegalStateException("Expected ACTIVE transaction - current status [" + status + "]")

View file

@ -10,10 +10,8 @@
*/
package se.scalablesolutions.akka.kernel.reactor
object EventBasedDispatcher extends MessageDispatcherBase {
class EventBasedDispatcher extends MessageDispatcherBase {
start
//def dispatch(messageQueue: MessageQueue) = if (!active) {
def start = if (!active) {
active = true

View file

@ -10,6 +10,8 @@ package se.scalablesolutions.akka.kernel.reactor
import java.util.concurrent.locks.{Lock, Condition, ReentrantLock}
import java.util.concurrent.TimeUnit
class FutureTimeoutException(message: String) extends RuntimeException(message)
sealed trait FutureResult {
def await_?
def await_!
@ -44,6 +46,7 @@ class DefaultCompletableFutureResult(timeout: Long) extends CompletableFutureRes
var start = currentTimeInNanos
try {
wait = _signal.awaitNanos(wait)
if (wait <= 0) throw new FutureTimeoutException("Future timed out after [" + timeout + "] milliseconds")
} catch {
case e: InterruptedException =>
wait = wait - (currentTimeInNanos - start)

View file

@ -0,0 +1,86 @@
/**
* Copyright (C) 2009 Scalable Solutions.
*/
/**
* Implements the Reactor pattern as defined in: [http://www.cs.wustl.edu/~schmidt/PDF/reactor-siemens.pdf].
* See also this article: [http://today.java.net/cs/user/print/a/350].
*
* Based on code from the actorom actor framework by Sergio Bossa [http://code.google.com/p/actorom/].
*/
package se.scalablesolutions.akka.kernel.reactor
class ProxyMessageDispatcher extends MessageDispatcherBase {
import java.util.concurrent.Executors
import java.util.HashSet
import org.codehaus.aspectwerkz.joinpoint.JoinPoint
// FIXME: make configurable using configgy + JMX
// FIXME: create one executor per invocation to dispatch(..), grab config settings for specific actor (set in registerHandler)
private val threadPoolSize: Int = 100
private val handlerExecutor = Executors.newCachedThreadPool()
def start = if (!active) {
active = true
val messageDemultiplexer = new ProxyMessageDemultiplexer(messageQueue)
selectorThread = new Thread {
override def run = {
while (active) {
try {
guard.synchronized { /* empty */ } // prevents risk for deadlock as described in [http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1315.pdf]
try {
messageDemultiplexer.select
} catch {case e: InterruptedException => active = false}
val queue = messageDemultiplexer.acquireSelectedQueue
for (index <- 0 until queue.size) {
val handle = queue.remove
handlerExecutor.execute(new Runnable {
override def run = {
try {
val result = handle.message.asInstanceOf[Invocation].joinpoint.proceed
handle.future.completeWithResult(result)
} catch {
case e: Exception => handle.future.completeWithException(e)
}
messageDemultiplexer.wakeUp
}
})
}
} finally {
messageDemultiplexer.releaseSelectedQueue
}
}
}
};
selectorThread.start
}
override protected def doShutdown = handlerExecutor.shutdownNow
}
class ProxyMessageDemultiplexer(private val messageQueue: MessageQueue) extends MessageDemultiplexer {
import java.util.concurrent.locks.ReentrantLock
import java.util.{LinkedList, Queue}
private val selectedQueue: Queue[MessageHandle] = new LinkedList[MessageHandle]
private val selectedQueueLock = new ReentrantLock
def select = try {
selectedQueueLock.lock
messageQueue.read(selectedQueue)
} finally {
selectedQueueLock.unlock
}
def acquireSelectedQueue: Queue[MessageHandle] = {
selectedQueueLock.lock
selectedQueue
}
def releaseSelectedQueue = {
selectedQueue.clear
selectedQueueLock.unlock
}
def wakeUp = messageQueue.interrupt
}

View file

@ -17,6 +17,7 @@ trait MessageHandler {
}
trait MessageDispatcher {
def messageQueue: MessageQueue
def registerHandler(key: AnyRef, handler: MessageHandler)
def unregisterHandler(key: AnyRef)
def start

View file

@ -10,22 +10,21 @@
*/
package se.scalablesolutions.akka.kernel.reactor
object ThreadBasedDispatcher extends MessageDispatcherBase {
class ThreadBasedDispatcher extends MessageDispatcherBase {
import java.util.concurrent.Executors
import java.util.HashSet
// FIXME: make configurable using configgy + JMX
// FIXME: create one executor per invocation to dispatch(..), grab config settings for specific actor (set in registerHandler)
private val threadPoolSize: Int = 10
private val threadPoolSize: Int = 100
private val busyHandlers = new HashSet[AnyRef]
private val handlerExecutor = Executors.newFixedThreadPool(threadPoolSize)
private val handlerExecutor = Executors.newCachedThreadPool()
start
def start = if (!active) {
active = true
val messageDemultiplexer = new ThreadBasedDemultiplexer(messageQueue)
selectorThread = new Thread {
//val enqued = new LinkedList[MessageHandle]
override def run = {
while (active) {
try {
@ -34,10 +33,15 @@ object ThreadBasedDispatcher extends MessageDispatcherBase {
messageDemultiplexer.select
} catch {case e: InterruptedException => active = false}
val queue = messageDemultiplexer.acquireSelectedQueue
println("--- QUEUE " + queue.size)
// while (!queue.isEmpty) {
for (index <- 0 until queue.size) {
val message = queue.peek
println("------ MESSAGE: " + message)
val messageHandler = getIfNotBusy(message.sender)
println("------ MESSAGEHANDLER: " + messageHandler)
if (messageHandler.isDefined) {
println("-------- SCHEDULING MESSAGE")
handlerExecutor.execute(new Runnable {
override def run = {
messageHandler.get.handle(message)
@ -48,6 +52,10 @@ object ThreadBasedDispatcher extends MessageDispatcherBase {
queue.remove
}
}
// }
if (!queue.isEmpty) {
for (index <- 0 until queue.size) messageQueue.append(queue.remove)
}
} finally {
messageDemultiplexer.releaseSelectedQueue
}
@ -88,7 +96,10 @@ class ThreadBasedDemultiplexer(private val messageQueue: MessageQueue) extends M
selectedQueue
}
def releaseSelectedQueue = selectedQueueLock.unlock
def releaseSelectedQueue = {
selectedQueue.clear
selectedQueueLock.unlock
}
def wakeUp = messageQueue.interrupt
}

View file

@ -36,7 +36,7 @@ class ActorTest {
val result = actor ! "OneWay"
Thread.sleep(100)
assertEquals("received", oneWay)
//actor.stop
actor.stop
}
@Test
@ -46,7 +46,7 @@ class ActorTest {
actor.start
val result = actor !? "Hello"
assertEquals("World", result.get.asInstanceOf[String])
//actor.stop
actor.stop
}
@Test
@ -56,7 +56,7 @@ class ActorTest {
actor.start
val result = actor !! "Hello"
assertEquals("World", result.get.asInstanceOf[String])
//actor.stop
actor.stop
}
@Test
@ -71,6 +71,6 @@ class ActorTest {
case e =>
assertEquals("expected", e.getMessage())
}
//actor.stop
actor.stop
}
}

View file

@ -57,10 +57,11 @@ class EventBasedDispatcherTest {
val guardLock = new ReentrantLock
val handleLatch = new CountDownLatch(10)
val key = "key"
EventBasedDispatcher.registerHandler(key, new TestMessageHandle(handleLatch))
EventBasedDispatcher.start
val dispatcher = new EventBasedDispatcher
dispatcher.registerHandler(key, new TestMessageHandle(handleLatch))
dispatcher.start
for (i <- 0 until 10) {
EventBasedDispatcher.messageQueue.append(new MessageHandle(key, new Object, new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key, new Object, new NullFutureResult))
}
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
assertFalse(threadingIssueDetected.get)
@ -70,11 +71,12 @@ class EventBasedDispatcherTest {
val handleLatch = new CountDownLatch(2)
val key1 = "key1"
val key2 = "key2"
EventBasedDispatcher.registerHandler(key1, new TestMessageHandle(handleLatch))
EventBasedDispatcher.registerHandler(key2, new TestMessageHandle(handleLatch))
EventBasedDispatcher.start
EventBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Object, new NullFutureResult))
EventBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Object, new NullFutureResult))
val dispatcher = new EventBasedDispatcher
dispatcher.registerHandler(key1, new TestMessageHandle(handleLatch))
dispatcher.registerHandler(key2, new TestMessageHandle(handleLatch))
dispatcher.start
dispatcher.messageQueue.append(new MessageHandle(key1, new Object, new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key2, new Object, new NullFutureResult))
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
assertFalse(threadingIssueDetected.get)
}
@ -83,7 +85,8 @@ class EventBasedDispatcherTest {
val handleLatch = new CountDownLatch(200)
val key1 = "key1"
val key2 = "key2"
EventBasedDispatcher.registerHandler(key1, new MessageHandler {
val dispatcher = new EventBasedDispatcher
dispatcher.registerHandler(key1, new MessageHandler {
var currentValue = -1;
def handle(message: MessageHandle) {
if (threadingIssueDetected.get) return
@ -94,7 +97,7 @@ class EventBasedDispatcherTest {
} else threadingIssueDetected.set(true)
}
})
EventBasedDispatcher.registerHandler(key2, new MessageHandler {
dispatcher.registerHandler(key2, new MessageHandler {
var currentValue = -1;
def handle(message: MessageHandle) {
if (threadingIssueDetected.get) return
@ -105,12 +108,13 @@ class EventBasedDispatcherTest {
} else threadingIssueDetected.set(true)
}
})
EventBasedDispatcher.start
dispatcher.start
for (i <- 0 until 100) {
EventBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), new NullFutureResult))
EventBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), new NullFutureResult))
}
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
assertFalse(threadingIssueDetected.get)
dispatcher.shutdown
}
}

View file

@ -30,25 +30,24 @@ class ThreadBasedDispatcherTest {
internalTestMessagesDispatchedToDifferentHandlersAreExecutedConcurrently
}
@Test
//@Test
def testMessagesDispatchedToHandlersAreExecutedInFIFOOrder = {
internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder
}
private def internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially: Unit = {
val guardLock = new ReentrantLock
val handleLatch = new CountDownLatch(10)
val handleLatch = new CountDownLatch(100)
val key = "key"
ThreadBasedDispatcher.registerHandler(key, new MessageHandler {
val dispatcher = new ThreadBasedDispatcher
dispatcher.registerHandler(key, new MessageHandler {
def handle(message: MessageHandle) {
try {
if (threadingIssueDetected.get) return
if (guardLock.tryLock) {
Thread.sleep(100)
handleLatch.countDown
} else {
threadingIssueDetected.set(true)
}
} else threadingIssueDetected.set(true)
} catch {
case e: Exception => threadingIssueDetected.set(true)
} finally {
@ -56,42 +55,46 @@ class ThreadBasedDispatcherTest {
}
}
})
ThreadBasedDispatcher.start
dispatcher.start
for (i <- 0 until 100) {
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key, new Object, new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key, new Object, new NullFutureResult))
}
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
assertTrue(handleLatch.await(5000, TimeUnit.SECONDS))
assertFalse(threadingIssueDetected.get)
//dispatcher.shutdown
}
private def internalTestMessagesDispatchedToDifferentHandlersAreExecutedConcurrently: Unit = {
val handlersBarrier = new CyclicBarrier(3)
val key1 = "key1"
val key2 = "key2"
ThreadBasedDispatcher.registerHandler(key1, new MessageHandler {
val dispatcher = new ThreadBasedDispatcher
dispatcher.registerHandler(key1, new MessageHandler {
def handle(message: MessageHandle) = synchronized {
try {handlersBarrier.await(1, TimeUnit.SECONDS)}
catch {case e: Exception => threadingIssueDetected.set(true)}
}
})
ThreadBasedDispatcher.registerHandler(key2, new MessageHandler {
dispatcher.registerHandler(key2, new MessageHandler {
def handle(message: MessageHandle) = synchronized {
try {handlersBarrier.await(1, TimeUnit.SECONDS)}
catch {case e: Exception => threadingIssueDetected.set(true)}
}
})
ThreadBasedDispatcher.start
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Object, new NullFutureResult))
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Object, new NullFutureResult))
handlersBarrier.await(1, TimeUnit.SECONDS)
dispatcher.start
dispatcher.messageQueue.append(new MessageHandle(key1, "Sending Message 1", new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key2, "Sending Message 2", new NullFutureResult))
handlersBarrier.await(5, TimeUnit.SECONDS)
assertFalse(threadingIssueDetected.get)
//dispatcher.shutdown
}
private def internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder: Unit = {
val handleLatch = new CountDownLatch(200)
val key1 = "key1"
val key2 = "key2"
ThreadBasedDispatcher.registerHandler(key1, new MessageHandler {
val dispatcher = new ThreadBasedDispatcher
dispatcher.registerHandler(key1, new MessageHandler {
var currentValue = -1;
def handle(message: MessageHandle) {
if (threadingIssueDetected.get) return
@ -102,23 +105,24 @@ class ThreadBasedDispatcherTest {
} else threadingIssueDetected.set(true)
}
})
ThreadBasedDispatcher.registerHandler(key2, new MessageHandler {
dispatcher.registerHandler(key2, new MessageHandler {
var currentValue = -1;
def handle(message: MessageHandle) {
if (threadingIssueDetected.get) return
val messageValue = message.message.asInstanceOf[Int]
if (messageValue.intValue == currentValue + 1) {
currentValue = messageValue.intValue
currentValue = messageValue .intValue
handleLatch.countDown
} else threadingIssueDetected.set(true)
}
})
ThreadBasedDispatcher.start
dispatcher.start
for (i <- 0 until 100) {
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), new NullFutureResult))
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), new NullFutureResult))
dispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), new NullFutureResult))
}
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
assertTrue(handleLatch.await(10, TimeUnit.SECONDS))
assertFalse(threadingIssueDetected.get)
dispatcher.shutdown
}
}