complete refactoring of transaction and transactional item management + removed duplicate tx management in ActiveObject

This commit is contained in:
Jonas Boner 2009-06-29 23:38:10 +02:00
parent 7083737f95
commit 6359920fa4
9 changed files with 393 additions and 517 deletions

317
akka.iws
View file

@ -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="&#10;# Brief commit desciption here&#10;&#10;# Full commit description here (comment lines starting with '#' will not be included)&#10;&#10;" />
<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>

View file

@ -82,6 +82,7 @@ class ActiveObjectFactory {
* @author <a href="http://jonasboner.com">Jonas Bon&#233;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&#233;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&#233;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;

View file

@ -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 !![T](message: AnyRef, timeout: Long): 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) {

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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
}
*/
}

View file

@ -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) {

View file

@ -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
}
*/
}