complete refactoring of transaction and transactional item management + removed duplicate tx management in ActiveObject
This commit is contained in:
parent
7083737f95
commit
6359920fa4
9 changed files with 393 additions and 517 deletions
317
akka.iws
317
akka.iws
|
|
@ -1,25 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project relativePaths="false" version="4">
|
||||
<component name="BookmarkManager">
|
||||
<editor_bookmark url="file://$PROJECT_DIR$/kernel/src/main/scala/stm/ChangeSet.scala" line="15" description="private[kernel] def +(items: Transactional) = lock..." />
|
||||
<editor_bookmark url="file://$PROJECT_DIR$/kernel/src/main/scala/nio/RequestReply.scala" line="52" description="def newReplyWithException(error: Throwable) = new ..." />
|
||||
<editor_bookmark url="file://$PROJECT_DIR$/kernel/src/main/scala/state/State.scala" line="91" description="trait TransactionalMapGuard[K, V] extends Transact..." />
|
||||
<commander_bookmark type="package" url="file://$PROJECT_DIR$/kernel/src/main/scala/stm" />
|
||||
<commander_bookmark type="package" url="file://$PROJECT_DIR$/kernel/src/main/scala/actor" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" name="Test" comment="">
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStatefulNested.java" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iws" afterPath="$PROJECT_DIR$/akka.iws" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/state/State.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/state/State.scala" />
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.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/stm/Transaction.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/stm/Transaction.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/nio/NettyServer.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/nio/NettyServer.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/actor/ActiveObject.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/actor/ActiveObject.scala" />
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/ThreadBasedDispatcher.scala" afterPath="" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/stm/TransactionManagement.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/stm/TransactionManagement.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/stm/ChangeSet.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/stm/ChangeSet.scala" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/actor/Actor.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/actor/Actor.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="NEW" beforePath="" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java" />
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStatefulNested.java" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iws" afterPath="$PROJECT_DIR$/akka.iws" />
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/kernel/src/main/scala/nio/ProxyServer.scala" afterPath="" />
|
||||
</list>
|
||||
<list name="Default" comment=" # Brief commit desciption here # Full commit description here (comment lines starting with '#' will not be included) " />
|
||||
<ignored path=".idea/workspace.xml" />
|
||||
|
|
@ -105,19 +102,6 @@
|
|||
<option name="CONDITION" value="" />
|
||||
<option name="LOG_MESSAGE" value="" />
|
||||
</breakpoint>
|
||||
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/stm/TransactionManagement.scala" line="61" class="Class at TransactionManagement.scala:61" 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$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java" line="45" class="se.scalablesolutions.akka.api.PersistentNestedStateTest" package="se.scalablesolutions.akka.api">
|
||||
<option name="ENABLED" value="true" />
|
||||
<option name="LOG_ENABLED" value="false" />
|
||||
|
|
@ -131,7 +115,7 @@
|
|||
<option name="CONDITION" value="" />
|
||||
<option name="LOG_MESSAGE" value="" />
|
||||
</breakpoint>
|
||||
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/stm/Transaction.scala" line="68" class="Class at Transaction.scala:68" package="">
|
||||
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/actor/Actor.scala" line="136" class="Class at Actor.scala:136" package="">
|
||||
<option name="ENABLED" value="true" />
|
||||
<option name="LOG_ENABLED" value="false" />
|
||||
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||
|
|
@ -207,55 +191,73 @@
|
|||
<component name="FileColors" enabled="false" enabledForTabs="false" />
|
||||
<component name="FileEditorManager">
|
||||
<leaf>
|
||||
<file leaf-file-name="PersistentNestedStateTest.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java">
|
||||
<file leaf-file-name="ThreadBasedDispatcherTest.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/ThreadBasedDispatcherTest.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="45" column="0" selection-start="1936" selection-end="1936" vertical-scroll-proportion="0.0">
|
||||
<state line="14" column="6" selection-start="483" selection-end="483" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="State.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/state/State.scala">
|
||||
<file leaf-file-name="SupervisorSpec.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/SupervisorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="157" column="86" selection-start="5629" selection-end="5629" vertical-scroll-proportion="0.0">
|
||||
<state line="20" column="6" selection-start="482" selection-end="482" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="TransactionManagement.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/TransactionManagement.scala">
|
||||
<file leaf-file-name="ActorTest.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/ActorTest.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="61" column="0" selection-start="1967" selection-end="1967" vertical-scroll-proportion="0.0">
|
||||
<state line="10" column="6" selection-start="239" selection-end="239" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="Transaction.scala" pinned="false" current="true" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/Transaction.scala">
|
||||
<file leaf-file-name="InMemoryActorSpec.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/InMemoryActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="63" column="33" selection-start="2173" selection-end="2173" vertical-scroll-proportion="0.09836066">
|
||||
<state line="64" column="6" selection-start="1788" selection-end="1788" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="ChangeSet.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/ChangeSet.scala">
|
||||
<file leaf-file-name="PersistentActorSpec.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/PersistentActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="10" column="6" selection-start="252" selection-end="252" vertical-scroll-proportion="0.0">
|
||||
<state line="122" column="6" selection-start="4368" selection-end="4368" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="CassandraNode.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/state/CassandraNode.scala">
|
||||
<file leaf-file-name="InMemNestedStateTest.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="134" column="0" selection-start="4277" selection-end="4277" vertical-scroll-proportion="0.0">
|
||||
<state line="84" column="14" selection-start="4621" selection-end="4621" vertical-scroll-proportion="-20.807692">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="InMemoryStateTest.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="124" column="16" selection-start="6244" selection-end="6244" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="RemoteInMemoryStateTest.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemoteInMemoryStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="115" column="56" selection-start="6049" selection-end="6049" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
|
@ -264,34 +266,16 @@
|
|||
<file leaf-file-name="Actor.scala" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/actor/Actor.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="319" column="0" selection-start="10764" selection-end="10764" vertical-scroll-proportion="0.0">
|
||||
<state line="80" column="26" selection-start="2923" selection-end="2923" 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">
|
||||
<file leaf-file-name="TransactionManagement.scala" pinned="false" current="true" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/TransactionManagement.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="61" column="0" selection-start="1734" selection-end="1734" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="PersistentStatefulNested.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStatefulNested.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="46" column="0" selection-start="1366" selection-end="1366" 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/actor/ActiveObject.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="149" column="12" selection-start="5652" selection-end="5652" vertical-scroll-proportion="0.0">
|
||||
<state line="67" column="0" selection-start="1912" selection-end="1912" vertical-scroll-proportion="0.5885262">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
|
@ -1833,6 +1817,40 @@
|
|||
<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-funtest-java" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="fun-test-java" />
|
||||
<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="test" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="java" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="api" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="ActiveObjectGuiceConfiguratorTest" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ClassTreeNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="akka" />
|
||||
|
|
@ -2218,7 +2236,7 @@
|
|||
<recent name="actor" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager" selected="JUnit.PersistentStateTest">
|
||||
<component name="RunManager" selected="JUnit.PersistentNestedStateTest">
|
||||
<configuration default="true" type="Remote" factoryName="Remote">
|
||||
<option name="USE_SOCKET_TRANSPORT" value="true" />
|
||||
<option name="SERVER_MODE" value="false" />
|
||||
|
|
@ -2459,7 +2477,13 @@
|
|||
<value defaultName="moduleWithDependencies" />
|
||||
</option>
|
||||
<envs />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="64043" />
|
||||
<option name="TRANSPORT" value="0" />
|
||||
<option name="LOCAL" value="true" />
|
||||
</RunnerSettings>
|
||||
<RunnerSettings RunnerId="Run" />
|
||||
<ConfigurationWrapper RunnerId="Debug" />
|
||||
<ConfigurationWrapper RunnerId="Run" />
|
||||
<method>
|
||||
<option name="AntTarget" value="false" />
|
||||
|
|
@ -3049,20 +3073,20 @@
|
|||
<window_info id="Web Preview" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32822478" sideWeight="0.5" order="16" 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="17" 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.32822478" sideWeight="0.5" order="8" side_tool="false" />
|
||||
<window_info id="Clojure REPL" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32749078" sideWeight="0.5" order="8" 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.32749078" 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.21156937" sideWeight="0.13653137" 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.21156937" sideWeight="0.6697417" 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.32380074" 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.2769342" sideWeight="0.22094509" order="0" side_tool="true" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="FLOATING" visible="true" weight="0.21156937" sideWeight="0.4483395" order="0" side_tool="true" x="1628" y="142" width="252" height="1015" />
|
||||
<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.21125461" sideWeight="0.5" order="14" 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="15" 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.32749078" sideWeight="0.5" order="9" side_tool="false" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.8570111" 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.6254613" 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.3997114" 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.44464946" 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="11" side_tool="false" />
|
||||
|
|
@ -3117,118 +3141,107 @@
|
|||
</buildFile>
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<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/PersistentNestedStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="24" column="0" selection-start="870" selection-end="870" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="26" column="53" selection-start="0" selection-end="6014" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStatefulNested.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="17" column="31" selection-start="639" selection-end="639" vertical-scroll-proportion="0.0">
|
||||
<folding>
|
||||
<element signature="imports" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<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="74" column="0" selection-start="1254" selection-end="1901" vertical-scroll-proportion="0.0">
|
||||
<folding>
|
||||
<element signature="imports" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<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="22" column="0" selection-start="572" selection-end="668" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/WEB-INF/classes/se/scalablesolutions/akka/kernel/CassandraPersistentTransactionalMap.class">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<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/state/State.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="157" column="86" selection-start="5629" selection-end="5629" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/ChangeSet.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="10" column="6" selection-start="252" selection-end="252" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/actor/Actor.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="319" column="0" selection-start="10764" selection-end="10764" 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="61" column="0" selection-start="1734" selection-end="1734" vertical-scroll-proportion="0.0">
|
||||
<state line="65" column="14" selection-start="3402" selection-end="3402" vertical-scroll-proportion="0.13596915">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/actor/ActiveObject.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="149" column="12" selection-start="5652" selection-end="5652" vertical-scroll-proportion="0.0">
|
||||
<state line="173" column="19" selection-start="6616" selection-end="6616" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentStatefulNested.java">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemotePersistentStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="46" column="0" selection-start="1366" selection-end="1366" vertical-scroll-proportion="0.0">
|
||||
<state line="93" column="14" selection-start="4355" selection-end="4355" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/state/CassandraNode.scala">
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="134" column="0" selection-start="4277" selection-end="4277" vertical-scroll-proportion="0.0">
|
||||
<state line="91" column="14" selection-start="3056" selection-end="3056" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/PersistentNestedStateTest.java">
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/EventBasedDispatcherTest.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="45" column="0" selection-start="1936" selection-end="1936" vertical-scroll-proportion="0.0">
|
||||
<state line="12" column="6" selection-start="427" selection-end="427" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/ThreadBasedDispatcherTest.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="14" column="6" selection-start="483" selection-end="483" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/SupervisorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="6" selection-start="482" selection-end="482" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/ActorTest.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="10" column="6" selection-start="239" selection-end="239" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/InMemoryActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="64" column="6" selection-start="1788" selection-end="1788" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/PersistentActorSpec.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="122" column="6" selection-start="4368" selection-end="4368" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="84" column="14" selection-start="4621" selection-end="4621" vertical-scroll-proportion="-20.807692">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="124" column="16" selection-start="6244" selection-end="6244" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/RemoteInMemoryStateTest.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="115" column="56" selection-start="6049" selection-end="6049" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/actor/Actor.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="80" column="26" selection-start="2923" selection-end="2923" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/TransactionManagement.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="61" column="0" selection-start="1967" selection-end="1967" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/stm/Transaction.scala">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="63" column="33" selection-start="2173" selection-end="2173" vertical-scroll-proportion="0.09836066">
|
||||
<state line="67" column="0" selection-start="1912" selection-end="1912" vertical-scroll-proportion="0.5885262">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ class ActiveObjectFactory {
|
|||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
object ActiveObject {
|
||||
val MATCH_ALL = "execution(* *.*(..))"
|
||||
val AKKA_CAMEL_ROUTING_SCHEME = "akka"
|
||||
|
||||
def newInstance[T](target: Class[T]): T = newInstance(target, new Dispatcher(target.getName), false)
|
||||
|
|
@ -99,7 +100,7 @@ object ActiveObject {
|
|||
val proxy = Proxy.newInstance(target, false, true)
|
||||
// FIXME switch to weaving in the aspect at compile time
|
||||
proxy.asInstanceOf[Advisable].aw_addAdvice(
|
||||
"execution(* *.*(..))", new TransactionalAroundAdvice(target, proxy, actor, remote))
|
||||
MATCH_ALL, new TransactionalAroundAdvice(target, proxy, actor, remote))
|
||||
proxy.asInstanceOf[T]
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ object ActiveObject {
|
|||
if (remote) NettyClient.connect
|
||||
val proxy = Proxy.newInstance(Array(intf), Array(target), false, true)
|
||||
proxy.asInstanceOf[Advisable].aw_addAdvice(
|
||||
"execution(* *.*(..))", new TransactionalAroundAdvice(intf, target, actor, remote))
|
||||
MATCH_ALL, new TransactionalAroundAdvice(intf, target, actor, remote))
|
||||
proxy.asInstanceOf[T]
|
||||
}
|
||||
|
||||
|
|
@ -126,50 +127,27 @@ object ActiveObject {
|
|||
*/
|
||||
@serializable sealed class TransactionalAroundAdvice(
|
||||
val target: Class[_], val targetInstance: AnyRef, actor: Actor, val isRemote: Boolean)
|
||||
extends AroundAdvice with TransactionManagement {
|
||||
|
||||
val transactionalInstance = targetInstance
|
||||
extends AroundAdvice {
|
||||
val id = target.getName
|
||||
actor.start
|
||||
|
||||
import kernel.reactor._
|
||||
private[this] var dispatcher = new ProxyMessageDispatcher
|
||||
private[this] var mailbox = dispatcher.messageQueue
|
||||
dispatcher.start
|
||||
|
||||
def invoke(joinpoint: JoinPoint): AnyRef =
|
||||
if (TransactionManagement.isTransactionsEnabled) transactionalDispatch(joinpoint)
|
||||
else
|
||||
dispatch(joinpoint)
|
||||
def invoke(joinpoint: JoinPoint): AnyRef = dispatch(joinpoint)
|
||||
|
||||
private def dispatch(joinpoint: JoinPoint) = {
|
||||
if (isRemote) remoteDispatch(joinpoint)
|
||||
else localDispatch(joinpoint)
|
||||
}
|
||||
|
||||
private def transactionalDispatch(joinpoint: JoinPoint) = {
|
||||
// FIXME join TX with same id, do not COMMIT
|
||||
tryToCommitTransaction
|
||||
if (isInExistingTransaction) joinExistingTransaction
|
||||
else if (isTransactional(joinpoint)) startNewTransaction
|
||||
incrementTransaction
|
||||
try {
|
||||
dispatch(joinpoint)
|
||||
} catch {
|
||||
case e: TransactionAwareWrapperException =>
|
||||
rollback(e.tx)
|
||||
throw e.cause
|
||||
} finally {
|
||||
decrementTransaction
|
||||
if (isTransactionAborted) removeTransactionIfTopLevel
|
||||
else tryToPrecommitTransaction
|
||||
TransactionManagement.threadBoundTx.set(None)
|
||||
}
|
||||
}
|
||||
|
||||
private def localDispatch(joinpoint: JoinPoint): AnyRef = {
|
||||
val rtti = joinpoint.getRtti.asInstanceOf[MethodRtti]
|
||||
if (isOneWay(rtti)) actor !! Invocation(joinpoint, activeTx) // FIXME investigate why ! causes TX to race
|
||||
if (isOneWay(rtti)) actor !! Invocation(joinpoint) // FIXME investigate why ! causes TX to race
|
||||
else {
|
||||
val result = actor !! Invocation(joinpoint, activeTx)
|
||||
val result = actor !! Invocation(joinpoint)
|
||||
if (result.isDefined) result.get
|
||||
else throw new IllegalStateException("No result defined for invocation [" + joinpoint + "]")
|
||||
}
|
||||
|
|
@ -179,7 +157,7 @@ object ActiveObject {
|
|||
val rtti = joinpoint.getRtti.asInstanceOf[MethodRtti]
|
||||
val oneWay = isOneWay(rtti)
|
||||
val future = NettyClient.send(
|
||||
new RemoteRequest(false, rtti.getParameterValues, rtti.getMethod.getName, target.getName, activeTx, oneWay, false))
|
||||
new RemoteRequest(false, rtti.getParameterValues, rtti.getMethod.getName, target.getName, None, oneWay, false))
|
||||
if (oneWay) null // for void methods
|
||||
else {
|
||||
future.await
|
||||
|
|
@ -192,13 +170,9 @@ object ActiveObject {
|
|||
private def getResultOrThrowException[T](future: FutureResult): Option[T] =
|
||||
if (future.exception.isDefined) {
|
||||
val (_, cause) = future.exception.get
|
||||
if (TransactionManagement.isTransactionsEnabled) throw new TransactionAwareWrapperException(cause, activeTx)
|
||||
else throw cause
|
||||
throw cause
|
||||
} else future.result.asInstanceOf[Option[T]]
|
||||
|
||||
private def isTransactional(joinpoint: JoinPoint) =
|
||||
joinpoint.getRtti.asInstanceOf[MethodRtti].getMethod.isAnnotationPresent(Annotations.transactional)
|
||||
|
||||
private def isOneWay(rtti: MethodRtti) = rtti.getMethod.getReturnType == java.lang.Void.TYPE
|
||||
}
|
||||
|
||||
|
|
@ -207,24 +181,22 @@ object ActiveObject {
|
|||
*
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
@serializable private[kernel] case class Invocation(val joinpoint: JoinPoint, val transaction: Option[Transaction]) {
|
||||
@serializable private[kernel] case class Invocation(val joinpoint: JoinPoint) {
|
||||
|
||||
override def toString: String = synchronized {
|
||||
"Invocation [joinpoint: " + joinpoint.toString+ " | transaction: " + transaction.toString + "]"
|
||||
"Invocation [joinpoint: " + joinpoint.toString + "]"
|
||||
}
|
||||
|
||||
override def hashCode(): Int = synchronized {
|
||||
var result = HashCode.SEED
|
||||
result = HashCode.hash(result, joinpoint)
|
||||
if (transaction.isDefined) result = HashCode.hash(result, transaction.get)
|
||||
result
|
||||
}
|
||||
|
||||
override def equals(that: Any): Boolean = synchronized {
|
||||
that != null &&
|
||||
that.isInstanceOf[Invocation] &&
|
||||
that.asInstanceOf[Invocation].joinpoint == joinpoint &&
|
||||
that.asInstanceOf[Invocation].transaction.getOrElse(false) == transaction.getOrElse(false)
|
||||
that.asInstanceOf[Invocation].joinpoint == joinpoint
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,45 +206,18 @@ object ActiveObject {
|
|||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
private[kernel] class Dispatcher(val targetName: String) extends Actor {
|
||||
//makeTransactional
|
||||
id = targetName
|
||||
makeTransactional
|
||||
|
||||
// FIXME implement the pre/post restart methods and call annotated methods on the POJO
|
||||
|
||||
// FIXME create new POJO on creation and swap POJO at restart - joinpoint.setTarget(new POJO)
|
||||
|
||||
override def receive: PartialFunction[Any, Unit] = {
|
||||
|
||||
case Invocation(joinpoint: JoinPoint, tx: Option[Transaction]) =>
|
||||
TransactionManagement.threadBoundTx.set(tx)
|
||||
try {
|
||||
case Invocation(joinpoint: JoinPoint) =>
|
||||
reply(joinpoint.proceed)
|
||||
} catch {
|
||||
case e =>
|
||||
throw new TransactionAwareWrapperException(e, tx)
|
||||
}
|
||||
|
||||
case unexpected =>
|
||||
throw new ActiveObjectException("Unexpected message [" + unexpected + "] sent to [" + this + "]")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: create a method setCallee/setCaller to the joinpoint interface and compiler
|
||||
/*
|
||||
private def nullOutTransientFieldsInJoinpoint(joinpoint: JoinPoint) = {
|
||||
val clazz = joinpoint.getClass
|
||||
val callee = clazz.getDeclaredField("CALLEE")
|
||||
callee.setAccessible(true)
|
||||
callee.set(joinpoint, null)
|
||||
val caller = clazz.getDeclaredField("CALLER")
|
||||
caller.setAccessible(true)
|
||||
caller.set(joinpoint, null)
|
||||
val interceptors = clazz.getDeclaredField("AROUND_INTERCEPTORS")
|
||||
interceptors.setAccessible(true)
|
||||
interceptors.set(joinpoint, null)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
ublic class CamelInvocationHandler implements InvocationHandler {
|
||||
private final Endpoint endpoint;
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@
|
|||
|
||||
package se.scalablesolutions.akka.kernel.actor
|
||||
|
||||
import java.util.concurrent.{CopyOnWriteArraySet, TimeUnit}
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
|
||||
import kernel.reactor._
|
||||
import kernel.config.ScalaConfig._
|
||||
import kernel.nio.{NettyClient, RemoteRequest}
|
||||
import kernel.stm.{TransactionAwareWrapperException, TransactionManagement, Transaction}
|
||||
import kernel.util.Logging
|
||||
import kernel.util.Helpers._
|
||||
|
||||
sealed abstract class LifecycleMessage
|
||||
case class Init(config: AnyRef) extends LifecycleMessage
|
||||
|
|
@ -33,11 +32,11 @@ class ActorMessageHandler(val actor: Actor) extends MessageHandler {
|
|||
}
|
||||
|
||||
trait Actor extends Logging with TransactionManagement {
|
||||
val transactionalInstance = this
|
||||
val id: String = this.getClass.toString
|
||||
|
||||
@volatile private[this] var isRemote = false
|
||||
@volatile private[this] var isTransactional = false
|
||||
@volatile private[this] var isRunning: Boolean = false
|
||||
protected[this] var id: String = super.toString
|
||||
protected[this] var dispatcher: MessageDispatcher = _
|
||||
protected[this] var senderFuture: Option[CompletableFutureResult] = None
|
||||
protected[this] val linkedActors = new CopyOnWriteArraySet[Actor]
|
||||
|
|
@ -135,7 +134,7 @@ trait Actor extends Logging with TransactionManagement {
|
|||
* TODO: document
|
||||
*/
|
||||
def !: Option[T] = if (isRunning) {
|
||||
if (TransactionManagement.isTransactionsEnabled) {
|
||||
if (TransactionManagement.isTransactionalityEnabled) {
|
||||
transactionalDispatch(message, timeout, false)
|
||||
} else {
|
||||
val future = postMessageToMailboxAndCreateFutureResultWithTimeout(message, timeout)
|
||||
|
|
@ -153,7 +152,7 @@ trait Actor extends Logging with TransactionManagement {
|
|||
* TODO: document
|
||||
*/
|
||||
def !?[T](message: AnyRef): T = if (isRunning) {
|
||||
if (TransactionManagement.isTransactionsEnabled) {
|
||||
if (TransactionManagement.isTransactionalityEnabled) {
|
||||
transactionalDispatch(message, 0, true).get
|
||||
} else {
|
||||
val future = postMessageToMailboxAndCreateFutureResultWithTimeout(message, 0)
|
||||
|
|
@ -206,10 +205,10 @@ trait Actor extends Logging with TransactionManagement {
|
|||
dispatcher = new EventBasedSingleThreadDispatcher
|
||||
case DispatcherType.EventBasedThreadPoolingDispatcher =>
|
||||
dispatcher = new EventBasedThreadPoolDispatcher
|
||||
case DispatcherType.ThreadBasedDispatcher =>
|
||||
dispatcher = new ThreadBasedDispatcher
|
||||
case DispatcherType.EventBasedThreadPooledProxyInvokingDispatcher =>
|
||||
dispatcher = new ProxyMessageDispatcher
|
||||
case DispatcherType.ThreadBasedDispatcher =>
|
||||
throw new UnsupportedOperationException("ThreadBasedDispatcher is not yet implemented. Please help out and send in a patch.")
|
||||
}
|
||||
mailbox = dispatcher.messageQueue
|
||||
dispatcher.registerHandler(this, new ActorMessageHandler(this))
|
||||
|
|
@ -313,7 +312,6 @@ trait Actor extends Logging with TransactionManagement {
|
|||
}
|
||||
|
||||
private def transactionalDispatch[T](message: AnyRef, timeout: Long, blocking: Boolean): Option[T] = {
|
||||
// FIXME join TX with same id, do not COMMIT
|
||||
tryToCommitTransaction
|
||||
if (isInExistingTransaction) joinExistingTransaction
|
||||
else if (isTransactional) startNewTransaction
|
||||
|
|
@ -336,13 +334,12 @@ trait Actor extends Logging with TransactionManagement {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private def getResultOrThrowException[T](future: FutureResult): Option[T] =
|
||||
if (isRemote) getRemoteResultOrThrowException(future)
|
||||
else {
|
||||
if (future.exception.isDefined) {
|
||||
val (_, cause) = future.exception.get
|
||||
if (TransactionManagement.isTransactionsEnabled) throw new TransactionAwareWrapperException(cause, activeTx)
|
||||
if (TransactionManagement.isTransactionalityEnabled) throw new TransactionAwareWrapperException(cause, activeTx)
|
||||
else throw cause
|
||||
} else {
|
||||
future.result.asInstanceOf[Option[T]]
|
||||
|
|
@ -354,7 +351,7 @@ trait Actor extends Logging with TransactionManagement {
|
|||
private def getRemoteResultOrThrowException[T](future: FutureResult): Option[T] =
|
||||
if (future.exception.isDefined) {
|
||||
val (_, cause) = future.exception.get
|
||||
if (TransactionManagement.isTransactionsEnabled) throw new TransactionAwareWrapperException(cause, activeTx)
|
||||
if (TransactionManagement.isTransactionalityEnabled) throw new TransactionAwareWrapperException(cause, activeTx)
|
||||
else throw cause
|
||||
} else {
|
||||
if (future.result.isDefined) {
|
||||
|
|
|
|||
|
|
@ -188,7 +188,6 @@ class ObjectServerHandler extends SimpleChannelUpstreamHandler with Logging {
|
|||
val clazz = Class.forName(name)
|
||||
try {
|
||||
val actor = new Dispatcher(clazz.getName)
|
||||
actor.start
|
||||
val newInstance = activeObjectFactory.newInstance(clazz, actor, false).asInstanceOf[AnyRef]
|
||||
activeObjects.put(name, newInstance)
|
||||
newInstance
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
* Copyright (C) 2009 Scalable Solutions.
|
||||
*/
|
||||
|
||||
package se.scalablesolutions.akka.kernel.nio
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.net.{Socket, InetAddress, InetSocketAddress}
|
||||
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.{HashSet, Date}
|
||||
import java.nio.channels.{Selector, ServerSocketChannel, SelectionKey}
|
||||
import java.nio.channels.spi.SelectorProvider
|
||||
import kernel.actor.Invocation
|
||||
import kernel.reactor.{MessageQueue, MessageDemultiplexer, MessageHandle, MessageDispatcherBase}
|
||||
|
||||
class ProxyServer extends MessageDispatcherBase {
|
||||
val port = 9999
|
||||
val host = InetAddress.getLocalHost
|
||||
|
||||
// Selector for incoming time requests
|
||||
val acceptSelector = SelectorProvider.provider.openSelector
|
||||
|
||||
// Create a new server socket and set to non blocking mode
|
||||
val ssc = ServerSocketChannel.open
|
||||
ssc.configureBlocking(true)
|
||||
|
||||
// Bind the server socket to the local host and port
|
||||
val address = new InetSocketAddress(host, port)
|
||||
ssc.socket.bind(address)
|
||||
|
||||
// Register accepts on the server socket with the selector. This
|
||||
// step tells the selector that the socket wants to be put on the
|
||||
// ready list when accept operations occur, so allowing multiplexed
|
||||
// non-blocking I/O to take place.
|
||||
val acceptKey = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT)
|
||||
|
||||
// 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
|
||||
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]
|
||||
|
||||
val keysAdded = acceptSelector.select
|
||||
val readyKeys = acceptSelector.selectedKeys
|
||||
val iter = readyKeys.iterator
|
||||
while (iter.hasNext) {
|
||||
val key = iter.next.asInstanceOf[SelectionKey]
|
||||
iter.remove
|
||||
/*
|
||||
if (key.isValid && key.isReadable) {
|
||||
eventHandler.onReadableEvent(key.channel)
|
||||
}
|
||||
if (key.isValid && key.isWritable) {
|
||||
key.interestOps(SelectionKey.OP_READ) // reset to read only
|
||||
eventHandler.onWriteableEvent(key.channel)
|
||||
}
|
||||
*/
|
||||
val channel = key.channel.asInstanceOf[ServerSocketChannel]
|
||||
val socket = channel.accept.socket
|
||||
socket.setKeepAlive(true)
|
||||
|
||||
|
||||
val in = socket.getInputStream
|
||||
val out = new PrintWriter(socket.getOutputStream, true)
|
||||
out.println(new Date)
|
||||
out.close
|
||||
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
*/
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
selectorThread.start
|
||||
}
|
||||
|
||||
override protected def doShutdown = handlerExecutor.shutdownNow
|
||||
}
|
||||
|
|
@ -4,10 +4,9 @@
|
|||
|
||||
package se.scalablesolutions.akka.kernel.state
|
||||
|
||||
import kernel.stm.TransactionManagement
|
||||
import kernel.stm.{Transaction, TransactionManagement}
|
||||
import org.codehaus.aspectwerkz.proxy.Uuid
|
||||
|
||||
import kernel.actor.ActiveObject
|
||||
import se.scalablesolutions.akka.collection._
|
||||
|
||||
import scala.collection.mutable.HashMap
|
||||
|
|
@ -68,14 +67,21 @@ class TransactionalState {
|
|||
*/
|
||||
@serializable
|
||||
trait Transactional {
|
||||
// FIXME: won't work across the cluster
|
||||
val uuid = Uuid.newUuid.toString
|
||||
|
||||
private[kernel] def begin
|
||||
private[kernel] def commit
|
||||
private[kernel] def rollback
|
||||
|
||||
protected def isInTransaction = TransactionManagement.threadBoundTx.get.isDefined
|
||||
protected def nonTransactionalCall = throw new IllegalStateException("Can't access transactional map outside the scope of a transaction")
|
||||
protected def verifyTransaction = {
|
||||
val cflowTx = TransactionManagement.threadBoundTx.get
|
||||
if (!cflowTx.isDefined) {
|
||||
throw new IllegalStateException("Can't access transactional reference outside the scope of a transaction [" + this + "]")
|
||||
} else {
|
||||
cflowTx.get.register(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -89,37 +95,6 @@ trait TransactionalMap[K, V] extends Transactional with scala.collection.mutable
|
|||
def remove(key: K)
|
||||
}
|
||||
|
||||
trait TransactionalMapGuard[K, V] extends TransactionalMap[K, V] with Transactional {
|
||||
abstract override def contains(key: K): Boolean =
|
||||
if (isInTransaction) super.contains(key)
|
||||
else nonTransactionalCall
|
||||
abstract override def clear =
|
||||
if (isInTransaction) super.clear
|
||||
else nonTransactionalCall
|
||||
abstract override def size: Int =
|
||||
if (isInTransaction) super.size
|
||||
else nonTransactionalCall
|
||||
abstract override def remove(key: K) =
|
||||
if (isInTransaction) super.remove(key)
|
||||
else nonTransactionalCall
|
||||
abstract override def elements: Iterator[(K, V)] =
|
||||
if (isInTransaction) super.elements
|
||||
else nonTransactionalCall
|
||||
abstract override def get(key: K): Option[V] =
|
||||
if (isInTransaction) super.get(key)
|
||||
else nonTransactionalCall
|
||||
abstract override def put(key: K, value: V): Option[V] =
|
||||
if (isInTransaction) super.put(key, value)
|
||||
else nonTransactionalCall
|
||||
abstract override def -=(key: K) =
|
||||
if (isInTransaction) super.-=(key)
|
||||
else nonTransactionalCall
|
||||
abstract override def update(key: K, value: V) =
|
||||
if (isInTransaction) super.update(key, value)
|
||||
else nonTransactionalCall
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Not thread-safe, but should only be using from within an Actor, e.g. one single thread at a time.
|
||||
*
|
||||
|
|
@ -135,21 +110,46 @@ class InMemoryTransactionalMap[K, V] extends TransactionalMap[K, V] {
|
|||
override def rollback = state = snapshot
|
||||
|
||||
// ---- Overriding scala.collection.mutable.Map behavior ----
|
||||
override def contains(key: K): Boolean = state.contains(key)
|
||||
override def clear = state = new HashTrie[K, V]
|
||||
override def size: Int = state.size
|
||||
override def contains(key: K): Boolean = {
|
||||
verifyTransaction
|
||||
state.contains(key)
|
||||
}
|
||||
override def clear = {
|
||||
verifyTransaction
|
||||
state = new HashTrie[K, V]
|
||||
}
|
||||
override def size: Int = {
|
||||
verifyTransaction
|
||||
state.size
|
||||
}
|
||||
|
||||
// ---- For scala.collection.mutable.Map ----
|
||||
override def remove(key: K) = state = state - key
|
||||
override def elements: Iterator[(K, V)] = state.elements
|
||||
override def get(key: K): Option[V] = state.get(key)
|
||||
override def remove(key: K) = {
|
||||
verifyTransaction
|
||||
state = state - key
|
||||
}
|
||||
override def elements: Iterator[(K, V)] = {
|
||||
// verifyTransaction
|
||||
state.elements
|
||||
}
|
||||
override def get(key: K): Option[V] = {
|
||||
verifyTransaction
|
||||
state.get(key)
|
||||
}
|
||||
override def put(key: K, value: V): Option[V] = {
|
||||
verifyTransaction
|
||||
val oldValue = state.get(key)
|
||||
state = state.update(key, value)
|
||||
oldValue
|
||||
}
|
||||
override def -=(key: K) = remove(key)
|
||||
override def update(key: K, value: V) = put(key, value)
|
||||
override def -=(key: K) = {
|
||||
verifyTransaction
|
||||
remove(key)
|
||||
}
|
||||
override def update(key: K, value: V) = {
|
||||
verifyTransaction
|
||||
put(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -173,12 +173,14 @@ abstract class PersistentTransactionalMap[K, V] extends TransactionalMap[K, V] {
|
|||
|
||||
// ---- For scala.collection.mutable.Map ----
|
||||
override def put(key: K, value: V): Option[V] = {
|
||||
println("--------- MAP.PUT " + uuid + " " + key + " " + value)
|
||||
|
||||
verifyTransaction
|
||||
changeSet += key -> value
|
||||
None // always return None to speed up writes (else need to go to DB to get
|
||||
}
|
||||
override def remove(key: K) = changeSet -= key
|
||||
override def remove(key: K) = {
|
||||
verifyTransaction
|
||||
changeSet -= key
|
||||
}
|
||||
override def -=(key: K) = remove(key)
|
||||
override def update(key: K, value: V) = put(key, value)
|
||||
}
|
||||
|
|
@ -190,31 +192,43 @@ abstract class PersistentTransactionalMap[K, V] extends TransactionalMap[K, V] {
|
|||
*/
|
||||
class CassandraPersistentTransactionalMap extends PersistentTransactionalMap[String, AnyRef] {
|
||||
|
||||
override def getRange(start: Int, count: Int) = CassandraNode.getMapStorageRangeFor(uuid, start, count)
|
||||
override def getRange(start: Int, count: Int) = {
|
||||
verifyTransaction
|
||||
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
|
||||
println("--------- COMMIT " + uuid + " " + key + " " + value)
|
||||
CassandraNode.insertMapStorageEntryFor(uuid, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Overriding scala.collection.mutable.Map behavior ----
|
||||
override def clear = CassandraNode.removeMapStorageFor(uuid)
|
||||
override def contains(key: String): Boolean = CassandraNode.getMapStorageEntryFor(uuid, key).isDefined
|
||||
override def size: Int = CassandraNode.getMapStorageSizeFor(uuid)
|
||||
override def clear = {
|
||||
verifyTransaction
|
||||
CassandraNode.removeMapStorageFor(uuid)
|
||||
}
|
||||
override def contains(key: String): Boolean = {
|
||||
verifyTransaction
|
||||
CassandraNode.getMapStorageEntryFor(uuid, key).isDefined
|
||||
}
|
||||
override def size: Int = {
|
||||
verifyTransaction
|
||||
CassandraNode.getMapStorageSizeFor(uuid)
|
||||
}
|
||||
|
||||
// ---- For scala.collection.mutable.Map ----
|
||||
override def get(key: String): Option[AnyRef] = {
|
||||
verifyTransaction
|
||||
val result = CassandraNode.getMapStorageEntryFor(uuid, key)
|
||||
println("--------- MAP.GET " + result + " " + uuid + " " + key)
|
||||
result
|
||||
}
|
||||
|
||||
override def elements: Iterator[Tuple2[String, AnyRef]] = {
|
||||
//verifyTransaction
|
||||
new Iterator[Tuple2[String, AnyRef]] {
|
||||
private val originalList: List[Tuple2[String, AnyRef]] = CassandraNode.getMapStorageFor(uuid)
|
||||
private var elements = originalList.reverse
|
||||
|
|
@ -250,9 +264,18 @@ class InMemoryTransactionalVector[T] extends TransactionalVector[T] {
|
|||
private[kernel] var state: Vector[T] = EmptyVector
|
||||
private[kernel] var snapshot = state
|
||||
|
||||
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]]
|
||||
def add(elem: T) = {
|
||||
verifyTransaction
|
||||
state = state + elem
|
||||
}
|
||||
def get(index: Int): T = {
|
||||
verifyTransaction
|
||||
state(index)
|
||||
}
|
||||
def getRange(start: Int, count: Int): List[T] = {
|
||||
verifyTransaction
|
||||
state.slice(start, count).toList.asInstanceOf[List[T]]
|
||||
}
|
||||
|
||||
// ---- For Transactional ----
|
||||
override def begin = snapshot = state
|
||||
|
|
@ -260,10 +283,22 @@ class InMemoryTransactionalVector[T] extends TransactionalVector[T] {
|
|||
override def rollback = state = snapshot
|
||||
|
||||
// ---- For Seq ----
|
||||
def length: Int = state.length
|
||||
def apply(index: Int): T = state(index)
|
||||
override def elements: Iterator[T] = state.elements
|
||||
override def toList: List[T] = state.toList
|
||||
def length: Int = {
|
||||
verifyTransaction
|
||||
state.length
|
||||
}
|
||||
def apply(index: Int): T = {
|
||||
verifyTransaction
|
||||
state(index)
|
||||
}
|
||||
override def elements: Iterator[T] = {
|
||||
//verifyTransaction
|
||||
state.elements
|
||||
}
|
||||
override def toList: List[T] = {
|
||||
verifyTransaction
|
||||
state.toList
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -284,7 +319,10 @@ abstract class PersistentTransactionalVector[T] extends TransactionalVector[T] {
|
|||
override def rollback = {}
|
||||
|
||||
// ---- For TransactionalVector ----
|
||||
override def add(value: T) = changeSet ::= value
|
||||
override def add(value: T) = {
|
||||
verifyTransaction
|
||||
changeSet ::= value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -295,12 +333,22 @@ abstract class PersistentTransactionalVector[T] extends TransactionalVector[T] {
|
|||
class CassandraPersistentTransactionalVector extends PersistentTransactionalVector[AnyRef] {
|
||||
|
||||
// ---- 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 get(index: Int): AnyRef = {
|
||||
verifyTransaction
|
||||
CassandraNode.getVectorStorageEntryFor(uuid, index)
|
||||
}
|
||||
override def getRange(start: Int, count: Int): List[AnyRef] = {
|
||||
verifyTransaction
|
||||
CassandraNode.getVectorStorageRangeFor(uuid, start, count)
|
||||
}
|
||||
override def length: Int = {
|
||||
verifyTransaction
|
||||
CassandraNode.getVectorStorageSizeFor(uuid)
|
||||
}
|
||||
override def apply(index: Int): AnyRef = get(index)
|
||||
override def first: AnyRef = get(0)
|
||||
override def last: AnyRef = {
|
||||
verifyTransaction
|
||||
val l = length
|
||||
if (l == 0) throw new NoSuchElementException("Vector is empty")
|
||||
get(length - 1)
|
||||
|
|
@ -311,7 +359,6 @@ class CassandraPersistentTransactionalVector extends PersistentTransactionalVect
|
|||
// FIXME: should use batch function once the bug is resolved
|
||||
for (element <- changeSet) {
|
||||
CassandraNode.insertVectorStorageEntryFor(uuid, element)
|
||||
println("33333333333 " + CassandraNode.getVectorStorageSizeFor(uuid))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -331,15 +378,31 @@ class TransactionalRef[T] extends Transactional {
|
|||
override def commit = if (ref.isDefined) snapshot = Some(ref.get)
|
||||
override def rollback = if (snapshot.isDefined) ref = Some(snapshot.get)
|
||||
|
||||
def swap(elem: T) = ref = Some(elem)
|
||||
def get: Option[T] = ref
|
||||
def getOrElse(default: => T): T = ref.getOrElse(default)
|
||||
def isDefined: Boolean = ref.isDefined
|
||||
def swap(elem: T) = {
|
||||
verifyTransaction
|
||||
ref = Some(elem)
|
||||
}
|
||||
def get: Option[T] = {
|
||||
verifyTransaction
|
||||
ref
|
||||
}
|
||||
def getOrElse(default: => T): T = {
|
||||
verifyTransaction
|
||||
ref.getOrElse(default)
|
||||
}
|
||||
def isDefined: Boolean = {
|
||||
verifyTransaction
|
||||
ref.isDefined
|
||||
}
|
||||
}
|
||||
|
||||
class CassandraPersistentTransactionalRef extends TransactionalRef[AnyRef] {
|
||||
override def commit = if (ref.isDefined) CassandraNode.insertRefStorageFor(uuid, ref.get)
|
||||
override def get: Option[AnyRef] = CassandraNode.getRefStorageFor(uuid)
|
||||
|
||||
override def get: Option[AnyRef] = {
|
||||
verifyTransaction
|
||||
CassandraNode.getRefStorageFor(uuid)
|
||||
}
|
||||
override def isDefined: Boolean = get.isDefined
|
||||
override def getOrElse(default: => AnyRef): AnyRef = {
|
||||
val ref = get
|
||||
|
|
|
|||
|
|
@ -4,17 +4,28 @@
|
|||
|
||||
package se.scalablesolutions.akka.kernel.stm
|
||||
|
||||
import kernel.state.{Transactional, TransactionalMap, TransactionalVector, TransactionalRef}
|
||||
import kernel.state.{Transactional, TransactionalMap}
|
||||
import kernel.util.Helpers.ReadWriteLock
|
||||
import scala.collection.immutable.HashSet
|
||||
|
||||
@serializable
|
||||
class ChangeSet(val id: String) {
|
||||
class ChangeSet {
|
||||
private val lock = new ReadWriteLock
|
||||
|
||||
private[kernel] def full: List[Transactional] = lock.withReadLock {
|
||||
_maps ::: _vectors ::: _refs
|
||||
private var transactionalItems: Set[Transactional] = new HashSet
|
||||
private[kernel] def +(item: Transactional) = lock.withWriteLock {
|
||||
transactionalItems += item
|
||||
}
|
||||
private[kernel] def items: List[Transactional] = lock.withReadLock {
|
||||
transactionalItems.toList.asInstanceOf[List[Transactional]]
|
||||
}
|
||||
|
||||
private[kernel] def clear = lock.withWriteLock {
|
||||
transactionalItems = new HashSet
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// TX Maps
|
||||
private[kernel] var _maps: List[TransactionalMap[_, _]] = Nil
|
||||
private[kernel] def maps_=(maps: List[TransactionalMap[_, _]]) = lock.withWriteLock {
|
||||
|
|
@ -41,5 +52,6 @@ class ChangeSet(val id: String) {
|
|||
private[kernel] def refs: List[TransactionalRef[_]] = lock.withReadLock {
|
||||
_refs
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
package se.scalablesolutions.akka.kernel.stm
|
||||
|
||||
import java.util.concurrent.atomic.{AtomicInteger, AtomicLong}
|
||||
import kernel.state.Transactional
|
||||
import kernel.util.Logging
|
||||
|
||||
import scala.collection.mutable.{HashSet, HashMap}
|
||||
|
|
@ -38,68 +39,69 @@ object TransactionIdFactory {
|
|||
|
||||
log.debug("Creating a new transaction with id [%s]", id)
|
||||
|
||||
// FIXME: add support for nested transactions
|
||||
//private[this] var parent: Option[Transaction] = None
|
||||
private[this] val participants = new HashSet[ChangeSet]
|
||||
private[this] val precommitted = new HashSet[ChangeSet]
|
||||
private[this] val transactionals = new ChangeSet
|
||||
|
||||
private[this] var participants: List[String] = Nil
|
||||
private[this] var precommitted: List[String] = Nil
|
||||
|
||||
private[this] val depth = new AtomicInteger(0)
|
||||
|
||||
@volatile private[this] var status: TransactionStatus = TransactionStatus.New
|
||||
|
||||
def increment = depth.incrementAndGet
|
||||
def decrement = depth.decrementAndGet
|
||||
def topLevel_? = depth.get == 0
|
||||
def increment = synchronized { depth.incrementAndGet }
|
||||
def decrement = synchronized { depth.decrementAndGet }
|
||||
def topLevel_? = synchronized { depth.get == 0 }
|
||||
|
||||
def begin(changeSet: ChangeSet) = synchronized {
|
||||
def register(transactional: Transactional) = synchronized {
|
||||
ensureIsActiveOrNew
|
||||
if (status == TransactionStatus.New) log.debug("TX BEGIN - Server [%s] is starting NEW transaction [%s]", changeSet.id, this)
|
||||
else log.debug("Server [%s] is participating in transaction", changeSet.id)
|
||||
changeSet.full.foreach(_.begin)
|
||||
participants + changeSet
|
||||
transactionals + transactional
|
||||
}
|
||||
|
||||
def begin(participant: String) = synchronized {
|
||||
ensureIsActiveOrNew
|
||||
if (status == TransactionStatus.New) log.debug("TX BEGIN - Server [%s] is starting NEW transaction [%s]", participant, this)
|
||||
else log.debug("Server [%s] is participating in transaction", participant)
|
||||
participants ::= participant
|
||||
status = TransactionStatus.Active
|
||||
}
|
||||
|
||||
def precommit(changeSet: ChangeSet) = synchronized {
|
||||
def precommit(participant: String) = synchronized {
|
||||
if (status == TransactionStatus.Active) {
|
||||
log.debug("TX PRECOMMIT - Pre-committing transaction [%s] for server [%s]", this, changeSet.id)
|
||||
precommitted + changeSet
|
||||
log.debug("TX PRECOMMIT - Pre-committing transaction [%s] for server [%s]", this, participant)
|
||||
precommitted ::= participant
|
||||
}
|
||||
}
|
||||
|
||||
def commit(changeSet: ChangeSet) = synchronized {
|
||||
def commit(participant: String) = synchronized {
|
||||
if (status == TransactionStatus.Active) {
|
||||
log.debug("TX COMMIT - Committing transaction [%s] for server [%s]", this, changeSet.id)
|
||||
log.debug("TX COMMIT - Committing transaction [%s] for server [%s]", this, participant)
|
||||
val haveAllPreCommitted =
|
||||
if (participants.size == precommitted.size) {{
|
||||
for (server <- participants) yield {
|
||||
if (precommitted.exists(_.id == changeSet.id)) true
|
||||
for (part <- participants) yield {
|
||||
if (precommitted.exists(_ == part)) true
|
||||
else false
|
||||
}}.exists(_ == true)
|
||||
} else false
|
||||
if (haveAllPreCommitted) {
|
||||
participants.foreach(_.full.foreach(_.commit))
|
||||
transactionals.items.foreach(_.commit)
|
||||
status = TransactionStatus.Completed
|
||||
} else rollback(changeSet)
|
||||
} else rollback(participant)
|
||||
}
|
||||
participants.clear
|
||||
precommitted.clear
|
||||
reset
|
||||
}
|
||||
|
||||
def rollback(changeSet: ChangeSet) = synchronized {
|
||||
def rollback(participant: String) = synchronized {
|
||||
ensureIsActiveOrAborted
|
||||
log.debug("TX ROLLBACK - Server [%s] has initiated transaction rollback for [%s], rolling back [%s]", changeSet.id, this, participants)
|
||||
participants.foreach(_.full.foreach(_.rollback))
|
||||
log.debug("TX ROLLBACK - Server [%s] has initiated transaction rollback for [%s]", participant, this)
|
||||
transactionals.items.foreach(_.rollback)
|
||||
status = TransactionStatus.Aborted
|
||||
participants.clear
|
||||
precommitted.clear
|
||||
reset
|
||||
}
|
||||
|
||||
def join(changeSet: ChangeSet) = synchronized {
|
||||
def join(participant: String) = synchronized {
|
||||
ensureIsActive
|
||||
println(" --- log ;" + log)
|
||||
println(" --- changeset ;" + changeSet)
|
||||
log.debug("TX JOIN - Server [%s] is joining transaction [%s]" , changeSet.id, this)
|
||||
changeSet.full.foreach(_.begin)
|
||||
participants + changeSet
|
||||
log.debug("TX JOIN - Server [%s] is joining transaction [%s]" , participant, this)
|
||||
participants ::= participant
|
||||
}
|
||||
|
||||
def isNew = status == TransactionStatus.New
|
||||
|
|
@ -107,6 +109,12 @@ object TransactionIdFactory {
|
|||
def isCompleted = status == TransactionStatus.Completed
|
||||
def isAborted = status == TransactionStatus.Aborted
|
||||
|
||||
private def reset = {
|
||||
transactionals.clear
|
||||
participants = Nil
|
||||
precommitted = Nil
|
||||
}
|
||||
|
||||
private def ensureIsActive = if (status != TransactionStatus.Active)
|
||||
throw new IllegalStateException("Expected ACTIVE transaction - current status [" + status + "]")
|
||||
|
||||
|
|
@ -116,6 +124,7 @@ object TransactionIdFactory {
|
|||
private def ensureIsActiveOrNew = if (!(status == TransactionStatus.Active || status == TransactionStatus.New))
|
||||
throw new IllegalStateException("Expected ACTIVE or NEW transaction - current status [" + status + "]")
|
||||
|
||||
// For reinitialize transaction after sending it over the wire
|
||||
private[kernel] def reinit = {
|
||||
import net.lag.logging.{Logger, Level}
|
||||
if (log == null) {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@
|
|||
|
||||
package se.scalablesolutions.akka.kernel.stm
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
import kernel.state.{TransactionalMap, TransactionalRef, TransactionalVector}
|
||||
import kernel.util.Logging
|
||||
|
||||
class TransactionAwareWrapperException(val cause: Throwable, val tx: Option[Transaction]) extends RuntimeException(cause) {
|
||||
|
|
@ -17,7 +15,7 @@ class TransactionAwareWrapperException(val cause: Throwable, val tx: Option[Tran
|
|||
object TransactionManagement {
|
||||
private val txEnabled = new AtomicBoolean(true)
|
||||
|
||||
def isTransactionsEnabled = txEnabled.get
|
||||
def isTransactionalityEnabled = txEnabled.get
|
||||
def enableTransactions = txEnabled.set(true)
|
||||
|
||||
private[kernel] val threadBoundTx: ThreadLocal[Option[Transaction]] = {
|
||||
|
|
@ -29,17 +27,14 @@ object TransactionManagement {
|
|||
|
||||
// FIXME: STM that allows concurrent updates, detects collision, rolls back and restarts
|
||||
trait TransactionManagement extends Logging {
|
||||
val transactionalInstance: AnyRef
|
||||
|
||||
private lazy val changeSet = new ChangeSet(transactionalInstance.getClass.getName)
|
||||
val id: String
|
||||
|
||||
import TransactionManagement.threadBoundTx
|
||||
private[kernel] var activeTx: Option[Transaction] = None
|
||||
|
||||
protected def startNewTransaction = {
|
||||
storeTransactionalItemsFor(transactionalInstance)
|
||||
val newTx = new Transaction
|
||||
newTx.begin(changeSet)
|
||||
newTx.begin(id)
|
||||
val tx = Some(newTx)
|
||||
activeTx = tx
|
||||
threadBoundTx.set(tx)
|
||||
|
|
@ -47,19 +42,18 @@ trait TransactionManagement extends Logging {
|
|||
|
||||
protected def joinExistingTransaction = {
|
||||
val cflowTx = threadBoundTx.get
|
||||
if (activeTx.isDefined && cflowTx.isDefined && activeTx.get.id == cflowTx.get.id) {
|
||||
storeTransactionalItemsFor(transactionalInstance)
|
||||
if (!activeTx.isDefined && cflowTx.isDefined) {
|
||||
val currentTx = cflowTx.get
|
||||
currentTx.join(changeSet)
|
||||
currentTx.join(id)
|
||||
activeTx = Some(currentTx)
|
||||
}
|
||||
}
|
||||
|
||||
protected def tryToPrecommitTransaction = if (activeTx.isDefined) activeTx.get.precommit(changeSet)
|
||||
protected def tryToPrecommitTransaction = if (activeTx.isDefined) activeTx.get.precommit(id)
|
||||
|
||||
protected def tryToCommitTransaction: Boolean = if (activeTx.isDefined) {
|
||||
val tx = activeTx.get
|
||||
tx.commit(changeSet)
|
||||
tx.commit(id)
|
||||
removeTransactionIfTopLevel
|
||||
true
|
||||
} else false
|
||||
|
|
@ -67,16 +61,10 @@ trait TransactionManagement extends Logging {
|
|||
protected def rollback(tx: Option[Transaction]) = tx match {
|
||||
case None => {} // no tx; nothing to do
|
||||
case Some(tx) =>
|
||||
tx.rollback(changeSet)
|
||||
tx.rollback(id)
|
||||
}
|
||||
|
||||
protected def isInExistingTransaction = {
|
||||
println(TransactionManagement)
|
||||
println(TransactionManagement.threadBoundTx)
|
||||
println(TransactionManagement.threadBoundTx.get)
|
||||
println(TransactionManagement.threadBoundTx.get.isDefined)
|
||||
TransactionManagement.threadBoundTx.get.isDefined
|
||||
}
|
||||
protected def isInExistingTransaction = TransactionManagement.threadBoundTx.get.isDefined
|
||||
|
||||
protected def isTransactionAborted = activeTx.isDefined && activeTx.get.isAborted
|
||||
|
||||
|
|
@ -95,58 +83,5 @@ trait TransactionManagement extends Logging {
|
|||
if (cflowTx.isDefined && cflowTx.get.id == activeTx.get.id) false
|
||||
else true
|
||||
} else true
|
||||
|
||||
/**
|
||||
* Search for transactional items for a specific target instance, crawl the class hierarchy recursively up to the top.
|
||||
*/
|
||||
protected def storeTransactionalItemsFor(targetInstance: AnyRef) = {
|
||||
require(targetInstance != null)
|
||||
var maps: List[TransactionalMap[_, _]] = Nil
|
||||
var refs: List[TransactionalRef[_]] = Nil
|
||||
var vectors: List[TransactionalVector[_]] = Nil
|
||||
|
||||
def getTransactionalItemsFor(target: Class[_]):
|
||||
Tuple3[List[TransactionalMap[_, _]], List[TransactionalVector[_]], List[TransactionalRef[_]]] = {
|
||||
for {
|
||||
field <- target.getDeclaredFields.toArray.toList.asInstanceOf[List[Field]]
|
||||
fieldType = field.getType
|
||||
if (fieldType == classOf[TransactionalMap[_, _]]) ||
|
||||
(fieldType == classOf[TransactionalVector[_]]) ||
|
||||
(fieldType == classOf[TransactionalRef[_]])
|
||||
txItem = {
|
||||
field.setAccessible(true)
|
||||
field.get(targetInstance)
|
||||
}
|
||||
if txItem != null
|
||||
} {
|
||||
log.debug("Managing transactional state [%s]", field)
|
||||
if (txItem.isInstanceOf[TransactionalMap[_, _]]) maps ::= txItem.asInstanceOf[TransactionalMap[_, _]]
|
||||
else if (txItem.isInstanceOf[TransactionalRef[_]]) refs ::= txItem.asInstanceOf[TransactionalRef[_]]
|
||||
else if (txItem.isInstanceOf[TransactionalVector[_]]) vectors ::= txItem.asInstanceOf[TransactionalVector[_]]
|
||||
}
|
||||
val parent = target.getSuperclass
|
||||
if (parent == classOf[Object]) (maps, vectors, refs)
|
||||
else getTransactionalItemsFor(parent)
|
||||
}
|
||||
|
||||
// start the search for transactional items, crawl the class hierarchy up until we reach Object
|
||||
val (m, v, r) = getTransactionalItemsFor(targetInstance.getClass)
|
||||
changeSet.maps = m
|
||||
changeSet.vectors = v
|
||||
changeSet.refs = r
|
||||
}
|
||||
|
||||
/*
|
||||
protected def getResultOrThrowException[T](future: FutureResult): Option[T] =
|
||||
if (future.exception.isDefined) {
|
||||
val (_, cause) = future.exception.get
|
||||
throw new TransactionAwareWrapperException(cause, activeTx)
|
||||
} else {
|
||||
if (future.result.isDefined) {
|
||||
val (res, tx) = future.result.get.asInstanceOf[Tuple2[AnyRef, Option[Transaction]]]
|
||||
Some(res).asInstanceOf[Option[T]]
|
||||
} else None
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue