etrap_server_impl.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,740 行 · 第 1/5 页
ERL
1,740 行
%%-----------------------------------------------------------%%% 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"}; _ ->
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?