From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/cosTransactions/AUTHORS | 4 + lib/cosTransactions/Makefile | 41 + lib/cosTransactions/doc/html/.gitignore | 0 lib/cosTransactions/doc/man3/.gitignore | 0 lib/cosTransactions/doc/man6/.gitignore | 0 lib/cosTransactions/doc/pdf/.gitignore | 0 .../doc/src/CosTransactions_Control.xml | 73 + .../doc/src/CosTransactions_Coordinator.xml | 229 +++ .../src/CosTransactions_RecoveryCoordinator.xml | 82 + .../doc/src/CosTransactions_Resource.xml | 128 ++ ...CosTransactions_SubtransactionAwareResource.xml | 75 + .../doc/src/CosTransactions_Synchronization.xml | 69 + .../doc/src/CosTransactions_Terminator.xml | 72 + .../doc/src/CosTransactions_TransactionFactory.xml | 64 + .../src/CosTransactions_TransactionalObject.xml | 42 + lib/cosTransactions/doc/src/Makefile | 229 +++ lib/cosTransactions/doc/src/book.gif | Bin 0 -> 1081 bytes lib/cosTransactions/doc/src/book.xml | 48 + lib/cosTransactions/doc/src/ch_contents.xml | 74 + lib/cosTransactions/doc/src/ch_example.xml | 280 ++++ lib/cosTransactions/doc/src/ch_install.xml | 103 ++ lib/cosTransactions/doc/src/ch_introduction.xml | 64 + lib/cosTransactions/doc/src/ch_skeletons.xml | 213 +++ lib/cosTransactions/doc/src/cosTransactions.xml | 141 ++ lib/cosTransactions/doc/src/fascicules.xml | 18 + lib/cosTransactions/doc/src/make.dep | 27 + lib/cosTransactions/doc/src/notes.gif | Bin 0 -> 2005 bytes lib/cosTransactions/doc/src/notes.xml | 243 +++ lib/cosTransactions/doc/src/part.xml | 40 + lib/cosTransactions/doc/src/part_notes.xml | 36 + lib/cosTransactions/doc/src/ref_man.gif | Bin 0 -> 1530 bytes lib/cosTransactions/doc/src/ref_man.xml | 43 + lib/cosTransactions/doc/src/summary.html.src | 1 + lib/cosTransactions/doc/src/user_guide.gif | Bin 0 -> 1581 bytes lib/cosTransactions/ebin/.gitignore | 0 lib/cosTransactions/examples/Makefile | 157 ++ lib/cosTransactions/include/.gitignore | 0 lib/cosTransactions/info | 2 + lib/cosTransactions/priv/.gitignore | 0 lib/cosTransactions/src/CosTransactions.cfg | 15 + lib/cosTransactions/src/CosTransactions.idl | 193 +++ .../src/CosTransactions_Terminator_impl.erl | 362 ++++ .../CosTransactions_TransactionFactory_impl.erl | 178 ++ lib/cosTransactions/src/ETraP_Common.erl | 185 +++ lib/cosTransactions/src/ETraP_Common.hrl | 340 ++++ lib/cosTransactions/src/ETraP_Server_impl.erl | 1739 ++++++++++++++++++++ lib/cosTransactions/src/Makefile | 175 ++ lib/cosTransactions/src/cosTransactions.app.src | 43 + lib/cosTransactions/src/cosTransactions.appup.src | 6 + lib/cosTransactions/src/cosTransactions.erl | 115 ++ lib/cosTransactions/src/etrap_logmgr.erl | 200 +++ lib/cosTransactions/vsn.mk | 9 + 52 files changed, 6158 insertions(+) create mode 100644 lib/cosTransactions/AUTHORS create mode 100644 lib/cosTransactions/Makefile create mode 100644 lib/cosTransactions/doc/html/.gitignore create mode 100644 lib/cosTransactions/doc/man3/.gitignore create mode 100644 lib/cosTransactions/doc/man6/.gitignore create mode 100644 lib/cosTransactions/doc/pdf/.gitignore create mode 100644 lib/cosTransactions/doc/src/CosTransactions_Control.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_Resource.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_Terminator.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml create mode 100644 lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml create mode 100644 lib/cosTransactions/doc/src/Makefile create mode 100644 lib/cosTransactions/doc/src/book.gif create mode 100644 lib/cosTransactions/doc/src/book.xml create mode 100644 lib/cosTransactions/doc/src/ch_contents.xml create mode 100644 lib/cosTransactions/doc/src/ch_example.xml create mode 100644 lib/cosTransactions/doc/src/ch_install.xml create mode 100644 lib/cosTransactions/doc/src/ch_introduction.xml create mode 100644 lib/cosTransactions/doc/src/ch_skeletons.xml create mode 100644 lib/cosTransactions/doc/src/cosTransactions.xml create mode 100644 lib/cosTransactions/doc/src/fascicules.xml create mode 100644 lib/cosTransactions/doc/src/make.dep create mode 100644 lib/cosTransactions/doc/src/notes.gif create mode 100644 lib/cosTransactions/doc/src/notes.xml create mode 100644 lib/cosTransactions/doc/src/part.xml create mode 100644 lib/cosTransactions/doc/src/part_notes.xml create mode 100644 lib/cosTransactions/doc/src/ref_man.gif create mode 100644 lib/cosTransactions/doc/src/ref_man.xml create mode 100644 lib/cosTransactions/doc/src/summary.html.src create mode 100644 lib/cosTransactions/doc/src/user_guide.gif create mode 100644 lib/cosTransactions/ebin/.gitignore create mode 100644 lib/cosTransactions/examples/Makefile create mode 100644 lib/cosTransactions/include/.gitignore create mode 100644 lib/cosTransactions/info create mode 100644 lib/cosTransactions/priv/.gitignore create mode 100644 lib/cosTransactions/src/CosTransactions.cfg create mode 100644 lib/cosTransactions/src/CosTransactions.idl create mode 100644 lib/cosTransactions/src/CosTransactions_Terminator_impl.erl create mode 100644 lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl create mode 100644 lib/cosTransactions/src/ETraP_Common.erl create mode 100644 lib/cosTransactions/src/ETraP_Common.hrl create mode 100644 lib/cosTransactions/src/ETraP_Server_impl.erl create mode 100644 lib/cosTransactions/src/Makefile create mode 100644 lib/cosTransactions/src/cosTransactions.app.src create mode 100644 lib/cosTransactions/src/cosTransactions.appup.src create mode 100644 lib/cosTransactions/src/cosTransactions.erl create mode 100644 lib/cosTransactions/src/etrap_logmgr.erl create mode 100644 lib/cosTransactions/vsn.mk (limited to 'lib/cosTransactions') diff --git a/lib/cosTransactions/AUTHORS b/lib/cosTransactions/AUTHORS new file mode 100644 index 0000000000..6d03df4c5a --- /dev/null +++ b/lib/cosTransactions/AUTHORS @@ -0,0 +1,4 @@ +Original Authors: +Niclas Eklund + +Contributors: diff --git a/lib/cosTransactions/Makefile b/lib/cosTransactions/Makefile new file mode 100644 index 0000000000..fddfa63db5 --- /dev/null +++ b/lib/cosTransactions/Makefile @@ -0,0 +1,41 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1999-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include vsn.mk +VSN=$(COSTRANSACTIONS_VSN) + +# ---------------------------------------------------- +# Common Macros +# ---------------------------------------------------- +# SUB_DIRECTORIES = src test examples doc/src +# At the moment we don't have any example programs. +SUB_DIRECTORIES = src doc/src + +SPECIAL_TARGETS = + +# ---------------------------------------------------- +# Default Subdir Targets +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_subdir.mk diff --git a/lib/cosTransactions/doc/html/.gitignore b/lib/cosTransactions/doc/html/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/doc/man3/.gitignore b/lib/cosTransactions/doc/man3/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/doc/man6/.gitignore b/lib/cosTransactions/doc/man6/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/doc/pdf/.gitignore b/lib/cosTransactions/doc/pdf/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/doc/src/CosTransactions_Control.xml b/lib/cosTransactions/doc/src/CosTransactions_Control.xml new file mode 100644 index 0000000000..f4d9a38d13 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_Control.xml @@ -0,0 +1,73 @@ + + + + +
+ + 1999 + 2007 + Ericsson AB, All Rights Reserved + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Initial Developer of the Original Code is Ericsson AB. + + + CosTransactions_Control + Niclas Eklund + Niclas Eklund + + Niclas Eklund + + 1999-04-12 + PA1 +
+ CosTransactions_Control + This module implements the OMG CosTransactions::Control interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + get_coordinator(Control) -> Return + Return the Coordinator object associated with the target object + + Control = #objref + Return = Coordinator | {'EXCEPTION', E} + Coordinator = #objref + E = #'CosTransactions_Unavailable' {} + + +

This operation returns the Coordinator object associated with the target object. + The Coordinator supports operations for termination of a transaction.

+
+
+ + get_terminator(Control) -> Return + Return the Terminator object associated with the target object + + Control = #objref + Return = Terminator | {'EXCEPTION', E} + Terminator = #objref + E = #'CosTransactions_Unavailable' {} + + +

This operation returns the Terminator object associated with the target object. + The Terminator supports operations for termination of a transaction.

+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml b/lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml new file mode 100644 index 0000000000..e172951e4e --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml @@ -0,0 +1,229 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + CosTransactions_Coordinator + + + + 1999-04-12 + PA1 +
+ CosTransactions_Coordinator + This module implements the OMG CosTransactions::Coordinator interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + create_subtransaction(Coordinator) -> Control + Create a new subtransaction. + + Coordinator = #objref + Control = #objref + + +

A new subtransaction is created whose parent is the Coordinator argument.

+

Raises exception:

+ + 'SubtransactionsUnavailable' - if nested transactions are not supported. + 'Inactive' - if target transaction has already been prepared. + +
+
+ + get_transaction_name(Coordinator) -> Name + Return the name associated with the object. + + Coordinator = #objref + Name = string() of type "oe_name@machine_type_timestamp" + + +

Returns a printable string, which describe the transaction. The main purpose is to support debugging.

+
+
+ + get_parent_status(Coordinator) -> Status + Return the status of the parent transaction. + + Coordinator = #objref + Status = atom() + + +

Returns the status of the parent transaction + associated with the target object. If the target object is a top-level + transaction this operation is equivalent to get_status/1 operation.

+

Possible Status replies:

+ + 'StatusCommitted' + 'StatusCommitting' + 'StatusMarkedRollback' + 'StatusRollingBack' + 'StatusRolledBack' + 'StatusActive' + 'StatusPrepared' + 'StatusUnknown' + 'StatusNoTransaction' + 'StatusPreparing' + +
+
+ + get_status(Coordinator) -> Status + Return the status of the transaction associated with the target object + + Coordinator = #objref + Status = atom() + + +

Returns the status of the transaction associated with the target object.

+
+
+ + get_top_level_status(Coordinator) -> Status + Return the status of the top-level transaction associated with the target object + + Coordinator = #objref + Status = atom() + + +

Returns the status of the top-level transaction associated with the target object.

+
+
+ + hash_top_level_tran(Coordinator) -> Return + Return a hash code for the top-level transaction associated with the target object + + Coordinator = #objref + Return = integer() + + +

Returns a hash code for the top-level transaction + associated with the target object. Equals the operation + hash_transaction/1 if the target object is a top-level transaction.

+
+
+ + hash_transaction(Coordinator) -> Return + Return a hash code for the transaction associated with the target object. + + Coordinator = #objref + Return = integer() + + +

Returns a hash code for the transaction associated with the target object.

+
+
+ + is_descendant_transaction(Coordinator, OtherCoordinator) -> Return + Return a boolean which indicates whether the transaction associated with the target object is a descendant of the transaction associated with the parameter object + + Coordinator = #objref + OtherCoordinator = #objref + Return = Boolean + + +

Returns true if the transaction associated with the target object is a + descendant of the transaction associated with the parameter object.

+
+
+ + is_same_transaction(Coordinator, OtherCoordinator) -> Return + Return true if the transaction associated with the target object is related to the transaction associated with the parameter object + + Coordinator = #objref + OtherCoordinator = #objref + Return = Boolean + + +

Returns true if the transaction associated with the target object is + related to the transaction associated with the parameter object.

+
+
+ + is_top_level_transaction(Coordinator) -> Return + Return true if the transaction associated with the target object is a top-level transaction + + Coordinator = #objref + Return = Boolean + + +

Returns true if the transaction associated with the target object is + a top-level transaction.

+
+
+ + register_resource(Coordinator, Resource) -> RecoveryCoordinator + Register the parameter Resourceobject as a participant in the transaction associated with the target object + + Coordinator = #objref + Resource = #objref + RecoveryCoordinator = #objref + + +

This operation registers the parameter Resource object as a participant in the + transaction associated with the target object. The RecoveryCoordinator returned + by this operation can be used by this Resource during recovery.

+ +

The Resources will be called in FIFO-order when preparing or committing. + Hence, be sure to register the Resources in the correct order.

+
+

Raises exception:

+ + 'Inactive' - if target transaction has already been prepared. + +
+
+ + register_subtran_aware(Coordinator, SubtransactionAwareResource) -> Return + Register the parameter SubtransactionAwareResourceobject such that it will be notified when the transaction, associated wit the target object, has committed or rolled back + + Coordinator = #objref + Return = ok + + +

This operation registers the parameter SubtransactionAwareResource object such that + it will be notified when the transaction, associated wit the target object, + has committed or rolled back.

+ +

The Resources will be called in FIFO-order. + Hence, be sure to register the Resources in the correct order.

+
+
+
+ + rollback_only(Coordinator) -> Return + Modify the transaction associated with the target object so the only possible outcome is to rollback the transaction + + Coordinator = #objref + Return = ok + + +

The transaction associated with the target object is modified so the only + possible outcome is to rollback the transaction.

+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml b/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml new file mode 100644 index 0000000000..4b870f4b90 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml @@ -0,0 +1,82 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + CosTransactions_­RecoveryCoordinator + ..._RecoveryCoordinator + Niclas Eklund + Niclas Eklund + + Niclas Eklund + + 1999-04-12 + PA1 +
+ CosTransactions_RecoveryCoordinator + This module implements the OMG CosTransactions::RecoveryCoordinator interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + replay_completion(RecoveryCoordinator, Timeout, Resource) -> Return + Return the current status of the transaction + + RecoveryCoordinator = #objref + Timeout = integer(), milliseconds | 'infinity' + Resource = #objref + Return = Status | {'EXCEPTION', E} + E = #'CosTransactions_NotPrepared'{} + Status = atom() + + +

The RecoveryCoordinator object is returned by the operation + CosTransactions_Coordinator:register_resource/3. The replay_completion/2 + may only be used by the registered Resource and returns the current status + of the transaction. The operation is used when recovering after a failure.

+

Possible Status replies:

+ + 'StatusCommitted' + 'StatusCommitting' + 'StatusMarkedRollback' + 'StatusRollingBack' + 'StatusRolledBack' + 'StatusActive' + 'StatusPrepared' + 'StatusUnknown' + 'StatusNoTransaction' + 'StatusPreparing' + + +

replay_completion/3 is blocking and may cause dead-lock if a child + calls this function at the same time as its parent invokes an operation + on the child. Dead-lock will not occur if the timeout has any value except 'infinity'.

+

If the call is external incoming (intra-ORB) the timeout will not be activated. + Hence, similar action must be taken if the Resource resides on another vendors ORB.

+
+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_Resource.xml b/lib/cosTransactions/doc/src/CosTransactions_Resource.xml new file mode 100644 index 0000000000..1f091a5092 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_Resource.xml @@ -0,0 +1,128 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + CosTransactions_Resource + + + + 1999-04-12 + PA1 +
+ CosTransactions_Resource + This module implements the OMG CosTransactions::Resource interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + commit(Resource) -> Return + Instruct the target object to commit the transaction + + Resource = #objref + Return = ok | {'EXCEPTION', E} + E = #'CosTransactions_NotPrepared'{} | #'CosTransactions_HeuristicRollback'{} | #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazard'{} + + +

This operation instructs the Resource to commit all changes made as a part of the transaction.

+

The Resource can raise:

+ + Heuristic Exception - if a Heuristic decision is made which differ + from the true outcome of the transaction. The Resource must remember + the Heuristic outcome until the forget operation is performed. + +
+
+ + commit_one_phase(Resource) -> Return + Instruct the target object to commit the transaction + + Resource = #objref + Return = ok | {'EXCEPTION', E} + E = #'CosTransactions_HeuristicHazard'{} | #'CosTransactions_TransactionRolledBack'{} + + +

If possible, the Resource should commit all changes made as part of the transaction, + else it should raise the TRANSACTION_ROLLEDBACK exception. + This operation can only be used if the Resource is the only child of its parent.

+
+
+ + forget(Resource) -> Return + Instruct the target object to forget any heuristic decisions + + Resource = #objref + Return = ok + + +

This operation informs the Resource that it is safe to forget any Heuristic + decisions and the knowledge of the transaction.

+
+
+ + prepare(Resource) -> Return + Instruct the target object to begin the two-phase commit protocol + + Resource = #objref + Return = Vote | {'EXCEPTION', E} + Vote = 'VoteReadOnly' | 'VoteCommit' | 'VoteRollback' + E = #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazard'{} + + +

This operation is invoked on the Resource to begin the two-phase commit protocol.

+

The Resource can reply:

+ + 'VoteReadOnly' - if no persistent data has been modified by the transaction. + The Resource can forget all knowledge of the transaction. + 'VoteCommit' - if the Resource has been prepared and is able to write all the + data needed to commit the transaction to stable storage. + 'VoteRollback' - under any circumstances but must do so if none of the alternatives above + are applicable. + Heuristic Exception - if a Heuristic decision is made which differ + from the true outcome of the transaction. The Resource must remember + the Heuristic outcome until the forget operation is performed. + +
+
+ + rollback(Resource) -> Return + Instruct the target object to rollback the transaction + + Resource = #objref + Return = ok | {'EXCEPTION', E} + E = #'CosTransactions_HeuristicCommit'{} | #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazard'{} + + +

This operation instructs the Resource to rollback all changes made as a part of the transaction.

+

The Resource can raise:

+ + Heuristic Exception - if a Heuristic decision is made which differ + from the true outcome of the transaction. The Resource must remember + the Heuristic outcome until the forget operation is performed. + +
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml b/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml new file mode 100644 index 0000000000..2c7b6b5215 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml @@ -0,0 +1,75 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + CosTransactions_­SubtransactionAwareResource + ..._SubtransactionAwareResource + + + + 1999-04-12 + PA1 +
+ CosTransactions_SubtransactionAwareResource + This module implements the OMG CosTransactions::SubtransactionAwareResource interface. + +

This interface inherits the CosTransactions::Resource interface. Hence, + it must also support all operations defined in the Resource interface.

+

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + commit_subtransaction(SubtransactionAwareResource, Coordinator) -> Return + Notify the target object that the transaction has committed + + SubtransactionAwareResource = #objref + Coordinator = #objref + Return = ok + + +

If the SubtransactionAwareResource have been registered with a subtransaction + using the operation CosTransactions_Coordinator:register_subtran_aware/2, + it will be notified when the transaction has committed.

+ +

The results of a committed subtransaction are relative to the completion of its ancestor + transactions, that is, these results can be undone if any ancestor transaction is rolled back.

+
+
+
+ + rollback_subtransaction(SubtransactionAwareResource) -> Return + Notify the target object that the transaction has been rolled back + + SubtransactionAwareResource = #objref + Return = ok + + +

If the SubtransactionAwareResource have been registered with a transactions + using the operation CosTransactions_Coordinator:register_subtran_aware/2 + it will be notified when the transaction has rolled back.

+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml b/lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml new file mode 100644 index 0000000000..62d19fe98f --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml @@ -0,0 +1,69 @@ + + + + +
+ + 1999 + 2007 + Ericsson AB, All Rights Reserved + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Initial Developer of the Original Code is Ericsson AB. + + + CosTransactions_Synchronization + Niclas Eklund + Niclas Eklund + + Niclas Eklund + + 1999-04-12 + PA1 +
+ CosTransactions_Synchronization + This module implements the OMG CosTransactions::Synchronization interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/CosTransactions.hrl").

+
+ + + before_completion(Synchronization) -> Return + Notify the target object that the transaction is about to enter the prepare phase + + Synchronization = #objref + Return = ok + + +

If the target object is a transaction using the operation register_synchronization/2 + it will be notified to perform necessary processing prior to the prepare phase.

+
+
+ + after_completion(Synchronization) -> Return + Notify the target object that the transaction is completed + + Synchronization = #objref + Return = ok + + +

If the target object is a transaction using the operation register_synchronization/2 + it will be notified to perform necessary processing after terminating the transaction.

+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_Terminator.xml b/lib/cosTransactions/doc/src/CosTransactions_Terminator.xml new file mode 100644 index 0000000000..0a8ebe6975 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_Terminator.xml @@ -0,0 +1,72 @@ + + + + +
+ + 1999 + 2007 + Ericsson AB, All Rights Reserved + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Initial Developer of the Original Code is Ericsson AB. + + + CosTransactions_Terminator + Niclas Eklund + Niclas Eklund + + Niclas Eklund + + 1999-04-12 + PA1 +
+ CosTransactions_Terminator + This module implements the OMG CosTransactions::Terminator interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + commit(Terminator, ReportHeuristics) -> Return + Try to commit a transaction + + Terminator = #objref + ReportHeuristics = boolean() + Return = ok | {'EXCEPTION', E} + E = #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazrd'{} | #'CosTransactions_TransactionRolledBack'{} + + +

This operation initiates the two-phase commit protocol. If the transaction has not been marked + 'rollback only' and all the participants agree to commit, the operation terminates normally. Otherwise, + the TransactionRolledBack is raised. If the parameter ReportHeuristics is true and inconsistent + outcomes by raising an Heuristic Exception.

+
+
+ + rollback(Terminator) -> Return + Rollback a transaction + + Terminator = #objref + Return = ok + + +

This operation roles back the transaction.

+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml b/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml new file mode 100644 index 0000000000..181801c574 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml @@ -0,0 +1,64 @@ + + + + +
+ + 1999 + 2007 + Ericsson AB, All Rights Reserved + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Initial Developer of the Original Code is Ericsson AB. + + + CosTransactions_­TransactionFactory + ..._TransactionFactory + Niclas Eklund + Niclas Eklund + + Niclas Eklund + + 1999-04-12 + PA1 +
+ CosTransactions_TransactionFactory + This module implements the OMG CosTransactions::TransactionFactory interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+
+ + + create(TransactionFactory, Timeout) -> Control + Create a new top-level transaction + + TransactionFactory = #objref + Timeout = integer() + Control = #objref + + +

This operation creates a new top-level transaction.

