diff options
Diffstat (limited to 'lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl')
-rw-r--r-- | lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl new file mode 100644 index 0000000000..f37a97c4a7 --- /dev/null +++ b/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl @@ -0,0 +1,721 @@ +%%-------------------------------------------------------------------- +%% +%% %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 : CosNotifyChannelAdmin_EventChannel_impl.erl +%% Purpose : +%% Created : 28 Sep 1999 +%%------------------------------------------------------------------- + +-module('CosNotifyChannelAdmin_EventChannel_impl'). + +%%--------------- INCLUDES ----------------------------------- +-include_lib("orber/include/corba.hrl"). +-include_lib("orber/include/ifr_types.hrl"). +%% Application files +-include("CosNotification.hrl"). +-include("CosNotifyChannelAdmin.hrl"). +-include("CosNotifyComm.hrl"). +-include("CosNotifyFilter.hrl"). +-include("CosNotification_Definitions.hrl"). + +%%--------------- EXPORTS ------------------------------------ +%%--------------- External ----------------------------------- +%%----- CosNotifyChannelAdmin::EventChannel ------------------ +-export([new_for_consumers/4, + new_for_suppliers/4, + get_consumeradmin/4, + get_supplieradmin/4, + get_all_consumeradmins/3, + get_all_supplieradmins/3]). + +%% Attributes (external) +-export(['_get_MyFactory'/3, + '_get_default_consumer_admin'/3, + '_get_default_supplier_admin'/3, + '_get_default_filter_factory'/3]). + +%%----- Inherit from CosNotification::QoSAdmin --------------- +-export([get_qos/3, + set_qos/4, + validate_qos/4]). + +%%----- Inherit from CosNotification::AdminPropertiesAdmin --- +-export([get_admin/3, + set_admin/4]). + +%%----- Inherit from CosEventChannelAdmin::EventChannel ------ +-export([for_consumers/3, + for_suppliers/3, + destroy/3]). +%%--------------- Internal ----------------------------------- +%%----- Inherit from cosNotificationComm --------------------- +-export([callAny/5, + callSeq/5]). + +%%--------------- gen_server specific exports ---------------- +-export([handle_info/2, code_change/3]). +-export([init/1, terminate/2]). + +%% Data structures +-record(state, {myFac, + myConsumers = [], + defConsumerAdmin, + defSupplierAdmin, + defConsumerAdminPid, + defSupplierAdminPid, + defFilterFac, + defFilterFacPid, + etsR, + qosLocal, + qosGlobal, + admGlobal, + options, + idCounter = 0, + 'MaxQueueLength', + 'MaxConsumers', + 'MaxSuppliers'}). +%% Data structures constructors +-define(get_InitState(My, Fil, FilPid, QoS, LQoS, GA, MQ, MC, MS, O), + #state{myFac = My, + defFilterFac = Fil, + defFilterFacPid = FilPid, + etsR = ets:new(oe_ets, [set, protected]), + qosLocal = LQoS, + qosGlobal = QoS, + admGlobal = GA, + options = O, + 'MaxQueueLength' = MQ, + 'MaxConsumers' = MC, + 'MaxSuppliers' = MS}). + +%% NOTE!!! +%% When forwarding events, the objects we will contact is ONLY ConsumerAdmins!! +%% Hence, we will store SupplierAdmins and ConsumerAdmins differently. SupplierAdmins +%% we store in our ets-table while the ConsumerAdmins will be stored on the local +%% State. + +%% Data structures selectors +-define(get_supplierAdmins(S), [S#state.defSupplierAdmin| + lists:flatten(ets:match(S#state.etsR, + {'_','$1','_'}))]). +-define(get_consumerAdmins(S), [{0, S#state.defConsumerAdmin,S#state.defConsumerAdminPid} + |S#state.myConsumers]). +-define(get_allAdmins(S), [S#state.defSupplierAdmin, + S#state.defConsumerAdmin| + lists:flatten(ets:match(S#state.etsR, + {'_','$1','_'}))++ + find_field(S#state.myConsumers, 2)]). +-define(get_consumerAdmIDs(S), [0|find_field(S#state.myConsumers, 1)]). +-define(get_supplierAdmIDs(S), [0|lists:flatten(ets:match(S#state.etsR, + {'$1','_','_'}))]). + +-define(get_supplierAdmin(S, I), find_obj(ets:lookup(S#state.etsR, I))). +-define(get_consumerAdmin(S, I), find_obj(lists:keysearch(I,1,S#state.myConsumers))). +-define(get_supplierAmount(S), ets:info(S#state.etsR, size)). +-define(get_consumerAmount(S), length(S#state.myConsumers)). + +-define(get_MyFactory(S), S#state.myFac). +-define(get_defConsumerAdm(S), S#state.defConsumerAdmin). +-define(get_defSupplierAdm(S), S#state.defSupplierAdmin). +-define(get_defConsumerAdmPid(S), S#state.defConsumerAdminPid). +-define(get_defSupplierAdmPid(S), S#state.defSupplierAdminPid). +-define(get_defFilterFac(S), S#state.defFilterFac). +-define(get_defFilterFacPid(S), S#state.defFilterFacPid). +-define(get_GlobalQoS(S), S#state.qosGlobal). +-define(get_LocalQoS(S), S#state.qosLocal). +-define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}). +-define(get_GlobalAdm(S), S#state.admGlobal). +-define(get_Options(S), S#state.options). +-define(get_MaxQueueLength(S), S#state.'MaxQueueLength'). +-define(get_MaxConsumers(S), S#state.'MaxConsumers'). +-define(get_MaxSuppliers(S), S#state.'MaxSuppliers'). +-define(get_IdCounter(S), S#state.idCounter). + +%% Data structures modifiers +-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}). +-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}). +-define(set_GlobalAdm(S,D), S#state{admGlobal=D}). +-define(set_AllAdminP(S,GD, MQ, MC, MS), + S#state{admGlobal=GD,'MaxQueueLength'=MQ, + 'MaxConsumers'=MC, 'MaxSuppliers'=MS}). +-define(set_MaxQueueLength(S,D), S#state{'MaxQueueLength'=D}). +-define(set_MaxConsumers(S,D), S#state{'MaxConsumers'=D}). +-define(set_MaxSuppliers(S,D), S#state{'MaxSuppliers'=D}). +-define(set_defConsumerAdm(S,D,P), S#state{defConsumerAdmin=D, defConsumerAdminPid=P}). +-define(set_defSupplierAdm(S,D,P), S#state{defSupplierAdmin=D, defSupplierAdminPid=P}). +-define(set_defFilterFac(S,D,P), S#state{defFilterFac=D, defFilterFacPid=P}). +-define(add_supplierAdmin(S,I,O,P), ets:insert(S#state.etsR, {I,O,P})). +-define(add_consumerAdmin(S,I,O,P), S#state{myConsumers= [{I,O,P}|S#state.myConsumers]}). +-define(del_supplierAdmin(S,I), ets:delete(S#state.etsR, I)). +-define(del_consumerAdmin(S,I), S#state{myConsumers= + lists:keydelete(I, 1, + S#state.myConsumers)}). +-define(del_consumerAdminRef(S,O), S#state{myConsumers= + lists:keydelete(O, 2, + S#state.myConsumers)}). +-define(del_AdminPid(S,P), delete_obj(S, P)). +-define(set_IdCounter(S,V), S#state{idCounter=V}). +-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)). +%% MISC +-define(is_UndefDefConsAdm(S), S#state.defConsumerAdmin == undefined). +-define(is_UndefDefSuppAdm(S), S#state.defSupplierAdmin == undefined). +-define(is_UndefDefFilterFac(S), S#state.defFilterFac == undefined). +-define(is_PersistentConnection(S), + ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent). +-define(is_PersistentEvent(S), + ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent). + +%%-----------------------------------------------------------% +%% function : handle_info, code_change +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the gen_server module. +%%------------------------------------------------------------ + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +handle_info(Info, State) -> + ?DBG("INFO: ~p~n", [Info]), + case Info of + {'EXIT', Pid, _Reason} when ?get_defConsumerAdmPid(State) == Pid -> + {noreply, ?set_defConsumerAdm(State, undefined, undefined)}; + {'EXIT', Pid, _Reason} when ?get_defSupplierAdmPid(State) == Pid -> + {noreply, ?set_defSupplierAdm(State, undefined, undefined)}; + {'EXIT', Pid, _Reason} when ?get_defFilterFacPid(State) == Pid -> + {noreply, ?set_defFilterFac(State, undefined, undefined)}; + {'EXIT', Pid, normal} -> + {noreply, ?del_AdminPid(State, Pid)}; + _Other -> + ?DBG("TERMINATED: ~p~n",[_Other]), + {noreply, State} + end. + +%%----------------------------------------------------------% +%% function : init, terminate +%% Arguments: +%%----------------------------------------------------------- + +init([MyFac, InitQoS, InitAdmin, LocalQoS, [MaxQ, MaxC, MaxS|_], Options]) -> + process_flag(trap_exit, true), + SO = 'CosNotification_Common':get_option(server_options, Options, + ?not_DEFAULT_SETTINGS), + + ?DBG("CHANNEL INIT STATE:~n~p~n~p~n~p ~p ~p ~p~n~p~n", + [InitQoS, InitAdmin, LocalQoS,MaxQ, MaxC, MaxS, Options]), + + %% Both default Admin:s have the unique id 0 (OMG spec, 98-11-01, + %% Notification p 148), hence, no need to create a unique id. + %% We don't have acces to OE_THIS in this stage so we cannot create the objects + %% now, even though the specification states that. + %% DefConAdm = 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([0],[]), + %% DefSupAdm = 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([0],[]), + + case 'CosNotifyFilter_FilterFactory':oe_create_link([], [{sup_child, true}|SO]) of + {ok, Pid, DefFiFac} -> + {ok, ?get_InitState(MyFac, DefFiFac, Pid, InitQoS, LocalQoS, + InitAdmin, MaxQ, MaxC, MaxS, Options)}; + Reason -> + {stop, Reason} + end. + +terminate(_Reason, _State) -> + ok. + +%%----------------------------------------------------------- +%%----- CosNotifyChannelAdmin_EventChannel attributes ------- +%%----------------------------------------------------------- +%%----------------------------------------------------------% +%% Attribute: '_get_MyFactory' +%% Type : readonly +%% Returns : +%%----------------------------------------------------------- +'_get_MyFactory'(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_MyFactory(State), State}. + +%%----------------------------------------------------------% +%% Attribute: '_get_default_consumer_admin' +%% Type : readonly +%% Returns : +%%----------------------------------------------------------- +'_get_default_consumer_admin'(OE_THIS, _OE_FROM, State) + when ?is_UndefDefConsAdm(State) -> + Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([0, OE_THIS, + self(), Op, + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, DefConAdm} -> + {reply, DefConAdm, ?set_defConsumerAdm(State, DefConAdm, Pid)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:_get_default_consumer_admin();~n" + "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +'_get_default_consumer_admin'(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_defConsumerAdm(State), State}. + +%%----------------------------------------------------------% +%% Attribute: '_get_default_supplier_admin' +%% Type : readonly +%% Returns : +%%----------------------------------------------------------- +'_get_default_supplier_admin'(OE_THIS, _OE_FROM, State) + when ?is_UndefDefSuppAdm(State) -> + Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([0, OE_THIS, + self(), Op, + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, DefSupAdm} -> + {reply, DefSupAdm, ?set_defSupplierAdm(State, DefSupAdm, Pid)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:_get_default_supplier_admin();~n" + "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +'_get_default_supplier_admin'(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_defSupplierAdm(State), State}. + +%%----------------------------------------------------------% +%% Attribute: '_get_default_filter_factory' +%% Type : readonly +%% Returns : +%%---------------------------------------------------------- +'_get_default_filter_factory'(_OE_THIS, _OE_FROM, State) + when ?is_UndefDefFilterFac(State) -> + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyFilter_FilterFactory':oe_create_link([], [{sup_child, true}|SO]) of + {ok, Pid, DefFiFac} -> + {reply, DefFiFac, ?set_defFilterFac(State, DefFiFac, Pid)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:_get_default_filter_factory();~n" + "Unable to create: CosNotifyChannelAdmin_FilterFactory.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +'_get_default_filter_factory'(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_defFilterFac(State), State}. + +%%----------------------------------------------------------- +%%------- Exported external functions ----------------------- +%%----------------------------------------------------------- +%%----------------------------------------------------------% +%% function : new_for_consumers +%% Arguments: Op - InterFilterGroupOperator: 'AND_OP' | 'OR_OP' +%% Determines if the Admin:s proxy-children will +%% use AND or OR when checking Filters. +%% Returns : ConsAdm +%% AdminId (out) +%%----------------------------------------------------------- +new_for_consumers(OE_THIS, _OE_FROM, State, Op) -> + is_admin_limit_reached(?get_MaxConsumers(State), ?get_consumerAmount(State)), + AdminId = ?new_Id(State), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([AdminId, OE_THIS, + self(), Op, + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, AdminCo} -> + %% Due to different storage, adding a new consumer is NOT done in the + %% same way as for suppliers. + NewState = ?add_consumerAdmin(State, AdminId, AdminCo, Pid), + {reply, {AdminCo, AdminId}, ?set_IdCounter(NewState, AdminId)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:nef_for_consumers();~n" + "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +%%----------------------------------------------------------% +%% function : new_for_suppliers +%% Arguments: Op - InterFilterGroupOperator: 'AND_OP' | 'OR_OP' +%% Determines if the Admin:s proxy-children will +%% use AND or OR when checking Filters. +%% Returns : SuppAdm +%% AdminId (out) +%%----------------------------------------------------------- +new_for_suppliers(OE_THIS, _OE_FROM, State, Op) -> + is_admin_limit_reached(?get_MaxSuppliers(State), ?get_supplierAmount(State)), + AdminId = ?new_Id(State), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([AdminId, OE_THIS, + self(), Op, + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, AdminSu} -> + %% Due to different storage, adding a new supplier is NOT done in the + %% same way as for consumers. + ?add_supplierAdmin(State, AdminId, AdminSu, Pid), + {reply, {AdminSu, AdminId}, ?set_IdCounter(State, AdminId)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:new_for_suppliers();~n" + "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +%%----------------------------------------------------------% +%% function : get_consumeradmin +%% Arguments: AdminId +%% Returns : ConsAdmin +%%----------------------------------------------------------- +get_consumeradmin(OE_THIS, _OE_FROM, State, 0) when ?is_UndefDefConsAdm(State) -> + Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([0, OE_THIS, + self(), Op, + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, DefConAdm} -> + {reply, DefConAdm, ?set_defConsumerAdm(State, DefConAdm, Pid)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_consumer_admin();~n" + "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +get_consumeradmin(_OE_THIS, _OE_FROM, State, 0) -> + {reply, ?get_defConsumerAdm(State), State}; +get_consumeradmin(_OE_THIS, _OE_FROM, State, AdminId) when is_integer(AdminId) -> + {reply, ?get_consumerAdmin(State, AdminId), State}; +get_consumeradmin(_, _, _, What) -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_consumeradmin(~p);~n" + "Not an integer", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}). + +%%----------------------------------------------------------% +%% function : get_supplieradmin +%% Arguments: AdminId +%% Returns : +%%----------------------------------------------------------- +get_supplieradmin(OE_THIS, _OE_FROM, State, 0) when ?is_UndefDefSuppAdm(State) -> + Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([0, OE_THIS, + self(), Op, + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, DefSupAdm} -> + {reply, DefSupAdm, ?set_defSupplierAdm(State, DefSupAdm, Pid)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_supplieradmin();~n" + "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +get_supplieradmin(_OE_THIS, _OE_FROM, State, 0) -> + {reply, ?get_defSupplierAdm(State), State}; +get_supplieradmin(_OE_THIS, _OE_FROM, State, AdminId) when is_integer(AdminId) -> + {reply, ?get_supplierAdmin(State, AdminId), State}; +get_supplieradmin(_, _, _, What) -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_supplieradmin(~p);~n" + "Not an integer", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}). + +%%----------------------------------------------------------% +%% function : get_all_consumeradmins +%% Arguments: - +%% Returns : AdminIDSeq - a list of all unique ID:s. +%%----------------------------------------------------------- +get_all_consumeradmins(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_consumerAdmIDs(State), State}. + +%%----------------------------------------------------------% +%% function : get_all_supplieradmins +%% Arguments: - +%% Returns : AdminIDSeq - a list of all unique ID:s. +%%----------------------------------------------------------- +get_all_supplieradmins(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_supplierAdmIDs(State), State}. + + +%%----- Inherit from CosNotification::QoSAdmin -------------- +%%----------------------------------------------------------% +%% function : get_qos +%% Arguments: - +%% Returns : CosNotification::QoSProperties +%% [#'Property'{name, value}, ...] where name eq. string() +%% and value eq. any(). +%%----------------------------------------------------------- +get_qos(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_GlobalQoS(State), State}. + +%%----------------------------------------------------------% +%% function : set_qos +%% Arguments: QoS - CosNotification::QoSProperties, i.e., +%% [#'Property'{name, value}, ...] where name eq. string() +%% and value eq. any(). +%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS} +%%----------------------------------------------------------- +set_qos(_OE_THIS, _OE_FROM, State, QoS) -> + {GQoS,LQoS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State), + channel, false, + ?get_allAdmins(State)), + {reply, ok, ?set_BothQoS(State, GQoS,LQoS)}. + +%%----------------------------------------------------------% +%% function : validate_qos +%% Arguments: Required_qos - CosNotification::QoSProperties +%% [#'Property'{name, value}, ...] where name eq. string() +%% and value eq. any(). +%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS} | +%% {ok, CosNotification::NamedPropertyRangeSeq} +%%----------------------------------------------------------- +validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) -> + QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State), + channel, false, + ?get_allAdmins(State)), + {reply, {ok, QoS}, State}. + +%%----- Inherit from CosNotification::AdminPropertiesAdmin -- +%%-----------------------------------------------------------% +%% function : get_admin +%% Arguments: - +%% Returns : AdminProperties +%%----------------------------------------------------------- +get_admin(_OE_THIS, _OE_FROM, State) -> + {reply, ?get_GlobalAdm(State), State}. + +%%----------------------------------------------------------% +%% function : set_admin +%% Arguments: Admin +%% Returns : +%%----------------------------------------------------------- +set_admin(_OE_THIS, _OE_FROM, State, Admin) -> + {GAdm,[MaxQ, MaxC, MaxS|_]} = + 'CosNotification_Common':set_adm(Admin, ?get_GlobalAdm(State)), + {reply, ok, ?set_AllAdminP(State, GAdm, MaxQ, MaxC, MaxS)}. + +%%----- Inherit from CosEventChannelAdmin::EventChannel ----- +%%----------------------------------------------------------% +%% function : for_consumers +%% Arguments: - +%% Returns : ConsAdm +%%----------------------------------------------------------- +for_consumers(OE_THIS, _OE_FROM, State) -> + is_admin_limit_reached(?get_MaxConsumers(State), ?get_consumerAmount(State)), + AdminId = ?new_Id(State), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([AdminId, OE_THIS, + self(), 'AND_OP', + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, AdminCo} -> + %% Due to different storage, adding a new consumer is NOT done in the + %% same way as for suppliers. + NewState = ?add_consumerAdmin(State, AdminId, AdminCo, Pid), + {reply, AdminCo, ?set_IdCounter(NewState, AdminId)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:for_consumers();~n" + "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +%%----------------------------------------------------------% +%% function : for_suppliers +%% Arguments: - +%% Returns : SuppAdm +%%----------------------------------------------------------- +for_suppliers(OE_THIS, _OE_FROM, State) -> + is_admin_limit_reached(?get_MaxSuppliers(State), ?get_supplierAmount(State)), + AdminId = ?new_Id(State), + SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State), + ?not_DEFAULT_SETTINGS), + case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([AdminId, OE_THIS, + self(), 'AND_OP', + ?get_GlobalQoS(State), + ?get_LocalQoS(State), + ?get_Options(State)], + [{sup_child, true}|SO]) of + {ok, Pid, AdminSu} -> + %% Due to different storage, adding a new supplier is NOT done in the + %% same way as for consumers. + ?add_supplierAdmin(State, AdminId, AdminSu, Pid), + {reply, AdminSu, ?set_IdCounter(State, AdminId)}; + What -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:for_suppliers();~n" + "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n" + "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end. + +%%-----------------------------------------------------------% +%% function : destroy +%% Arguments: - +%% Returns : ok +%%------------------------------------------------------------ +destroy(_OE_THIS, _OE_FROM, State) -> + {stop, normal, ok, State}. + +%%--------------- LOCAL FUNCTIONS ---------------------------- +find_obj([]) -> {'EXCEPTION', #'CosNotifyChannelAdmin_AdminNotFound'{}}; +find_obj([{_, Obj,_}]) -> Obj; +find_obj({value, {_, Obj,_}}) -> Obj; +find_obj(_) -> {'EXCEPTION', #'CosNotifyChannelAdmin_AdminNotFound'{}}. + + +find_field(List, Field) -> + find_field(List, Field, []). + +find_field([], _, Acc) -> + Acc; +find_field([{I,_,_}|T], 1, Acc) -> + find_field(T, 1, [I|Acc]); +find_field([{_,O,_}|T], 2, Acc) -> + find_field(T, 2, [O|Acc]); +% Left out for now to avoid dialyzer warning. +%find_field([{_,_,P}|T], 3, Acc) -> +% find_field(T, 3, [P|Acc]); +find_field(What, _, _) -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:find_field();~n" + "Data corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL), + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}). + +delete_obj(State, Pid) -> + case ets:match_object(State#state.etsR, {'_', '_', Pid}) of + [] -> + State#state{myConsumers=lists:keydelete(Pid, 3, State#state.myConsumers)}; + [{Id,_Obj,Pid}] -> + ets:delete(State#state.etsR, Id), + State + end. + +%% Test if we have reached limit for Admin objects. +is_admin_limit_reached(0, _) -> + %% When set to zero it means that there is no limit. + ok; +is_admin_limit_reached(Max, Current) when Current >= Max -> + %% The Current value do not include the default Admin objects, hence + %% we use >= instead of >. + corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO}); +is_admin_limit_reached(_, _) -> + ok. + +%%----------------------------------------------------------- +%% function : callSeq +%% Arguments: +%% Returns : +%%----------------------------------------------------------- +callSeq(_OE_THIS, OE_FROM, State, Event, Status) -> + corba:reply(OE_FROM, ok), + forward(seq, State, Event, Status). + +%%----------------------------------------------------------- +%% function : callAny +%% Arguments: +%% Returns : +%%----------------------------------------------------------- +callAny(_OE_THIS, OE_FROM, State, Event, Status) -> + corba:reply(OE_FROM, ok), + forward(any, State, Event, Status). + +%% Forward events +forward(Type, State, Event, Status) -> + forward(Type, ?get_consumerAdmins(State), State, Event, Status). + +forward(_, [], State, _, _) -> + {noreply, State}; +forward(Type, [{_,undefined,_}|T], State, Event, Status) -> + %% Match if no default objects associated. + forward(Type, T, State, Event, Status); +forward(any, [{_,H,_}|T], State, Event, Status) -> + case catch oe_CosNotificationComm_Event:callAny(H, Event, Status) of + ok -> + ?DBG("CHANNEL FORWARD ANY: ~p~n",[Event]), + forward(any, T, State, Event, Status); + {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n" + "Admin no longer exists; dropping it: ~p", + [?LINE, H], ?DEBUG_LEVEL), + NewState = ?del_consumerAdminRef(State,H), + forward(any, T, NewState, Event, Status); + R when ?is_PersistentConnection(State) -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n" + "Admin behaves badly: ~p/~p", + [?LINE, R, H], ?DEBUG_LEVEL), + forward(any, T, State, Event, Status); + R -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n" + "Admin behaves badly: ~p~n" + "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL), + NewState = ?del_consumerAdminRef(State, H), + forward(any, T, NewState, Event, Status) + end; +forward(seq, [{_,H,_}|T], State, Event, Status) -> + case catch oe_CosNotificationComm_Event:callSeq(H, Event, Status) of + ok -> + ?DBG("CHANNEL FORWARD SEQUENCE: ~p~n",[Event]), + forward(seq, T, State, Event, Status); + {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n" + "Admin no longer exists; dropping it: ~p", + [?LINE, H], ?DEBUG_LEVEL), + NewState = ?del_consumerAdminRef(State,H), + forward(seq, T, NewState, Event, Status); + R when ?is_PersistentConnection(State) -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n" + "Admin behaves badly: ~p/~p", + [?LINE, R, H], ?DEBUG_LEVEL), + forward(seq, T, State, Event, Status); + R -> + orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n" + "Admin behaves badly: ~p~n" + "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL), + NewState = ?del_consumerAdminRef(State,H), + forward(seq, T, NewState, Event, Status) + end. + + +%%--------------- MISC FUNCTIONS, E.G. DEBUGGING ------------- +%%--------------- END OF MODULE ------------------------------ |