+

The Timeout argument can be:

+ + 0 - no timeout. + N (integer() > 0) - the transaction will be subject to being rolled back + if it does not complete before N seconds have elapsed. + +
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml b/lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml new file mode 100644 index 0000000000..0e836f5818 --- /dev/null +++ b/lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml @@ -0,0 +1,42 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + CosTransactions_TransactionalObject + + + + 1999-04-12 + PA1 +
+ CosTransactions_TransactionalObject + This module implements the OMG CosTransactions::TransactionalObject interface. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/CosTransactions.hrl").

+

The TransactionalObject interface is used by an object to indicate that it is transactional. + By supporting this interface, an object indicates that it wants the transaction context associated with + the client to be associated with all operation on its interface. No operations are defined.

+
+ +
+ diff --git a/lib/cosTransactions/doc/src/Makefile b/lib/cosTransactions/doc/src/Makefile new file mode 100644 index 0000000000..eab52d3dc9 --- /dev/null +++ b/lib/cosTransactions/doc/src/Makefile @@ -0,0 +1,229 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1999-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(COSTRANSACTIONS_VSN) +APPLICATION=cosTransactions + +# ---------------------------------------------------- +# Include dependency +# ---------------------------------------------------- + +ifndef DOCSUPPORT +include make.dep +endif + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +XML_APPLICATION_FILES = ref_man.xml +XML_REF3_FILES = \ + cosTransactions.xml \ + CosTransactions_Control.xml \ + CosTransactions_Coordinator.xml \ + CosTransactions_RecoveryCoordinator.xml \ + CosTransactions_Resource.xml \ + CosTransactions_SubtransactionAwareResource.xml \ + CosTransactions_Terminator.xml \ + CosTransactions_TransactionFactory.xml +# CosTransactions_Synchronization.xml + +XML_PART_FILES = \ + part.xml \ + part_notes.xml +XML_CHAPTER_FILES = \ + ch_contents.xml \ + ch_introduction.xml \ + ch_install.xml \ + ch_example.xml \ + ch_skeletons.xml \ + notes.xml + +BOOK_FILES = book.xml + +TECHNICAL_DESCR_FILES = + +GIF_FILES = \ + book.gif \ + notes.gif \ + ref_man.gif \ + user_guide.gif + +PS_FILES = + +# ---------------------------------------------------- + +INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html) + +HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) + +INFO_FILE = ../../info +EXTRA_FILES = summary.html.src \ + $(DEFAULT_GIF_FILES) \ + $(DEFAULT_HTML_FILES) \ + $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) + +MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) + +ifdef DOCSUPPORT + +HTML_REF_MAN_FILE = $(HTMLDIR)/index.html + +TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf + +else + +TEX_FILES_BOOK = \ + $(BOOK_FILES:%.xml=%.tex) +TEX_FILES_REF_MAN = $(XML_REF3_FILES:%.xml=%.tex) \ + $(XML_APPLICATION_FILES:%.xml=%.tex) +TEX_FILES_USERS_GUIDE = \ + $(XML_CHAPTER_FILES:%.xml=%.tex) + +TOP_PDF_FILE = $(APPLICATION)-$(VSN).pdf + +TOP_PS_FILE = $(APPLICATION)-$(VSN).ps + +$(TOP_PDF_FILE): book.dvi ../../vsn.mk + $(DVI2PS) $(DVIPS_FLAGS) -f $< | $(DISTILL) $(DISTILL_FLAGS) > $@ + +$(TOP_PS_FILE): book.dvi ../../vsn.mk + $(DVI2PS) $(DVIPS_FLAGS) -f $< > $@ + +endif + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +XML_FLAGS += +DVIPS_FLAGS += + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +$(HTMLDIR)/%.gif: %.gif + $(INSTALL_DATA) $< $@ + +ifdef DOCSUPPORT + +docs: pdf html man + +$(TOP_PDF_FILE): $(XML_FILES) + +pdf: $(TOP_PDF_FILE) + +html: gifs $(HTML_REF_MAN_FILE) + +clean clean_docs: + rm -rf $(HTMLDIR)/* + rm -f $(MAN3DIR)/* + rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f errs core *~ + +else + +ifeq ($(DOCTYPE),pdf) +docs: pdf +else +ifeq ($(DOCTYPE),ps) +docs: ps +else +docs: html gifs man +endif +endif + +pdf: $(TOP_PDF_FILE) + +ps: $(TOP_PS_FILE) + +html: $(HTML_FILES) $(INTERNAL_HTML_FILES) + +clean clean_docs clean_tex: + rm -f $(TEX_FILES_USERS_GUIDE) $(TEX_FILES_REF_MAN) $(TEX_FILES_BOOK) + rm -f $(HTML_FILES) $(MAN3_FILES) + rm -f $(TOP_PDF_FILE) $(TOP_PS_FILE) + rm -f errs core *~ *xmls_output *xmls_errs $(LATEX_CLEAN) + +endif + +man: $(MAN3_FILES) + +gifs: $(GIF_FILES:%=$(HTMLDIR)/%) + +$(INDEX_TARGET): $(INDEX_SRC) + sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET) + +debug opt: + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +ifdef DOCSUPPORT + +release_docs_spec: docs + $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf + $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf + $(INSTALL_DIR) $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(HTMLDIR)/* \ + $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR) + $(INSTALL_DIR) $(RELEASE_PATH)/man/man3 + $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3 +else + +ifeq ($(DOCTYPE),pdf) +release_docs_spec: pdf + $(INSTALL_DIR) $(RELEASE_PATH)/pdf + $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELEASE_PATH)/pdf +else +ifeq ($(DOCTYPE),ps) +release_docs_spec: ps + $(INSTALL_DIR) $(RELEASE_PATH)/ps + $(INSTALL_DATA) $(TOP_PS_FILE) $(RELEASE_PATH)/ps +else +release_docs_spec: docs + $(INSTALL_DIR) $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \ + $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR) + $(INSTALL_DIR) $(RELEASE_PATH)/man/man3 + $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3 + +endif +endif + +endif + +release_spec: + diff --git a/lib/cosTransactions/doc/src/book.gif b/lib/cosTransactions/doc/src/book.gif new file mode 100644 index 0000000000..94b3868792 Binary files /dev/null and b/lib/cosTransactions/doc/src/book.gif differ diff --git a/lib/cosTransactions/doc/src/book.xml b/lib/cosTransactions/doc/src/book.xml new file mode 100644 index 0000000000..785cf387c0 --- /dev/null +++ b/lib/cosTransactions/doc/src/book.xml @@ -0,0 +1,48 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + cosTransactions + Niclas Eklund + + 1999-04-14 + 2.0 +
+ + + cosTransactions + + + + + + + + + + + + + + +
+ diff --git a/lib/cosTransactions/doc/src/ch_contents.xml b/lib/cosTransactions/doc/src/ch_contents.xml new file mode 100644 index 0000000000..21cefda955 --- /dev/null +++ b/lib/cosTransactions/doc/src/ch_contents.xml @@ -0,0 +1,74 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + The cosTransactions Application + Niclas Eklund + + 1999-04-14 + B + ch_contents.xml +
+ +
+ Content Overview +

The cosTransactions documentation is divided into three sections: +

+ + +

PART ONE - The User's Guide +

+Description of the cosTransactions Application including + services and a small tutorial demonstrating + the development of a simple service.

+
+ +

PART TWO - Release Notes +

+A concise history of cosTransactions.

+
+ +

PART THREE - The Reference Manual +

+ A quick reference guide, including a + brief description, to all the functions available in cosTransactions.

+
+
+
+ +
+ Brief Description of the User's Guide +

The User's Guide contains the following parts:

+ + +

cosTransactions overview

+
+ +

cosTransactions installation

+
+ +

A tutorial example

+
+
+
+
+ diff --git a/lib/cosTransactions/doc/src/ch_example.xml b/lib/cosTransactions/doc/src/ch_example.xml new file mode 100644 index 0000000000..65350166f0 --- /dev/null +++ b/lib/cosTransactions/doc/src/ch_example.xml @@ -0,0 +1,280 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + cosTransactions Examples + + + 1999-04-27 + A + ch_example.xml +
+ +
+ A Tutorial on How to Create a Simple Service + +
+ Interface design +

To use the cosTransactions application participants must be implemented. + There are two types of participants:

+ + CosTransactions_Resource - operations used to commit or rollback resources. + CosTransactions_SubtransactionAwareResource - + operations used when the resources want to be notified when a subtransaction commits. + This interface inherits the CosTransactions_Resource + +

The interfaces for these participants are defined in CosTransactions.idl

+
+ +
+ Generating a Participant Interface +

We start by creating an interface which inherits from CosTransactions::Resource. Hence, + we must also implement all operations defined in the Resource interface. The IDL-file could look like:

+ + +module ownResourceImpl { + + interface ownInterface:CosTransactions::Resource { + + void ownFunctions(in any NeededArguments) + raises(Systemexceptions,OwnExceptions); + + }; +}; + +#endif + ]]> +

Run the IDL compiler on this file by calling the ic:gen/1 function. + This will produce the API named ownResourceImpl_ownInterface.erl. + After generating the API stubs and the server skeletons it is time to + implement the servers and if no special options are sent + to the IDl compiler the file name is ownResourceImpl_ownInterface_impl.erl.

+
+ +
+ Implementation of Participant interface +

If the participant is intended to be a plain Resource, we must implement the following operations:

+ + prepare/1 - this operation is invoked on the Resource to begin the two-phase commit protocol. + rollback/1 - this operation instructs the Resource to rollback all changes made as a part of the transaction. + commit/1 - this operation instructs the Resource to commit all changes made as a part of the transaction. + commit_one_phase/1 - if possible, the Resource should commit all changes made as part of the transaction. + This operation can only be used if the Resource is the only child of its parent. + forget/1 - this operation informs the Resource that it is safe to forget any + Heuristic decisions is a unilateral decision by a participant to commit or rollback without receiving the true outcome of the transaction from its parents coordinator.and the knowledge of the transaction. + ownFunctions - all application specific operations. + +

If the participant wants to be notified when a subtransaction commits, we must also implement the following operations + (besides the operations above):

+ + commit_subtransaction/2 - if the SubtransactionAwareResource have been registered + with a transactions using the operation CosTransactions_Coordinator:register_subtran_aware/2 it will + be notified when the transaction has + committed. + rollback_subtransaction/1 - if the SubtransactionAwareResource have been registered + with a transactions using the operation CosTransactions_Coordinator:register_subtran_aware/2 + it will be notified when the transaction has + rolled back. + + +

The results of a committed subtransaction are relative to the completion of its ancestor transactions, + that is, these results can be undone if any ancestor transaction is rolled back.

+
+
+ +
+ Participant Operations Behavior +

Each application participant must behave in a certain way to ensure that the two-phase commit protocol + can complete the transactions correctly.

+ +
+ prepare +

This operation ask the participant to vote on the outcome of the transaction. Possible replies are:

+ + 'VoteReadOnly' - if no data associated with the transaction has been modified VoteReadOnly may be returned. + The Resource can forget all knowledge of the transaction and terminate. + 'VoteCommit' - if the Resource is able to write all the data needed to commit the transaction to a stable storage, + VoteCommit may be returned. The Resource will then wait until it is informed of the outcome of the transaction. + The Resource may, however, make a unilateral decision (Heuristic) to commit or rollback changes associated + with the transaction. When the Resource is informed of the true outcome (rollback/commit) and it is equal to + the Heuristic decision the Resource just return 'ok'. But, if there is a mismatch and the commit-operation is irreversible, + the Resource must raise a Heuristic Exception and wait + until the forget operation is invoked. The Heuristic Decision must be recorded in stable storage. + 'VoteRollback' - the Resource may vote VoteRollback under any circumstances. + The Resource can forget all knowledge of the transaction and terminate. + + +

Before replying to the prepare operation, the Resource must record the prepare state, the reference of its + superior RecoveryCoordinator in stable storage. + The RecoveryCoordinator is obtained when registering as a participant in a transaction.

+
+
+ +
+ rollback +

The Resource should, if necessary, rollback all changes made as part of the transaction. If the Resource is not aware of the + transaction it should do nothing, e.g., recovered after a failure and have no data in stable storage. Heuristic Decisions + must be handled as described above.

+
+ +
+ commit +

The Resource should, if necessary, commit all changes made as part of the transaction. If the Resource is not aware of the + transaction it should do nothing, e.g., recovered after a failure and have no data in stable storage. Heuristic Decisions + must be handled as described above.

+
+ +
+ commit_one_phase +

If possible, the Resource should commit all changes made as part of the transaction. If it cannot, it should raise the + TRANSACTION_ROLLEDBACK exception. This operation can only be used if the Resource is the only child of its parent. + If a failure occurs the completion of the operation must be retried when the failure is repaired. Heuristic Decisions + must be handled as described above.

+
+ +
+ forget +

If the Resource raised a Heuristic Exception to commit, rollback or commit_one_phase this operation + will be performed. The Resource can forget all knowledge of the transaction and terminate.

+
+ +
+ commit_subtransaction +

If the SubtransactionAwareResource have been registered with a subtransaction + using the operation CosTransactions_Coordinator:register_subtran_aware/2 + it will be notified when the transaction has committed. The Resource may raise the exception + 'TRANSACTION_ROLLEDBACK'.

+ +

The result of a committed subtransaction is relative to the completion of its ancestor + transactions, that is, these results can be undone if any ancestor transaction is rolled back.

+
+
+ +
+ rollback_subtransaction +

If the SubtransactionAwareResource have been registered with a subtransaction + using the operation CosTransactions_Coordinator:register_subtran_aware/2 + it will be notified when the subtransaction has rolled back.

+
+
+ +
+ How to Run Everything +

Below is a short transcript on how to run cosTransactions.

+ + +%% Start Mnesia and Orber +mnesia:delete_schema([node()]), +mnesia:create_schema([node()]), +orber:install([node()]), +application:start(mnesia), +application:start(orber), + +%% Register CosTransactions in the IFR. +'oe_CosTransactions':'oe_register'(), + +%% Register the application specific Resource implementations +%% in the IFR. +'oe_ownResourceImpl':'oe_register'(), + +%%-- Set parameters -- +%% Timeout can be either 0 (no timeout) or an integer N > 0. +%% The later state that the transaction should be rolled +%% back if the transaction have not completed within N seconds. +TimeOut = 0, + +%% Do we want the transaction to report Heuristic Exceptions? +%% This variable must be boolean and indicates the way the +%% Terminator should behave. +Heuristics = true, + +%% Start the cosTransactions application. +cosTransactions:start(), %% or application:start(cosTransactions), + +%% Start a factory using the default configuration +TrFac = cosTransactions:start_factory(), +%% ... or use configuration parameters. +TrFac = cosTransactions:start_factory([{typecheck, false}, {hash_max, 3013}]), + +%% Create a new top-level transaction. +Control = 'CosTransactions_TransactionFactory':create(TrFac, TimeOut), + +%% Retrieve the Coordinator and Terminator object references from +%% the Control Object. +Term = 'CosTransactions_Control':get_terminator(Control), +Coord = 'CosTransactions_Control':get_coordinator(Control), + +%% Create two SubTransactions with the root-Coordinator as parent. +SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord), +SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord), + +%% Retrieve the Coordinator references from the Control Objects. +SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1), +SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2), + +%% Create application Resources. We can, for example, start the Resources +%% our selves or look them up in the naming service. This is application +%% specific. +Res1 = ... +Res2 = ... +Res3 = ... +Res4 = ... + +%% Register Resources with respective Coordinator. Each call returns +%% a RecoveryCoordinator object reference. +RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, Res1), +RC2 = 'CosTransactions_Coordinator':register_resource(SubCoord1, Res2), +RC3 = 'CosTransactions_Coordinator':register_resource(SubCoord2, Res3), +RC4 = 'CosTransactions_Coordinator':register_resource(SubCoord2, Res4), + +%% Register Resource 4 with SubCoordinator 1 so that the Resource will be +%% informed when the SubCoordinator commits or roll-back. +'CosTransactions_Coordinator':register_subtran_aware(SubCoord1, Res4), + +%% We are now ready to try to commit the transaction. The second argument +%% must be a boolean +Outcome = (catch 'CosTransactions_Terminator':commit(Term, Heuristics)), + + +

For the cosTransaction application to be able to recognize if a Resource is + dead or in the process of restarting the Resource must be started as persistent, + e.g., 'OwnResource':oe_create_link(Env, [{regname, {global, RegName}}, {persistent, true}]). + For more information see the Orber documentation.

+
+

The outcome of the transaction can be:

+ + ok - the transaction was successfully committed. + {'EXCEPTION', HeuristicExc} - at least one participant made a + Heuristic decision or, due to a failure, one or more participants + where unreachable. + {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}} - + the transaction was successfully rolled back. + Any system exception - + the transaction failed with unknown reason. + +
+
+
+ diff --git a/lib/cosTransactions/doc/src/ch_install.xml b/lib/cosTransactions/doc/src/ch_install.xml new file mode 100644 index 0000000000..d4b64d3987 --- /dev/null +++ b/lib/cosTransactions/doc/src/ch_install.xml @@ -0,0 +1,103 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Installing cosTransactions + + + 1999-04-20 + + ch_install.xml +
+ +
+ Installation Process +

This chapter describes how to install + cosTransactions + in an Erlang Environment. +

+ +
+ Preparation +

Before starting the installation process for cosTransactions, + the application Orber must be running.

+

The cosTransactions application must be able to log progress to disk. The log files are + created in the current directory as "oe_name@machine_type_timestamp". Hence, read and + write rights must be granted. If the transaction completes in an orderly fashion the + logfiles are removed, but not if an error, which demands human intervention, occur.

+
+ +
+ Configuration +

When using the Transaction Service the cosTransactions application + must be started using either cosTransactions:start() or + application:start(cosTransactions). +

+

The following application configuration parameters exist:

+ + maxRetries - default is 40 times, i.e., if a transaction participant is unreachable + the application will retry to contact it N times. Reaching the maximum is considered to be a disaster. + comFailWait - default is 5000 milliseconds, i.e., before the application + retries to contact unreachable transaction participants the application wait Time milliseconds. + +

Then the Transaction Factory + must be started:

+ + cosTransactions:start_factory() - starts and returns a reference to a factory using default configuration parameters. + cosTransactions:start_factory(Options) - starts and returns a reference to a factory using given configuration parameters. + +

The following options exist: +

+ + {hash_max, HashValue} - + This value denotes the upper bound of the hash value the Coordinator uses. + Default is 1013. HashValue must be an integer. + {allow_subtr, Boolean} - + If set to true it is possible to create subtransactions. + Default is true. + {typecheck, Boolean} - + If set to to true all transaction operation's arguments will be type-checked. + Default is true. + {tty, Boolean} - + Enables or disables error printouts to the tty. + If Flag is false, all text that the error logger would have sent to the terminal is discarded. + If Flag is true, error messages are sent to the terminal screen. + {logfile, FileName} - + This function makes it possible to store all system information in FileName (string()). + It can be used in combination with the tty(false) item to have a silent system, + where all system information are logged to a file. + As default no logfile is used. + {maxRetries, Integer} - + default is 40 times, i.e., if a transaction participant is unreachable the application will + retry to contact it N times. Reaching the maximum is considered to be a disaster. + This option overrides the application configuration parameter. + {comFailWait, Integer} - + default is 5000 milliseconds, i.e., before the application retries to contact unreachable + transaction participants the application wait Time milliseconds. + This option overrides the application configuration parameter. + +

The Factory is now ready to use. For a more detailed description see Examples. +

+
+
+
+ diff --git a/lib/cosTransactions/doc/src/ch_introduction.xml b/lib/cosTransactions/doc/src/ch_introduction.xml new file mode 100644 index 0000000000..b0e58c5528 --- /dev/null +++ b/lib/cosTransactions/doc/src/ch_introduction.xml @@ -0,0 +1,64 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Introduction to cosTransactions + Niclas Eklund + + 1999-04-26 + + ch_introduction.xml +
+ +
+ Overview +

The cosTransactions application is a Transaction Service compliant with the OMG + Transaction Service CosTransactions 1.1. +

+ +
+ Purpose and Dependencies +

cosTransactions is dependent on Orber version 3.0.1 or later(see the Orber + documentation), which provides CORBA functionality in an Erlang environment.

+

cosTransactions is dependent on supervisor/stdlib-1.7 or later.

+

Basically, cosTransaction implements a two-phase commit protocol and allows objects running + on different platforms to participate in a transaction.

+
+ +
+ Prerequisites +

To fully understand the concepts presented in the + documentation, it is recommended that the user is familiar + with distributed programming, CORBA and the Orber application. +

+

Recommended reading includes CORBA, Fundamentals and Programming - Jon Siegel and Open Telecom Platform Documentation Set. It is also helpful to have read + Concurrent Programming in Erlang and, for example, Transaction Processing: concepts and techniques - Jim Gray, Andreas Reuter.

+ +

The cosTransaction application is compliant with the OMG CosTransactions specification 1.1. Using + other vendors transaction service, compliant with the OMG CosTransactions specification 1.0, may + not work since the 'TRANSACTION_REQUIRED', 'TRANSACTION_ROLLEDBACK' and 'INVALID_TRANSACTION' + exceptions have been redefined to be system exceptions, i.e., used to be transaction-specific ('CosTransactions_Exc').

+
+
+
+
+ diff --git a/lib/cosTransactions/doc/src/ch_skeletons.xml b/lib/cosTransactions/doc/src/ch_skeletons.xml new file mode 100644 index 0000000000..a6dd41f929 --- /dev/null +++ b/lib/cosTransactions/doc/src/ch_skeletons.xml @@ -0,0 +1,213 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Resource Skeletons + Niclas Eklund + + 1999-04-29 + + ch_skeletons.xml +
+ +
+ Resource Skeletons +

This chapter provides a skeleton for application Resources. For more information + see the Orber documentation.

+ +%%%----------------------------------------------------------- +%%% File : Module_Interface_impl.erl +%%% Author : +%%% Purpose : +%%% Created : +%%%----------------------------------------------------------- + +-module('Module_Interface_impl'). + +%%--------------- INCLUDES ----------------------------------- +-include_lib("orber/include/corba.hrl"). +-include_lib("cosTransactions/include/CosTransactions.hrl"). + +%%--------------- EXPORTS------------------------------------- +%%- Inherit from CosTransactions::Resource ------------------- +-export([prepare/2, + rollback/2, + commit/2, + commit_one_phase/2, + forget/2]). + +%%- Inherit from CosTransactions::SubtransactionAwareResource +-export([commit_subtransaction/3, + rollback_subtransaction/2]). + +%%--------------- gen_server specific ------------------------ +-export([init/1, terminate/2, code_change/3, handle_info/2]). + +%%------------------------------------------------------------ +%% function : gen_server specific +%%------------------------------------------------------------ +init(Env) -> + %% 'trap_exit' optional + process_flag(trap_exit,true), + + %%--- Possible replies --- + %% Reply and await next request + {ok, State}. + + %% Reply and if no more requests within Time the special + %% timeout message should be handled in the + %% Module_Interface_impl:handle_info/2 call-back function (use the + %% IC option {{handle_info, "Module::Interface"}, true}). + {ok, State, TimeOut}. + + %% Return ignore in order to inform the parent, especially if it is a + %% supervisor, that the server, as an example, did not start in + %% accordance with the configuration data. + ignore. + + %% If the initializing procedure fails, the reason + %% is supplied as StopReason. + {stop, StopReason}. + + +terminate(Reason, State) -> + ok. + +code_change(OldVsn, State, Extra) -> + {ok, NewState}. + +%% If use IC option {{handle_info, "Module::Interface"}, true} +handle_info(Info, State) -> + %%--- Possible replies --- + %% Await the next invocation. + {noreply, State}. + %% Stop with Reason. + {stop, Reason, State}. + + +%%- Inherit from CosTransactions::Resource ------------------- +prepare(State) -> + + %%% Do application specific actions here %%% + + %%-- Reply: -- + %% If no data related to the transaction changed. + {reply, 'VoteReadOnly', State} + %% .. or (for example): + {stop, normal, 'VoteReadOnly', State}. + + %% If able to commit + {reply, 'VoteCommit', State} + + %% If not able to commit + {reply, 'VoteRollback', State} + %% .. or (for example): + {stop, normal, 'VoteRollback', State}. + +rollback(State) -> + + %%% Do application specific actions here %%% + + %%-- Reply: -- + %% If able to rollback successfully + {reply, ok, State} + %% .. or (for example): + {stop, normal, ok, State}. + + %% If Heuristic Decision. Raise exception: + corba:raise(#'CosTransactions_HeuristicMixed' {}) + corba:raise(#'CosTransactions_HeuristicHazard' {}) + corba:raise(#'CosTransactions_HeuristicCommit'{}) + + +commit(State) -> + + %%% Do application specific actions here %%% + + %%-- Reply: -- + %% If able to commit successfully + {reply, ok, State} + %% .. or (for example): + {stop, normal, ok, State}. + + %% If the prepare operation never been invoked: + corba:raise(#'CosTransactions_NotPrepared'{}) + + %% If Heuristic Decision. Raise exception: + corba:raise(#'CosTransactions_HeuristicMixed' {}) + corba:raise(#'CosTransactions_HeuristicHazard' {}) + corba:raise(#'CosTransactions_HeuristicRollback'{}) + + +commit_one_phase(State) -> + + %%% Do application specific actions here %%% + + %%-- Reply: -- + %% If able to commit successfully + {reply, ok, State} + %% .. or (for example): + {stop, normal, ok, State}. + + %% If fails. Raise exception: + corba:raise(#'CosTransactions_HeuristicHazard' {}) + + %% If able to rollback successfully + corba:raise(#'CosTransactions_TransactionRolledBack' {}) + + +forget(State) -> + + %%% Do application specific actions here %%% + + %%-- Reply: -- + {reply, ok, State}. + %% .. or (for example): + {stop, normal, ok, State}. + + + +%%%%%% If the Resource is also supposed to be a %%%%%% +%%%%%% SubtransactionAwareResource implement these. %%%%%% + +%%- Inherit from CosTransactions::SubtransactionAwareResource +commit_subtransaction(State, Parent) -> + %%% Do application specific actions here %%% + + %%-- Reply: -- + {reply, ok, State}. + %% .. or (for example): + {stop, normal, ok, State}. + +rollback_subtransaction(State) -> + %%% Do application specific actions here %%% + + %%-- Reply: -- + {reply, ok, State}. + %% .. or (for example): + {stop, normal, ok, State}. + +%%--------------- END OF MODULE ------------------------------ + +
+
+ diff --git a/lib/cosTransactions/doc/src/cosTransactions.xml b/lib/cosTransactions/doc/src/cosTransactions.xml new file mode 100644 index 0000000000..836506974c --- /dev/null +++ b/lib/cosTransactions/doc/src/cosTransactions.xml @@ -0,0 +1,141 @@ + + + + +
+ + 1999 + 2007 + Ericsson AB, All Rights Reserved + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Initial Developer of the Original Code is Ericsson AB. + + + cosTransactions + Niclas Eklund + Niclas Eklund + + Niclas Eklund + + 1999-04-23 + PA1 +
+ cosTransactions + The main module of the cosTransactions application. + +

To get access to the record definitions for the structures use:

+-include_lib("cosTransactions/include/CosTransactions.hrl").

+

This module contains the functions for starting and stopping the application. + If the application is started using application:start(cosTransactions) the + default configuration is used (see listing below). The Factory reference is stored using the CosNaming Service + under the id "oe_cosTransactionsFac_IPNo".

+

The following application configuration parameters exist:

+ + maxRetries - default is 40 times, i.e., if a transaction participant is unreachable + the application will retry to contact it N times. Reaching the maximum is considered to be a disaster. + comFailWait - default is 5000 milliseconds, i.e., before the application + retries to contact unreachable transaction participants the application wait Time milliseconds. + +
+ + + start() -> Return + Start the cosTransactions application + + Return = ok | {error, Reason} + + +

This operation starts the cosTransactions application.

+
+
+ + stop() -> Return + Stop the cosTransactions application + + Return = ok | {error, Reason} + + +

This operation stops the cosTransactions application.

+
+
+ + start_factory() -> TransactionFactory + Start a Transaction Factory + + TransactionFactory = #objref + + +

This operation creates a Transaction Factory. + The Factory is used to create a new top-level transaction using default options (see listing below).

+
+
+ + start_factory(FacDef) -> TransactionFactory + Start a Transaction Factorywith given options + + FacDef = [Options], see Option listing below. + TransactionFactory = #objref + + +

This operation creates a Transaction Factory. + The Factory is used to create a new top-level transaction.

+

The FacDef list must be a list of {Item, Value} tuples, + where the following values are allowed:

+ + {hash_max, HashValue} - + This value denotes the upper bound of the hash value the + Coordinator uses. + Default is 1013. HashValue must be an integer. + {allow_subtr, Boolean} - + If set to true it is possible to create subtransactions. + Default is true. + {typecheck, Boolean} - + If set to to true all transaction operation's arguments will be type-checked. + Default is true. + {tty, Boolean} - + Enables or disables error printouts to the tty. + If Flag is false, all text that the error logger would have sent to the terminal is discarded. + If Flag is true, error messages are sent to the terminal screen. + {logfile, FileName} - + This function makes it possible to store all system information in FileName (string()). + It can be used in combination with the tty(false) item in to have a silent system, + where all system information are logged to a file. + As default no logfile is used. + {maxRetries, Integer} - + default is 40 times, i.e., if a transaction participant is unreachable the application will + retry to contact it N times. Reaching the maximum is considered to be a disaster. + This option overrides the application configuration parameter. + {comFailWait, Integer} - + default is 5000 milliseconds, i.e., before the application retries to contact unreachable + transaction participants the application wait Time milliseconds. + This option overrides the application configuration parameter. + +
+
+ + stop_factory(TransactionFactory) -> Reply + Terminate the target object + + TransactionFactory = #objref + Reply = ok | {'EXCEPTION', E} + + +

This operation stop the target transaction factory.

+
+
+
+ +
+ diff --git a/lib/cosTransactions/doc/src/fascicules.xml b/lib/cosTransactions/doc/src/fascicules.xml new file mode 100644 index 0000000000..0678195e07 --- /dev/null +++ b/lib/cosTransactions/doc/src/fascicules.xml @@ -0,0 +1,18 @@ + + + + + + User's Guide + + + Reference Manual + + + Release Notes + + + Off-Print + + + diff --git a/lib/cosTransactions/doc/src/make.dep b/lib/cosTransactions/doc/src/make.dep new file mode 100644 index 0000000000..bd45aea286 --- /dev/null +++ b/lib/cosTransactions/doc/src/make.dep @@ -0,0 +1,27 @@ +# ---------------------------------------------------- +# >>>> Do not edit this file <<<< +# This file was automaticly generated by +# /home/otp/bin/docdepend +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# TeX files that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: CosTransactions_Control.tex CosTransactions_Coordinator.tex \ + CosTransactions_RecoveryCoordinator.tex CosTransactions_Resource.tex \ + CosTransactions_SubtransactionAwareResource.tex \ + CosTransactions_Terminator.tex CosTransactions_TransactionFactory.tex \ + book.tex ch_contents.tex ch_example.tex ch_install.tex \ + ch_introduction.tex ch_skeletons.tex cosTransactions.tex \ + part.tex ref_man.tex + +# ---------------------------------------------------- +# Source inlined when transforming from source to LaTeX +# ---------------------------------------------------- + +book.tex: ref_man.xml + +ch_example.tex: ../../../../system/doc/definitions/term.defs + diff --git a/lib/cosTransactions/doc/src/notes.gif b/lib/cosTransactions/doc/src/notes.gif new file mode 100644 index 0000000000..e000cca26a Binary files /dev/null and b/lib/cosTransactions/doc/src/notes.gif differ diff --git a/lib/cosTransactions/doc/src/notes.xml b/lib/cosTransactions/doc/src/notes.xml new file mode 100644 index 0000000000..953382ef87 --- /dev/null +++ b/lib/cosTransactions/doc/src/notes.xml @@ -0,0 +1,243 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + cosTransactions Release Notes + Niclas Eklund + Niclas Eklund + + + + 99-04-14 + A + notes.xml +
+ +
+ cosTransactions 1.2.8 + +
+ Improvements and New Features + + +

+ The documentation is now built with open source tools (xsltproc and fop) + that exists on most platforms. One visible change is that the frames are removed.

+

+ Own Id: OTP-8201 Aux Id:

+
+
+
+
+ +
+ cosTransactions 1.2.7 + +
+ Improvements and New Features + + +

Obsolete guards, e.g. record vs is_record, has been changed + to avoid compiler warnings.

+

Own id: OTP-7987

+
+
+
+
+ +
+ cosTransactions 1.2.6 + +
+ Improvements and New Features + + +

Updated file headers.

+

Own id: OTP-7837

+
+
+
+
+ +
+ cosTransactions 1.2.5 + +
+ Improvements and New Features + + +

Documentation source included in open source releases.

+

Own id: OTP-7595

+
+
+
+
+ +
+ cosTransactions 1.2.4 + +
+ Improvements and New Features + + +

Updated file headers.

+

Own id: OTP-7011

+
+
+
+
+ +
+ cosTransactions 1.2.3 + +
+ Improvements and New Features + + +

The documentation source has been converted from SGML to XML.

+

Own id: OTP-6754 Aux Id:

+
+
+
+
+ +
+ cosTransactions 1.2.2 + +
+ Improvements and New Features + + +

Minor Makefile changes.

+

Own id: OTP-6701 Aux Id:

+
+
+
+
+ +
+ cosTransactions 1.2.1 + +
+ Improvements and New Features + + +

Removed some unused code.

+

Own id: OTP-6527 Aux Id:

+
+
+
+
+ +
+ cosTransactions 1.2 + +
+ Improvements and New Features + + +

The stub/skeleton-files generated by IC have been improved, + i.e., depending on the IDL-files, reduced the size of the + erl- and beam-files and decreased dependencies off Orber's + Interface Repository. It is necessary to re-compile all IDL-files + and use COS-applications, including Orber, compiled with + IC-4.2.

+

Own id: OTP-4576

+
+
+
+
+ +
+ cosTransactions 1.1.2 + +
+ Improvements and New Features + + +

To avoid un-necessary Heuristic decisions cosTransactions now + recognize more systems exceptions.

+

Own Id: OTP-4485

+
+
+
+
+ +
+ cosTransactions 1.1.1.1 + +
+ Improvements and New Features + + +

Updated internal documentation.

+
+
+
+
+ +
+ cosTransactions 1.1.1 + +
+ Improvements and New Features + + +

cosTransactions is now able to handle upgrade properly.

+

Own Id: -

+
+ +

The cosTransactions factory now accepts maxRetries and + comFailWait options, which overrides the configuration parameters.

+

Own Id: -

+
+
+
+ +
+ Incompatibilities + + +

The configuration parameters comm_failure_wait and max_retries + changed to maxRetries and comFailWait. The default value for + maxRetries have been raised from 20 to 40.

+

Own Id: -

+
+
+
+
+ +
+ cosTransactions 1.1 + +
+ Improvements and New Features + + +

First release of the cosTransactions application.

+

Own Id: OTP-1741

+
+
+
+
+
+ diff --git a/lib/cosTransactions/doc/src/part.xml b/lib/cosTransactions/doc/src/part.xml new file mode 100644 index 0000000000..b5a8397525 --- /dev/null +++ b/lib/cosTransactions/doc/src/part.xml @@ -0,0 +1,40 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + cosTransactions User's Guide + Niclas Eklund + + 1999-04-20 + 2.2 +
+ +

The cosTransactions application is an Erlang implementation + of the OMG CORBA Transaction Service.

+
+ + + + + +
+ diff --git a/lib/cosTransactions/doc/src/part_notes.xml b/lib/cosTransactions/doc/src/part_notes.xml new file mode 100644 index 0000000000..16e1968093 --- /dev/null +++ b/lib/cosTransactions/doc/src/part_notes.xml @@ -0,0 +1,36 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + cosTransactions Release Notes + + + 1999-04-14 + 2.0 +
+ +

The cosTransactions Application is an Erlang implementation of the OMG + CORBA Transaction Service.

+
+ +
+ diff --git a/lib/cosTransactions/doc/src/ref_man.gif b/lib/cosTransactions/doc/src/ref_man.gif new file mode 100644 index 0000000000..b13c4efd53 Binary files /dev/null and b/lib/cosTransactions/doc/src/ref_man.gif differ diff --git a/lib/cosTransactions/doc/src/ref_man.xml b/lib/cosTransactions/doc/src/ref_man.xml new file mode 100644 index 0000000000..b662f30b28 --- /dev/null +++ b/lib/cosTransactions/doc/src/ref_man.xml @@ -0,0 +1,43 @@ + + + + +
+ + 19992009 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + cosTransactions Reference Manual + Niclas Eklund + + 1999-04-14 + 2.0 +
+ +

The cosTransactions application is an Erlang implementation + of the OMG CORBA Transaction Service.

+
+ + + + + + + + +
+ diff --git a/lib/cosTransactions/doc/src/summary.html.src b/lib/cosTransactions/doc/src/summary.html.src new file mode 100644 index 0000000000..8fb7d6ea20 --- /dev/null +++ b/lib/cosTransactions/doc/src/summary.html.src @@ -0,0 +1 @@ +Orber OMG Transaction Service \ No newline at end of file diff --git a/lib/cosTransactions/doc/src/user_guide.gif b/lib/cosTransactions/doc/src/user_guide.gif new file mode 100644 index 0000000000..e6275a803d Binary files /dev/null and b/lib/cosTransactions/doc/src/user_guide.gif differ diff --git a/lib/cosTransactions/ebin/.gitignore b/lib/cosTransactions/ebin/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/examples/Makefile b/lib/cosTransactions/examples/Makefile new file mode 100644 index 0000000000..24cd12202a --- /dev/null +++ b/lib/cosTransactions/examples/Makefile @@ -0,0 +1,157 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1999-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +# +include $(ERL_TOP)/make/target.mk + +EBIN= ../ebin + +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(COSTRANSACTIONS_VSN) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/cosTransactions-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +INETRC_EXAMPLE = \ +# inetrc + +IDL_FILES = \ +# hotel.idl \ +# travelAgency.idl + +GEN_ERL_MODULES = \ +# oe_travelAgency \ +# travelAgency_book \ + +MODULES= \ +# travelAgency_book_impl \ + +GEN_HRL_FILES = \ +# oe_travelAgency.hrl \ +# travelAgency_book.hrl + +HRL_FILES= + +ERL_FILES= $(MODULES:%=%.erl) + +JAVA_CLASSES = \ +# HotelResource + +JAVA_FILES= $(JAVA_CLASSES:%=%.java) +CLASS_FILES= $(JAVA_CLASSES:%=%.class) + +TARGET_FILES = \ + $(GEN_ERL_MODULES:%=$(EBIN)/%.$(EMULATOR)) \ + $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + + +ifeq ($(findstring sparc-sun-solaris2, $(TARGET)),sparc-sun-solaris2) + JAVA_TARGET=java +endif + +# ---------------------------------------------------- +# PROGRAMS +# ---------------------------------------------------- +JAVA_IDL = idl +LOCAL_CLASSPATH = $(ERL_TOP)/lib/cosTransactions/priv:$(ERL_TOP)/lib/cosTransactions/examples/java_output:$(ERL_TOP)/lib/cosTransactions/src:$(ERL_TOP)/lib/cosTransactions/examples:$(ERL_TOP)/lib/cosTransactions/examples/java_output/hotel + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_IDL_FLAGS += -pa /clearcase/otp/libraries/cosTransactions/ebin -pa /clearcase/otp/libraries/ic/ebin +# includes from other directories than ../include . +ERL_COMPILE_FLAGS += \ + $(ERL_IDL_FLAGS) \ + -pa /clearcase/otp/libraries/cosTransactions -I/clearcase/otp/libraries/cosTransactions +YRL_FLAGS = + +JAVA_OPTIONS = -classpath ../priv:/opt/local/pgm/OrbixWeb2.0.1 + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +tests debug opt: $(TARGET_FILES) $(JAVA_TARGET) + +java: java_costransactions_idl java_objects +# java_hotel_idl + +clean: + rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) + rm -rf java_costransactions_idl + rm -rf java_output/* + rm -f errs core *~ +# rm -rf java_hotel_idl + +docs: + +java_costransactions_idl: + $(JAVA_IDL) ../src/CosTransactions.idl + @if [ -d java_output ]; then \ + echo "compiling java classes for CosTransactions ... This will take a while!!"; \ + CLASSPATH="${CLASSPATH}:${LOCAL_CLASSPATH}"; \ + export CLASSPATH;\ + (cd java_output/CosTransactions; $(JAVA) *.java;); \ + fi + @touch java_costransactions_idl + +#java_hotel_idl: +# $(JAVA_IDL) hotel.idl +# @if [ -d java_output ]; then \ +# echo "compiling java classes for hotel ..."; \ +# CLASSPATH="${CLASSPATH}:${LOCAL_CLASSPATH}"; \ +# export CLASSPATH;\ +# (cd java_output/hotel; $(JAVA) *.java;); \ +# fi +# @touch java_hotel_idl + +#java_objects: +# @if [ -d java_output ]; then \ +# echo "compiling java example files ..."; \ +# CLASSPATH="${CLASSPATH}:${LOCAL_CLASSPATH}"; \ +# export CLASSPATH;\ +# $(JAVA) *.java; \ +# fi +# @touch java_hotel_resource + +#oe_travelAgency.erl: travelAgency.idl +# erlc $(ERL_IDL_FLAGS) travelAgency.idl + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/examples + $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(IDL_FILES) $(RELSYSDIR)/examples + $(INSTALL_DATA) $(INETRC_EXAMPLE) $(RELSYSDIR)/examples + @tar cf - java_output | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: diff --git a/lib/cosTransactions/include/.gitignore b/lib/cosTransactions/include/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/info b/lib/cosTransactions/info new file mode 100644 index 0000000000..e5d7c53ac0 --- /dev/null +++ b/lib/cosTransactions/info @@ -0,0 +1,2 @@ +group: orb +short: Orber OMG Transaction Service diff --git a/lib/cosTransactions/priv/.gitignore b/lib/cosTransactions/priv/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cosTransactions/src/CosTransactions.cfg b/lib/cosTransactions/src/CosTransactions.cfg new file mode 100644 index 0000000000..05709d21cf --- /dev/null +++ b/lib/cosTransactions/src/CosTransactions.cfg @@ -0,0 +1,15 @@ +{this, "CosTransactions::Coordinator"}. +{this, "CosTransactions::RecoveryCoordinator"}. +{this, "CosTransactions::Terminator"}. +{this, "CosTransactions::Control"}. +{this, "CosTransactions::Resource"}. +{this, "CosTransactions::TransactionFactory"}. +{{handle_info, "CosTransactions::Terminator"}, true}. +{{handle_info, "CosTransactions::TransactionFactory"}, true}. +{this, "ETraP::Server"}. +{{handle_info, "ETraP::Server"}, true}. +{{impl, "CosTransactions::Coordinator"}, "ETraP_Server_impl"}. +{{impl, "CosTransactions::RecoveryCoordinator"}, "ETraP_Server_impl"}. +{{impl, "CosTransactions::Control"}, "ETraP_Server_impl"}. +{{impl, "CosTransactions::Resource"}, "ETraP_Server_impl"}. +{timeout,"CosTransactions::RecoveryCoordinator"}. diff --git a/lib/cosTransactions/src/CosTransactions.idl b/lib/cosTransactions/src/CosTransactions.idl new file mode 100644 index 0000000000..11ec5cbf5b --- /dev/null +++ b/lib/cosTransactions/src/CosTransactions.idl @@ -0,0 +1,193 @@ +#ifndef _COSTRANSACTIONS_IDL +#define _COSTRANSACTIONS_IDL + +#pragma prefix "omg.org" + +module CosTransactions { + +// DATATYPES + enum Status { + StatusActive, + StatusMarkedRollback, + StatusPrepared, + StatusCommitted, + StatusRolledBack, + StatusUnknown, + StatusNoTransaction, + StatusPreparing, + StatusCommitting, + StatusRollingBack + }; + + enum Vote { + VoteCommit, + VoteRollback, + VoteReadOnly + }; + + // Forward references for interfaces defined later in module + interface Control; + interface Terminator; + interface Coordinator; + interface Resource; + interface RecoveryCoordinator; + interface SubtransactionAwareResource; + interface TransactionFactory; + interface TransactionalObject; + // interface Synchronization; + + // Structure definitions + struct otid_t { + long formatID; /*format identifier. 0 is OSI TP */ + long bqual_length; + sequence tid; + }; + struct TransIdentity { + Coordinator coord; + Terminator term; + otid_t otid; + }; + struct PropagationContext { + unsigned long timeout; + TransIdentity current; + sequence parents; + any implementation_specific_data; + }; + // interface Current; + + // Standard exceptions + // Defined in orber/include/corba.hrl + // exception TransactionRequired {}; + // exception TransactionRolledBack {}; + // exception InvalidTransaction {}; + + // Heuristic exceptions + exception HeuristicRollback {}; + exception HeuristicCommit {}; + exception HeuristicMixed {}; + exception HeuristicHazard {}; + + // Exception from Orb operations + exception WrongTransaction {}; + + // Other transaction-specific exceptions + exception SubtransactionsUnavailable {}; + exception NotSubtransaction {}; + exception Inactive {}; + exception NotPrepared {}; + exception NoTransaction {}; + exception InvalidControl {}; + exception Unavailable {}; + exception SynchronizationUnavailable {}; + + interface TransactionFactory { + Control create(in unsigned long time_out); + Control recreate(in PropagationContext ctx); + }; + + interface Control { + Terminator get_terminator() + raises(Unavailable); + Coordinator get_coordinator() + raises(Unavailable); + }; + + interface Terminator { + void commit(in boolean report_heuristics) + raises( HeuristicMixed, + HeuristicHazard ); + void rollback(); + }; + + interface Coordinator { + + Status get_status(); + Status get_parent_status(); + Status get_top_level_status(); + + boolean is_same_transaction(in Coordinator tc); + boolean is_related_transaction(in Coordinator tc); + boolean is_ancestor_transaction(in Coordinator tc); + boolean is_descendant_transaction(in Coordinator tc); + boolean is_top_level_transaction(); + + unsigned long hash_transaction(); + unsigned long hash_top_level_tran(); + + RecoveryCoordinator register_resource(in Resource r) + raises(Inactive); + +// void register_synchronization (in Synchronization sync) +// raises(Inactive, SynchronizationUnavailable); + + void register_subtran_aware(in SubtransactionAwareResource r) + raises(Inactive, NotSubtransaction); + + void rollback_only() + raises(Inactive); + + string get_transaction_name(); + Control create_subtransaction() + raises(SubtransactionsUnavailable, Inactive); + + PropagationContext get_txcontext () + raises(Unavailable); + }; + + + interface RecoveryCoordinator { + Status replay_completion(in Resource r) + raises(NotPrepared); + }; + + interface Resource { + Vote prepare() + raises(HeuristicMixed, + HeuristicHazard); + void rollback() + raises( HeuristicCommit, + HeuristicMixed, + HeuristicHazard ); + void commit() + raises( NotPrepared, + HeuristicRollback, + HeuristicMixed, + HeuristicHazard ); + void commit_one_phase() + raises( HeuristicHazard, + HeuristicRollback, + HeuristicMixed); + void forget(); + }; + +// interface TransactionalObject { +// }; + +// interface Synchronization : TransactionalObject { +// void before_completion(); +// void after_completion(in CosTransactions::Status status); +// }; + + interface SubtransactionAwareResource : Resource { + void commit_subtransaction(in Coordinator parent); + void rollback_subtransaction(); + }; + +}; // End of CosTransactions Module + +module ETraP { + + // interface Server + interface Server : + CosTransactions::Coordinator, CosTransactions::Resource, + CosTransactions::RecoveryCoordinator, CosTransactions::Control { + }; +// interface Server : +// CosTransactions::Coordinator, CosTransactions::Resource, +// CosTransactions::RecoveryCoordinator, CosTransactions::Control, +// CosTransactions::Synchronization { +// }; + +}; // End of ETraP Module + +#endif diff --git a/lib/cosTransactions/src/CosTransactions_Terminator_impl.erl b/lib/cosTransactions/src/CosTransactions_Terminator_impl.erl new file mode 100644 index 0000000000..768e63950c --- /dev/null +++ b/lib/cosTransactions/src/CosTransactions_Terminator_impl.erl @@ -0,0 +1,362 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : CosTransactions_Terminator_impl.erl +%% Purpose : Support operations to commit or roll-back a transaction. +%%---------------------------------------------------------------------- + +-module('CosTransactions_Terminator_impl'). + +%%--------------- INCLUDES ----------------------------------- +-include_lib("orber/include/corba.hrl"). +%% Local +-include_lib("ETraP_Common.hrl"). +-include_lib("CosTransactions.hrl"). + +%%--------------- IMPORTS------------------------------------- +-import(etrap_logmgr, [log_safe/2, get_next/2]). + +%%--------------- EXPORTS------------------------------------- +%%-compile(export_all). +-export([commit/3, rollback/2]). +-export([init/1, terminate/2]). +-export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]). + +%%--------------- LOCAL DATA --------------------------------- +%-record(terminator, {reg_resources, rollback_only, regname, coordinator}). + +%%------------------------------------------------------------ +%% function : init, terminate +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the module ic. Used to initiate +%% and terminate a gen_server. +%%------------------------------------------------------------ + +init(State) -> + process_flag(trap_exit,true), + case catch start_object(State) of + {'EXIT', Reason} -> + %% Happens when, for example, we encounter an + %% error when reading from the log file. + {stop, Reason}; + Other -> + Other + end. + +start_object(State) -> + case catch file:read_file_info(?tr_get_terminator(State)) of + {error, enoent} -> + %% File does not exist. It's the first time. No restart. + ?debug_print("Terminator:init(~p)~n", [?tr_get_terminator(State)]), + etrap_logmgr:start(?tr_get_terminator(State)), + {ok, State, ?tr_get_timeout(State)}; + {error, Reason} -> % File exist but error occurred. + ?tr_error_msg("CosTransactions_Terminator( ~p ) Cannot open log file: ~p~n", + [?tr_get_terminator(State), Reason]), + {stop, {error, "unable_to_open_log"}}; + _ -> % File exists, perform restart. + etrap_logmgr:start(?tr_get_terminator(State)), + ?debug_print("RESTART Terminator:init(~p)~n", + [?tr_get_terminator(State)]), + do_restart(State, get_next(?tr_get_terminator(State), start), init) + end. + + +terminate(Reason, State) -> + ?debug_print("STOP ~p ~p~n", [?tr_get_terminator(State), Reason]), + case Reason of + normal -> + %% normal termination. Transaction completed. + log_safe(?tr_get_terminator(State), done), + etrap_logmgr:stop(?tr_get_terminator(State)), + file:delete(?tr_get_terminator(State)), + ok; + _ -> + ok + end. + +%%------------------------------------------------------------ +%% function : handle_call, handle_cast, handle_info, code_change +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the module ic. +%%------------------------------------------------------------ + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +handle_call(_,_, State) -> + {noreply, State}. + + +handle_cast(_, State) -> + {noreply, State}. + + +handle_info(Info, State) -> + ?debug_print("Terminator:handle_info(~p)~n", [Info]), + Pid = self(), + case Info of + timeout -> + ?tr_error_msg("Object( ~p ) timeout. Rolling back.~n", + [?tr_get_terminator(State)]), + {stop, normal, State}; + {suicide, Pid} -> + {stop, normal, State}; + _-> + {noreply, State} + end. + +%%------------------------------------------------------------ +%% function : commit +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Heuristics - boolean; report heuristic decisions? +%% Returns : ok - equal to void +%% Effect : +%% Exception: HeuristicMixed - Highest priority +%% HeuristicHazard - Lowest priority +%%------------------------------------------------------------ + +commit(_Self, State, _Heuristics) when ?tr_is_retransmit(State) -> + ?debug_print("Terminator:commit() recalled.~n", []), + {stop, normal, ?tr_get_reportH(State), State}; +commit(Self, State, Heuristics) -> + ?debug_print("Terminator:commit() called.~n", []), + NewState = ?tr_set_reportH(State, Heuristics), + log_safe(?tr_get_terminator(NewState), {init_commit, NewState}), + transmit(Self, NewState, Heuristics). + + +transmit(Self, State, Heuristics) -> + case catch 'ETraP_Common':try_timeout(?tr_get_alarm(State)) of + false -> +% catch 'ETraP_Server':before_completion(?tr_get_etrap(State)), + case catch 'CosTransactions_Resource':prepare(?tr_get_etrap(State)) of + 'VoteCommit' -> + evaluate_answer(Self, State, Heuristics, + 'ETraP_Common':try_timeout(?tr_get_alarm(State))); + 'VoteRollback' -> + {stop, normal, + {'EXCEPTION', + #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + State}; + 'VoteReadOnly' -> + {stop, normal, ok, State}; + {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicMixed'), + Heuristics==true-> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), + {stop, normal, {'EXCEPTION', E}, State}; + {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicHazard'), + Heuristics==true-> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), + {stop, normal, {'EXCEPTION', E}, State}; + {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicMixed') -> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), + {stop, normal, + {'EXCEPTION',#'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + State}; + {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicHazard') -> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), + {stop, normal, + {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + State}; + Other -> + ?tr_error_msg("Coordinator:prepare( ~p ) failed. REASON ~p~n", + [?tr_get_etrap(State), Other]), + {stop, normal, + {'EXCEPTION', + #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + State} + end; + _ -> + %% Timeout, rollback. + log_safe(?tr_get_terminator(State), rolled_back), + catch 'ETraP_Server':rollback(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, + {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + State} + end. + +evaluate_answer(Self, State, Heuristics, false) -> + evaluate_answer(Self, State, Heuristics, commit); +evaluate_answer(Self, State, Heuristics, true) -> + evaluate_answer(Self, State, Heuristics, rollback); +evaluate_answer(_Self, State, Heuristics, Vote) -> + case catch 'ETraP_Common':send_stubborn('ETraP_Server', Vote, + ?tr_get_etrap(State), + ?tr_get_maxR(State), + ?tr_get_maxW(State)) of + ok -> + ?eval_debug_fun({_Self, commit_ok1}, State), + log_safe(?tr_get_terminator(State), committed), + ?eval_debug_fun({_Self, commit_ok2}, State), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusCommitted'), + {stop, normal, ok, State}; + {'EXCEPTION', E} when Heuristics == true andalso + is_record(E,'CosTransactions_HeuristicMixed') -> + log_safe(?tr_get_terminator(State), {heuristic, State, E}), + ?eval_debug_fun({_Self, commit_heuristic1}, State), + catch 'ETraP_Server':forget(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, {'EXCEPTION', E}, State}; + {'EXCEPTION', E} when Heuristics == true andalso + is_record(E, 'CosTransactions_HeuristicHazard') -> + log_safe(?tr_get_terminator(State), {heuristic, State, E}), + catch 'ETraP_Server':forget(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, {'EXCEPTION', E}, State}; + {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') -> + log_safe(?tr_get_terminator(State), rolled_back), + {stop, normal, {'EXCEPTION', ?tr_hazard}, State}; + {'EXCEPTION', E} when is_record(E, 'TRANSACTION_ROLLEDBACK') -> + log_safe(?tr_get_terminator(State), rolled_back), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, {'EXCEPTION', E}, State}; + {'EXCEPTION', E} when is_record(E, 'CosTransactions_HeuristicCommit') -> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, ok, State}; + {'EXCEPTION', E} when is_record(E, 'CosTransactions_HeuristicRollback') -> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusCommitted'), + {stop, normal, + {'EXCEPTION', + #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + State}; + _Other when Heuristics == true -> + log_safe(?tr_get_terminator(State), rolled_back), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, {'EXCEPTION', ?tr_hazard}, State}; + _Other -> + log_safe(?tr_get_terminator(State), rolled_back), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + {stop, normal, ok, State} + end. + +%%-----------------------------------------------------------% +%% function : rollback +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : ok - equal to void +%% Effect : +%%------------------------------------------------------------ + +rollback(_Self, State) -> + ?debug_print("Terminator:rollback() called.~n", []), + log_safe(?tr_get_terminator(State), rolled_back), + catch 'ETraP_Server':rollback(?tr_get_etrap(State)), + {stop, normal, ok, State}. + +%%-----------------------------------------------------------% +%% function : do_restart +%% Arguments: State - server context +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +%% No data in file. Commit never initiated so we rollback (presumed rollback. +do_restart(State, eof, init) -> + log_safe(?tr_get_terminator(State), rolled_back), + catch 'ETraP_Server':rollback(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), 'StatusRolledBack'), + self() ! {suicide, self()}, + {ok, State}; + +do_restart(State, {error, Reason}, _) -> + ?tr_error_msg("CosTransactions_Terminator (~p) failed. Cannot read log file: ~p~n", + [?tr_get_terminator(State), Reason]), + {stop, Reason}; +do_restart(State, eof, Phase) -> + ?debug_print("Terminator:do_restart(~p)~n", [Phase]), + case Phase of + committed -> + {ok, ?tr_set_reportH(State, ok)}; + rolled_back -> + self() ! {suicide, self()}, + {ok, State}; + init_commit -> + case catch corba_object:non_existent(?tr_get_etrap(State)) of + true -> + self() ! {suicide, self()}, + {ok, State}; + _-> + case transmit(false, State, ?tr_get_reportH(State)) of + {stop, normal, ok, NewState} -> + {ok, NewState}; + {stop, normal, + {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + NewState} -> + self() ! {suicide, self()}, + {ok, NewState}; + {stop, normal, {'EXCEPTION', Exc}, NewState} -> + if + ?tr_dont_reportH(State) -> + self() ! {suicide, self()}, + {ok, NewState}; + true -> + {ok, ?tr_set_reportH(NewState, Exc)} + end + end + end; + {heuristic, Exc} -> + catch 'ETraP_Server':forget(?tr_get_etrap(State)), +% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), +% 'StatusRolledBack'), + if + ?tr_dont_reportH(State) -> + self() ! {suicide, self()}, + {ok, State}; + true -> + {ok, ?tr_set_reportH(State, {'EXCEPTION',Exc})} + end + end; +%% All done. +do_restart(State, {done, _Cursor}, _Phase) -> + ?debug_print("Terminator:do_restart(~p)~n", [_Phase]), + self() ! {suicide, self()}, + {ok, State}; +do_restart(State, {rolled_back, Cursor}, _Phase) -> + ?debug_print("Terminator:do_restart(~p)~n", [_Phase]), + do_restart(State, get_next(?tr_get_terminator(State), Cursor), rolled_back); +do_restart(State, {committed, Cursor}, _Phase) -> + ?debug_print("Terminator:do_restart(~p)~n", [_Phase]), + do_restart(State, get_next(?tr_get_terminator(State), Cursor), committed); +do_restart(State, {{heuristic, SavedState, Exc}, Cursor}, _Phase) -> + ?debug_print("Terminator:do_restart(~p)~n", [_Phase]), + do_restart(SavedState, get_next(?tr_get_terminator(State), Cursor), + {heuristic, Exc}); +do_restart(State, {{init_commit, SavedState}, Cursor}, _) -> + ?debug_print("Terminator:do_restart(~p)~n", [init_commit]), + do_restart(SavedState, get_next(?tr_get_terminator(State), Cursor), init_commit). + +%%--------------- END OF MODULE ------------------------------ diff --git a/lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl b/lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl new file mode 100644 index 0000000000..36e37e2d5f --- /dev/null +++ b/lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl @@ -0,0 +1,178 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : CosTransactions_TransactionFactory_impl.erl +%% Purpose : Is provided to allow the transaction originator to begin +%% a transaction. +%%---------------------------------------------------------------------- + +-module('CosTransactions_TransactionFactory_impl'). + +%%--------------- INCLUDES ----------------------------------- +-include_lib("orber/include/corba.hrl"). + +%% Local +-include_lib("ETraP_Common.hrl"). +-include_lib("CosTransactions.hrl"). +%%--------------- IMPORTS------------------------------------- +-import('ETraP_Common', [get_option/3]). + +%%--------------- EXPORTS------------------------------------- +-export([create/3, recreate/3, init/1, terminate/2]). +-export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]). + +%%--------------- LOCAL DATA --------------------------------- +-record(factory, {hashMax, subtrOK, typeCheck, maxRetries, comFailWait}). + +%%--------------- LOCAL DEFINITIONS -------------------------- + +%%------------------------------------------------------------ +%% function : init +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the module ic. Used to initiate +%% a gen_server. +%%------------------------------------------------------------ + +init(Options) when is_list(Options) -> + ?debug_print("Factory:init(~p)~n", [Options]), + process_flag(trap_exit,true), + DefaultValues = [{maxRetries, ?tr_max_retries}, + {comFailWait, ?tr_comm_failure_wait}|?tr_FAC_DEF], + Hash = get_option(hash_max, Options, DefaultValues), + SubtrOK = get_option(allow_subtr, Options, DefaultValues), + TypeCheck = get_option(typecheck, Options, DefaultValues), + TTY = get_option(tty, Options, DefaultValues), + LogFile = get_option(logfile, Options, DefaultValues), + MaxRetries = get_option(maxRetries, Options, DefaultValues), + ComFailWait = get_option(comFailWait, Options, DefaultValues), + error_logger:tty(TTY), + case LogFile of + false -> + ok; + _-> + error_logger:logfile({open, LogFile}) + end, + {ok, #factory{typeCheck = TypeCheck, hashMax = Hash, subtrOK = SubtrOK, + maxRetries = MaxRetries, comFailWait = ComFailWait}}; + +init(Options) -> + ?tr_error_msg("TransactionFactory~nBad argument: ~p~n", [Options]), + corba:raise(?tr_badparam). + + +%%------------------------------------------------------------ +%% function : terminate +%% Arguments: +%% Returns : +%% Effect : Function demanded by the module ic. Used to +%% terminate a gen_server. +%%------------------------------------------------------------ + +terminate(_Reason, _State) -> + ?debug_print("Factory:terminate(~p)~n", [_Reason]), + ok. + +%%------------------------------------------------------------ +%% function : handle_call, handle_cast, handle_info, code_change +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the module ic. +%%------------------------------------------------------------ + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +handle_call(_,_, State) -> + {noreply, State}. + + +handle_cast(_, State) -> + {noreply, State}. + + +handle_info({'EXIT',_From,shutdown}, State) -> + ?debug_print("Factory:handle_info(~p)~n", [shutdown]), + {stop, shutdown, State}; +handle_info(_Info, State) -> + ?debug_print("Factory:handle_info(~p)~n", [_Info]), + {noreply, State}. + +%%------------------------------------------------------------ +%% function : create +%% Arguments: TimeOut - rollback the transaction after TimeOut +%% seconds. If 0 no timeout. +%% Returns : a Control object +%% Effect : Creates a new top-level transaction. The Control +%% can be used to manage or control participation +%% in the new transaction. Used for direct context +%% management. +%%------------------------------------------------------------ + +create(_Self, State, TimeOut) when is_integer(TimeOut) -> + %% Generate objectnames. + ETraPName = 'ETraP_Common':create_name("root"), + TermName = 'ETraP_Common':create_name("term"), + EState = ?tr_create_context(ETraPName, TermName, + State#factory.typeCheck, + State#factory.hashMax, + State#factory.subtrOK, + State#factory.maxRetries, + State#factory.comFailWait), + + case TimeOut of + 0 -> + ETraP = ?tr_start_child(?SUP_ETRAP(EState)), + {reply, ETraP, State}; + _ -> + if + TimeOut > 0 -> + {MegaSecs, Secs, _Microsecs} = erlang:now(), + EState2 = ?tr_set_alarm(EState, MegaSecs*1000000+Secs+TimeOut), + EState3 = ?tr_set_timeout(EState2, TimeOut*1000), + ETraP = ?tr_start_child(?SUP_ETRAP(EState3)), + {reply, ETraP, State}; + true -> + ?tr_error_msg("TransactionFactory:create( Integer >= 0 )~nBad argument. Not an integer.~n", []), + corba:raise(?tr_badparam) + end + end; + +create(_Self, _State, _TimeOut) -> + ?tr_error_msg("TransactionFactory:create( Integer >= 0 )~nBad argument. Not an integer.~n", []), + corba:raise(?tr_badparam). + + +%%------------------------------------------------------------ +%% function : recreate +%% Arguments: PropagationContext +%% Returns : a Control object +%% Effect : +%%------------------------------------------------------------ + +recreate(_Self, _State, #'CosTransactions_PropagationContext'{current = _C}) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_YES}). +%recreate(Self, State, #'CosTransactions_PropagationContext'{current = C}) -> +% {reply, C#'CosTransactions_TransIdentity'.coord, State}. + + +%%--------------- END OF MODULE ------------------------------ + diff --git a/lib/cosTransactions/src/ETraP_Common.erl b/lib/cosTransactions/src/ETraP_Common.erl new file mode 100644 index 0000000000..dd68e9b038 --- /dev/null +++ b/lib/cosTransactions/src/ETraP_Common.erl @@ -0,0 +1,185 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : ETraP_Common.erl +%% Purpose : +%%---------------------------------------------------------------------- + +-module('ETraP_Common'). + +%%--------------- INCLUDES ---------------------------------- +-include_lib("orber/include/corba.hrl"). +-include_lib("orber/include/ifr_types.hrl"). +%% Local +-include_lib("ETraP_Common.hrl"). +-include_lib("CosTransactions.hrl"). + +%%--------------- EXPORTS ----------------------------------- +-export([try_timeout/1, + get_option/3, + create_name/2, + create_name/1, + is_debug_compiled/0, + send_stubborn/5, + create_link/3]). + +%%--------------- DEFINITIONS OF CONSTANTS ------------------ +%%------------------------------------------------------------ +%% function : create_link +%% Arguments: Module - which Module to call +%% Env/ARgList - ordinary oe_create arguments. +%% Returns : +%% Exception: +%% Effect : Necessary since we want the supervisor to be a +%% 'simple_one_for_one'. Otherwise, using for example, +%% 'one_for_one', we have to call supervisor:delete_child +%% to remove the childs startspecification from the +%% supervisors internal state. +%%------------------------------------------------------------ +create_link(Module, Env, ArgList) -> + Module:oe_create_link(Env, ArgList). + +%%------------------------------------------------------------ +%% function : get_option +%% Arguments: +%% Returns : +%% Exception: +%% Effect : +%%------------------------------------------------------------ + +get_option(Key, OptionList, DefaultList) -> + case lists:keysearch(Key, 1, OptionList) of + {value,{Key,Value}} -> + Value; + _ -> + case lists:keysearch(Key, 1, DefaultList) of + {value,{Key,Value}} -> + Value; + _-> + {error, "Invalid option"} + end + end. +%%------------------------------------------------------------ +%% function : create_name/2 +%% Arguments: +%% Returns : +%% Exception: +%% Effect : +%%------------------------------------------------------------ + +create_name(Name,Type) -> + {MSec, Sec, USec} = erlang:now(), + lists:concat(['oe_',node(),'_',Type,'_',Name,'_',MSec, '_', Sec, '_', USec]). + +%%------------------------------------------------------------ +%% function : create_name/1 +%% Arguments: +%% Returns : +%% Exception: +%% Effect : +%%------------------------------------------------------------ + +create_name(Type) -> + {MSec, Sec, USec} = erlang:now(), + lists:concat(['oe_',node(),'_',Type,'_',MSec, '_', Sec, '_', USec]). + +%%------------------------------------------------------------ +%% function : try_timeout +%% Arguments: Id - name of the timeoutSrv server. +%% Returns : Boolean +%% Exception: +%% Effect : +%%------------------------------------------------------------ + +try_timeout(TimeoutAt) -> + case TimeoutAt of + infinity -> + false; + _-> + {MegaSecs, Secs, _Microsecs} = erlang:now(), + Time = MegaSecs*1000000+Secs, + if + Time < TimeoutAt -> + false; + true -> + true + end + end. + +%%------------------------------------------------------------ +%% function : send_stubborn +%% Arguments: M - module +%% F - function +%% A - arguments +%% MaxR - Maximum no retries +%% Wait - sleep Wait seconds before next try. +%% Returns : see effect +%% Exception: +%% Effect : Retries repeatedly until anything else besides +%% 'EXIT', 'COMM_FAILURE' or 'OBJECT_NOT_EXIST' +%%------------------------------------------------------------ + +send_stubborn(M, F, A, MaxR, Wait) when is_list(A) -> + send_stubborn(M, F, A, MaxR, Wait, 0); +send_stubborn(M, F, A, MaxR, Wait) -> + send_stubborn(M, F, [A], MaxR, Wait, 0). +send_stubborn(M, F, A, MaxR, _Wait, MaxR) -> + ?tr_error_msg("~p:~p( ~p ) failed!! Tried ~p times.~n", [M,F,A,MaxR]), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}); +send_stubborn(M, F, A, MaxR, Wait, Times) -> + ?debug_print("~p:~p(~p) # of retries: ~p~n", [M,F,A, Times]), + case catch apply(M,F,A) of + {'EXCEPTION', E} when is_record(E, 'COMM_FAILURE')-> + NewTimes = Times +1, + timer:sleep(Wait), + send_stubborn(M, F, A, MaxR, Wait, NewTimes); + {'EXCEPTION', E} when is_record(E, 'TRANSIENT')-> + NewTimes = Times +1, + timer:sleep(Wait), + send_stubborn(M, F, A, MaxR, Wait, NewTimes); + {'EXCEPTION', E} when is_record(E, 'TIMEOUT')-> + NewTimes = Times +1, + timer:sleep(Wait), + send_stubborn(M, F, A, MaxR, Wait, NewTimes); + {'EXIT', _} -> + NewTimes = Times +1, + timer:sleep(Wait), + send_stubborn(M, F, A, MaxR, Wait, NewTimes); + Other -> + ?debug_print("~p:~p(~p) Resulted in: ~p~n", [M,F,A, Other]), + Other + end. + +%%------------------------------------------------------------ +%% function : is_debug_compiled +%% Arguments: +%% Returns : +%% Exception: +%% Effect : +%%------------------------------------------------------------ + +-ifdef(debug). + is_debug_compiled() -> true. +-else. + is_debug_compiled() -> false. +-endif. + +%%--------------- END OF MODULE ------------------------------ diff --git a/lib/cosTransactions/src/ETraP_Common.hrl b/lib/cosTransactions/src/ETraP_Common.hrl new file mode 100644 index 0000000000..5082282efb --- /dev/null +++ b/lib/cosTransactions/src/ETraP_Common.hrl @@ -0,0 +1,340 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%--------------------------------------------------------------------- +%% File : ETraP_Common.hrl +%% Purpose : +%%--------------------------------------------------------------------- + +-ifndef(ETRAP_COMMON_HRL). +-define(ETRAP_COMMON_HRL, true). + +%%--------------- INCLUDES --------------------------------------------- +-include_lib("orber/include/corba.hrl"). +-include_lib("cosTransactions/include/CosTransactions.hrl"). + +%%-------- CONSTANTS --------------------------------------------------- +%% Timeouts +-define(tr_comm_failure_wait, + case catch application:get_env(cosTransactions, comFailWait) of + {ok, _Time} when is_integer(_Time) -> + _Time; + _ -> + 5000 + end). + +-define(tr_max_retries, + case catch application:get_env(cosTransactions, maxRetries) of + {ok, _Max} when is_integer(_Max) -> + _Max; + _ -> + 40 + end). + +%% Exceptions +% Heuristic +-define(tr_mixed, + #'CosTransactions_HeuristicMixed' {}). +-define(tr_hazard, + #'CosTransactions_HeuristicHazard' {}). +-define(tr_commit, + #'CosTransactions_HeuristicCommit' {}). +-define(tr_rollback, + #'CosTransactions_HeuristicRollback' {}). +%% Standard +-define(tr_subunavailable, + #'CosTransactions_SubtransactionsUnavailable' {}). +-define(tr_unavailable, + #'CosTransactions_Unavailable' {}). +-define(tr_unprepared, + #'CosTransactions_NotPrepared' {}). +-define(tr_inactive, + #'CosTransactions_Inactive' {}). +-define(tr_nosync, + #'CosTransactions_SynchronizationUnavailable' {}). +-define(tr_badparam, + #'BAD_PARAM'{completion_status=?COMPLETED_NO}). +-define(tr_NotSubtr, + #'CosTransactions_NotSubtransaction' {}). + +%% TypeID:s +-define(tr_Terminator, + 'CosTransactions_Terminator':typeID()). +-define(tr_Coordinator, + 'CosTransactions_Coordinator':typeID()). +-define(tr_Control, + 'CosTransactions_Control':typeID()). +-define(tr_RecoveryCoordinator, + 'CosTransactions_RecoveryCoordinator':typeID()). +-define(tr_SubtransactionAwareResource, + 'CosTransactions_SubtransactionAwareResource':typeID()). +-define(tr_Synchronization, + 'CosTransactions_Synchronization':typeID()). +-define(tr_Resource, + 'CosTransactions_Resource':typeID()). +-define(tr_ETraP, + 'ETraP_Server':typeID()). +-define(tr_TransactionalObject, + 'CosTransactions_TransactionalObject':typeID()). + + +%%-------- MISC -------------------------------------------------------- + +-define(tr_error_msg(Txt, Arg), +error_logger:error_msg("============ CosTransactions ==============~n" + Txt + "===========================================~n", + Arg)). + + +-define(tr_NIL_OBJ_REF, corba:create_nil_objref()). + +-define(tr_FAC_DEF, [{hash_max, 1013}, + {allow_subtr, true}, + {typecheck, true}, + {tty, false}, + {logfile, false}]). + + +%%-------- Supervisor child-specs ------------------------------------ +-define(FACTORY_NAME, oe_cosTransactionsFactory). +-define(SUPERVISOR_NAME, cosTransactions_sup). +-define(SUP_FLAG, {simple_one_for_one,50,10}). + +-define(SUP_FAC(Env), + ['CosTransactions_TransactionFactory',Env, + [{sup_child, true}, {regname, {local, ?FACTORY_NAME}}]]). + +-define(SUP_ETRAP(Env), + ['ETraP_Server', Env, + [{sup_child, true}, {persistent, true}, + {regname, {global, ?tr_get_etrap(Env)}}]]). + +-define(SUP_TERMINATOR(Env), + ['CosTransactions_Terminator', Env, + [{sup_child, true}, {persistent, true}, + {regname, {global, ?tr_get_etrap(Env)}}]]). + +-define(SUP_CHILD, + {"oe_child", + {'ETraP_Common',create_link, []}, + transient,100000,worker, + ['ETraP_Common', + 'ETraP_Server_impl', + 'ETraP_Server', + 'CosTransactions_Terminator_impl', + 'CosTransactions_Terminator', + 'CosTransactions_TransactionFactory_impl', + 'CosTransactions_TransactionFactory']}). + + +-define(tr_start_child(SPEC), + case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of + {ok, Pid, Obj} when is_pid(Pid) -> + Obj; + _Other-> + corba:raise(?tr_badparam) + end). + +-define(tr_start_child_pid(SPEC), + supervisor:start_child(?SUPERVISOR_NAME, SPEC)). + +-define(tr_terminate_child(Child), + supervisor:terminate_child(?SUPERVISOR_NAME, Child)). + +-define(tr_delete_child(Child), + supervisor:delete_child(?SUPERVISOR_NAME, Child)). + +%%-------- DATASTRUCTURES ---------------------------------------------- +%% tr_*_* +-record(context, {terminator, etrap, recCoord, alarm = infinity, + timeout = infinity, parents=[], trid, typeCheck, + sub_tr_allowed, hashMax, local, rollback=false, + reportH, maxRetries, comFailWait}). + + +%%-------- FUNS -------------------------------------------------------- +-define(tr_IS_MEMBER(Obj), + fun(X) -> + case catch corba_object:is_equivalent(Obj, X) of + true -> + true; + _ -> + false + end + end). + +%% Managing conditional debug functions +-define(is_debug_compiled, 'ETraP_Common':is_debug_compiled()). +-define(set_debug_context(L, C), + etrap_test_lib:set_debug_context(L, C, ?FILE, ?LINE)). + + +-ifdef(debug). +-define(put_debug_data(Key, Data), erlang:put(Key, Data)). +-define(get_debug_data(Key), erlang:get(Key)). +-define(eval_debug_fun(I, E), + etrap_test_lib:eval_debug_fun(I, E, ?FILE, ?LINE)). +-define(activate_debug_fun(I, F, C), + etrap_test_lib:activate_debug_fun(I, F, C, ?FILE, ?LINE)). +-define(deactivate_debug_fun(I), + etrap_test_lib:deactivate_debug_fun(I, ?FILE, ?LINE)). +-define(debug_print(F,A), + io:format("[LINE: ~p] "++F,[?LINE]++A)). +-define(scratch_debug_fun, + etrap_test_lib:scratch_debug_fun()). +-else. +-define(put_debug_data(Key, Data), ok). +-define(get_debug_data(Key), ok). +-define(eval_debug_fun(I, E), ok). +-define(activate_debug_fun(I, F, C), ok). +-define(deactivate_debug_fun(I), ok). +-define(debug_print(F,A), ok). +-define(scratch_debug_fun, ok). +-endif. + + +%%-------- CONSTRUCTORS ------------------------------------------------ + +-define(tr_create_context(ETraP, Terminator, TypeCheck, HM, SubtrOK, MaxRetries, + ComFailWait), + #context{etrap = ETraP, terminator = Terminator, typeCheck = TypeCheck, + hashMax = HM, sub_tr_allowed = SubtrOK, maxRetries = MaxRetries, + comFailWait = ComFailWait}). + + +%%-------- MISC -------------------------------------------------------- +-define(tr_notimeout(Context), + 'ETraP_Common':try_timeout(Context#context.alarm) == false). +-define(tr_is_root(Context), Context#context.parents == []). +-define(tr_dont_reportH(Context), Context#context.reportH == false). +-define(tr_is_retransmit(Context), + Context#context.reportH =/= undefined, + Context#context.reportH =/= true, + Context#context.reportH =/= false). + +%%-------- SELECTORS --------------------------------------------------- + +-define(tr_get_reportH(Context), + Context#context.reportH). + +-define(tr_get_rollback(Context), + Context#context.rollback). + +-define(tr_get_subTraOK(Context), + Context#context.sub_tr_allowed). + +-define(tr_get_hashMax(Context), + Context#context.hashMax). + +-define(tr_get_local(Context), + Context#context.local). + +-define(tr_get_trid(Context), + Context#context.trid). + +-define(tr_get_typeCheck(Context), + Context#context.typeCheck). + +-define(tr_get_recCoord(Context), + Context#context.recCoord). + +-define(tr_get_alarm(Context), + Context#context.alarm). + +-define(tr_get_timeout(Context), + Context#context.timeout). + +-define(tr_get_etrap(Context), + Context#context.etrap). + +-define(tr_get_terminator(Context), + Context#context.terminator). + +-define(tr_get_id(Context), + Context#context.self). + +-define(tr_get_maxW(Context), + Context#context.comFailWait). + +-define(tr_get_maxR(Context), + Context#context.maxRetries). + +-define(tr_get_parents(Context), + Context#context.parents). + +-define(tr_get_parent(Context), + lists:nth(1, Context#context.parents)). + +%%-------- MODIFIERS --------------------------------------------------- + +-define(tr_set_reportH(Context, Bool), + Context#context{reportH = Bool}). + +-define(tr_set_rollback(Context, Bool), + Context#context{rollback = Bool}). + +-define(tr_set_subTraOK(Context, Bool), + Context#context{sub_tr_allowed = Bool}). + +-define(tr_set_hashMax(Context, HM), + Context#context{hashMax = HM}). + +-define(tr_reset_local(Context), + Context#context{local = undefined}). + +-define(tr_set_local(Context, Local), + Context#context{local = Local}). + +-define(tr_set_trid(Context, TRID), + Context#context{trid = TRID}). + +-define(tr_set_typeCheck(Context, Bool), + Context#context{typeCheck = Bool}). + +-define(tr_set_id(Context, ID), + Context#context{self = ID}). + +-define(tr_set_parents(Context, Parents), + Context#context{parents = Parents). + +-define(tr_add_parent(Context, Parent), + Context#context{parents = [Parent] ++ Context#context.parents}). + +-define(tr_set_recCoord(Context, R), + Context#context{recCoord = R}). + +-define(tr_set_alarm(Context, EC), + Context#context{alarm = EC}). + +-define(tr_set_timeout(Context, T), + Context#context{timeout = T}). + +-define(tr_set_etrap(Context, ETraP), + Context#context{etrap = ETraP}). + +-define(tr_set_terminator(Context, T), + Context#context{terminator = T}). + +-endif. + +%%-------------- EOF --------------------------------------------------- + + diff --git a/lib/cosTransactions/src/ETraP_Server_impl.erl b/lib/cosTransactions/src/ETraP_Server_impl.erl new file mode 100644 index 0000000000..e2c5d88f9d --- /dev/null +++ b/lib/cosTransactions/src/ETraP_Server_impl.erl @@ -0,0 +1,1739 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : ETraP_Server_impl.erl +%% Purpose : +%%---------------------------------------------------------------------- +%% GENERAL CODE COMMENTS: +%% ###################### +%% TypeChecking incoming arguments: +%% -------------------------------- +%% We allow the user to configure the system so that external calls +%% (not CosTransactions calls) may be typechecked or not when calling +%% for example 'replay_completion'. With typecheck the user will get +%% instant feedback. But since 'is_a' add quiet a lot extra overhead +%% if the object is located on a remote ORB. Hence, it is up to the +%% user to decide; speed vs. "safety". +%% +%% Log behavior +%% ------------ +%% Log files are created in the current directory, which is why the +%% application requires read/write rights for current directory. The +%% file name looks like: +%% "oe_nonode@nohost_subc_939_383117_295538" (the last part is now()) +%% It is equal to what the object is started as, i.e., {regname, {global, X}}. +%% +%% If the application is unable to read the log it will exit and the +%% supervisor definitions (found in ETraP_Common.hrl) determines how +%% many times we will retry. If it's impossible to read the log it's +%% considered as a disaster, i.e., user intervention is needed. +%% +%% If an Object is unreachable when a Coordinator is trying to inform +%% of the true outcome of the transaction the application will retry N +%% times with T seconds wait in between. If it's still impossible to +%% reach the object it's considered as a disaster, i.e., user +%% intervention is needed. +%% +%%---------------------------------------------------------------------- + +-module('ETraP_Server_impl'). + +%%--------------- INCLUDES ----------------------------------- +-include_lib("orber/include/corba.hrl"). + +%% Local +-include_lib("cosTransactions/src/ETraP_Common.hrl"). +-include_lib("cosTransactions/include/CosTransactions.hrl"). + + +%%--------------- IMPORTS------------------------------------- +-import('ETraP_Common', [try_timeout/1]). + +%%--------------- EXPORTS------------------------------------- +%%--------------- Inherit from CosTransactions::Resource ---- +-export([prepare/2, + rollback/2, + commit/2, + commit_one_phase/2, + forget/2]). + +%%--------------- Inherit from CosTransactions::Control ----- +-export([get_terminator/2, + get_coordinator/2]). + +%%----- Inherit from CosTransactions::RecoveryCoordinator --- +-export([replay_completion/3]). + +%%--------------- Inherit from CosTransactions::Coordinator - +-export([create_subtransaction/2, + get_txcontext/2, + get_transaction_name/2, + get_parent_status/2, + get_status/2, + get_top_level_status/2, + hash_top_level_tran/2, + hash_transaction/2, + is_ancestor_transaction/3, + is_descendant_transaction/3, + is_related_transaction/3, + is_same_transaction/3, + is_top_level_transaction/2, + register_resource/3, + register_subtran_aware/3, + register_synchronization/3, + rollback_only/2]). + +%%--------- Inherit from CosTransactions::Synchronization --- +%-export([before_completion/2, +% after_completion/3]). + + +%%--------------- gen_server specific ------------------------ +-export([init/1, terminate/2]). +-export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]). + + + +%%--------------- LOCAL DATA --------------------------------- +-record(exc, + {rollback = false, + mixed = false, + hazard = false, + unprepared = false, + commit = false}). + +%%--------------- LOCAL DEFINITIONS -------------------------- + +%%--------------- MISC MACROS -------------------------------- +-define(etr_log(Log, Data), etrap_logmgr:log_safe(Log, Data)). +-define(etr_read(Log, Cursor), etrap_logmgr:get_next(Log, Cursor)). + +-record(coord, + {status, %% Status of the transaction. + members = [], %% List of registred resources. + votedCommit = [], %% List of the ones that voted commit. + raisedHeuristic = [], %% The members which raised an Heur. exc. + subAw = [], %% Resorces which want to be informed of outcome. + sync = [], + exc = void, + self, + etsR}). + +%% Selectors +-define(etr_get_status(L), L#coord.status). +-define(etr_get_members(L), lists:reverse(L#coord.members)). +-define(etr_get_vc(L), lists:reverse(L#coord.votedCommit)). +-define(etr_get_raisedH(L), lists:reverse(L#coord.raisedHeuristic)). +-define(etr_get_exc(L), L#coord.exc). +-define(etr_get_subAw(L), lists:reverse(L#coord.subAw)). +-define(etr_get_sync(L), lists:reverse(L#coord.sync)). +-define(etr_get_self(L), L#coord.self). +-define(etr_get_etsR(L), L#coord.etsR). +-define(etr_get_init(Env), #coord{}). +-define(etr_get_exc_init(), #exc{}). +%% Modifiers +-define(etr_set_status(L, D), L#coord{status = D}). +-define(etr_set_members(L, D), L#coord{members = D}). +-define(etr_add_member(L, D), L#coord{members = [D|L#coord.members]}). +-define(etr_set_vc(L, D), L#coord{votedCommit = D}). +-define(etr_add_vc(L, D), L#coord{votedCommit = [D|L#coord.votedCommit]}). +-define(etr_remove_vc(L, D), L#coord{votedCommit = + lists:delete(D, ?etr_get_vc(L))}). +-define(etr_set_raisedH(L, D), L#coord{raisedHeuristic = [D]}). +-define(etr_add_raisedH(L, D), L#coord{raisedHeuristic = + [D|L#coord.raisedHeuristic]}). +-define(etr_remove_raisedH(L, D), L#coord{raisedHeuristic = + lists:delete(D, ?etr_get_raisedH(L))}). +-define(etr_set_exc(L, D), L#coord{exc = D}). +-define(etr_set_subAw(L, D), L#coord{subAw = [D]}). +-define(etr_add_subAw(L, D), L#coord{subAw = [D|L#coord.subAw]}). +-define(etr_remove_subAw(L, D), L#coord{subAw = + lists:delete(D,?etr_get_subAw(L))}). +-define(etr_set_sync(L, D), L#coord{sync = [D]}). +-define(etr_add_sync(L, D), L#coord{sync = [D|L#coord.sync]}). +-define(etr_remove_sync(L, D), L#coord{sync = lists:delete(D,?etr_get_sync(L))}). +-define(etr_set_self(L, D), L#coord{self = D}). +-define(etr_set_etsR(L, D), L#coord{etsR = D}). + + +%%------------------------------------------------------------ +%% function : init, terminate +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the module ic. +%%------------------------------------------------------------ + +init(Env) -> + process_flag(trap_exit,true), + case catch start_object(Env) of + {'EXIT', Reason} -> + %% Happens when, for example, we encounter an + %% error when reading from the log file. + {stop, Reason}; + {'EXCEPTION', E} -> + self() ! {suicide, self()}, + corba:raise(E); + Other -> + Other + end. + + + +terminate(Reason, {Env, _Local}) -> + ?debug_print("STOP ~p ~p~n", [?tr_get_etrap(Env), Reason]), + case Reason of + normal -> + %% normal termination. Transaction completed. + etrap_logmgr:stop(?tr_get_etrap(Env)), + file:delete(?tr_get_etrap(Env)), + ok; + _ -> + ?tr_error_msg("Object(~p) terminated abnormal.~n",[?tr_get_etrap(Env)]), + ok + end. + + +%%------------------------------------------------------------ +%% function : handle_call, handle_cast, handle_info, code_change +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the gen_server module. +%%------------------------------------------------------------ + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +handle_call(_,_, State) -> + {noreply, State}. + +handle_cast(_, State) -> + {noreply, State}. + + +handle_info(Info, {Env, Local}) -> + ?debug_print("ETraP_Server:handle_info(~p)~n", [Info]), + Pid = self(), + case Info of + timeout -> + ?tr_error_msg("Object( ~p ) timeout. Rolling back.~n", + [?tr_get_etrap(Env)]), + {stop, normal, {Env, Local}}; + {suicide, Pid} -> + {stop, normal, {Env, Local}}; + _-> + {noreply, {Env, Local}} + end. + + +%%--------------- Inherit from CosTransactions::Control ----- +%%-----------------------------------------------------------% +%% function : get_terminator +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : a Terminator object reference. +%% Effect : Supports operations for termination of a transaction +%%------------------------------------------------------------ + +get_terminator(Self, {Env, Local}) -> + %% Only allows the root-coordinator to export the termonator. + %% The reason for this is that only the root-coordinator is allowed + %% to initiate termination of a transaction. This is however possible + %% to change and add restictions elsewhere, i.e. to verify if the + %% commit or rollback call is ok. + case catch ?tr_get_parents(Env) of + [] -> % No parents, it's a root-coordinator. + % Create terminators environment. + TEnv = ?tr_set_etrap(Env, Self), + T = ?tr_start_child(?SUP_TERMINATOR(TEnv)), + {reply, T, {Env, Local}, ?tr_get_timeout(TEnv)}; + _ -> + corba:raise(?tr_unavailable) + end. + +%%-----------------------------------------------------------% +%% function : get_coordinator +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : a Coordinator object reference. The OMG specification +%% states that a object reference must be returned. +%% Effect : Supports operations needed by resources to participate +%% in the transaction. +%%------------------------------------------------------------ + +get_coordinator(Self, State) -> + {reply, Self, State}. + +%%----- Inherit from CosTransactions::RecoveryCoordinator --- +%%-----------------------------------------------------------% +%% function : replay_completion +%% Arguments: +%% Returns : Status +%% Effect : Provides a hint to the Coordinator that the commit +%% or rollback operations have not been performed on +%% the resource. +%%------------------------------------------------------------ + +replay_completion(_Self, {Env, Local}, Resource) -> + type_check(?tr_get_typeCheck(Env), ?tr_Resource, + "RecoveryCoordinator:replay_completion", Resource), + case ?etr_get_status(Local) of + 'StatusActive' -> + corba:raise(?tr_unprepared); + Status -> + case lists:any(?tr_IS_MEMBER(Resource), ?etr_get_members(Local)) of + true -> + {reply, Status, {Env, Local}}; + _ -> + corba:raise(#'NO_PERMISSION'{completion_status=?COMPLETED_YES}) + end + end. + +%%--------------- Inherit from CosTransactions::Resource ---- +%%-----------------------------------------------------------% +%% function : prepare +%% Arguments: +%% Returns : a Vote +%% Effect : Is invoked to begin the two-phase-commit on the +%% resource. +%%------------------------------------------------------------ + +prepare(_Self, {Env, Local}) -> + %% Set status as prepared. No new Resources are allowed to register. + NewL = ?etr_set_status(Local, 'StatusPrepared'), + + ?eval_debug_fun({?tr_get_etrap(Env), root_delay}, Env), + + case catch send_prepare(?etr_get_members(NewL), + ?tr_get_alarm(Env)) of + readOnly -> + %% All voted ReadOnly, done. No need to log. + {stop, normal, 'VoteReadOnly', {Env, NewL}}; + %% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, 'VoteReadOnly', {Env, NewL}}; +% _ -> +% {reply, 'VoteReadOnly', {Env, NewL}} +% end; + {commit, VC} -> + %% All voted Commit. + NewL2 = ?etr_set_vc(NewL, VC), + case catch try_timeout(?tr_get_alarm(Env)) of + false -> + case ?etr_log(?tr_get_etrap(Env), {pre_vote, commit, NewL2}) of + ok -> + ?eval_debug_fun({?tr_get_etrap(Env), prepare1}, Env), + {reply, 'VoteCommit', {Env, NewL2}}; + _-> + %% Cannot log. Better to be safe than sorry; do rollback. + %% However, try to log rollback. + ?etr_log(?tr_get_etrap(Env),{pre_vote, rollback, NewL2}), + send_decision({Env, NewL2}, 'VoteRollback', rollback) + end; + _-> + ?etr_log(?tr_get_etrap(Env), + {pre_vote, rollback, NewL2}), + %% timeout, reply rollback. + send_decision({Env, NewL2}, 'VoteRollback', rollback) + end; + {rollback, VC} -> + %% Rollback vote received. + %% Send rollback to commit voters. + N2 = ?etr_set_vc(NewL, VC), + NewL2 = ?etr_set_status(N2,'StatusRolledBack'), + ?etr_log(?tr_get_etrap(Env), {pre_vote, rollback, NewL2}), + send_decision({Env, NewL2}, 'VoteRollback', rollback); + {'EXCEPTION', E, VC, Obj} -> + NewL2 = case is_heuristic(E) of + true -> + N2 = ?etr_set_vc(NewL, VC), + N3 = ?etr_set_exc(N2, E), + ?etr_set_raisedH(N3, Obj); + _-> + ?etr_set_vc(NewL, VC) + end, + ?etr_log(?tr_get_etrap(Env),{pre_vote,rollback, NewL2}), + ?eval_debug_fun({?tr_get_etrap(Env), prepare2}, Env), + send_decision({Env, NewL2}, {'EXCEPTION', E}, rollback); + {failed, VC} -> + NewL2 = ?etr_set_vc(NewL, VC), + ?etr_log(?tr_get_etrap(Env),{pre_vote, rollback, NewL2}), + send_decision({Env, NewL2}, + {'EXCEPTION', ?tr_hazard}, rollback) + end. + + +%%-----------------------------------------------------------% +%% function : rollback +%% Arguments: Self - the servers own objref. +%% {Env, Local} - the servers internal state. +%% Returns : ok +%% Effect : Rollback the transaction. If its status is +%% "StatusRolledBack", this is not the first +%% rollback call to this server. Might occur if +%% the parent coordinator just recoeverd from a crasch. +%% Exception: HeuristicCommit, HeuristicMixed, HeuristicHazard +%%------------------------------------------------------------ + +rollback(Self, {Env, Local}) -> + case ?etr_get_status(Local) of + 'StatusRolledBack' -> + case ?etr_get_exc(Local) of + void -> + {stop, normal, ok, {Env, Local}}; + %% Replace the reply above if allow synchronization + %% Rolled back successfullly earlier. +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, ok, {Env, Local}}; +% _ -> +% {reply, ok, {Env, Local}} +% end; + E -> + %% Already rolledback with heuristic decision + corba:raise(E) + end; + 'StatusPrepared' -> + NewL = ?etr_set_status(Local, 'StatusRolledBack'), + ?eval_debug_fun({?tr_get_etrap(Env), rollback}, Env), + ?etr_log(?tr_get_etrap(Env), rollback), + ?eval_debug_fun({?tr_get_etrap(Env), rollback2}, Env), + send_decision({Env, NewL}, ok, rollback); + 'StatusActive' -> + NewL = ?etr_set_status(Local, 'StatusRolledBack'), + ?etr_log(?tr_get_etrap(Env), {rollback, NewL}), + send_info(?etr_get_members(NewL), 'CosTransactions_Resource', rollback), + notify_subtrAware(rollback, ?etr_get_subAw(NewL), Self), + {stop, normal, ok, {Env, NewL}} +%% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, ok, {NewEnv, NewL}}; +% _ -> +% {reply, ok, {NewEnv, NewL}} +% end; + end. + + +%%-----------------------------------------------------------% +%% function : commit +%% Arguments: Self - the servers own objref. +%% {Env, Local} - the servers internal state. +%% Returns : ok +%% Effect : Commit the transaction. +%% Exception: HeuristicRollback, HeuristicMixed, HeuristicHazard, +%% NotPrepared +%%------------------------------------------------------------ + +commit(_Self, {Env, Local}) -> + case ?etr_get_status(Local) of + 'StatusPrepared' -> + ?eval_debug_fun({?tr_get_etrap(Env), commit}, Env), + NewL = ?etr_set_status(Local, 'StatusCommitted'), + ?etr_log(?tr_get_etrap(Env),commit), + ?eval_debug_fun({?tr_get_etrap(Env), commit2}, Env), + send_decision({Env, NewL}, ok, commit); + 'StatusCommitted' -> + case ?etr_get_exc(Local) of + void -> + {stop, normal, ok, {Env, Local}}; + %% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, ok, {Env, Local}}; +% _ -> +% {reply, ok, {Env, Local}} +% end; + E-> + corba:raise(E) + end; + _ -> + corba:raise(?tr_unprepared) + end. + +%%-----------------------------------------------------------% +%% function : commit_one_phase +%% Arguments: Self - the servers own objref. +%% {Env, Local} - the servers internal state. +%% Returns : ok +%% Effect : Commit the transaction using one-phase commit. +%% Use ONLY when there is only one registered Resource. +%% Exception: HeuristicRollback, HeuristicMixed, HeuristicHazard, +%% TRANSACTION_ROLLEDBACK +%%------------------------------------------------------------ + +commit_one_phase(_Self, {Env, Local}) -> + case ?etr_get_members(Local) of + [Resource] -> + case ?etr_get_status(Local) of + 'StatusActive' -> + %% Set status as prepared. No new Resources are allowed to register. + NewL = ?etr_set_status(Local, 'StatusPrepared'), + ?eval_debug_fun({?tr_get_etrap(Env), onePC}, Env), + case try_timeout(?tr_get_alarm(Env)) of + false -> + case catch 'CosTransactions_Resource':prepare(Resource) of + 'VoteCommit' -> + case try_timeout(?tr_get_alarm(Env)) of + false -> + send_decision({Env, NewL}, ok, commit, [Resource]); + _-> + %% Timeout, rollback. + send_decision({Env, NewL}, + {'EXCEPTION', + #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + rollback, [Resource]) + end; + 'VoteRollback' -> + {stop, normal, + {'EXCEPTION', + #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + {Env, NewL}}; + 'VoteReadOnly' -> + {stop, normal, ok, {Env, NewL}}; + {'EXCEPTION', E} + when is_record(E, 'CosTransactions_HeuristicMixed') -> + {reply, {'EXCEPTION', E}, {Env, NewL}}; + {'EXCEPTION', E} + when is_record(E, 'CosTransactions_HeuristicHazard') -> + {reply, {'EXCEPTION', E}, {Env, NewL}}; + Other -> + ?tr_error_msg("Coordinator:prepare( ~p ) failed. REASON ~p~n", + [Resource, Other]), + {stop, normal, + {'EXCEPTION', + #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + {Env, NewL}} + end; + _-> + NewL2 = ?etr_set_status(NewL, 'StatusRolledBack'), + send_info(Resource, 'CosTransactions_Resource', rollback), + {stop, normal, + {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + {Env, NewL2}} + %% Replace the reply above if allow synchronization +% case ?etr_get_sync(NewL2) of +% [] -> +% send_info(Resource, 'CosTransactions_Resource', rollback), +% {stop, normal, +% {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, +% {Env, NewL2}}; +% _ -> +% send_info(Resource, 'CosTransactions_Resource', rollback), +% {reply, +% {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, +% {Env, NewL2}} +% end + end; + _ -> + case evaluate_status(?etr_get_status(Local)) of + commit -> + test_exc(set_exception(?etr_get_exc_init(), + ?etr_get_exc(Local)), + commit, ok, {Env, Local}); + _-> + test_exc(set_exception(?etr_get_exc_init(), + ?etr_get_exc(Local)), + rollback, + {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + {Env, Local}) + end + end; + _-> + {reply, {'EXCEPTION', #'NO_PERMISSION'{completion_status=?COMPLETED_NO}}, + {Env, Local}} + end. + +%%-----------------------------------------------------------% +%% function : forget +%% Arguments: Self - the servers own objref. +%% State - the servers internal state. +%% Returns : ok +%% Effect : The resource can forget all knowledge about the +%% transaction. Terminate this server. +%%------------------------------------------------------------ + +forget(_Self, {Env, Local}) -> + ?etr_log(?tr_get_etrap(Env), forget_phase), + send_forget(?etr_get_raisedH(Local), ?tr_get_etrap(Env)), + {stop, normal, ok, {Env, ?etr_set_exc(Local, void)}}. +%% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, ok, {Env, ?etr_set_exc(Local, void)}}; +% _ -> +% {reply, ok, {Env, ?etr_set_exc(Local, void)}} +% end. + +%%--------------- Inherrit from CosTransactions::Coordinator - + +%%-----------------------------------------------------------% +%% function : get_status +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : Status +%% Effect : Returns the status of the transaction associated +%% with the target object. +%%------------------------------------------------------------ + +get_status(_Self, {Env, Local}) -> + {reply, ?etr_get_status(Local), {Env, Local}}. + + +%%-----------------------------------------------------------% +%% function : get_parent_status +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : Status +%% Effect : Returns the status of the parent transaction +%% associated with the target object. If top-level +%% transaction equal to get_status. +%%------------------------------------------------------------ + +get_parent_status(_Self, {Env, Local}) -> + case catch ?tr_get_parents(Env) of + [] -> + {reply, ?etr_get_status(Local), {Env, Local}}; + [Parent|_] -> + case catch 'CosTransactions_Coordinator':get_status(Parent) of + {'EXCEPTION', _E} -> + corba:raise(?tr_unavailable); + {'EXIT', _} -> + corba:raise(?tr_unavailable); + Status -> + {reply, Status, {Env, Local}} + end + end. + + +%%-----------------------------------------------------------% +%% function : get_top_level_status +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : Status +%% Effect : Returns the status of the top-level transaction +%% associated with the target object. If top-level +%% transaction equal to get_status. +%%------------------------------------------------------------ + +get_top_level_status(_Self, {Env, Local}) -> + case catch ?tr_get_parents(Env) of + [] -> + {reply, ?etr_get_status(Local), {Env, Local}}; + Ancestrors -> + case catch 'CosTransactions_Coordinator':get_status(lists:last(Ancestrors)) of + {'EXCEPTION', _E} -> + corba:raise(?tr_unavailable); + {'EXIT', _} -> + corba:raise(?tr_unavailable); + Status -> + {reply, Status, {Env, Local}} + end + end. + + +%%-----------------------------------------------------------% +%% function : is_same_transaction +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Coordinator object reference +%% Returns : boolean +%% Effect : +%%------------------------------------------------------------ + +is_same_transaction(Self, {Env, Local}, Coordinator) -> + type_check(?tr_get_typeCheck(Env), ?tr_Coordinator, + "Coordinator:is_same_transaction", Coordinator), + {reply, corba_object:is_equivalent(Self, Coordinator), {Env, Local}}. + +%%------------------------------------------------------------ +%% function : is_related_transaction +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Coordinator object reference +%% Returns : boolean +%% Effect : +%%------------------------------------------------------------ + +is_related_transaction(_Self, {_Env, _Local}, _Coordinator) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_YES}). +% type_check(?tr_get_typeCheck(Env), ?tr_Coordinator, +% "Coordinator:is_related_transaction", Coordinator), +% {reply, false, {Env, Local}}. + + +%%------------------------------------------------------------ +%% function : is_ancestor_transaction +%% Coordinator object reference +%% Returns : boolean +%% Effect : +%%------------------------------------------------------------ + +is_ancestor_transaction(_Self, {_Env, _Local}, _Coordinator) -> + corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_YES}). +% type_check(?tr_get_typeCheck(Env), ?tr_Coordinator, +% "Coordinator:is_ancestor_transaction", Coordinator), +% {reply, false, {Env, Local}}. + + +%%-----------------------------------------------------------% +%% function : is_descendant_transaction +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Coordinator object reference +%% Returns : boolean +%% Effect : +%%------------------------------------------------------------ + +is_descendant_transaction(Self, {Env, Local}, Coordinator) -> + type_check(?tr_get_typeCheck(Env), ?tr_Coordinator, + "Coordinator:is_descendant_transaction", Coordinator), + {reply, + lists:any(?tr_IS_MEMBER(Coordinator), [Self|?tr_get_parents(Env)]), + {Env, Local}}. + +%%-----------------------------------------------------------% +%% function : is_top_level_transaction +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : boolean +%% Effect : +%%------------------------------------------------------------ + +is_top_level_transaction(_Self, {Env, Local}) -> + case catch ?tr_get_parents(Env) of + [] -> + {reply, true, {Env, Local}}; + _ -> + {reply, false, {Env, Local}} + end. + +%%-----------------------------------------------------------% +%% function : hash_transaction +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : hash code +%% Effect : Returns a hash code for the transaction associated +%% with the target object. +%%------------------------------------------------------------ + +hash_transaction(Self, {Env, Local}) -> + {reply, corba_object:hash(Self, ?tr_get_hashMax(Env)), {Env, Local}}. + + +%%-----------------------------------------------------------% +%% function : hash_top_level_tran +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : hash code +%% Effect : Returns a hash code for the top-level transaction +%% associated with the target object. Equals +%% hash_transaction if it's a top-level transaction. +%%------------------------------------------------------------ + +hash_top_level_tran(Self, {Env, Local}) -> + case ?tr_get_parents(Env) of + [] -> + {reply, + corba_object:hash(Self, ?tr_get_hashMax(Env)), + {Env, Local}}; + Ancestrors -> + case catch corba_object:hash(lists:last(Ancestrors), + ?tr_get_hashMax(Env)) of + {'EXCEPTION', _E} -> + corba:raise(?tr_unavailable); + Hash -> + {reply, Hash, {Env, Local}} + end + end. + + + +%%-----------------------------------------------------------% +%% function : register_resource +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Resource object reference +%% Returns : RecoveryCoordinator (can be used during recovery) +%% Effect : Registers the specified resource as as participant +%% in the transaction associated with the target object. +%% Exception: Inactive - Is prepared or terminated. +%%------------------------------------------------------------ + +register_resource(Self, {Env, Local}, Resource) -> + type_check(?tr_get_typeCheck(Env), ?tr_Resource, + "Coordinator:register_resource", Resource), + case ?etr_get_status(Local) of + 'StatusActive' -> % ok to register the Resource. + NewLocal = ?etr_add_member(Local, Resource), + RecoveryCoord = corba:create_subobject_key(Self, ?tr_get_etrap(Env)), + {reply, RecoveryCoord, {Env, NewLocal}, ?tr_get_timeout(Env)}; + _-> % Not active anymore. New members not ok. + corba:raise(?tr_inactive) + end. + + + +%%-----------------------------------------------------------% +%% function : register_subtran_aware +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% SubTransactionAwareResource object reference +%% Returns : - +%% Effect : Registers the specified object such that it +%% will be notified when the subtransaction has +%% commited or rolled back. +%%------------------------------------------------------------ + +register_subtran_aware(Self, {Env, Local}, SubTrAwareResource) -> + case ?tr_get_parents(Env) of + [] -> + corba:raise(?tr_NotSubtr); + _-> + type_check(?tr_get_typeCheck(Env), ?tr_SubtransactionAwareResource, + "Coordinator:register_subtran_aware", SubTrAwareResource), + NewL = ?etr_add_subAw(Local, SubTrAwareResource), + {reply, ok, {Env, ?etr_set_self(NewL, Self)}, + ?tr_get_timeout(Env)} + end. + +%%-----------------------------------------------------------% +%% function : register_synchronization +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Synchronization +%% Returns : - +%% Effect : +%%------------------------------------------------------------ + +register_synchronization(_Self, {_Env, _Local}, _Synchronization) -> + corba:raise(#'CosTransactions_SynchronizationUnavailable'{}). + +%register_synchronization(Self, {Env, Local}, Synchronization) -> +% type_check(?tr_get_typeCheck(Env), ?tr_Synchronization, +% "Coordinator:register_synchronization", Synchronization), +% case ?etr_get_status(Local) of +% 'StatusActive' -> +% case catch ?tr_get_parents(Env) of +% [] -> +% {reply, ok, {Env, ?etr_add_sync(Local, Synchronization)}, +% ?tr_get_timeout(Env)}; +% [Parent|_] -> +% case catch 'ETraP_Server':register_synchronization(Parent, Self) of +% {'EXCEPTION', E} -> +% corba:raise(E); +% ok -> +% {reply, ok, {Env, ?etr_add_sync(Local, Synchronization)}, +% ?tr_get_timeout(Env)}; +% What -> +% corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_MAYBE}) +% end +% end; +% _ -> +% corba:raise(?tr_inactive) +% end. + +%%-----------------------------------------------------------% +%% function : rollback_only +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : - +%% Effect : The transaction associated with the target object +%% is modified so that rollback IS the result. +%%------------------------------------------------------------ + +rollback_only(Self, {Env, Local}) -> + case ?etr_get_status(Local) of + 'StatusActive' -> + NewL = ?etr_set_status(Local, 'StatusRolledBack'), + NewEnv = ?tr_set_rollback(Env, true), + ?etr_log(?tr_get_etrap(Env),{rollback, NewL}), + send_info(?etr_get_members(NewL), 'CosTransactions_Resource', rollback), + notify_subtrAware(rollback, ?etr_get_subAw(NewL), Self), + {stop, normal, ok, {NewEnv, NewL}}; +%% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, ok, {NewEnv, NewL}}; +% _ -> +% {reply, ok, {NewEnv, NewL}} +% end; + _ -> + corba:raise(?tr_inactive) + end. + +%%-----------------------------------------------------------% +%% function : get_transaction_name +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : string - which describes the transaction associated +%% with the target object. +%% Effect : Intended for debugging. +%%------------------------------------------------------------ + +get_transaction_name(_Self, {Env, Local}) -> + {reply, ?tr_get_etrap(Env), {Env, Local}}. + +%%-----------------------------------------------------------% +%% function : create_subtransaction +%% Arguments: Self - its own object reference. +%% State - Gen-Server State +%% Returns : A control object if subtransactions are allowed, +%% otherwise an exception is raised. +%% Effect : A new subtransaction is created whos parent is +%% the transaction associated with the target object. +%% Exception: SubtransactionUnavailabe - no support for nested +%% transactions. +%% Inactive - already been prepared. +%%------------------------------------------------------------ + +create_subtransaction(Self, {Env, Local}) -> + case ?etr_get_status(Local) of + 'StatusActive' -> + case ?tr_get_subTraOK(Env) of + true -> + ETraPName = 'ETraP_Common':create_name("subc"), + Tname = 'ETraP_Common':create_name("subt"), + + %% Create context for the new object. + State = ?tr_create_context(ETraPName, Tname, + ?tr_get_typeCheck(Env), + ?tr_get_hashMax(Env), + ?tr_get_subTraOK(Env), + ?tr_get_maxR(Env), + ?tr_get_maxW(Env)), + + + State2 = ?tr_add_parent(State, Self), + + State3 = ?tr_set_alarm(State2, ?tr_get_alarm(Env)), + + State4 = ?tr_set_timeout(State3, ?tr_get_timeout(Env)), + + Control = ?tr_start_child(?SUP_ETRAP(State4)), + %% Set the SubCoordinator object reference and register it as participant. + SubCoord = 'CosTransactions_Control':get_coordinator(Control), + NewLocal = ?etr_add_member(Local, SubCoord), + {reply, Control, {Env, NewLocal}, ?tr_get_timeout(Env)}; + _ -> + %% subtransactions not allowed, raise exception. + corba:raise(?tr_subunavailable) + end; + _-> + corba:raise(?tr_inactive) + end. + +%%-----------------------------------------------------------% +%% function : get_txcontext +%% Arguments: +%% Returns : PropagationContext +%% Effect : +%%------------------------------------------------------------ + +get_txcontext(_Self, {_Env, _Local}) -> + corba:raise(#'CosTransactions_Unavailable'{}). + +%get_txcontext(Self, {Env, Local}) -> +% Otid = #'CosTransactions_otid_t'{formatID=0, +% bqual_length=0, +% tid=[corba_object:hash(Self, +% ?tr_get_hashMax(Env))]}, +% TrIDs = create_TransIdentities(?tr_get_parents(Env), Env, [], Otid), +% C=case ?tr_get_parents(Env) of +% [] -> +% #'CosTransactions_TransIdentity'{coord=Self, +% term=?tr_get_terminator(Env), +% otid=Otid}; +% _-> +% #'CosTransactions_TransIdentity'{coord=Self, +% term=?tr_NIL_OBJ_REF, +% otid=Otid} +% end, +% case ?tr_get_timeout(Env) of +% infinity -> +% #'CosTransactions_PropagationContext'{timeout=0, +% current= C, +% parents=TrIDs}; +% T -> +% #'CosTransactions_PropagationContext'{timeout=T/1000, +% current= C, +% parents=TrIDs} +% end. + +%create_TransIdentities([], _, Parents, _) -> Parents; +%create_TransIdentities([Phead|Ptail], Env, Parents, Otid) -> +% NO=Otid#'CosTransactions_TransIdentity'{otid= +% corba_object:hash(Phead, +% ?tr_get_hashMax(Env))}, +% create_TransIdentities([Phead|Ptail], Env, Parents++ +% [#'CosTransactions_TransIdentity'{coord=Phead, +% term=?tr_NIL_OBJ_REF, +% otid=NO}], +% Otid). + + +%%--------- Inherit from CosTransactions::Synchronization --- + +%%-----------------------------------------------------------% +%% function : before_completion +%% Arguments: +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +%before_completion(Self, {Env, Local}) -> +% send_info(?etr_get_sync(Local), +% 'CosTransactions_Synchronization', before_completion), +% {reply, ok, {Env, Local}}. + +%%-----------------------------------------------------------% +%% function : after_completion +%% Arguments: +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +%after_completion(Self, {Env, Local}, Status) -> +% send_info(?etr_get_sync(Local), Status, +% 'CosTransactions_Synchronization', after_completion), +% {stop, normal, ok, {Env, Local}}. + +%%--------------- IMPLEMENTATION SPECIFIC ------------------- +%%-----------------------------------------------------------% +%% function : start_object +%% Arguments: +%% Returns : EXIT, EXCEPTION, or {ok, State} +%% Effect : used by init/1 only. +%%------------------------------------------------------------ + +start_object(Env)-> + ?put_debug_data(self, Env), + Local = ?etr_get_init(Env), + LogName = ?tr_get_etrap(Env), + case catch file:read_file_info(LogName) of + {error, enoent} -> + %% File does not exist. It's the first time. No restart. + ?debug_print("ETraP_Server:init(~p)~n",[?tr_get_etrap(Env)]), + etrap_logmgr:start(LogName), + {ok, + {Env, ?etr_set_status(Local, 'StatusActive')}, + ?tr_get_timeout(Env)}; + {error, Reason} -> + %% File exist but error occurred. + ?tr_error_msg("Control (~p) Cannot open log file: ~p~n", + [LogName, Reason]), + {stop, "unable_to_open_log"}; + _ -> + %% File exists, perform restart. + etrap_logmgr:start(LogName), + ?debug_print("RESTART ~p~n", [?tr_get_etrap(Env)]), + prepare_restart({Env, ?etr_set_status(Local, 'StatusUnknown')}, + ?etr_read(?tr_get_etrap(Env), start)) + end. + + +%%-----------------------------------------------------------% +%% function : send_prepare +%% Arguments: List of registred resources. +%% Returns : ok - equal to void +%% Effect : calls send_prepare/3, which sends a prepare call +%% to resources participating in the transaction and then collect +%% their votes. send_prepare will block until +%% it recieves a reply from the resource. +%%------------------------------------------------------------ + +send_prepare(RegResources, Alarm) -> + send_prepare(RegResources, [], Alarm). + +% All voted ReadOnly. We are done. +send_prepare([], [], _) -> + readOnly; + +% All voted commit (VC) or ReadOnly. +send_prepare([], VC, Alarm) -> + case catch try_timeout(Alarm) of + false -> + {commit, VC}; + _-> + {rollback, VC} + end; + +send_prepare([Rhead|Rtail], VC, Alarm) -> + ?debug_print("send_prepare()~n",[]), + case catch 'CosTransactions_Resource':prepare(Rhead) of + 'VoteCommit' -> + case catch try_timeout(Alarm) of + false -> + _Env = ?get_debug_data(self), + ?eval_debug_fun({?tr_get_etrap(_Env), send_prepare}, _Env), + send_prepare(Rtail, VC++[Rhead], Alarm); + _-> + %% Timeout, rollback. However, the resource did vote + %% commit. Add it to the list. + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC++[Rhead]} + end; + 'VoteRollback' -> + %% Don't care about timeout since we voted rollback. + %% A rollback received. No need for more prepare-calls. + %% See OMG 10-51, Transaction Service:v1.0 + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC}; + 'VoteReadOnly' -> + case catch try_timeout(Alarm) of + false -> + send_prepare(Rtail, VC, Alarm); + _-> + %% timeout, reply rollback. + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC} + end; + {'EXCEPTION',E} when is_record(E, 'TIMEOUT') -> + ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n", + [Rhead]), + %% Since we use presumed abort we will rollback the transaction. + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC}; + {'EXCEPTION',E} when is_record(E, 'TRANSIENT') -> + ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n", + [Rhead]), + %% Since we use presumed abort we will rollback the transaction. + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC}; + {'EXCEPTION',E} when is_record(E, 'COMM_FAILURE') -> + ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n", + [Rhead]), + %% Since we use presumed abort we will rollback the transaction. + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC}; + {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') -> + ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n", + [Rhead]), + send_info(Rtail, 'CosTransactions_Resource', rollback), + {rollback, VC}; + {'EXCEPTION', Exc} -> + ?tr_error_msg("Coordinator:prepare( ~p )~nThe Object raised exception: ~p~n", + [Rhead, Exc]), + send_info(Rtail, 'CosTransactions_Resource', rollback), + %% This can occur if a subtransaction get one or more + %% "VoteCommit" followed by a "VoteRollback". + %% The subtransaction then do a send_decision(rollback), + %% which can generate Heuristic decisions. Must rollback + %% since at least one participant voted rollback. + {'EXCEPTION', Exc, VC, Rhead}; + Other -> + ?tr_error_msg("Coordinator:prepare( ~p ) failed. REASON ~p~n", + [Rhead, Other]), + send_info(Rtail, 'CosTransactions_Resource', rollback), + {failed, VC} + end. + +%%-----------------------------------------------------------% +%% function : type_check +%% Arguments: Bool - perform typecheck? +%% ID - Type it should be. +%% Func - Name of the function (for error_msg) +%% Obj - objectrefernce to test. +%% Returns : 'ok' or raises exception. +%% Effect : +%%------------------------------------------------------------ +type_check(false, _, _, _) -> + ok; +type_check(_, ID, Func, Obj) -> + case catch corba_object:is_a(Obj,ID) of + true -> + ok; + _ -> + ?tr_error_msg("~p( ~p ) Bad argument!!~n", [Func, Obj]), + corba:raise(?tr_badparam) + end. + +%%-----------------------------------------------------------% +%% function : is_heuristic +%% Arguments: Exception +%% Returns : boolean +%% Effect : Returns true if the exception is a heuristic exc. +%%------------------------------------------------------------ + +is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicMixed') -> true; +is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicHazard') -> true; +is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicCommit') -> true; +is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicRollback') -> true; +is_heuristic(_) -> false. + +%%-----------------------------------------------------------% +%% function : exception_set +%% Arguments: Genserver state +%% Returns : +%% Effect : Used when restarting. +%%------------------------------------------------------------ + +exception_set({Env,Local}) -> + case ?etr_get_exc(Local) of + void -> + self() ! {suicide, self()}, + {ok, {Env, Local}}; + _ -> + {ok, {Env, Local}} + end. + +%%-----------------------------------------------------------% +%% function : set_exception +%% Arguments: Locally defined #exc{} +%% Heuristic mixed or hazard Exeption +%% Returns : Altered locally defined #exc{} +%% Effect : Set the correct tuple member to true. +%%------------------------------------------------------------ + +set_exception(Exc, E) when is_record(E, 'CosTransactions_HeuristicMixed') -> + Exc#exc{mixed = true}; +set_exception(Exc, E) when is_record(E, 'CosTransactions_HeuristicHazard') -> + Exc#exc{hazard = true}; +set_exception(Exc, _) -> Exc. + +%%-----------------------------------------------------------% +%% function : send_forget +%% Arguments: +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +send_forget([], _) -> ok; +send_forget([Rhead|Rtail], LogName) -> + ?debug_print("send_forget()~n",[]), + _Env = ?get_debug_data(self), + case catch 'CosTransactions_Resource':forget(Rhead) of + ok -> + ?eval_debug_fun({?tr_get_etrap(_Env), send_forget1}, _Env), + ?etr_log(LogName, {forgotten, Rhead}), + ?eval_debug_fun({?tr_get_etrap(_Env), send_forget2}, _Env), + send_forget(Rtail, LogName); + Other -> + ?tr_error_msg("CosTransactions_Coordinator failed sending forget to ~p~nREASON: ~p~n", + [Rhead, Other]), + ?eval_debug_fun({?tr_get_etrap(_Env), send_forget3}, _Env), + ?etr_log(LogName, {not_forgotten, Rhead}), + ?eval_debug_fun({?tr_get_etrap(_Env), send_forget4}, _Env), + send_forget(Rtail, LogName) + end. + +%%-----------------------------------------------------------% +%% function : send_decision +%% Arguments: List of registred resources which vote commit. +%% Vote - the outcome of the transaction. +%% Returns : ok - equal to void +%% Effect : Inform those who voted commit of the outcome. +%% They who voted rollback already knows the outcome. +%% They who voted ReadOnly are not affected. +%%------------------------------------------------------------ + +%%-- Adding extra parameters +send_decision({Env, Local}, Reply, Vote) -> + send_decision({Env, Local}, Reply, ?etr_get_vc(Local), Vote, #exc{}, [], 0). +send_decision({Env, Local}, Reply, Vote, VC) -> + send_decision({Env, Local}, Reply, VC, Vote, #exc{}, [], 0). +send_decision(State, no_reply, VC, Vote, Exc) -> + send_decision(State, no_reply, VC, Vote, Exc, [], 0). + +%%-- Decision sent to all members. Do not reply (used when restarting). +send_decision({Env, Local}, no_reply, [], _, #exc{mixed = true}, [], _) -> + {Env, ?etr_set_exc(Local, ?tr_mixed)}; +send_decision({Env, Local}, no_reply, [], _, #exc{hazard = true}, [], _) -> + {Env, ?etr_set_exc(Local, ?tr_hazard)}; +send_decision({Env, Local}, no_reply, [], _, _, [], _) -> + {Env, Local}; +send_decision({Env, Local}, no_reply, [], Vote, Exc, Failed, Times) -> + case ?tr_get_maxR(Env) of + Times -> + ?tr_error_msg("MAJOR ERROR, failed sending commit decision to: ~p. Tried ~p times.", [Failed,Times]), + {Env, ?etr_set_exc(Local, ?tr_hazard)}; + _-> + timer:sleep(?tr_get_maxW(Env)), + NewTimes = Times+1, + send_decision({Env, Local}, no_reply, Failed, Vote, Exc, [], NewTimes) + end; +%%-- end special cases. + +%% Decision sent to all members. Test exceptions. +send_decision({Env, Local}, Reply, [], Vote, Exc, [], _) -> + notify_subtrAware(Vote, ?etr_get_subAw(Local), ?etr_get_self(Local)), + test_exc(Exc, Vote, Reply, {Env, Local}); +%% Decision not sent to all members (one or more failed). Retry. +send_decision({Env, Local}, Reply, [], Vote, Exc, Failed, Times) -> + case ?tr_get_maxR(Env) of + Times -> + ?tr_error_msg("MAJOR ERROR, failed sending commit decision to: ~p. Tried ~p times.", [Failed,Times]), + notify_subtrAware(Vote, ?etr_get_subAw(Local), ?etr_get_self(Local)), + test_exc(Exc#exc{hazard = true}, Vote, Reply, {Env, Local}); + _-> + NewTimes = Times+1, + timer:sleep(?tr_get_maxW(Env)), + send_decision({Env, Local}, Reply, Failed, Vote, Exc, [], NewTimes) + end; + +send_decision({Env, Local}, Reply, [Rhead|Rtail], Vote, Exc, Failed, Times) -> + ?debug_print("Coordinator:send_decision(~p) Try: ~p~n",[Vote, Times]), + case catch 'CosTransactions_Resource':Vote(Rhead) of + ok -> + ?etr_log(?tr_get_etrap(Env),{sent, Rhead}), + send_decision({Env, Local}, Reply, Rtail, Vote, Exc, Failed, Times); + {'EXCEPTION', E} when Vote == commit andalso + is_record(E, 'CosTransactions_NotPrepared') -> + ?debug_print("send_decision resource unprepared~n",[]), + case catch 'CosTransactions_Resource':prepare(Rhead) of + 'VoteCommit' -> + send_decision({Env, Local}, Reply, [Rhead|Rtail], Vote, Exc, Failed, Times); + 'VoteRollback' -> + send_decision({Env, Local}, Reply, Rtail, Vote, Exc#exc{mixed = true}, Failed, Times); + {'EXCEPTION', E} -> + {SetExc, NewL, DidFail} = + evaluate_answer(E, Rhead, Vote, Exc, + ?tr_get_etrap(Env), Local), + send_decision({Env, NewL}, Reply, Rtail, Vote, SetExc, DidFail++Failed, Times) + end; + {'EXCEPTION', E} -> + {SetExc, NewL, DidFail} = + evaluate_answer(E, Rhead, Vote, Exc, ?tr_get_etrap(Env), Local), + ?tr_error_msg("Resource:~p( ~p )~nRaised Exception: ~p~n", + [Vote, Rhead, E]), + send_decision({Env, NewL}, Reply, Rtail, Vote, SetExc, DidFail++Failed, Times); + {'EXIT', _} -> + send_decision({Env, Local}, Reply, Rtail, + Vote, Exc, [Rhead|Failed], Times); + Other -> + ?tr_error_msg("Resource:~p( ~p ) failed.~nREASON: ~p~n", + [Vote, Rhead, Other]), + case catch corba_object:non_existent(Rhead) of + true when Vote == commit -> + %% Presumed rollback + send_decision({Env, Local}, Reply, Rtail, Vote, + Exc#exc{mixed = true}, Failed, Times); + true -> + %% Presumed rollback + send_decision({Env, Local}, Reply, Rtail, Vote, + Exc#exc{hazard = true}, Failed, Times); + _ -> + send_decision({Env, Local}, Reply, Rtail, + Vote, Exc, [Rhead|Failed], Times) + end + end. + +%%-----------------------------------------------------------% +%% function : notify_subtrAware, +%% Arguments: +%% Returns : +%% Effect : Invoke an operation on a list of objects. We don't +%% care about return values or exceptions. +%%------------------------------------------------------------ + +notify_subtrAware(commit, Resources, Self) -> + send_info(Resources, Self, + 'CosTransactions_SubtransactionAwareResource', + commit_subtransaction); +notify_subtrAware(_, Resources, _) -> + send_info(Resources, 'CosTransactions_SubtransactionAwareResource', + rollback_subtransaction). + +%%-----------------------------------------------------------% +%% function : send_info +%% Arguments: ObjectList - List of object refernces to call. +%% M - Module +%% F - Function +%% (Arg - required arguments) +%% Returns : ok +%% Effect : A lightweight function to be used when we don't +%% "care" about the return value. +%%------------------------------------------------------------ + +send_info([], _, _, _) -> + ok; +send_info([Rhead|Rtail], Arg, M, F) -> + ?debug_print("~p( ~p )~n",[F, Arg]), + case catch M:F(Rhead, Arg) of + {'EXIT',R} -> + ?tr_error_msg("~p:~p(~p, ~p) returned {'EXIT',~p}", [M,F,Rhead,Arg,R]); + {'EXCEPTION',E} -> + ?tr_error_msg("~p:~p(~p, ~p) returned {'EXCEPTION',~p}", [M,F,Rhead,Arg,E]); + _-> + ok + end, + send_info(Rtail, Arg, M, F). + +send_info([], _, _) -> + ok; +send_info([Rhead|Rtail], M, F) -> + ?debug_print("~p( )~n",[F]), + case catch M:F(Rhead) of + {'EXIT',R} -> + ?tr_error_msg("~p:~p(~p) returned {'EXIT',~p}", [M,F,Rhead,R]); + {'EXCEPTION',E} -> + ?tr_error_msg("~p:~p(~p) returned {'EXCEPTION',~p}", [M,F,Rhead,E]); + _-> + ok + end, + send_info(Rtail, M, F). + +%%-----------------------------------------------------------% +%% function : evaluate_answer +%% Arguments: +%% Returns : +%% Effect : Check what kind of exception we received. +%%------------------------------------------------------------ + +evaluate_answer(E, Rhead, _Vote, Exc, Log, Local) + when is_record(E, 'CosTransactions_HeuristicMixed') -> + ?etr_log(Log, {heuristic, {Rhead, E}}), + {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []}; +evaluate_answer(E, Rhead, _Vote, Exc, Log, Local) + when is_record(E, 'CosTransactions_HeuristicHazard') -> + ?etr_log(Log, {heuristic, {Rhead, E}}), + {Exc#exc{hazard = true}, ?etr_add_raisedH(Local, Rhead), []}; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local) + when is_record(E, 'CosTransactions_HeuristicCommit') -> + case Vote of + commit -> + ?etr_log(Log, {heuristic, {Rhead, E}}), + {Exc, ?etr_add_raisedH(Local, Rhead), []}; + _-> + ?etr_log(Log, {heuristic, {Rhead, ?tr_mixed}}), + {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []} + end; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local) + when is_record(E, 'CosTransactions_HeuristicRollback')-> + case Vote of + rollback -> + ?etr_log(Log, {heuristic, {Rhead, ?tr_rollback}}), + {Exc, ?etr_add_raisedH(Local, Rhead), []}; + _-> + ?etr_log(Log, {heuristic, {Rhead, ?tr_mixed}}), + {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []} + end; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local) + when Vote == commit andalso is_record(E, 'TRANSACTION_ROLLEDBACK') -> + ?etr_log(Log, {heuristic, {Rhead, ?tr_mixed}}), + {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []}; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local) when is_record(E, 'TIMEOUT') -> + ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n", + [Vote, Rhead, E]), + case catch corba_object:non_existent(Rhead) of + true -> + %% Since we have presumed abort, the child will + %% assume rollback if this server do not exist any more. + ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}), + {Exc#exc{hazard = true}, Local, []}; + _ -> + {Exc, Local, [Rhead]} + end; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local) when is_record(E, 'TRANSIENT') -> + ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n", + [Vote, Rhead, E]), + case catch corba_object:non_existent(Rhead) of + true -> + %% Since we have presumed abort, the child will + %% assume rollback if this server do not exist any more. + ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}), + {Exc#exc{hazard = true}, Local, []}; + _ -> + {Exc, Local, [Rhead]} + end; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local) when is_record(E, 'COMM_FAILURE') -> + ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n", + [Vote, Rhead, E]), + case catch corba_object:non_existent(Rhead) of + true -> + %% Since we have presumed abort, the child will + %% assume rollback if this server do not exist any more. + ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}), + {Exc#exc{hazard = true}, Local, []}; + _ -> + {Exc, Local, [Rhead]} + end; +evaluate_answer(E, Rhead, Vote, Exc, Log, Local)when is_record(E, 'OBJECT_NOT_EXIST') -> + ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n", + [Vote, Rhead, E]), + %% Since we have presumed abort, the child will + %% assume rollback if this server do not exist any more. + ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}), + {Exc#exc{hazard = true}, Local, []}; +evaluate_answer(Unknown, Rhead, Vote, Exc, _Log, Local)-> + ?tr_error_msg("Coordinator:~p( ~p ). Unknown reply: ~p.~n", + [Vote, Rhead, Unknown]), + {Exc, Local, []}. + + +%%-----------------------------------------------------------% +%% function : test_exc +%% Arguments: Exc - instance of #exc{} locally declared. +%% Vote - 'rollback' or 'commit' +%% Reply - If no exceptions this is the default reply. +%% State - genserver state +%% Returns : +%% Effect : Raise the correct exception or simply reply to +%% the genserver. NOTE that the testing for exceptions +%% differs if we are performing a rollback or commit. +%% Check if Mixed first; takes priority over Hazard. +%% HeuristicRollback and VoteCommit together give +%% HeuristicMixed +%% HeuristicCommit and VoteRollback together give +%% HeuristicMixed +%%------------------------------------------------------------ + +test_exc(#exc{mixed = true}, _, _, {Env, Local}) -> + {reply, {'EXCEPTION', ?tr_mixed}, {Env, ?etr_set_exc(Local, ?tr_mixed)}}; +% Left out for now to avoid dialyzer warning. +%test_exc(#exc{rollback = true}, commit, _, {Env, Local}) -> +% {reply, {'EXCEPTION', ?tr_mixed}, {Env, ?etr_set_exc(Local, ?tr_mixed)}}; +% Left out for now to avoid dialyzer warning. +%test_exc(#exc{commit = true}, rollback, _, {Env, Local}) -> +% {reply, {'EXCEPTION', ?tr_mixed}, {Env, ?etr_set_exc(Local, ?tr_mixed)}}; +test_exc(#exc{hazard = true}, _, _, {Env, Local}) -> + {reply, {'EXCEPTION', ?tr_hazard}, {Env, ?etr_set_exc(Local, ?tr_hazard)}}; +test_exc(_, _, {'EXCEPTION', E}, {Env, Local}) + when is_record(E, 'TRANSACTION_ROLLEDBACK')-> + {stop, normal, {'EXCEPTION', E}, {Env, Local}}; +%% Replace the case above if allow synchronization +%test_exc(_, _, {'EXCEPTION', E}, {Env, Local}) +% when record(E, 'TRANSACTION_ROLLEDBACK')-> +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, {'EXCEPTION', E}, {Env, Local}}; +% _-> +% {reply, {'EXCEPTION', E}, {Env, Local}} +% end; +test_exc(_, _, {'EXCEPTION', E}, State) -> + {reply, {'EXCEPTION', E}, State}; +test_exc(_, _, Reply, {Env, Local}) -> + {stop, normal, Reply, {Env, Local}}. +%% Replace the case above if allow synchronization +%test_exc(_, _, Reply, {Env, Local}) -> +% case ?etr_get_sync(Local) of +% [] -> +% {stop, normal, Reply, {Env, Local}}; +% _ -> +% {reply, Reply, {Env, Local}} +% end. + +%%-----------------------------------------------------------% +%% function : evaluate_status +%% Arguments: +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +evaluate_status(Status) -> + case Status of + 'StatusCommitted' -> commit; + 'StatusCommitting' -> commit; + 'StatusMarkedRollback' -> rollback; + 'StatusRollingBack' -> rollback; + 'StatusRolledBack' -> rollback; + 'StatusActive' -> rollback; + 'StatusPrepared' -> rollback; + 'StatusUnknown' -> rollback; + 'StatusNoTransaction' -> rollback; + 'StatusPreparing' -> rollback; + _-> rollback + end. + + +%%-----------------------------------------------------------% +%% function : prepare_restart +%% Arguments: +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +%% The file contains no data. The coordinator crashed before +%% a prepare-call was made. Presumed rollback. +prepare_restart(State, eof) -> + ?debug_print("prepare_restart: eof, init~n",[]), + self() ! {suicide, self()}, + {ok, State}; +%% Collected all necessary votes. Do commit_restart. +prepare_restart({Env, _}, {{pre_vote, _Vote, Data}, Cursor}) -> + ?debug_print("prepare_restart: pre_vote( ~p )~n",[_Vote]), + if + ?tr_is_root(Env) -> + commit_restart({Env, Data}, + ?etr_read(?tr_get_etrap(Env), Cursor), root); + true -> + commit_restart({Env, Data}, + ?etr_read(?tr_get_etrap(Env), Cursor), subCoord) + end; +%% 'rollback' called without 'prepare'. This case occurs if the Coordinator +%% crashes when send_info or notify_subtrAware. +prepare_restart({Env, _}, {{rollback, NewL}, _Cursor}) -> + ?debug_print("prepare_restart: pre_vote( rollback )~n",[]), + send_info(?etr_get_members(NewL), 'CosTransactions_Resource', rollback), + notify_subtrAware(rollback, ?etr_get_subAw(NewL), ?etr_get_self(NewL)), + self() ! {suicide, self()}, + {ok, {Env, NewL}}; +%% Something is wrong in the log. +prepare_restart(_, _) -> + ?tr_error_msg("Internal log read failed:~n", []), + {stop, {error, "restart failed"}}. + +%%-----------------------------------------------------------% +%% function : commit_restart +%% Arguments: Env - server context +%% Returns : +%% Effect : +%%------------------------------------------------------------ +commit_restart({Env, Local}, Data, Phase) -> + Exc = set_exception(#exc{}, ?etr_get_exc(Local)), + commit_restart({Env, Local}, Data, Phase, Exc). + +%% Normal case. No errors no exceptions. +commit_restart({Env, Local}, {{sent, Obj}, Cursor}, Vote, Exc) -> + ?debug_print("commit_restart: sent~n",[]), + commit_restart({Env, ?etr_remove_vc(Local, Obj)}, + ?etr_read(?tr_get_etrap(Env), Cursor), Vote, Exc); +commit_restart({Env, Local}, {{heuristic, {Obj,E}}, Cursor}, Vote, Exc) -> + ?debug_print("commit_restart: heuristic ~p~n",[E]), + NewExc = set_exception(Exc, E), + commit_restart({Env, ?etr_add_raisedH(Local, Obj)}, + ?etr_read(?tr_get_etrap(Env), Cursor), Vote, NewExc); + + +%% --- cases which only can occure once in the log ------------ + +%% The file contains no data. The coordinator crashed before +%% a decision was made. Causes rollback. +commit_restart({E, L}, eof, root, Exc) -> + ?debug_print("commit_restart: eof init (root only)~n",[]), + {Env, Local} = send_decision({E, L}, no_reply, ?etr_get_vc(L), + rollback, Exc), + exception_set({Env, Local}); +%% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% exception_set({Env, Local}); +% SynchObjs -> +% {ok, {Env, Local}} +% end; + + +%% Passed the prepare_restart. Not received a commit decision from the +%% parent. +commit_restart({E, L}, eof, subCoord, Exc) -> + ?debug_print("commit_restart: eof init (subcoord only)~n",[]), + case catch corba_object:non_existent(?tr_get_parent(E)) of + true -> + %% Presumed rollback. + {Env, Local} = send_decision({E, L}, no_reply, ?etr_get_vc(L), + rollback, Exc), + self() ! {suicide, self()}, + {ok, {Env, Local}}; +%% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% self() ! {suicide, self()}, +% {ok, {Env, Local}}; +% SynchObjs -> +% case ?tr_get_parents(Env) of +% [] -> +% send_info(SynchObjs, ?etr_get_status(Local), +% 'CosTransactions_Synchronization', after_completion); +% _-> +% ok +% end, +% self() ! {suicide, self()}, +% {ok, {Env, Local}} +% end; + _-> + {ok, {E, L}} + end; + +commit_restart({Env, Local}, eof, Vote, Exc) -> + ?debug_print("commit_restart: eof VOTE: ~p~n",[Vote]), + case ?etr_get_vc(Local) of + [] -> + ?debug_print("commit_restart: all sent, test exc~n",[]), + exception_set({Env, Local}); + VC -> + ?debug_print("commit_restart: note done. send more~n",[]), + State = send_decision({Env, Local}, no_reply, VC, Vote, Exc), + exception_set(State) + end; + +%% Decision made, i.e. rollback or commit. +commit_restart({Env, Local}, {rollback, Cursor}, _Phase, Exc) -> + ?debug_print("commit_restart: decided rollback~n",[]), + commit_restart({Env, ?etr_set_status(Local, 'StatusRolledBack')}, + ?etr_read(?tr_get_etrap(Env), Cursor), rollback, Exc); +commit_restart({Env, Local}, {commit, Cursor}, _Phase, Exc) -> + ?debug_print("commit_restart: decided commit~n",[]), + commit_restart({Env, ?etr_set_status(Local, 'StatusCommitted')}, + ?etr_read(?tr_get_etrap(Env), Cursor), commit, Exc); +commit_restart({Env, Local}, {forget_phase, Cursor}, _, _) -> + ?debug_print("commit_restart: start sending forget~n",[]), + forget_restart({Env, Local}, ?etr_read(?tr_get_etrap(Env), Cursor)); + +commit_restart({_Env, _Local}, _R, _, _) -> + ?debug_print("RESTART FAIL: ~p~n",[_R]), + ?tr_error_msg("Internal log read failed:~n", []), + exit("restart failed"). + +%%-----------------------------------------------------------% +%% function : forget_restart +%% Arguments: {Env, Local} - server context +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +%% Exception logged. Test if we issued a 'forget()' to the Resource. +forget_restart({Env, Local}, eof) -> + case ?etr_get_raisedH(Local) of + [] -> + ?debug_print("forget_restart: all done~n",[]); + Left -> + ?debug_print("forget_restart: not done. send more~n",[]), + send_forget(Left, ?tr_get_etrap(Env)) + end, + self() ! {suicide, self()}, + {ok, {Env, Local}}; +%% Replace the reply above if allow synchronization +% case ?etr_get_sync(Local) of +% [] -> +% self() ! {suicide, self()}, +% {ok, {Env, Local}}; +% SynchObjs -> +% case ?tr_get_parents(Env) of +% [] -> +% send_info(SynchObjs, ?etr_get_status(Local), +% 'CosTransactions_Synchronization', after_completion), +% self() ! {suicide, self()}, +% {ok, {Env, Local}}; +% _-> +% {ok, {Env, Local}} +% end +% end; +forget_restart({Env, Local}, {{forgotten, Obj}, Cursor}) -> + ?debug_print("forget_restart: forgotten heuristic~n",[]), + NewL = ?etr_remove_raisedH(Local, Obj), + forget_restart({Env, NewL}, ?etr_read(?tr_get_etrap(Env), Cursor)); +forget_restart({Env, Local}, {{not_forgotten, Obj}, Cursor}) -> + ?debug_print("forget_restart: not_forgotten~n",[]), + NewL = ?etr_remove_raisedH(Local, Obj), + send_forget([Obj], dummy), + forget_restart({Env, NewL}, ?etr_read(?tr_get_etrap(Env), Cursor)). + +%%--------------- END OF MODULE ------------------------------ diff --git a/lib/cosTransactions/src/Makefile b/lib/cosTransactions/src/Makefile new file mode 100644 index 0000000000..7e10ec175b --- /dev/null +++ b/lib/cosTransactions/src/Makefile @@ -0,0 +1,175 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1999-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# +# +include $(ERL_TOP)/make/target.mk +EBIN=../ebin + +ifeq ($(TYPE),debug) +ERL_COMPILE_FLAGS += -Ddebug -W +endif + +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk +VSN=$(COSTRANSACTIONS_VSN) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/cosTransactions-$(VSN) +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES = \ + ETraP_Common \ + etrap_logmgr \ + ETraP_Server_impl \ + CosTransactions_Terminator_impl \ + CosTransactions_TransactionFactory_impl \ + cosTransactions + +ERL_FILES = $(MODULES:%=%.erl) +HRL_FILES = \ + ETraP_Common.hrl + +GEN_ERL_FILES = \ + oe_CosTransactions.erl \ + CosTransactions_Control.erl \ + CosTransactions_Coordinator.erl \ + CosTransactions_HeuristicCommit.erl \ + CosTransactions_HeuristicHazard.erl \ + CosTransactions_HeuristicMixed.erl \ + CosTransactions_HeuristicRollback.erl \ + CosTransactions_Inactive.erl \ + CosTransactions_InvalidControl.erl \ + CosTransactions_NoTransaction.erl \ + CosTransactions_NotPrepared.erl \ + CosTransactions_NotSubtransaction.erl \ + CosTransactions_RecoveryCoordinator.erl \ + CosTransactions_Resource.erl \ + CosTransactions_SubtransactionAwareResource.erl \ + CosTransactions_SubtransactionsUnavailable.erl \ + CosTransactions_Terminator.erl \ + CosTransactions_TransactionFactory.erl \ + CosTransactions_Unavailable.erl \ + CosTransactions_SynchronizationUnavailable.erl \ + CosTransactions_TransIdentity.erl \ + CosTransactions_PropagationContext.erl \ + CosTransactions_otid_t.erl \ + CosTransactions_WrongTransaction.erl \ + ETraP_Server.erl +# CosTransactions_Synchronization.erl \ + +EXTERNAL_INC_PATH = ../include + +GEN_HRL_FILES = \ + oe_CosTransactions.hrl \ + CosTransactions.hrl \ + CosTransactions_Control.hrl \ + CosTransactions_Coordinator.hrl \ + CosTransactions_RecoveryCoordinator.hrl \ + CosTransactions_Resource.hrl \ + CosTransactions_SubtransactionAwareResource.hrl \ + CosTransactions_Terminator.hrl \ + CosTransactions_TransactionFactory.hrl \ + ETraP.hrl \ + ETraP_Server.hrl +# CosTransactions_Synchronization.hrl \ + +EXTERNAL_GEN_HRL_FILES = $(GEN_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%) + +GEN_FILES = $(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES) + +TARGET_FILES = \ + $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \ + $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +IDL_FILE = \ + CosTransactions.idl + +APPUP_FILE = cosTransactions.appup +APPUP_SRC = $(APPUP_FILE).src +APPUP_TARGET = $(EBIN)/$(APPUP_FILE) + +APP_FILE = cosTransactions.app +APP_SRC = $(APP_FILE).src +APP_TARGET = $(EBIN)/$(APP_FILE) + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosTransactions/ebin \ + -pa $(ERL_TOP)/lib/ic/ebin\ + -pa $(ERL_TOP)/lib/orber/ebin + +# The -pa option is just used temporary until erlc can handle +# includes from other directories than ../include . +ERL_COMPILE_FLAGS += \ + $(ERL_IDL_FLAGS) \ + -I$(ERL_TOP)/lib/cosTransactions/include \ + -I$(ERL_TOP)/lib/orber/include \ + +'{parse_transform,sys_pre_attributes}' \ + +'{attribute,insert,app_vsn,"cosTransactions_$(COSTRANSACTIONS_VSN)"}' + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) + +debug: + @${MAKE} TYPE=debug + +clean: + rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) + rm -f errs core *~ + +$(APP_TARGET): $(APP_SRC) + sed -e 's;%VSN%;$(VSN);' $(APP_SRC) > $(APP_TARGET) + +$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk + sed -e 's;%VSN%;$(VSN);' $< > $@ + +docs: + +# ---------------------------------------------------- +# Special Build Targets +# ---------------------------------------------------- +$(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES): CosTransactions.idl + erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTransactions.cfg"}' CosTransactions.idl + mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH) + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/ebin + $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin + $(INSTALL_DIR) $(RELSYSDIR)/src + $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILE) $(RELSYSDIR)/src + $(INSTALL_DIR) $(RELSYSDIR)/include + $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) $(RELSYSDIR)/include + +release_docs_spec: diff --git a/lib/cosTransactions/src/cosTransactions.app.src b/lib/cosTransactions/src/cosTransactions.app.src new file mode 100644 index 0000000000..52769b1711 --- /dev/null +++ b/lib/cosTransactions/src/cosTransactions.app.src @@ -0,0 +1,43 @@ +{application, cosTransactions, + [{description, "The Erlang CosTransactions application"}, + {vsn, "%VSN%"}, + {modules, + [ + etrap_logmgr, + 'ETraP_Server_impl', + 'CosTransactions_Terminator_impl', + 'CosTransactions_TransactionFactory_impl', + 'ETraP_Common', + oe_CosTransactions, + 'CosTransactions_Control', + 'CosTransactions_Coordinator', + 'CosTransactions_HeuristicCommit', + 'CosTransactions_HeuristicHazard', + 'CosTransactions_HeuristicMixed', + 'CosTransactions_HeuristicRollback', + 'CosTransactions_Inactive', + 'CosTransactions_InvalidControl', + 'CosTransactions_NoTransaction', + 'CosTransactions_NotPrepared', + 'CosTransactions_NotSubtransaction', + 'CosTransactions_RecoveryCoordinator', + 'CosTransactions_Resource', + 'CosTransactions_SubtransactionAwareResource', + 'CosTransactions_SubtransactionsUnavailable', + 'CosTransactions_Terminator', + 'CosTransactions_TransactionFactory', + 'CosTransactions_Unavailable', + 'CosTransactions_SynchronizationUnavailable', + 'CosTransactions_TransIdentity', + 'CosTransactions_PropagationContext', + 'CosTransactions_otid_t', + 'CosTransactions_WrongTransaction', + 'ETraP_Server', + cosTransactions + ] + }, + {registered, [cosTransactions_sup, oe_cosTransactionsFactory]}, + {applications, [orber, stdlib, kernel]}, + {env, []}, + {mod, {cosTransactions, []}} +]}. diff --git a/lib/cosTransactions/src/cosTransactions.appup.src b/lib/cosTransactions/src/cosTransactions.appup.src new file mode 100644 index 0000000000..f3eead4a0c --- /dev/null +++ b/lib/cosTransactions/src/cosTransactions.appup.src @@ -0,0 +1,6 @@ +{"%VSN%", + [ + ], + [ + ] +}. diff --git a/lib/cosTransactions/src/cosTransactions.erl b/lib/cosTransactions/src/cosTransactions.erl new file mode 100644 index 0000000000..ffc01f50a4 --- /dev/null +++ b/lib/cosTransactions/src/cosTransactions.erl @@ -0,0 +1,115 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : cosTransactions.erl +%% Purpose : Initialize the 'cosTransactions' application +%%---------------------------------------------------------------------- + +-module(cosTransactions). + +%%--------------- INCLUDES ----------------------------------- +%% Local +-include_lib("ETraP_Common.hrl"). +-include_lib("CosTransactions.hrl"). +%%--------------- EXPORTS------------------------------------- +%% cosTransactions API external +-export([start/0, stop/0, start_factory/1, start_factory/0, stop_factory/1]). + +%% Application callbacks +-export([start/2, init/1, stop/1]). + +%%------------------------------------------------------------ +%% function : start/stop +%% Arguments: +%% Returns : +%% Effect : Starts or stops the cosTRansaction application. +%%------------------------------------------------------------ + +start() -> + application:start(cosTransactions). +stop() -> + application:stop(cosTransactions). + +%%------------------------------------------------------------ +%% function : start_factory +%% Arguments: none or an argumentlist which by default is defined +%% in ETraP_Common.hrl, i.e., '?tr_FAC_DEF' +%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason} +%% Effect : Starts a CosTransactions_TransactionFactory +%%------------------------------------------------------------ + +start_factory() -> + ?tr_start_child(?SUP_FAC(?tr_FAC_DEF)). + +start_factory(Args) when is_list(Args) -> + ?tr_start_child(?SUP_FAC(Args)); +start_factory(Args) -> + ?tr_error_msg("applications:start( ~p ) failed. Bad parameters~n", [Args]), + exit("applications:start failed. Bad parameters"). + +%%------------------------------------------------------------ +%% function : stop_factory +%% Arguments: Factory Object Reference +%% Returns : ok | {'EXCEPTION', _} +%% Effect : +%%------------------------------------------------------------ + +stop_factory(Fac)-> + corba:dispose(Fac). + +%%------------------------------------------------------------ +%% function : start +%% Arguments: Type - see module application +%% Arg - see module application +%% Returns : +%% Effect : Module callback for application +%%------------------------------------------------------------ + +start(_, _) -> + supervisor:start_link({local, ?SUPERVISOR_NAME}, cosTransactions, app_init). + + +%%------------------------------------------------------------ +%% function : stop +%% Arguments: Arg - see module application +%% Returns : +%% Effect : Module callback for application +%%------------------------------------------------------------ + +stop(_) -> + ok. + +%%------------------------------------------------------------ +%% function : init +%% Arguments: +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +%% Starting using create_factory/X +init(own_init) -> + {ok,{?SUP_FLAG, [?SUP_CHILD]}}; +%% When starting as an application. +init(app_init) -> + {ok,{?SUP_FLAG, [?SUP_CHILD]}}. + + +%%--------------- END OF MODULE ------------------------------ diff --git a/lib/cosTransactions/src/etrap_logmgr.erl b/lib/cosTransactions/src/etrap_logmgr.erl new file mode 100644 index 0000000000..a418d782e3 --- /dev/null +++ b/lib/cosTransactions/src/etrap_logmgr.erl @@ -0,0 +1,200 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : etrap_logmgr.erl +%% Purpose : Make it easier to use disk_log. +%%---------------------------------------------------------------------- + +-module(etrap_logmgr). + +%%--------------- INCLUDES ----------------------------------- +%% Local +-include_lib("ETraP_Common.hrl"). +%%--------------- IMPORTS------------------------------------- +%%--------------- EXPORTS------------------------------------- +-export([start/1, stop/1, log_safe/2, log_lazy/2, get_next/2]). + + +%%------------------------------------------------------------ +%% function : start +%% Arguments: LogName - name of the disk_log. +%% Returns : +%% Effect : creating linked log +%%------------------------------------------------------------ + +start(LogName) -> + case catch disk_log:open([{name, LogName}, + {file, LogName}, + {type, halt}, + {size, infinity}]) of + {ok, LogName} -> + ok; + {error, Reason} -> + ?tr_error_msg("Initiating internal log failed: ~p", [Reason]), + exit({error, Reason}); + {repaired, LogName, {recovered, _Rec}, {badbytes, _Bad}} -> + ok; + Other -> + ?tr_error_msg("Initiating internal log failed: ~p", [Other]), + exit({error, Other}) + end. + +%%------------------------------------------------------------ +%% function : stop +%% Arguments: LogName - name of the disk_log. +%% Returns : +%% Effect : +%%------------------------------------------------------------ + +stop(LogName) -> + case catch disk_log:close(LogName) of + ok -> + ok; + {error, Reason} -> + ?tr_error_msg("Stopping internal log failed: ~p", [Reason]), + {error, Reason}; + Other -> + ?tr_error_msg("Stopping internal log failed: ~p", [Other]), + {error, Other} + end. + + +%%------------------------------------------------------------ +%% function : log_safe +%% Arguments: LogName - name of the disk_log. If 'dummy' is +%% used nothing should be logged. Reason, reuse code. +%% LogRecord - record to store in the log. +%% Returns : +%% Effect : Writes a logrecord and synchronizes to make sure +%% that the record is stored. +%%------------------------------------------------------------ + +log_safe(dummy, _) -> + ok; +log_safe(LogName, LogRecord) -> + case write_safe(LogName, LogRecord) of + ok -> + ok; + _ -> + %% We have to catch the exit because in some cases + %% it's not possible to abort action in the 2PC-protocol. + case catch start(LogName) of + ok -> + write_safe(LogName, LogRecord); + {'EXIT', Reason} -> + {error, Reason} + end + end. + + +write_safe(LogName, LogRecord) -> + case catch disk_log:log(LogName, LogRecord) of + ok -> % wrote to kernel successfully + case catch disk_log:sync(LogName) of + ok -> % Written to disk successfully + ok; + {error, Reason} -> + ?tr_error_msg("Internal log write failed: ~p ~p", + [Reason, LogName]), + {error, Reason}; + Other -> + ?tr_error_msg("Internal log write failed: ~p ~p", + [Other, LogName]), + {error, Other} + end; + {error, Reason} -> + ?tr_error_msg("Internal log write failed: ~p ~p", [Reason, LogName]), + {error, Reason}; + Other -> + ?tr_error_msg("Internal log write failed: ~p ~p", [Other, LogName]), + {error, Other} + end. + + +%%------------------------------------------------------------ +%% function : log_lazy +%% Arguments: LogName - name of the disk_log. If 'dummy' is +%% used nothing should be logged. Reason, reuse code. +%% LogRecord - record to store in the log. +%% Returns : +%% Effect : Writes a logrecord. The record may be lost. +%%------------------------------------------------------------ + +log_lazy(dummy, _LogRecord) -> + ok; +log_lazy(LogName, LogRecord) -> + case write_lazy(LogName, LogRecord) of + ok -> + ok; + _ -> + %% We have to catch the exit because in some cases + %% it's not possible to abort action in the 2PC-protocol. + case catch start(LogName) of + ok -> + write_lazy(LogName, LogRecord); + {'EXIT', Reason} -> + {error, Reason} + end + end. + +write_lazy(LogName, LogRecord) -> + case catch disk_log:log(LogName, LogRecord) of + ok -> + %% wrote to kernel successfully + ok; + {error, Reason} -> + %% Write to kernel failed with Reason + ?tr_error_msg("Internal log write failed: ~p", [Reason]), + {error, Reason}; + Other -> + %% unknown message received. + ?tr_error_msg("Internal log write failed: ~p", [Other]), + {error, Other} + end. + + +%%------------------------------------------------------------ +%% function : get_next +%% Arguments: LogName - name of the disk_log. +%% Cursor - place to read from. +%% Returns : {Cursor, LogRecs} - A cursor and up to N logrecords. +%% eof - the atom 'eof', indicating logfile empty. +%% {error, Reason} - error. +%% Effect : +%% Purpose : Used when performing a REDO scan +%%------------------------------------------------------------ + +get_next(LogName, Cursor) -> + case catch disk_log:chunk(LogName, Cursor, 1) of + {NewCursor, [Data]} -> + {Data, NewCursor}; + eof -> + eof; + {error, Reason} -> + ?tr_error_msg("Internal log '~p' read failed: ~p", + [LogName, Reason]), + exit({error, Reason}); + _Other -> + ?tr_error_msg("Internal log '~p' read failed: 'log_corrupt'", [LogName]), + exit({error, "log_corrupt"}) + end. + +%%--------------- END OF MODULE ------------------------------ diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk new file mode 100644 index 0000000000..404a9ed7af --- /dev/null +++ b/lib/cosTransactions/vsn.mk @@ -0,0 +1,9 @@ +COSTRANSACTIONS_VSN = 1.2.8 + +TICKETS = OTP-8201 + +TICKETS_1.2.7 = OTP-7987 + +TICKETS_1.2.6 = OTP-7837 + +TICKETS_1.2.5 = OTP-7595 -- cgit v1.2.3