aboutsummaryrefslogtreecommitdiffstats
path: root/lib/cosNotification/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cosNotification/src')
-rw-r--r--lib/cosNotification/src/CosEvent.cfg20
-rw-r--r--lib/cosNotification/src/CosNotification.cfg0
-rw-r--r--lib/cosNotification/src/CosNotification.idl146
-rw-r--r--lib/cosNotification/src/CosNotification_Common.erl1210
-rw-r--r--lib/cosNotification/src/CosNotification_Definitions.hrl340
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin.cfg60
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin.idl275
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl670
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl142
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl721
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl579
-rw-r--r--lib/cosNotification/src/CosNotifyComm.cfg0
-rw-r--r--lib/cosNotification/src/CosNotifyComm.idl83
-rw-r--r--lib/cosNotification/src/CosNotifyFilter.cfg6
-rw-r--r--lib/cosNotification/src/CosNotifyFilter.idl140
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl125
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl670
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl578
-rw-r--r--lib/cosNotification/src/CosTypedEvent.idl57
-rw-r--r--lib/cosNotification/src/CosTypedNotification.idl109
-rw-r--r--lib/cosNotification/src/Makefile369
-rw-r--r--lib/cosNotification/src/PullerConsumer_impl.erl773
-rw-r--r--lib/cosNotification/src/PullerSupplier_impl.erl914
-rw-r--r--lib/cosNotification/src/PusherConsumer_impl.erl729
-rw-r--r--lib/cosNotification/src/PusherSupplier_impl.erl1052
-rw-r--r--lib/cosNotification/src/cosNotification.app.src120
-rw-r--r--lib/cosNotification/src/cosNotification.appup.src7
-rw-r--r--lib/cosNotification/src/cosNotificationApp.erl447
-rw-r--r--lib/cosNotification/src/cosNotificationAppComm.idl17
-rw-r--r--lib/cosNotification/src/cosNotificationComm.cfg3
-rw-r--r--lib/cosNotification/src/cosNotification_Filter.erl964
-rw-r--r--lib/cosNotification/src/cosNotification_Grammar.yrl166
-rw-r--r--lib/cosNotification/src/cosNotification_Scanner.erl268
-rw-r--r--lib/cosNotification/src/cosNotification_eventDB.erl1350
34 files changed, 13110 insertions, 0 deletions
diff --git a/lib/cosNotification/src/CosEvent.cfg b/lib/cosNotification/src/CosEvent.cfg
new file mode 100644
index 0000000000..e3399139a4
--- /dev/null
+++ b/lib/cosNotification/src/CosEvent.cfg
@@ -0,0 +1,20 @@
+{this, "CosEventChannelAdmin::EventChannel"}.
+{{handle_info, "CosEventChannelAdmin::EventChannel"}, true}.
+{this, "CosEventChannelAdmin::EventChannelFactory"}.
+{{handle_info, "CosEventChannelAdmin::EventChannelFactory"}, true}.
+{this, "CosEventChannelAdmin::SupplierAdmin"}.
+{{handle_info, "CosEventChannelAdmin::SupplierAdmin"}, true}.
+{this, "CosEventChannelAdmin::ConsumerAdmin"}.
+{{handle_info, "CosEventChannelAdmin::ConsumerAdmin"}, true}.
+{this, "CosEventChannelAdmin::ProxyPushSupplier"}.
+{{handle_info, "CosEventChannelAdmin::ProxyPushSupplier"}, true}.
+{{impl, "CosEventChannelAdmin::ProxyPushSupplier"}, "PusherSupplier_impl"}.
+{this, "CosEventChannelAdmin::ProxyPullSupplier"}.
+{{handle_info, "CosEventChannelAdmin::ProxyPullSupplier"}, true}.
+{{impl, "CosEventChannelAdmin::ProxyPullSupplier"}, "PullerSupplier_impl"}.
+{this, "CosEventChannelAdmin::ProxyPushConsumer"}.
+{{handle_info, "CosEventChannelAdmin::ProxyPushConsumer"}, true}.
+{{impl, "CosEventChannelAdmin::ProxyPushConsumer"}, "PusherConsumer_impl"}.
+{this, "CosEventChannelAdmin::ProxyPullConsumer"}.
+{{handle_info, "CosEventChannelAdmin::ProxyPullConsumer"}, true}.
+{{impl, "CosEventChannelAdmin::ProxyPullConsumer"}, "PullerConsumer_impl"}.
diff --git a/lib/cosNotification/src/CosNotification.cfg b/lib/cosNotification/src/CosNotification.cfg
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/cosNotification/src/CosNotification.cfg
diff --git a/lib/cosNotification/src/CosNotification.idl b/lib/cosNotification/src/CosNotification.idl
new file mode 100644
index 0000000000..e080b44b0c
--- /dev/null
+++ b/lib/cosNotification/src/CosNotification.idl
@@ -0,0 +1,146 @@
+#ifndef _COS_NOTIFICATION_IDL_
+#define _COS_NOTIFICATION_IDL_
+
+#pragma prefix "omg.org"
+
+#include"CosEventChannelAdmin.idl"
+#include"CosEventComm.idl"
+
+module CosNotification {
+ typedef string Istring;
+ typedef Istring PropertyName;
+ typedef any PropertyValue;
+ struct Property {
+ PropertyName name;
+ PropertyValue value;
+ };
+ typedef sequence<Property> PropertySeq;
+ // The following are the same, but serve different purposes.
+ typedef PropertySeq OptionalHeaderFields;
+ typedef PropertySeq FilterableEventBody;
+ typedef PropertySeq QoSProperties;
+ typedef PropertySeq AdminProperties;
+ struct EventType {
+ string domain_name;
+ string type_name;
+ };
+ typedef sequence<EventType> EventTypeSeq;
+ struct PropertyRange {
+ PropertyValue low_val;
+ PropertyValue high_val;
+ };
+ struct NamedPropertyRange {
+ PropertyName name;
+ PropertyRange range;
+ };
+
+ typedef sequence<NamedPropertyRange> NamedPropertyRangeSeq;
+
+ enum QoSError_code {
+ UNSUPPORTED_PROPERTY,
+ UNAVAILABLE_PROPERTY,
+ UNSUPPORTED_VALUE,
+ UNAVAILABLE_VALUE,
+ BAD_PROPERTY,
+ BAD_TYPE,
+ BAD_VALUE
+ };
+
+ struct PropertyError {
+ QoSError_code code;
+ PropertyName name;
+ PropertyRange available_range;
+ };
+
+ typedef sequence<PropertyError> PropertyErrorSeq;
+ exception UnsupportedQoS { PropertyErrorSeq qos_err; };
+ exception UnsupportedAdmin { PropertyErrorSeq admin_err; };
+
+ // Define the Structured Event structure
+ struct FixedEventHeader {
+ EventType event_type;
+ string event_name;
+ };
+ struct EventHeader {
+ FixedEventHeader fixed_header;
+ OptionalHeaderFields variable_header;
+ };
+
+ struct StructuredEvent {
+ EventHeader header;
+ FilterableEventBody filterable_data;
+ any remainder_of_body;
+ }; // StructuredEvent
+
+ typedef sequence<StructuredEvent> EventBatch;
+
+ // The following constant declarations define the standard
+ // QoS property names and the associated values each property
+ // can take on. The name/value pairs for each standard property
+ // are grouped, beginning with a string constant defined for the
+ // property name, followed by the values the property can take on.
+ const string EventReliability = "EventReliability";
+ const short BestEffort = 0;
+ const short Persistent = 1;
+ const string ConnectionReliability = "ConnectionReliability";
+
+ // Can take on the same values as EventReliability
+ const string Priority = "Priority";
+ const short LowestPriority = -32767;
+ const short HighestPriority = 32767;
+ const short DefaultPriority = 0;
+ const string StartTime = "StartTime";
+
+ // StartTime takes a value of type TimeBase::UtcT.
+ const string StopTime = "StopTime";
+ // StopTime takes a value of type TimeBase::UtcT.
+ const string Timeout = "Timeout";
+ // Timeout takes on a value of type TimeBase::TimeT
+ const string OrderPolicy = "OrderPolicy";
+ const short AnyOrder = 0;
+ const short FifoOrder = 1;
+ const short PriorityOrder = 2;
+ const short DeadlineOrder = 3;
+ const string DiscardPolicy = "DiscardPolicy";
+ // DiscardPolicy takes on the same values as OrderPolicy, plus
+ const short LifoOrder = 4;
+ const short RejectNewEvents = 5;
+ const string MaximumBatchSize = "MaximumBatchSize";
+ // MaximumBatchSize takes on a value of type long
+ const string PacingInterval = "PacingInterval";
+ // PacingInterval takes on a value of type TimeBase::TimeT
+ const string StartTimeSupported = "StartTimeSupported";
+ // StartTimeSupported takes on a boolean value
+ const string StopTimeSupported = "StopTimeSupported";
+ // StopTimeSupported takes on a boolean value
+ const string MaxEventsPerConsumer = "MaxEventsPerConsumer";
+ // MaxEventsPerConsumer takes on a value of type long
+
+ interface QoSAdmin {
+ QoSProperties get_qos();
+ void set_qos ( in QoSProperties qos)
+ raises ( UnsupportedQoS );
+ void validate_qos (in QoSProperties required_qos,
+ out NamedPropertyRangeSeq available_qos )
+ raises ( UnsupportedQoS );
+ }; // QosAdmin
+
+ // Admin properties are defined in similar manner as QoS
+ // properties. The only difference is that these properties
+ // are related to channel administration policies, as opposed
+ // message quality of service
+ const string MaxQueueLength = "MaxQueueLength";
+ // MaxQueueLength takes on a value of type long
+ const string MaxConsumers = "MaxConsumers";
+ // MaxConsumers takes on a value of type long
+ const string MaxSuppliers = "MaxSuppliers";
+ // MaxSuppliers takes on a value of type long
+ interface AdminPropertiesAdmin {
+ AdminProperties get_admin();
+ void set_admin (in AdminProperties admin)
+ raises ( UnsupportedAdmin);
+ };// AdminPropertiesAdmin
+}; // CosNotification
+
+#endif /* ifndef _COS_NOTIFICATION_IDL_ */
+
diff --git a/lib/cosNotification/src/CosNotification_Common.erl b/lib/cosNotification/src/CosNotification_Common.erl
new file mode 100644
index 0000000000..0e0f1da0d5
--- /dev/null
+++ b/lib/cosNotification/src/CosNotification_Common.erl
@@ -0,0 +1,1210 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : CosNotification_Common.erl
+%% Purpose :
+%%--------------------------------------------------------------------
+
+-module('CosNotification_Common').
+
+
+%%--------------- 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 MISC
+-export([get_option/3,
+ create_name/2,
+ create_name/1,
+ create_id/0,
+ create_id/1,
+ is_debug_compiled/0,
+ type_check/2,
+ send_stubborn/5,
+ create_link/3,
+ disconnect/3,
+ do_disconnect/3,
+ notify/1]).
+
+%% Internal AdminProperties
+-export([init_adm/1,
+ set_adm/2,
+ 'MaxQueueLength'/6,
+ 'MaxConsumers'/6,
+ 'MaxSuppliers'/6]).
+%% Internal QoS
+-export([init_qos/1,
+ set_qos/5,
+ validate_qos/5,
+ validate_event_qos/2,
+ 'EventReliability'/6,
+ 'ConnectionReliability'/6,
+ 'Priority'/6,
+ 'StartTimeSupported'/6,
+ 'StopTimeSupported'/6,
+ 'Timeout'/6,
+ 'OrderPolicy'/6,
+ 'DiscardPolicy'/6,
+ 'MaximumBatchSize'/6,
+ 'PacingInterval'/6,
+ 'MaxEventsPerConsumer'/6]).
+
+%%--------------- DEFINITIONS OF CONSTANTS -------------------
+%%--------------- EXTERNAL MISC FUNCTIONS --------------------
+%%------------------------------------------------------------
+%% 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 : create_id/0
+%% Arguments: -
+%% Returns : id (long) =/= 0
+%% Both default Admin:s have the unique id 0 (OMG spec, 98-11-01,
+%% Notification p 148), hence, we may not return 0.
+%% Exception:
+%% Purpose : Throughout the CosNotification service we use,
+%% according to the OMG specification, id:s (long),
+%% which must be "unique", to retrieve object references.
+%% For example: CosNotifyChannelAdmin::ChannelId/AdminID.
+%%------------------------------------------------------------
+create_id(-1) ->
+ 1;
+create_id( 2147483647) ->
+ -2147483648;
+create_id(OldID) ->
+ OldID+1.
+
+create_id() ->
+ {_A,_B,C}=now(),
+ C.
+
+%%-----------------------------------------------------------%
+%% function : type_check
+%% Arguments: Obj - objectrefernce to test.
+%% Mod - Module which contains typeID/0.
+%% Returns : 'ok' or raises exception.
+%% Effect :
+%%------------------------------------------------------------
+type_check(Obj, Mod) ->
+ case cosNotificationApp:type_check() of
+ false ->
+ ok;
+ _ ->
+ case catch corba_object:is_a(Obj,Mod:typeID()) of
+ true ->
+ ok;
+ false ->
+ orber:dbg("[~p] CosNotification_Common:type_check(~p);~n"
+ "The supplied Object is not or does not inherrit from: ~p",
+ [?LINE, Obj, Mod], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
+ {'EXCEPTION', E} ->
+ orber:dbg("[~p] CosNotification_Common:type_check(~p, ~p);~n"
+ "Failed due to: ~p",
+ [?LINE, Obj, Mod, E], ?DEBUG_LEVEL),
+ corba:raise(E);
+ What ->
+ orber:dbg("[~p] CosNotification_Common:type_check(~p, ~p);~n"
+ "Failed due to: ~p",
+ [?LINE, Obj, Mod, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end
+ end.
+
+
+%%-----------------------------------------------------------%
+%% function : notify
+%% Arguments: Items - [Item]
+%% Item - {proxy, IOR} | {client, IOR} | {reason, term()}
+%% Returns : 'ok' or raises exception.
+%% Effect :
+%%------------------------------------------------------------
+notify(Items) ->
+ case cosNotificationApp:notify() of
+ false ->
+ ok;
+ Module ->
+ catch Module:terminated(Items),
+ ok
+ 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 repeatidly untill 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) ->
+ orber:dbg("[~p] CosNotification_Common:send_stubborn( ~p ~p ~p ~p).~n"
+ "Failed to deliver the event.~n", [?LINE, M,F,A,MaxR], ?DEBUG_LEVEL),
+ 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);
+ {'EXIT', _} ->
+ NewTimes = Times +1,
+ timer:sleep(Wait),
+ send_stubborn(M, F, A, MaxR, Wait, NewTimes);
+ Other ->
+ Other
+ end.
+
+
+%%-----------------------------------------------------------%
+%% function : disconnect
+%% Arguments: Module - one of the interfaces defined in CosEventComm.
+%% Function - the appropriate disconnect function.
+%% Object - the client object reference.
+%% Returns : ok
+%% Exception:
+%% Effect : If the process would try to diconnect itself it could
+%% result in a deadlock. Hence, we spawn a new process to do it.
+%%------------------------------------------------------------
+disconnect(Module, Function, Object) ->
+ spawn(?MODULE, do_disconnect, [Module, Function, Object]),
+ ok.
+
+do_disconnect(Module, Function, Object) ->
+ catch Module:Function(Object),
+ ?DBG("Disconnect ~p:~p(..).~n", [Module, Function]),
+ ok.
+
+
+
+%%------------------------------------------------------------
+%% function : is_debug_compiled
+%% Arguments:
+%% Returns :
+%% Exception:
+%% Effect :
+%%------------------------------------------------------------
+
+-ifdef(debug).
+ is_debug_compiled() -> true.
+-else.
+ is_debug_compiled() -> false.
+-endif.
+
+
+%%------------------------------------------------------------
+%%--------------- AdminPropertiesAdmin -----------------------
+%%------------------------------------------------------------
+%%------------------------------------------------------------
+%% function : init_adm
+%% Arguments: Wanted - requested Admins to be set.
+%% Returns : #'CosNotification_UnsupportedAdmin'{} |
+%% {NewAdmProperties, [MaxQ, MaxC, MaxS]}
+%% Effect : may only be used when creating a channel!!!!!!!!
+%%------------------------------------------------------------
+init_adm(Wanted) ->
+ {NewA,_} = set_properties(Wanted, ?not_DEFAULT_ADMINPROPERTIES, channelAdm,
+ ?not_SUPPORTED_ADMINPROPERTIES, [], [],
+ false, false, false),
+ {NewA, [extract_value(NewA, ?not_MaxQueueLength),
+ extract_value(NewA, ?not_MaxConsumers),
+ extract_value(NewA, ?not_MaxSuppliers)]}.
+
+set_adm(Wanted, Current) ->
+ {NewA,_} = set_properties(Wanted, Current, channelAdm,
+ ?not_SUPPORTED_ADMINPROPERTIES,
+ [], [], false, false, false),
+ {NewA, [extract_value(NewA, ?not_MaxQueueLength),
+ extract_value(NewA, ?not_MaxConsumers),
+ extract_value(NewA, ?not_MaxSuppliers)]}.
+
+'MaxQueueLength'(Req,channelAdm,_, _, _, _) -> admin_ok(Req).
+'MaxConsumers'(Req,channelAdm,_, _, _, _)-> admin_ok(Req).
+'MaxSuppliers'(Req,channelAdm,_, _, _, _)-> admin_ok(Req).
+
+admin_ok(Req) ->
+ case any:get_value(Req#'CosNotification_Property'.value) of
+ Val when is_integer(Val) andalso Val >= 0 ->
+ {ok, Req};
+ _ ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+
+%%------------------------------------------------------------
+%%--------------- QOS FUNCTIONS ------------------------------
+%%------------------------------------------------------------
+%%------------------------------------------------------------
+%% function : init_qos
+%% Arguments: Wanted - requested QoS to be set.
+%% Returns : see set_properties/9
+%% Effect : may only be used when creating a channel!!!!!!!!
+%%------------------------------------------------------------
+init_qos(Wanted) ->
+ LQS = set_local_qos(?not_DEFAULT_QOS, ?not_CreateInitQoS()),
+ set_properties(Wanted, ?not_DEFAULT_QOS, channel, ?not_SUPPORTED_QOS,
+ [], [], false, [], LQS).
+
+%%------------------------------------------------------------
+%% function : set_qos/5
+%% Arguments: Wanted - requested QoS to be set.
+%% Current - current QoS OMG style
+%% LQS - local representation of QoS.
+%% Type - channel | admin | proxy
+%% Parent - Factory if Channel, Channel if Admin etc
+%% Childs - Admins if Channel etc
+%% Returns : see set_properties/9
+%%------------------------------------------------------------
+set_qos(Wanted, {Current, LQS}, proxy, Parent, _) ->
+ set_properties(Wanted, Current, proxy, ?not_SUPPORTED_QOS, [], [], Parent, false,LQS);
+set_qos(Wanted, {Current, LQS}, admin, Parent, Childs) ->
+ set_properties(Wanted, Current, admin, ?not_SUPPORTED_QOS, [], [], Parent, Childs,LQS);
+set_qos(Wanted, {Current, LQS}, channel, _, Childs) ->
+ set_properties(Wanted, Current, channel, ?not_SUPPORTED_QOS, [], [], false, Childs,LQS).
+
+%%------------------------------------------------------------
+%% function :
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns : ok - if requested equal to current value.
+%% {ok, Req, LQS} - if new and allowed QoS
+%% {unsupported,#'CosNotification_PropertyError'{}} otherwise.
+%% Effect :
+%%------------------------------------------------------------
+'EventReliability'(Req,channel, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
+ {Val, Val, _, _} ->
+ %% Is the value requested.
+ ok;
+ {Val, _, Val, _} ->
+ {ok, Req, LQS};
+ {Val, _, _, Val} ->
+ {ok, Req, LQS};
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end;
+'EventReliability'(Req,_,_,_,_,_) ->
+ %% only valid to set this QoS for channels (or per-event).
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'UNAVAILABLE_PROPERTY',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }.
+
+%%------------------------------------------------------------
+%% function : 'ConnectionReliability'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Exception:
+%% Effect :
+%%------------------------------------------------------------
+%% The most complex QoS to set is ConnectionReliability, and the reason for this
+%% is that we cannot set the Channel to offer best effort while its children
+%% offer persistent. A child may only offer Persistent if its parent do, which
+%% is why we must check the following:
+%%
+%% # Persistent Change to Best Effort
+%% _____
+%% | | (1) -> Check if children BE
+%% |Chann| (2) ok <-
+%% -----
+%% |
+%% _____
+%% | | (3) -> Check if children BE
+%% |Admin| (4) Check if parent Pers. <-
+%% -----
+%% |
+%% _____
+%% | | (5) -> ok
+%% |Proxy| (6) Check if parent Pers. <-
+%% -----
+%% NOTE: a parent always exists but we may change the QoS before creating any
+%% childrens. The cases (2) and (5) is always ok, i.e., no need to confirm
+%% with parent or children.
+%%------------------------------------------------------------
+'ConnectionReliability'(Req, channel, _Curr, _Parent, Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
+ {Val, Val, _, _} ->
+ %% Is the value requested.
+ ok;
+ {Val, P, Val, P} ->
+ %% Requested is BestEffort, Current Persistent => (1)
+ check_with_relatives(Childs, Req, LQS);
+ {Val, B, B, Val} ->
+ %% Requested is Persistent, Current BestEffort => (2)
+ {ok, Req, LQS};
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end;
+'ConnectionReliability'(Req, admin, _Curr, Parent, Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
+ {Val, Val, _, _} ->
+ %% Is the value requested.
+ ok;
+ {Val, P, Val, P} ->
+ %% Requested is BestEffort, Current Persistent => (3)
+ check_with_relatives(Childs, Req, LQS);
+ {Val, B, B, Val} ->
+ %% Requested is Persistent, Current BestEffort => (4)
+ check_with_relatives([Parent], Req, LQS);
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end;
+'ConnectionReliability'(Req, proxy, _Curr, Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
+ {Val, Val, _, _} ->
+ %% Is the value requested.
+ ok;
+ {Val, P, Val, P} ->
+ %% Requested is BestEffort, Current Persistent => (5)
+ {ok, Req, LQS};
+ {Val, B, B, Val} ->
+ %% Requested is Persistent, Current BestEffort => (6)
+ check_with_relatives([Parent], Req, LQS);
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : 'Priority'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'Priority'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetPriority(LQS), ?not_HighestPriority, ?not_LowestPriority} of
+ {Val, Val, _, _} ->
+ ok;
+ {Val, _, H, L} when Val =< H, Val >= L ->
+ {ok, Req, LQS};
+ {_, _, H, L} ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), L),
+ high_val=any:create(orber_tc:short(), H)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : 'StartTimeSupported'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'StartTimeSupported'(Req, _Type, _Curr, _, _, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetStartTimeSupported(LQS)} of
+ {Val, Val} ->
+ ok;
+ {Val, _} when Val =/= true, Val =/= false ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:boolean(), false),
+ high_val=any:create(orber_tc:boolean(), true)
+ }
+ }
+ };
+ _->
+ {ok, Req, LQS}
+ end.
+
+%%------------------------------------------------------------
+%% function : 'StopTimeSupported'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'StopTimeSupported'(Req, _Type, _Curr, _, _, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetStopTimeSupported(LQS)} of
+ {Val, Val} ->
+ ok;
+ {Val, _} when Val =/= true, Val =/= false ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:boolean(), false),
+ high_val=any:create(orber_tc:boolean(), true)
+ }
+ }
+ };
+ _->
+ {ok, Req, LQS}
+ end.
+
+%%------------------------------------------------------------
+%% function : 'Timeout'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'Timeout'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetTimeout(LQS)} of
+ {Val, Val} ->
+ ok;
+ {Val, _} when Val >= ?not_MinTimeout, Val =< ?not_MaxTimeout ->
+ {ok, Req, LQS};
+ {Val, _} when is_integer(Val) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinTimeout),
+ high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxTimeout)
+ }
+ }
+ };
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : 'OrderPolicy'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'OrderPolicy'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetOrderPolicy(LQS), 'CosNotification':'AnyOrder'(),
+ 'CosNotification':'PriorityOrder'()} of
+ {Val, Val,_,_} ->
+ ok;
+ {Val, _, L, H} when Val >= L, Val =< H ->
+ {ok, Req, LQS};
+ {Val, _, L, H} when is_integer(Val) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), L),
+ high_val=any:create(orber_tc:short(), H)
+ }
+ }
+ };
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+
+%%------------------------------------------------------------
+%% function : 'DiscardPolicy'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'DiscardPolicy'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetDiscardPolicy(LQS), ?not_AnyOrder, ?not_PriorityOrder} of
+ {Val, Val,_,_} ->
+ ok;
+ {Val, _, L, H} when Val >= L, Val =< H ->
+ {ok, Req, LQS};
+ {Val, _, L, H} when is_integer(Val) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), L),
+ high_val=any:create(orber_tc:short(), H)
+ }
+ }
+ };
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : 'DiscardPolicy'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'MaximumBatchSize'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetMaximumBatchSize(LQS)} of
+ {Val, Val} ->
+ ok;
+ {Val, _} when Val >= ?not_MinBatchSize, Val =< ?not_MaxBatchSize ->
+ {ok, Req, LQS};
+ {Val, _} when is_integer(Val) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinBatchSize),
+ high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxBatchSize)
+ }
+ }
+ };
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'UNSUPPORTED_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:long(), ?not_MinBatchSize),
+ high_val=any:create(orber_tc:long(), ?not_MaxBatchSize)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : 'PacingInterval'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Comment : PacingInterval is defined to be:
+%% * TimeBase::UtcT (p 57, 2.5.5, OMG TC Document telecom/98-11-01)
+%% * TimeBase::TimeT (p 189, appendix B, OMG TC Document telecom/98-11-01)
+%% This implementation use TimeBase::TimeT, especially since
+%% TimeBase::UtcT contains information which are of no importance.
+%% When writing this, the OMG homepage contained no information
+%% regarding this.
+%%------------------------------------------------------------
+'PacingInterval'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetPacingInterval(LQS)} of
+ {Val, Val} ->
+ ok;
+ {Val, _} when Val >= ?not_MinPacing, Val =< ?not_MaxPacing ->
+ {ok, Req, LQS};
+ {Val, _} when is_integer(Val) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinPacing),
+ high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxPacing)
+ }
+ }
+ };
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_TYPE',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : 'MaxEventsPerConsumer'/6
+%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
+%% Type - Requestee, channel | admin | proxy
+%% Curr - Current QoS, #'CosNotification_Property'{}
+%% Parent - false | ObjRef
+%% Childs - false | [ObjRef1, .., ObjRefN]
+%% LQS - #qos{} defined in CosNotification_Definitions.hrl
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+'MaxEventsPerConsumer'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
+ case {any:get_value(Req#'CosNotification_Property'.value),
+ ?not_GetMaxEventsPerConsumer(LQS)} of
+ {Val, Val} ->
+ ok;
+ {Val, _} when is_integer(Val) andalso
+ Val >= ?not_MinConsumerEvents andalso
+ Val =< ?not_MaxConsumerEvents ->
+ {ok, Req, LQS};
+ {Val, _} when is_integer(Val) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinConsumerEvents),
+ high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxConsumerEvents)
+ }
+ }
+ };
+ _->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'UNSUPPORTED_VALUE',
+ name = Req#'CosNotification_Property'.name,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:long(), ?not_MinConsumerEvents),
+ high_val=any:create(orber_tc:long(), ?not_MaxConsumerEvents)
+ }
+ }
+ }
+ end.
+
+%%------------------------------------------------------------
+%% function : validate_qos/5
+%% Arguments: Wanted - requested QoS to be set.
+%% Curr - current QoS OMG style and LQS, local
+%% representation of QoS, grouped as {OMGQ, LQS}
+%% Type - channel | admin | proxy
+%% Parent - Factory if Channel, Channel if Admin etc
+%% Childs - Admins if Channel etc
+%% Returns : NamedPropertySeq | #'CosNotification_UnsupportedQoS'{}
+%% case 1 if all supported, case 2 if at least 1 QoS not
+%% supported.
+%% See also p59, 2.5.6.4, OMG TC Document telecom/98-11-01. Quote:
+%% "If the supplied QoS is supported, it returns additional QoS
+%% properties which could be optionally added as well."
+%%------------------------------------------------------------
+validate_qos(Wanted, Curr, Type, Parent, Childs) ->
+ %% If not supported this function will raise an exception, which we should
+ %% not catch, but all we need to is to raise the exception as it is.
+ {_, LQS}=set_qos(Wanted, Curr, Type, Parent, Childs),
+ NewNPR = check_limits(LQS, ?not_QOS_LIMITS),
+ remove_qos(Wanted, LQS, NewNPR).
+
+remove_qos([], _, NPR) ->
+ NPR;
+remove_qos([H|T], LQS, NPR) ->
+ NewNPR=remove(NPR, H#'CosNotification_Property'.name),
+ remove_qos(T, LQS, NewNPR).
+
+check_limits(LQS, NPR) ->
+ case {?not_GetEventReliability(LQS), ?not_GetConnectionReliability(LQS),
+ ?not_Persistent, ?not_BestEffort} of
+ {P,P,P,_B} ->
+ New = #'CosNotification_NamedPropertyRange'
+ {name=?not_EventReliability,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_BestEffort),
+ high_val=any:create(orber_tc:short(), ?not_BestEffort)
+ }},
+ NewNPR=change(NPR, ?not_EventReliability, New),
+ remove(NewNPR, ?not_ConnectionReliability);
+ {_,B,_P,B} ->
+ remove(NPR, ?not_EventReliability);
+ {B,P,P,B} ->
+ New = #'CosNotification_NamedPropertyRange'
+ {name=?not_ConnectionReliability,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_BestEffort),
+ high_val=any:create(orber_tc:short(), ?not_BestEffort)
+ }},
+ change(NPR, ?not_ConnectionReliability, New)
+ end.
+
+%%------------------------------------------------------------
+%% function : validate_event_qos/2
+%% Arguments: Wanted - requested QoS to be set.
+%% Curr - LQS, local representation of QoS
+%% Returns : NamedPropertySeq | #'CosNotification_UnsupportedQoS'{}
+%% case 1 if all supported, case 2 if at least 1 QoS not
+%% supported.
+%%------------------------------------------------------------
+validate_event_qos(Wanted, Curr) ->
+ v_e_q_helper(Wanted, Curr, []),
+ [].
+v_e_q_helper([], _Curr, []) ->
+ %% Parsed all and foynd no conflicts.
+ ok;
+v_e_q_helper([], _Curr, Unsupp) ->
+ %% Not possible to use these requested QoS.
+ corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Unsupp});
+
+%%--- EventReliability ---%%
+v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability,
+ value=#any{value=?not_BestEffort}}|T], Curr, Unsupp) ->
+ %% Always ok.
+ v_e_q_helper(T, Curr, Unsupp);
+v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability,
+ value=#any{value=?not_Persistent}}|T], Curr, Unsupp)
+ when ?not_GetConnectionReliability(Curr) =/= ?not_BestEffort,
+ ?not_GetEventReliability(Curr) =/= ?not_BestEffort,
+ ?not_GetStopTimeSupported(Curr) =/= true ->
+ v_e_q_helper(T, Curr, Unsupp);
+v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability}|T],
+ Curr, Unsupp) ->
+ %% Impossible to set to Persistent if the connection reliability is best effort.
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'UNAVAILABLE_VALUE', name = ?not_EventReliability,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)}}|Unsupp]);
+
+%%--- Priority ---%%
+v_e_q_helper([#'CosNotification_Property'{name=?not_Priority, value=#any{value=V}}|T], Curr,
+ Unsupp) ->
+ if
+ ?not_GetOrderPolicy(Curr) =/= ?not_AnyOrder,
+ ?not_GetOrderPolicy(Curr) =/= ?not_Priority,
+ ?not_GetDiscardPolicy(Curr) =/= ?not_Priority ->
+ %% No use setting Priority since it's not currently used.
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'UNAVAILABLE_VALUE', name = ?not_Priority,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }}|Unsupp]);
+ V =< ?not_HighestPriority, V >= ?not_LowestPriority ->
+ v_e_q_helper(T, Curr, Unsupp);
+ true ->
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'BAD_VALUE', name = ?not_Priority,
+ available_range =
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(),
+ ?not_LowestPriority),
+ high_val=any:create(orber_tc:short(),
+ ?not_HighestPriority)}}|Unsupp])
+ end;
+
+%%--- StartTime ---%%
+v_e_q_helper([#'CosNotification_Property'{name=?not_StartTime}|T], Curr, Unsupp)
+ when ?not_GetStartTimeSupported(Curr) =/= false,
+ ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
+ v_e_q_helper(T, Curr, Unsupp);
+v_e_q_helper([#'CosNotification_Property'{name=?not_StartTime}|T], Curr, Unsupp) ->
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'UNAVAILABLE_VALUE', name = ?not_StartTime,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }}|Unsupp]);
+
+%%--- StopTime ---%%
+v_e_q_helper([#'CosNotification_Property'{name=?not_StopTime}|T], Curr, Unsupp)
+ when ?not_GetStopTimeSupported(Curr) =/= false,
+ ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
+ v_e_q_helper(T, Curr, Unsupp);
+v_e_q_helper([#'CosNotification_Property'{name=?not_StopTime}|T], Curr, Unsupp) ->
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'UNAVAILABLE_VALUE', name = ?not_StopTime,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }}|Unsupp]);
+
+%%--- Timeout ---%%
+v_e_q_helper([#'CosNotification_Property'{name=?not_Timeout}|T], Curr, Unsupp)
+ when ?not_GetStopTimeSupported(Curr) =/= false,
+ ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
+ v_e_q_helper(T, Curr, Unsupp);
+v_e_q_helper([#'CosNotification_Property'{name=?not_Timeout}|T], Curr, Unsupp) ->
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'UNAVAILABLE_VALUE', name = ?not_Timeout,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }}|Unsupp]);
+
+%%--- Unknown Event QoS ---%%
+v_e_q_helper([#'CosNotification_Property'{name=Name}|T], Curr, Unsupp) ->
+ %% Unsupported property.
+ v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
+ {code = 'BAD_PROPERTY', name = Name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }}|Unsupp]);
+v_e_q_helper(What, _, _) ->
+ %% Not a Property struct.
+ orber:dbg("[~p] CosNotification_Common:v_e_q_helper(~p);~n"
+ "Not a CosNotification_Property struct.",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%-------------- QOS HELP FUNCTIONS --------------------------
+%%------------------------------------------------------------
+%% function : set_properties/9
+%% Arguments: Wanted - requested QoS to be set.
+%% Current - current QoS OMG style
+%% Type - channel | admin | proxy
+%% Supported - List of supported QoS
+%% Unsupp - acc
+%% NewQoS - acc
+%% Parent - Factory if Channel, Channel if Admin etc
+%% Childs - Admins if Channel etc
+%% LQS - local representation of QoS.
+%% Returns : {NewOMGStyleQoS, NewLocalQoS} | #'CosNotification_UnsupportedQoS'{}
+%%------------------------------------------------------------
+set_properties([], Curr, channelAdm, _, [], NewQoS,_,_,LAS) ->
+ merge_properties(NewQoS, Curr, LAS);
+set_properties([], Curr, _, _, [], NewQoS,_,_,LQS) ->
+ %% set_local_qos and merge_properties are help functions found at the end of QoS
+ %% functions.
+ NewLQS = set_local_qos(NewQoS, LQS),
+ merge_properties(NewQoS, Curr, NewLQS);
+set_properties([], _, channelAdm, _, Unsupp, _,_,_,_) ->
+ corba:raise(#'CosNotification_UnsupportedAdmin'{admin_err = Unsupp});
+set_properties([], _, _, _, Unsupp, _,_,_,_) ->
+ corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Unsupp});
+
+set_properties([Req|Tail], Curr, Type, Supported, Unsupp, NewQoS, Parent, Childs,LQS) ->
+ %% set_values and is_supported are help functions found at the end of QoS
+ %% functions.
+ case set_values(is_supported(Supported, Req), Req, Type, Curr, Parent, Childs,LQS) of
+ {unsupported, U} ->
+ set_properties(Tail, Curr, Type, Supported, [U|Unsupp], NewQoS, Parent, Childs,LQS);
+ {ok, S, NewLQS} ->
+ set_properties(Tail, Curr, Type, Supported, Unsupp, [S|NewQoS], Parent, Childs,NewLQS);
+ {ok, S} ->
+ set_properties(Tail, Curr, Type, Supported, Unsupp, [S|NewQoS], Parent, Childs,LQS);
+ ok ->
+ set_properties(Tail, Curr, Type, Supported, Unsupp, NewQoS, Parent, Childs,LQS)
+ end.
+
+
+set_values(unsupported,Req,_,_,_,_,_) ->
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'BAD_PROPERTY',
+ name = Req#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ };
+set_values({ok, Func}, Req, Type, Curr, Parent, Childs, LQS) ->
+ ?MODULE:Func(Req, Type, Curr, Parent, Childs, LQS).
+
+%% Update OMG style QoS list with new values.
+merge_properties([], NewCurrQoS, LQS) ->
+ {NewCurrQoS, LQS};
+merge_properties([H|T], Curr, LQS) ->
+ merge_properties(T, lists:keyreplace(H#'CosNotification_Property'.name, %% get key.
+ #'CosNotification_Property'.name, %% get index.
+ Curr, H), LQS).
+
+%% Is the Property S among our supported QoS?
+is_supported([], _) ->
+ unsupported;
+is_supported([{Name, Func}|_], #'CosNotification_Property'{name=Name}) ->
+ {ok, Func};
+is_supported([_|T], S) ->
+ is_supported(T, S).
+
+%% Find matching S-Property from a list of OMG style QoS
+extract([], _) -> unsupported;
+extract([H|_T], S) when H#'CosNotification_Property'.name==
+ S#'CosNotification_Property'.name ->
+ {ok, H};
+extract([_|T], S) -> extract(T,S).
+
+%% Find matching Property name from a list of OMG style QoS
+extract_value([], _) -> unsupported;
+extract_value([H|_T], Key) when H#'CosNotification_Property'.name== Key ->
+ {ok, any:get_value(H#'CosNotification_Property'.value)};
+extract_value([_|T], Key) -> extract(T,Key).
+
+%% Remove matching S-QoS from a list of OMG style QoS
+remove(List, Key) ->
+ lists:keydelete(Key,
+ #'CosNotification_NamedPropertyRange'.name, %% get index.
+ List).
+
+change(List, Key, New) ->
+ lists:keyreplace(Key,
+ #'CosNotification_NamedPropertyRange'.name, %% get index.
+ List, New).
+%% Get QoS from supplied objects and check if it's the same as S.
+check_with_relatives([], S, LQS) ->
+ {ok, S, LQS};
+check_with_relatives([undefined|T], S, LQS) ->
+ check_with_relatives(T, S, LQS);
+check_with_relatives([H|T], S, LQS) ->
+ case catch extract('CosNotification_QoSAdmin':get_qos(H), S) of
+ {ok, S} ->
+ check_with_relatives(T, S, LQS);
+ _->
+ %% Varioues reasons for this case (Object not responding, not supported)
+ {unsupported,
+ #'CosNotification_PropertyError'{
+ code = 'UNAVAILABLE_PROPERTY',
+ name = S#'CosNotification_Property'.name,
+ available_range = #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:null(), null),
+ high_val=any:create(orber_tc:null(), null)
+ }
+ }
+ }
+ end.
+
+%% Set new values to locally defined representation of QoS. Using this approach is
+%% necessary since we must state the record-field at compile-time.
+set_local_qos([], LQS) -> LQS;
+set_local_qos([#'CosNotification_Property'{name=N,value=V}|T], LQS) ->
+ NewLQS =
+ case N of
+ "EventReliability" ->
+ ?not_SetEventReliability(LQS, any:get_value(V));
+ "ConnectionReliability" ->
+ ?not_SetConnectionReliability(LQS, any:get_value(V));
+ "Priority" ->
+ ?not_SetPriority(LQS, any:get_value(V));
+ "Timeout" ->
+ ?not_SetTimeout(LQS, any:get_value(V));
+ "OrderPolicy" ->
+ ?not_SetOrderPolicy(LQS, any:get_value(V));
+ "DiscardPolicy" ->
+ ?not_SetDiscardPolicy(LQS, any:get_value(V));
+ "MaximumBatchSize" ->
+ ?not_SetMaximumBatchSize(LQS, any:get_value(V));
+ "PacingInterval" ->
+ ?not_SetPacingInterval(LQS, any:get_value(V));
+ "StartTimeSupported" ->
+ ?not_SetStartTimeSupported(LQS, any:get_value(V));
+ "StopTimeSupported" ->
+ ?not_SetStopTimeSupported(LQS, any:get_value(V));
+ "MaxEventsPerConsumer" ->
+ ?not_SetMaxEventsPerConsumer(LQS, any:get_value(V))
+ end,
+ set_local_qos(T, NewLQS).
+
+%%%%%%%%%%%%%%%%% END QOS FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotification_Definitions.hrl b/lib/cosNotification/src/CosNotification_Definitions.hrl
new file mode 100644
index 0000000000..755b07cd5d
--- /dev/null
+++ b/lib/cosNotification/src/CosNotification_Definitions.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 : CosNotification_Definitions.hrl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-ifndef(COSNOTIFICATION_DEFINITIONS_HRL).
+-define(COSNOTIFICATION_DEFINITIONS_HRL, true).
+
+%% ---------------- General comment ------------------------------------
+%% ******* README ********
+%% The prefix 'not' is short for notification, and is used to separate locally
+%% defined macros from the global ones, i.e., do NOT confuse this with a negation!!
+%%
+%% In this file you find globally used data structures, constants etc.
+%%
+
+%%--------------- INCLUDES ---------------------------------------------
+
+%%-------- Constants -------------------------------------------------
+-define(not_SupportedGrammars, ["EXTENDED_TCL"]).
+
+%% !!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+%%
+%% If OMG redefines the values for the constants the definitions
+%% below must be redefined!!
+%%
+%% !!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+-define(not_BestEffort, 0).
+-define(not_Persistent, 1).
+-define(not_EventReliability, "EventReliability").
+-define(not_ConnectionReliability, "ConnectionReliability").
+-define(not_Priority, "Priority").
+-define(not_LowestPriority, -32767).
+-define(not_HighestPriority, 32767).
+-define(not_DefaultPriority, 0).
+-define(not_StartTime, "StartTime").
+-define(not_StopTime, "StopTime").
+-define(not_Timeout, "Timeout").
+-define(not_OrderPolicy, "OrderPolicy").
+-define(not_AnyOrder, 0).
+-define(not_FifoOrder, 1).
+-define(not_PriorityOrder, 2).
+-define(not_DeadlineOrder, 3).
+-define(not_DiscardPolicy, "DiscardPolicy").
+-define(not_LifoOrder, 4).
+-define(not_RejectNewEvents, 5).
+-define(not_MaximumBatchSize, "MaximumBatchSize").
+-define(not_PacingInterval, "PacingInterval").
+-define(not_StartTimeSupported, "StartTimeSupported").
+-define(not_StopTimeSupported, "StopTimeSupported").
+-define(not_MaxEventsPerConsumer, "MaxEventsPerConsumer").
+-define(not_MaxQueueLength, "MaxQueueLength").
+-define(not_MaxConsumers, "MaxConsumers").
+-define(not_MaxSuppliers, "MaxSuppliers").
+
+%%--------------- QOS DEFINITIONS ----------------------------
+%% Limits for QoS. These are our own limits.
+-define(not_MaxBatchSize, 10000).
+-define(not_MinBatchSize, 1).
+-define(not_MinTimeout, 0).
+-define(not_MaxTimeout, 100000000000).
+-define(not_MinPacing, 0).
+-define(not_MaxPacing, 100000000000).
+-define(not_MinConsumerEvents, 1).
+-define(not_MaxConsumerEvents, 10000).
+
+-define(not_QOS_LIMITS,
+[#'CosNotification_NamedPropertyRange'
+ {name=?not_EventReliability,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_BestEffort),
+ high_val=any:create(orber_tc:short(), ?not_Persistent)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_ConnectionReliability,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_BestEffort),
+ high_val=any:create(orber_tc:short(), ?not_Persistent)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_Priority,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_LowestPriority),
+ high_val=any:create(orber_tc:short(), ?not_HighestPriority)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_StartTimeSupported,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:boolean(), false),
+ high_val=any:create(orber_tc:boolean(), true)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_StopTimeSupported,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:boolean(), false),
+ high_val=any:create(orber_tc:boolean(), true)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_Timeout,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinTimeout),
+ high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxTimeout)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_OrderPolicy,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_AnyOrder),
+ high_val=any:create(orber_tc:short(), ?not_PriorityOrder)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_DiscardPolicy,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:short(), ?not_AnyOrder),
+ high_val=any:create(orber_tc:short(), ?not_PriorityOrder)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_MaximumBatchSize,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:long(), ?not_MinBatchSize),
+ high_val=any:create(orber_tc:long(), ?not_MaxBatchSize)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_PacingInterval,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinPacing),
+ high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxPacing)
+ }},
+ #'CosNotification_NamedPropertyRange'
+ {name=?not_MaxEventsPerConsumer,
+ range=
+ #'CosNotification_PropertyRange'{
+ low_val=any:create(orber_tc:long(), ?not_MinConsumerEvents),
+ high_val=any:create(orber_tc:long(), ?not_MaxConsumerEvents)
+ }}
+].
+
+
+
+%% Local record used internally, and the reason for this is we get faster
+%% access to QoS settings.
+-record(qos, {'EventReliability',
+ 'ConnectionReliability',
+ 'Priority',
+ 'StartTimeSupported',
+ 'StopTimeSupported',
+ 'Timeout',
+ 'OrderPolicy',
+ 'DiscardPolicy',
+ 'MaximumBatchSize',
+ 'PacingInterval',
+ 'MaxEventsPerConsumer'}).
+
+%% Global (OMG) representation of QoS.
+-define(not_DEFAULT_QOS,
+[#'CosNotification_Property'{name=?not_MaximumBatchSize,
+ value=any:create(orber_tc:long(), 1)},
+ #'CosNotification_Property'{name=?not_PacingInterval,
+ value=any:create(orber_tc:unsigned_long_long(), 0)},
+ #'CosNotification_Property'{name=?not_Timeout,
+ value=any:create(orber_tc:unsigned_long_long(), 0)},
+ #'CosNotification_Property'{name=?not_MaxEventsPerConsumer,
+ value=any:create(orber_tc:long(), 100)},
+ #'CosNotification_Property'{name=?not_OrderPolicy,
+ value=any:create(orber_tc:short(),
+ ?not_PriorityOrder)},
+ #'CosNotification_Property'{name=?not_EventReliability,
+ value=any:create(orber_tc:short(),
+ ?not_BestEffort)},
+ #'CosNotification_Property'{name=?not_ConnectionReliability,
+ value=any:create(orber_tc:short(),
+ ?not_BestEffort)},
+ #'CosNotification_Property'{name=?not_DiscardPolicy,
+ value=any:create(orber_tc:short(),
+ ?not_RejectNewEvents)},
+ #'CosNotification_Property'{name=?not_StartTimeSupported,
+ value=any:create(orber_tc:boolean(), false)},
+ #'CosNotification_Property'{name=?not_StopTimeSupported,
+ value=any:create(orber_tc:boolean(), false)},
+ #'CosNotification_Property'{name=?not_Priority,
+ value=any:create(orber_tc:short(), ?not_DefaultPriority)}]).
+
+%%--------------- QOS CREATORS -------------------------------
+-define(not_CreateInitQoS(), #qos{}).
+
+%%--------------- QOS DESTRUCTORS ----------------------------
+-define(not_DestroyQoS(Q), ok).
+
+%%--------------- QOS SELECTORS ------------------------------
+-define(not_GetEventReliability(Q), Q#qos.'EventReliability').
+-define(not_GetConnectionReliability(Q), Q#qos.'ConnectionReliability').
+-define(not_GetPriority(Q), Q#qos.'Priority').
+-define(not_GetStartTimeSupported(Q), Q#qos.'StartTimeSupported').
+-define(not_GetStopTimeSupported(Q), Q#qos.'StopTimeSupported').
+-define(not_GetTimeout(Q), Q#qos.'Timeout').
+-define(not_GetOrderPolicy(Q), Q#qos.'OrderPolicy').
+-define(not_GetDiscardPolicy(Q), Q#qos.'DiscardPolicy').
+-define(not_GetMaximumBatchSize(Q), Q#qos.'MaximumBatchSize').
+-define(not_GetPacingInterval(Q), Q#qos.'PacingInterval').
+-define(not_GetMaxEventsPerConsumer(Q), Q#qos.'MaxEventsPerConsumer').
+
+%%--------------- QOS MODIFIERS ------------------------------
+-define(not_SetEventReliability(Q,D), Q#qos{'EventReliability'=D}).
+-define(not_SetConnectionReliability(Q,D), Q#qos{'ConnectionReliability'=D}).
+-define(not_SetPriority(Q,D), Q#qos{'Priority'=D}).
+-define(not_SetStartTimeSupported(Q,D), Q#qos{'StartTimeSupported'=D}).
+-define(not_SetStopTimeSupported(Q,D), Q#qos{'StopTimeSupported'=D}).
+-define(not_SetTimeout(Q,D), Q#qos{'Timeout'=D}).
+-define(not_SetOrderPolicy(Q,D), Q#qos{'OrderPolicy'=D}).
+-define(not_SetDiscardPolicy(Q,D), Q#qos{'DiscardPolicy'=D}).
+-define(not_SetMaximumBatchSize(Q,D), Q#qos{'MaximumBatchSize'=D}).
+-define(not_SetPacingInterval(Q,D), Q#qos{'PacingInterval'=D}).
+-define(not_SetMaxEventsPerConsumer(Q,D), Q#qos{'MaxEventsPerConsumer'=D}).
+
+%%--------------- StructuredEvent CREATORS -------------------
+-define(not_CreateSE(StrD,StrT,StrE,PSeqV,PSeqF,AnyR),
+#'CosNotification_StructuredEvent'{header =
+ #'CosNotification_EventHeader'{fixed_header =
+ #'CosNotification_FixedEventHeader'{event_type =
+ #'CosNotification_EventType'{domain_name=StrD,
+ type_name=StrT},
+ event_name = StrE},
+ variable_header = PSeqV},
+ filterable_data = PSeqF,
+ remainder_of_body = AnyR}).
+%% Can be used in guards.
+-define(not_isConvertedAny(E),
+ (((E#'CosNotification_StructuredEvent'.header)
+ #'CosNotification_EventHeader'.fixed_header)
+ #'CosNotification_FixedEventHeader'.event_type)
+ #'CosNotification_EventType'.type_name == "%ANY").
+%% Can NOT be used in guards!!!!!
+-define(not_isConvertedStructured(E),
+ any:get_typecode(E) == 'CosNotification_StructuredEvent':tc()).
+
+%%--------------- StructuredEvent DESTRUCTORS ----------------
+-define(not_DestroySE(E), ok).
+
+%%--------------- StructuredEvent SELECTORS ------------------
+-define(not_GetSEHeader(E), E#'StructuredEvent'.header).
+-define(not_GetSEFixedHeader(E), E#'StructuredEvent'.header).
+
+%%--------------- StructuredEvent MODIFIERS ------------------
+
+%%-------- QoS support -----------------------------------------------
+-define(not_SUPPORTED_QOS,
+[{?not_EventReliability, 'EventReliability'},
+ {?not_ConnectionReliability, 'ConnectionReliability'},
+ {?not_Priority, 'Priority'},
+ {?not_StartTimeSupported, 'StartTimeSupported'},
+ {?not_StopTimeSupported, 'StopTimeSupported'},
+ {?not_Timeout, 'Timeout'},
+ {?not_OrderPolicy, 'OrderPolicy'},
+ {?not_DiscardPolicy, 'DiscardPolicy'},
+ {?not_MaximumBatchSize, 'MaximumBatchSize'},
+ {?not_PacingInterval, 'PacingInterval'},
+ {?not_MaxEventsPerConsumer, 'MaxEventsPerConsumer'}]).
+
+%%-------- ADMINPROPERTIESADMIN --------------------------------------
+
+%% According to the OMG TC Document telecom/98-11-01, p 63 (section 2.5.7), the
+%% default-value for these 3 admin properties is zero, which means that no limit
+%% applies to that property.
+-define(not_DEFAULT_ADMINPROPERTIES,
+[#'CosNotification_Property'{name=?not_MaxQueueLength,
+ value=any:create(orber_tc:long(), 0)},
+ #'CosNotification_Property'{name=?not_MaxConsumers,
+ value=any:create(orber_tc:long(), 0)},
+ #'CosNotification_Property'{name=?not_MaxSuppliers,
+ value=any:create(orber_tc:long(), 0)}]).
+
+-define(not_SUPPORTED_ADMINPROPERTIES,
+[{?not_MaxQueueLength, 'MaxQueueLength'},
+ {?not_MaxConsumers, 'MaxConsumers'},
+ {?not_MaxSuppliers, 'MaxSuppliers'}]).
+
+
+%%-------- MISC --------------------------------------------------------
+
+-define(not_DEFAULT_SETTINGS, [{pullInterval, 20},
+ {filterOp, 'OR_OP'},
+ {gcTime, 60},
+ {gcLimit, 50},
+ {timeService, undefined},
+ {typecheck, true},
+ {tty, false},
+ {logfile, false},
+ {server_options, []}]).
+-define(not_CreateDBKey, term_to_binary({now(), node()})).
+
+-define(DEBUG_LEVEL, 3).
+
+-ifdef(debug).
+
+-define(debug_print(F,A), io:format("[~p(~p)] "++F,[?MODULE, ?LINE]++A)).
+-define(DBG(F,A), io:format("[~p(~p)] "++F,[?MODULE, ?LINE]++A)).
+-define(not_TypeCheck(O,I), ok).
+%-define(not_TypeCheck(O,M), 'CosNotification_Common':type_check(O,M)).
+
+-else.
+
+-define(debug_print(F,A), ok).
+-define(DBG(F,A), ok).
+-define(not_TypeCheck(O,I), ok).
+
+-endif.
+
+
+
+-endif.
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin.cfg b/lib/cosNotification/src/CosNotifyChannelAdmin.cfg
new file mode 100644
index 0000000000..8647b281a2
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyChannelAdmin.cfg
@@ -0,0 +1,60 @@
+{this, "CosNotifyChannelAdmin::EventChannel"}.
+{from, "CosNotifyChannelAdmin::EventChannel"}.
+{{handle_info, "CosNotifyChannelAdmin::EventChannel"}, true}.
+{this, "CosNotifyChannelAdmin::EventChannelFactory"}.
+{from, "CosNotifyChannelAdmin::EventChannelFactory"}.
+{{handle_info, "CosNotifyChannelAdmin::EventChannelFactory"}, true}.
+{this, "CosNotifyChannelAdmin::SupplierAdmin"}.
+{from, "CosNotifyChannelAdmin::SupplierAdmin"}.
+{{handle_info, "CosNotifyChannelAdmin::SupplierAdmin"}, true}.
+{this, "CosNotifyChannelAdmin::ConsumerAdmin"}.
+{from, "CosNotifyChannelAdmin::ConsumerAdmin"}.
+{{handle_info, "CosNotifyChannelAdmin::ConsumerAdmin"}, true}.
+{this, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}.
+{from, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}.
+{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}, true}.
+{{impl, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}, "PusherSupplier_impl"}.
+{this, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}.
+{from, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}.
+{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}, true}.
+{{impl, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}, "PullerSupplier_impl"}.
+{this, "CosNotifyChannelAdmin::ProxyPushSupplier"}.
+{from, "CosNotifyChannelAdmin::ProxyPushSupplier"}.
+{{handle_info, "CosNotifyChannelAdmin::ProxyPushSupplier"}, true}.
+{{impl, "CosNotifyChannelAdmin::ProxyPushSupplier"}, "PusherSupplier_impl"}.
+{this, "CosNotifyChannelAdmin::ProxyPullSupplier"}.
+{from, "CosNotifyChannelAdmin::ProxyPullSupplier"}.
+{{handle_info, "CosNotifyChannelAdmin::ProxyPullSupplier"}, true}.
+{{impl, "CosNotifyChannelAdmin::ProxyPullSupplier"}, "PullerSupplier_impl"}.
+{this, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}.
+{from, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}.
+{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}, true}.
+{{impl, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}, "PusherSupplier_impl"}.
+{this, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}.
+{from, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}.
+{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}, true}.
+{{impl, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}, "PullerSupplier_impl"}.
+{this, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}.
+{from, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}.
+{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}, true}.
+{{impl, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}, "PusherConsumer_impl"}.
+{this, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}.
+{from, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}.
+{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}, true}.
+{{impl, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}, "PullerConsumer_impl"}.
+{this, "CosNotifyChannelAdmin::ProxyPushConsumer"}.
+{from, "CosNotifyChannelAdmin::ProxyPushConsumer"}.
+{{handle_info, "CosNotifyChannelAdmin::ProxyPushConsumer"}, true}.
+{{impl, "CosNotifyChannelAdmin::ProxyPushConsumer"}, "PusherConsumer_impl"}.
+{this, "CosNotifyChannelAdmin::ProxyPullConsumer"}.
+{from, "CosNotifyChannelAdmin::ProxyPullConsumer"}.
+{{handle_info, "CosNotifyChannelAdmin::ProxyPullConsumer"}, true}.
+{{impl, "CosNotifyChannelAdmin::ProxyPullConsumer"}, "PullerConsumer_impl"}.
+{this, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}.
+{from, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}.
+{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}, true}.
+{{impl, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}, "PusherConsumer_impl"}.
+{this, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}.
+{from, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}.
+{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}, true}.
+{{impl, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}, "PullerConsumer_impl"}.
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin.idl b/lib/cosNotification/src/CosNotifyChannelAdmin.idl
new file mode 100644
index 0000000000..b345ff5423
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyChannelAdmin.idl
@@ -0,0 +1,275 @@
+#ifndef _COS_NOTIFYCHANNELADMIN_IDL_
+#define _COS_NOTIFYCHANNELADMIN_IDL_
+
+#pragma prefix "omg.org"
+
+#include<cosNotificationAppComm.idl>
+#include<CosNotifyFilter.idl>
+#include<CosNotifyComm.idl>
+#include<CosNotification.idl>
+
+module CosNotifyChannelAdmin {
+ exception ConnectionAlreadyActive {};
+ exception ConnectionAlreadyInactive {};
+ exception NotConnected {};
+ // Forward declarations
+ interface ConsumerAdmin;
+ interface SupplierAdmin;
+ interface EventChannel;
+ interface EventChannelFactory;
+
+ enum ProxyType {
+ PUSH_ANY,
+ PULL_ANY,
+ PUSH_STRUCTURED,
+ PULL_STRUCTURED,
+ PUSH_SEQUENCE,
+ PULL_SEQUENCE};
+
+ enum ObtainInfoMode {
+ ALL_NOW_UPDATES_OFF,
+ ALL_NOW_UPDATES_ON,
+ NONE_NOW_UPDATES_OFF,
+ NONE_NOW_UPDATES_ON};
+
+ interface ProxyConsumer : CosNotification::QoSAdmin, CosNotifyFilter::FilterAdmin {
+ readonly attribute ProxyType MyType;
+ readonly attribute SupplierAdmin MyAdmin;
+
+ CosNotification::EventTypeSeq obtain_subscription_types(in ObtainInfoMode mode);
+
+ void validate_event_qos (in CosNotification::QoSProperties required_qos,
+ out CosNotification::NamedPropertyRangeSeq available_qos)
+ raises (CosNotification::UnsupportedQoS);
+ }; // ProxyConsumer
+
+ interface ProxySupplier : CosNotification::QoSAdmin, CosNotifyFilter::FilterAdmin {
+ readonly attribute ProxyType MyType;
+ readonly attribute ConsumerAdmin MyAdmin;
+ attribute CosNotifyFilter::MappingFilter priority_filter;
+ attribute CosNotifyFilter::MappingFilter lifetime_filter;
+
+ CosNotification::EventTypeSeq obtain_offered_types(in ObtainInfoMode mode);
+
+ void validate_event_qos (in CosNotification::QoSProperties required_qos,
+ out CosNotification::NamedPropertyRangeSeq available_qos)
+ raises (CosNotification::UnsupportedQoS);
+ }; // ProxySupplier
+
+ interface ProxyPushConsumer : ProxyConsumer, CosNotifyComm::PushConsumer,
+ CosEventChannelAdmin::ProxyPushConsumer {
+ void connect_any_push_supplier (in CosEventComm::PushSupplier push_supplier)
+ raises(CosEventChannelAdmin::AlreadyConnected);
+ }; // ProxyPushConsumer
+
+ interface StructuredProxyPushConsumer : ProxyConsumer, CosNotifyComm::StructuredPushConsumer {
+ void connect_structured_push_supplier (in CosNotifyComm::StructuredPushSupplier push_supplier)
+ raises(CosEventChannelAdmin::AlreadyConnected);
+ }; // StructuredProxyPushConsumer
+
+ interface SequenceProxyPushConsumer : ProxyConsumer, CosNotifyComm::SequencePushConsumer {
+ void connect_sequence_push_supplier (in CosNotifyComm::SequencePushSupplier push_supplier)
+ raises(CosEventChannelAdmin::AlreadyConnected);
+ }; // SequenceProxyPushConsumer
+
+ interface ProxyPullSupplier : ProxySupplier, CosNotifyComm::PullSupplier,
+ CosEventChannelAdmin::ProxyPullSupplier, oe_CosNotificationComm::Event {
+ void connect_any_pull_consumer (in CosEventComm::PullConsumer pull_consumer)
+ raises(CosEventChannelAdmin::AlreadyConnected);
+ }; // ProxyPullSupplier
+
+ interface StructuredProxyPullSupplier : ProxySupplier, CosNotifyComm::StructuredPullSupplier,
+ oe_CosNotificationComm::Event {
+ void connect_structured_pull_consumer (in CosNotifyComm::StructuredPullConsumer pull_consumer)
+ raises(CosEventChannelAdmin::AlreadyConnected);
+ }; // StructuredProxyPullSupplier
+
+ interface SequenceProxyPullSupplier : ProxySupplier, CosNotifyComm::SequencePullSupplier,
+ oe_CosNotificationComm::Event {
+ void connect_sequence_pull_consumer (in CosNotifyComm::SequencePullConsumer pull_consumer)
+ raises(CosEventChannelAdmin::AlreadyConnected);
+ }; // SequenceProxyPullSupplier
+
+ interface ProxyPullConsumer : ProxyConsumer, CosNotifyComm::PullConsumer,
+ CosEventChannelAdmin::ProxyPullConsumer {
+ void connect_any_pull_supplier (in CosEventComm::PullSupplier pull_supplier)
+ raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises(ConnectionAlreadyInactive, NotConnected);
+
+ void resume_connection()
+ raises(ConnectionAlreadyActive, NotConnected);
+ }; // ProxyPullConsumer
+
+ interface StructuredProxyPullConsumer : ProxyConsumer, CosNotifyComm::StructuredPullConsumer {
+ void connect_structured_pull_supplier (in CosNotifyComm::StructuredPullSupplier pull_supplier)
+ raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises(ConnectionAlreadyInactive, NotConnected);
+
+ void resume_connection()
+ raises(ConnectionAlreadyActive, NotConnected);
+ }; // StructuredProxyPullConsumer
+
+ interface SequenceProxyPullConsumer : ProxyConsumer, CosNotifyComm::SequencePullConsumer {
+ void connect_sequence_pull_supplier (in CosNotifyComm::SequencePullSupplier pull_supplier)
+ raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises(ConnectionAlreadyInactive, NotConnected);
+
+ void resume_connection()
+ raises(ConnectionAlreadyActive, NotConnected);
+ }; // SequenceProxyPullConsumer
+
+ interface ProxyPushSupplier : ProxySupplier, CosNotifyComm::PushSupplier,
+ CosEventChannelAdmin::ProxyPushSupplier, oe_CosNotificationComm::Event {
+ void connect_any_push_consumer (in CosEventComm::PushConsumer push_consumer)
+ raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises(ConnectionAlreadyInactive, NotConnected);
+
+ void resume_connection()
+ raises(ConnectionAlreadyActive, NotConnected);
+ }; // ProxyPushSupplier
+
+ interface StructuredProxyPushSupplier : ProxySupplier, CosNotifyComm::StructuredPushSupplier,
+ oe_CosNotificationComm::Event {
+ void connect_structured_push_consumer (in CosNotifyComm::StructuredPushConsumer push_consumer)
+ raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises(ConnectionAlreadyInactive, NotConnected);
+
+ void resume_connection()
+ raises(ConnectionAlreadyActive, NotConnected);
+ }; // StructuredProxyPushSupplier
+
+ interface SequenceProxyPushSupplier : ProxySupplier, CosNotifyComm::SequencePushSupplier,
+ oe_CosNotificationComm::Event {
+ void connect_sequence_push_consumer (in CosNotifyComm::SequencePushConsumer push_consumer)
+ raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises(ConnectionAlreadyInactive, NotConnected);
+
+ void resume_connection()
+ raises(ConnectionAlreadyActive, NotConnected);
+ }; // SequenceProxyPushSupplier
+
+
+ typedef long ProxyID;
+ typedef sequence <ProxyID> ProxyIDSeq;
+
+ enum ClientType {
+ ANY_EVENT,
+ STRUCTURED_EVENT,
+ SEQUENCE_EVENT};
+
+ enum InterFilterGroupOperator {
+ AND_OP,
+ OR_OP };
+
+ typedef long AdminID;
+ typedef sequence<AdminID> AdminIDSeq;
+
+ exception AdminNotFound {};
+ exception ProxyNotFound {};
+
+ struct AdminLimit {
+ CosNotification::PropertyName name;
+ CosNotification::PropertyValue value;
+ };
+
+ exception AdminLimitExceeded { AdminLimit admin_property_err; };
+
+ interface ConsumerAdmin : CosNotification::QoSAdmin, CosNotifyComm::NotifySubscribe,
+ CosNotifyFilter::FilterAdmin, CosEventChannelAdmin::ConsumerAdmin,
+ oe_CosNotificationComm::Event {
+ readonly attribute AdminID MyID;
+ readonly attribute EventChannel MyChannel;
+ readonly attribute InterFilterGroupOperator MyOperator;
+ attribute CosNotifyFilter::MappingFilter priority_filter;
+ attribute CosNotifyFilter::MappingFilter lifetime_filter;
+ readonly attribute ProxyIDSeq pull_suppliers;
+ readonly attribute ProxyIDSeq push_suppliers;
+
+ ProxySupplier get_proxy_supplier (in ProxyID proxy_id)
+ raises (ProxyNotFound);
+
+ ProxySupplier obtain_notification_pull_supplier (in ClientType ctype, out ProxyID proxy_id)
+ raises (AdminLimitExceeded);
+
+ ProxySupplier obtain_notification_push_supplier (in ClientType ctype, out ProxyID proxy_id)
+ raises (AdminLimitExceeded);
+
+ void destroy();
+ }; // ConsumerAdmin
+
+ interface SupplierAdmin : CosNotification::QoSAdmin, CosNotifyComm::NotifyPublish,
+ CosNotifyFilter::FilterAdmin, CosEventChannelAdmin::SupplierAdmin ,
+ oe_CosNotificationComm::Event {
+ readonly attribute AdminID MyID;
+ readonly attribute EventChannel MyChannel;
+ readonly attribute InterFilterGroupOperator MyOperator;
+ readonly attribute ProxyIDSeq pull_consumers;
+ readonly attribute ProxyIDSeq push_consumers;
+
+ ProxyConsumer get_proxy_consumer (in ProxyID proxy_id)
+ raises (ProxyNotFound);
+
+ ProxyConsumer obtain_notification_pull_consumer (in ClientType ctype, out ProxyID proxy_id)
+ raises (AdminLimitExceeded);
+
+ ProxyConsumer obtain_notification_push_consumer (in ClientType ctype, out ProxyID proxy_id)
+ raises (AdminLimitExceeded);
+
+ void destroy();
+ }; // SupplierAdmin
+
+ interface EventChannel : CosNotification::QoSAdmin, CosNotification::AdminPropertiesAdmin,
+ CosEventChannelAdmin::EventChannel,
+ oe_CosNotificationComm::Event {
+ readonly attribute EventChannelFactory MyFactory;
+ readonly attribute ConsumerAdmin default_consumer_admin;
+ readonly attribute SupplierAdmin default_supplier_admin;
+ readonly attribute CosNotifyFilter::FilterFactory default_filter_factory;
+
+ ConsumerAdmin new_for_consumers(in InterFilterGroupOperator op, out AdminID id);
+
+ SupplierAdmin new_for_suppliers(in InterFilterGroupOperator op, out AdminID id);
+
+ ConsumerAdmin get_consumeradmin (in AdminID id)
+ raises (AdminNotFound);
+
+ SupplierAdmin get_supplieradmin (in AdminID id)
+ raises (AdminNotFound);
+
+ AdminIDSeq get_all_consumeradmins();
+
+ AdminIDSeq get_all_supplieradmins();
+ }; // EventChannel
+
+ typedef long ChannelID;
+ typedef sequence<ChannelID> ChannelIDSeq;
+ exception ChannelNotFound {};
+
+ interface EventChannelFactory {
+ EventChannel create_channel (in CosNotification::QoSProperties initial_qos,
+ in CosNotification::AdminProperties initial_admin,
+ out ChannelID id)
+ raises(CosNotification::UnsupportedQoS, CosNotification::UnsupportedAdmin);
+
+ ChannelIDSeq get_all_channels();
+
+ EventChannel get_event_channel (in ChannelID id)
+ raises (ChannelNotFound);
+ }; // EventChannelFactory
+}; // CosNotifyChannelAdmin
+
+
+#endif /* ifndef _COS_NOTIFYCHANNELADMIN_IDL_ */
+
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl
new file mode 100644
index 0000000000..5ac8c810ea
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl
@@ -0,0 +1,670 @@
+%%--------------------------------------------------------------------
+%%
+%% %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_ConsumerAdmin_impl.erl
+%% Purpose :
+%%-------------------------------------------------------------------
+
+-module('CosNotifyChannelAdmin_ConsumerAdmin_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::ConsumerAdmin -----------------
+-export([get_proxy_supplier/4,
+ obtain_notification_pull_supplier/4,
+ obtain_notification_push_supplier/4,
+ destroy/3]).
+
+%%----- Inherit from CosNotification::QoSAdmin ---------------
+-export([get_qos/3,
+ set_qos/4,
+ validate_qos/4]).
+
+%%----- Inherit from CosNotifyComm::NotifySubscribe ----------
+-export([subscription_change/5]).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
+-export([add_filter/4,
+ remove_filter/4,
+ get_filter/4,
+ get_all_filters/3,
+ remove_all_filters/3]).
+
+%%----- Inherit from CosEventChannelAdmin::ConsumerAdmin -----
+-export([obtain_push_supplier/3,
+ obtain_pull_supplier/3]).
+
+%% Attributes (external)
+-export(['_get_MyID'/3,
+ '_get_MyChannel'/3,
+ '_get_MyOperator'/3,
+ '_get_priority_filter'/3,
+ '_set_priority_filter'/4,
+ '_get_lifetime_filter'/3,
+ '_set_lifetime_filter'/4,
+ '_get_pull_suppliers'/3,
+ '_get_push_suppliers'/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]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {myId,
+ myChannel,
+ myChannelPid,
+ myOperator,
+ myFilters = [],
+ mySuppliers = [],
+ idCounter = 0,
+ priorityFilter,
+ lifetimeFilter,
+ etsR,
+ qosGlobal,
+ qosLocal,
+ options}).
+
+%% Data structures constructors
+-define(get_InitState(_MyID, _MyCh, _MyChP, _MyOp, _PFil, _LFil, _QoS, _LQS, _O),
+ #state{myId = _MyID,
+ myChannel = _MyCh,
+ myChannelPid = _MyChP,
+ myOperator = _MyOp,
+ priorityFilter = _PFil,
+ lifetimeFilter = _LFil,
+ qosGlobal = _QoS,
+ qosLocal = _LQS,
+ options = _O,
+ etsR = ets:new(oe_ets, [set, protected])}).
+
+%% Data structures selectors
+-define(get_PushSupplierIDs(S), find_ids(S#state.mySuppliers, pusher)).
+-define(get_PullSupplierIDs(S), find_ids(S#state.mySuppliers, puller)).
+-define(get_AllSuppliers(S), S#state.mySuppliers).
+-define(get_AllSupplierRefs(S), find_refs(S#state.mySuppliers)).
+-define(get_Supplier(S, I), find_obj(lists:keysearch(I,1,S#state.mySuppliers),
+ supplier)).
+
+-define(get_MyID(S), S#state.myId).
+-define(get_MyChannel(S), S#state.myChannel).
+-define(get_MyChannelPid(S), S#state.myChannelPid).
+-define(get_MyOperator(S), S#state.myOperator).
+-define(get_PrioFilter(S), S#state.priorityFilter).
+-define(get_LifeFilter(S), S#state.lifetimeFilter).
+-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_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters),
+ filter)).
+-define(get_AllFilter(S), S#state.myFilters).
+-define(get_AllFilterID(S), find_ids(S#state.myFilters)).
+-define(get_Options(S), S#state.options).
+-define(get_IdCounter(S), S#state.idCounter).
+
+%% Data structures modifiers
+-define(set_PrioFilter(S,D), S#state{priorityFilter=D}).
+-define(set_LifeFilter(S,D), S#state{lifetimeFilter=D}).
+-define(set_LocalQoS(S,D), S#state{qosLocal=D}).
+-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
+-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
+-define(add_PushSupplier(S,I,R,P),S#state{mySuppliers=[{I,R,P,pusher}|S#state.mySuppliers]}).
+-define(add_PullSupplier(S,I,R,P),S#state{mySuppliers=[{I,R,P,puller}|S#state.mySuppliers]}).
+-define(del_Supplier(S,I), S#state{mySuppliers=
+ lists:keydelete(I, 1,
+ S#state.mySuppliers)}).
+-define(del_SupplierRef(S,O), S#state{mySuppliers=
+ lists:keydelete(O, 2,
+ S#state.mySuppliers)}).
+-define(del_SupplierPid(S,P), S#state{mySuppliers=
+ lists:keydelete(P, 3,
+ S#state.mySuppliers)}).
+-define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
+-define(del_Filter(S,I), S#state{myFilters=
+ delete_filter(lists:keydelete(I, 1,
+ S#state.myFilters),
+ S#state.myFilters)}).
+-define(del_AllFilter(S), S#state{myFilters=[]}).
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(
+ S#state.idCounter)).
+
+%% MISC
+-define(is_PersistentConnection(S),
+ ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
+-define(is_PersistentEvent(S),
+ ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
+-define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
+
+%%----------------------------------------------------------%
+%% 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) ->
+ case Info of
+ {'EXIT', Pid, Reason} when ?get_MyChannelPid(State) == Pid ->
+ ?DBG("PARENT CHANNEL: ~p TERMINATED.~n",[Reason]),
+ {stop, Reason, State};
+ {'EXIT', Pid, normal} ->
+ {noreply, ?del_SupplierPid(State, Pid)};
+ _Other ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([MyId, MyChannel, MyChannelPid, MyOperator, InitQoS, LQS, Options]) ->
+ process_flag(trap_exit, true),
+ PriorityFilter = corba:create_nil_objref(),
+ LifeTimeFilter = corba:create_nil_objref(),
+ {ok, ?get_InitState(MyId, MyChannel, MyChannelPid, MyOperator,
+ PriorityFilter, LifeTimeFilter, InitQoS, LQS, Options)}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------
+%%----- CosNotifyChannelAdmin_ConsumerAdmin attributes ------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyID'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyID'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyID(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyChannel'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyChannel'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyChannel(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyOperator'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyOperator'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyOperator(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_priority_filter'
+%% Type : read and write
+%% Returns :
+%%-----------------------------------------------------------
+'_get_priority_filter'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PrioFilter(State), State}.
+
+'_set_priority_filter'(_OE_THIS, _OE_FROM, State, PrioFilter) ->
+ {reply, ok, ?set_PrioFilter(State, PrioFilter)}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_lifetime_filter'
+%% Type : read and write
+%% Returns :
+%%-----------------------------------------------------------
+'_get_lifetime_filter'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_LifeFilter(State), State}.
+'_set_lifetime_filter'(_OE_THIS, _OE_FROM, State, LifeFilter) ->
+ {reply, ok, ?set_LifeFilter(State, LifeFilter)}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_pull_suppliers'
+%% Type : readonly
+%% Returns : ProxyIDSeq
+%%-----------------------------------------------------------
+'_get_pull_suppliers'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PullSupplierIDs(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_push_suppliers'
+%% Type : readonly
+%% Returns : ProxyIDSeq
+%%-----------------------------------------------------------
+'_get_push_suppliers'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PushSupplierIDs(State), State}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% function : get_proxy_supplier
+%% Arguments: ProxyID - unique identifier (long)
+%% Returns : ObjRef | {'EXCEPTION', #'ProxyNotFound'{}}
+%%-----------------------------------------------------------
+get_proxy_supplier(_OE_THIS, _OE_FROM, State, Proxy_id) ->
+ {reply, ?get_Supplier(State, Proxy_id), State}.
+
+%%----------------------------------------------------------%
+%% function : obtain_notification_pull_supplier
+%% Arguments: Ctype - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
+%% Returns : A Proxy of the requested type.
+%%-----------------------------------------------------------
+obtain_notification_pull_supplier(OE_THIS, _OE_FROM, State, Ctype) ->
+ %% Choose which module to use.
+ {Mod, Type} =
+ case Ctype of
+ 'ANY_EVENT' ->
+ {'CosNotifyChannelAdmin_ProxyPullSupplier', 'PULL_ANY'};
+ 'STRUCTURED_EVENT' ->
+ {'CosNotifyChannelAdmin_StructuredProxyPullSupplier', 'PULL_STRUCTURED'};
+ 'SEQUENCE_EVENT' ->
+ {'CosNotifyChannelAdmin_SequenceProxyPullSupplier', 'PULL_SEQUENCE'};
+ _ ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:"
+ "obtain_notification_pull_supplier(~p);~n"
+ "Incorrect enumerant",
+ [?LINE, Ctype], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end,
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
+ ?get_LocalQoS(State), ?get_MyChannel(State),
+ ?get_Options(State), ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, PrRef} ->
+ ProxyID = ?new_Id(State),
+ NewState = ?add_PullSupplier(State, ProxyID, PrRef, Pid),
+ {reply, {PrRef, ProxyID}, ?set_IdCounter(NewState, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:"
+ "obtain_notification_pull_supplier();~n"
+ "Unable to create: ~p/~p~n"
+ "Reason: ~p", [?LINE, Mod, Type, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%----------------------------------------------------------%
+%% function : obtain_notification_push_supplier
+%% Arguments: Ctype - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
+%% Returns : A Proxy of the requested type.
+%%-----------------------------------------------------------
+obtain_notification_push_supplier(OE_THIS, _OE_FROM, State, Ctype) ->
+ %% Choose which module to use.
+ {Mod, Type} =
+ case Ctype of
+ 'ANY_EVENT' ->
+ {'CosNotifyChannelAdmin_ProxyPushSupplier', 'PUSH_ANY'};
+ 'STRUCTURED_EVENT' ->
+ {'CosNotifyChannelAdmin_StructuredProxyPushSupplier', 'PUSH_STRUCTURED'};
+ 'SEQUENCE_EVENT' ->
+ {'CosNotifyChannelAdmin_SequenceProxyPushSupplier', 'PUSH_SEQUENCE'};
+ _ ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:"
+ "obtain_notification_push_supplier(~p);~n"
+ "Incorrect enumerant", [?LINE, Ctype], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end,
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
+ ?get_LocalQoS(State), ?get_MyChannel(State),
+ ?get_Options(State), ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, PrRef} ->
+ ProxyID = ?new_Id(State),
+ NewState = ?add_PushSupplier(State, ProxyID, PrRef, Pid),
+ {reply, {PrRef, ProxyID}, ?set_IdCounter(NewState, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:obtain_notification_push_supplier();~n"
+ "Unable to create: ~p/~p~n"
+ "Reason: ~p",
+ [?LINE, Mod, Type, 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}.
+
+%%----- Inherit from CosNotification::QoSAdmin --------------
+%%----------------------------------------------------------%
+%% function : get_qos
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+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) ->
+ {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
+ admin, ?get_MyChannel(State),
+ ?get_AllSupplierRefs(State)),
+ {reply, ok, ?set_BothQoS(State, NewQoS, LQS)}.
+
+%%----------------------------------------------------------%
+%% function : validate_qos
+%% Arguments: Required_qos - CosNotification::QoSProperties
+%% [#'Property'{name, value}, ...] where name eq. string()
+%% and value eq. any().
+%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
+%%-----------------------------------------------------------
+validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
+ QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
+ admin, ?get_MyChannel(State),
+ ?get_AllSupplierRefs(State)),
+ {reply, {ok, QoS}, State}.
+
+%%----- Inherit from CosNotifyComm::NotifySubscribe ---------
+%%----------------------------------------------------------*
+%% function : subscription_change
+%% Arguments:
+%% Returns : ok |
+%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{type}}
+%%-----------------------------------------------------------
+subscription_change(_OE_THIS, _OE_FROM, State, _Added, _Removed) ->
+ ?DBG("CALLBACK INFORMED: ~p ~p~n",[_Added, _Removed]),
+ {reply, ok, State}.
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
+%%----------------------------------------------------------%
+%% function : add_filter
+%% Arguments: Filter - CosNotifyFilter::Filter
+%% Returns : FilterID - long
+%%-----------------------------------------------------------
+add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
+ 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
+ FilterID = ?new_Id(State),
+ NewState = ?set_IdCounter(State, FilterID),
+ {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
+
+%%----------------------------------------------------------%
+%% function : remove_filter
+%% Arguments: FilterID - long
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ok, ?del_Filter(State, FilterID)};
+remove_filter(_,_,_,_) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_filter
+%% Arguments: FilterID - long
+%% Returns : Filter - CosNotifyFilter::Filter |
+%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
+%%-----------------------------------------------------------
+get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ?get_Filter(State, FilterID), State};
+get_filter(_,_,_,_) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_all_filters
+%% Arguments: -
+%% Returns : Filter - CosNotifyFilter::FilterIDSeq
+%%-----------------------------------------------------------
+get_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_AllFilterID(State), State}.
+
+%%----------------------------------------------------------%
+%% function : remove_all_filters
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ok, ?del_AllFilter(State)}.
+
+%%----- Inherit from CosEventChannelAdmin::ConsumerAdmin ----
+%%----------------------------------------------------------%
+%% function : obtain_push_supplier
+%% Arguments: -
+%% Returns : ProxyPushSupplier
+%%-----------------------------------------------------------
+obtain_push_supplier(OE_THIS, _OE_FROM, State) ->
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_create_link(['PUSH_ANY', OE_THIS,
+ self(),
+ ?get_GlobalQoS(State),
+ ?get_LocalQoS(State),
+ ?get_MyChannel(State),
+ ?get_Options(State),
+ ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, PrRef} ->
+ ProxyID = ?new_Id(State),
+ NewState = ?add_PushSupplier(State, ProxyID, PrRef, Pid),
+ {reply, PrRef, ?set_IdCounter(NewState, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:obtain_push_supplier();~n"
+ "Unable to create: CosNotifyChannelAdmin_ProxyPushSupplier~n"
+ "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%----------------------------------------------------------%
+%% function : obtain_pull_supplier
+%% Arguments: -
+%% Returns : ProxyPullSupplier
+%%-----------------------------------------------------------
+obtain_pull_supplier(OE_THIS, _OE_FROM, State) ->
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_create_link(['PULL_ANY', OE_THIS,
+ self(),
+ ?get_GlobalQoS(State),
+ ?get_LocalQoS(State),
+ ?get_MyChannel(State),
+ ?get_Options(State),
+ ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, PrRef} ->
+ ProxyID = ?new_Id(State),
+ NewState = ?add_PullSupplier(State, ProxyID, PrRef, Pid),
+ {reply, PrRef, ?set_IdCounter(NewState, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:obtain_pull_supplier();~n"
+ "Unable to create: CosNotifyChannelAdmin_ProxyPullSupplier~n"
+ "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+%% To match suppliers
+find_obj({value, {_,Obj,_,_}},_) -> Obj;
+%% To match filters
+find_obj({value, {_,Obj}},_) -> Obj;
+find_obj(_, supplier) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}};
+find_obj(_, filter) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
+
+find_ids(List) ->
+ find_ids(List, [], false).
+find_ids(List, Type) ->
+ find_ids(List, [], Type).
+
+find_ids([], Acc, _) ->
+ Acc;
+find_ids([{I,_}|T], Acc, Type) ->
+ find_ids(T, [I|Acc], Type);
+find_ids([{I,_,_,Type}|T], Acc, Type) ->
+ find_ids(T, [I|Acc], Type);
+find_ids([{_I,_,_,_}|T], Acc, Type) ->
+ find_ids(T, Acc, Type);
+find_ids(What, _, _) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:find_ids();~n"
+ "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+find_refs(List) ->
+ find_refs(List, []).
+
+find_refs([], Acc) ->
+ Acc;
+find_refs([{_,R,_,_}|T], Acc) ->
+ find_refs(T, [R|Acc]);
+find_refs(What, _) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:find_refs();~n"
+ "Reference corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+%% Delete a single filter.
+%% The list do not differ, i.e., no filter removed, raise exception.
+delete_filter(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
+delete_filter(List, _) -> List.
+
+
+%%-----------------------------------------------------------
+%% function : callSeq
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callSeq(_OE_THIS, OE_FROM, State, Events, _Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:filter_events(Events, ?get_AllFilter(State)) of
+ {[], _} when ?is_ANDOP(State) ->
+ %% Since AND it doesn't matter what the proxies 'think'. Done.
+ {noreply, State};
+ {[], Failed} ->
+ %% Is OR but the Proxy may allow the events; pass on.
+ forward(seq, State, Failed, 'MATCH');
+ {Passed, _} when ?is_ANDOP(State) ->
+ %% Since AND we only forward those who passed this objects filters.
+ forward(seq, State, Passed, 'MATCH');
+ {Passed, []} ->
+ %% Since OR we forward and tell the proxy to do no filtering.
+ forward(seq, State, Passed, 'MATCHED');
+ {Passed, Failed} ->
+ %% Since OR we forward both and instruct the proxy to check only
+ %% the ones that failed.
+ forward(seq, State, Passed, 'MATCHED'),
+ forward(seq, State, Failed, 'MATCH')
+ end.
+
+
+%%-----------------------------------------------------------
+%% function : callAny
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callAny(_OE_THIS, OE_FROM, State, Event, _Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State)) of
+ {[], _} when ?is_ANDOP(State) ->
+ %% Since AND it doesn't matter what the proxies 'think'. Done.
+ {noreply, State};
+ {[], [Failed]} ->
+ %% Is OR but the Proxy may allow the event; pass on.
+ forward(any, State, Failed, 'MATCH');
+ {[Passed], _} when ?is_ANDOP(State) ->
+ %% Since AND we only forward those who passed this objects filters.
+ forward(any, State, Passed, 'MATCH');
+ {[Passed], _} ->
+ %% Since OR we forward and instruct the proxy to do no checks.
+ forward(any, State, Passed, 'MATCHED')
+ end.
+
+
+
+%% Forward events
+forward(Type, State, Event, Status) ->
+ forward(Type, ?get_AllSuppliers(State), State, Event, Status).
+forward(_, [], State, _, _) ->
+ {noreply, State};
+forward(any, [{_,H,_,_}|T], State, Event, Status) ->
+ case catch oe_CosNotificationComm_Event:callAny(H, Event, Status) of
+ ok ->
+ ?DBG("CONSUMERADM FORWARD ANY: ~p~n",[Event]),
+ forward(any, T, State, Event, Status);
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
+ "Proxy no longer exists; dropping it: ~p",
+ [?LINE, H], ?DEBUG_LEVEL),
+ NewState = ?del_SupplierRef(State,H),
+ forward(any, T, NewState, Event, Status);
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
+ "Proxy behaves badly: ~p/~p",
+ [?LINE, R, H], ?DEBUG_LEVEL),
+ forward(any, T, State, Event, Status);
+ R ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
+ "Proxy behaves badly: ~p~n"
+ "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL),
+ NewState = ?del_SupplierRef(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("CONSUMERADM FORWARD SEQUENCE: ~p~n",[Event]),
+ forward(seq, T, State, Event, Status);
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
+ "Proxy no longer exists; dropping it: ~p",
+ [?LINE, H], ?DEBUG_LEVEL),
+ NewState = ?del_SupplierRef(State,H),
+ forward(seq, T, NewState, Event, Status);
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
+ "Proxy behaves badly: ~p/~p", [?LINE, R, H], ?DEBUG_LEVEL),
+ forward(seq, T, State, Event, Status);
+ R ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
+ "Proxy behaves badly: ~p~n"
+ "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL),
+ NewState = ?del_SupplierRef(State, H),
+ forward(seq, T, NewState, Event, Status)
+ end.
+
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl
new file mode 100644
index 0000000000..872a786f92
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl
@@ -0,0 +1,142 @@
+%%--------------------------------------------------------------------
+%%
+%% %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_EventChannelFactory_impl.erl
+%% Purpose :
+%%-------------------------------------------------------------------
+
+-module('CosNotifyChannelAdmin_EventChannelFactory_impl').
+
+%%--------------- INCLUDES -----------------------------------
+%% Application files
+-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").
+
+%%--------------- IMPORTS ------------------------------------
+
+%%--------------- EXPORTS ------------------------------------
+%% External
+-export([create_channel/5,
+ get_all_channels/3,
+ get_event_channel/4]).
+
+%%--------------- gen_server specific exports ----------------
+-export([handle_info/2, code_change/3]).
+-export([init/1, terminate/2]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {adminProp,
+ idCounter = 0,
+ options,
+ etsR,
+ server_options}).
+
+%%-----------------------------------------------------------%
+%% function : handle_info, code_change
+%% Arguments: See gen_server documentation.
+%% Effect : Functions demanded by the gen_server module.
+%%------------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+handle_info(Info, State) ->
+ ?debug_print("INFO: ~p~n", [Info]),
+ case Info of
+ {'EXIT', Pid, normal} ->
+ ets:match_delete(State#state.etsR, {'_','_',Pid}),
+ {noreply, State};
+ _Other ->
+ ?debug_print("TERMINATED: ~p~n",[_Other]),
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init(Options) ->
+ process_flag(trap_exit, true),
+ SO = 'CosNotification_Common':get_option(server_options, Options, ?not_DEFAULT_SETTINGS),
+ {ok, #state{options = Options,
+ etsR = ets:new(oe_ets, [set, protected]),
+ server_options = SO}}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% function : create_channel
+%% Arguments: InitQoS
+%% InitAdmin
+%% Returns : Ch - Channel obj ref
+%% Id - Channel Id (out-type)
+%%-----------------------------------------------------------
+create_channel(OE_THIS, _OE_FROM, State, InitQoS, InitAdmin) ->
+ {QoS, LQoS} = 'CosNotification_Common':init_qos(InitQoS),
+ {IAdm, LAdm} = 'CosNotification_Common':init_adm(InitAdmin),
+ Id = 'CosNotification_Common':create_id(State#state.idCounter),
+ case 'CosNotifyChannelAdmin_EventChannel':oe_create_link([OE_THIS, QoS, IAdm,
+ LQoS, LAdm,
+ State#state.options],
+ [{sup_child, true}|State#state.server_options]) of
+ {ok, Pid, Ch} ->
+ ets:insert(State#state.etsR, {Id,Ch,Pid}),
+ {reply, {Ch, Id}, State#state{idCounter=Id}};
+ _ ->
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%----------------------------------------------------------%
+%% function : get_all_channels
+%% Arguments: -
+%% Returns : ChannelIDSeq - List of alive channels created
+%% by this factory.
+%%-----------------------------------------------------------
+get_all_channels(_OE_THIS, _OE_FROM, State) ->
+ {reply, lists:flatten(ets:match(State#state.etsR, {'$1','_','_'})), State}.
+
+%%----------------------------------------------------------%
+%% function : get_event_channel
+%% Arguments: ChannelId
+%% Returns : ChannelRef | 'CosNotifyChannelAdmin_ChannelNotFound'
+%%-----------------------------------------------------------
+get_event_channel(_OE_THIS, _OE_FROM, State, Id) ->
+ {reply, find_obj(ets:lookup(State#state.etsR, Id)), State}.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+find_obj([]) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}};
+find_obj([{_, Obj,_}]) -> Obj;
+find_obj(_) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}.
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
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 ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl
new file mode 100644
index 0000000000..1c3f3d8d0b
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl
@@ -0,0 +1,579 @@
+%%--------------------------------------------------------------------
+%%
+%% %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_SupplierAdmin_impl.erl
+%% Purpose :
+%%-------------------------------------------------------------------
+
+-module('CosNotifyChannelAdmin_SupplierAdmin_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::SupplierAdmin -----------------
+-export([get_proxy_consumer/4,
+ obtain_notification_pull_consumer/4,
+ obtain_notification_push_consumer/4,
+ destroy/3]).
+
+%%----- Inherit from CosNotification::QoSAdmin ---------------
+-export([get_qos/3,
+ set_qos/4,
+ validate_qos/4]).
+
+%%----- Inherit from CosNotifyComm::NotifyPublish ------------
+-export([offer_change/5]).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
+-export([add_filter/4,
+ remove_filter/4,
+ get_filter/4,
+ get_all_filters/3,
+ remove_all_filters/3]).
+
+%%----- Inherit from CosEventChannelAdmin::SupplierAdmin -----
+-export([obtain_push_consumer/3,
+ obtain_pull_consumer/3]).
+
+%% Attributes (external)
+-export(['_get_MyID'/3,
+ '_get_MyChannel'/3,
+ '_get_MyOperator'/3,
+ '_get_pull_consumers'/3,
+ '_get_push_consumers'/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]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {myId,
+ myChannel,
+ myChannelPid,
+ myOperator,
+ myFilters = [],
+ idCounter = 0,
+ etsR,
+ qosGlobal,
+ qosLocal,
+ options}).
+
+%% Data structures constructors
+-define(get_InitState(_MyID, _MyCh, _MyChP, _MyOp, _QoS, _LQS, _O),
+ #state{myId = _MyID,
+ myChannel = _MyCh,
+ myChannelPid = _MyChP,
+ myOperator = _MyOp,
+ qosGlobal = _QoS,
+ qosLocal = _LQS,
+ options = _O,
+ etsR = ets:new(oe_ets, [set, protected])}).
+
+%% Data structures selectors
+-define(get_PushConsumers(S), lists:flatten(ets:match(S#state.etsR,
+ {'_','$1','_',pusher}))).
+-define(get_PullConsumers(S), lists:flatten(ets:match(S#state.etsR,
+ {'_','$1','_',puller}))).
+-define(get_AllConsumers(S), lists:flatten(ets:match(S#state.etsR,
+ {'_','$1','_','_'}))).
+-define(get_PushConsumerIDs(S), lists:flatten(ets:match(S#state.etsR,
+ {'$1','_','_',pusher}))).
+-define(get_PullConsumerIDs(S), lists:flatten(ets:match(S#state.etsR,
+ {'$1','_','_',puller}))).
+
+-define(get_Consumer(S, I), find_obj(ets:lookup(S#state.etsR, I), consumer)).
+
+-define(get_MyID(S), S#state.myId).
+-define(get_MyChannel(S), S#state.myChannel).
+-define(get_MyChannelPid(S), S#state.myChannelPid).
+-define(get_MyOperator(S), S#state.myOperator).
+-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_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters),
+ filter)).
+-define(get_AllFilter(S), S#state.myFilters).
+-define(get_AllFilterID(S), find_ids(S#state.myFilters)).
+-define(get_Options(S), S#state.options).
+-define(get_IdCounter(S), S#state.idCounter).
+
+%% Data structures modifiers
+-define(set_LocalQoS(S,D), S#state{qosLocal=D}).
+-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
+-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
+-define(add_PushConsumer(S,I,R,P),ets:insert(State#state.etsR, {I,R,P,pusher})).
+-define(add_PullConsumer(S,I,R,P),ets:insert(State#state.etsR, {I,R,P,puller})).
+-define(del_Consumer(S,I), ets:delete(S#state.etsR, I)).
+-define(del_ConsumerPid(S,P), ets:match_delete(S#state.etsR, {'_','_',P,'_'})).
+-define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
+-define(del_Filter(S,I), S#state{myFilters=
+ delete_filter(lists:keydelete(I, 1,
+ S#state.myFilters),
+ S#state.myFilters)}).
+-define(del_AllFilter(S), S#state{myFilters=[]}).
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+
+%% MISC
+-define(is_PersistentEvent(S),
+ ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
+-define(is_PersistentConnection(S),
+ ?not_GetConnectionReliability((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) ->
+ case Info of
+ {'EXIT', Pid, Reason} when ?get_MyChannelPid(State) == Pid ->
+ ?DBG("PARENT CHANNEL: ~p TERMINATED.~n",[Reason]),
+ {stop, Reason, State};
+ {'EXIT', Pid, normal} ->
+ ?del_ConsumerPid(State, Pid),
+ {noreply, State};
+ _Other ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([MyId, MyChannel, MyChannelPid, MyOperator, InitQoS, LQS, Options]) ->
+ process_flag(trap_exit, true),
+ {ok, ?get_InitState(MyId, MyChannel, MyChannelPid, MyOperator, InitQoS, LQS, Options)}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------
+%%----- CosNotifyChannelAdmin_ConsumerAdmin attributes ------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyID'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyID'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyID(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyChannel'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyChannel'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyChannel(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyOperator'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyOperator'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyOperator(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_pull_consumers'
+%% Type : readonly
+%% Returns : ProxyIDSeq
+%%-----------------------------------------------------------
+'_get_pull_consumers'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PullConsumerIDs(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_push_consumers'
+%% Type : readonly
+%% Returns : ProxyIDSeq
+%%-----------------------------------------------------------
+'_get_push_consumers'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PushConsumerIDs(State), State}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% function : get_proxy_consumer
+%% Arguments: ProxyId - unique identifier (long)
+%% Returns : ObjRef | {'EXCEPTION', #'ProxyNotFound'{}}
+%%-----------------------------------------------------------
+get_proxy_consumer(_OE_THIS, _OE_FROM, State, ProxyId) ->
+ {reply, ?get_Consumer(State, ProxyId), State}.
+
+%%----------------------------------------------------------%
+%% function : obtain_notification_pull_consumer
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+obtain_notification_pull_consumer(OE_THIS, _OE_FROM, State, Ctype) ->
+ %% Choose which module to use.
+ {Mod, Type} =
+ case Ctype of
+ 'ANY_EVENT' ->
+ {'CosNotifyChannelAdmin_ProxyPullConsumer', 'PULL_ANY'};
+ 'STRUCTURED_EVENT' ->
+ {'CosNotifyChannelAdmin_StructuredProxyPullConsumer', 'PULL_STRUCTURED'};
+ 'SEQUENCE_EVENT' ->
+ {'CosNotifyChannelAdmin_SequenceProxyPullConsumer', 'PULL_SEQUENCE'};
+ _ ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
+ "obtain_notification_pull_consumer(~p);~n"
+ "Incorrect enumerant",
+ [?LINE, Ctype], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end,
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case catch Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
+ ?get_LocalQoS(State), ?get_MyChannel(State),
+ ?get_Options(State), ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, Proxy} ->
+ ProxyID = ?new_Id(State),
+ ?add_PullConsumer(State, ProxyID, Proxy, Pid),
+ {reply, {Proxy, ProxyID}, ?set_IdCounter(State, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
+ "obtain_notification_pull_consumer();~n"
+ "Unable to create: ~p/~p~n"
+ "Reason: ~p", [?LINE, Mod, Type, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%----------------------------------------------------------%
+%% function : obtain_notification_push_supplier
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+obtain_notification_push_consumer(OE_THIS, _OE_FROM, State, Ctype) ->
+ %% Choose which module to use.
+ {Mod, Type} =
+ case Ctype of
+ 'ANY_EVENT' ->
+ {'CosNotifyChannelAdmin_ProxyPushConsumer', 'PUSH_ANY'};
+ 'STRUCTURED_EVENT' ->
+ {'CosNotifyChannelAdmin_StructuredProxyPushConsumer', 'PUSH_STRUCTURED'};
+ 'SEQUENCE_EVENT' ->
+ {'CosNotifyChannelAdmin_SequenceProxyPushConsumer', 'PUSH_SEQUENCE'};
+ _ ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
+ "obtain_notification_push_consumer(~p);~n"
+ "Incorrect enumerant", [?LINE, Ctype], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end,
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case catch Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
+ ?get_LocalQoS(State), ?get_MyChannel(State),
+ ?get_Options(State), ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, Proxy} ->
+ ProxyID = ?new_Id(State),
+ ?add_PushConsumer(State, ProxyID, Proxy, Pid),
+ {reply, {Proxy, ProxyID}, ?set_IdCounter(State, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
+ "obtain_notification_push_consumer();~n"
+ "Unable to create: ~p/~p~n"
+ "Reason: ~p", [?LINE, Mod, Type, 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}.
+
+%%----- Inherit from CosNotification::QoSAdmin --------------
+%%----------------------------------------------------------%
+%% function : get_qos
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+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) ->
+ {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
+ admin, ?get_MyChannel(State),
+ ?get_AllConsumers(State)),
+ {reply, ok, ?set_BothQoS(State, NewQoS, LQS)}.
+
+%%----------------------------------------------------------%
+%% 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),
+ admin, ?get_MyChannel(State),
+ ?get_AllConsumers(State)),
+ {reply, {ok, QoS}, State}.
+
+%%----- Inherit from CosNotifyComm::NotifyPublish -----------
+%%----------------------------------------------------------*
+%% function : offer_change
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+offer_change(_OE_THIS, _OE_FROM, State, _Added, _Removed) ->
+ {reply, ok, State}.
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
+%%----------------------------------------------------------%
+%% function : add_filter
+%% Arguments: Filter - CosNotifyFilter::Filter
+%% Returns : FilterID - long
+%%-----------------------------------------------------------
+add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
+ 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
+ FilterID = ?new_Id(State),
+ NewState = ?set_IdCounter(State, FilterID),
+ {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
+
+%%----------------------------------------------------------%
+%% function : remove_filter
+%% Arguments: FilterID - long
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ok, ?del_Filter(State, FilterID)};
+remove_filter(_,_,_,What) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:remove_filter(~p);~n"
+ "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_filter
+%% Arguments: FilterID - long
+%% Returns : Filter - CosNotifyFilter::Filter |
+%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
+%%-----------------------------------------------------------
+get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ?get_Filter(State, FilterID), State};
+get_filter(_,_,_,What) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:get_filter(~p);~n"
+ "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_all_filters
+%% Arguments: -
+%% Returns : Filter - CosNotifyFilter::FilterIDSeq
+%%-----------------------------------------------------------
+get_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_AllFilterID(State), State}.
+
+%%----------------------------------------------------------%
+%% function : remove_all_filters
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ok, ?del_AllFilter(State)}.
+
+%%----- Inherit from CosEventChannelAdmin::SupplierAdmin ----
+%%----------------------------------------------------------%
+%% function : obtain_push_consumer
+%% Arguments: -
+%% Returns : ProxyPushConsumer
+%%-----------------------------------------------------------
+obtain_push_consumer(OE_THIS, _OE_FROM, State) ->
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case catch 'CosNotifyChannelAdmin_ProxyPushConsumer':
+ oe_create_link(['PUSH_ANY', OE_THIS, self(), ?get_GlobalQoS(State),
+ ?get_LocalQoS(State), ?get_MyChannel(State),
+ ?get_Options(State), ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, Proxy} ->
+ ProxyID = ?new_Id(State),
+ ?add_PushConsumer(State, ProxyID, Proxy, Pid),
+ {reply, Proxy, ?set_IdCounter(State, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:obtain_push_consumer();~n"
+ "Unable to create: CosNotifyChannelAdmin_ProxyPushConsumer~n"
+ "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%----------------------------------------------------------%
+%% function : obtain_pull_consumer
+%% Arguments: -
+%% Returns : ProxyPullConsumer
+%%-----------------------------------------------------------
+obtain_pull_consumer(OE_THIS, _OE_FROM, State) ->
+ SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
+ ?not_DEFAULT_SETTINGS),
+ case catch 'CosNotifyChannelAdmin_ProxyPullConsumer':
+ oe_create_link(['PULL_ANY', OE_THIS, self(), ?get_GlobalQoS(State),
+ ?get_LocalQoS(State), ?get_MyChannel(State),
+ ?get_Options(State), ?get_MyOperator(State)],
+ [{sup_child, true}|SO]) of
+ {ok, Pid, Proxy} ->
+ ProxyID = ?new_Id(State),
+ ?add_PullConsumer(State, ProxyID, Proxy, Pid),
+ {reply, Proxy, ?set_IdCounter(State, ProxyID)};
+ What ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:obtain_push_consumer();~n"
+ "Unable to create: CosNotifyChannelAdmin_ProxyPullConsumer~n"
+ "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+find_obj([], consumer) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}};
+find_obj([], filter) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}};
+%% To match consumers
+find_obj([{_,Obj,_,_}],_) -> Obj;
+%% To match filters
+find_obj({value, {_,Obj}},_) -> Obj;
+find_obj(_,consumer) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}};
+find_obj(_,filter) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
+
+find_ids(List) -> find_ids(List, []).
+find_ids([], Acc) -> Acc;
+find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
+find_ids(What, _) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:find_ids();~n"
+ "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+%% Delete a single filter.
+%% The list do not differ, i.e., no filter removed, raise exception.
+delete_filter(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
+delete_filter(List, _) -> List.
+
+%%-----------------------------------------------------------
+%% function : callSeq
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callSeq(_OE_THIS, OE_FROM, State, Events, _Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:filter_events(Events, ?get_AllFilter(State)) of
+ {[], _} ->
+ {noreply, State};
+ {Passed, _} ->
+ forward(seq, State, Passed, 'MATCHED')
+ end.
+
+%%-----------------------------------------------------------
+%% function : callAny
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callAny(_OE_THIS, OE_FROM, State, Event, _Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State)) of
+ {[], _} ->
+ {noreply, State};
+ {[Passed], _} ->
+ forward(any, State, Passed, 'MATCHED')
+ end.
+
+%% Forward events
+forward(any, State, Event, Status) ->
+ case catch oe_CosNotificationComm_Event:callAny(?get_MyChannel(State),
+ Event, Status) of
+ ok ->
+ ?DBG("SUPPLIERADM FORWARD ANY: ~p~n",[Event]),
+ {noreply, State};
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
+ "Channel no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ {stop, normal, State};
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
+ "Channel respond incorrect: ~p~n"
+ "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ R ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
+ "Channel respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, R, Event], ?DEBUG_LEVEL),
+ {stop, normal, State}
+ end;
+forward(seq, State, Event, Status) ->
+ case catch oe_CosNotificationComm_Event:callSeq(?get_MyChannel(State),
+ Event, Status) of
+ ok ->
+ ?DBG("SUPPLIERADM FORWARD SEQUENCE: ~p~n",[Event]),
+ {noreply, State};
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
+ "Channel no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ {stop, normal, State};
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
+ "Channel respond incorrect: ~p~n"
+ "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ R ->
+ orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
+ "Channel respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, R, Event], ?DEBUG_LEVEL),
+ {stop, normal, State}
+ end.
+
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyComm.cfg b/lib/cosNotification/src/CosNotifyComm.cfg
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyComm.cfg
diff --git a/lib/cosNotification/src/CosNotifyComm.idl b/lib/cosNotification/src/CosNotifyComm.idl
new file mode 100644
index 0000000000..f0386f0982
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyComm.idl
@@ -0,0 +1,83 @@
+#ifndef _COS_NOTIFYCOMM_IDL_
+#define _COS_NOTIFYCOMM_IDL_
+
+#pragma prefix "omg.org"
+
+
+#include<CosNotification.idl>
+
+module CosNotifyComm {
+ exception InvalidEventType { CosNotification::EventType type; };
+
+ interface NotifyPublish {
+ void offer_change (in CosNotification::EventTypeSeq added,
+ in CosNotification::EventTypeSeq removed)
+ raises (InvalidEventType);
+ }; // NotifyPublish
+
+ interface NotifySubscribe {
+ void subscription_change(in CosNotification::EventTypeSeq added,
+ in CosNotification::EventTypeSeq removed)
+ raises (InvalidEventType);
+ }; // NotifySubscribe
+
+ interface PushConsumer : NotifyPublish, CosEventComm::PushConsumer { }; // PushConsumer
+
+ interface PullConsumer : NotifyPublish, CosEventComm::PullConsumer { }; // PullConsumer
+
+ interface PullSupplier : NotifySubscribe, CosEventComm::PullSupplier { }; // PullSupplier
+
+ interface PushSupplier : NotifySubscribe, CosEventComm::PushSupplier { };
+
+ interface StructuredPushConsumer : NotifyPublish {
+ void push_structured_event(in CosNotification::StructuredEvent notification)
+ raises(CosEventComm::Disconnected);
+
+ void disconnect_structured_push_consumer();
+ }; // StructuredPushConsumer
+
+ interface StructuredPullConsumer : NotifyPublish {
+ void disconnect_structured_pull_consumer();
+ }; // StructuredPullConsumer
+
+ interface StructuredPullSupplier : NotifySubscribe {
+ CosNotification::StructuredEvent pull_structured_event()
+ raises(CosEventComm::Disconnected);
+
+ CosNotification::StructuredEvent try_pull_structured_event(out boolean has_event)
+ raises(CosEventComm::Disconnected);
+
+ void disconnect_structured_pull_supplier();
+ }; // StructuredPullSupplier
+
+ interface StructuredPushSupplier : NotifySubscribe {
+ void disconnect_structured_push_supplier();
+ }; // StructuredPushSupplier
+
+ interface SequencePushConsumer : NotifyPublish {
+ void push_structured_events(in CosNotification::EventBatch notifications)
+ raises(CosEventComm::Disconnected);
+
+ void disconnect_sequence_push_consumer();
+ }; // SequencePushConsumer
+
+ interface SequencePullConsumer : NotifyPublish {
+ void disconnect_sequence_pull_consumer();
+ }; // SequencePullConsumer
+
+ interface SequencePullSupplier : NotifySubscribe {
+ CosNotification::EventBatch pull_structured_events(in long max_number)
+ raises(CosEventComm::Disconnected);
+ CosNotification::EventBatch try_pull_structured_events(in long max_number, out boolean has_event)
+ raises(CosEventComm::Disconnected);
+
+ void disconnect_sequence_pull_supplier();
+ }; // SequencePullSupplier
+
+ interface SequencePushSupplier : NotifySubscribe {
+ void disconnect_sequence_push_supplier();
+ }; // SequencePushSupplier
+}; // CosNotifyComm
+
+#endif /* ifndef _COS_NOTIFYCOMM_IDL_ */
+
diff --git a/lib/cosNotification/src/CosNotifyFilter.cfg b/lib/cosNotification/src/CosNotifyFilter.cfg
new file mode 100644
index 0000000000..167550e0f5
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyFilter.cfg
@@ -0,0 +1,6 @@
+{this, "CosNotifyFilter::Filter"}.
+{{handle_info, "CosNotifyFilter::Filter"}, true}.
+{this, "CosNotifyFilter::MappingFilter"}.
+{{handle_info, "CosNotifyFilter::MappingFilter"}, true}.
+{this, "CosNotifyFilter::FilterFactory"}.
+{{handle_info, "CosNotifyFilter::FilterFactory"}, true}.
diff --git a/lib/cosNotification/src/CosNotifyFilter.idl b/lib/cosNotification/src/CosNotifyFilter.idl
new file mode 100644
index 0000000000..c6498ddcd0
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyFilter.idl
@@ -0,0 +1,140 @@
+#ifndef _COS_NOTIFYFILTER_IDL_
+#define _COS_NOTIFYFILTER_IDL_
+
+#pragma prefix "omg.org"
+
+#include<CosNotifyComm.idl>
+#include<CosNotification.idl>
+
+module CosNotifyFilter {
+ typedef long ConstraintID;
+ struct ConstraintExp {
+ CosNotification::EventTypeSeq event_types;
+ string constraint_expr;
+ };
+
+ typedef sequence<ConstraintID> ConstraintIDSeq;
+ typedef sequence<ConstraintExp> ConstraintExpSeq;
+ struct ConstraintInfo {
+ ConstraintExp constraint_expression;
+ ConstraintID constraint_id;
+ };
+ typedef sequence<ConstraintInfo> ConstraintInfoSeq;
+ struct MappingConstraintPair {
+ ConstraintExp constraint_expression;
+ any result_to_set;
+ };
+ typedef sequence<MappingConstraintPair> MappingConstraintPairSeq;
+ struct MappingConstraintInfo {
+ ConstraintExp constraint_expression;
+ ConstraintID constraint_id;
+ any value;
+ };
+ typedef sequence<MappingConstraintInfo> MappingConstraintInfoSeq;
+ typedef long CallbackID;
+ typedef sequence<CallbackID> CallbackIDSeq;
+ exception UnsupportedFilterableData {};
+ exception InvalidGrammar {};
+ exception InvalidConstraint {ConstraintExp constr;};
+ exception DuplicateConstraintID {ConstraintID id;};
+ exception ConstraintNotFound {ConstraintID id;};
+ exception CallbackNotFound {};
+ exception InvalidValue {ConstraintExp constr; any value;};
+ interface Filter {
+ readonly attribute string constraint_grammar;
+ ConstraintInfoSeq add_constraints (in ConstraintExpSeq constraint_list)
+ raises (InvalidConstraint);
+
+ void modify_constraints (in ConstraintIDSeq del_list,
+ in ConstraintInfoSeq modify_list)
+ raises (InvalidConstraint, ConstraintNotFound);
+
+ ConstraintInfoSeq get_constraints(in ConstraintIDSeq id_list)
+ raises (ConstraintNotFound);
+
+ ConstraintInfoSeq get_all_constraints();
+
+ void remove_all_constraints();
+ void destroy();
+ boolean match (in any filterable_data)
+ raises (UnsupportedFilterableData);
+
+ boolean match_structured (in CosNotification::StructuredEvent filterable_data)
+ raises (UnsupportedFilterableData);
+
+ boolean match_typed (in CosNotification::PropertySeq filterable_data)
+ raises (UnsupportedFilterableData);
+
+ CallbackID attach_callback (in CosNotifyComm::NotifySubscribe callback);
+
+ void detach_callback (in CallbackID callback)
+ raises ( CallbackNotFound );
+
+ CallbackIDSeq get_callbacks();
+ }; // Filter
+
+ interface MappingFilter {
+ readonly attribute string constraint_grammar;
+
+ readonly attribute CORBA::TypeCode value_type;
+
+ readonly attribute any default_value;
+
+ MappingConstraintInfoSeq add_mapping_constraints (in MappingConstraintPairSeq pair_list)
+ raises (InvalidConstraint, InvalidValue);
+
+ void modify_mapping_constraints (in ConstraintIDSeq del_list,
+ in MappingConstraintInfoSeq modify_list)
+ raises (InvalidConstraint, InvalidValue, ConstraintNotFound);
+
+ MappingConstraintInfoSeq get_mapping_constraints (in ConstraintIDSeq id_list)
+ raises (ConstraintNotFound);
+
+ MappingConstraintInfoSeq get_all_mapping_constraints();
+
+ void remove_all_mapping_constraints();
+
+ void destroy();
+
+ boolean match (in any filterable_data, out any result_to_set)
+ raises (UnsupportedFilterableData);
+
+ boolean match_structured (in CosNotification::StructuredEvent filterable_data, out any result_to_set)
+ raises (UnsupportedFilterableData);
+
+ boolean match_typed (in CosNotification::PropertySeq filterable_data, out any result_to_set)
+ raises (UnsupportedFilterableData);
+ }; // MappingFilter
+
+
+ interface FilterFactory {
+
+ Filter create_filter (in string constraint_grammar)
+ raises (InvalidGrammar);
+
+ MappingFilter create_mapping_filter (in string constraint_grammar, in any default_value)
+ raises(InvalidGrammar);
+ }; // FilterFactory
+
+ typedef long FilterID;
+ typedef sequence<FilterID> FilterIDSeq;
+ exception FilterNotFound {};
+
+ interface FilterAdmin {
+ FilterID add_filter (in Filter new_filter);
+
+ void remove_filter (in FilterID filter)
+ raises (FilterNotFound);
+
+ Filter get_filter (in FilterID filter)
+ raises (FilterNotFound);
+
+ FilterIDSeq get_all_filters();
+
+ void remove_all_filters();
+ }; // FilterAdmin
+}; // CosNotifyFilter
+
+
+#endif /* ifndef _COS_NOTIFYFILTER_IDL_ */
+
diff --git a/lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl b/lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl
new file mode 100644
index 0000000000..9a7b431513
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl
@@ -0,0 +1,125 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : CosNotifyFilter_FilterFactory_impl.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module('CosNotifyFilter_FilterFactory_impl').
+
+
+%%--------------- INCLUDES -----------------------------------
+%% Application files
+-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").
+
+%%--------------- IMPORTS ------------------------------------
+
+%%--------------- EXPORTS ------------------------------------
+%% External
+-export([create_filter/3,
+ create_mapping_filter/4]).
+
+%%--------------- gen_server specific exports ----------------
+-export([handle_info/2, code_change/3]).
+-export([init/1, terminate/2]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {adminProp,
+ etsR,
+ options}).
+
+%%-----------------------------------------------------------%
+%% function : handle_info, code_change
+%% Arguments: See gen_server documentation.
+%% Effect : Functions demanded by the gen_server module.
+%%------------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+handle_info(_Info, State) ->
+ ?debug_print("INFO: ~p DATA: ~p~n", [State, _Info]),
+ {noreply, State}.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init(Options) ->
+ process_flag(trap_exit, true),
+ {ok, #state{options = Options}}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% function : create_filter
+%% Arguments: InitGrammar - string()
+%% Returns : CosNotifyFilter::Filter |
+%% {'EXCEPTION', InvalidGrammar}
+%%-----------------------------------------------------------
+create_filter(OE_THIS, State, InitGrammar) ->
+ case lists:member(InitGrammar, ?not_SupportedGrammars) of
+ true ->
+ SO = 'CosNotification_Common':get_option(server_options, State#state.options,
+ ?not_DEFAULT_SETTINGS),
+ Fi='CosNotifyFilter_Filter':oe_create_link([OE_THIS, self(),
+ InitGrammar],
+ SO),
+ {reply, Fi, State};
+ _ ->
+ corba:raise(#'CosNotifyFilter_InvalidGrammar'{})
+ end.
+
+%%----------------------------------------------------------%
+%% function : create_mapping_filter
+%% Arguments: InitGrammar - string()
+%% Returns : CosNotifyFilter::Filter |
+%% {'EXCEPTION', InvalidGrammar}
+%%-----------------------------------------------------------
+create_mapping_filter(OE_THIS, State, InitGrammar, DefVal) ->
+ case lists:member(InitGrammar, ?not_SupportedGrammars) of
+ true ->
+ SO = 'CosNotification_Common':get_option(server_options, State#state.options,
+ ?not_DEFAULT_SETTINGS),
+ Fi='CosNotifyFilter_MappingFilter':oe_create_link([OE_THIS, self(),
+ InitGrammar, DefVal],
+ SO),
+ {reply, Fi, State};
+ _ ->
+ corba:raise(#'CosNotifyFilter_InvalidGrammar'{})
+ end.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl b/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
new file mode 100644
index 0000000000..042e180170
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
@@ -0,0 +1,670 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : CosNotifyFilter_Filter_impl.erl
+%% Purpose :
+%% Note : For an event to be forwarded it's sufficient that at least
+%% one of the constraints return 'true'.
+%% ALL functions in this module are internal. May NOT be used
+%% externally in ANY WAY; only CosNotification system modules.
+%%----------------------------------------------------------------------
+
+-module('CosNotifyFilter_Filter_impl').
+
+%%--------------- INCLUDES -----------------------------------
+%% Application files
+-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").
+
+%%--------------- IMPORTS ------------------------------------
+
+%%--------------- EXPORTS ------------------------------------
+%% External Attributes
+-export(['_get_constraint_grammar'/2]).
+%% External Functions
+-export([add_constraints/3,
+ modify_constraints/4,
+ get_constraints/3,
+ get_all_constraints/2,
+ remove_all_constraints/2,
+ destroy/2,
+ match/3,
+ match_structured/3,
+ match_typed/3,
+ attach_callback/3,
+ detach_callback/3,
+ get_callbacks/2]).
+
+%%--------------- gen_server specific exports ----------------
+-export([handle_info/2, code_change/3]).
+-export([init/1, terminate/2]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%%######### MISC ##########
+-define(create_ConstraintInfo(_Types, _Con, _ID),
+ #'CosNotifyFilter_ConstraintInfo'{
+ constraint_expression =
+ #'CosNotifyFilter_ConstraintExp'{
+ event_types = _Types,
+ constraint_expr = _Con},
+ constraint_id = _ID
+ }).
+
+%%#### Data structures ####
+-record(state, {constraint_grammar,
+ constraints = [],
+ filters = [],
+ callbacks = [],
+ idCounter = 0,
+ filterFactory,
+ factoryPid,
+ etsR}).
+
+%% Data structures constructors
+-define(get_InitState(Fac, Pid, Gr),
+ #state{constraint_grammar=Gr,
+ filterFactory=Fac,
+ factoryPid=Pid,
+ etsR = ets:new(oe_ets, [bag, protected])}).
+
+%%------------------- Data structures selectors -------------------
+%% Grammar
+-define(get_Grammar(S), S#state.constraint_grammar).
+%% Callbacks
+% Left out for now to avoid dialyzer warning.
+%-define(get_Callback(S,I), find_obj(lists:keysearch(I, 1, S#state.callbacks),
+% callback)).
+-define(get_AllCallback(S), lists:map(fun({_V, C}) -> C end,
+ S#state.callbacks)).
+-define(get_AllCallbackID(S), lists:map(fun({V, _C}) -> V end,
+ S#state.callbacks)).
+%% ID:s
+-define(get_IdCounter(S), S#state.idCounter).
+
+%% Constraints
+-define(get_Constraint(S,I), find_obj(lists:keysearch(I, 1, S#state.constraints),
+ constraint)).
+-define(get_AllConstraints(S), lists:map(fun({I, C, _W, _WC, _K, T}) ->
+ ?create_ConstraintInfo(T, C, I)
+ end,
+ S#state.constraints)).
+-define(get_ConstraintAllData(S), S#state.constraints).
+-define(get_ConstraintData(S,I), lists:keysearch(I, 1, S#state.constraints)).
+-define(match_Type(S,I,ET), ets:lookup(S#state.etsR, {I, ET})).
+%% Parse Tree
+-define(get_ParseTree(S,K), find_obj(ets:lookup(S#state.etsR, K), tree)).
+
+%%------------------- Data structures modifiers -------------------
+%% Callbacks
+-define(del_Callback(S,I), S#state{callbacks =
+ delete_obj(lists:keydelete(I,1,
+ S#state.callbacks),
+ S#state.callbacks, callback)}).
+-define(del_AllCallbacks(S), S#state{callbacks=[]}).
+-define(add_Callback(S,V,C), S#state{idCounter=V,
+ callbacks = [{V,C}|S#state.callbacks]}).
+%% ID:s
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+
+%% Constraints
+-define(del_Constraint(S, I), match_delete(S, S#state.constraints, I)).
+-define(del_AllConstraints(S), clear_DB(S)).
+-define(add_Constraint(S,I,C,W,_WC,K,T), S#state{constraints =
+ [{I, C, W, _WC, K, T}|S#state.constraints]}).
+-define(set_Constraints(S,C), S#state{constraints = C}).
+
+-define(del_AllTypes(S), ets:match_delete(S#state.etsR, {'_','_',types})).
+-define(del_Type(S,I), ets:match_delete(S#state.etsR, {{I, '_'}, '_', types})).
+-define(add_Type(S,I,ET,K), ets:insert(S#state.etsR, {{I, ET}, K, types})).
+
+%% Parse Tree
+-define(add_ParseTree(S,K,T), ets:insert(S#state.etsR, {K, T, tree})).
+-define(del_ParseTree(S,K), ets:delete(S#state.etsR, K)).
+-define(del_AllParseTress(S), ets:match_delete(S#state.etsR, {'_','_',tree})).
+
+%%------------------- MISC ----------------------------------------
+-define(is_EmptyFilter(S), S#state.constraints==[]).
+
+-define(InfoSeq2EventTypeSeq(L), lists:flatten(
+ lists:map(fun(#'CosNotifyFilter_ConstraintInfo'
+ {constraint_expression=
+ #'CosNotifyFilter_ConstraintExp'
+ {event_types = ET}}) ->
+ ET
+ end,
+ L))).
+
+%%-----------------------------------------------------------%
+%% Function : handle_info, code_change
+%% Arguments: See gen_server documentation.
+%% Effect : Functions demanded by the gen_server module.
+%%------------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+handle_info(Info, State) ->
+ ?debug_print("INFO: ~p DATA: ~p~n", [State, Info]),
+ case Info of
+ {'EXIT', _Pid, _Reason} ->
+ {noreply, State};
+ _ ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% Function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([FiFac, FacPid, ConstraintGr]) ->
+ process_flag(trap_exit, true),
+ {ok, ?get_InitState(FiFac, FacPid, ConstraintGr)}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------
+%%------- Exported external attributes ----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Function : '_get_constraint_grammar'/2
+%% Type : readonly
+%% Returns : Grammar - string()
+%%-----------------------------------------------------------
+'_get_constraint_grammar'(_OE_THIS, State) ->
+ {reply, ?get_Grammar(State), State}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Function : add_constraints/3
+%% Arguments: CL - CosNotifyFilter::ConstraintExpSeq
+%% Returns : CosNotifyFilter::ConstraintInfoSeq |
+%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint}
+%%-----------------------------------------------------------
+add_constraints(_OE_THIS, State, CL) ->
+ {NewState, Filters, Info, EventTSeq} = try_create_filters(State, CL),
+ NewState2=store_filters(NewState, Filters),
+ inform_callbacks(?get_AllCallback(NewState2), EventTSeq, []),
+ {reply, Info, NewState2}.
+
+%%----------------------------------------------------------%
+%% Function : modify_constraints/4
+%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
+%% AddConstraintInfoSeq - CosNotifyFilter::ConstraintInfoSeq
+%% Returns : ok |
+%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
+%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
+%%-----------------------------------------------------------
+%% The OMG specification (TC Document telecom/98-11-01, chapter
+%% 3.2.1.3) states (concerning IDs):
+%%
+%% "If all input values supplied within a particular invocation
+%% of this operation are valid, then the specific constraints
+%% identified by the values contained in the first input parameter
+%% will be deleted from the list of those encapsulated by the target
+%% filter object."
+%%
+%% Hence, first we must check if all ID's exists before deleting.
+modify_constraints(_OE_THIS, State, IDs, AddConstraintInfoSeq) ->
+ %% The following functions are 'safe', i.e., they do not alter any data.
+ RemoveConstraintInfoSeq = lookup_constraints(IDs, State),
+ lookup_constraints(AddConstraintInfoSeq, State),
+ {NewState, Filters, _Info, AddedEventTSeq} =
+ try_create_filters(State, AddConstraintInfoSeq),
+ RemovedEventTSeq = ?InfoSeq2EventTypeSeq(RemoveConstraintInfoSeq),
+
+ %% We cannot change anything before our checks (see above). Hence,
+ %% do NOT move the following lines above this point.
+ NewState2 = delete_constraints(IDs, NewState),
+
+%% The OMG specification (TC Document telecom/98-11-01, chapter
+%% 3.2.1.3) states (concerning AddConstraintInfoSeq):
+%%
+%% "If all input values supplied within a particular invocation of this
+%% operation are valid, then the constraint expression associated with the
+%% already encapsulated constraint identified by the numeric value contained
+%% within each element of the input sequence will be modified to the new
+%% constraint expression that is contained within the same sequence element."
+%%
+%% This, our interpretation, implies that ALL previous data related
+%% to each unique ID should be removed and replaced by the new data.
+
+ NewState3 = delete_constraints(AddConstraintInfoSeq, NewState2),
+ NewState4 = store_filters(NewState3, Filters),
+ inform_callbacks(?get_AllCallback(NewState4),
+ AddedEventTSeq, RemovedEventTSeq),
+ {reply, ok, NewState4}.
+
+%%----------------------------------------------------------%
+%% Function : get_constraints/3
+%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
+%% Returns : CosNotifyFilter::ConstraintInfoSeq |
+%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
+%%-----------------------------------------------------------
+get_constraints(_OE_THIS, State, IDs) ->
+ {reply, lookup_constraints(IDs, State), State}.
+
+%%----------------------------------------------------------%
+%% Function : get_all_constraints/2
+%% Arguments: -
+%% Returns : CosNotifyFilter::ConstraintInfoSeq
+%%-----------------------------------------------------------
+get_all_constraints(_OE_THIS, State) ->
+ {reply, ?get_AllConstraints(State), State}.
+
+%%----------------------------------------------------------%
+%% Function : remove_all_constraints/2
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_constraints(_OE_THIS, State) ->
+ {reply, ok, ?del_AllConstraints(State)}.
+
+%%----------------------------------------------------------%
+%% Function : destroy/2
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+destroy(_OE_THIS, State) ->
+ {stop, normal, ok, State}.
+
+%%----------------------------------------------------------%
+%% Function : match/3
+%% Arguments: Event - #any{}
+%% Returns : boolean() |
+%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
+%%-----------------------------------------------------------
+
+match(_OE_THIS, State, Event) when is_record(Event,'any'), ?is_EmptyFilter(State) ->
+ {reply, true, State};
+match(_OE_THIS, State, Event) when is_record(Event,'any') ->
+ match_any_event(State, Event, ?get_ConstraintAllData(State));
+match(_,_,What) ->
+ orber:dbg("[~p] CosNotifyFilter_Filter:match(~p);~n"
+ "Not an CORBA::Any", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% Function : match_structured/3
+%% Arguments: Event - CosNotification::StructuredEvent
+%% Returns : boolean() |
+%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
+%%-----------------------------------------------------------
+match_structured(_OE_THIS, State, Event) when
+ is_record(Event,'CosNotification_StructuredEvent') andalso ?is_EmptyFilter(State) ->
+ {reply, true, State};
+match_structured(_OE_THIS, State, Event) when
+ is_record(Event,'CosNotification_StructuredEvent') ->
+ match_str_event(State, Event, ?get_ConstraintAllData(State));
+match_structured(_,_,What) ->
+ orber:dbg("[~p] CosNotifyFilter_Filter:match_structured(~p);~n"
+ "Not a StructuredEvent", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------*
+%% Function : match_typed/3
+%% Arguments: Data - CosNotification::PropertySeq
+%% Returns : boolean() |
+%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
+%%-----------------------------------------------------------
+match_typed(_OE_THIS, _State, _Data) ->
+ corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% Function : attach_callback/3
+%% Arguments: CB - CosNotifyComm::NotifySubscribe
+%% Returns : ID - CosNotifyFilter::CallbackID
+%%-----------------------------------------------------------
+attach_callback(_OE_THIS, State, CB) ->
+ 'CosNotification_Common':type_check(CB, 'CosNotifyComm_NotifySubscribe'),
+ CBID = ?new_Id(State),
+ {reply, CBID, ?add_Callback(State, CBID, CB)}.
+
+%%----------------------------------------------------------%
+%% Function : detach_callback/3
+%% Arguments: ID - CosNotifyFilter::CallbackID
+%% Returns : ok | {'EXCEPTION', CosNotifyFilter::CallbackNotFound}
+%%-----------------------------------------------------------
+detach_callback(_OE_THIS, State, ID) when is_integer(ID) ->
+ {reply, ok, ?del_Callback(State, ID)};
+detach_callback(_,_,What) ->
+ orber:dbg("[~p] CosNotifyFilter_Filter:detach_callback(~p);~n"
+ "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% Function : get_callbacks/2
+%% Arguments: -
+%% Returns : CosNotifyFilter::CallbackIDSeq
+%%-----------------------------------------------------------
+get_callbacks(_OE_THIS, State) ->
+ {reply, ?get_AllCallbackID(State), State}.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+%% To match callbacks
+find_obj({value, {_, Obj}},_) -> Obj;
+%% To match constraints
+find_obj({value, {Id, Con, _, _, _, Types}}, _) ->
+ ?create_ConstraintInfo(Types, Con, Id);
+find_obj([{_, Tree, tree}|_], tree) -> Tree;
+% Left out for now to avoid dialyzer warning.
+%find_obj(_,callback) -> {'EXCEPTION', #'CosNotifyFilter_CallbackNotFound'{}};
+find_obj(_,tree) -> undefined;
+find_obj(_,constraint) -> error.
+
+%% Delete a single object.
+delete_obj(List,List,callback) -> corba:raise(#'CosNotifyFilter_CallbackNotFound'{});
+delete_obj(List,_,_) -> List.
+
+%% Delete given object from list and all related objects in DB (parse tree and types).
+match_delete(State, Constraints, ID) ->
+ match_delete(State, Constraints, ID, []).
+match_delete(_, [], _, _) ->
+ error;
+match_delete(State, [{ID, _Con, _Which, _WC, Key, _Types}|T], ID, Acc) ->
+ ?del_Type(State, ID),
+ ?del_ParseTree(State, Key),
+ {ok, ?set_Constraints(State, Acc++T)};
+match_delete(State, [H|T], ID, Acc) ->
+ match_delete(State, T, ID, [H|Acc]).
+
+%% Remove all data related with constraints; for now, since no other data
+%% stored in DB, we do in a rather brutal way.
+clear_DB(State) ->
+ catch ets:delete(State#state.etsR),
+ State#state{etsR = ets:new(oe_ets, [bag, protected]), constraints=[]}.
+
+%% Given a list of Constrain IDs we want to find the related constraints.
+%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
+lookup_constraints(IDs, State) ->
+ lookup_constraints(IDs, State, []).
+lookup_constraints([], _State, Accum) ->
+ Accum;
+lookup_constraints([H|T], State, Accum)
+ when is_record(H, 'CosNotifyFilter_ConstraintInfo') ->
+ case ?get_Constraint(State, H#'CosNotifyFilter_ConstraintInfo'.constraint_id) of
+ error ->
+ corba:raise(#'CosNotifyFilter_ConstraintNotFound'
+ {id = H#'CosNotifyFilter_ConstraintInfo'.constraint_id});
+ _Con ->
+ %% We don't need to collect the result since the input already is of
+ %% the correct type, i.e., ConstraintInfoSeq
+ lookup_constraints(T, State, Accum)
+ end;
+lookup_constraints([H|T], State, Accum) when is_integer(H) ->
+ case ?get_Constraint(State,H) of
+ error ->
+ corba:raise(#'CosNotifyFilter_ConstraintNotFound'{id=H});
+ Con ->
+ lookup_constraints(T, State, [Con|Accum])
+ end;
+lookup_constraints(_, _, _) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%% Given a list of Constrain IDs we want to delet the related constraints.
+%% We need also to return the ConstraintInfoSeq described related to the
+%% given ID's.
+delete_constraints([], State) ->
+ State;
+delete_constraints([H|T], State)
+ when is_record(H, 'CosNotifyFilter_ConstraintInfo') ->
+ case catch ?del_Constraint(State,
+ H#'CosNotifyFilter_ConstraintInfo'.constraint_id) of
+ {ok, NewState} ->
+ delete_constraints(T, NewState);
+ Reason ->
+ orber:dbg("[~p] 'CosNotifyFilter_Filter':modify_constraints().~n"
+ "Unable to remove: ~p~n"
+ "Reason: ~p~n",
+ [?LINE, H, Reason], ?DEBUG_LEVEL),
+ delete_constraints(T, State)
+ end;
+delete_constraints([H|T], State) ->
+ case catch ?del_Constraint(State,H) of
+ {ok, NewState} ->
+ delete_constraints(T, NewState);
+ Reason ->
+ orber:dbg("[~p] 'CosNotifyFilter_Filter':modify_constraints().~n"
+ "Unable to remove: ~p~n"
+ "Reason: ~p~n",
+ [?LINE, H, Reason], ?DEBUG_LEVEL),
+ delete_constraints(T, State)
+ end.
+
+%% Inform all registered callbacks that the constraints have changed.
+%% Added and Removed must be a CosNotification::EventTypeSeq
+inform_callbacks([],_,_) ->
+ ok;
+inform_callbacks([H|T], Added, Removed) ->
+ case catch 'CosNotifyComm_NotifySubscribe':subscription_change(H, Added, Removed) of
+ ok ->
+ ?debug_print("INFORMED CALLBACK: ~p ADDED: ~p REMOVED: ~p",
+ [H, Added, Removed]),
+ inform_callbacks(T, Added, Removed);
+ Other ->
+ orber:dbg("[~p] 'CosNotifyComm_NotifySubscribe':subscription_change().~n"
+ "Unable to inform callback: ~p~n"
+ "Reason: ~p~n",
+ [?LINE, H, Other], ?DEBUG_LEVEL),
+ inform_callbacks(T, Added, Removed)
+ end.
+
+%%-----------------------------------------------------------
+%% Function : try_create_filters/2
+%% Arguments: CL - #'CosNotifyFilter_ConstraintExp'{
+%% event_types = [#'CosNotification_EventType'{
+%% domain_name = Str, type_name = Str}]
+%% constraint_expr = Str}
+%% Returns : {State, AccumList}
+%%-----------------------------------------------------------
+%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
+try_create_filters(State, CL) ->
+ try_create_filters(State, CL, [], [], []).
+try_create_filters(State, [], Accum, InfoSeq, EventTSeq) ->
+ {State, Accum, InfoSeq, EventTSeq};
+try_create_filters(State, [#'CosNotifyFilter_ConstraintExp'{event_types = Types,
+ constraint_expr = Con}|T],
+ Accum, InfoSeq, EventTSeq) ->
+ case catch cosNotification_Filter:create_filter(Con) of
+ {ok, Tree} ->
+ case catch cosNotification_Filter:check_types(Types) of
+ true ->
+ ID = ?new_Id(State),
+ Key = ?not_CreateDBKey,
+ NewETSeq = Types ++ EventTSeq,
+ try_create_filters(?set_IdCounter(State, ID), T,
+ [{ID, true, [], Key, Types, Con, Tree}|Accum],
+ [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
+ NewETSeq);
+ {ok, Which, WC} ->
+ ID = ?new_Id(State),
+ Key = ?not_CreateDBKey,
+ NewETSeq = Types ++ EventTSeq,
+ try_create_filters(?set_IdCounter(State, ID), T,
+ [{ID, Which, WC, Key, Types, Con, Tree}|Accum],
+ [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
+ NewETSeq);
+ _ ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+ _ ->
+ corba:raise(#'CosNotifyFilter_InvalidConstraint'
+ {constr = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con}})
+ end;
+try_create_filters(State, [#'CosNotifyFilter_ConstraintInfo'
+ {constraint_expression = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con},
+ constraint_id=ID}|T], Accum, InfoSeq, EventTSeq) ->
+ case catch cosNotification_Filter:create_filter(Con) of
+ {ok, Tree} ->
+ case catch cosNotification_Filter:check_types(Types) of
+ true ->
+ Key = ?not_CreateDBKey,
+ NewETSeq = Types ++ EventTSeq,
+ try_create_filters(State, T,
+ [{ID, true, [], Key, Types, Con, Tree}|Accum],
+ [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
+ NewETSeq);
+ {ok, Which, WC} ->
+ Key = ?not_CreateDBKey,
+ NewETSeq = Types ++ EventTSeq,
+ try_create_filters(State, T,
+ [{ID, Which, WC, Key, Types, Con, Tree}|Accum],
+ [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
+ NewETSeq);
+ _ ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+ _ ->
+ corba:raise(#'CosNotifyFilter_InvalidConstraint'
+ {constr = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con}})
+ end;
+try_create_filters(_,_,_,_,_) ->
+ %% The list contained something else but ConstraintExp.
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%-----------------------------------------------------------
+%% Function : store_filters/4
+%% Arguments: Filters - a list of filters.
+%% Returns :
+%%-----------------------------------------------------------
+
+store_filters(State, []) ->
+ State;
+store_filters(State, [{ID, Which, WC, Key, Types, Con, Tree}|T]) ->
+ ?add_ParseTree(State, Key, Tree),
+ write_types(State, Types, ID, Key),
+ store_filters(?add_Constraint(State, ID, Con, Which, WC, Key, Types), T).
+
+
+write_types(_State, [],_, _) ->
+ ok;
+write_types(State, [EventType|T], ID, Key) ->
+ ?add_Type(State, ID, EventType, Key),
+ ?debug_print("FILTER: ~p ~p ~p~n", [ID, Key, EventType]),
+ write_types(State, T, ID, Key).
+
+%%-----------------------------------------------------------
+%% Function : match_any_event
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+match_any_event(State, _Event, []) ->
+ ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
+ {reply, false, State};
+match_any_event(State, Event, [{_, _, _, _, Key, _}|T]) ->
+ case catch cosNotification_Filter:eval(?get_ParseTree(State,Key), Event) of
+ true ->
+ ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
+ {reply, true, State};
+ _ ->
+ match_any_event(State, Event, T)
+ end.
+
+
+%%-----------------------------------------------------------
+%% Function : match_str_event
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+
+match_str_event(State, _Event, []) ->
+ ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
+ {reply, false, State};
+match_str_event(State, Event, [{ID, _Con, Which, WC, Key, _Types}|T]) ->
+ ET = ((Event#'CosNotification_StructuredEvent'.header)
+ #'CosNotification_EventHeader'.fixed_header)
+ #'CosNotification_FixedEventHeader'.event_type,
+ CheckList =
+ case Which of
+ both ->
+ [ET];
+ domain ->
+ [ET,
+ ET#'CosNotification_EventType'{type_name=""},
+ ET#'CosNotification_EventType'{type_name="*"}];
+ type ->
+ [ET,
+ ET#'CosNotification_EventType'{domain_name=""},
+ ET#'CosNotification_EventType'{domain_name="*"}];
+ _ ->
+ [ET,
+ ET#'CosNotification_EventType'{type_name=""},
+ ET#'CosNotification_EventType'{type_name="*"},
+ ET#'CosNotification_EventType'{domain_name=""},
+ ET#'CosNotification_EventType'{domain_name="*"}]
+ end,
+ case check_DB(State, ID, CheckList) of
+ false ->
+ %% No match, may have used wildcards, e.g., "dom*".
+ case catch cosNotification_Filter:match_types(
+ ET#'CosNotification_EventType'.domain_name,
+ ET#'CosNotification_EventType'.type_name,
+ WC) of
+ true ->
+ case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
+ Event) of
+ true ->
+ ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
+ {reply, true, State};
+ _ ->
+ match_str_event(State, Event, T)
+ end;
+ _->
+ match_str_event(State, Event, T)
+ end;
+ Key ->
+ case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
+ Event) of
+ true ->
+ ?debug_print("FILTER APPROVED: ~p~n", [Event]),
+ {reply, true, State};
+ _ ->
+ match_str_event(State, Event, T)
+ end
+ end.
+
+check_DB(_, _, []) ->
+ false;
+check_DB(State, ID, [H|T]) ->
+ case ?match_Type(State, ID, H) of
+ [] ->
+ check_DB(State, ID, T);
+ [{_, K, types}|_] ->
+ K
+ end.
+
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
+
diff --git a/lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl b/lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl
new file mode 100644
index 0000000000..f9103001f1
--- /dev/null
+++ b/lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl
@@ -0,0 +1,578 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : CosNotifyFilter_MappingFilter_impl.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module('CosNotifyFilter_MappingFilter_impl').
+
+%%--------------- INCLUDES -----------------------------------
+%% Application files
+-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").
+
+%%--------------- IMPORTS ------------------------------------
+
+%%--------------- EXPORTS ------------------------------------
+%% External Attributes
+-export(['_get_constraint_grammar'/2,
+ '_get_value_type'/2,
+ '_get_default_value'/2]).
+%% External Functions
+-export([add_mapping_constraints/3,
+ modify_mapping_constraints/4,
+ get_mapping_constraints/3,
+ get_all_mapping_constraints/2,
+ remove_all_mapping_constraints/2,
+ destroy/2,
+ match/3,
+ match_structured/3,
+ match_typed/3]).
+
+%%--------------- gen_server specific exports ----------------
+-export([handle_info/2, code_change/3]).
+-export([init/1, terminate/2]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%%######### MISC ##########
+-define(create_MappingInfo(_Types, _Con, _ID, _A),
+ #'CosNotifyFilter_MappingConstraintInfo'{
+ constraint_expression =
+ #'CosNotifyFilter_ConstraintExp'{
+ event_types = _Types,
+ constraint_expr = _Con},
+ constraint_id = _ID,
+ value = _A
+ }).
+%%#### Data structures ####
+-record(state, {constraint_grammar,
+ value,
+ typeC,
+ constraints = [],
+ filters = [],
+ idCounter = 0,
+ filterFactory,
+ factoryPid,
+ etsR}).
+
+%% Data structures constructors
+-define(get_InitState(Gr, DVal, FF, FP),
+ #state{constraint_grammar=Gr,
+ value = DVal,
+ typeC = any:get_typecode(DVal),
+ filterFactory = FF,
+ factoryPid = FP,
+ etsR = ets:new(oe_ets, [bag, protected])}).
+
+%%------------------- Data structures selectors -------------------
+%% Attributes
+-define(get_Grammar(S), S#state.constraint_grammar).
+-define(get_DefVal(S), S#state.value).
+-define(get_DefTC(S), S#state.typeC).
+-define(get_DefAny(S), S#state.value).
+
+%% ID:s
+-define(get_IdCounter(S), S#state.idCounter).
+
+%% Constraints
+-define(get_Constraint(S,I), find_obj(lists:keysearch(I, 1, S#state.constraints),
+ constraint)).
+-define(get_AllConstraints(S), lists:map(fun({I, C, _W, _WC, _K, T, A}) ->
+ ?create_MappingInfo(T, C, I, A)
+ end,
+ S#state.constraints)).
+-define(get_ConstraintAllData(S), S#state.constraints).
+-define(get_ConstraintData(S,I), lists:keysearch(I, 1, S#state.constraints)).
+-define(match_Type(S,I,ET), ets:lookup(S#state.etsR, {I, ET})).
+%% Parse Tree
+-define(get_ParseTree(S,K), find_obj(ets:lookup(S#state.etsR, K), tree)).
+
+%%------------------- Data structures modifiers -------------------
+%% ID:s
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+
+%% Constraints
+-define(del_Constraint(S, I), match_delete(S, S#state.constraints, I)).
+-define(del_AllConstraints(S), clear_DB(S)).
+-define(add_Constraint(S,I,C,W,_WC,K,T,A), S#state{constraints =
+ [{I, C, W, _WC, K, T, A}|S#state.constraints]}).
+-define(set_Constraints(S,C), S#state{constraints = C}).
+
+-define(del_AllTypes(S), ets:match_delete(S#state.etsR, {'_','_',types})).
+-define(del_Type(S,I), ets:match_delete(S#state.etsR, {{I, '_'}, '_', types})).
+-define(add_Type(S,I,ET,K), ets:insert(S#state.etsR, {{I, ET}, K, types})).
+
+%% Parse Tree
+-define(add_ParseTree(S,K,T), ets:insert(S#state.etsR, {K, T, tree})).
+-define(del_ParseTree(S,K), ets:delete(S#state.etsR, K)).
+-define(del_AllParseTress(S), ets:match_delete(S#state.etsR, {'_','_',tree})).
+
+%%------------------- MISC ----------------------------------------
+-define(is_EmptyFilter(S), S#state.constraints==[]).
+-define(is_EqualType(S,T), S#state.typeC==any:get_typecode(T)).
+
+%%-----------------------------------------------------------%
+%% function : handle_info, code_change
+%% Arguments: See gen_server documentation.
+%% Effect : Functions demanded by the gen_server module.
+%%------------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+handle_info(Info, State) ->
+ ?debug_print("INFO: ~p DATA: ~p~n", [State, Info]),
+ case Info of
+ {'EXIT', _Pid, _Reason} ->
+ {noreply, State};
+ _ ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([FiFac, FacPid, InitGr, DefVal]) ->
+ process_flag(trap_exit, true),
+ {ok, ?get_InitState(InitGr, DefVal, FiFac, FacPid)}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%-----------------------------------------------------------
+%%------- Exported external attributes ----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Function : '_get_constraint_grammar'/2
+%% Type : readonly
+%% Returns : string()
+%%-----------------------------------------------------------
+'_get_constraint_grammar'(_OE_THIS, State) ->
+ {reply, ?get_Grammar(State), State}.
+%%----------------------------------------------------------%
+%% Function : '_get_value_type'/2
+%% Type : readonly
+%% Returns : CORBA::TypeCode
+%%-----------------------------------------------------------
+'_get_value_type'(_OE_THIS, State) ->
+ {reply, ?get_DefTC(State), State}.
+%%----------------------------------------------------------%
+%% Function : '_get_default_value'/2
+%% Type : readonly
+%% Returns : #any{}
+%%-----------------------------------------------------------
+'_get_default_value'(_OE_THIS, State) ->
+ {reply, ?get_DefVal(State), State}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Function : add_mapping_constraints/3
+%% Arguments: Pairs - CosNotifyFilter::MappingConstraintPairSeq
+%% Returns : CosNotifyFilter::MappingConstraintInfoSeq |
+%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
+%% {'EXCEPTION', CosNotifyFilter::InvalidValue}
+%%-----------------------------------------------------------
+add_mapping_constraints(_OE_THIS, State, Pairs) ->
+ {NewState, Filters, Info} = try_create_filters(State, Pairs),
+ NewState2=store_filters(NewState, Filters),
+ {reply, Info, NewState2}.
+
+%%----------------------------------------------------------%
+%% Function : modify_mapping_constraints/4
+%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
+%% Info - CosNotifyFilter::MappingConstraintInfoSeq
+%% Returns : ok |
+%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
+%% {'EXCEPTION', CosNotifyFilter::InvalidValue} |
+%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
+%%-----------------------------------------------------------
+modify_mapping_constraints(_OE_THIS, State, IDs, InfoSeq) ->
+ lookup_constraints(IDs, State),
+ lookup_constraints(InfoSeq, State),
+ {NewState, Filters, _Info} = try_create_filters(State, InfoSeq),
+
+ %% We cannot change anything before our checks (see above). Hence,
+ %% do NOT move the following lines above this point.
+
+ NewState2 = delete_constraints(IDs, NewState),
+ NewState3 = delete_constraints(InfoSeq, NewState2),
+ NewState4 = store_filters(NewState3, Filters),
+ {reply, ok, NewState4}.
+
+%%----------------------------------------------------------%
+%% Function : get_mapping_constraints/3
+%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
+%% Returns : CosNotifyFilter::MappingConstraintInfoSeq |
+%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
+%%-----------------------------------------------------------
+get_mapping_constraints(_OE_THIS, State, IDs) ->
+ {reply, lookup_constraints(IDs, State), State}.
+
+%%----------------------------------------------------------%
+%% Function : get_all_mapping_constraints/2
+%% Arguments: -
+%% Returns : CosNotifyFilter::MappingConstraintInfoSeq
+%%-----------------------------------------------------------
+get_all_mapping_constraints(_OE_THIS, State) ->
+ {reply, ?get_AllConstraints(State), State}.
+
+%%----------------------------------------------------------%
+%% Function : remove_all_mapping_constraints/2
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_mapping_constraints(_OE_THIS, State) ->
+ {reply, ok, ?del_AllConstraints(State)}.
+
+%%----------------------------------------------------------%
+%% Function : destroy/2
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+destroy(_OE_THIS, State) ->
+ {stop, normal, ok, State}.
+
+%%----------------------------------------------------------%
+%% Function : match/3
+%% Arguments: Event - #any{}
+%% Returns : boolean(), #any{} (out-type) |
+%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
+%%-----------------------------------------------------------
+match(_OE_THIS, State, Event) when is_record(Event,'any') andalso ?is_EmptyFilter(State) ->
+ {reply, {false, ?get_DefAny(State)}, State};
+match(_OE_THIS, State, Event) when is_record(Event,'any') ->
+ match_any_event(State, Event, ?get_ConstraintAllData(State));
+match(_,_,_) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+
+%%----------------------------------------------------------%
+%% Function : match_structured/3
+%% Arguments: Event - CosNotification::StructuredEvent
+%% Returns : boolean(), #any{} (out-type) |
+%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
+%%-----------------------------------------------------------
+match_structured(_OE_THIS, State, Event) when
+ is_record(Event,'CosNotification_StructuredEvent') andalso ?is_EmptyFilter(State) ->
+ {reply, {false, ?get_DefAny(State)}, State};
+match_structured(_OE_THIS, State, Event) when
+ is_record(Event,'CosNotification_StructuredEvent') ->
+ match_str_event(State, Event, ?get_ConstraintAllData(State));
+match_structured(_,_,_) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------*
+%% Function : match_typed/3
+%% Arguments: Data - CosNotification::PropertySeq
+%% Returns : boolean() , #any{} (out-type) |
+%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
+%%-----------------------------------------------------------
+match_typed(_OE_THIS, _State, _Data) ->
+ corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+%% To match constraints
+find_obj({value, {Id, Con, _, _, _, Types, Any}}, _) ->
+ ?create_MappingInfo(Types, Con, Id, Any);
+find_obj([{_, Tree, tree}|_], tree) -> Tree;
+find_obj(_,tree) -> undefined;
+find_obj(_,constraint) -> error.
+
+%% Delete given object from list and all related objects in DB (parse tree and types).
+match_delete(State, Constraints, ID) ->
+ match_delete(State, Constraints, ID, []).
+match_delete(_, [], _, _) ->
+ error;
+match_delete(State, [{ID, _Con, _Which, _WC, Key, _Types, _Any}|T], ID, Acc) ->
+ ?del_Type(State, ID),
+ ?del_ParseTree(State, Key),
+ {ok, ?set_Constraints(State, Acc++T)};
+match_delete(State, [H|T], ID, Acc) ->
+ match_delete(State, T, ID, [H|Acc]).
+
+%% Remove all data related with constraints; for now, since no other data
+%% stored in DB, we do in a rather brutal way.
+clear_DB(State) ->
+ catch ets:delete(State#state.etsR),
+ State#state{etsR = ets:new(oe_ets, [bag, protected]), constraints=[]}.
+
+%% Given a list of Constrain IDs we want to find the related constraints.
+%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
+lookup_constraints(IDs, State) ->
+ lookup_constraints(IDs, State, []).
+lookup_constraints([], _State, Accum) ->
+ Accum;
+lookup_constraints([H|T], State, Accum)
+ when is_record(H, 'CosNotifyFilter_MappingConstraintInfo') ->
+ case ?get_Constraint(State, H#'CosNotifyFilter_MappingConstraintInfo'.constraint_id) of
+ error ->
+ corba:raise(#'CosNotifyFilter_ConstraintNotFound'
+ {id = H#'CosNotifyFilter_MappingConstraintInfo'.constraint_id});
+ _Con ->
+ %% We don't need to collect the result since the input already is of
+ %% the correct type, i.e., ConstraintInfoSeq
+ lookup_constraints(T, State, Accum)
+ end;
+lookup_constraints([H|T], State, Accum) when is_integer(H) ->
+ case ?get_Constraint(State,H) of
+ error ->
+ corba:raise(#'CosNotifyFilter_ConstraintNotFound'{id=H});
+ Con ->
+ lookup_constraints(T, State, [Con|Accum])
+ end;
+lookup_constraints(_, _, _) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%% Given a list of Constrain IDs we want to delet the related constraints.
+%% We need also to return the ConstraintInfoSeq described related to the
+%% given ID's.
+delete_constraints([], State) ->
+ State;
+delete_constraints([H|T], State)
+ when is_record(H, 'CosNotifyFilter_MappingConstraintInfo') ->
+ case catch ?del_Constraint(State,
+ H#'CosNotifyFilter_MappingConstraintInfo'.constraint_id) of
+ {ok, NewState} ->
+ delete_constraints(T, NewState);
+ Reason ->
+ orber:dbg("[~p] 'CosNotifyFilter_MappingFilter':modify_mapping_constraints().~n"
+ "Unable to remove: ~p~n"
+ "Reason: ~p~n",
+ [?LINE, H, Reason], ?DEBUG_LEVEL),
+ delete_constraints(T, State)
+ end;
+delete_constraints([H|T], State) ->
+ case catch ?del_Constraint(State,H) of
+ {ok, NewState} ->
+ delete_constraints(T, NewState);
+ Reason ->
+ orber:dbg("[~p] 'CosNotifyFilter_MappingFilter':modify_mapping_constraints().~n"
+ "Unable to remove: ~p~n"
+ "Reason: ~p~n",
+ [?LINE, H, Reason], ?DEBUG_LEVEL),
+ delete_constraints(T, State)
+ end.
+
+%%-----------------------------------------------------------
+%% Function : try_create_filters/2
+%% Arguments: CL - #'CosNotifyFilter_MappingConstraintPair{
+%% constraint_expression =
+%% #'CosNotifyFilter_ConstraintExp'{
+%% event_types =
+%% [#'CosNotification_EventType'{
+%% domain_name = Str, type_name = Str}]
+%% constraint_expr = Str},
+%% result_to_set = Any}
+%% Returns : {State, AccumList}
+%%-----------------------------------------------------------
+%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
+try_create_filters(State, CL) ->
+ try_create_filters(State, CL, [], []).
+try_create_filters(State, [], Accum, InfoSeq) ->
+ {State, Accum, InfoSeq};
+try_create_filters(State, [#'CosNotifyFilter_MappingConstraintPair'
+ {constraint_expression =
+ #'CosNotifyFilter_ConstraintExp'{event_types = Types,
+ constraint_expr = Con},
+ result_to_set=Any}|T], Accum, InfoSeq) ->
+ case catch {?is_EqualType(State,Any), cosNotification_Filter:create_filter(Con)} of
+ {false, _} ->
+ corba:raise(#'CosNotifyFilter_InvalidValue'
+ {constr = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con},
+ value=Any});
+ {_, {ok, Tree}} ->
+ case catch cosNotification_Filter:check_types(Types) of
+ true ->
+ ID = ?new_Id(State),
+ Key = ?not_CreateDBKey,
+ try_create_filters(?set_IdCounter(State, ID), T,
+ [{ID, true, [], Key, Types, Con, Tree, Any}|Accum],
+ [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
+ {ok, Which, WC} ->
+ ID = ?new_Id(State),
+ Key = ?not_CreateDBKey,
+ try_create_filters(?set_IdCounter(State, ID), T,
+ [{ID, Which, WC, Key, Types, Con, Tree, Any}|Accum],
+ [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
+ _ ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+ _ ->
+ corba:raise(#'CosNotifyFilter_InvalidConstraint'
+ {constr = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con}})
+ end;
+try_create_filters(State, [#'CosNotifyFilter_MappingConstraintInfo'
+ {constraint_expression = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con},
+ constraint_id=ID,
+ value=Any}|T], Accum, InfoSeq) ->
+ case catch cosNotification_Filter:create_filter(Con) of
+ {ok, Tree} ->
+ case catch cosNotification_Filter:check_types(Types) of
+ true ->
+ Key = ?not_CreateDBKey,
+ try_create_filters(State, T,
+ [{ID, true, [], Key, Types, Con, Tree, Any}|Accum],
+ [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
+ {ok, Which, WC} ->
+ Key = ?not_CreateDBKey,
+ try_create_filters(State, T,
+ [{ID, Which, WC, Key, Types, Con, Tree, Any}|Accum],
+ [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
+ _ ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+ _ ->
+ corba:raise(#'CosNotifyFilter_InvalidConstraint'
+ {constr = #'CosNotifyFilter_ConstraintExp'
+ {event_types = Types, constraint_expr = Con}})
+ end;
+try_create_filters(_,_,_,_) ->
+ %% The list contained something else but ConstraintExp.
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%-----------------------------------------------------------
+%% Function : store_filters/4
+%% Arguments: Filters - a list of filters.
+%% Returns :
+%%-----------------------------------------------------------
+
+store_filters(State, []) ->
+ State;
+store_filters(State, [{ID, Which, WC, Key, Types, Con, Tree, Any}|T]) ->
+ ?add_ParseTree(State, Key, Tree),
+ write_types(State, Types, ID, Key),
+ store_filters(?add_Constraint(State, ID, Con, Which, WC, Key, Types, Any), T).
+
+
+write_types(_State, [],_, _) ->
+ ok;
+write_types(State, [EventType|T], ID, Key) ->
+ ?add_Type(State, ID, EventType, Key),
+ ?debug_print("FILTER: ~p ~p ~p~n", [ID, Key, EventType]),
+ write_types(State, T, ID, Key).
+
+%%-----------------------------------------------------------
+%% Function : match_any_event
+%% Arguments: Event - #any{}
+%% Returns :
+%%-----------------------------------------------------------
+match_any_event(State, _Event, []) ->
+ ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
+ {reply, {false, ?get_DefAny(State)}, State};
+match_any_event(State, Event, [{_, _, _, _, Key, Any}|T]) ->
+ case catch cosNotification_Filter:eval(?get_ParseTree(State,Key), Event) of
+ true ->
+ ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
+ {reply, {true, Any}, State};
+ _ ->
+ match_any_event(State, Event, T)
+ end.
+
+
+%%-----------------------------------------------------------
+%% Function : match_str_event
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+
+match_str_event(State, _Event, []) ->
+ ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
+ {reply, {false, ?get_DefAny(State)}, State};
+match_str_event(State, Event, [{ID, _Con, Which, WC, Key, _Types, Any}|T]) ->
+ ET = ((Event#'CosNotification_StructuredEvent'.header)
+ #'CosNotification_EventHeader'.fixed_header)
+ #'CosNotification_FixedEventHeader'.event_type,
+ CheckList =
+ case Which of
+ both ->
+ [ET];
+ domain ->
+ [ET,
+ ET#'CosNotification_EventType'{type_name=""},
+ ET#'CosNotification_EventType'{type_name="*"}];
+ type ->
+ [ET,
+ ET#'CosNotification_EventType'{domain_name=""},
+ ET#'CosNotification_EventType'{domain_name="*"}];
+ _ ->
+ [ET,
+ ET#'CosNotification_EventType'{type_name=""},
+ ET#'CosNotification_EventType'{type_name="*"},
+ ET#'CosNotification_EventType'{domain_name=""},
+ ET#'CosNotification_EventType'{domain_name="*"}]
+ end,
+ case check_DB(State, ID, CheckList) of
+ false ->
+ %% No match, may have used wildcards, e.g., "dom*".
+ case catch cosNotification_Filter:match_types(
+ ET#'CosNotification_EventType'.domain_name,
+ ET#'CosNotification_EventType'.type_name,
+ WC) of
+ true ->
+ case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
+ Event) of
+ true ->
+ ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
+ {reply, {true, Any}, State};
+ _ ->
+ match_str_event(State, Event, T)
+ end;
+ _->
+ match_str_event(State, Event, T)
+ end;
+ Key ->
+ case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
+ Event) of
+ true ->
+ ?debug_print("FILTER APPROVED: ~p~n", [Event]),
+ {reply, {true, Any}, State};
+ _ ->
+ match_str_event(State, Event, T)
+ end
+ end.
+
+check_DB(_, _, []) ->
+ false;
+check_DB(State, ID, [H|T]) ->
+ case ?match_Type(State, ID, H) of
+ [] ->
+ check_DB(State, ID, T);
+ [{_, K, types}|_] ->
+ K
+ end.
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
+
diff --git a/lib/cosNotification/src/CosTypedEvent.idl b/lib/cosNotification/src/CosTypedEvent.idl
new file mode 100644
index 0000000000..d77c37731a
--- /dev/null
+++ b/lib/cosNotification/src/CosTypedEvent.idl
@@ -0,0 +1,57 @@
+#ifndef _COS_TYPED_EVENT_IDL_
+#define _COS_TYPED_EVENT_IDL_
+
+#pragma prefix "omg.org"
+
+#include<CosEvent.idl>
+
+module CosTypedEventComm {
+
+ interface TypedPushConsumer : CosEventComm::PushConsumer {
+ Object get_typed_consumer();
+ };
+
+ interface TypedPullSupplier : CosEventComm::PullSupplier {
+ Object get_typed_supplier();
+ };
+};
+
+module CosTypedEventChannelAdmin {
+
+ exception InterfaceNotSupported {};
+ exception NoSuchImplementation {};
+ typedef string Key;
+
+
+ interface TypedProxyPushConsumer :
+ CosEventChannelAdmin::ProxyPushConsumer,
+ CosTypedEventComm::TypedPushConsumer { };
+
+ interface TypedProxyPullSupplier :
+ CosEventChannelAdmin::ProxyPullSupplier,
+ CosTypedEventComm::TypedPullSupplier { };
+
+ interface TypedSupplierAdmin :
+ CosEventChannelAdmin::SupplierAdmin {
+ TypedProxyPushConsumer obtain_typed_push_consumer(in Key supported_interface)
+ raises(InterfaceNotSupported);
+ CosEventChannelAdmin::ProxyPullConsumer obtain_typed_pull_consumer (in Key uses_interface)
+ raises(NoSuchImplementation);
+ };
+
+ interface TypedConsumerAdmin :
+ CosEventChannelAdmin::ConsumerAdmin {
+ TypedProxyPullSupplier obtain_typed_pull_supplier(in Key supported_interface)
+ raises (InterfaceNotSupported);
+ CosEventChannelAdmin::ProxyPushSupplier obtain_typed_push_supplier(in Key uses_interface)
+ raises(NoSuchImplementation);
+ };
+
+ interface TypedEventChannel {
+ TypedConsumerAdmin for_consumers();
+ TypedSupplierAdmin for_suppliers();
+ void destroy ();
+ };
+};
+
+#endif /* ifndef _COS_TYPED_EVENT_IDL_ */
diff --git a/lib/cosNotification/src/CosTypedNotification.idl b/lib/cosNotification/src/CosTypedNotification.idl
new file mode 100644
index 0000000000..882cde16e0
--- /dev/null
+++ b/lib/cosNotification/src/CosTypedNotification.idl
@@ -0,0 +1,109 @@
+#ifndef _COS_TYPED_NOTIFICATION_IDL_
+#define _COS_TYPED_NOTIFICATION_IDL_
+
+#pragma prefix "omg.org"
+
+#include<CosNotifyChannelAdmin.idl>
+#include<CosTypedEvent.idl>
+#include<CosNotification.idl>
+
+module CosTypedNotifyComm {
+ interface TypedPushConsumer : CosTypedEventComm::TypedPushConsumer, CosNotifyComm::NotifyPublish { }; // TypedPushConsumer
+
+ interface TypedPullSupplier : CosTypedEventComm::TypedPullSupplier, CosNotifyComm::NotifySubscribe { }; // TypedPullSupplier
+}; // CosTypedNotifyComm
+
+
+module CosTypedNotifyChannelAdmin {
+ // Forward declaration
+ interface TypedEventChannelFactory;
+ typedef string Key;
+ interface TypedProxyPushConsumer : CosNotifyChannelAdmin::ProxyConsumer, CosTypedNotifyComm::TypedPushConsumer {
+ void connect_typed_push_supplier (in CosEventComm::PushSupplier push_supplier)
+ raises (CosEventChannelAdmin::AlreadyConnected);
+ }; // TypedProxyPushConsumer
+
+ interface TypedProxyPullSupplier : CosNotifyChannelAdmin::ProxySupplier, CosTypedNotifyComm::TypedPullSupplier {
+ void connect_typed_pull_consumer (in CosEventComm::PullConsumer pull_consumer)
+ raises (CosEventChannelAdmin::AlreadyConnected);
+ }; // TypedProxyPullSupplier
+
+ interface TypedProxyPullConsumer : CosNotifyChannelAdmin::ProxyConsumer, CosNotifyComm::PullConsumer {
+ void connect_typed_pull_supplier (in CosTypedEventComm::TypedPullSupplier pull_supplier)
+ raises (CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises (CosNotifyChannelAdmin::ConnectionAlreadyInactive, CosNotifyChannelAdmin::NotConnected);
+
+ void resume_connection()
+ raises (CosNotifyChannelAdmin::ConnectionAlreadyActive, CosNotifyChannelAdmin::NotConnected);
+ }; // TypedProxyPullConsumer
+
+ interface TypedProxyPushSupplier : CosNotifyChannelAdmin::ProxySupplier, CosNotifyComm::PushSupplier {
+ void connect_typed_push_consumer (in CosTypedEventComm::TypedPushConsumer push_consumer)
+ raises (CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
+
+ void suspend_connection()
+ raises (CosNotifyChannelAdmin::ConnectionAlreadyInactive, CosNotifyChannelAdmin::NotConnected);
+
+ void resume_connection()
+ raises (CosNotifyChannelAdmin::ConnectionAlreadyActive, CosNotifyChannelAdmin::NotConnected);
+ }; // TypedProxyPushSupplier
+
+ interface TypedConsumerAdmin : CosNotifyChannelAdmin::ConsumerAdmin, CosTypedEventChannelAdmin::TypedConsumerAdmin {
+ TypedProxyPullSupplier obtain_typed_notification_pull_supplier(in Key supported_interface,
+ out CosNotifyChannelAdmin::ProxyID proxy_id)
+ raises( CosTypedEventChannelAdmin::InterfaceNotSupported, CosNotifyChannelAdmin::AdminLimitExceeded );
+
+ TypedProxyPushSupplier obtain_typed_notification_push_supplier(in Key uses_interface,
+ out CosNotifyChannelAdmin::ProxyID proxy_id)
+ raises(CosTypedEventChannelAdmin::NoSuchImplementation, CosNotifyChannelAdmin::AdminLimitExceeded);
+ }; // TypedConsumerAdmin
+
+ interface TypedSupplierAdmin : CosNotifyChannelAdmin::SupplierAdmin, CosTypedEventChannelAdmin::TypedSupplierAdmin {
+ TypedProxyPushConsumer obtain_typed_notification_push_consumer(in Key supported_interface,
+ out CosNotifyChannelAdmin::ProxyID proxy_id)
+ raises( CosTypedEventChannelAdmin::InterfaceNotSupported, CosNotifyChannelAdmin::AdminLimitExceeded);
+ TypedProxyPullConsumer obtain_typed_notification_pull_consumer(in Key uses_interface,
+ out CosNotifyChannelAdmin::ProxyID proxy_id )
+ raises(CosTypedEventChannelAdmin::NoSuchImplementation, CosNotifyChannelAdmin::AdminLimitExceeded);
+ }; // TypedSupplierAdmin
+
+ interface TypedEventChannel : CosNotification::QoSAdmin, CosNotification::AdminPropertiesAdmin,
+ CosTypedEventChannelAdmin::TypedEventChannel {
+ readonly attribute TypedEventChannelFactory MyFactory;
+ readonly attribute TypedConsumerAdmin default_consumer_admin;
+ readonly attribute TypedSupplierAdmin default_supplier_admin;
+ readonly attribute CosNotifyFilter::FilterFactory default_filter_factory;
+
+ TypedConsumerAdmin new_for_typed_notification_consumers(in CosNotifyChannelAdmin::InterFilterGroupOperator op,
+ out CosNotifyChannelAdmin::AdminID id);
+
+ TypedSupplierAdmin new_for_typed_notification_suppliers(in CosNotifyChannelAdmin::InterFilterGroupOperator op,
+ out CosNotifyChannelAdmin::AdminID id);
+
+ TypedConsumerAdmin get_consumeradmin (in CosNotifyChannelAdmin::AdminID id )
+ raises (CosNotifyChannelAdmin::AdminNotFound);
+
+ TypedSupplierAdmin get_supplieradmin (in CosNotifyChannelAdmin::AdminID id)
+ raises (CosNotifyChannelAdmin::AdminNotFound);
+
+ CosNotifyChannelAdmin::AdminIDSeq get_all_consumeradmins();
+
+ CosNotifyChannelAdmin::AdminIDSeq get_all_supplieradmins();
+ }; // TypedEventChannel
+
+ interface TypedEventChannelFactory {
+ TypedEventChannel create_typed_channel (in CosNotification::QoSProperties initial_QoS,
+ in CosNotification::AdminProperties initial_admin,
+ out CosNotifyChannelAdmin::ChannelID id)
+ raises( CosNotification::UnsupportedQoS, CosNotification::UnsupportedAdmin);
+
+ CosNotifyChannelAdmin::ChannelIDSeq get_all_typed_channels();
+
+ TypedEventChannel get_typed_event_channel (in CosNotifyChannelAdmin::ChannelID id)
+ raises (CosNotifyChannelAdmin::ChannelNotFound);
+ }; // TypedEventChannelFactory
+}; // CosTypedNotifyChannelAdmin
+
+#endif /* ifndef _COS_TYPED_NOTIFICATION_IDL_ */
diff --git a/lib/cosNotification/src/Makefile b/lib/cosNotification/src/Makefile
new file mode 100644
index 0000000000..637c633e52
--- /dev/null
+++ b/lib/cosNotification/src/Makefile
@@ -0,0 +1,369 @@
+#
+# %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
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug -W
+endif
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(COSNOTIFICATION_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/cosNotification-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES = \
+ CosNotification_Common \
+ CosNotifyChannelAdmin_ConsumerAdmin_impl \
+ CosNotifyChannelAdmin_EventChannelFactory_impl \
+ CosNotifyChannelAdmin_EventChannel_impl \
+ CosNotifyChannelAdmin_SupplierAdmin_impl \
+ CosNotifyFilter_Filter_impl \
+ CosNotifyFilter_MappingFilter_impl \
+ CosNotifyFilter_FilterFactory_impl \
+ PullerConsumer_impl \
+ PullerSupplier_impl \
+ PusherConsumer_impl \
+ PusherSupplier_impl \
+ cosNotificationApp \
+ cosNotification_Scanner \
+ cosNotification_Filter \
+ cosNotification_eventDB
+
+ERL_FILES = $(MODULES:%=%.erl)
+HRL_FILES = \
+ CosNotification_Definitions.hrl
+
+YECC_FILES = cosNotification_Grammar.yrl
+
+GEN_YECC_ERL_FILES = cosNotification_Grammar.erl
+
+GEN_YECC_HRL_FILES =
+
+GEN_NOTIFICATION_ERL_FILES = \
+ oe_CosNotification.erl \
+ CosNotification.erl \
+ CosNotification_AdminPropertiesAdmin.erl \
+ CosNotification_EventHeader.erl \
+ CosNotification_EventType.erl \
+ CosNotification_FixedEventHeader.erl \
+ CosNotification_NamedPropertyRange.erl \
+ CosNotification_Property.erl \
+ CosNotification_PropertyError.erl \
+ CosNotification_PropertyRange.erl \
+ CosNotification_QoSAdmin.erl \
+ CosNotification_StructuredEvent.erl \
+ CosNotification_UnsupportedAdmin.erl \
+ CosNotification_UnsupportedQoS.erl \
+ CosNotification_EventBatch.erl \
+ CosNotification_EventTypeSeq.erl \
+ CosNotification_NamedPropertyRangeSeq.erl \
+ CosNotification_PropertyErrorSeq.erl \
+ CosNotification_PropertySeq.erl
+
+GEN_CHANNELADMIN_ERL_FILES = \
+ oe_CosNotifyChannelAdmin.erl \
+ CosNotifyChannelAdmin_AdminLimit.erl \
+ CosNotifyChannelAdmin_AdminLimitExceeded.erl \
+ CosNotifyChannelAdmin_AdminNotFound.erl \
+ CosNotifyChannelAdmin_ChannelNotFound.erl \
+ CosNotifyChannelAdmin_ConnectionAlreadyActive.erl \
+ CosNotifyChannelAdmin_ConnectionAlreadyInactive.erl \
+ CosNotifyChannelAdmin_ConsumerAdmin.erl \
+ CosNotifyChannelAdmin_EventChannel.erl \
+ CosNotifyChannelAdmin_EventChannelFactory.erl \
+ CosNotifyChannelAdmin_NotConnected.erl \
+ CosNotifyChannelAdmin_ProxyConsumer.erl \
+ CosNotifyChannelAdmin_ProxyNotFound.erl \
+ CosNotifyChannelAdmin_ProxyPullConsumer.erl \
+ CosNotifyChannelAdmin_ProxyPullSupplier.erl \
+ CosNotifyChannelAdmin_ProxyPushConsumer.erl \
+ CosNotifyChannelAdmin_ProxyPushSupplier.erl \
+ CosNotifyChannelAdmin_ProxySupplier.erl \
+ CosNotifyChannelAdmin_SequenceProxyPullConsumer.erl \
+ CosNotifyChannelAdmin_SequenceProxyPullSupplier.erl \
+ CosNotifyChannelAdmin_SequenceProxyPushConsumer.erl \
+ CosNotifyChannelAdmin_SequenceProxyPushSupplier.erl \
+ CosNotifyChannelAdmin_StructuredProxyPullConsumer.erl \
+ CosNotifyChannelAdmin_StructuredProxyPullSupplier.erl \
+ CosNotifyChannelAdmin_StructuredProxyPushConsumer.erl \
+ CosNotifyChannelAdmin_StructuredProxyPushSupplier.erl \
+ CosNotifyChannelAdmin_SupplierAdmin.erl \
+ CosNotifyChannelAdmin_AdminIDSeq.erl \
+ CosNotifyChannelAdmin_ChannelIDSeq.erl \
+ CosNotifyChannelAdmin_ProxyIDSeq.erl
+
+GEN_NOTIFYFILTER_ERL_FILES = \
+ oe_CosNotifyFilter.erl \
+ CosNotifyFilter_CallbackNotFound.erl \
+ CosNotifyFilter_ConstraintExp.erl \
+ CosNotifyFilter_ConstraintInfo.erl \
+ CosNotifyFilter_ConstraintNotFound.erl \
+ CosNotifyFilter_DuplicateConstraintID.erl \
+ CosNotifyFilter_Filter.erl \
+ CosNotifyFilter_FilterAdmin.erl \
+ CosNotifyFilter_FilterFactory.erl \
+ CosNotifyFilter_FilterNotFound.erl \
+ CosNotifyFilter_InvalidConstraint.erl \
+ CosNotifyFilter_InvalidGrammar.erl \
+ CosNotifyFilter_InvalidValue.erl \
+ CosNotifyFilter_MappingConstraintInfo.erl \
+ CosNotifyFilter_MappingConstraintPair.erl \
+ CosNotifyFilter_MappingFilter.erl \
+ CosNotifyFilter_UnsupportedFilterableData.erl \
+ CosNotifyFilter_CallbackIDSeq.erl \
+ CosNotifyFilter_ConstraintExpSeq.erl \
+ CosNotifyFilter_ConstraintIDSeq.erl \
+ CosNotifyFilter_ConstraintInfoSeq.erl \
+ CosNotifyFilter_FilterIDSeq.erl \
+ CosNotifyFilter_MappingConstraintInfoSeq.erl \
+ CosNotifyFilter_MappingConstraintPairSeq.erl
+
+GEN_NOTIFYCOMM_ERL_FILES = \
+ oe_CosNotifyComm.erl \
+ CosNotifyComm_InvalidEventType.erl \
+ CosNotifyComm_NotifyPublish.erl \
+ CosNotifyComm_NotifySubscribe.erl \
+ CosNotifyComm_PullConsumer.erl \
+ CosNotifyComm_PullSupplier.erl \
+ CosNotifyComm_PushConsumer.erl \
+ CosNotifyComm_PushSupplier.erl \
+ CosNotifyComm_SequencePullConsumer.erl \
+ CosNotifyComm_SequencePullSupplier.erl \
+ CosNotifyComm_SequencePushConsumer.erl \
+ CosNotifyComm_SequencePushSupplier.erl \
+ CosNotifyComm_StructuredPullConsumer.erl \
+ CosNotifyComm_StructuredPullSupplier.erl \
+ CosNotifyComm_StructuredPushConsumer.erl \
+ CosNotifyComm_StructuredPushSupplier.erl \
+
+GEN_OE_EVENTCOMM_ERL_FILES = \
+ oe_cosNotificationAppComm.erl \
+ oe_CosNotificationComm_Event.erl
+
+EXTERNAL_INC_PATH = ../include
+
+GEN_NOTIFICATION_HRL_FILES = \
+ oe_CosNotification.hrl \
+ CosNotification.hrl \
+ CosNotification_AdminPropertiesAdmin.hrl \
+ CosNotification_QoSAdmin.hrl \
+
+EXTERNAL_GEN_NOTIFICATION_HRL_FILES = \
+ $(GEN_NOTIFICATION_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
+
+GEN_CHANNELADMIN_HRL_FILES = \
+ oe_CosNotifyChannelAdmin.hrl \
+ CosNotifyChannelAdmin.hrl \
+ CosNotifyChannelAdmin_ConsumerAdmin.hrl \
+ CosNotifyChannelAdmin_EventChannel.hrl \
+ CosNotifyChannelAdmin_EventChannelFactory.hrl \
+ CosNotifyChannelAdmin_ProxyConsumer.hrl \
+ CosNotifyChannelAdmin_ProxyPullConsumer.hrl \
+ CosNotifyChannelAdmin_ProxyPullSupplier.hrl \
+ CosNotifyChannelAdmin_ProxyPushConsumer.hrl \
+ CosNotifyChannelAdmin_ProxyPushSupplier.hrl \
+ CosNotifyChannelAdmin_ProxySupplier.hrl \
+ CosNotifyChannelAdmin_SequenceProxyPullConsumer.hrl \
+ CosNotifyChannelAdmin_SequenceProxyPullSupplier.hrl \
+ CosNotifyChannelAdmin_SequenceProxyPushConsumer.hrl \
+ CosNotifyChannelAdmin_SequenceProxyPushSupplier.hrl \
+ CosNotifyChannelAdmin_StructuredProxyPullConsumer.hrl \
+ CosNotifyChannelAdmin_StructuredProxyPullSupplier.hrl \
+ CosNotifyChannelAdmin_StructuredProxyPushConsumer.hrl \
+ CosNotifyChannelAdmin_StructuredProxyPushSupplier.hrl \
+ CosNotifyChannelAdmin_SupplierAdmin.hrl \
+
+EXTERNAL_GEN_CHANNELADMIN_HRL_FILES = \
+ $(GEN_CHANNELADMIN_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
+
+GEN_NOTIFYFILTER_HRL_FILES = \
+ oe_CosNotifyFilter.hrl \
+ CosNotifyFilter.hrl \
+ CosNotifyFilter_Filter.hrl \
+ CosNotifyFilter_FilterAdmin.hrl \
+ CosNotifyFilter_FilterFactory.hrl \
+ CosNotifyFilter_MappingFilter.hrl
+
+EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES = \
+ $(GEN_NOTIFYFILTER_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
+
+GEN_NOTIFYCOMM_HRL_FILES = \
+ oe_CosNotifyComm.hrl \
+ CosNotifyComm.hrl \
+ CosNotifyComm_NotifyPublish.hrl \
+ CosNotifyComm_NotifySubscribe.hrl \
+ CosNotifyComm_PullConsumer.hrl \
+ CosNotifyComm_PullSupplier.hrl \
+ CosNotifyComm_PushConsumer.hrl \
+ CosNotifyComm_PushSupplier.hrl \
+ CosNotifyComm_SequencePullConsumer.hrl \
+ CosNotifyComm_SequencePullSupplier.hrl \
+ CosNotifyComm_SequencePushConsumer.hrl \
+ CosNotifyComm_SequencePushSupplier.hrl \
+ CosNotifyComm_StructuredPullConsumer.hrl \
+ CosNotifyComm_StructuredPullSupplier.hrl \
+ CosNotifyComm_StructuredPushConsumer.hrl \
+ CosNotifyComm_StructuredPushSupplier.hrl \
+
+EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES = \
+ $(GEN_NOTIFYCOMM_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
+
+GEN_OE_EVENTCOMM_HRL_FILES = \
+ oe_cosNotificationAppComm.hrl \
+ oe_CosNotificationComm.hrl \
+ oe_CosNotificationComm_Event.hrl
+
+GEN_ERL_FILES = \
+ $(GEN_NOTIFICATION_ERL_FILES) \
+ $(GEN_OE_EVENTCOMM_ERL_FILES) \
+ $(GEN_NOTIFYCOMM_ERL_FILES) \
+ $(GEN_NOTIFYFILTER_ERL_FILES) \
+ $(GEN_CHANNELADMIN_ERL_FILES) \
+ $(GEN_YECC_ERL_FILES)
+
+GEN_HRL_FILES = \
+ $(EXTERNAL_GEN_NOTIFICATION_HRL_FILES) \
+ $(GEN_OE_EVENTCOMM_HRL_FILES) \
+ $(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES) \
+ $(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES) \
+ $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES) \
+ $(GEN_YECC_HRL_FILES)
+
+
+GEN_FILES = \
+ $(GEN_HRL_FILES) \
+ $(GEN_ERL_FILES)
+
+TARGET_FILES = \
+ $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+IDL_FILES = \
+ CosNotification.idl \
+ CosNotifyChannelAdmin.idl \
+ CosNotifyFilter.idl \
+ CosNotifyComm.idl \
+ cosNotificationAppComm.idl
+
+APPUP_FILE = cosNotification.appup
+APPUP_SRC = $(APPUP_FILE).src
+APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+
+APP_FILE = cosNotification.app
+APP_SRC = $(APP_FILE).src
+APP_TARGET = $(EBIN)/$(APP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosNotification/ebin \
+ -pa $(ERL_TOP)/lib/ic/ebin\
+ -pa $(ERL_TOP)/lib/orber/ebin \
+ -pa $(ERL_TOP)/lib/cosEvent/ebin \
+ -pa $(ERL_TOP)/lib/cosTime/ebin \
+ -I$(ERL_TOP)/lib/cosEvent/src
+
+# The -pa option is just used temporary until erlc can handle
+# includes from other directories than ../include .
+ERL_COMPILE_FLAGS += \
+ $(ERL_IDL_FLAGS) \
+ -pa $(ERL_TOP)/lib/orber/include \
+ -pa $(ERL_TOP)/lib/cosNotification/include \
+ -pa $(ERL_TOP)/lib/cosEvent/include \
+ -pa $(ERL_TOP)/lib/cosTime/include \
+ -I$(ERL_TOP)/lib/orber/include \
+ -I$(ERL_TOP)/lib/cosNotification/include \
+ -I$(ERL_TOP)/lib/cosEvent/include \
+ -I$(ERL_TOP)/lib/cosTime/include \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,app_vsn,"cosNotification_$(COSNOTIFICATION_VSN)"}'
+
+YECC_COMPILE_FLAGS =
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+
+debug:
+ @${MAKE} TYPE=debug
+
+cleanb:
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f errs core *~
+
+clean:
+ rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f errs core *~
+
+$(APP_TARGET): $(APP_SRC)
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+docs:
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+$(GEN_NOTIFICATION_ERL_FILES) $(EXTERNAL_GEN_NOTIFICATION_HRL_FILES): CosNotification.idl
+ erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotification.cfg"}' CosNotification.idl
+ mv $(GEN_NOTIFICATION_HRL_FILES) $(EXTERNAL_INC_PATH)
+$(GEN_CHANNELADMIN_ERL_FILES) $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES): CosNotifyChannelAdmin.idl
+ erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyChannelAdmin.cfg"}' CosNotifyChannelAdmin.idl
+ mv $(GEN_CHANNELADMIN_HRL_FILES) $(EXTERNAL_INC_PATH)
+$(GEN_NOTIFYFILTER_ERL_FILES) $(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES): CosNotifyFilter.idl
+ erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyFilter.cfg"}' CosNotifyFilter.idl
+ mv $(GEN_NOTIFYFILTER_HRL_FILES) $(EXTERNAL_INC_PATH)
+$(GEN_OE_EVENTCOMM_ERL_FILES) $(GEN_OE_EVENTCOMM_HRL_FILES): cosNotificationAppComm.idl
+ erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosNotificationComm.cfg"}' cosNotificationAppComm.idl
+$(GEN_NOTIFYCOMM_ERL_FILES) $(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES): CosNotifyComm.idl
+ erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyComm.cfg"}' CosNotifyComm.idl
+ mv $(GEN_NOTIFYCOMM_HRL_FILES) $(EXTERNAL_INC_PATH)
+$(GEN_YECC_ERL_FILES) $(GEN_YECC_HRL_FILES): cosNotification_Grammar.yrl
+
+# ----------------------------------------------------
+# 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) $(GEN_FILES) $(IDL_FILES) $(YECC_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILES) $(YECC_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/include
+ $(INSTALL_DATA) $(GEN_HRL_FILES) $(RELSYSDIR)/include
+
+release_docs_spec:
diff --git a/lib/cosNotification/src/PullerConsumer_impl.erl b/lib/cosNotification/src/PullerConsumer_impl.erl
new file mode 100644
index 0000000000..fe6f9f8968
--- /dev/null
+++ b/lib/cosNotification/src/PullerConsumer_impl.erl
@@ -0,0 +1,773 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : PullerConsumer_impl.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module('PullerConsumer_impl').
+
+%%--------------- INCLUDES -----------------------------------
+-include_lib("orber/include/corba.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+%% cosEvent files.
+-include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
+-include_lib("cosEvent/include/CosEventComm.hrl").
+%% Application files
+-include("CosNotification.hrl").
+-include("CosNotifyChannelAdmin.hrl").
+-include("CosNotifyComm.hrl").
+-include("CosNotifyFilter.hrl").
+-include("CosNotification_Definitions.hrl").
+
+%%--------------- EXPORTS ------------------------------------
+%%--------------- External -----------------------------------
+%%----- CosNotifyChannelAdmin::ProxyPullConsumer -------------
+-export([connect_any_pull_supplier/4]).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPullConsumer -----
+-export([connect_sequence_pull_supplier/4]).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPullConsumer ---
+-export([connect_structured_pull_supplier/4]).
+
+%%----- CosNotifyChannelAdmin::*ProxyPullConsumer ------------
+-export([suspend_connection/3,
+ resume_connection/3]).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ----
+-export([obtain_subscription_types/4,
+ validate_event_qos/4]).
+
+%%----- Inherit from CosNotification::QoSAdmin ---------------
+-export([get_qos/3,
+ set_qos/4,
+ validate_qos/4]).
+
+%%----- Inherit from CosNotifyComm::NotifyPublish ------------
+-export([offer_change/5]).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
+-export([add_filter/4,
+ remove_filter/4,
+ get_filter/4,
+ get_all_filters/3,
+ remove_all_filters/3]).
+
+%%----- Inherit from CosEventComm::PullConsumer -------------
+-export([disconnect_pull_consumer/3]).
+
+%%----- Inherit from CosNotifyComm::SequencePullConsumer ----
+-export([disconnect_sequence_pull_consumer/3]).
+
+%%----- Inherit from CosNotifyComm::StructuredPullConsumer --
+-export([disconnect_structured_pull_consumer/3]).
+
+%%----- Inherit from CosEventChannelAdmin::ProxyPullConsumer
+-export([connect_pull_supplier/4]).
+
+
+%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
+-export(['_get_MyType'/3,
+ '_get_MyAdmin'/3]).
+
+%%--------------- gen_server specific exports ----------------
+-export([handle_info/2, code_change/3]).
+-export([init/1, terminate/2]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {myType,
+ myAdmin,
+ myAdminPid,
+ myChannel,
+ myFilters = [],
+ myOperator,
+ idCounter = 0,
+ client,
+ qosGlobal,
+ qosLocal,
+ suspended = false,
+ pullTimer,
+ pullInterval,
+ publishType = false,
+ etsR,
+ eventCounter = 0,
+ eventDB,
+ this}).
+
+%% Data structures constructors
+-define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _PI, _MyOP, _GT, _GL, _TR),
+ #state{myType = _MyT,
+ myAdmin = _MyA,
+ myAdminPid = _MyAP,
+ myChannel = _Ch,
+ myOperator = _MyOP,
+ qosGlobal = _QS,
+ qosLocal = _LQS,
+ pullInterval = _PI,
+ etsR = ets:new(oe_ets, [set, protected]),
+ eventDB = cosNotification_eventDB:create_db(_LQS, _GT, _GL, _TR)}).
+
+%%-------------- Data structures selectors -----------------
+%% Attributes
+-define(get_MyType(S), S#state.myType).
+-define(get_MyAdmin(S), S#state.myAdmin).
+-define(get_MyAdminPid(S), S#state.myAdminPid).
+-define(get_MyChannel(S), S#state.myChannel).
+-define(get_MyOperator(S), S#state.myOperator).
+%% Client Object
+-define(get_Client(S), S#state.client).
+%% QoS
+-define(get_GlobalQoS(S), S#state.qosGlobal).
+-define(get_LocalQoS(S), S#state.qosLocal).
+-define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
+%% Filters
+-define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
+-define(get_AllFilter(S), S#state.myFilters).
+-define(get_AllFilterID(S), find_ids(S#state.myFilters)).
+%% Admin
+-define(get_PullInterval(S), S#state.pullInterval).
+-define(get_PullTimer(S), S#state.pullTimer).
+-define(get_PacingInterval(S), round(?not_GetPacingInterval((S#state.qosLocal))/10000000)).
+-define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
+%% Publish
+-define(get_AllPublish(S), lists:flatten(ets:match(S#state.etsR,
+ {'$1',publish}))).
+-define(get_PublishType(S), S#state.publishType).
+%% ID
+-define(get_IdCounter(S), S#state.idCounter).
+%% Event
+-define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB)).
+-define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M)).
+-define(get_EventCounter(S), S#state.eventCounter).
+
+%%-------------- Data structures modifiers -----------------
+%% Client Object
+-define(set_Client(S,D), S#state{client=D}).
+-define(del_Client(S), S#state{client=undefined}).
+-define(set_Suspended(S), S#state{client=true}).
+-define(set_NotSuspended(S), S#state{client=false}).
+-define(set_Unconnected(S), S#state{client=undefined}).
+%% QoS
+-define(set_LocalQoS(S,D), S#state{qosLocal=D}).
+-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
+-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
+%% Filters
+-define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
+-define(del_Filter(S,I), S#state{myFilters=
+ delete_obj(lists:keydelete(I, 1, S#state.myFilters),
+ S#state.myFilters)}).
+-define(del_AllFilter(S), S#state{myFilters=[]}).
+%% Admin
+-define(set_PullInterval(S,V), S#state{pullInterval=V}).
+-define(set_PullTimer(S,T), S#state{pullTimer=T}).
+%% Publish
+-define(add_Publish(S,E), ets:insert(S#state.etsR, {E, publish})).
+-define(del_Publish(S,E), ets:delete(S#state.etsR, E)).
+-define(set_PublishType(S,T), S#state{publishType=T}).
+%% ID
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+%% Event
+-define(add_Event(S,E), cosNotification_eventDB:add_event(S#state.eventDB, E)).
+-define(update_EventDB(S,Q), S#state{eventDB=
+ cosNotification_eventDB:update(S#state.eventDB, Q)}).
+
+-define(set_EventCounter(S,V), S#state{eventCounter=V}).
+-define(add_to_EventCounter(S,V),S#state{eventCounter=S#state.eventCounter+V}).
+-define(reset_EventCounter(S), S#state{eventCounter=0}).
+-define(increase_EventCounter(S),S#state{eventCounter=(S#state.eventCounter+1)}).
+-define(decrease_EventCounter(S),S#state{eventCounter=S#state.eventCounter-1}).
+-define(add_ToEventCounter(S,A), S#state{eventCounter=(S#state.eventCounter+A)}).
+-define(sub_FromEventCounter(S,_A), S#state{eventCounter=(S#state.eventCounter-_A)}).
+-define(set_EventCounterTo(S,V), S#state{eventCounter=V}).
+
+%%-------------- MISC ----------------------------------------
+-define(is_ANY(S), S#state.myType == 'PULL_ANY').
+-define(is_STRUCTURED(S), S#state.myType == 'PULL_STRUCTURED').
+-define(is_SEQUENCE(S), S#state.myType == 'PULL_SEQUENCE').
+-define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
+-define(is_UnConnected(S), S#state.client == undefined).
+-define(is_Connected(S), S#state.client =/= undefined).
+-define(is_Suspended(S), S#state.suspended == true).
+-define(is_NotSuspended(S), S#state.suspended == false).
+-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_MyAdminPid(State) == Pid->
+ ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
+ {stop, Reason, State};
+ {'EXIT', _Pid, _Reason} ->
+ ?DBG("PROXYPUSHSUPPLIER: ~p TERMINATED.~n",[_Reason]),
+ {noreply, State};
+ pull ->
+ try_pull_events(State);
+ _ ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, Options, Operator]) ->
+ process_flag(trap_exit, true),
+ Secs = timer:seconds('CosNotification_Common':get_option(pullInterval,
+ Options,
+ ?not_DEFAULT_SETTINGS)),
+ GCTime = 'CosNotification_Common':get_option(gcTime, Options,
+ ?not_DEFAULT_SETTINGS),
+ GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
+ ?not_DEFAULT_SETTINGS),
+ TimeRef = 'CosNotification_Common':get_option(timeService, Options,
+ ?not_DEFAULT_SETTINGS),
+ timer:start(),
+ {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid, InitQoS,
+ LQS, MyChannel, Secs, Operator, GCTime,
+ GCLimit, TimeRef)}.
+
+terminate(_Reason, State) when ?is_UnConnected(State) ->
+ %% We are currently not connected to a client. Hence, no need for sending
+ %% a disconnect request.
+ stop_timer(State),
+ ok;
+terminate(_Reason, State) when ?is_ANY(State) ->
+ stop_timer(State),
+ 'CosNotification_Common':disconnect('CosEventComm_PullSupplier',
+ disconnect_pull_supplier,
+ ?get_Client(State));
+terminate(_Reason, State) when ?is_SEQUENCE(State) ->
+ stop_timer(State),
+ 'CosNotification_Common':disconnect('CosNotifyComm_SequencePullSupplier',
+ disconnect_sequence_pull_supplier,
+ ?get_Client(State));
+terminate(_Reason, State) when ?is_STRUCTURED(State) ->
+ stop_timer(State),
+ 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPullSupplier',
+ disconnect_structured_pull_supplier,
+ ?get_Client(State)).
+
+%%-----------------------------------------------------------
+%%----- CosNotifyChannelAdmin_ProxyConsumer attributes ------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyType'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyType(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyAdmin'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyAdmin(State), State}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----- CosEventChannelAdmin::ProxyPullConsumer -------------
+%%----------------------------------------------------------%
+%% function : connect_pull_supplier
+%% Arguments: Client - CosEventComm::PullSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%% Both exceptions from CosEventChannelAdmin!!!
+%%-----------------------------------------------------------
+connect_pull_supplier(OE_THIS, OE_FROM, State, Client) ->
+ connect_any_pull_supplier(OE_THIS, OE_FROM, State, Client).
+
+%%----- CosNotifyChannelAdmin::ProxyPullConsumer ------------
+%%----------------------------------------------------------%
+%% function : connect_any_pull_supplier
+%% Arguments: Client - CosEventComm::PullSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%% Both exceptions from CosEventChannelAdmin!!!
+%%-----------------------------------------------------------
+connect_any_pull_supplier(OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
+ 'CosNotification_Common':type_check(Client, 'CosEventComm_PullSupplier'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ NewState = start_timer(State),
+ {reply, ok, NewState#state{client = Client, this = OE_THIS}}
+ end;
+connect_any_pull_supplier(_, _, _,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPullConsumer ----
+%%----------------------------------------------------------%
+%% function : connect_sequence_pull_supplier
+%% Arguments: Client - CosNotifyComm::SequencePullSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%%-----------------------------------------------------------
+connect_sequence_pull_supplier(OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
+ 'CosNotification_Common':type_check(Client, 'CosNotifyComm_SequencePullSupplier'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ NewState = start_timer(State),
+ {reply, ok, NewState#state{client = Client, this = OE_THIS}}
+ end;
+connect_sequence_pull_supplier(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPullConsumer --
+%%----------------------------------------------------------%
+%% function : connect_structured_pull_supplier
+%% Arguments: Client - CosNotifyComm::StructuredPullSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%%-----------------------------------------------------------
+connect_structured_pull_supplier(OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
+ 'CosNotification_Common':type_check(Client, 'CosNotifyComm_StructuredPullSupplier'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ NewState = start_timer(State),
+ {reply, ok, NewState#state{client = Client, this = OE_THIS}}
+ end;
+connect_structured_pull_supplier(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::*ProxyPullConsumer -----------
+%%----------------------------------------------------------%
+%% function : suspend_connection
+%% Arguments:
+%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyInactive'{}} |
+%% {'EXCEPTION', #'NotConneced'{}}
+%%-----------------------------------------------------------
+suspend_connection(_OE_THIS, _OE_FROM, State) when ?is_Connected(State) ->
+ if
+ ?is_Suspended(State) ->
+ corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{});
+ true ->
+ stop_timer(State),
+ {reply, ok, ?set_Suspended(State)}
+ end;
+suspend_connection(_, _, _) ->
+ corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
+
+%%----------------------------------------------------------%
+%% function : resume_connection
+%% Arguments:
+%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyActive'{}} |
+%% {'EXCEPTION', #'NotConneced'{}}
+%%-----------------------------------------------------------
+resume_connection(_OE_THIS, _OE_FROM, State) when ?is_Connected(State) ->
+ if
+ ?is_NotSuspended(State) ->
+ corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyActive'{});
+ true ->
+ NewState = start_timer(State),
+ {reply, ok, ?set_NotSuspended(NewState)}
+ end;
+resume_connection(_, _, _) ->
+ corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ---
+%%----------------------------------------------------------%
+%% function : obtain_subscription_types
+%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
+%% Returns : CosNotification::EventTypeSeq
+%%-----------------------------------------------------------
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
+ {reply, ?get_AllPublish(State), ?set_PublishType(State, false)};
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
+ {reply, ?get_AllPublish(State), ?set_PublishType(State, true)};
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
+ {reply, [], ?set_PublishType(State, false)};
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
+ {reply, [], ?set_PublishType(State, true)};
+obtain_subscription_types(_,_,_,What) ->
+ orber:dbg("[~p] PullerConsumer:obtain_subscription_types(~p);~n"
+ "Incorrect enumerant", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : validate_event_qos
+%% Arguments: RequiredQoS - CosNotification::QoSProperties
+%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
+%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
+%%-----------------------------------------------------------
+validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
+ AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
+ ?get_LocalQoS(State)),
+ {reply, {ok, AvilableQoS}, State}.
+
+%%----- Inherit from CosNotification::QoSAdmin --------------
+%%----------------------------------------------------------%
+%% function : get_qos
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+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) ->
+ {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
+ proxy, ?get_MyAdmin(State),
+ false),
+ NewState = ?update_EventDB(State, LQS),
+ {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
+
+%%----------------------------------------------------------%
+%% 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),
+ proxy, ?get_MyAdmin(State),
+ false),
+ {reply, {ok, QoS}, State}.
+
+%%----- Inherit from CosNotifyComm::NotifyPublish -----------
+%%----------------------------------------------------------%
+%% function : offer_change
+%% Arguments: Added - #'CosNotification_EventType'{}
+%% Removed - #'CosNotification_EventType'{}
+%% Returns : ok |
+%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
+%%-----------------------------------------------------------
+offer_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
+ cosNotification_Filter:validate_types(Added),
+ cosNotification_Filter:validate_types(Removed),
+ %% On this "side" we don't really care about which
+ %% type of events the client will supply.
+ %% Perhaps, later on, if we want to check this against Filters
+ %% associated with this object we may change this approach, i.e., if
+ %% the filter will not allow passing certain event types. But the
+ %% user should see to that that situation never occurs. It would add
+ %% extra overhead. Also see PusherSupplier- and PullerSuppler-
+ %% 'subscription_change'.
+ update_publish(add, State, Added),
+ update_publish(remove, State, Removed),
+ case ?get_PublishType(State) of
+ true ->
+ %% Perhaps we should handle exception here?!
+ %% Probably not. Better to stay "on-line".
+ catch 'CosNotifyComm_NotifySubscribe':
+ subscription_change(?get_Client(State), Added, Removed),
+ ok;
+ _->
+ ok
+ end,
+ {reply, ok, State}.
+
+update_publish(_, _, [])->
+ ok;
+update_publish(add, State, [H|T]) ->
+ ?add_Publish(State, H),
+ update_publish(add, State, T);
+update_publish(remove, State, [H|T]) ->
+ ?del_Publish(State, H),
+ update_publish(remove, State, T).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
+%%----------------------------------------------------------%
+%% function : add_filter
+%% Arguments: Filter - CosNotifyFilter::Filter
+%% Returns : FilterID - long
+%%-----------------------------------------------------------
+add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
+ 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
+ FilterID = ?new_Id(State),
+ NewState = ?set_IdCounter(State, FilterID),
+ {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
+
+%%----------------------------------------------------------%
+%% function : remove_filter
+%% Arguments: FilterID - long
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ok, ?del_Filter(State, FilterID)};
+remove_filter(_,_,_,What) ->
+ orber:dbg("[~p] PullerConsumer:remove_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_filter
+%% Arguments: FilterID - long
+%% Returns : Filter - CosNotifyFilter::Filter |
+%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
+%%-----------------------------------------------------------
+get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ?get_Filter(State, FilterID), State};
+get_filter(_,_,_,What) ->
+ orber:dbg("[~p] PullerConsumer:get_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_all_filters
+%% Arguments: -
+%% Returns : Filter - CosNotifyFilter::FilterIDSeq
+%%-----------------------------------------------------------
+get_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_AllFilterID(State), State}.
+
+%%----------------------------------------------------------%
+%% function : remove_all_filters
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ok, ?del_AllFilter(State)}.
+
+%%----- Inherit from CosEventComm::PullConsumer -------------
+%%----------------------------------------------------------%
+%% function : disconnect_pull_consumer
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_pull_consumer(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----- Inherit from CosNotifyComm::SequencePullConsumer ----
+%%----------------------------------------------------------%
+%% function : disconnect_sequence_pull_consumer
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_sequence_pull_consumer(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----- Inherit from CosNotifyComm::StructuredPullConsumer ----
+%%----------------------------------------------------------%
+%% function : disconnect_structured_pull_consumer
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_structured_pull_consumer(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+find_obj({value, {_, Obj}}) -> Obj;
+find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
+
+find_ids(List) -> find_ids(List, []).
+find_ids([], Acc) -> Acc;
+find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
+find_ids(What, _) ->
+ orber:dbg("[~p] PullerConsumer:find_ids();~n"
+ "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+%% Delete a single object.
+%% The list don not differ, i.e., no filter removed, raise exception.
+delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
+delete_obj(List,_) -> List.
+
+%% Start timer which send a message each time we should pull for new events.
+start_timer(State) ->
+ case catch timer:send_interval(?get_PullInterval(State), pull) of
+ {ok,PullTRef} ->
+ ?DBG("PULL CONSUMER STARTED PULL TIMER ~p~n",
+ [?get_PullInterval(State)]),
+ ?set_PullTimer(State, PullTRef);
+ What ->
+ orber:dbg("[~p] PullerConsumer:start_timer();~n"
+ "Unable to invoke timer:send_interval/2: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+stop_timer(State) ->
+ ?DBG("PULL CONSUMER STOPPED TIMER~n",[]),
+ timer:cancel(?get_PullTimer(State)).
+
+%% Try pull event(s); which method is determined by which type this proxy is.
+try_pull_events(State) when ?is_ANY(State) ->
+ case catch 'CosEventComm_PullSupplier':try_pull(?get_Client(State)) of
+ {_,false} ->
+ {noreply, State};
+ {Event, true} ->
+ case ?not_isConvertedStructured(Event) of
+ true ->
+ forward(seq, State,
+ cosNotification_eventDB:filter_events([any:get_value(Event)],
+ ?get_AllFilter(State)));
+ _ ->
+ forward(any, State,
+ cosNotification_eventDB:filter_events([Event],
+ ?get_AllFilter(State)))
+ end;
+ _->
+ {noreply, State}
+ end;
+try_pull_events(State) when ?is_SEQUENCE(State) ->
+ case catch 'CosNotifyComm_SequencePullSupplier':
+ try_pull_structured_events(?get_Client(State), ?get_BatchLimit(State)) of
+ {_,false} ->
+ {noreply, State};
+ {EventSeq, true} ->
+ %% We cannot convert parts of the sequence to any, event though they
+ %% are converted from any to structured. Would be 'impossible' to send.
+ forward(seq, State,
+ cosNotification_eventDB:filter_events(EventSeq,
+ ?get_AllFilter(State)));
+ _->
+ {noreply, State}
+ end;
+try_pull_events(State) when ?is_STRUCTURED(State) ->
+ case catch 'CosNotifyComm_StructuredPullSupplier':
+ try_pull_structured_event(?get_Client(State)) of
+ {_,false} ->
+ {noreply, State};
+ {Event, true} when ?not_isConvertedAny(Event) ->
+ forward(any, State,
+ cosNotification_eventDB:filter_events([Event#'CosNotification_StructuredEvent'.remainder_of_body],
+ ?get_AllFilter(State)));
+ {Event, true} ->
+ forward(seq, State,
+ cosNotification_eventDB:filter_events([Event],
+ ?get_AllFilter(State)));
+ _->
+ {noreply, State}
+ end.
+
+
+
+%% Forward events
+forward(_, State, {[], _}) when ?is_ANDOP(State) ->
+ %% Did not pass filtering. Since AND no need to pass on.
+ {noreply, State};
+forward(Type, State, {[], Failed}) ->
+ %% Did not pass filtering, but since OR it may pass Admin filters, hence, pass
+ %% on to Admin
+ forward(Type, State, Failed, ?get_MyAdmin(State), 'MATCH');
+forward(Type, State, {Passed, _}) when ?is_ANDOP(State) ->
+ %% Did pass filtering, but since AND we must pass it to Admin to check against
+ %% its Filters. Just ignore the ones that failed.
+ forward(Type, State, Passed, ?get_MyAdmin(State), 'MATCH');
+forward(Type, State, {Passed, []}) ->
+ %% Did pass filtering, and since OR we can pass it to the Channel directly.
+ forward(Type, State, Passed, ?get_MyChannel(State), 'MATCHED');
+forward(Type, State, {Passed, Failed}) ->
+ %% Some passed filtering, and since OR we can pass the ones that passed directly
+ %% to the channel and the other ones via the admin.
+ forward(Type, State, Passed, ?get_MyChannel(State), 'MATCHED'),
+ forward(Type, State, Failed, ?get_MyAdmin(State), 'MATCH').
+
+forward(any, State, [Event], SendTo, Status) ->
+ case catch oe_CosNotificationComm_Event:callAny(SendTo, Event, Status) of
+ ok ->
+ ?DBG("PROXY FORWARD ANY: ~p~n",[Event]),
+ {noreply, State};
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ orber:dbg("[~p] PullerConsumer:forward();~n"
+ "Admin/Channel no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PullerConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ R ->
+ orber:dbg("[~p] PullerConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, R, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, R}]),
+ {stop, normal, State}
+ end;
+forward(seq, State, Event, SendTo, Status) ->
+ case catch oe_CosNotificationComm_Event:callSeq(SendTo, Event, Status) of
+ ok ->
+ ?DBG("PROXY FORWARD SEQUENCE: ~p~n",[Event]),
+ {noreply, State};
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ orber:dbg("[~p] PullerConsumer:forward();~n"
+ "Admin/Channel no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PullerConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ R ->
+ orber:dbg("[~p] PullerConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, R, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, R}]),
+ {stop, normal, State}
+ end.
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/PullerSupplier_impl.erl b/lib/cosNotification/src/PullerSupplier_impl.erl
new file mode 100644
index 0000000000..9f12f9c742
--- /dev/null
+++ b/lib/cosNotification/src/PullerSupplier_impl.erl
@@ -0,0 +1,914 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : PullerSupplier_impl.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module('PullerSupplier_impl').
+
+%%--------------- INCLUDES -----------------------------------
+-include_lib("orber/include/corba.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+%% cosEvent files.
+-include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
+%% Application files
+-include("CosNotification.hrl").
+-include("CosNotifyChannelAdmin.hrl").
+-include("CosNotifyComm.hrl").
+-include("CosNotifyFilter.hrl").
+
+-include("CosNotification_Definitions.hrl").
+
+%%--------------- EXPORTS ------------------------------------
+%%--------------- External -----------------------------------
+%%----- CosNotifyChannelAdmin::ProxyPullSupplier -------------
+-export([connect_any_pull_consumer/4]).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPullSupplier -----
+-export([connect_sequence_pull_consumer/4]).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPullSupplier ---
+-export([connect_structured_pull_consumer/4]).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ----
+-export([obtain_offered_types/4,
+ validate_event_qos/4]).
+
+%%----- Inherit from CosNotification::QoSAdmin ---------------
+-export([get_qos/3,
+ set_qos/4,
+ validate_qos/4]).
+
+%%----- Inherit from CosNotifyComm::NotifySubscribe ----------
+-export([subscription_change/5]).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
+-export([add_filter/4,
+ remove_filter/4,
+ get_filter/4,
+ get_all_filters/3,
+ remove_all_filters/3]).
+
+%%----- Inherit from CosEventComm::PullSupplier -------------
+-export([pull/3,
+ try_pull/3,
+ disconnect_pull_supplier/3]).
+
+%%----- Inherit from CosNotifyComm::SequencePullSupplier --
+-export([pull_structured_events/4,
+ try_pull_structured_events/4,
+ disconnect_sequence_pull_supplier/3]).
+
+%%----- Inherit from CosNotifyComm::StructuredPullSupplier --
+-export([pull_structured_event/3,
+ try_pull_structured_event/3,
+ disconnect_structured_pull_supplier/3]).
+
+%%----- Inherit from CosEventChannelAdmin::ProxyPullSupplier
+-export([connect_pull_consumer/4]).
+
+%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
+-export(['_get_MyType'/3,
+ '_get_MyAdmin'/3,
+ '_get_priority_filter'/3,
+ '_set_priority_filter'/4,
+ '_get_lifetime_filter'/3,
+ '_set_lifetime_filter'/4]).
+
+%%--------------- 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]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {myType,
+ myAdmin,
+ myAdminPid,
+ myChannel,
+ myFilters = [],
+ myOperator,
+ idCounter = 0,
+ prioFil,
+ lifetFil,
+ client,
+ qosGlobal,
+ qosLocal,
+ pacingTimer,
+ respondTo,
+ subscribeType = false,
+ subscribeData = true,
+ etsR,
+ eventDB}).
+
+%% Data structures constructors
+-define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _MyOp, _GT, _GL, _TR),
+ #state{myType = _MyT,
+ myAdmin = _MyA,
+ myAdminPid= _MyAP,
+ myChannel = _Ch,
+ myOperator= _MyOp,
+ qosGlobal = _QS,
+ qosLocal = _LQS,
+ etsR = ets:new(oe_ets, [set, protected]),
+ eventDB = cosNotification_eventDB:create_db(_LQS, _GT, _GL, _TR)}).
+
+
+%% Data structures selectors
+%% Attributes
+-define(get_MyType(S), S#state.myType).
+-define(get_MyAdmin(S), S#state.myAdmin).
+-define(get_MyAdminPid(S), S#state.myAdmin).
+-define(get_MyChannel(S), S#state.myChannel).
+-define(get_MyOperator(S), S#state.myOperator).
+-define(get_PrioFil(S), S#state.prioFil).
+-define(get_LifeTFil(S), S#state.lifetFil).
+%% Client Object
+-define(get_Client(S), S#state.client).
+%% QoS
+-define(get_GlobalQoS(S), S#state.qosGlobal).
+-define(get_LocalQoS(S), S#state.qosLocal).
+-define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
+%% Filters
+-define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
+-define(get_AllFilter(S), S#state.myFilters).
+-define(get_AllFilterID(S), find_ids(S#state.myFilters)).
+%% Event
+-define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB)).
+-define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M)).
+-define(get_RespondTo(S), S#state.respondTo).
+%% Amin
+-define(get_PacingTimer(S), S#state.pacingTimer).
+-define(get_PacingInterval(S), round(?not_GetPacingInterval((S#state.qosLocal))/10000000)).
+-define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
+%% Subscribe
+-define(get_AllSubscribe(S), lists:flatten(ets:match(S#state.etsR,
+ {'$1',subscribe}))).
+-define(get_SubscribeType(S), S#state.subscribeType).
+-define(get_SubscribeData(S), S#state.subscribeData).
+%% ID
+-define(get_IdCounter(S), S#state.idCounter).
+-define(get_SubscribeDB(S), S#state.etsR).
+
+%% Data structures modifiers
+%% Attributes
+-define(set_PrioFil(S,D), S#state{prioFil=D}).
+-define(set_LifeTFil(S,D), S#state{lifetFil=D}).
+%% Client Object
+-define(set_Client(S,D), S#state{client=D}).
+-define(del_Client(S), S#state{client=undefined}).
+%% QoS
+-define(set_LocalQoS(S,D), S#state{qosLocal=D}).
+-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
+-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
+-define(update_EventDB(S,Q), S#state{eventDB=
+ cosNotification_eventDB:update(S#state.eventDB, Q)}).
+%% Filters
+-define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
+-define(del_Filter(S,I), S#state{myFilters=
+ delete_obj(lists:keydelete(I, 1, S#state.myFilters),
+ S#state.myFilters)}).
+-define(del_AllFilter(S), S#state{myFilters=[]}).
+-define(set_Unconnected(S), S#state{client=undefined}).
+-define(reset_RespondTo(S), S#state{respondTo=undefined}).
+-define(set_RespondTo(S,F), S#state{respondTo=F}).
+%% Event
+-define(add_Event(S,E), catch cosNotification_eventDB:
+ add_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil)).
+-define(addAndGet_Event(S,E), catch cosNotification_eventDB:
+ add_and_get_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil)).
+%% Admin
+-define(set_PacingTimer(S,T), S#state{pacingTimer=T}).
+%% Subscribe
+-define(add_Subscribe(S,E), ets:insert(S#state.etsR, {E, subscribe})).
+-define(del_Subscribe(S,E), ets:delete(S#state.etsR, E)).
+-define(set_SubscribeType(S,T), S#state{subscribeType=T}).
+-define(set_SubscribeData(S,D), S#state{subscribeData=D}).
+%% ID
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+
+%% MISC
+-define(is_ANY(S), S#state.myType == 'PULL_ANY').
+-define(is_STRUCTURED(S), S#state.myType == 'PULL_STRUCTURED').
+-define(is_SEQUENCE(S), S#state.myType == 'PULL_SEQUENCE').
+-define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
+-define(is_UnConnected(S), S#state.client == undefined).
+-define(is_Connected(S), S#state.client =/= undefined).
+-define(is_Waiting(S), S#state.respondTo =/= undefined).
+-define(is_SubscribedFor(S,K), ets:lookup(S#state.etsR, K) =/= []).
+-define(is_BatchLimitReached(S,M), cosNotification_eventDB:
+ status(S#state.eventDB, {batchLimit,
+ ?not_GetMaximumBatchSize((S#state.qosLocal)), M})).
+
+%%----------------------------------------------------------%
+%% 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_MyAdminPid(State)==Pid->
+ ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
+ {stop, Reason, State};
+ {'EXIT', _Pid, _Reason} ->
+ ?DBG("PROXYPUSHSUPPLIER: ~p TERMINATED.~n",[_Reason]),
+ {noreply, State};
+ {pacing, TS} when ?is_Waiting(State) ->
+ case ?get_PacingTimer(State) of
+ {_, TS} ->
+ ?DBG("PULL SUPPLIER PACING LIMIT REACHED~n",[]),
+ {RespondTo, Max} = ?get_RespondTo(State),
+ {EventSeq, _} = ?get_Events(State, Max),
+ corba:reply(RespondTo, EventSeq),
+ {noreply, ?reset_RespondTo(State)};
+ _ ->
+ %% Must have been an old timer event, i.e., we reached the
+ %% Batch Limit before Pace limit and we were not able
+ %% to stop the timer before it triggered an event.
+ ?DBG("PULL SUPPLIER OLD PACING LIMIT REACHED~n",[]),
+ {noreply, State}
+ end;
+ {pacing, _} ->
+ ?DBG("PULL SUPPLIER PACING LIMIT REACHED BUT NO CLIENT; IMPOSSIBLE!!!~n",[]),
+ {noreply, State};
+ _ ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, Options, Operator]) ->
+ process_flag(trap_exit, true),
+ GCTime = 'CosNotification_Common':get_option(gcTime, Options,
+ ?not_DEFAULT_SETTINGS),
+ GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
+ ?not_DEFAULT_SETTINGS),
+ TimeRef = 'CosNotification_Common':get_option(timeService, Options,
+ ?not_DEFAULT_SETTINGS),
+ {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel,
+ Operator, GCTime, GCLimit, TimeRef)}.
+
+terminate(_Reason, State) when ?is_UnConnected(State) ->
+ ok;
+terminate(_Reason, State) ->
+ Client = ?get_Client(State),
+ case catch corba_object:is_nil(Client) of
+ false when ?is_ANY(State) ->
+ 'CosNotification_Common':disconnect('CosEventComm_PullConsumer',
+ disconnect_pull_consumer,
+ Client);
+ false when ?is_SEQUENCE(State) ->
+ 'CosNotification_Common':disconnect('CosNotifyComm_SequencePullConsumer',
+ disconnect_sequence_pull_consumer,
+ Client);
+ false when ?is_STRUCTURED(State) ->
+ 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPullConsumer',
+ disconnect_structured_pull_consumer,
+ Client);
+ _ ->
+ ok
+ end.
+
+%%-----------------------------------------------------------
+%%----- CosNotifyChannelAdmin_ProxySupplier attributes ------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyType'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyType(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyAdmin'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyAdmin(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_*et_priority_filter'
+%% Type : read/write
+%% Returns :
+%%-----------------------------------------------------------
+'_get_priority_filter'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PrioFil(State), State}.
+'_set_priority_filter'(_OE_THIS, _OE_FROM, State, PrioF) ->
+ {reply, ok, ?set_PrioFil(State, PrioF)}.
+
+
+%%----------------------------------------------------------%
+%% Attribute: '_*et_lifetime_filter'
+%% Type : read/write
+%% Returns :
+%%-----------------------------------------------------------
+'_get_lifetime_filter'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_LifeTFil(State), State}.
+'_set_lifetime_filter'(_OE_THIS, _OE_FROM, State, LifeTF) ->
+ {reply, ok, ?set_LifeTFil(State, LifeTF)}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----- CosEventChannelAdmin::ProxyPullSupplier -------------
+%%----------------------------------------------------------%
+%% function : connect_pull_consumer
+%% Arguments: Client - CosEventComm::PullConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%% Both exceptions from CosEventChannelAdmin!!!
+%%-----------------------------------------------------------
+connect_pull_consumer(OE_THIS, OE_FROM, State, Client) ->
+ connect_any_pull_consumer(OE_THIS, OE_FROM, State, Client).
+
+%%----- CosNotifyChannelAdmin::ProxyPullSupplier ------------
+%%----------------------------------------------------------%
+%% function : connect_any_pull_consumer
+%% Arguments: Client - CosEventComm::PullConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%% Both exceptions from CosEventChannelAdmin!!!
+%%-----------------------------------------------------------
+connect_any_pull_consumer(_OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
+ ?not_TypeCheck(Client, 'CosEventComm_PullConsumer'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, ?set_Client(State, Client)}
+ end;
+connect_any_pull_consumer(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPullSupplier ----
+%%----------------------------------------------------------%
+%% function : connect_sequence_pull_consumer
+%% Arguments: Client - CosNotifyComm::SequencePullConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%%-----------------------------------------------------------
+connect_sequence_pull_consumer(_OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
+ ?not_TypeCheck(Client, 'CosNotifyComm_SequencePullConsumer'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, ?set_Client(State, Client)}
+ end;
+connect_sequence_pull_consumer(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPullSupplier --
+%%----------------------------------------------------------%
+%% function : connect_structured_pull_consumer
+%% Arguments: Client - CosNotifyComm::StructuredPullConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}} |
+%% {'EXCEPTION', #'BAD_OPERATION'{}}
+%%-----------------------------------------------------------
+connect_structured_pull_consumer(_OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
+ ?not_TypeCheck(Client, 'CosNotifyComm_StructuredPullConsumer'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, ?set_Client(State, Client)}
+ end;
+connect_structured_pull_consumer(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ---
+%%----------------------------------------------------------%
+%% function : obtain_offered_types
+%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
+%% Returns : CosNotification::EventTypeSeq
+%%-----------------------------------------------------------
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
+ {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, false)};
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
+ {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, true)};
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
+ {reply, [], ?set_SubscribeType(State, false)};
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
+ {reply, [], ?set_SubscribeType(State, true)};
+obtain_offered_types(_,_,_,What) ->
+ orber:dbg("[~p] PullerSupplier:obtain_offered_types(~p);~n"
+ "Incorrect enumerant", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : validate_event_qos
+%% Arguments: RequiredQoS - CosNotification::QoSProperties
+%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
+%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
+%%-----------------------------------------------------------
+validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
+ AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
+ ?get_LocalQoS(State)),
+ {reply, {ok, AvilableQoS}, State}.
+
+%%----- Inherit from CosNotification::QoSAdmin --------------
+%%----------------------------------------------------------%
+%% function : get_qos
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+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) ->
+ {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
+ proxy, ?get_MyAdmin(State),
+ false),
+ NewState = ?update_EventDB(State, LQS),
+ {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
+
+%%----------------------------------------------------------%
+%% 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),
+ proxy, ?get_MyAdmin(State),
+ false),
+ {reply, {ok, QoS}, State}.
+
+%%----- Inherit from CosNotifyComm::NotifySubscribe ---------
+%%----------------------------------------------------------%
+%% function : subscription_change
+%% Arguments: Added - Removed - CosNotification::EventTypeSeq
+%% Returns : ok
+%%-----------------------------------------------------------
+subscription_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
+ cosNotification_Filter:validate_types(Added),
+ cosNotification_Filter:validate_types(Removed),
+ %% On this "side", we care about which type of events the client
+ %% will require, since the client (or an agent) clearly stated
+ %% that it's only interested in these types of events.
+ %% Also see PusherConsumer- and PullerConsumer-'offer_change'.
+ update_subscribe(remove, State, Removed),
+ CurrentSub = ?get_AllSubscribe(State),
+ NewState =
+ case cosNotification_Filter:check_types(Added++CurrentSub) of
+ true ->
+ %% Types supplied does in some way cause all events to be valid.
+ %% Smart? Would have been better to not supply any at all.
+ ?set_SubscribeData(State, true);
+ {ok, Which, WC} ->
+ ?set_SubscribeData(State, {Which, WC})
+ end,
+ update_subscribe(add, NewState, Added),
+ case ?get_SubscribeType(NewState) of
+ true ->
+ %% Perhaps we should handle exception here?!
+ %% Probably not. Better to stay "on-line".
+ catch 'CosNotifyComm_NotifyPublish':
+ offer_change(?get_Client(NewState), Added, Removed),
+ ok;
+ _->
+ ok
+ end,
+ {reply, ok, NewState}.
+
+update_subscribe(_, _, [])->
+ ok;
+update_subscribe(add, State, [H|T]) ->
+ ?add_Subscribe(State, H),
+ update_subscribe(add, State, T);
+update_subscribe(remove, State, [H|T]) ->
+ ?del_Subscribe(State, H),
+ update_subscribe(remove, State, T).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
+%%----------------------------------------------------------%
+%% function : add_filter
+%% Arguments: Filter - CosNotifyFilter::Filter
+%% Returns : FilterID - long
+%%-----------------------------------------------------------
+add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
+ 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
+ FilterID = ?new_Id(State),
+ NewState = ?set_IdCounter(State, FilterID),
+ {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
+
+%%----------------------------------------------------------%
+%% function : remove_filter
+%% Arguments: FilterID - long
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ok, ?del_Filter(State, FilterID)};
+remove_filter(_,_,_,What) ->
+ orber:dbg("[~p] PullerSupplier:remove_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_filter
+%% Arguments: FilterID - long
+%% Returns : Filter - CosNotifyFilter::Filter |
+%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
+%%-----------------------------------------------------------
+get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ?get_Filter(State, FilterID), State};
+get_filter(_,_,_,What) ->
+ orber:dbg("[~p] PullerSupplier:get_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_all_filters
+%% Arguments: -
+%% Returns : Filter - CosNotifyFilter::FilterIDSeq
+%%-----------------------------------------------------------
+get_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_AllFilterID(State), State}.
+
+%%----------------------------------------------------------%
+%% function : remove_all_filters
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ok, ?del_AllFilter(State)}.
+
+%%----- Inherit from CosEventComm::PullSupplier -------------
+%%----------------------------------------------------------%
+%% function : disconnect_pull_supplier
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_pull_supplier(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----------------------------------------------------------%
+%% function : pull
+%% Arguments: -
+%% Returns : any - CORBA::ANY
+%%-----------------------------------------------------------
+pull(_OE_THIS, OE_FROM, State) when ?is_ANY(State) ->
+ case ?get_Event(State) of
+ {[], _} ->
+ {noreply, ?set_RespondTo(State, OE_FROM)};
+ {Event,_} ->
+ {reply, Event, State}
+ end;
+pull(_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : try_pull
+%% Arguments: -
+%% Returns : any - CORBA::ANY
+%% HasEvent - boolean (out-type)
+%%-----------------------------------------------------------
+try_pull(_OE_THIS, _OE_FROM, State) when ?is_ANY(State) ->
+ case ?get_Event(State) of
+ {[], _} ->
+ {reply, {any:create(orber_tc:null(), null), false}, State};
+ {Event, Bool} ->
+ {reply, {Event, Bool}, State}
+ end;
+try_pull(_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- Inherit from CosNotifyComm::SequencePullSupplier ----
+%%----------------------------------------------------------%
+%% function : disconnect_sequence_pull_supplier
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_sequence_pull_supplier(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----------------------------------------------------------%
+%% function : pull_structured_events
+%% Arguments: Max - long()
+%% Returns : [StructuredEvent, ..]
+%%-----------------------------------------------------------
+pull_structured_events(_OE_THIS, OE_FROM, State, Max) when ?is_SEQUENCE(State) ->
+ case ?is_BatchLimitReached(State, Max) of
+ true ->
+ %% This test is not fool-proof; if Events have been stored
+ %% using StartTime they will still be there but we cannot
+ %% deliver them anyway. To solve this "problem" would cost!
+ %% Hence, since it works fine otherwise it will do.
+ case ?get_Events(State, Max) of
+ {[], false} ->
+ NewState = start_timer(State),
+ {noreply, ?set_RespondTo(NewState, {OE_FROM, Max})};
+ {Event,_} ->
+ {reply, Event, State}
+ end;
+ _->
+ NewState = start_timer(State),
+ {noreply, ?set_RespondTo(NewState, {OE_FROM, Max})}
+ end;
+pull_structured_events(_,_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : try_pull_structured_events
+%% Arguments: Max - long()
+%% Returns : [StructuredEvent, ..]
+%% HasEvent - Boolean()
+%%-----------------------------------------------------------
+try_pull_structured_events(_OE_THIS, _OE_FROM, State, Max) when ?is_SEQUENCE(State) ->
+ {reply, ?get_Events(State, Max), State};
+try_pull_structured_events(_,_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- Inherit from CosNotifyComm::StructuredPullSupplier --
+%%----------------------------------------------------------%
+%% function : disconnect_structured_pull_supplier
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_structured_pull_supplier(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----------------------------------------------------------%
+%% function : pull_structured_event
+%% Arguments: -
+%% Returns :
+%%-----------------------------------------------------------
+pull_structured_event(_OE_THIS, OE_FROM, State) when ?is_STRUCTURED(State) ->
+ case ?get_Event(State) of
+ {[], _} ->
+ {noreply, ?set_RespondTo(State, OE_FROM)};
+ {Event,_} ->
+ {reply, Event, State}
+ end;
+pull_structured_event(_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : try_pull_structured_event
+%% Arguments: -
+%% Returns :
+%%-----------------------------------------------------------
+try_pull_structured_event(_OE_THIS, _OE_FROM, State) when ?is_STRUCTURED(State) ->
+ case ?get_Event(State) of
+ {[], _} ->
+ {reply,
+ {?not_CreateSE("","","",[],[],any:create(orber_tc:null(), null)), false},
+ State};
+ {Event, Bool} ->
+ {reply, {Event, Bool}, State}
+ end;
+try_pull_structured_event(_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+find_obj({value, {_, Obj}}) -> Obj;
+find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
+
+find_ids(List) -> find_ids(List, []).
+find_ids([], Acc) -> Acc;
+find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
+find_ids(_, _) -> corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+%% Delete a single object.
+%% The list do not differ, i.e., no filter removed, raise exception.
+delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
+delete_obj(List,_) -> List.
+
+
+%%-----------------------------------------------------------
+%% function : callSeq
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callSeq(_OE_THIS, OE_FROM, State, EventsIn, Status) ->
+ %% We should do something here, i.e., see what QoS this Object offers and
+ %% act accordingly.
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventsIn,
+ ?get_AllFilter(State),
+ ?get_SubscribeDB(State),
+ Status) of
+ {[], _} ->
+ ?DBG("PROXY NOSUBSCRIPTION SEQUENCE/STRUCTURED: ~p~n",[EventsIn]),
+ {noreply, State};
+ %% Just one event and we got a client waiting => there is no need to store
+ %% the event, just transform it and pass it on.
+ {[Event], _} when ?is_ANY(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED SEQUENCE[1]==>ANY: ~p~n",[Event]),
+ AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
+ case ?addAndGet_Event(State, AnyEvent) of
+ {[], _} ->
+ ?DBG("PROXY RECEIVED UNDELIVERABLE SEQUENCE[1]: ~p~n",
+ [Event]),
+ %% Cannot deliver the event at the moment; perhaps Starttime
+ %% set or Deadline passed.
+ {noreply, State};
+ {PossiblyOtherEvent, _} ->
+ ?DBG("PROXY RECEIVED SEQUENCE[1] ~p; DELIVER: ~p~n",
+ [Event, PossiblyOtherEvent]),
+ corba:reply(?get_RespondTo(State), PossiblyOtherEvent),
+ {noreply, ?reset_RespondTo(State)}
+ end;
+ {[Event],_} when ?is_STRUCTURED(State), ?is_Waiting(State) ->
+ case ?addAndGet_Event(State, Event) of
+ {[], _} ->
+ ?DBG("PROXY RECEIVED UNDELIVERABLE SEQUENCE[1]: ~p~n",
+ [Event]),
+ %% Cannot deliver the event at the moment; perhaps Starttime
+ %% set or Deadline passed.
+ {noreply, State};
+ {PossiblyOtherEvent, _} ->
+ ?DBG("PROXY RECEIVED SEQUENCE[1] ~p; DELIVER: ~p~n",
+ [Event, PossiblyOtherEvent]),
+ corba:reply(?get_RespondTo(State), PossiblyOtherEvent),
+ {noreply, ?reset_RespondTo(State)}
+ end;
+ %% A sequence of events => store them and extract the first (according to QoS)
+ %% event and forward it.
+ {Events,_} when ?is_ANY(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED SEQUENCE==>ANY: ~p~n",[Events]),
+ store_events(State, Events),
+ case ?get_Event(State) of
+ {[], _} ->
+ {noreply, State};
+ {AnyEvent, _} ->
+ corba:reply(?get_RespondTo(State), AnyEvent),
+ {noreply, ?reset_RespondTo(State)}
+ end;
+ {Events, _} when ?is_STRUCTURED(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
+ store_events(State, Events),
+ case ?get_Event(State) of
+ {[], _} ->
+ {noreply, State};
+ {_StrEvent, _} ->
+ corba:reply(?get_RespondTo(State), Events),
+ {noreply, ?reset_RespondTo(State)}
+ end;
+ {Events, _} when ?is_SEQUENCE(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
+ %% Store them first and extract Max events in QoS order.
+ store_events(State, Events),
+ {RespondTo, Max} = ?get_RespondTo(State),
+ case ?is_BatchLimitReached(State, Max) of
+ true ->
+ {EventSeq, _} = ?get_Events(State, Max),
+ corba:reply(RespondTo, EventSeq),
+ stop_timer(State),
+ {noreply, ?reset_RespondTo(State)};
+ _->
+ {noreply, State}
+ end;
+ %% No client waiting. Store the event(s).
+ {Events, _} ->
+ ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
+ store_events(State, Events),
+ {noreply, State}
+ end.
+
+store_events(_State, []) ->
+ ok;
+store_events(State, [Event|Rest]) when ?is_ANY(State) ->
+ AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
+ ?add_Event(State,AnyEvent),
+ store_events(State, Rest);
+store_events(State, [Event|Rest]) ->
+ ?add_Event(State,Event),
+ store_events(State, Rest).
+
+%%-----------------------------------------------------------
+%% function : callAny
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callAny(_OE_THIS, OE_FROM, State, EventIn, Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventIn,
+ ?get_AllFilter(State),
+ ?get_SubscribeDB(State),
+ Status) of
+ {[],_} ->
+ ?DBG("PROXY NOSUBSCRIPTION ANY: ~p~n",[EventIn]),
+ {noreply, State};
+ {Event,_} when ?is_ANY(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED ANY: ~p~n",[Event]),
+ case ?addAndGet_Event(State, Event) of
+ {[],_} ->
+ %% Unable to deliver the event (Starttime, Deadline etc).
+ {noreply, State};
+ {MaybeOtherEvent , _} ->
+ corba:reply(?get_RespondTo(State), MaybeOtherEvent),
+ {noreply, ?reset_RespondTo(State)}
+ end;
+ {Event,_} when ?is_ANY(State) ->
+ ?DBG("PROXY RECEIVED ANY: ~p~n",[Event]),
+ ?add_Event(State,Event),
+ {noreply, State};
+ {Event,_} when ?is_STRUCTURED(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED ANY==>STRUCTURED: ~p~n",[Event]),
+ case ?addAndGet_Event(State, ?not_CreateSE("","%ANY","",[],[],Event)) of
+ {[],_} ->
+ %% Unable to deliver the event (Starttime, Deadline etc).
+ {noreply, State};
+ {MaybeOtherEvent , _} ->
+ corba:reply(?get_RespondTo(State), MaybeOtherEvent),
+ {noreply, ?reset_RespondTo(State)}
+ end;
+ {Event,_} when ?is_SEQUENCE(State), ?is_Waiting(State) ->
+ ?DBG("PROXY RECEIVED ANY==>SEQUENCE[1]: ~p~n",[Event]),
+ ?add_Event(State,?not_CreateSE("","%ANY","",[],[],Event)),
+ {RespondTo, Max} = ?get_RespondTo(State),
+ case ?is_BatchLimitReached(State, Max) of
+ true ->
+ {EventSeq, _} = ?get_Events(State, Max),
+ corba:reply(RespondTo, EventSeq),
+ stop_timer(State),
+ {noreply, ?reset_RespondTo(State)};
+ _ ->
+ {noreply, State}
+ end;
+ {Event,_} ->
+ ?DBG("PROXY RECEIVED ANY==>STRUCTURED/SEQUENCE: ~p~n",[Event]),
+ ?add_Event(State,?not_CreateSE("","%ANY","",[],[],Event)),
+ {noreply, State}
+ end.
+
+
+
+%% Start timers which send a message each time we should push events. Only used
+%% when this objects is defined to supply sequences.
+start_timer(State) ->
+ TS = now(),
+ case catch timer:send_after(timer:seconds(?get_PacingInterval(State)),
+ {pacing, TS}) of
+ {ok,PacTRef} ->
+ ?DBG("PULL SUPPLIER STARTED TIMER, BATCH LIMIT: ~p~n",
+ [?get_BatchLimit(State)]),
+ ?set_PacingTimer(State, {PacTRef, TS});
+ What ->
+ orber:dbg("[~p] PullerSupplier:start_timer();~n"
+ "Unable to invoke timer:send_interval/2: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end.
+
+stop_timer(State) ->
+ case ?get_PacingTimer(State) of
+ undefined ->
+ ok;
+ {Timer, _} ->
+ ?DBG("PULL SUPPLIER STOPPED TIMER~n",[]),
+ timer:cancel(Timer)
+ end.
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/PusherConsumer_impl.erl b/lib/cosNotification/src/PusherConsumer_impl.erl
new file mode 100644
index 0000000000..195e81ec58
--- /dev/null
+++ b/lib/cosNotification/src/PusherConsumer_impl.erl
@@ -0,0 +1,729 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : PusherConsumer_impl.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module('PusherConsumer_impl').
+
+%%--------------- INCLUDES -----------------------------------
+-include_lib("orber/include/corba.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+%% cosEvent files.
+-include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
+-include_lib("cosEvent/include/CosEventComm.hrl").
+%% Application files
+-include("CosNotification.hrl").
+-include("CosNotifyChannelAdmin.hrl").
+-include("CosNotifyComm.hrl").
+-include("CosNotifyFilter.hrl").
+
+-include("CosNotification_Definitions.hrl").
+
+%%--------------- EXPORTS ------------------------------------
+%%--------------- External -----------------------------------
+%%----- CosNotifyChannelAdmin::ProxyPushConsumer -------------
+-export([connect_any_push_supplier/4]).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPushConsumer -----
+-export([connect_sequence_push_supplier/4]).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPushConsumer ---
+-export([connect_structured_push_supplier/4]).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ----
+-export([obtain_subscription_types/4,
+ validate_event_qos/4]).
+
+%%----- Inherit from CosNotification::QoSAdmin ---------------
+-export([get_qos/3,
+ set_qos/4,
+ validate_qos/4]).
+
+%%----- Inherit from CosNotifyComm::NotifyPublish ------------
+-export([offer_change/5]).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
+-export([add_filter/4,
+ remove_filter/4,
+ get_filter/4,
+ get_all_filters/3,
+ remove_all_filters/3]).
+
+%%----- Inherit from CosEventComm::PushConsumer -------------
+-export([push/4,
+ disconnect_push_consumer/3]).
+
+%%----- Inherit from CosNotifyComm::SequencePushConsumer ----
+-export([push_structured_events/4,
+ disconnect_sequence_push_consumer/3]).
+
+%%----- Inherit from CosNotifyComm::StructuredPushConsumer --
+-export([push_structured_event/4,
+ disconnect_structured_push_consumer/3]).
+
+%%----- Inherit from CosEventChannelAdmin::ProxyPushConsumer
+-export([connect_push_supplier/4]).
+
+%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
+-export(['_get_MyType'/3,
+ '_get_MyAdmin'/3]).
+
+%%--------------- gen_server specific exports ----------------
+-export([handle_info/2, code_change/3]).
+-export([init/1, terminate/2]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {myType,
+ myAdmin,
+ myAdminPid,
+ myChannel,
+ myFilters = [],
+ myOperator,
+ idCounter = 0,
+ client,
+ qosGlobal,
+ qosLocal,
+ publishType = false,
+ etsR,
+ eventDB}).
+
+%% Data structures constructors
+-define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _EDB, _MyOP),
+ #state{myType = _MyT,
+ myAdmin = _MyA,
+ myAdminPid= _MyAP,
+ myChannel = _Ch,
+ myOperator= _MyOP,
+ qosGlobal = _QS,
+ qosLocal = _LQS,
+ etsR = ets:new(oe_ets, [set, protected]),
+ eventDB = _EDB}).
+
+%%-------------- Data structures selectors -----------------
+%% Attributes
+-define(get_MyType(S), S#state.myType).
+-define(get_MyAdmin(S), S#state.myAdmin).
+-define(get_MyAdminPid(S), S#state.myAdminPid).
+-define(get_MyChannel(S), S#state.myChannel).
+-define(get_MyOperator(S), S#state.myOperator).
+%% Client Object
+-define(get_Client(S), S#state.client).
+%% QoS
+-define(get_GlobalQoS(S), S#state.qosGlobal).
+-define(get_LocalQoS(S), S#state.qosLocal).
+-define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
+%% Filters
+-define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
+-define(get_AllFilter(S), S#state.myFilters).
+-define(get_AllFilterID(S), find_ids(S#state.myFilters)).
+%% Publish
+-define(get_AllPublish(S), lists:flatten(ets:match(S#state.etsR,
+ {'$1',publish}))).
+-define(get_PublishType(S), S#state.publishType).
+%% ID
+-define(get_IdCounter(S), S#state.idCounter).
+%% Event
+-define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB)).
+-define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M)).
+
+-define(get_EventCounter(S), S#state.eventCounter).
+%% Admin
+-define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
+
+%%-------------- Data structures modifiers -----------------
+%% Client Object
+-define(set_Client(S,D), S#state{client=D}).
+-define(del_Client(S), S#state{client=undefined}).
+-define(set_Unconnected(S), S#state{client=undefined}).
+%% QoS
+-define(set_LocalQoS(S,D), S#state{qosLocal=D}).
+-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
+-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
+%% Filters
+-define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
+-define(del_Filter(S,I), S#state{myFilters=
+ delete_obj(lists:keydelete(I, 1, S#state.myFilters),
+ S#state.myFilters)}).
+-define(del_AllFilter(S), S#state{myFilters=[]}).
+%% Publish
+-define(add_Publish(S,E), ets:insert(S#state.etsR, {E, publish})).
+-define(del_Publish(S,E), ets:delete(S#state.etsR, E)).
+-define(set_PublishType(S,T), S#state{publishType=T}).
+%% ID
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+%% Event
+-define(add_Event(S,E), cosNotification_eventDB:add_event(S#state.eventDB, E)).
+-define(update_EventDB(S,Q), S#state{eventDB=
+ cosNotification_eventDB:update(S#state.eventDB, Q)}).
+
+-define(set_EventCounter(S,V), S#state{eventCounter=V}).
+-define(add_to_EventCounter(S,V),S#state{eventCounter=S#state.eventCounter+V}).
+-define(reset_EventCounter(S), S#state{eventCounter=0}).
+-define(increase_EventCounter(S),S#state{eventCounter=(S#state.eventCounter+1)}).
+-define(decrease_EventCounter(S),S#state{eventCounter=S#state.eventCounter-1}).
+-define(add_ToEventCounter(S,A), S#state{eventCounter=(S#state.eventCounter+A)}).
+-define(sub_FromEventCounter(S,_A), S#state{eventCounter=(S#state.eventCounter-_A)}).
+-define(set_EventCounterTo(S,V), S#state{eventCounter=V}).
+
+%% MISC
+-define(is_ANY(S), S#state.myType == 'PUSH_ANY').
+-define(is_STRUCTURED(S), S#state.myType == 'PUSH_STRUCTURED').
+-define(is_SEQUENCE(S), S#state.myType == 'PUSH_SEQUENCE').
+-define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
+-define(is_UnConnected(S), S#state.client == undefined).
+-define(is_Connected(S), S#state.client =/= undefined).
+-define(is_PersistentConnection(S),
+ ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
+-define(is_PersistentEvent(S),
+ ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
+-define(is_BatchLimitReached(S), S#state.eventCounter >=
+ ?not_GetMaximumBatchSize((S#state.qosLocal))).
+
+
+%%----------------------------------------------------------%
+%% 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_MyAdminPid(State)==Pid->
+ ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
+ {stop, Reason, State};
+ {'EXIT', _Pid, _Reason} ->
+ ?DBG("PROXYPUSHCONSUMER: ~p TERMINATED.~n",[_Reason]),
+ {noreply, State};
+ _ ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init(['PUSH_SEQUENCE', MyAdmin, MyAdminPid, InitQoS, LQS,
+ MyChannel, Options, Operator]) ->
+ process_flag(trap_exit, true),
+ %% Only if MyType is 'PUSH_SEQUENCE' we need an ets to store events in.
+ %% Otherwise we'll forward them at once. Why? We don't know when the next event
+ %% is due.
+ GCTime = 'CosNotification_Common':get_option(gcTime, Options,
+ ?not_DEFAULT_SETTINGS),
+ GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
+ ?not_DEFAULT_SETTINGS),
+ TimeRef = 'CosNotification_Common':get_option(timeService, Options,
+ ?not_DEFAULT_SETTINGS),
+ {ok, ?get_InitState('PUSH_SEQUENCE', MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel,
+ cosNotification_eventDB:create_db(LQS, GCTime, GCLimit, TimeRef),
+ Operator)};
+init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, _Options, Operator]) ->
+ process_flag(trap_exit, true),
+ {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel,
+ undefined, Operator)}.
+
+terminate(_Reason, State) when ?is_UnConnected(State) ->
+ ok;
+terminate(_Reason, State) ->
+ Client = ?get_Client(State),
+ case catch corba_object:is_nil(Client) of
+ false when ?is_ANY(State) ->
+ 'CosNotification_Common':disconnect('CosEventComm_PushSupplier',
+ disconnect_push_supplier,
+ Client);
+ false when ?is_SEQUENCE(State) ->
+ 'CosNotification_Common':disconnect('CosNotifyComm_SequencePushSupplier',
+ disconnect_sequence_push_supplier,
+ Client);
+ false when ?is_STRUCTURED(State) ->
+ 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPushSupplier',
+ disconnect_structured_push_supplier,
+ Client);
+ _ ->
+ ok
+ end.
+
+%%-----------------------------------------------------------
+%%----- CosNotifyChannelAdmin_ProxyConsumer attributes ------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyType'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyType(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyAdmin'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyAdmin(State), State}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----- CosEventChannelAdmin::ProxyPushConsumer -------------
+%%----------------------------------------------------------%
+%% function : connect_push_supplier
+%% Arguments: Client - CosEventComm::PushSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%% Both exceptions from CosEventChannelAdmin!!!
+%%-----------------------------------------------------------
+connect_push_supplier(OE_THIS, OE_FROM, State, Client) ->
+ connect_any_push_supplier(OE_THIS, OE_FROM, State, Client).
+
+%%----- CosNotifyChannelAdmin::ProxyPushConsumer ------------
+%%----------------------------------------------------------%
+%% function : connect_any_push_supplier
+%% Arguments: Client - CosEventComm::PushSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%% Both exceptions from CosEventChannelAdmin!!!
+%%-----------------------------------------------------------
+connect_any_push_supplier(_OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
+ ?not_TypeCheck(Client, 'CosEventComm_PushSupplier'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, ?set_Client(State, Client)}
+ end;
+connect_any_push_supplier(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPushConsumer ----
+%%----------------------------------------------------------%
+%% function : connect_sequence_push_supplier
+%% Arguments: Client - CosNotifyComm::SequencePushSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%%-----------------------------------------------------------
+connect_sequence_push_supplier(_OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
+ ?not_TypeCheck(Client, 'CosNotifyComm_SequencePushSupplier'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, ?set_Client(State, Client)}
+ end;
+connect_sequence_push_supplier(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPushConsumer --
+%%----------------------------------------------------------%
+%% function : connect_structured_push_supplier
+%% Arguments: Client - CosNotifyComm::StructuredPushSupplier
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%%-----------------------------------------------------------
+connect_structured_push_supplier(_OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
+ ?not_TypeCheck(Client, 'CosNotifyComm_StructuredPushSupplier'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, ?set_Client(State, Client)}
+ end;
+connect_structured_push_supplier(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ---
+%%----------------------------------------------------------%
+%% function : obtain_subscription_types
+%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
+%% Returns : CosNotification::EventTypeSeq
+%%-----------------------------------------------------------
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
+ {reply, ?get_AllPublish(State), ?set_PublishType(State, false)};
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
+ {reply, ?get_AllPublish(State), ?set_PublishType(State, true)};
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
+ {reply, [], ?set_PublishType(State, false)};
+obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
+ {reply, [], ?set_PublishType(State, true)};
+obtain_subscription_types(_,_,_,What) ->
+ orber:dbg("[~p] PusherConsumer:obtain_subscription_types(~p);~n"
+ "Incorrect enumerant", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : validate_event_qos
+%% Arguments: RequiredQoS - CosNotification::QoSProperties
+%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
+%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
+%%-----------------------------------------------------------
+validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
+ AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
+ ?get_LocalQoS(State)),
+ {reply, {ok, AvilableQoS}, State}.
+
+%%----- Inherit from CosNotification::QoSAdmin --------------
+%%----------------------------------------------------------%
+%% function : get_qos
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+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) ->
+ {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
+ proxy, ?get_MyAdmin(State),
+ false),
+ NewState = ?update_EventDB(State, LQS),
+ {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
+
+%%----------------------------------------------------------%
+%% 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),
+ proxy, ?get_MyAdmin(State),
+ false),
+ {reply, {ok, QoS}, State}.
+
+%%----- Inherit from CosNotifyComm::NotifyPublish -----------
+%%----------------------------------------------------------%
+%% function : offer_change
+%% Arguments: Added - #'CosNotification_EventType'{}
+%% Removed - #'CosNotification_EventType'{}
+%% Returns : ok |
+%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
+%%-----------------------------------------------------------
+offer_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
+ cosNotification_Filter:validate_types(Added),
+ cosNotification_Filter:validate_types(Removed),
+ %% On this "side" we don't really care about which
+ %% type of events the client will supply.
+ %% Perhaps, later on, if we want to check this against Filters
+ %% associated with this object we may change this approach, i.e., if
+ %% the filter will not allow passing certain event types. But the
+ %% user should see to that that situation never occurs. It would add
+ %% extra overhead. Also see PusherSupplier- and PullerSuppler-
+ %% 'subscription_change'.
+ update_publish(add, State, Added),
+ update_publish(remove, State, Removed),
+ case ?get_PublishType(State) of
+ true ->
+ %% Perhaps we should handle exception here?!
+ %% Probably not. Better to stay "on-line".
+ catch 'CosNotifyComm_NotifySubscribe':
+ subscription_change(?get_Client(State), Added, Removed),
+ ok;
+ _->
+ ok
+ end,
+ {reply, ok, State}.
+
+update_publish(_, _, [])->
+ ok;
+update_publish(add, State, [H|T]) ->
+ ?add_Publish(State, H),
+ update_publish(add, State, T);
+update_publish(remove, State, [H|T]) ->
+ ?del_Publish(State, H),
+ update_publish(remove, State, T).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
+%%----------------------------------------------------------%
+%% function : add_filter
+%% Arguments: Filter - CosNotifyFilter::Filter
+%% Returns : FilterID - long
+%%-----------------------------------------------------------
+add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
+ 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
+ FilterID = ?new_Id(State),
+ NewState = ?set_IdCounter(State, FilterID),
+ {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
+
+%%----------------------------------------------------------%
+%% function : remove_filter
+%% Arguments: FilterID - long
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ok, ?del_Filter(State, FilterID)};
+remove_filter(_,_,_,What) ->
+ orber:dbg("[~p] PusherConsumer:remove_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_filter
+%% Arguments: FilterID - long
+%% Returns : Filter - CosNotifyFilter::Filter |
+%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
+%%-----------------------------------------------------------
+get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ?get_Filter(State, FilterID), State};
+get_filter(_,_,_,What) ->
+ orber:dbg("[~p] PusherConsumer:get_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_all_filters
+%% Arguments: -
+%% Returns : Filter - CosNotifyFilter::FilterIDSeq
+%%-----------------------------------------------------------
+get_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_AllFilterID(State), State}.
+
+%%----------------------------------------------------------%
+%% function : remove_all_filters
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ok, ?del_AllFilter(State)}.
+
+%%----- Inherit from CosEventComm::PushConsumer -------------
+%%----------------------------------------------------------%
+%% function : disconnect_push_consumer
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_push_consumer(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----------------------------------------------------------%
+%% function : push
+%% Arguments: AnyEvent
+%% Returns : ok |
+%%-----------------------------------------------------------
+push(OE_THIS, OE_FROM, State, Event) when ?is_ANY(State) ->
+ corba:reply(OE_FROM, ok),
+ case {?not_isConvertedStructured(Event),
+ cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State))} of
+ {_, {[],_}} when ?is_ANDOP(State) ->
+ {noreply, State};
+ {true, {[],[_]}} ->
+ %% Is OR and converted, change back and forward to Admin
+ forward(seq, ?get_MyAdmin(State), State, [any:get_value(Event)],
+ 'MATCH', OE_THIS);
+ {_, {[],[_]}} ->
+ %% Is OR and not converted, forward to Admin
+ forward(any, ?get_MyAdmin(State), State, Event, 'MATCH', OE_THIS);
+ {true, {[_],_}} when ?is_ANDOP(State) ->
+ %% Is AND and converted, change back and forward to Admin
+ forward(seq, ?get_MyAdmin(State), State, [any:get_value(Event)],
+ 'MATCH', OE_THIS);
+ {true, {[_],_}} ->
+ %% Is OR and converted, change back and forward to Channel
+ forward(seq, ?get_MyChannel(State), State, [any:get_value(Event)],
+ 'MATCHED', OE_THIS);
+ {_, {[_],_}} when ?is_ANDOP(State) ->
+ %% Is AND and not converted, forward to Admin
+ forward(any, ?get_MyAdmin(State), State, Event, 'MATCH', OE_THIS);
+ _ ->
+ %% Is OR and not converted, forward to Channel
+ forward(any, ?get_MyChannel(State), State, Event, 'MATCHED', OE_THIS)
+ end;
+push(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- Inherit from CosNotifyComm::SequencePushConsumer ----
+%%----------------------------------------------------------%
+%% function : disconnect_sequence_push_consumer
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_sequence_push_consumer(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----------------------------------------------------------%
+%% function : push_structured_events
+%% Arguments: CosNotification::EventBatch
+%% Returns : ok |
+%%-----------------------------------------------------------
+push_structured_events(OE_THIS, OE_FROM, State, Events) when ?is_SEQUENCE(State) ->
+ corba:reply(OE_FROM, ok),
+ %% We cannot convert parts of the sequence to any, event though they
+ %% are converted from any to structured. Would be 'impossible' to send.
+ case cosNotification_eventDB:filter_events(Events, ?get_AllFilter(State)) of
+ {[],_} when ?is_ANDOP(State) ->
+ {noreply, State};
+ {[],Failed} ->
+ forward(seq, ?get_MyAdmin(State), State, Failed, 'MATCH', OE_THIS);
+ {Passed, _} when ?is_ANDOP(State) ->
+ forward(seq, ?get_MyAdmin(State), State, Passed, 'MATCH', OE_THIS);
+ {Passed, []} ->
+ forward(seq, ?get_MyChannel(State), State, Passed, 'MATCHED', OE_THIS);
+ {Passed, Failed} ->
+ %% Is OR, send Passed to channel and Failed to Admin.
+ forward(seq, ?get_MyChannel(State), State, Passed, 'MATCHED', OE_THIS),
+ forward(seq, ?get_MyAdmin(State), State, Failed, 'MATCH', OE_THIS)
+ end;
+push_structured_events(_,_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- Inherit from CosNotifyComm::StructuredPushConsumer --
+%%----------------------------------------------------------%
+%% function : disconnect_structured_push_consumer
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_structured_push_consumer(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----------------------------------------------------------%
+%% function : push_structured_event
+%% Arguments: CosNotification::StructuredEvent
+%% Returns : ok |
+%%-----------------------------------------------------------
+push_structured_event(OE_THIS, OE_FROM, State, Event) when ?is_STRUCTURED(State) ->
+ corba:reply(OE_FROM, ok),
+ case {?not_isConvertedAny(Event),
+ cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State))} of
+ {_, {[],_}} when ?is_ANDOP(State) ->
+ {noreply, State};
+ {true, {[],[_]}} ->
+ %% Is OR and converted, change back and forward to Admin
+ forward(any, ?get_MyAdmin(State), State,
+ Event#'CosNotification_StructuredEvent'.remainder_of_body,
+ 'MATCH', OE_THIS);
+ {_, {[],[_]}} ->
+ %% Is OR and not converted, forward to Admin
+ forward(seq, ?get_MyAdmin(State), State, [Event], 'MATCH', OE_THIS);
+ {true, {[_],_}} when ?is_ANDOP(State) ->
+ %% Is AND and converted, change back and forward to Admin
+ forward(any, ?get_MyAdmin(State), State,
+ Event#'CosNotification_StructuredEvent'.remainder_of_body,
+ 'MATCH', OE_THIS);
+ {true, {[_],_}} ->
+ %% Is OR and converted, change back and forward to Channel
+ forward(any, ?get_MyChannel(State), State,
+ Event#'CosNotification_StructuredEvent'.remainder_of_body,
+ 'MATCHED', OE_THIS);
+ {_, {[_],_}} when ?is_ANDOP(State) ->
+ %% Is AND and not converted, forward to Admin
+ forward(seq, ?get_MyAdmin(State), State, [Event], 'MATCH', OE_THIS);
+ _ ->
+ %% Is OR and not converted, forward to Channel
+ forward(seq, ?get_MyChannel(State), State, [Event], 'MATCHED', OE_THIS)
+ end;
+push_structured_event(_,_,_,_) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+find_obj({value, {_, Obj}}) -> Obj;
+find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
+
+find_ids(List) -> find_ids(List, []).
+find_ids([], Acc) -> Acc;
+find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
+find_ids(What, _) ->
+ orber:dbg("[~p] PusherConsumer:find_ids();~n"
+ "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+%% Delete a single object.
+%% The list don not differ, i.e., no filter removed, raise exception.
+delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
+delete_obj(List,_) -> List.
+
+%% Forward events
+forward(any, SendTo, State, Event, Status, OE_THIS) ->
+ case catch oe_CosNotificationComm_Event:callAny(SendTo, Event, Status) of
+ ok ->
+ ?DBG("PROXY FORWARD ANY: ~p~n",[Event]),
+ {noreply, State};
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ orber:dbg("[~p] PusherConsumer:forward();~n"
+ "Admin/Channel no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, OE_THIS},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PusherConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ R ->
+ orber:dbg("[~p] PusherConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, R, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, OE_THIS},
+ {client, ?get_Client(State)},
+ {reason, R}]),
+ {stop, normal, State}
+ end;
+forward(seq, SendTo, State, Event, Status, OE_THIS) ->
+ case catch oe_CosNotificationComm_Event:callSeq(SendTo, Event, Status) of
+ ok ->
+ {noreply, State};
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ ?DBG("ADMIN NO LONGER EXIST; DROPPING: ~p~n", [Event]),
+ 'CosNotification_Common':notify([{proxy, OE_THIS},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ R when ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PusherConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ R ->
+ orber:dbg("[~p] PusherConsumer:forward();~n"
+ "Admin/Channel respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, R, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, OE_THIS},
+ {client, ?get_Client(State)},
+ {reason, R}]),
+ {stop, normal, State}
+ end.
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/PusherSupplier_impl.erl b/lib/cosNotification/src/PusherSupplier_impl.erl
new file mode 100644
index 0000000000..51949b8c46
--- /dev/null
+++ b/lib/cosNotification/src/PusherSupplier_impl.erl
@@ -0,0 +1,1052 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : PusherSupplier_impl.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module('PusherSupplier_impl').
+
+
+%%--------------- INCLUDES -----------------------------------
+-include_lib("orber/include/corba.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+%% cosEvent files.
+-include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
+-include_lib("cosEvent/include/CosEventComm.hrl").
+%% Application files
+-include("CosNotification.hrl").
+-include("CosNotifyChannelAdmin.hrl").
+-include("CosNotifyComm.hrl").
+-include("CosNotifyFilter.hrl").
+
+-include("CosNotification_Definitions.hrl").
+
+%%--------------- EXPORTS ------------------------------------
+%%--------------- External -----------------------------------
+%%----- CosNotifyChannelAdmin::ProxyPushSupplier -------------
+-export([connect_any_push_consumer/4]).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPushSupplier ---
+-export([connect_structured_push_consumer/4]).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPushSupplier -----
+-export([connect_sequence_push_consumer/4]).
+
+%%----- CosNotifyChannelAdmin::*ProxyPushSupplier ------------
+-export([suspend_connection/3,
+ resume_connection/3]).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ----
+-export([obtain_offered_types/4,
+ validate_event_qos/4]).
+
+%%----- Inherit from CosNotification::QoSAdmin ---------------
+-export([get_qos/3,
+ set_qos/4,
+ validate_qos/4]).
+
+%%----- Inherit from CosNotifyComm::NotifySubscribe ----------
+-export([subscription_change/5]).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
+-export([add_filter/4,
+ remove_filter/4,
+ get_filter/4,
+ get_all_filters/3,
+ remove_all_filters/3]).
+
+%%----- Inherit from CosEventComm::PushSupplier -------------
+-export([disconnect_push_supplier/3]).
+
+%%----- Inherit from CosNotifyComm::StructuredPushSupplier --
+-export([disconnect_structured_push_supplier/3]).
+
+%%----- Inherit from CosNotifyComm::SequencePushSupplier ----
+-export([disconnect_sequence_push_supplier/3]).
+
+%%----- Inherit from CosEventChannelAdmin::ProxyPushSupplier
+-export([connect_push_consumer/4]).
+
+%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
+-export(['_get_MyType'/3,
+ '_get_MyAdmin'/3,
+ '_get_priority_filter'/3,
+ '_set_priority_filter'/4,
+ '_get_lifetime_filter'/3,
+ '_set_lifetime_filter'/4]).
+
+%%--------------- 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]).
+
+%%--------------- LOCAL DEFINITIONS --------------------------
+%% Data structures
+-record(state, {myType,
+ myAdmin,
+ myAdminPid,
+ myChannel,
+ myFilters = [],
+ myOperator,
+ idCounter = 0,
+ prioFil,
+ lifetFil,
+ client,
+ qosGlobal,
+ qosLocal,
+ suspended = false,
+ pacingTimer,
+ subscribeType = false,
+ subscribeData = true,
+ etsR,
+ eventDB,
+ this,
+ maxCache,
+ cacheTimeout,
+ cacheInterval}).
+
+%% Data structures constructors
+-define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _MyOp, _GT, _GL, _TR),
+ #state{myType = _MyT,
+ myAdmin = _MyA,
+ myAdminPid= _MyAP,
+ qosGlobal = _QS,
+ qosLocal = _LQS,
+ myChannel = _Ch,
+ myOperator=_MyOp,
+ etsR = ets:new(oe_ets, [set, protected]),
+ eventDB = cosNotification_eventDB:create_db(_LQS, _GT, _GL, _TR),
+ maxCache = cosNotificationApp:max_events()}).
+
+%% Data structures selectors
+%%-------------- Data structures selectors -----------------
+%% Attributes
+-define(get_MyType(S), S#state.myType).
+-define(get_MyAdmin(S), S#state.myAdmin).
+-define(get_MyAdminPid(S), S#state.myAdminPid).
+-define(get_MyChannel(S), S#state.myChannel).
+-define(get_MyOperator(S), S#state.myOperator).
+-define(get_PrioFil(S), S#state.prioFil).
+-define(get_LifeTFil(S), S#state.lifetFil).
+%% Client Object
+-define(get_Client(S), S#state.client).
+%% QoS
+-define(get_GlobalQoS(S), S#state.qosGlobal).
+-define(get_LocalQoS(S), S#state.qosLocal).
+-define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
+%% Filters
+-define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
+-define(get_AllFilter(S), S#state.myFilters).
+-define(get_AllFilterID(S), find_ids(S#state.myFilters)).
+%% Amin
+-define(get_PacingTimer(S), S#state.pacingTimer).
+-define(get_PacingInterval(S), round(?not_GetPacingInterval((S#state.qosLocal))/10000000)).
+-define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
+%% Subscribe
+-define(get_AllSubscribe(S), lists:flatten(ets:match(S#state.etsR,
+ {'$1',subscribe}))).
+-define(get_SubscribeType(S), S#state.subscribeType).
+-define(get_SubscribeData(S), S#state.subscribeData).
+%% ID
+-define(get_IdCounter(S), S#state.idCounter).
+-define(get_SubscribeDB(S), S#state.etsR).
+%% Event
+-define(is_PersistentConnection(S),
+ (?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent)).
+-define(is_PersistentEvent(S),
+ (?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent)).
+
+-define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB,
+ false)).
+% (not ?is_PersistentEvent(S)))).
+-define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M, false)).
+% (not ?is_PersistentEvent(S)))).
+
+%%-------------- Data structures modifiers -----------------
+%% Attributes
+-define(set_PrioFil(S,D), S#state{prioFil=D}).
+-define(set_LifeTFil(S,D), S#state{lifetFil=D}).
+%% Client Object
+-define(set_Client(S,D), S#state{client=D}).
+-define(del_Client(S), S#state{client=undefined}).
+-define(set_Unconnected(S), S#state{client=undefined}).
+-define(set_Suspended(S), S#state{suspended=true}).
+-define(set_NotSuspended(S), S#state{suspended=false}).
+%% QoS
+-define(set_LocalQoS(S,D), S#state{qosLocal=D}).
+-define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
+-define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
+%% Filters
+-define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
+-define(del_Filter(S,I), S#state{myFilters=
+ delete_obj(lists:keydelete(I, 1, S#state.myFilters),
+ S#state.myFilters)}).
+-define(del_AllFilter(S), S#state{myFilters=[]}).
+%% Admin
+-define(set_PacingTimer(S,T), S#state{pacingTimer=T}).
+%% Publish
+%% Subscribe
+-define(add_Subscribe(S,E), ets:insert(S#state.etsR, {E, subscribe})).
+-define(del_Subscribe(S,E), ets:delete(S#state.etsR, E)).
+-define(set_SubscribeType(S,T), S#state{subscribeType=T}).
+-define(set_SubscribeData(S,D), S#state{subscribeData=D}).
+%% ID
+-define(set_IdCounter(S,V), S#state{idCounter=V}).
+-define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
+%% Events
+-define(add_Event(S,E), catch cosNotification_eventDB:
+ add_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil)).
+-define(addAndGet_Event(S,E), catch cosNotification_eventDB:
+ add_and_get_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil,
+ false)).
+% ?is_PersistentEvent(S))).
+-define(update_EventDB(S,Q), S#state{eventDB=
+ cosNotification_eventDB:update(S#state.eventDB, Q)}).
+
+
+%%-------------- MISC ----------------------------------------
+-define(is_ANY(S), S#state.myType == 'PUSH_ANY').
+-define(is_STRUCTURED(S), S#state.myType == 'PUSH_STRUCTURED').
+-define(is_SEQUENCE(S), S#state.myType == 'PUSH_SEQUENCE').
+-define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
+-define(is_UnConnected(S), S#state.client == undefined).
+-define(is_Connected(S), S#state.client =/= undefined).
+-define(is_Suspended(S), S#state.suspended == true).
+-define(is_NotSuspended(S), S#state.suspended == false).
+-define(is_BatchLimitReached(S), cosNotification_eventDB:status(S#state.eventDB,
+ {batchLimit,
+ ?not_GetMaximumBatchSize((S#state.qosLocal))})).
+-define(has_Filters(S), S#state.myFilters =/= []).
+
+%%----------------------------------------------------------%
+%% 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{cacheTimeout = Timeout,
+ cacheInterval = Interval} = State) ->
+ ?DBG("INFO: ~p~n", [Info]),
+ case Info of
+ {'EXIT', Pid, Reason} when ?get_MyAdminPid(State)==Pid ->
+ ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
+ {stop, Reason, State};
+ {'EXIT', _Pid, _Reason} ->
+ ?DBG("PROXYPUSHSUPPLIER: ~p TERMINATED.~n",[_Reason]),
+ {noreply, State};
+ pacing ->
+ lookup_and_push(State, true);
+ cacheInterval ->
+ lookup_and_push(State, true);
+ cacheTimeout when Timeout == undefined, Interval == undefined ->
+ %% Late message, do not terminate
+ {noreply, State};
+ cacheTimeout ->
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, State#state.client},
+ {reason,
+ {timer, "Reached upper limit"}}]),
+ {stop, normal, State};
+ _ ->
+ {noreply, State}
+ end.
+
+%%----------------------------------------------------------%
+%% function : init, terminate
+%% Arguments:
+%%-----------------------------------------------------------
+
+init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, Options, Operator]) ->
+ process_flag(trap_exit, true),
+ GCTime = 'CosNotification_Common':get_option(gcTime, Options,
+ ?not_DEFAULT_SETTINGS),
+ GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
+ ?not_DEFAULT_SETTINGS),
+ TimeRef = 'CosNotification_Common':get_option(timeService, Options,
+ ?not_DEFAULT_SETTINGS),
+ timer:start(),
+ {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid,
+ InitQoS, LQS, MyChannel, Operator, GCTime, GCLimit, TimeRef)}.
+
+terminate(_Reason, State) when ?is_UnConnected(State) ->
+ stop_timer(State#state.cacheTimeout),
+ stop_timer(State#state.cacheInterval),
+ stop_timer(State#state.pacingTimer),
+ %% We are not connected to a Client. Hence, no need to invoke disconnect.
+ ok;
+terminate(_Reason, State) when ?is_ANY(State) ->
+ stop_timer(State#state.cacheTimeout),
+ stop_timer(State#state.cacheInterval),
+ stop_timer(State#state.pacingTimer),
+ 'CosNotification_Common':disconnect('CosEventComm_PushConsumer',
+ disconnect_push_consumer,
+ ?get_Client(State));
+terminate(_Reason, State) when ?is_SEQUENCE(State) ->
+ stop_timer(State#state.cacheTimeout),
+ stop_timer(State#state.cacheInterval),
+ stop_timer(State#state.pacingTimer),
+ 'CosNotification_Common':disconnect('CosNotifyComm_SequencePushConsumer',
+ disconnect_sequence_push_consumer,
+ ?get_Client(State));
+terminate(_Reason, State) when ?is_STRUCTURED(State) ->
+ stop_timer(State#state.cacheTimeout),
+ stop_timer(State#state.cacheInterval),
+ stop_timer(State#state.pacingTimer),
+ 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPushConsumer',
+ disconnect_structured_push_consumer,
+ ?get_Client(State)).
+
+%%-----------------------------------------------------------
+%%----- CosNotifyChannelAdmin_ProxySupplier attributes ------
+%%-----------------------------------------------------------
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyType'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyType(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_get_MyAdmin'
+%% Type : readonly
+%% Returns :
+%%-----------------------------------------------------------
+'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_MyAdmin(State), State}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_*et_priority_filter'
+%% Type : read/write
+%% Returns :
+%%-----------------------------------------------------------
+'_get_priority_filter'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_PrioFil(State), State}.
+'_set_priority_filter'(_OE_THIS, _OE_FROM, State, PrioF) ->
+ {reply, ok, ?set_PrioFil(State, PrioF)}.
+
+%%----------------------------------------------------------%
+%% Attribute: '_*et_lifetime_filter'
+%% Type : read/write
+%% Returns :
+%%-----------------------------------------------------------
+'_get_lifetime_filter'(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_LifeTFil(State), State}.
+'_set_lifetime_filter'(_OE_THIS, _OE_FROM, State, LifeTF) ->
+ {reply, ok, ?set_LifeTFil(State, LifeTF)}.
+
+%%-----------------------------------------------------------
+%%------- Exported external functions -----------------------
+%%-----------------------------------------------------------
+%%----- CosEventChannelAdmin::ProxyPushSupplier -------------
+%%----------------------------------------------------------%
+%% function : connect_push_consumer
+%% Arguments: Client - CosEventComm::PushConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%% Both exceptions from CosEventChannelAdmin!!!!
+%%-----------------------------------------------------------
+connect_push_consumer(OE_THIS, OE_FROM, State, Client) ->
+ connect_any_push_consumer(OE_THIS, OE_FROM, State, Client).
+
+%%----- CosNotifyChannelAdmin::ProxyPushSupplier ------------
+%%----------------------------------------------------------%
+%% function : connect_any_push_consumer
+%% Arguments: Client - CosEventComm::PushConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%% Both exceptions from CosEventChannelAdmin!!!!
+%%-----------------------------------------------------------
+connect_any_push_consumer(OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
+ 'CosNotification_Common':type_check(Client, 'CosEventComm_PushConsumer'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, State#state{client = Client, this = OE_THIS}}
+ end;
+connect_any_push_consumer(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::SequenceProxyPushSupplier ----
+%%----------------------------------------------------------%
+%% function : connect_sequence_push_consumer
+%% Arguments: Client - CosNotifyComm::SequencePushConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%%-----------------------------------------------------------
+connect_sequence_push_consumer(OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
+ 'CosNotification_Common':type_check(Client,
+ 'CosNotifyComm_SequencePushConsumer'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ NewState = start_timer(State),
+ {reply, ok, NewState#state{client = Client, this = OE_THIS}}
+ end;
+connect_sequence_push_consumer(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::StructuredProxyPushSupplier ---
+%%----------------------------------------------------------%
+%% function : connect_structured_push_consumer
+%% Arguments: Client - CosNotifyComm::StructuredPushConsumer
+%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
+%% {'EXCEPTION', #'TypeError'{}}
+%%-----------------------------------------------------------
+connect_structured_push_consumer(OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
+ 'CosNotification_Common':type_check(Client,
+ 'CosNotifyComm_StructuredPushConsumer'),
+ if
+ ?is_Connected(State) ->
+ corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
+ true ->
+ {reply, ok, State#state{client = Client, this = OE_THIS}}
+ end;
+connect_structured_push_consumer(_, _, _, _) ->
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----- CosNotifyChannelAdmin::*ProxyPushSupplier -----------
+%%----------------------------------------------------------%
+%% function : suspend_connection
+%% Arguments:
+%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyInactive'{}} |
+%% {'EXCEPTION', #'NotConneced'{}}
+%%-----------------------------------------------------------
+suspend_connection(_OE_THIS, _OE_FROM, State) when ?is_Connected(State) ->
+ if
+ ?is_Suspended(State) ->
+ corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{});
+ true ->
+ stop_timer(State#state.pacingTimer),
+ {reply, ok, State#state{pacingTimer = undefined,
+ suspended=true}}
+ end;
+suspend_connection(_,_,_)->
+ corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
+
+%%----------------------------------------------------------%
+%% function : resume_connection
+%% Arguments:
+%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyActive'{}} |
+%% {'EXCEPTION', #'NotConneced'{}}
+%%-----------------------------------------------------------
+resume_connection(_OE_THIS, OE_FROM, State) when ?is_Connected(State) ->
+ if
+ ?is_NotSuspended(State) ->
+ corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyActive'{});
+ true ->
+ corba:reply(OE_FROM, ok),
+ if
+ ?is_SEQUENCE(State) ->
+ start_timer(State);
+ true ->
+ ok
+ end,
+ lookup_and_push(?set_NotSuspended(State))
+ end;
+resume_connection(_,_,_) ->
+ corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
+
+%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ---
+%%----------------------------------------------------------%
+%% function : obtain_offered_types
+%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
+%% Returns : CosNotification::EventTypeSeq
+%%-----------------------------------------------------------
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
+ {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, false)};
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
+ {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, true)};
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
+ {reply, [], ?set_SubscribeType(State, false)};
+obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
+ {reply, [], ?set_SubscribeType(State, true)};
+obtain_offered_types(_,_,_,What) ->
+ orber:dbg("[~p] PusherSupplier:obtain_offered_types(~p);~n"
+ "Bad enumerant", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : validate_event_qos
+%% Arguments: RequiredQoS - CosNotification::QoSProperties
+%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
+%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
+%%-----------------------------------------------------------
+validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
+ AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
+ ?get_LocalQoS(State)),
+ {reply, {ok, AvilableQoS}, State}.
+
+%%----- Inherit from CosNotification::QoSAdmin --------------
+%%----------------------------------------------------------%
+%% function : get_qos
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+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) ->
+ {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
+ proxy, ?get_MyAdmin(State),
+ false),
+ NewState = ?update_EventDB(State, LQS),
+ {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
+
+%%----------------------------------------------------------%
+%% 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),
+ proxy, ?get_MyAdmin(State),
+ false),
+ {reply, {ok, QoS}, State}.
+
+%%----- Inherit from CosNotifyComm::NotifySubscribe ---------
+%%----------------------------------------------------------%
+%% function : subscription_change
+%% Arguments: Added - #'CosNotification_EventType'{}
+%% Removed - #'CosNotification_EventType'{}
+%% Returns : ok |
+%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
+%%-----------------------------------------------------------
+subscription_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
+ cosNotification_Filter:validate_types(Added),
+ cosNotification_Filter:validate_types(Removed),
+ %% On this "side", we care about which type of events the client
+ %% will require, since the client (or an agent) clearly stated
+ %% that it's only interested in these types of events.
+ %% Also see PusherConsumer- and PullerConsumer-'offer_change'.
+ update_subscribe(remove, State, Removed),
+ CurrentSub = ?get_AllSubscribe(State),
+ NewState =
+ case cosNotification_Filter:check_types(Added++CurrentSub) of
+ true ->
+ %% Types supplied does in some way cause all events to be valid.
+ %% Smart? Would have been better to not supply any at all.
+ ?set_SubscribeData(State, true);
+ {ok, Which, WC} ->
+ ?set_SubscribeData(State, {Which, WC})
+ end,
+ update_subscribe(add, NewState, Added),
+ case ?get_SubscribeType(NewState) of
+ true ->
+ %% Perhaps we should handle exception here?!
+ %% Probably not. Better to stay "on-line".
+ catch 'CosNotifyComm_NotifyPublish':
+ offer_change(?get_Client(NewState), Added, Removed),
+ ok;
+ _->
+ ok
+ end,
+ {reply, ok, NewState}.
+
+update_subscribe(_, _, [])->
+ ok;
+update_subscribe(add, State, [H|T]) ->
+ ?add_Subscribe(State, H),
+ update_subscribe(add, State, T);
+update_subscribe(remove, State, [H|T]) ->
+ ?del_Subscribe(State, H),
+ update_subscribe(remove, State, T).
+
+%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
+%%----------------------------------------------------------%
+%% function : add_filter
+%% Arguments: Filter - CosNotifyFilter::Filter
+%% Returns : FilterID - long
+%%-----------------------------------------------------------
+add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
+ 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
+ FilterID = ?new_Id(State),
+ NewState = ?set_IdCounter(State, FilterID),
+ {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
+
+%%----------------------------------------------------------%
+%% function : remove_filter
+%% Arguments: FilterID - long
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ok, ?del_Filter(State, FilterID)};
+remove_filter(_,_,_,What) ->
+ orber:dbg("[~p] PusherSupplier:remove_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_filter
+%% Arguments: FilterID - long
+%% Returns : Filter - CosNotifyFilter::Filter |
+%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
+%%-----------------------------------------------------------
+get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
+ {reply, ?get_Filter(State, FilterID), State};
+get_filter(_,_,_,What) ->
+ orber:dbg("[~p] PusherSupplier:get_filter(~p); Not an integer",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%----------------------------------------------------------%
+%% function : get_all_filters
+%% Arguments: -
+%% Returns : Filter - CosNotifyFilter::FilterIDSeq
+%%-----------------------------------------------------------
+get_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ?get_AllFilterID(State), State}.
+
+%%----------------------------------------------------------%
+%% function : remove_all_filters
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+remove_all_filters(_OE_THIS, _OE_FROM, State) ->
+ {reply, ok, ?del_AllFilter(State)}.
+
+
+%%----- Inherit from CosEventComm::PushSupplier -------------
+%%----------------------------------------------------------%
+%% function : disconnect_push_supplier
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_push_supplier(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----- Inherit from CosNotifyComm::StructuredPushSupplier --
+%%----------------------------------------------------------%
+%% function : disconnect_structured_push_supplier
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_structured_push_supplier(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%----- Inherit from CosNotifyComm::SequencePushSupplier ----
+%%----------------------------------------------------------%
+%% function : disconnect_sequence_push_supplier
+%% Arguments: -
+%% Returns : ok
+%%-----------------------------------------------------------
+disconnect_sequence_push_supplier(_OE_THIS, _OE_FROM, State) ->
+ {stop, normal, ok, ?set_Unconnected(State)}.
+
+%%--------------- LOCAL FUNCTIONS ----------------------------
+find_obj({value, {_, Obj}}) -> Obj;
+find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
+
+find_ids(List) -> find_ids(List, []).
+find_ids([], Acc) -> Acc;
+find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
+find_ids(What, _) ->
+ orber:dbg("[~p] PusherSupplier:find_ids();~n"
+ "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
+
+%% Delete a single object.
+%% The list do not differ, i.e., no filter removed, raise exception.
+delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
+delete_obj(List,_) -> List.
+
+%%-----------------------------------------------------------
+%% function : callSeq
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callSeq(_OE_THIS, OE_FROM, State, EventsIn, Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventsIn,
+ ?get_AllFilter(State),
+ ?get_SubscribeDB(State),
+ Status) of
+ {[],_} ->
+ ?DBG("PROXY NOSUBSCRIPTION SEQUENCE/STRUCTURED: ~p~n",[EventsIn]),
+ {noreply, State};
+ {Events,_} when ?is_Suspended(State) ->
+ store_events(State, Events),
+ {noreply, State};
+ {Events,_} when ?is_UnConnected(State) ->
+ orber:dbg("[~p] PusherSupplier:callAny();~n"
+ "Not connected, dropping event(s): ~p",
+ [?LINE, Events], ?DEBUG_LEVEL),
+ {noreply, State};
+ {[Event],_} when ?is_STRUCTURED(State) ->
+ ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Event]),
+ empty_db(State, ?addAndGet_Event(State, Event));
+ {[Event],_} when ?is_ANY(State) ->
+ ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Event]),
+ AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
+ empty_db(State, ?addAndGet_Event(State, AnyEvent));
+ {Events,_} ->
+ ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
+ store_events(State, Events),
+ lookup_and_push(State)
+ end.
+
+%%-----------------------------------------------------------
+%% function : callAny
+%% Arguments:
+%% Returns :
+%%-----------------------------------------------------------
+callAny(_OE_THIS, OE_FROM, State, EventIn, Status) ->
+ corba:reply(OE_FROM, ok),
+ case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventIn,
+ ?get_AllFilter(State),
+ ?get_SubscribeDB(State),
+ Status) of
+ {[],_} ->
+ ?DBG("PROXY NOSUBSCRIPTION ANY: ~p~n",[EventIn]),
+ %% To be on the safe side, test if there are any events that not
+ %% have been forwarded (should only be possible if StartTime is used).
+ lookup_and_push(State);
+ {Event,_} when ?is_Suspended(State), ?is_ANY(State) ->
+ ?add_Event(State, Event),
+ {noreply, State};
+ {Event,_} when ?is_Suspended(State) ->
+ ?add_Event(State, ?not_CreateSE("","%ANY","",[],[],Event)),
+ {noreply, State};
+ {Event,_} when ?is_UnConnected(State) ->
+ orber:dbg("[~p] PusherSupplier:callAny();~n"
+ "Not connected, dropping event: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ {noreply, State};
+ {Event,_} when ?is_ANY(State) ->
+ ?DBG("PROXY RECEIVED ANY: ~p~n",[Event]),
+ %% We must store the event since there may be other events that should
+ %% be delivered first, e.g., higher priority.
+ empty_db(State, ?addAndGet_Event(State, Event));
+ {Event,_} when ?is_SEQUENCE(State) ->
+ ?DBG("PROXY RECEIVED ANY==>SEQUENCE: ~p~n",[Event]),
+ StrEvent = ?not_CreateSE("","%ANY","",[],[],Event),
+ ?add_Event(State, StrEvent),
+ lookup_and_push(State);
+ {Event,_} ->
+ ?DBG("PROXY RECEIVED ANY==>STRUCTURED: ~p~n",[Event]),
+ StrEvent = ?not_CreateSE("","%ANY","",[],[],Event),
+ empty_db(State, ?addAndGet_Event(State, StrEvent))
+ end.
+
+%% Lookup and push "the correct" amount of events.
+lookup_and_push(State) ->
+ %% The boolean indicates, if false, that we will only push events if we have
+ %% passed the BatchLimit. If true we will ignore this limit and push events
+ %% anyway (typcially invoked when pacing limit passed).
+ lookup_and_push(State, false).
+lookup_and_push(State, false) when ?is_SEQUENCE(State) ->
+ case ?is_BatchLimitReached(State) of
+ true ->
+ case ?get_Events(State, ?get_BatchLimit(State)) of
+ {[], _, _} ->
+ ?DBG("BATCHLIMIT (~p) REACHED BUT NO EVENTS FOUND~n",
+ [?get_BatchLimit(State)]),
+ {noreply, State};
+ {Events, _, Keys} ->
+ ?DBG("BATCHLIMIT (~p) REACHED, EVENTS FOUND: ~p~n",
+ [?get_BatchLimit(State), Events]),
+ case catch 'CosNotifyComm_SequencePushConsumer':
+ push_structured_events(?get_Client(State), Events) of
+ ok ->
+ cosNotification_eventDB:delete_events(Keys),
+ lookup_and_push(reset_cache(State), false);
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ ?DBG("PUSH SUPPLIER CLIENT NO LONGER EXIST~n", []),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ What when ?is_PersistentEvent(State),
+ ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ check_cache(State);
+ What when ?is_PersistentConnection(State) ->
+ %% Here we should do something when we want to handle
+ %% Persistent EventReliability.
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p~n"
+ "Dropping events: ~p",
+ [?LINE, What, Events], ?DEBUG_LEVEL),
+ cosNotification_eventDB:delete_events(Keys),
+ {noreply, State};
+ WhatII ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p~n"
+ "Terminating and dropping events: ~p",
+ [?LINE, WhatII, Events], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, WhatII}]),
+ {stop, normal, State}
+ end
+ end;
+ _ ->
+ ?DBG("BATCHLIMIT (~p) NOT REACHED~n",[?get_BatchLimit(State)]),
+ {noreply, State}
+ end;
+lookup_and_push(State, true) when ?is_SEQUENCE(State) ->
+ case ?get_Events(State, ?get_BatchLimit(State)) of
+ {[], _, _} ->
+ ?DBG("PACELIMIT REACHED BUT NO EVENTS FOUND~n", []),
+ {noreply, State};
+ {Events, _, Keys} ->
+ ?DBG("PACELIMIT REACHED, EVENTS FOUND: ~p~n", [Events]),
+ case catch 'CosNotifyComm_SequencePushConsumer':
+ push_structured_events(?get_Client(State), Events) of
+ ok ->
+ cosNotification_eventDB:delete_events(Keys),
+ lookup_and_push(reset_cache(State), false);
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client no longer exists; terminating and dropping events: ~p",
+ [?LINE, Events], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ What when ?is_PersistentEvent(State),
+ ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ check_cache(State);
+ What when ?is_PersistentConnection(State) ->
+ %% Here we should do something when we want to handle
+ %% Persistent EventReliability.
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p~n"
+ "Dropping events: ~p",
+ [?LINE, What, Events], ?DEBUG_LEVEL),
+ cosNotification_eventDB:delete_events(Keys),
+ {noreply, State};
+ WhatII ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p~n"
+ "Terminating and dropping events: ~p",
+ [?LINE, WhatII, Events], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, WhatII}]),
+ {stop, normal, State}
+ end
+ end;
+lookup_and_push(State, _) ->
+ empty_db(State, ?get_Event(State)).
+
+
+%% Push all events stored while not connected or received in sequence.
+empty_db(State, {[], _, _}) ->
+ {noreply, State};
+empty_db(State, {Event, _, Keys}) when ?is_STRUCTURED(State) ->
+ case catch 'CosNotifyComm_StructuredPushConsumer':
+ push_structured_event(?get_Client(State), Event) of
+ ok ->
+ cosNotification_eventDB:delete_events(Keys),
+ NewState = reset_cache(State),
+ empty_db(NewState, ?get_Event(NewState));
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ orber:dbg("[~p] PusherSupplier:empty_db();~n"
+ "Client no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ What when ?is_PersistentEvent(State),
+ ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ check_cache(State);
+ What when ?is_PersistentConnection(State) ->
+ %% Here we should do something when we want to handle
+ %% Persistent EventReliability.
+ orber:dbg("[~p] PusherSupplier:empty_db();~n"
+ "Client respond incorrect: ~p~n"
+ "Dropping event: ~p",
+ [?LINE, What, Event], ?DEBUG_LEVEL),
+ cosNotification_eventDB:delete_events(Keys),
+ {noreply, State};
+ WhatII ->
+ orber:dbg("[~p] PusherSupplier:empty_db();~n"
+ "Client respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, WhatII, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, WhatII}]),
+ {stop, normal, State}
+ end;
+empty_db(State, {Event, _, Keys}) when ?is_ANY(State) ->
+ case catch 'CosEventComm_PushConsumer':push(?get_Client(State), Event) of
+ ok ->
+ cosNotification_eventDB:delete_events(Keys),
+ NewState = reset_cache(State),
+ empty_db(NewState, ?get_Event(NewState));
+ {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
+ is_record(E, 'NO_PERMISSION') orelse
+ is_record(E, 'CosEventComm_Disconnected') ->
+ orber:dbg("[~p] PusherSupplier:empty_db();~n"
+ "Client no longer exists; terminating and dropping: ~p",
+ [?LINE, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, {'EXCEPTION', E}}]),
+ {stop, normal, State};
+ What when ?is_PersistentEvent(State),
+ ?is_PersistentConnection(State) ->
+ orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
+ "Client respond incorrect: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ check_cache(State);
+ What when ?is_PersistentConnection(State) ->
+ %% Here we should do something when we want to handle
+ %% Persistent EventReliability.
+ orber:dbg("[~p] PusherSupplier:empty_db();~n"
+ "Client respond incorrect: ~p~n"
+ "Dropping Event: ~p",
+ [?LINE, What, Event], ?DEBUG_LEVEL),
+ cosNotification_eventDB:delete_events(Keys),
+ {noreply, State};
+ WhatII ->
+ orber:dbg("[~p] PusherSupplier:empty_db();~n"
+ "Client respond incorrect: ~p~n"
+ "Terminating and dropping: ~p",
+ [?LINE, WhatII, Event], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, ?get_Client(State)},
+ {reason, WhatII}]),
+ {stop, normal, State}
+ end.
+
+reset_cache(#state{cacheTimeout = undefined,
+ cacheInterval = undefined} = State) ->
+ State;
+reset_cache(State) ->
+ stop_timer(State#state.cacheTimeout),
+ stop_timer(State#state.cacheInterval),
+ State#state{cacheTimeout = undefined,
+ cacheInterval = undefined}.
+
+check_cache(#state{maxCache = Max, cacheTimeout = Timeout,
+ cacheInterval = Interval} = State) ->
+ case cosNotification_eventDB:status(State#state.eventDB, eventCounter) of
+ Count when Count > Max ->
+ %% Reached the upper limit, terminate.
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, State#state.client},
+ {reason, {max_events, Max}}]),
+ {stop, normal, State};
+ _ when Timeout == undefined, Interval == undefined ->
+ case {timer:send_interval(cosNotificationApp:interval_events(),
+ cacheInterval),
+ timer:send_after(cosNotificationApp:timeout_events(),
+ cacheTimeout)} of
+ {{ok, IntervalRef}, {ok, TimeoutRef}} ->
+ {noreply, State#state{cacheTimeout = TimeoutRef,
+ cacheInterval = IntervalRef}};
+ Error ->
+ orber:dbg("[~p] PusherSupplier:check_cache();~n"
+ "Unable to start timers: ~p",
+ [?LINE, Error], ?DEBUG_LEVEL),
+ 'CosNotification_Common':notify([{proxy, State#state.this},
+ {client, State#state.client},
+ {reason, {timer, Error}}]),
+ {stop, normal, State}
+ end;
+ _ ->
+ %% Timers already started.
+ {noreply, State}
+ end.
+
+store_events(_State, []) ->
+ ok;
+store_events(State, [Event|Rest]) when ?is_ANY(State) ->
+ AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
+ ?add_Event(State, AnyEvent),
+ store_events(State, Rest);
+store_events(State, [Event|Rest]) ->
+ ?add_Event(State, Event),
+ store_events(State, Rest).
+
+%% Start timers which send a message each time we should push events. Only used
+%% when this objects is defined to supply sequences.
+start_timer(State) ->
+ case ?get_PacingInterval(State) of
+ 0 ->
+ ?DBG("PUSH SUPPLIER STARTED NO TIMER (0), BATCH LIMIT: ~p~n",
+ [?get_BatchLimit(State)]),
+
+ State;
+ PacInt ->
+ case catch timer:send_interval(timer:seconds(PacInt), pacing) of
+ {ok,PacTRef} ->
+ ?DBG("PUSH SUPPLIER STARTED TIMER, BATCH LIMIT: ~p~n",
+ [?get_BatchLimit(State)]),
+ ?set_PacingTimer(State, PacTRef);
+ What ->
+ orber:dbg("[~p] PusherSupplier:start_timer();~n"
+ "Unable to invoke timer:send_interval/2: ~p",
+ [?LINE, What], ?DEBUG_LEVEL),
+ corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
+ end
+ end.
+
+stop_timer(undefined) ->
+ ?DBG("PUSH SUPPLIER HAVE NO TIMER TO STOP~n",[]),
+ ok;
+stop_timer(Timer) ->
+ ?DBG("PUSH SUPPLIER STOPPED TIMER~n",[]),
+ timer:cancel(Timer),
+ ok.
+
+
+%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/cosNotification.app.src b/lib/cosNotification/src/cosNotification.app.src
new file mode 100644
index 0000000000..04beac36e8
--- /dev/null
+++ b/lib/cosNotification/src/cosNotification.app.src
@@ -0,0 +1,120 @@
+{application, cosNotification,
+ [{description, "The Erlang CosNotification application"},
+ {vsn, "%VSN%"},
+ {modules,
+ [
+ 'CosNotification_Common',
+ 'CosNotifyChannelAdmin_ConsumerAdmin_impl',
+ 'CosNotifyChannelAdmin_EventChannelFactory_impl',
+ 'CosNotifyChannelAdmin_EventChannel_impl',
+ 'CosNotifyChannelAdmin_SupplierAdmin_impl',
+ 'PullerConsumer_impl',
+ 'PullerSupplier_impl',
+ 'PusherConsumer_impl',
+ 'PusherSupplier_impl',
+ 'cosNotificationApp',
+ 'CosNotifyFilter_Filter_impl',
+ 'CosNotifyFilter_MappingFilter_impl',
+ 'CosNotifyFilter_FilterFactory_impl',
+ 'cosNotification_Scanner',
+ 'cosNotification_Grammar',
+ 'cosNotification_Filter',
+ 'cosNotification_eventDB',
+ 'oe_CosNotification',
+ 'oe_cosNotificationAppComm',
+ 'oe_CosNotificationComm_Event',
+ 'CosNotification',
+ 'CosNotification_AdminPropertiesAdmin',
+ 'CosNotification_EventHeader',
+ 'CosNotification_EventType',
+ 'CosNotification_FixedEventHeader',
+ 'CosNotification_NamedPropertyRange',
+ 'CosNotification_Property',
+ 'CosNotification_PropertyError',
+ 'CosNotification_PropertyRange',
+ 'CosNotification_QoSAdmin',
+ 'CosNotification_StructuredEvent',
+ 'CosNotification_UnsupportedAdmin',
+ 'CosNotification_UnsupportedQoS',
+ 'CosNotification_EventBatch',
+ 'CosNotification_EventTypeSeq',
+ 'CosNotification_NamedPropertyRangeSeq',
+ 'CosNotification_PropertyErrorSeq',
+ 'CosNotification_PropertySeq',
+ 'oe_CosNotifyChannelAdmin',
+ 'CosNotifyChannelAdmin_AdminLimit',
+ 'CosNotifyChannelAdmin_AdminLimitExceeded',
+ 'CosNotifyChannelAdmin_AdminNotFound',
+ 'CosNotifyChannelAdmin_ChannelNotFound',
+ 'CosNotifyChannelAdmin_ConnectionAlreadyActive',
+ 'CosNotifyChannelAdmin_ConnectionAlreadyInactive',
+ 'CosNotifyChannelAdmin_ConsumerAdmin',
+ 'CosNotifyChannelAdmin_EventChannel',
+ 'CosNotifyChannelAdmin_EventChannelFactory',
+ 'CosNotifyChannelAdmin_NotConnected',
+ 'CosNotifyChannelAdmin_ProxyConsumer',
+ 'CosNotifyChannelAdmin_ProxyNotFound',
+ 'CosNotifyChannelAdmin_ProxyPullConsumer',
+ 'CosNotifyChannelAdmin_ProxyPullSupplier',
+ 'CosNotifyChannelAdmin_ProxyPushConsumer',
+ 'CosNotifyChannelAdmin_ProxyPushSupplier',
+ 'CosNotifyChannelAdmin_ProxySupplier',
+ 'CosNotifyChannelAdmin_SequenceProxyPullConsumer',
+ 'CosNotifyChannelAdmin_SequenceProxyPullSupplier',
+ 'CosNotifyChannelAdmin_SequenceProxyPushConsumer',
+ 'CosNotifyChannelAdmin_SequenceProxyPushSupplier',
+ 'CosNotifyChannelAdmin_StructuredProxyPullConsumer',
+ 'CosNotifyChannelAdmin_StructuredProxyPullSupplier',
+ 'CosNotifyChannelAdmin_StructuredProxyPushConsumer',
+ 'CosNotifyChannelAdmin_StructuredProxyPushSupplier',
+ 'CosNotifyChannelAdmin_SupplierAdmin',
+ 'CosNotifyChannelAdmin_AdminIDSeq',
+ 'CosNotifyChannelAdmin_ChannelIDSeq',
+ 'CosNotifyChannelAdmin_ProxyIDSeq',
+ 'oe_CosNotifyComm',
+ 'CosNotifyComm_InvalidEventType',
+ 'CosNotifyComm_NotifyPublish',
+ 'CosNotifyComm_NotifySubscribe',
+ 'CosNotifyComm_PullConsumer',
+ 'CosNotifyComm_PullSupplier',
+ 'CosNotifyComm_PushConsumer',
+ 'CosNotifyComm_PushSupplier',
+ 'CosNotifyComm_SequencePullConsumer',
+ 'CosNotifyComm_SequencePullSupplier',
+ 'CosNotifyComm_SequencePushConsumer',
+ 'CosNotifyComm_SequencePushSupplier',
+ 'CosNotifyComm_StructuredPullConsumer',
+ 'CosNotifyComm_StructuredPullSupplier',
+ 'CosNotifyComm_StructuredPushConsumer',
+ 'CosNotifyComm_StructuredPushSupplier',
+ 'oe_CosNotifyFilter',
+ 'CosNotifyFilter_CallbackNotFound',
+ 'CosNotifyFilter_ConstraintExp',
+ 'CosNotifyFilter_ConstraintInfo',
+ 'CosNotifyFilter_ConstraintNotFound',
+ 'CosNotifyFilter_DuplicateConstraintID',
+ 'CosNotifyFilter_Filter',
+ 'CosNotifyFilter_FilterAdmin',
+ 'CosNotifyFilter_FilterFactory',
+ 'CosNotifyFilter_FilterNotFound',
+ 'CosNotifyFilter_InvalidConstraint',
+ 'CosNotifyFilter_InvalidGrammar',
+ 'CosNotifyFilter_InvalidValue',
+ 'CosNotifyFilter_MappingConstraintInfo',
+ 'CosNotifyFilter_MappingConstraintPair',
+ 'CosNotifyFilter_MappingFilter',
+ 'CosNotifyFilter_UnsupportedFilterableData',
+ 'CosNotifyFilter_CallbackIDSeq',
+ 'CosNotifyFilter_ConstraintExpSeq',
+ 'CosNotifyFilter_ConstraintIDSeq',
+ 'CosNotifyFilter_ConstraintInfoSeq',
+ 'CosNotifyFilter_FilterIDSeq',
+ 'CosNotifyFilter_MappingConstraintInfoSeq',
+ 'CosNotifyFilter_MappingConstraintPairSeq'
+ ]
+ },
+ {registered, [cosNotificationSup, oe_cosNotificationFactory]},
+ {applications, [orber, stdlib, kernel]},
+ {env, []},
+ {mod, {cosNotificationApp, []}}
+]}.
diff --git a/lib/cosNotification/src/cosNotification.appup.src b/lib/cosNotification/src/cosNotification.appup.src
new file mode 100644
index 0000000000..6c3b2833b7
--- /dev/null
+++ b/lib/cosNotification/src/cosNotification.appup.src
@@ -0,0 +1,7 @@
+{"%VSN%",
+ [
+ ],
+ [
+ ]
+}.
+
diff --git a/lib/cosNotification/src/cosNotificationApp.erl b/lib/cosNotification/src/cosNotificationApp.erl
new file mode 100644
index 0000000000..ba44163272
--- /dev/null
+++ b/lib/cosNotification/src/cosNotificationApp.erl
@@ -0,0 +1,447 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : cosNotificationApp.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module(cosNotificationApp).
+
+%%--------------- INCLUDES -----------------------------------
+%% Local
+-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-------------------------------------
+%% cosNotification API external
+-export([start/0, stop/0,
+ start_factory/1, start_factory/0, stop_factory/1,
+ start_global_factory/0, start_global_factory/1,
+ start_filter_factory/1, start_filter_factory/0, stop_filter_factory/1,
+ install/0, install/1, uninstall/0, uninstall/1,
+ install_event/0, install_event/1, uninstall_event/0, uninstall_event/1,
+ install_typed/0, install_typed/1, uninstall_typed/0, uninstall_typed/1,
+ create_structured_event/6, type_check/0, notify/0, max_events/0,
+ timeout_events/0, interval_events/0]).
+
+%% Application callbacks
+-export([start/2, init/1, stop/1]).
+
+%%--------------- DEFINES ------------------------------------
+-define(IDL_MODULES, ['oe_CosNotification',
+ 'oe_cosNotificationAppComm',
+ 'oe_CosNotifyComm',
+ 'oe_CosNotifyFilter',
+ 'oe_CosNotifyChannelAdmin']).
+-define(EVENT_IDL_MODULES, ['oe_CosEventComm',
+ 'oe_CosEventChannelAdmin']).
+-define(TYPED_IDL_MODULES, ['oe_CosTypedEvent',
+ 'oe_CosTypedNotification']).
+
+-define(FACTORY_NAME, oe_cosNotificationFactory).
+-define(SUPERVISOR_NAME, cosNotificationSup).
+
+
+%%------------------------------------------------------------
+%% function : install/X
+%% Arguments: - | Time (seconds)
+%% Returns : ok | EXIT | EXCEPTION
+%% Effect : Install necessary data in the IFR DB
+%%------------------------------------------------------------
+
+install() ->
+ install(0).
+
+install(Time) when is_integer(Time) ->
+ install_loop(?IDL_MODULES, timer:seconds(Time));
+install(_Time) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%------------------------------------------------------------
+%% function : install_event/X
+%% Arguments: - | Time (seconds)
+%% Returns : ok | EXIT | EXCEPTION
+%% Effect : Install necessary data in the IFR DB
+%%------------------------------------------------------------
+
+install_event() ->
+ install_event(0).
+
+install_event(Time) when is_integer(Time) ->
+ install_loop(?EVENT_IDL_MODULES, timer:seconds(Time));
+install_event(_Time) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%------------------------------------------------------------
+%% function : install_typed/X
+%% Arguments: - | Time (seconds)
+%% Returns : ok | EXIT | EXCEPTION
+%% Effect : Install necessary data in the IFR DB
+%%------------------------------------------------------------
+
+install_typed() ->
+ install_typed(0).
+
+install_typed(Time) when is_integer(Time) ->
+ install_loop(?TYPED_IDL_MODULES, timer:seconds(Time));
+install_typed(_Time) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+install_loop([], _) ->
+ ok;
+install_loop([H|T], Time) ->
+ H:'oe_register'(),
+ timer:sleep(Time),
+ install_loop(T, Time).
+
+%%------------------------------------------------------------
+%% function : uninstall/X
+%% Arguments: - | Time (seconds)
+%% Returns : ok | EXIT | EXCEPTION
+%% Effect : Remove data related to cosNotificationin from the IFR DB
+%%------------------------------------------------------------
+
+uninstall() ->
+ uninstall(0).
+
+uninstall(Time) when is_integer(Time) ->
+ uninstall_loop(lists:reverse(?IDL_MODULES), timer:seconds(Time));
+uninstall(_Time) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%------------------------------------------------------------
+%% function : uninstall_event/X
+%% Arguments: - | Time (seconds)
+%% Returns : ok | EXIT | EXCEPTION
+%% Effect : Remove data related to cosNotificationin from the IFR DB
+%%------------------------------------------------------------
+
+uninstall_event() ->
+ uninstall_event(0).
+
+uninstall_event(Time) when is_integer(Time) ->
+ uninstall_loop(lists:reverse(?EVENT_IDL_MODULES), timer:seconds(Time));
+uninstall_event(_Time) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%------------------------------------------------------------
+%% function : uninstall_typed/X
+%% Arguments: - | Time (seconds)
+%% Returns : ok | EXIT | EXCEPTION
+%% Effect : Remove data related to cosNotificationin from the IFR DB
+%%------------------------------------------------------------
+
+uninstall_typed() ->
+ uninstall_typed(0).
+
+uninstall_typed(Time) when is_integer(Time) ->
+ uninstall_loop(lists:reverse(?TYPED_IDL_MODULES), timer:seconds(Time));
+uninstall_typed(_Time) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+uninstall_loop([], _) ->
+ ok;
+uninstall_loop([H|T], Time) ->
+ H:'oe_unregister'(),
+ timer:sleep(Time),
+ uninstall_loop(T, Time).
+
+
+%%------------------------------------------------------------
+%% function : start/stop
+%% Arguments:
+%% Returns :
+%% Effect : Starts or stops the cosTRansaction application.
+%%------------------------------------------------------------
+
+start() ->
+ application:start(cosNotification).
+stop() ->
+ application:stop(cosNotification).
+
+%%------------------------------------------------------------
+%% function : start_factory
+%% Arguments: none or an argumentlist whith default values.
+%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
+%% Effect : Starts a CosNotifyChannelAdmin_EventChannelFactory
+%%------------------------------------------------------------
+start_factory() ->
+ start_factory(?not_DEFAULT_SETTINGS).
+
+start_factory(Args) when is_list(Args) ->
+ SO = 'CosNotification_Common':get_option(server_options, Args, ?not_DEFAULT_SETTINGS),
+ SPEC = ['CosNotifyChannelAdmin_EventChannelFactory',Args,
+ [{sup_child, true},
+ {regname, {local, oe_cosNotificationFactory}}|SO]],
+ case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
+ {ok, Pid, Obj} when is_pid(Pid) ->
+ Obj;
+ Other->
+ orber:dbg("[~p] cosNotificationApp:start_factory( ~p ).~n"
+ "Reason: ~p~n", [?LINE, Args, Other], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+start_factory(Args) ->
+ orber:dbg("[~p] cosNotificationApp:start_factory( ~p ).~n"
+ "Bad parameters~n", [?LINE, Args], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+%%------------------------------------------------------------
+%% function : start_global_factory
+%% Arguments: none or an argumentlist whith default values.
+%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
+%% Effect : Starts a CosNotifyChannelAdmin_EventChannelFactory
+%%------------------------------------------------------------
+start_global_factory() ->
+ start_global_factory(?not_DEFAULT_SETTINGS).
+
+start_global_factory(Args) when is_list(Args) ->
+ SO = 'CosNotification_Common':get_option(server_options, Args, ?not_DEFAULT_SETTINGS),
+ Name = create_name(),
+ SPEC = ['CosNotifyChannelAdmin_EventChannelFactory',Args,
+ [{sup_child, true},
+ {regname, {global, Name}}|SO]],
+ case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
+ {ok, Pid, Obj} when is_pid(Pid) ->
+ Obj;
+ Other->
+ orber:dbg("[~p] cosNotificationApp:start_global_factory( ~p ).~n"
+ "Reason: ~p~n", [?LINE, Args, Other], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+start_global_factory(Args) ->
+ orber:dbg("[~p] cosNotificationApp:start_global_factory( ~p ).~n"
+ "Bad parameters~n", [?LINE, Args], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+
+%%------------------------------------------------------------
+%% function : stop_factory
+%% Arguments: Factory Object Reference
+%% Returns : ok | {'EXCEPTION', _}
+%% Effect :
+%%------------------------------------------------------------
+
+stop_factory(Fac)->
+ corba:dispose(Fac).
+
+%%------------------------------------------------------------
+%% function : start_filter_factory
+%% Arguments: none or an argumentlist which by default is defined
+%% in CosNotification_Definitions.hrl, i.e., '?not_FILTERFAC_DEF'
+%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
+%% Effect : Starts a CosNotifyChannelAdmin_EventChannelFactory
+%%------------------------------------------------------------
+start_filter_factory() ->
+ start_filter_factory([{typecheck, true},
+ {tty, false},
+ {logfile, false},
+ {server_options, []}]).
+start_filter_factory(Args) when is_list(Args) ->
+ SO = 'CosNotification_Common':get_option(server_options, Args,
+ ?not_DEFAULT_SETTINGS),
+ SPEC = ['CosNotifyFilter_FilterFactory',Args, [{sup_child, true}|SO]],
+ case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
+ {ok, Pid, Obj} when is_pid(Pid) ->
+ Obj;
+ Other->
+ orber:dbg("[~p] cosNotificationApp:start_filter_factory( ~p ).~n"
+ "Reason: ~p~n", [?LINE, Args, Other], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+start_filter_factory(Args) ->
+ orber:dbg("[~p] cosNotificationApp:start_filter_factory( ~p ).~n"
+ "Bad parameters~n", [?LINE, Args], ?DEBUG_LEVEL),
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+
+%%------------------------------------------------------------
+%% function : stop_filter_factory
+%% Arguments: FilterFactory Object Reference
+%% Returns : ok | {'EXCEPTION', _}
+%% Effect :
+%%------------------------------------------------------------
+
+stop_filter_factory(Fac)->
+ corba:dispose(Fac).
+
+
+%%------------------------------------------------------------
+%% function : create_structured_event
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+create_structured_event(StrD,StrT,StrE,PSeqV,PSeqF,AnyR)
+ when is_list(StrD) andalso is_list(StrT) andalso is_list(StrE)
+ andalso is_list(PSeqV) andalso is_list(PSeqF) andalso
+ is_record(AnyR, any) ->
+#'CosNotification_StructuredEvent'{header =
+ #'CosNotification_EventHeader'{fixed_header =
+ #'CosNotification_FixedEventHeader'{event_type =
+ #'CosNotification_EventType'{domain_name=StrD,
+ type_name=StrT},
+ event_name = StrE},
+ variable_header = PSeqV},
+ filterable_data = PSeqF,
+ remainder_of_body = AnyR};
+create_structured_event(_StrD,_StrT,_StrE,_PSeqV,_PSeqF,_AnyR) ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+
+%%------------------------------------------------------------
+%% function : type_check
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+type_check() ->
+ case application:get_env(cosNotification, type_check) of
+ {ok, Boolean} when is_atom(Boolean) ->
+ Boolean;
+ _ ->
+ true
+ end.
+
+%%------------------------------------------------------------
+%% function : notify
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+notify() ->
+ case application:get_env(cosNotification, notify) of
+ {ok, Module} when is_atom(Module) ->
+ Module;
+ _ ->
+ false
+ end.
+
+%%------------------------------------------------------------
+%% function : max_events
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+max_events() ->
+ case application:get_env(cosNotification, max_events) of
+ {ok, Max} when is_integer(Max) ->
+ Max;
+ _ ->
+ 50
+ end.
+
+%%------------------------------------------------------------
+%% function : timeout_events
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+timeout_events() ->
+ case application:get_env(cosNotification, timeout_events) of
+ {ok, Max} when is_integer(Max) ->
+ Max;
+ _ ->
+ 3000000 %% 5 minutes
+ end.
+
+
+%%------------------------------------------------------------
+%% function : interval_events
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+interval_events() ->
+ case application:get_env(cosNotification, interval_events) of
+ {ok, Max} when is_integer(Max) ->
+ Max;
+ _ ->
+ 10000 %% 10 seconds
+ end.
+
+
+%%------------------------------------------------------------
+%% function : start
+%% Arguments: Type - see module application
+%% Arg - see module application
+%% Returns :
+%% Effect : Module callback for application
+%%------------------------------------------------------------
+
+start(_, _) ->
+ supervisor:start_link({local, ?SUPERVISOR_NAME}, cosNotificationApp, 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,{{simple_one_for_one,50,10},
+ [{"oe_NotChild",
+ {'CosNotification_Common',create_link, []},
+ transient,100000,worker,
+ ['CosNotifyChannelAdmin_EventChannel',
+ 'CosNotifyChannelAdmin_EventChannel_impl']}]}};
+%% When starting as an application.
+init(app_init) ->
+ {ok,{{simple_one_for_one,50,10},
+ [{"oe_NotChild",
+ {'CosNotification_Common',create_link, []},
+ transient,100000,worker,
+ ['CosNotifyChannelAdmin_EventChannel',
+ 'CosNotifyChannelAdmin_EventChannel_impl']}]}}.
+
+
+
+%%------------------------------------------------------------
+%% function : create_name
+%% Arguments:
+%% Returns :
+%% Effect : Create a unique name to use when, for eaxmple, starting
+%% a new server.
+%%------------------------------------------------------------
+create_name() ->
+ {MSec, Sec, USec} = erlang:now(),
+ lists:concat(['oe_',node(),'_',MSec, '_', Sec, '_', USec]).
+
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/cosNotificationAppComm.idl b/lib/cosNotification/src/cosNotificationAppComm.idl
new file mode 100644
index 0000000000..09e0af2568
--- /dev/null
+++ b/lib/cosNotification/src/cosNotificationAppComm.idl
@@ -0,0 +1,17 @@
+#ifndef _OE_COSNOTIFICATIONCOMM_IDL_
+#define _OE_COSNOTIFICATIONCOMM_IDL_
+
+#include<CosNotification.idl>
+
+module oe_CosNotificationComm {
+
+ interface Event {
+
+ enum status {MATCH, MATCHED};
+ void callSeq(in CosNotification::EventBatch events, in status stat);
+ void callAny(in any event, in status stat);
+ };
+
+};
+#endif /* ifndef _OE_COSNOTIFICATIONCOMM_IDL_ */
+
diff --git a/lib/cosNotification/src/cosNotificationComm.cfg b/lib/cosNotification/src/cosNotificationComm.cfg
new file mode 100644
index 0000000000..89d207528d
--- /dev/null
+++ b/lib/cosNotification/src/cosNotificationComm.cfg
@@ -0,0 +1,3 @@
+{this, "oe_CosNotificationComm::Event"}.
+{from, "oe_CosNotificationComm::Event"}.
+{{handle_info, "oe_CosNotificationComm::Event"}, true}.
diff --git a/lib/cosNotification/src/cosNotification_Filter.erl b/lib/cosNotification/src/cosNotification_Filter.erl
new file mode 100644
index 0000000000..dd3b5beb93
--- /dev/null
+++ b/lib/cosNotification/src/cosNotification_Filter.erl
@@ -0,0 +1,964 @@
+%%--------------------------------------------------------------------
+%%
+%% %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 : cosNotification_Filter.erl
+%% Purpose :
+%%----------------------------------------------------------------------
+
+-module(cosNotification_Filter).
+
+
+%%--------------- 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 ------------------------------------
+%% Internal Filter Functions
+-export([eval/1,
+ eval/2,
+ create_filter/1,
+ check_types/1,
+ match_types/3,
+ validate_types/1]).
+
+%%--------------- DEFINES ------------------------------------
+-define(EVENT_PATH, [{dotid,"header"}, {dotid,"fixed_header"},
+ {dotid,"event_name"}]).
+-define(DOMAIN_PATH, [{dotid,"header"}, {dotid,"fixed_header"},
+ {dotid,"event_type"}, {dotid,"domain_name"}]).
+-define(TYPE_PATH, [{dotid,"header"}, {dotid,"fixed_header"},
+ {dotid,"event_type"}, {dotid,"type_name"}]).
+-define(VARIABLE_PATH(I), [{dotid,"header"}, {dotid,"variable_header"}, {dotid,I}]).
+-define(FILTERABLE_PATH(I), [{dotid,"filterable_data"}, {dotid,I}]).
+
+
+%%------------------------------------------------------------
+%%--------------- FILTER FUNCTIONS ---------------------------
+%%------------------------------------------------------------
+%%------------------------------------------------------------
+%% function : create_filter/1
+%% Arguments: String - Filter grammar
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+create_filter(Str) ->
+ {ok, Tokens} = cosNotification_Scanner:scan(Str),
+ case cosNotification_Grammar:parse(Tokens) of
+ {ok, Filter} ->
+ {ok, Filter};
+ _->
+ corba:raise(#'CosNotifyFilter_InvalidConstraint'{constr = Str})
+ end.
+
+%%------------------------------------------------------------
+%% function : eval
+%% Arguments:
+%% Returns :
+%% Effect :
+%%------------------------------------------------------------
+
+eval('$empty') -> true;
+eval(Tree) -> eval(Tree, []).
+
+
+%% Leaf expressions (literals and idents).
+eval('$empty', _) -> true;
+eval(Lit, _Env) when is_number(Lit) -> Lit;
+eval(Lit, _Env) when is_list(Lit) -> Lit; %list == string
+eval(Lit, _Env) when is_atom(Lit) -> Lit; %atom == bool
+eval({component, V}, []) ->
+ %% Cannot evaluate variables at this stage.
+ throw({error, {unbound_variable, V}});
+eval({component, V}, Env) ->
+ case catch lookup(V, Env, undefined) of
+ {ok, Val} ->
+ Val;
+ _X ->
+ {error, {unbound_variable, V}}
+ end;
+
+%% CORBA2.3-15/26 states:
+%% "The name parameters in tk_objref, tk_struct, tk_union, tk_enum, tk_alias,
+%% tk_value, tk_value_box, tk_abstract_interface, tk_native and tk_except TypeCodes
+%% and the member name parameters in tk_struct, tk_union, tk_enum, tk_value and
+%% tk_except TypeCodes are not specified by (or significant in) GIOP. Agents should
+%% not make assumptions about type equivalence based on these name values; only the
+%% structural information (including RepositoryId values, if provided) is
+%% significant. If provided, the strings should be the simple, unscoped names
+%% supplied in the OMG IDL definition text. If omitted, they are encoded as empty
+%% strings."
+%% Makes it rather hard to follow the grammar 100 %.
+eval({default_component, V}, Env) ->
+ case catch lookup(V, Env, default_component) of
+ {ok, false} ->
+ false;
+ {ok, true} ->
+ true;
+ _X ->
+ {error, {unbound_variable, V}}
+ end;
+eval({exist_component, V}, Env) ->
+ case catch lookup(V, Env, exist_component) of
+ {ok, false} ->
+ false;
+ {ok, _} ->
+ true;
+ {error, _} ->
+ false;
+ _X ->
+ {error, {unbound_variable, V}}
+ end;
+%% Arithmetic expressions.
+eval({'*', X, Y}, Env) ->
+ eval_arith({fun(_X, _Y) -> _X*_Y end, X, Y}, Env);
+eval({'/', X, Y}, Env) ->
+ eval_arith({fun(_X, _Y) -> _X/_Y end, X, Y}, Env);
+eval({'+', X, Y}, Env) ->
+ eval_arith({fun(_X, _Y) -> _X+_Y end, X, Y}, Env);
+eval({'-', X, Y}, Env) ->
+ eval_arith({fun(_X, _Y) -> _X-_Y end, X, Y}, Env);
+eval({'u-', X}, Env) ->
+ eval_arith({fun(_X) -> -_X end, X}, Env);
+%% Relational expressions.
+eval({'==', X, Y}, Env) ->
+ eval_rel({fun(_X, _Y) -> _X == _Y end, X, Y}, Env);
+eval({'!=', X, Y}, Env) ->
+ eval_rel({fun(_X, _Y) -> _X /= _Y end, X, Y}, Env);
+eval({'<', X, Y}, Env) ->
+ eval_rel({fun(_X, _Y) -> _X < _Y end, X, Y}, Env);
+eval({'<=', X, Y}, Env) ->
+ eval_rel({fun(_X, _Y) -> _X =< _Y end, X, Y}, Env);
+eval({'>', X, Y}, Env) ->
+ eval_rel({fun(_X, _Y) -> _X > _Y end, X, Y}, Env);
+eval({'>=', X, Y}, Env) ->
+ eval_rel({fun(_X, _Y) -> _X >= _Y end, X, Y}, Env);
+eval({'~', Needle, Haystack}, Env) -> %substring match
+ N = eval(Needle, Env),
+ H = eval(Haystack, Env),
+ if
+ is_list(N) andalso is_list(H) ->
+ string:str(H, N) /= 0;
+ true ->
+ throw({error, {bad_type, Needle, Haystack}})
+ end;
+eval({'in', Needle, Haystack}, Env) -> %set membership
+ N = eval(Needle, Env),
+ H = eval(Haystack, Env),
+ if
+ is_list(H) ->
+ lists:member(N, H);
+ true ->
+ throw({error, {bad_type, Needle, Haystack}})
+ end;
+%% Boolean expressions.
+eval({'and', false, _Y}, _Env) ->
+ false;
+eval({'and', _X, false}, _Env) ->
+ false;
+eval({'and', X, Y}, Env) ->
+ eval_and_bool({fun(_X, _Y) -> _X and _Y end, X, Y}, Env);
+
+eval({'or', true, _Y}, _Env) ->
+ true;
+eval({'or', _X, true}, _Env) ->
+ true;
+eval({'or', X, Y}, Env) ->
+ eval_or_bool({fun(_X, _Y) -> _X or _Y end, X, Y}, Env);
+eval({'not', X}, Env) ->
+ eval_bool({fun(_X) -> not _X end, X}, Env);
+%% Catch-all
+eval(_T, _Env) ->
+ throw({error, internal}).
+
+eval_bool({Fun, X}, Env) ->
+ Xe = eval(X, Env),
+ if
+ is_atom(Xe) ->
+ Fun(Xe);
+ true ->
+ throw({error, {bad_type, X}})
+ end.
+eval_and_bool({Fun, X, Y}, Env) ->
+ case eval(X, Env) of
+ false ->
+ %% No need for evaluating the other expression.
+ false;
+ Xe ->
+ Ye = eval(Y, Env),
+ if
+ is_atom(Xe) andalso is_atom(Ye) ->
+ Fun(Xe, Ye);
+ true ->
+ throw({error, {bad_type, X, Y}})
+ end
+ end.
+eval_or_bool({Fun, X, Y}, Env) ->
+ case eval(X, Env) of
+ true ->
+ %% No need for evaluating the other expression.
+ true;
+ Xe ->
+ Ye = eval(Y, Env),
+ if
+ is_atom(Xe) andalso is_atom(Ye) ->
+ Fun(Xe, Ye);
+ true ->
+ throw({error, {bad_type, X, Y}})
+ end
+ end.
+
+
+%% According to issue 2203, OMG stated that arithmetic operations involving booleans
+%% is allowed. TRUE equals 1 and FALSE 0. They refer to:
+
+%% "We at NEC like this feature, and feel it is both required and
+%% standard with the way CORBA treats boolean values. We feel it's
+%% required because it allows the constraint grammar to handle
+%% expressions that combine the results of boolean comparisons,
+%% which we feel is typically expected of a constraint grammar
+%% (e.g., ($.fruit == apples) + ($.color == red) + ($.kind == macintosh) > 2)
+%% Furthermore, while we have no fundamental opposition to explicitly
+%% stating that TRUE=1 and FALSE=0, we don't necessarily feel it's
+%% necessary because section 12.3.1 of CORBA alread states that
+%% "Boolean values are encoded as single octets, where TRUE is the
+%% value 1, and FALSE is 0." Essentially, we feel CORBA already
+%% defines TRUE to be 1 and FALSE to be 0, however we are not
+%% opposed to adding such a statement into Notification if folks
+%% feel it's necessary."
+%% If still valid, see: ftp://ftp.omg.org/pub/docs/telecom/99-07-06.txt
+
+%% The section they refer to (CORBA-2.0) merely states that TRUE and FALSE are
+%% encoded as 1 and 0 in GIOP. Does not imply that booleans may be used as numeric.
+%% But, they have stated that this should be the case so.....
+
+remap_bool(Num) when is_number(Num) -> Num;
+remap_bool(true) -> 1;
+remap_bool(false) -> 0;
+remap_bool(X) -> throw({error, {bad_type, X}}).
+
+eval_arith({Fun, X}, Env) ->
+ Xe = remap_bool(eval(X, Env)),
+ Fun(Xe);
+eval_arith({Fun, X, Y}, Env) ->
+ Xe = remap_bool(eval(X, Env)),
+ Ye = remap_bool(eval(Y, Env)),
+ Fun(Xe, Ye).
+
+eval_rel({Fun, X, Y}, Env) ->
+ Xe = eval(X, Env),
+ Ye = eval(Y, Env),
+ if
+ is_number(Xe) andalso is_number(Ye) ->
+ Fun(Xe, Ye);
+ is_list(Xe) andalso is_list(Ye) ->
+ Fun(Xe, Ye);
+ is_atom(Xe) andalso is_atom(Ye) ->
+ Fun(Xe, Ye);
+ true ->
+ throw({error, {bad_type, X, Y}})
+ end.
+
+%%------------------------------------------------------------
+%% function : get_variable
+%% Arguments: A sequence of CosNotification::Property{}, i.e.,
+%% name-value pairs.
+%% ID - name in the Property
+%% Any - remainder of body
+%% Returns : Value in the Property | false
+%% Comment : When searching for a variable we must start with
+%% 'variable_header' followed by 'filterable_body'.
+%% If not found we will then look in the 'remainder_of_body'
+%%------------------------------------------------------------
+
+get_variable([], ID, Any) when is_record(Any, any) ->
+ case {any:get_value(Any), any:get_typecode(Any)} of
+ {#'CosNotification_Property'{name=ID, value=A}, _} ->
+ any:get_value(A);
+ {_, TC} when is_atom(TC) ->
+ %% Since TC atom it must be a simple type, which don't have members.
+ throw({error, {bad_id, ID}});
+ {Value, {tk_alias,_,ID,_}} when is_record(Value, any) ->
+ %% {tk_alias, IFRId, ID, TypeCode}
+ any:get_value(Value);
+ {Value, {tk_alias,_,ID,_}} ->
+ %% {tk_alias, IFRId, ID, TypeCode}
+ Value;
+ {Value, _TC} ->
+ get_variable([],ID, Value)
+ end;
+get_variable([], ID, #'CosNotification_Property'{name=ID, value=Any}) ->
+ any:get_value(Any);
+get_variable([], ID, [#'CosNotification_Property'{name=ID, value=Any}|_]) ->
+ any:get_value(Any);
+get_variable([], ID, [H|T]) when is_record(H, 'CosNotification_Property') ->
+ get_variable([], ID, T);
+get_variable([], ID, false) ->
+ throw({error, {bad_id, ID}});
+get_variable([], ID, Value) ->
+ M = element(1, Value),
+ case catch M:tc() of
+ {tk_struct,_,_,SList} ->
+ %% {tk_struct, Id, Name, ElementList}.
+ Field = get_field(ID, SList),
+ element(Field, Value);
+ {tk_union,_,_,_, DefNo, UList} ->
+ %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
+ case id2switch(UList, ID) of
+ [default] when DefNo >= 0 ->
+ element(3, Value);
+ [default] ->
+ throw({error, {bad_id, "Bad Union ID supplied"}});
+ Found ->
+ case catch lists:member(element(2, Value), Found) of
+ true ->
+ element(3, Value);
+ _ ->
+ throw({error, {bad_id, "Bad Union ID supplied"}})
+ end
+ end;
+ _->
+ throw({error, {bad_id, ID}})
+ end;
+get_variable([#'CosNotification_Property'{name=ID, value=A}|_], ID, _) ->
+ any:get_value(A);
+get_variable([_|T], ID, Any) ->
+ get_variable(T, ID, Any).
+
+%%------------------------------------------------------------
+%% function : lookup
+%% Arguments: T - A parse tree representing the grammar.
+%% S - The event we want to extract data from
+%% Op - which type of lookup should be done on this
+%% component, e.g., 'default' or 'exist'.
+%% Returns : {ok, boolean()} |
+%% {error, _}
+%% Comment : WARNING!!!!
+%% This function uses some Orber core information to
+%% extract data, e.g., TypeCode representation. Why?
+%% We don't want to see the performance take a plunge
+%% due to that users write constraints which they
+%% can/may not know is slow. The alternative would be
+%% to use the IFR. However, these shortcuts aren't
+%% that frequent and we can easily update the code.
+%% To update, investigate:
+%% * lookup/3 cases related to '_type_id'
+%% * lookup/3 cases related to unions
+%% * get_variable/3
+%% * id2switch/2
+%% * switch2alias/2
+%%------------------------------------------------------------
+%% Done parsing, return the result.
+lookup([],S,_) -> {ok, S};
+lookup('$empty', #'CosNotification_StructuredEvent'{remainder_of_body = Any},_) ->
+ {ok, any:get_value(Any)};
+lookup('$empty',S,_) when is_record(S, any) ->
+ {ok, any:get_value(S)};
+
+%%------- varid --------
+%% CosNotification-revision-98-11-01/46 states:
+%% "The following rules govern translation of a run-time variable, $variable ,
+%% into a specific event field. If the run-time variable is reserved
+%% (e.g., $curtime) this translation takes precedence. Next, the first matching
+%% translation is chosen respectively from:
+%% * a simple-typed member of $.header.fixed_header,
+%% * properties in $.header.variable_header,
+%% and properties in $.header.filterable_data.
+%% If no match is found, the translation defaults to $.variable.
+%% Given these rules, an unstructured event with a $.priority member and a
+%% structured event using $.header.variable_header(priority) can be specified
+%% in a generic constraint using the run-time variable $priority .
+%% Alternatively, a constraint can be written specifically for a structured or
+%% unstructured event by avoiding the use of run-time variables."
+
+%% The above contains one error; $.header.filterable_data is not a part of the
+%% header, but contained in the event body.
+
+%% For any events we must first verify that a path exist, e.g.,
+%% "header"->"fixed_header"->"event_type"->"domain_name", otherwise we will
+%% use {dotid, "xxx"}.
+lookup([{varid, "type_name"}|T],
+ #'CosNotification_StructuredEvent'
+ {header = #'CosNotification_EventHeader'
+ {fixed_header = #'CosNotification_FixedEventHeader'
+ {event_type = #'CosNotification_EventType'{type_name=TN}}}}, Op) ->
+ lookup(T, TN, Op);
+lookup([{varid, "type_name"}|T], Any, Op) when is_record(Any, any) ->
+ case locate_var([?TYPE_PATH, ?VARIABLE_PATH("type_name"),
+ ?FILTERABLE_PATH("type_name")], Any, Op) of
+ {ok, Val} ->
+ lookup(T, Val, Op);
+ _ ->
+ lookup(T, get_variable([], "type_name", Any), Op)
+ end;
+lookup([{varid, "domain_name"}|T],
+ #'CosNotification_StructuredEvent'
+ {header = #'CosNotification_EventHeader'
+ {fixed_header = #'CosNotification_FixedEventHeader'
+ {event_type = #'CosNotification_EventType'{domain_name=DN}}}}, Op) ->
+ lookup(T, DN, Op);
+lookup([{varid, "domain_name"}|T], Any, Op) when is_record(Any, any) ->
+ case locate_var([?DOMAIN_PATH, ?VARIABLE_PATH("domain_name"),
+ ?FILTERABLE_PATH("domain_name")], Any, Op) of
+ {ok, Val} ->
+ lookup(T, Val, Op);
+ _ ->
+ lookup(T, get_variable([], "domain_name", Any), Op)
+ end;
+lookup([{varid, "event_name"}|T],
+ #'CosNotification_StructuredEvent'
+ {header = #'CosNotification_EventHeader'
+ {fixed_header = #'CosNotification_FixedEventHeader'
+ {event_name = EN}}}, Op) ->
+ lookup(T, EN, Op);
+lookup([{varid, "event_name"}|T], Any, Op) when is_record(Any, any) ->
+ case locate_var([?EVENT_PATH, ?VARIABLE_PATH("event_name"),
+ ?FILTERABLE_PATH("event_name")], Any, Op) of
+ {ok, Val} ->
+ lookup(T, Val, Op);
+ _ ->
+ lookup(T, get_variable([], "event_name", Any), Op)
+ end;
+
+lookup([{varid, ID}|T],
+ #'CosNotification_StructuredEvent'{header =
+ #'CosNotification_EventHeader'{variable_header = VS},
+ filterable_data = FS,
+ remainder_of_body = Any}, Op) ->
+ lookup(T, get_variable(VS++FS, ID, Any), Op);
+lookup([{varid, ID}|T], Any, Op) ->
+ case locate_var([?VARIABLE_PATH(ID), ?FILTERABLE_PATH(ID)], Any, Op) of
+ {ok, Val} ->
+ lookup(T, Val, Op);
+ _ ->
+ lookup(T, get_variable([], ID, Any), Op)
+ end;
+
+%%------- dotid --------
+%% First level
+lookup([{dotid, "header"}|T],
+ #'CosNotification_StructuredEvent'{header = S}, Op) ->
+ lookup(T, S, Op);
+lookup([{dotid, "filterable_data"}|T],
+ #'CosNotification_StructuredEvent'{filterable_data = S}, Op) ->
+ lookup(T, S, Op);
+
+lookup([{dotid, remainder_of_body}|T],
+ #'CosNotification_StructuredEvent'{remainder_of_body = S}, Op) ->
+ lookup(T, S, Op);
+%% Second level. Previous token must have been header
+lookup([{dotid, "fixed_header"}|T],
+ #'CosNotification_EventHeader'{fixed_header = S}, Op) ->
+ lookup(T, S, Op);
+lookup([{dotid, "variable_header"}|T],
+ #'CosNotification_EventHeader'{variable_header = S}, Op) ->
+ lookup(T, S, Op);
+%% Third level. Previous token must have been fixed_header.
+lookup([{dotid, "event_type"}|T],
+ #'CosNotification_FixedEventHeader'{event_type = S}, Op) ->
+ lookup(T, S, Op);
+lookup([{dotid, "event_name"}|T],
+ #'CosNotification_FixedEventHeader'{event_name = S}, Op) ->
+ lookup(T, S, Op);
+%% Fourth level. Previous token must have been event_type
+lookup([{dotid, "domain_name"}|T], #'CosNotification_EventType'{domain_name = S}, Op) ->
+ lookup(T, S, Op);
+lookup([{dotid, "type_name"}|T], #'CosNotification_EventType'{type_name = S}, Op) ->
+ lookup(T, S, Op);
+
+%% Leaf expressions
+lookup([{dotid, "name"}|T], #'CosNotification_Property'{name=S}, Op) ->
+ lookup(T, S, Op);
+lookup([{dotid, "value"}|T], #'CosNotification_Property'{value=S}, Op) ->
+ lookup(T, S, Op);
+
+lookup([{dotid, ID}|T],
+ #'CosNotification_StructuredEvent'{remainder_of_body = Any}, Op) ->
+ lookup(T, get_variable([], ID, Any), Op);
+lookup([{dotid, ID}|T], Any, Op) ->
+ lookup(T, get_variable([], ID, Any), Op);
+
+lookup([{associd, ID}|T], S, Op) when is_list(S) ->
+ %% Refers to an associative array, i.e., a list of
+ %% #'CosNotification_Property'{name=ID, value=A}
+ lookup(T, get_variable(S, ID, false), Op);
+
+lookup([{dotint, Position}|T], S, Op) when is_record(S, any) ->
+ lookup(T, element(Position+2, any:get_value(S)), Op);
+lookup([{dotint, Position}|T], S, Op) ->
+ lookup(T, element(Position+2, S), Op);
+
+lookup([{uint, ID}|T], S, Op) when is_record(S, any) ->
+ lookup([{uint, ID}|T], any:get_value(S), Op);
+lookup([{uint, ID} |T], S, Op) when is_tuple(S) ->
+ case catch element(2, S) of
+ ID ->
+ %% The supplied union do contain the requested discriminator.
+ lookup(T, element(3, S), Op);
+ _Other when Op == exist_component ->
+ throw({error, {bad_id, "Bad Union ID"}});
+ Other ->
+ %% Check if default is allowed.
+ M = element(1, S),
+ case catch M:tc() of
+ {tk_union,_,_,_,DefNo, UList} ->
+ %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
+ case switch2alias(UList, ID) of
+ {ok, [], _} ->
+ throw({error, {bad_id, "Bad Union ID"}});
+ {ok, default, _} when DefNo >= 0 ->
+ lookup(T, element(3, S), Op);
+ {ok, List, _} ->
+ case lists:member(Other, List) of
+ true ->
+ lookup(T, element(3, S), Op);
+ _->
+ throw({error, {bad_id, "Bad Union ID"}})
+ end
+ end
+ end
+ end;
+lookup([{ustr, ID}|T], S, Op) when is_record(S, any) ->
+ lookup([{ustr, ID}|T], any:get_value(S), Op);
+lookup([{ustr, ID}|T], S, Op) when is_tuple(S) ->
+ M = element(1, S),
+ case catch M:tc() of
+ {tk_union,_,_,_,DefNo, UList} ->
+ case id2switch(UList, ID) of
+ [default] when DefNo >= 0 ->
+ lookup(T, element(3, S), Op);
+ [default] ->
+ throw({error, {bad_id, "Bad Union ID supplied"}});
+ Found ->
+ case catch lists:member(element(2, S), Found) of
+ true ->
+ lookup(T, element(3, S), Op);
+ _ ->
+ throw({error, {bad_id, "Bad Union ID supplied"}})
+ end
+ end
+ end;
+lookup([default|T], S, Op) when is_record(S, any) ->
+ lookup([default|T], any:get_value(S), Op);
+lookup([default|T], S, Op) when is_tuple(S) ->
+ M = element(1, S),
+ case catch M:tc() of
+ {tk_union,_,_,_,DefNo, _UList} when DefNo < 0 ->
+ %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
+ throw({error, {bad_id, "No default discriminator"}});
+ {tk_union,_,_,_,_DefNo, UList} ->
+ %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
+ %% Check if the label really is default.
+ case lists:keymember(element(2, S), 1, UList) of
+ false ->
+ lookup(T, element(3, S), Op);
+ _->
+ throw({error, {bad_id, "Bad Union"}})
+ end;
+ _->
+ throw({error, {bad_id, "Bad Union"}})
+ end;
+
+lookup([{arrindex, Index}|T], S, Op) when is_tuple(S) ->
+ %% The OMG uses c/c++ index. We must add one.
+ lookup(T, element(Index+1,S), Op);
+
+%%%%%%%%%%%%%%%%%%%%%%% LEAF EXPRESSIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% got '$._length', which maps to the 'remainder_of_body'
+lookup(['_length'],
+ #'CosNotification_StructuredEvent'{remainder_of_body = Any}, _Op) ->
+ {ok, length(any:get_value(Any))};
+lookup(['_length'], S, _Op) when is_record(S, any) ->
+ {ok, length(any:get_value(S))};
+lookup(['_length'], S, _Op) when is_list(S) ->
+ {ok, length(S)};
+lookup(['_length'], S, _Op) when is_tuple(S) ->
+ {ok, length(tuple_to_list(S))};
+
+%% got '$._d', which maps to the 'remainder_of_body'
+%% The discriminator may, accordiong to the CORBA specification, be (2.3/p3-37):
+%% * integer_type
+%% * char_type
+%% * boolean_type
+%% * enum_type
+%% * scoped_name
+lookup(['_d'],
+ #'CosNotification_StructuredEvent'{remainder_of_body = Any},
+ default_component) ->
+ lookup(['_d'], any:get_value(Any), default_component);
+lookup(['_d'], S, default_component) when is_record(S, any) ->
+ lookup(['_d'], any:get_value(S), default_component);
+lookup(['_d'], S, default_component) ->
+ M = element(1, S),
+ case catch M:tc() of
+ {tk_union,_,_,_,DefNo,_} when DefNo < 0 ->
+ %% '-1' indicates that no default value may exist.
+ {ok, false};
+ {tk_union,_,_,_,_,UList} ->
+ %% May be using the default setting; check if the Value is in the list.
+ {ok, not lists:keymember(element(2, S), 1, UList)};
+ _ ->
+ {ok, false}
+ end;
+lookup(['_d'],
+ #'CosNotification_StructuredEvent'{remainder_of_body = Any}, _Op) ->
+ {ok, element(2, any:get_value(Any))};
+lookup(['_d'], S, _Op) when is_record(S, any) ->
+ {ok, element(2, any:get_value(S))};
+lookup(['_d'], S, _Op) ->
+ {ok, element(2, S)};
+
+
+lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_StructuredEvent') ->
+ {ok, "StructuredEvent"};
+lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_EventHeader') ->
+ {ok, "EventHeader"};
+lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_FixedEventHeader') ->
+ {ok, "FixedEventHeader"};
+lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_EventType') ->
+ {ok, "EventType"};
+lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_Property') ->
+ {ok, "Property"};
+lookup(['_type_id'], S, _Op) when is_tuple(S) ->
+ M=element(1, S),
+ Name = case catch M:tc() of
+ {tk_union,_,ID,_,_,_} ->
+ ID;
+ {tk_enum, _, ID, _} ->
+ ID;
+ {tk_exception, _, ID, _} ->
+ ID;
+ {tk_alias, _, ID, _} ->
+ ID;
+ {tk_struct,_,ID,_} ->
+ ID
+ end,
+ {ok, Name};
+
+lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_StructuredEvent') ->
+ {ok, 'CosNotification_StructuredEvent':id()};
+lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_EventHeader') ->
+ {ok, 'CosNotification_EventHeader':id()};
+lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_FixedEventHeader') ->
+ {ok, 'CosNotification_FixedEventHeader':id()};
+lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_EventType') ->
+ {ok, 'CosNotification_EventType':id()};
+lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_Property') ->
+ {ok, 'CosNotification_Property':id()};
+lookup(['_repos_id'], S, _Op) when is_tuple(S) ->
+ M = element(1, S),
+ {ok, M:id()};
+
+lookup(_, _, _) ->
+ error.
+
+
+%%------------------------------------------------------------
+%% function : locate_var
+%% Arguments: Paths - A list of path-lists which tells us where
+%% to search for runtime variables and in which
+%% order.
+%% S - Data
+%% Op - se lookup/3
+%% Returns : {error, _} |
+%% {ok, Val}
+%%------------------------------------------------------------
+locate_var([], _S, _) ->
+ {error, "not found"};
+locate_var([H|T], S, Op) ->
+ case catch lookup(H, S, Op) of
+ {ok, Val} ->
+ {ok,Val};
+ _ ->
+ locate_var(T, S, Op)
+ end.
+
+%%------------------------------------------------------------
+%% function : id2switch
+%% Arguments: UList - The list of elements contained in the
+%% Union TypeCode.
+%% ID - string() eq name of element.
+%% Returns : Acc - A list of switches related to given ID.
+%%------------------------------------------------------------
+id2switch(UList, ID) ->
+ id2switch(UList, ID, [], false).
+id2switch([], _, Acc, _) ->
+ Acc;
+id2switch([{Sw, ID, _}|T], ID, Acc, _) ->
+ id2switch(T, ID, [Sw|Acc], true);
+id2switch([_|_T], _ID, Acc, true) ->
+ Acc;
+id2switch([_|T], ID, Acc, Found) ->
+ id2switch(T, ID, Acc, Found).
+
+%%------------------------------------------------------------
+%% function : switch2alias
+%% Arguments: UList - The list of elements contained in the
+%% Union TypeCode.
+%% Switch - the union discriminator.
+%% Returns : Acc - A list of switches that are defined with the same
+%% ID - The switches common ID.
+%% Comment : A union IDL code can look like:
+%% union Union switch(long) {
+%% case 1:
+%% case 2: long ID; };
+%% In this case supplying Switch == 1 (or) the result
+%% should be {ok, [1,2], "ID"}
+%%------------------------------------------------------------
+switch2alias([], _Switch) ->
+ %% Is it really possible to define an empty union??
+ {ok, [], undefined};
+switch2alias([{Sw, ID, TC}|UList], Switch) ->
+ switch2alias([{Sw, ID, TC}|UList], Switch, [], ID, false).
+
+
+switch2alias([{default, ID, _}], _, _, _, false) ->
+ {ok, default, ID};
+switch2alias([], _, _Acc, _, false) ->
+ {ok, [], undefined};
+switch2alias([], _, Acc, PreviousID, _) ->
+ {ok, Acc, PreviousID};
+
+%% Seen the ID before but just found the correct switch, e.g.,
+%% [... {0,"K",{tk_string,0}}, {2,"K",{tk_string,0}}...] and switch eq '2'
+switch2alias([{Switch, PreviousID, _}|T], Switch, Acc, PreviousID, _Found) ->
+ switch2alias(T, Switch, [Switch|Acc], PreviousID, true);
+
+%% First time for this ID and found the correct switch
+switch2alias([{Switch, ID, _}|T], Switch, _Acc, _PreviousID, false) ->
+ switch2alias(T, Switch, [Switch], ID, true);
+
+%% Seen this ID and found the correct switch before.
+switch2alias([{Sw, PreviousID, _}|T], Switch, Acc, PreviousID, true) ->
+ switch2alias(T, Switch, [Sw|Acc], PreviousID, true);
+
+%% Seen this ID but not found the correct switch.
+switch2alias([{Sw, PreviousID, _}|T], Switch, Acc, PreviousID, false) ->
+ switch2alias(T, Switch, [Sw|Acc], PreviousID, false);
+
+%% No more of the correct ID/Switch. Done.
+switch2alias([{_, _ID, _}|_], _, Acc, PreviousID, true) ->
+ {ok, Acc, PreviousID};
+%% Not found correct switch and ID is updated.
+switch2alias([{Sw, ID, _}|T], Switch, _Acc, _PreviousID, Found) ->
+ switch2alias(T, Switch, [Sw], ID, Found).
+
+
+%%------------------------------------------------------------
+%% function : get_field
+%% Arguments: ID - element name
+%% List - The list of elements contained in the
+%% TypeCode.
+%% Returns : false |
+%% offset
+%%------------------------------------------------------------
+get_field(ID, List) ->
+ get_field(ID, List, 2).
+get_field(_ID, [], _) ->
+ false;
+get_field(ID, [ID|_], I) ->
+ %% Memberlists in enum.
+ I;
+get_field(ID, [{ID,_}|_], I) ->
+ %% Memberlists in structs.
+ I;
+get_field(ID, [_|T], I) ->
+ get_field(ID, T, I+1).
+
+%%------------------------------------------------------------
+%% function : check_types
+%% Arguments: A sequence of CosNotification::EventType{}, i.e.,
+%% name-value pairs.
+%% Returns : {ok, WhichType, WC}
+%% WhichType - type/domain/both
+%% WC - [Types using wildcard]
+%%------------------------------------------------------------
+%% With check_types we try to determin if one or more EventTypes force us to check
+%% all events against this constraint. For example:
+%% EventType A1 has domain_name="car",type_name = "*"
+%% EventType A2 has domain_name="*",type_name = "DodgeViper"
+%% Since A1 says that we must test against any type_name and A2
+%% against any domain_name, we must test all events using these permutations.
+%% It's better to do these test now instead of when we are up and running. But
+%% if a client change the constraints VERY often it's up to them and they have
+%% to accept the delay.
+%%------------------------------------------------------------
+
+%% If types is an empty list it means that this constraint must be used
+%% for all events.
+check_types([]) -> true;
+check_types(Types) -> check_types(Types, both, []).
+check_types([], Which, WildCard) -> {ok, Which, WildCard};
+%% The following cases means that all events matches.
+check_types([#'CosNotification_EventType'{domain_name="",type_name = ""}|_T],_,_) ->
+ true;
+check_types([#'CosNotification_EventType'{domain_name="",type_name = "*"}|_T],_,_) ->
+ true;
+check_types([#'CosNotification_EventType'{domain_name="*",type_name = ""}|_T],_,_) ->
+ true;
+check_types([#'CosNotification_EventType'{domain_name="*",type_name = "*"}|_T],_,_) ->
+ true;
+%% The following cases means that all events must be tested using this constraint.
+check_types([#'CosNotification_EventType'{domain_name="",type_name = Ty}|T], domain,WC) when is_list(Ty) ->
+ check_wildcard(T, all, WC, "", Ty);
+check_types([#'CosNotification_EventType'{domain_name="*",type_name = Ty}|T], domain, WC) when is_list(Ty) ->
+ check_wildcard(T, all, WC, "", Ty);
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name = ""}|T], type,WC) when is_list(Do) ->
+ check_wildcard(T, all, WC, Do, "");
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name = "*"}|T], type,WC) when is_list(Do) ->
+ check_wildcard(T, all, WC, Do, "");
+%% The following cases is used to prevent other cases from converting,
+%% for example, all->type.
+check_types([#'CosNotification_EventType'{domain_name="",type_name = Ty}|T], all,WC) when is_list(Ty) ->
+ check_wildcard(T, all, WC, "", Ty);
+check_types([#'CosNotification_EventType'{domain_name="*",type_name = Ty}|T], all,WC) when is_list(Ty) ->
+ check_wildcard(T, all, WC, "", Ty);
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name = ""}|T], all,WC) when is_list(Do) ->
+ check_wildcard(T, all, WC, Do, "");
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name = "*"}|T], all,WC) when is_list(Do) ->
+ check_wildcard(T, all, WC, Do, "");
+%% The following cases means that all events with matching Type must be
+%% tested using this constraint.
+check_types([#'CosNotification_EventType'{domain_name="",type_name = Ty}|T], _W,WC) when is_list(Ty) ->
+ check_wildcard(T, type, WC, "", Ty);
+check_types([#'CosNotification_EventType'{domain_name="*",type_name = Ty}|T], _W,WC) when is_list(Ty) ->
+ check_wildcard(T, type, WC, "", Ty);
+%% The following cases means that all events with matching Domain must be
+%% tested using this constraint.
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name = ""}|T], _W,WC) when is_list(Do) ->
+ check_wildcard(T, domain, WC, Do, "");
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name = "*"}|T], _W,WC) when is_list(Do) ->
+ check_wildcard(T, domain, WC, Do, "");
+%% Sorry, no shortcuts.
+check_types([#'CosNotification_EventType'{domain_name=Do,type_name=Ty}|T], W,WC) when is_list(Do) andalso is_list(Ty) ->
+ check_wildcard(T, W, WC, Do, Ty);
+check_types([H|_], _,_) when is_record(H, 'CosNotification_EventType') ->
+ %% Not valid.
+ corba:raise(#'CosNotifyComm_InvalidEventType'{type=H});
+check_types(_,_,_) ->
+ %% Wasn't even a correct input.
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+check_wildcard(Types, Which, WC, Domain, Type) ->
+ NewWC =
+ case {string:chr(Domain, $*), string:chr(Type, $*)} of
+ {0, 0} ->
+ WC;
+ {0, _}->
+ [{type, Domain, convert_wildcard(Type, [])}|WC];
+ {_, 0}->
+ [{domain, convert_wildcard(Domain, []), Type}|WC];
+ _->
+ [{both, convert_wildcard(Domain, []), convert_wildcard(Type, [])}|WC]
+ end,
+ check_types(Types, Which, NewWC).
+
+%% Change '*' to '.*', see regexp:parse/2 documentation.
+convert_wildcard([], Acc) ->
+ case regexp:parse(lists:reverse(Acc)) of
+ {ok, Expr} ->
+ Expr;
+ _ ->
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
+ end;
+convert_wildcard([$*|T], Acc) ->
+ convert_wildcard(T, [$*, $.|Acc]);
+convert_wildcard([H|T], Acc) ->
+ convert_wildcard(T, [H|Acc]).
+
+%%------------------------------------------------------------
+%% function : match_types
+%% Arguments: A sequence of {Which, Domain, Type}, i.e., the same as
+%% returned from cosNotification_Filter:check_types/3
+%% Returns : bolean()
+%%------------------------------------------------------------
+match_types(_, _, []) ->
+ false;
+match_types(Domain, Type, [{domain, WCDomain, Type}|T]) ->
+ L=length(Domain),
+ case catch regexp:matches(Domain, WCDomain) of
+ {match, []} ->
+ match_types(Domain, Type, T);
+ {match, [{1, L}]} ->
+ true;
+ _->
+ match_types(Domain, Type, T)
+ end;
+match_types(Domain, Type, [{type, Domain, WCType}|T]) ->
+ L=length(Type),
+ case catch regexp:matches(Type, WCType) of
+ {match, []} ->
+ match_types(Domain, Type, T);
+ {match, [{1, L}]} ->
+ true;
+ _->
+ match_types(Domain, Type, T)
+ end;
+match_types(Domain, Type, [{both, WCDomain, WCType}|T]) ->
+ L1=length(Domain),
+ case catch regexp:matches(Domain, WCDomain) of
+ {match, []} ->
+ match_types(Domain, Type, T);
+ {match, [{1, L1}]} ->
+ L2=length(Type),
+ case catch regexp:matches(Type, WCType) of
+ {match, []} ->
+ match_types(Domain, Type, T);
+ {match, [{1, L2}]} ->
+ true;
+ _->
+ match_types(Domain, Type, T)
+ end;
+ _->
+ match_types(Domain, Type, T)
+ end;
+match_types(Domain, Type, [_|T]) ->
+ match_types(Domain, Type, T).
+
+%%------------------------------------------------------------
+%% function : validate_types
+%% Arguments: A sequence of CosNotification::EventType{}, i.e.,
+%% name-value pairs.
+%% Returns : ok |
+%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
+%%------------------------------------------------------------
+
+validate_types([]) ->
+ ok;
+validate_types([#'CosNotification_EventType'{domain_name=Do,type_name=Ty}|T])
+ when is_list(Do) andalso is_list(Ty) ->
+ validate_types(T);
+validate_types([H|_])
+ when is_record(H, 'CosNotification_EventType') ->
+ %% Not valid.
+ corba:raise(#'CosNotifyComm_InvalidEventType'{type=H});
+validate_types(_) ->
+ %% Wasn't even a correct input.
+ corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
+
+
+%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/cosNotification_Grammar.yrl b/lib/cosNotification/src/cosNotification_Grammar.yrl
new file mode 100644
index 0000000000..98233bf92d
--- /dev/null
+++ b/lib/cosNotification/src/cosNotification_Grammar.yrl
@@ -0,0 +1,166 @@
+%%--------------------------------------------------------------------
+%% %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 : cosNotification_Grammar.yrl
+%% Purpose : Implement the constraint grammar for CosNotification filters.
+%%--------------------------------------------------------------------
+
+Nonterminals
+ '<toplevel>' '<constraint>' '<expr>' '<bool>' '<bool_or>' '<Ident>'
+ '<bool_and>' '<bool_compare>' '<expr_in>' '<expr_twiddle>' '<term>'
+ '<factor_not>' '<factor>' '<Component>' '<CompExt>' '<CompDot>' '<UnionVal>'.
+
+Terminals
+% 'dbslsh' 'bslshd'
+ 'bslsh' 'ident' 'string'
+ '_length' '_d''_type_id' '_repos_id'
+ 'not' 'or' 'and' 'num'
+ 'in' '~' '.' 'dollar'
+ 'ADDOP' 'RELOP' 'MULOP' 'default' 'exist'
+ 'TRUE' 'FALSE'
+ '(' ')' '[' ']' 'int'.
+
+Left 100 'or'.
+Left 200 'and'.
+%Nonassoc 300 'RELOP'. % '==', '!=', '<', '>', '<=', '=>'
+Left 300 'RELOP'.
+%Nonassoc 400 'in'.
+Left 400 'in'.
+%Nonassoc 500 '~'.
+Left 500 '~'.
+Left 600 'ADDOP'. % '+', '-'
+Left 700 'MULOP'. % '*', '/'
+Unary 800 'not'.
+Unary 900 'exist'.
+Unary 900 'default'.
+%Unary 900 'u-'. % unary minus
+
+Rootsymbol '<toplevel>'.
+Endsymbol '$end'.
+
+'<toplevel>' -> '$empty' : '$empty'.
+'<toplevel>' -> '<constraint>' : '$1'.
+
+'<constraint>' -> '<bool>' : '$1'.
+
+'<bool>' -> '<bool_or>' : '$1'.
+
+'<bool_or>' -> '<bool_or>' 'or' '<bool_and>' : {'or', '$1', '$3'}.
+'<bool_or>' -> '<bool_and>' : '$1'.
+
+'<bool_and>' -> '<bool_and>' 'and' '<bool_compare>' : {'and', '$1', '$3'}.
+'<bool_and>' -> '<bool_compare>' : '$1'.
+
+'<bool_compare>' -> '<expr_in>' 'RELOP' '<expr_in>' : {element(2, '$2'), '$1', '$3'}.
+'<bool_compare>' -> '<expr_in>' : '$1'.
+
+'<expr_in>' -> '<expr_twiddle>' : '$1'.
+'<expr_in>' -> '<expr_twiddle>' 'in' '<Ident>' : {'in', '$1', '$3'}.
+'<expr_in>' -> '<expr_twiddle>' 'in' 'dollar' '<Component>' : {'in', '$1', examin_comp({'component', '$4'})}.
+
+'<expr_twiddle>' -> '<expr>' : '$1'.
+'<expr_twiddle>' -> '<expr>' '~' '<expr>' : {'~', '$1', '$3'}.
+
+'<expr>' -> '<term>' : '$1'.
+'<expr>' -> '<expr>' 'ADDOP' '<term>' : {element(2, '$2'), '$1', '$3'}.
+
+'<term>' -> '<factor_not>' : '$1'.
+'<term>' -> '<term>' 'MULOP' '<factor_not>' : {element(2, '$2'), '$1', '$3'}.
+
+'<factor_not>' -> '<factor>' : '$1'.
+'<factor_not>' -> 'not' '<factor>' : {'not', '$2'}.
+
+'<factor>' -> '(' '<bool_or>' ')' : '$2'.
+'<factor>' -> 'num' : element(2, '$1').
+'<factor>' -> 'int' : element(2, '$1').
+'<factor>' -> 'string' : element(2, '$1').
+'<factor>' -> 'TRUE' : 'true'.
+'<factor>' -> 'FALSE' : 'false'.
+'<factor>' -> 'ADDOP' 'num' : create_unary(element(2, '$1'), element(2, '$2')).
+'<factor>' -> 'ADDOP' 'int' : create_unary(element(2, '$1'), element(2, '$2')).
+'<factor>' -> '<Ident>' : list_to_atom('$1').
+'<factor>' -> 'dollar' '<Component>' : examin_comp({component, '$2'}).
+'<factor>' -> 'default' 'dollar' '<Component>' : examin_comp({'default_component', '$3'}).
+'<factor>' -> 'exist' 'dollar' '<Component>' : examin_comp({'exist_component', '$3'}).
+
+%% The following rules are used to create Components. The format used is:
+%% [...]
+'<Component>' -> '.' '<CompDot>' : '$2'.
+'<Component>' -> '[' 'int' ']' '<CompExt>' : [{'arrindex', element(2, '$2')} | '$4']. %% CompArray
+'<Component>' -> '(' '<Ident>' ')' '<CompExt>' : [{'associd', '$2'} | '$4']. %%CompAssoc
+'<Component>' -> '<Ident>' '<CompExt>' : [{'varid', '$1'} | '$2']. %% run-time variable
+'<Component>' -> '$empty' : [].
+
+'<CompExt>' -> '.' '<CompDot>' : '$2'.
+'<CompExt>' -> '[' 'int' ']' '<CompExt>' : [{'arrindex', element(2, '$2')} | '$4']. %% CompArray
+'<CompExt>' -> '(' '<Ident>' ')' '<CompExt>' : [{'associd', '$2'} | '$4']. %%CompAssoc
+'<CompExt>' -> '$empty' : [].
+
+'<CompDot>' -> '<Ident>' '<CompExt>' : [{'dotid', '$1'} | '$2'].
+'<CompDot>' -> 'int' '<CompExt>' : [{'dotint', element(2, '$1')} | '$2']. %% ComPos
+'<CompDot>' -> '(' '<UnionVal>' ')' '<CompExt>' : ['$2' | '$4']. %% UnionPos
+'<CompDot>' -> '_length' : ['_length']. %% arrays or sequences ONLY
+'<CompDot>' -> '_d' : ['_d']. %% discriminated unions ONLY
+'<CompDot>' -> '_type_id' : ['_type_id']. %% ok if info can be obtained
+'<CompDot>' -> '_repos_id' : ['_repos_id']. %% ok if info can be obtained
+
+'<Ident>' -> 'ident' : element(2, '$1').
+'<Ident>' -> 'bslsh' 'ident' : element(2, '$2').
+
+'<UnionVal>' -> 'int' : {'uint', element(2, '$1')}.
+'<UnionVal>' -> 'ADDOP' 'int' : {'uint', create_unary(element(2, '$1'), element(2, '$2'))}.
+'<UnionVal>' -> 'string' : {'ustr', element(2, '$1')}.
+'<UnionVal>' -> '$empty': 'default'.
+
+Erlang code.
+%%--------------------------------------------------------------------
+%%
+%% %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 : cosNotification_Grammar.erl
+%% Purpose : THIS FILE HAS BEEN GENERATED. DO NOT EDIT!!!!
+%%----------------------------------------------------------------------
+
+-include("CosNotification_Definitions.hrl").
+
+create_unary('+', Val) when is_number(Val) -> Val;
+create_unary('-', Val) when is_number(Val) -> -Val;
+create_unary(_, _) -> return_error(0, "syntax error").
+
+examin_comp({T, []}) ->
+ {T, '$empty'};
+examin_comp(V) ->
+ V.
+
diff --git a/lib/cosNotification/src/cosNotification_Scanner.erl b/lib/cosNotification/src/cosNotification_Scanner.erl
new file mode 100644
index 0000000000..e9c54319f0
--- /dev/null
+++ b/lib/cosNotification/src/cosNotification_Scanner.erl
@@ -0,0 +1,268 @@
+%%----------------------------------------------------------------------
+%%
+%% %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 : cosNotification_Scanner.erl
+%% Purpose : Scan and pre-process a grammar.
+%%----------------------------------------------------------------------
+
+-module('cosNotification_Scanner').
+
+-export([scan/1]).
+
+scan(Str) ->
+ RSL = scan(Str, 1, [], any),
+ {ok, lists:reverse(RSL)}.
+
+
+%% Guard macros used at top scan functions only
+-define(is_number(X), X >= $0, X =< $9).
+-define(is_upper(X), X >= $A, X =< $Z).
+-define(is_lower(X), X >= $a, X =< $z).
+
+%%----------------------------------------------------------------------
+%% scan
+%%
+%% A-Z
+scan([X|Str], Line, Out, Type) when ?is_upper(X) ->
+ scan_name(Str, [X], Line, Out, Type);
+%% a-z
+scan([X|Str], Line, Out, Type) when ?is_lower(X) ->
+ scan_name(Str, [X], Line, Out, Type);
+%% 0-9
+scan([X|Str], Line, Out, Type) when ?is_number(X) ->
+ scan_number(Str, [X], Line, Out, Type);
+
+%% RELOP:s == != <= >= > <
+scan([$=,$= | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'RELOP', '=='} | Out], any);
+scan([$!,$= | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'RELOP', '!='} | Out], any);
+scan([$<,$= | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'RELOP', '<='} | Out], any);
+scan([$>,$= | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'RELOP', '>='} | Out], any);
+scan([$> | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'RELOP', '>'} | Out], any);
+scan([$< | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'RELOP', '<'} | Out], any);
+
+%% ADDOP:s + -
+scan([$+ | Str], Line, Out, Type) ->
+ scan(Str, Line, [{'ADDOP', '+'} | Out], Type);
+scan([$- | Str], Line, Out, Type) ->
+ scan(Str, Line, [{'ADDOP', '-'} | Out], Type);
+
+%% MULOP:s * /
+scan([$* | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'MULOP', '*'} | Out], any);
+scan([$/ | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'MULOP', '/'} | Out], any);
+
+%% TAB
+scan([9| T], Line, Out, Type) -> scan(T, Line, Out, Type);
+%% SP
+scan([32| T], Line, Out, Type) -> scan(T, Line, Out, Type);
+%% CR
+scan([$\r|Str], Line, Out, Type) ->
+ scan(Str, Line, Out, Type);
+%% LF
+scan([$\n|Str], Line, Out, Type) ->
+ scan(Str, Line+1, Out, Type);
+%% \\
+scan([92, 92 | Str], Line, Out, Type) ->
+ scan(Str, Line, [{'dbslsh', Line} | Out], Type);
+%% \'
+scan([92, 39 | Str], Line, Out, Type) ->
+ scan(Str, Line, [{'bslshd', Line} | Out], Type);
+%% '\'
+scan([92 | Str], Line, Out, Type) ->
+ scan(Str, Line, [{'bslsh', Line} | Out], Type);
+%% '_'
+scan([$_ | Str], Line, Out, dollar) ->
+ scan_name(Str, [$_], Line, Out, dollar);
+%% '$'
+scan([$$, 92 | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'bslsh', Line}, {'dollar', Line} | Out], dollar);
+scan([$$ | Str], Line, Out, _Type) ->
+ scan(Str, Line, [{'dollar', Line} | Out], dollar);
+scan([$"|Str], Line, Out, Type) ->
+ scan_const(char, Str, [], Line, Out, Type);
+scan([$'|Str], Line, Out, Type) ->
+ scan_const(string, Str, [], Line, Out, Type);
+
+%% Writing '+.<CompDot>' is not allowed ('+' or '-' are only allowed
+%% as unary for <UnionVal> (within a component) which must be en integer).
+scan([$. | Str], Line, [{'ADDOP', Op}|Out], _) ->
+ scan_frac(Str, [$.], Line, [{'ADDOP', Op}|Out], any);
+%% Must be a <CompDot>
+scan([$. | Str], Line, Out, dollar) ->
+ scan(Str, Line, [{'.',Line} | Out], dollar);
+%% Number
+scan([$. | Str], Line, Out, Type) ->
+ scan_frac(Str, [$.], Line, Out, Type);
+scan([C|Str], Line, Out, Type) ->
+ scan(Str, Line, [{list_to_atom([C]), Line} | Out], Type);
+
+scan([], _Line, Out, _Type) ->
+ Out.
+
+%%----------------------------------------------------------------------
+%% scan_name
+%%
+
+scan_number([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
+ scan_number(Str, [X|Accum], Line, Out, Type);
+scan_number([X|Str], Accum, Line, Out, dollar) when X==$. ->
+ scan(Str, Line, [{'.', Line},
+ {'int', list_to_integer(lists:reverse(Accum))} | Out], dollar);
+scan_number([X|Str], Accum, Line, Out, Type) when X==$. ->
+ scan_frac(Str, [X|Accum], Line, Out, Type);
+scan_number([X|Str], Accum, Line, Out, Type) when X==$e ->
+ scan_exp(Str, [X|Accum], Line, Out, Type);
+scan_number([X|Str], Accum, Line, Out, Type) when X==$E ->
+ scan_exp(Str, [X|Accum], Line, Out, Type);
+scan_number(Str, Accum, Line, Out, Type) ->
+ scan(Str, Line, [{'int', list_to_integer(lists:reverse(Accum))} | Out], Type).
+
+
+%% Floating point number scan.
+%%
+%% Non trivial scan. A float consists of an integral part, a
+%% decimal point, a fraction part, an e or E and a signed integer
+%% exponent. Either the integer part or the fraction part but not
+%% both may be missing, and either the decimal point or the
+%% exponent part but not both may be missing. The exponent part
+%% must consist of an e or E and a possibly signed exponent.
+%%
+%% Analysis shows that "1." ".7" "1e2" ".5e-3" "1.7e2" "1.7e-2"
+%% is allowed and "1" ".e9" is not. The sign is only allowed just
+%% after an e or E. The scanner reads a number as an integer
+%% until it encounters a "." so the integer part only error case
+%% will not be caught in the scanner (but rather in expression
+%% evaluation)
+
+scan_frac([$e | _Str], [$.], _Line, _Out, _Type) ->
+ {error, "illegal_float"};
+scan_frac([$E | _Str], [$.], _Line, _Out, _Type) ->
+ {error, "illegal_float"};
+scan_frac(Str, Accum, Line, Out, Type) ->
+ scan_frac2(Str, Accum, Line, Out, Type).
+
+scan_frac2([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
+ scan_frac2(Str, [X|Accum], Line, Out, Type);
+scan_frac2([X|Str], Accum, Line, Out, Type) when X==$e ->
+ scan_exp(Str, [X|Accum], Line, Out, Type);
+scan_frac2([X|Str], Accum, Line, Out, Type) when X==$E ->
+ scan_exp(Str, [X|Accum], Line, Out, Type);
+%% Since '.2' is allowed, we add '0' in front to be sure (erlang do not allow
+%% list_to_float(".2") and list_to_float("0.2") eq. list_to_float("00.2")).
+scan_frac2(Str, Accum, Line, Out, Type) ->
+ scan(Str, Line, [{'num', list_to_float([$0|lists:reverse(Accum)])} | Out], Type).
+
+scan_exp([X|Str], Accum, Line, Out, Type) when X==$- ->
+ scan_exp2(Str, [X|Accum], Line, Out, Type);
+scan_exp(Str, Accum, Line, Out, Type) ->
+ scan_exp2(Str, Accum, Line, Out, Type).
+
+scan_exp2([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
+ scan_exp2(Str, [X|Accum], Line, Out, Type);
+%% Since '.2' is allowed, we add '0' in front to be sure (erlang do not allow
+%% list_to_float(".2")).
+scan_exp2(Str, Accum, Line, Out, Type) ->
+ scan(Str, Line, [{'num', list_to_float([$0|lists:reverse(Accum)])} | Out], Type).
+
+
+scan_name([X|Str], Accum, Line, Out, Type) when ?is_upper(X) ->
+ scan_name(Str, [X|Accum], Line, Out, Type);
+scan_name([X|Str], Accum, Line, Out, Type) when ?is_lower(X) ->
+ scan_name(Str, [X|Accum], Line, Out, Type);
+scan_name([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
+ scan_name(Str, [X|Accum], Line, Out, Type);
+scan_name([$_|Str], Accum, Line, Out, dollar) ->
+ scan_name(Str, [$_|Accum], Line, Out, dollar);
+scan_name(S, Accum, Line, [{bslsh,LL} | Out], Type) ->
+ %% An escaped identifier.
+ L = lists:reverse(Accum),
+ scan(S, Line, [{'ident', L}, {bslsh,LL} | Out], Type);
+scan_name(S, Accum, Line, Out, Type) ->
+ L = lists:reverse(Accum),
+ {X, NewType} = case check_name(L) of
+ false ->
+ {{'ident', L}, Type};
+ _ ->
+ {{list_to_atom(L), Line}, any}
+ end,
+ scan(S, Line, [X | Out], NewType).
+
+%% Shall scan a constant
+scan_const(char, [$" | Rest], Accum, Line, Out, Type) ->
+ scan(Rest, Line,
+ [{'ident', list_to_atom(lists:reverse(Accum))} | Out], Type);
+scan_const(char, [], _Accum, _Line, Out, _Type) -> %% Bad string
+% {error, "bad_string"};
+ Out;
+scan_const(string, [$' | Rest], Accum, Line, Out, Type) ->
+ scan(Rest, Line,
+ [{'string', lists:reverse(Accum)} | Out], Type);
+scan_const(Mode, [$\\, C | Rest], Accum, Line, Out, Type) ->
+ case escaped_char(C) of
+ error ->
+ %% Bad escape character
+ %% {error, "bad_escape_character"};
+ scan_const(Mode, Rest, [C | Accum], Line, Out, Type);
+ EC ->
+ scan_const(Mode, Rest, [EC | Accum], Line, Out, Type)
+ end;
+scan_const(Mode, [C | Rest], Accum, Line, Out, Type) ->
+ scan_const(Mode, Rest, [C | Accum], Line, Out, Type).
+
+%% Escaped character. Escaped chars are repr as two characters in the
+%% input list of letters and this is translated into one char.
+escaped_char($n) -> $\n;
+escaped_char($t) -> $\t;
+escaped_char($v) -> $\v;
+escaped_char($b) -> $\b;
+escaped_char($r) -> $ ;
+escaped_char($f) -> $\f;
+escaped_char($a) -> $\a;
+escaped_char($\\) -> $\\;
+escaped_char($?) -> $?;
+escaped_char($') -> $';
+escaped_char($") -> $";
+%% Error
+escaped_char(_Other) -> error.
+
+
+check_name("exist") -> true;
+check_name("default") -> true;
+check_name("_length") -> true;
+check_name("_d") -> true;
+check_name("_type_id") -> true;
+check_name("_repos_id") -> true;
+check_name("not") -> true;
+check_name("or") -> true;
+check_name("and") -> true;
+check_name("FALSE") -> true;
+check_name("TRUE") -> true;
+check_name("in") -> true;
+check_name(_) -> false.
+
+
diff --git a/lib/cosNotification/src/cosNotification_eventDB.erl b/lib/cosNotification/src/cosNotification_eventDB.erl
new file mode 100644
index 0000000000..89332d53f2
--- /dev/null
+++ b/lib/cosNotification/src/cosNotification_eventDB.erl
@@ -0,0 +1,1350 @@
+%%--------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-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 : cosNotification_eventDB.erl
+%% Purpose :
+%% Purpose : This module is supposed to centralize Event storage.
+%% Comments:
+%% * Setting Order Policy to AnyOrder eq. Priority order
+%%
+%% * Setting Discard Policy to AnyOrder eq. RejectNewEvents.
+%%
+%% * DB ordering: Since the deliver- and discard-order may differ we need
+%% two ets-tables, both of type 'ordered_set'. They contain:
+%% - table 1 (T1): deliver order key and the associated event.
+%% - table 2 (T2): discard order key.
+%%
+%% When adding a new event we add, if necessary, related keys in T2.
+%% For example, if we should discard events in FIFO order, the delivery
+%% order may be set to Priority order. If the Max Event limit is reached
+%% we first look in T2 to find out which event to discard by using and
+%% reorder the key elements. T2 gives {TimeStamp, Priority}, which is used
+%% to lookup in T1 as {Priority, TimeStamp}.
+%% A TimeStamp is always included in the DB keys, even if FIFO or LIFO
+%% is used, since lots of events probably will have the same prioity and
+%% with a little bit of bad luck some events will never be delivered.
+%%
+%% Note: deliver order AnyOrder and PriorityOrder is equal since the later
+%% is defined as default.
+%% discard order AnyOrder and RejectNewEvents is equal since the later
+%% is defined as default.
+%% The keys used is ('-' indicates T2 is not needed and, thus, not instantiated):
+%%
+%% T1 policy T1 Key T2 Policy T2 Key
+%% ------------------------------------------------------------------
+%% DeadlineOrder {DL, Key, Prio} PriorityOrder {Prio, Key, DL}
+%% DeadlineOrder {DL, Key} FifoOrder {Key, DL}
+%% DeadlineOrder {DL, Key} LifoOrder {Key, DL}
+%% DeadlineOrder {DL, Key} RejectNewEvents -
+%% DeadlineOrder {DL, Key} DeadlineOrder -
+%% FifoOrder {Key, DL} DeadlineOrder {DL, Key}
+%% FifoOrder {Key, Prio} PriorityOrder {Prio, Key}
+%% FifoOrder Key RejectNewEvents -
+%% FifoOrder Key Fifo -
+%% FifoOrder Key Lifo -
+%% PriorityOrder {Prio, Key, DL} DeadlineOrder {DL, Key, Prio}
+%% PriorityOrder {Prio, Key} Fifo {Key, Prio}
+%% PriorityOrder {Prio, Key} Lifo {Key, Prio}
+%% PriorityOrder {Prio, Key} RejectNewEvents -
+%% ------------------------------------------------------------------
+%% DL == Deadline, Key == TimeStamp, Prio == Priority
+%%
+%% NOTE: If defined, the Discard DB Keys are the same as in Event DB, except
+%% that the first and last Key change place. {K1,K2}<->{K2,K1} and
+%% {K1,K2,K3}<->{K3,K2,K1}.
+%%----------------------------------------------------------------------
+
+-module(cosNotification_eventDB).
+
+
+%%--------------- INCLUDES -----------------------------------
+-include_lib("orber/include/corba.hrl").
+-include_lib("orber/include/ifr_types.hrl").
+-include_lib("cosTime/include/TimeBase.hrl").
+
+%% Application files
+-include("CosNotification.hrl").
+-include("CosNotifyChannelAdmin.hrl").
+-include("CosNotifyComm.hrl").
+-include("CosNotifyFilter.hrl").
+
+-include("CosNotification_Definitions.hrl").
+
+%%--------------- EXPORTS ------------------------------------
+%% Internal Filter Functions
+-export([validate_event/5,
+ create_db/4,
+ destroy_db/1,
+ get_event/1,
+ get_event/2,
+ get_events/2,
+ get_events/3,
+ delete_events/1,
+ update/2,
+ update/4,
+ add_event/2,
+ add_event/4,
+ add_and_get_event/2,
+ add_and_get_event/3,
+ add_and_get_event/4,
+ add_and_get_event/5,
+ gc_events/2,
+ gc_events_local/4,
+ gc_start/2,
+ filter_events/2,
+ filter_events/3,
+ status/2]).
+
+%%--------------- DATA STRUCTURES ----------------------------
+-record(dbRef, {orderRef, discardRef, orderPolicy, discardPolicy,
+ defPriority, maxEvents, defStopT, startTsupport,
+ stopTsupport, gcTime, gcLimit, timeRef}).
+
+
+
+%%--------------- DEFINES ------------------------------------
+
+-define(CreateRef(OR, DR, O, D, DP, ME, DS, StaT, StoT, GT, GL, TR),
+ #dbRef{orderRef=OR, discardRef=DR, orderPolicy=O, discardPolicy=D,
+ defPriority=DP, maxEvents=ME, defStopT=DS, startTsupport=StaT,
+ stopTsupport=StoT, gcTime=GT, gcLimit=round(ME*GL/100),
+ timeRef=TR}).
+
+
+-define(get_OrderP(DR), DR#dbRef.orderPolicy).
+-define(get_DiscardP(DR), DR#dbRef.discardPolicy).
+-define(get_OrderRef(DR), DR#dbRef.orderRef).
+-define(get_DiscardRef(DR), DR#dbRef.orderRef).
+-define(get_DefPriority(DR), DR#dbRef.defPriority).
+-define(get_MaxEvents(DR), DR#dbRef.maxEvents).
+-define(get_DefStopT(DR), DR#dbRef.defStopT).
+-define(get_StartTsupport(DR), DR#dbRef.startTsupport).
+-define(get_StopTsupport(DR), DR#dbRef.stopTsupport).
+-define(get_GCTime(DR), DR#dbRef.gcTime).
+-define(get_GCLimit(DR), DR#dbRef.gcLimit).
+-define(get_TimeRef(DR), DR#dbRef.timeRef).
+
+-define(set_OrderP(DR, O), DR#dbRef{orderPolicy = O}).
+-define(set_DiscardP(DR, D), DR#dbRef{discardPolicy = D}).
+-define(set_OrderRef(DR, E), DR#dbRef{orderRef = E}).
+-define(set_DiscardRef(DR, E), DR#dbRef{orderRef = E}).
+-define(set_DefPriority(DR, DP), DR#dbRef{defPriority = DP}).
+-define(set_MaxEvents(DR, ME), DR#dbRef{maxEvents = ME}).
+-define(set_DefStopT(DR, DS), DR#dbRef{defStopT = DS}).
+-define(set_StartTsupport(DR, B), DR#dbRef{startTsupport = B}).
+-define(set_StopTsupport(DR, B), DR#dbRef{stopTsupport = B}).
+
+-define(is_StartTNotSupported(DR), DR#dbRef.startTsupport == false).
+-define(is_StopTNotSupported(DR), DR#dbRef.stopTsupport == false).
+-define(is_TimeoutNotUsed(DR), DR#dbRef.defStopT == 0).
+
+
+%%------------------------------------------------------------
+%% function : status
+%% Arguments: DBRef
+%% Key - which information we want.
+%% Returns : Data related to the Key.
+%%------------------------------------------------------------
+status(DBRef, eventCounter) ->
+ ets:info(?get_OrderRef(DBRef), size);
+status(DBRef, {batchLimit, Limit}) ->
+ case ets:info(?get_OrderRef(DBRef), size) of
+ Current when is_integer(Current) andalso Current >= Limit ->
+ ?debug_print("BATCH LIMIT (~p) REACHED, CONTAINS: ~p~n", [Limit, Current]),
+ true;
+ _Other ->
+ ?debug_print("BATCH LIMIT (~p) NOT REACHED, CONTAINS: ~p~n",
+ [Limit, _Other]),
+ false
+ end;
+status(DBRef, {batchLimit, Limit, TemporaryMax}) ->
+ case ets:info(?get_OrderRef(DBRef), size) of
+ Current when is_integer(Current) andalso Current >= TemporaryMax ->
+ ?debug_print("MAX LIMIT (~p) REACHED, CONTAINS: ~p~n",
+ [TemporaryMax, Current]),
+ true;
+ Current when is_integer(Current) andalso Current >= Limit ->
+ ?debug_print("BATCH LIMIT (~p) REACHED, CONTAINS: ~p~n", [Limit, Current]),
+ true;
+ _Other ->
+ ?debug_print("BATCH LIMIT (~p) NOT REACHED, CONTAINS: ~p~n",
+ [Limit, _Other]),
+ false
+ end;
+status(_, _) ->
+ error.
+
+
+%%------------------------------------------------------------
+%% function : gc_events_local
+%% Arguments: DBRef
+%% Returns :
+%% Comment : This function is intended for "emergency" GC, i.e.,
+%% when the DB must discard events we should first try
+%% to remove events with expired deadlines.
+%%------------------------------------------------------------
+gc_events_local(_, _, false, _) ->
+ ok;
+gc_events_local(_, _, _, 0) ->
+ ok;
+gc_events_local(ORef, DRef, _, _) ->
+ gc_loop(ets:first(ORef), ORef, DRef).
+
+%%------------------------------------------------------------
+%% function : gc_events
+%% Arguments: DBRef
+%% Priority - 'low', 'medium' or 'high'; will determine
+%% how important a fast gc is.
+%% Returns :
+%% Comment : This function is intended for background GC.
+%%------------------------------------------------------------
+gc_events(DBRef, _Priority) when ?is_TimeoutNotUsed(DBRef) ->
+ ok;
+gc_events(DBRef, _Priority) when ?is_StopTNotSupported(DBRef) ->
+ ok;
+gc_events(DBRef, Priority) ->
+ {M,S,U} = now(),
+ case get(oe_GC_timestamp) of
+ Num when {M,S,U} > Num ->
+ put(oe_GC_timestamp, {M,S+?get_GCTime(DBRef),U}),
+ spawn_link(?MODULE, gc_start, [DBRef, Priority]);
+ _->
+ ok
+ end.
+
+
+%%------------------------------------------------------------
+%% function : gc_start
+%% Arguments:
+%% Returns :
+%%------------------------------------------------------------
+gc_start(#dbRef{orderRef = ORef, discardRef = DRef}, Priority) ->
+ process_flag(priority, Priority),
+ gc_loop(ets:first(ORef), ORef, DRef).
+
+gc_loop('$end_of_table', _, _) ->
+ ok;
+gc_loop(Key, ORef, DRef) ->
+ [{Keys,DL,_,_,_}]=ets:lookup(ORef, Key),
+ case check_deadline(DL) of
+ true when DRef == undefined ->
+ ets:delete(ORef, Key);
+ true ->
+ ets:delete(ORef, Key),
+ gc_discard_DB(Keys, DRef);
+ _ ->
+ ok
+ end,
+ gc_loop(ets:next(ORef, Key), ORef, DRef).
+
+gc_discard_DB({Key1, Key2}, DRef) ->
+ ets:delete(DRef, {Key2, Key1});
+gc_discard_DB({Key1, Key2, Key3}, DRef) ->
+ ets:delete(DRef, {Key3, Key2, Key1}).
+
+%%------------------------------------------------------------
+%% function : create_FIFO_Key
+%% Arguments:
+%% Returns :
+%%------------------------------------------------------------
+create_FIFO_Key() ->
+ {M, S, U} = erlang:now(),
+ -M*1000000000000 - S*1000000 - U.
+
+%%------------------------------------------------------------
+%% function : convert_FIFO_Key
+%% Arguments:
+%% Returns : A now tuple
+%% Comment : Used when we must reuse a timestamp, i.e., only
+%% when we must reorder the DB.
+%%------------------------------------------------------------
+convert_FIFO_Key(Key) ->
+ K = abs(Key),
+ Secs = trunc(K/1000000),
+ M = trunc(K/1000000000000),
+ S = Secs-M*1000000,
+ U = K - S*1000000-M*1000000000000,
+ {M, S, U}.
+
+%%------------------------------------------------------------
+%% function : extract_priority
+%% Arguments: Event
+%% Defalt Value
+%% Mapping Filter Value
+%% - false value not needed (depends on QoS type)
+%% - undefined value needed but no filter associated.
+%% Returns :
+%%------------------------------------------------------------
+extract_priority(_, _, false) ->
+ false;
+extract_priority(#'CosNotification_StructuredEvent'
+ {header = #'CosNotification_EventHeader'
+ {variable_header = VH}}, DefPriority, undefined) ->
+ extract_value(VH, ?not_Priority, DefPriority);
+%% Maybe a unstructured event.
+extract_priority(_, DefPriority, undefined) ->
+ DefPriority;
+extract_priority(_, _, PriorityOverride) ->
+ %% Must have an associated MappingFilter for Priority.
+ PriorityOverride.
+
+%%------------------------------------------------------------
+%% function : extract_start_time
+%% Arguments:
+%% Returns :
+%%------------------------------------------------------------
+extract_start_time(_, false, _) ->
+ false;
+extract_start_time(#'CosNotification_StructuredEvent'
+ {header = #'CosNotification_EventHeader'
+ {variable_header = VH}}, _, TRef) ->
+ ST = case extract_value(VH, ?not_StartTime, undefined) of
+ UTC when is_record(UTC, 'TimeBase_UtcT') ->
+ UTC;
+ _ ->
+ false
+ end,
+ convert_time(ST, TRef, now());
+extract_start_time(_, _, _) ->
+ false.
+
+%%------------------------------------------------------------
+%% function : extract_deadline
+%% Arguments: Structured Event
+%% Default Timeout Value - TimeT or UtcT (see cosTime).
+%% StopTSupported - boolean().
+%% TRef - reference to TimeService
+%% Mapping Filter Value
+%% - false eq. value not needed (depends on QoS type)
+%% - undefined eq. value needed but no filter associated.
+%% Now - used when we want to reuse old TimeStamp which
+%% must be done when changing QoS.
+%% Returns : A modified return from now().
+%%------------------------------------------------------------
+extract_deadline(_, _, _, _, false) ->
+ false;
+extract_deadline(Event, DefaultT, StopTSupported, TRef, MappingVal) ->
+ extract_deadline(Event, DefaultT, StopTSupported, TRef, MappingVal, now()).
+
+extract_deadline(_, _, _, _, false, _) ->
+ false;
+extract_deadline(#'CosNotification_StructuredEvent'
+ {header = #'CosNotification_EventHeader'
+ {variable_header = VH}}, DefaultT, StopTSupported,
+ TRef, undefined, Now) ->
+ DL = case extract_value(VH, ?not_Timeout, undefined) of
+ undefined when StopTSupported == true, TRef =/= undefined ->
+ case extract_value(VH, ?not_StopTime, undefined) of
+ undefined ->
+ DefaultT;
+ DefinedTime ->
+ DefinedTime
+ end;
+ undefined ->
+ DefaultT;
+ DefinedTime ->
+ DefinedTime
+ end,
+ convert_time(DL, TRef, Now);
+%% Maybe a unstructured event.
+extract_deadline(_, Time, _, TRef, undefined, Now) ->
+ convert_time(Time, TRef, Now);
+extract_deadline(_, _, _, TRef, DOverride, Now) ->
+ %% Must have an associated MappingFilter defining a Deadline.
+ convert_time(DOverride, TRef, Now).
+
+convert_time(0, _, _) ->
+ false;
+convert_time(UTC, TRef, {M,S,U}) when is_record(UTC, 'TimeBase_UtcT') ->
+ case catch get_time_diff(UTC, TRef) of
+ {'EXCEPTION', _} ->
+ false;
+ {'EXIT', _} ->
+ false;
+ DL ->
+ MicroSecs = round(DL/10),
+ Secs = round(MicroSecs/1000000),
+ MegaSecs = round(Secs/1000000),
+ {-M-MegaSecs, -S-Secs+MegaSecs, -U-MicroSecs+Secs}
+ end;
+convert_time(DL, _, {M,S,U}) when is_integer(DL) ->
+ MicroSecs = round(DL/10),
+ Secs = round(MicroSecs/1000000),
+ MegaSecs = round(Secs/1000000),
+ {-M-MegaSecs, -S-Secs+MegaSecs, -U-MicroSecs+Secs};
+convert_time(_, _, _) ->
+ false.
+
+
+get_time_diff(UTC, TRef) ->
+ UTO = 'CosTime_TimeService':universal_time(TRef),
+ UTO2 = 'CosTime_TimeService':uto_from_utc(TRef, UTC),
+ TIO = 'CosTime_UTO':time_to_interval(UTO, UTO2),
+ #'TimeBase_IntervalT'{lower_bound=LB, upper_bound = UB} =
+ 'CosTime_TIO':'_get_time_interval'(TIO),
+ UB-LB.
+
+check_deadline(DL) when is_tuple(DL) ->
+ {M,S,U} = now(),
+ DL >= {-M,-S,-U};
+check_deadline(_DL) ->
+ %% This case will cover if no timeout is set.
+ false.
+
+check_start_time(ST) when is_tuple(ST) ->
+ {M,S,U} = now(),
+ ST >= {-M,-S,-U};
+check_start_time(_ST) ->
+ %% This case will cover if no earliest delivery time is set.
+ true.
+
+%%------------------------------------------------------------
+%% function : extract_value
+%% Arguments: A Property Sequence
+%% ID - wanted property string()
+%% Other - default-value.
+%% Returns : Value associated with given ID or default value.
+%%------------------------------------------------------------
+extract_value([], _, Other) ->
+ Other;
+extract_value([#'CosNotification_Property'{name=ID, value=V}|_], ID, _) ->
+ any:get_value(V);
+extract_value([_H|T], ID, Other) ->
+ extract_value(T, ID, Other).
+
+%%------------------------------------------------------------
+%% function : get_event
+%% Arguments:
+%% Returns :
+%%------------------------------------------------------------
+get_event(DBRef) ->
+ get_event(DBRef, true).
+get_event(DBRef, Delete) ->
+ case get_events(DBRef, 1, Delete) of
+ {[], false} ->
+ {[], false};
+ {[], false, Keys} ->
+ {[], false, Keys};
+ {[Event], Bool} ->
+ {Event, Bool};
+ {[Event], Bool, Keys} ->
+ {Event, Bool, Keys}
+ end.
+
+%%------------------------------------------------------------
+%% function : get_events
+%% Arguments:
+%% Returns : A list of events (possibly empty) and a boolean
+%% indicating if event found.
+%% Comments : Try to extract Max events from the database.
+%%------------------------------------------------------------
+get_events(#dbRef{orderRef = ORef, discardRef = DRef}, Max) ->
+ event_loop(ets:last(ORef), ORef, DRef, Max, [], [], true).
+
+get_events(#dbRef{orderRef = ORef, discardRef = DRef}, Max, Delete) ->
+ event_loop(ets:last(ORef), ORef, DRef, Max, [], [], Delete).
+
+event_loop('$end_of_table', _, _, _, [], _, true) ->
+ {[], false};
+event_loop('$end_of_table', _, _, _, [], [], _) ->
+ {[], false, []};
+event_loop('$end_of_table', _ORef, _, _, Accum, _Keys, true) ->
+ {lists:reverse(Accum), true};
+event_loop('$end_of_table', _ORef, _, _, Accum, Keys, _) ->
+ {lists:reverse(Accum), true, Keys};
+event_loop(_, _ORef, _, 0, [], _Keys, true) ->
+ %% Only possible if some tries to pull a sequence of 0 events.
+ %% Should we really test for this case?
+ {[], false};
+event_loop(_, _ORef, _, 0, [], Keys, _) ->
+ {[], false, Keys};
+event_loop(_, _ORef, _, 0, Accum, _Keys, true) ->
+ {lists:reverse(Accum), true};
+event_loop(_, _ORef, _, 0, Accum, Keys, _) ->
+ {lists:reverse(Accum), true, Keys};
+event_loop(Key, ORef, undefined, Left, Accum, Keys, Delete) ->
+ [{_,DL,ST,_PO,Event}]=ets:lookup(ORef, Key),
+ case check_deadline(DL) of
+ true ->
+ ets:delete(ORef, Key),
+ event_loop(ets:prev(ORef, Key), ORef, undefined,
+ Left, Accum, Keys, Delete);
+ false ->
+ case check_start_time(ST) of
+ true when Delete == true ->
+ ets:delete(ORef, Key),
+ event_loop(ets:prev(ORef, Key), ORef, undefined,
+ Left-1, [Event|Accum], Keys, Delete);
+ true ->
+ event_loop(ets:prev(ORef, Key), ORef, undefined,
+ Left-1, [Event|Accum], [{ORef, Key}|Keys], Delete);
+ false ->
+ event_loop(ets:prev(ORef, Key), ORef, undefined,
+ Left, Accum, Keys, Delete)
+ end
+ end;
+event_loop({Key1, Key2}, ORef, DRef, Left, Accum, Keys, Delete) ->
+ [{_,DL,ST,_PO,Event}]=ets:lookup(ORef, {Key1, Key2}),
+ case check_deadline(DL) of
+ true ->
+ ets:delete(ORef, {Key1, Key2}),
+ ets:delete(DRef, {Key2, Key1}),
+ event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
+ Left, Accum, Keys, Delete);
+ false ->
+ case check_start_time(ST) of
+ true when Delete == true ->
+ ets:delete(ORef, {Key1, Key2}),
+ ets:delete(DRef, {Key2, Key1}),
+ event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
+ Left-1, [Event|Accum], Keys, Delete);
+ true ->
+ event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
+ Left-1, [Event|Accum],
+ [{ORef, {Key1, Key2}}, {DRef, {Key2, Key1}}|Keys],
+ Delete);
+ false ->
+ event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
+ Left, Accum, Keys, Delete)
+ end
+ end;
+event_loop({Key1, Key2, Key3}, ORef, DRef, Left, Accum, Keys, Delete) ->
+ [{_,DL,ST,_PO,Event}]=ets:lookup(ORef, {Key1, Key2, Key3}),
+ case check_deadline(DL) of
+ true ->
+ ets:delete(ORef, {Key1, Key2, Key3}),
+ ets:delete(DRef, {Key3, Key2, Key1}),
+ event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
+ Left, Accum, Keys, Delete);
+ false ->
+ case check_start_time(ST) of
+ true when Delete == true ->
+ ets:delete(ORef, {Key1, Key2, Key3}),
+ ets:delete(DRef, {Key3, Key2, Key1}),
+ event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
+ Left-1, [Event|Accum], Keys, Delete);
+ true ->
+ event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
+ Left-1, [Event|Accum],
+ [{ORef, {Key1, Key2, Key3}},
+ {DRef, {Key3, Key2, Key1}}|Keys], Delete);
+ false ->
+ event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
+ Left, Accum, Keys, Delete)
+ end
+ end.
+
+%%------------------------------------------------------------
+%% function : delete_events
+%% Arguments: EventList - what's returned by get_event, get_events
+%% and add_and_get_event.
+%% Returns :
+%% Comment : Shall be invoked when it's safe to premanently remove
+%% the events found in the EventList.
+%%
+%%------------------------------------------------------------
+delete_events([]) ->
+ ok;
+delete_events([{DB, Key}|T]) ->
+ ets:delete(DB, Key),
+ delete_events(T).
+
+%%------------------------------------------------------------
+%% function : update
+%% Arguments:
+%% Returns :
+%% Comment : As default we shall deliver Events in Priority order.
+%% Hence, if AnyOrder set we will still deliver in
+%% Priority order.
+%%------------------------------------------------------------
+update(undefined, _QoS) ->
+ ok;
+update(DBRef, QoS) ->
+ update(DBRef, QoS, undefined, undefined).
+
+update(DBRef, QoS, LifeFilter, PrioFilter) ->
+ case updated_order(DBRef, ?not_GetOrderPolicy(QoS)) of
+ false ->
+ case updated_discard(DBRef, ?not_GetDiscardPolicy(QoS)) of
+ false ->
+ DBR2 = ?set_DefPriority(DBRef, ?not_GetPriority(QoS)),
+ DBR3 = ?set_MaxEvents(DBR2, ?not_GetMaxEventsPerConsumer(QoS)),
+ DBR4 = ?set_DefStopT(DBR3, ?not_GetTimeout(QoS)),
+ DBR5 = ?set_StartTsupport(DBR4, ?not_GetStartTimeSupported(QoS)),
+ DBR6 = ?set_StopTsupport(DBR5, ?not_GetStopTimeSupported(QoS)),
+ case ets:info(?get_OrderRef(DBR6), size) of
+ N when N =< ?get_MaxEvents(DBR6) ->
+ %% Even if the QoS MaxEvents have been changed
+ %% we don't reach the limit.
+ DBR6;
+ N ->
+ %% The QoS MaxEvents must have been decreased.
+ discard_events(DBR6, N-?get_MaxEvents(DBR6)),
+ DBR6
+ end;
+ true ->
+ destroy_discard_db(DBRef),
+ NewDBRef = create_db(QoS, ?get_GCTime(DBRef), ?get_GCLimit(DBRef),
+ ?get_TimeRef(DBRef)),
+ move_events(DBRef, NewDBRef, ets:first(?get_OrderRef(DBRef)),
+ LifeFilter, PrioFilter)
+ end;
+ true ->
+ destroy_discard_db(DBRef),
+ NewDBRef = create_db(QoS, ?get_GCTime(DBRef), ?get_GCLimit(DBRef),
+ ?get_TimeRef(DBRef)),
+ move_events(DBRef, NewDBRef, ets:first(?get_OrderRef(DBRef)),
+ LifeFilter, PrioFilter)
+ end.
+
+updated_order(#dbRef{orderPolicy = Equal}, Equal) -> false;
+updated_order(#dbRef{orderPolicy = ?not_PriorityOrder}, ?not_AnyOrder) -> false;
+updated_order(#dbRef{orderPolicy = ?not_AnyOrder}, ?not_PriorityOrder) -> false;
+updated_order(_, _) -> true.
+
+updated_discard(#dbRef{discardPolicy = Equal}, Equal) -> false;
+updated_discard(#dbRef{discardPolicy = ?not_RejectNewEvents}, ?not_AnyOrder) -> false;
+updated_discard(#dbRef{discardPolicy = ?not_AnyOrder}, ?not_RejectNewEvents) -> false;
+updated_discard(_, _) -> true.
+
+move_events(DBRef, NewDBRef, '$end_of_table', _, _) ->
+ destroy_order_db(DBRef),
+ case ets:info(?get_OrderRef(NewDBRef), size) of
+ N when N =< ?get_MaxEvents(NewDBRef) ->
+ %% Even if the QoS MaxEvents have been changed
+ %% we don't reach the limit.
+ NewDBRef;
+ N ->
+ %% The QoS MaxEvents must have been decreased.
+ discard_events(DBRef, N-?get_MaxEvents(NewDBRef)),
+ NewDBRef
+ end;
+move_events(DBRef, NewDBRef, Key, LifeFilter, PrioFilter) ->
+ [{Keys, DeadLine, StartTime, PriorityOverride, Event}] =
+ ets:lookup(?get_OrderRef(DBRef), Key),
+ case check_deadline(DeadLine) of
+ true ->
+ ok;
+ _->
+ write_event(?get_OrderP(DBRef),
+ {Keys, DeadLine, StartTime, PriorityOverride, Event},
+ DBRef, NewDBRef, Key, LifeFilter, PrioFilter)
+ end,
+ ets:delete(?get_OrderRef(DBRef), Key),
+ move_events(DBRef, NewDBRef, ets:next(?get_OrderRef(DBRef), Key),
+ LifeFilter, PrioFilter).
+
+%% We cannot use do_add_event directly since we MUST lookup the timestamp (TS).
+write_event(?not_DeadlineOrder, {{_, TS, _Prio}, DL, ST, PO, Event}, _DBRef, NewDBRef,
+ _Key, _LifeFilter, _PrioFilter) ->
+ StartT = update_starttime(NewDBRef, Event, ST),
+ %% Deadline and Priority previously extracted.
+ do_add_event(NewDBRef, Event, TS, DL, StartT, PO);
+write_event(?not_DeadlineOrder, {{_, TS}, DL, _ST, PO, Event}, _DBRef, NewDBRef,
+ _Key, _LifeFilter, PrioFilter) ->
+ %% Priority not previously extracted.
+ POverride = update_priority(NewDBRef, PrioFilter, Event, PO),
+ StartT = extract_start_time(Event, ?get_StartTsupport(NewDBRef),
+ ?get_TimeRef(NewDBRef)),
+ do_add_event(NewDBRef, Event, TS, DL, StartT, POverride);
+write_event(?not_FifoOrder, {{TS, _PorD}, DL, ST, PO, Event}, _DBRef, NewDBRef,
+ _Key, LifeFilter, PrioFilter) ->
+ %% Priority or Deadline have been extracted before but we cannot tell which.
+ POverride = update_priority(NewDBRef, PrioFilter, Event, PO),
+ DeadL = update_deadline(NewDBRef, LifeFilter, Event, TS, DL),
+ StartT = update_starttime(NewDBRef, Event, ST),
+ do_add_event(NewDBRef, Event, TS, DeadL, StartT, POverride);
+write_event(?not_FifoOrder, {TS, DL, ST, PO, Event}, _DBRef, NewDBRef,
+ _Key, LifeFilter, PrioFilter) ->
+ %% Priority and Deadline not extracetd before. Do it now.
+ POverride = update_priority(NewDBRef, PrioFilter, Event, PO),
+ DeadL = update_deadline(NewDBRef, LifeFilter, Event, TS, DL),
+ StartT = update_starttime(NewDBRef, Event, ST),
+ do_add_event(NewDBRef, Event, TS, DeadL, StartT, POverride);
+%% Order Policy must be AnyOrder or PriorityOrder.
+write_event(_, {{_Prio, TS}, DL, ST, PO, Event}, _DBRef, NewDBRef,
+ _Key, LifeFilter, _PrioFilter) ->
+ DeadL = update_deadline(NewDBRef, LifeFilter, Event, TS, DL),
+ StartT = update_starttime(NewDBRef, Event, ST),
+ do_add_event(NewDBRef, Event, TS, DeadL, StartT, PO);
+write_event(_, {{_Prio, TS, DL}, DL, ST, PO, Event}, _DBRef, NewDBRef, _Key, _, _) ->
+ %% Both Deadline and Priority have been extracetd before.
+ StartT = update_starttime(NewDBRef, Event, ST),
+ do_add_event(NewDBRef, Event, TS, DL, StartT, PO).
+
+
+%%------------------------------------------------------------
+%% function : update_priority
+%% Arguments:
+%% Returns :
+%% Comment : The purpose with this function is to avoid
+%% calling MappingFilter priority again, especially
+%% deadline again (we especially want to avoid calling
+%% since it may require intra-ORB communication.
+%% Use only when doing an update.
+%%------------------------------------------------------------
+update_priority(DBRef, PrioFilter, Event, OldPrio) when is_atom(OldPrio) ->
+ get_prio_mapping_value(DBRef, PrioFilter, Event);
+update_priority(_DBRef, _PrioFilter, _Event, OldPrio) ->
+ OldPrio.
+
+%%------------------------------------------------------------
+%% function : update_deadline
+%% Arguments:
+%% Returns :
+%% Comment : The purpose with this function is to avoid
+%% calling MappingFilter or parsing the events for
+%% deadline again (we especially want to avoid calling
+%% the MappingFilter since it may require intra-ORB
+%% communication. Use only when doing an update.
+%%------------------------------------------------------------
+update_deadline(DBRef, _LifeFilter, _Event, _TS, _OldDeadL) when
+ ?get_DiscardP(DBRef) =/= ?not_DeadlineOrder,
+ ?get_OrderP(DBRef) =/= ?not_DeadlineOrder,
+ ?is_StopTNotSupported(DBRef) ->
+ %% We do not need to extract the Deadline since it will not be used.
+ false;
+update_deadline(DBRef, LifeFilter, Event, TS, OldDeadL) when is_atom(OldDeadL) ->
+ %% We need the Deadline and it have not been extracetd before.
+ DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
+ %% We must find out when the event was delivered; setting a deadline using
+ %% a new timestamp would not be accurate since we cannot tell for how long
+ %% the event have been waiting.
+ OldNow = convert_FIFO_Key(TS),
+ extract_deadline(Event, ?get_DefStopT(DBRef), ?get_StopTsupport(DBRef),
+ ?get_TimeRef(DBRef), DOverride, OldNow);
+update_deadline(_DBRef, _LifeFilter, _Event, _TS, OldDeadL) ->
+ %% We need the Deadline and it have been extracetd before.
+ OldDeadL.
+
+%%------------------------------------------------------------
+%% function : update_starttime
+%% Arguments:
+%% Returns :
+%% Comment : The purpose with this function is to avoid
+%% parsing the events for starttime again.
+%% Use only when doing an update.
+%%------------------------------------------------------------
+update_starttime(DBRef, Event, OldStartT) when is_atom(OldStartT) ->
+ %% Probably not previously extracted; try to get it.
+ extract_start_time(Event, ?get_StartTsupport(DBRef), ?get_TimeRef(DBRef));
+update_starttime(_DBRef, _Event, OldStartT) ->
+ %% Previously extracted.
+ OldStartT.
+
+%%------------------------------------------------------------
+%% function : discard_events
+%% Arguments: DBRef
+%% N - number of events we must discard.
+%% Returns :
+%% Comment : As default we shall Reject New Events when the limit
+%% is reached. Any discard order will do the same.
+%%
+%% This function can only be used for the discard policies
+%% Fifo, Priority and Deadline. Any or RejectNewEvents
+%% will not allow events to be stored at all, i.e., no events
+%% to discard. Lifo will not be stored either since when
+%% trying to add an event it is definitely the last event in.
+%%------------------------------------------------------------
+%% Since no Discard DB must the same Order policy.
+discard_events(#dbRef{orderRef = ORef, discardRef = undefined,
+ discardPolicy = ?not_DeadlineOrder}, N) ->
+ ?debug_print("Discarding ~p events Deadline Order.",[N]),
+ index_loop_backward(ets:last(ORef), undefined, ORef, N);
+discard_events(#dbRef{orderRef = ORef, discardRef = DRef,
+ discardPolicy = ?not_DeadlineOrder}, N) ->
+ ?debug_print("Discarding ~p events Deadline Order.",[N]),
+ index_loop_backward(ets:last(DRef), DRef, ORef, N);
+%% Fifo.
+discard_events(#dbRef{orderRef = ORef, discardRef = undefined,
+ discardPolicy = ?not_FifoOrder}, N) ->
+ ?debug_print("Discarding ~p events Fifo Order.",[N]),
+ index_loop_backward(ets:last(ORef), undefined, ORef, N);
+discard_events(#dbRef{orderRef = ORef, discardRef = DRef,
+ discardPolicy = ?not_FifoOrder}, N) ->
+ ?debug_print("Discarding ~p events Fifo Order.",[N]),
+ index_loop_backward(ets:last(DRef), DRef, ORef, N);
+%% Lifo- or Priority-Order
+discard_events(#dbRef{orderRef = ORef, discardRef = undefined}, N) ->
+ ?debug_print("Discarding ~p events Lifo- or Priority-Order.",[N]),
+ index_loop_forward(ets:first(ORef), undefined, ORef, N);
+discard_events(#dbRef{orderRef = ORef, discardRef = DRef}, N) ->
+ ?debug_print("Discarding ~p events Lifo- or Priority-Order.",[N]),
+ index_loop_forward(ets:first(DRef), DRef, ORef, N).
+
+
+index_loop_forward('$end_of_table', _, _, _Left) ->
+ ok;
+index_loop_forward(_, _, _, 0) ->
+ ok;
+index_loop_forward(Key, undefined, ORef, Left) ->
+ ets:delete(ORef, Key),
+ NewKey=ets:next(ORef, Key),
+ index_loop_forward(NewKey, undefined, ORef, Left-1);
+
+index_loop_forward({Key1, Key2, Key3}, DRef, ORef, Left) ->
+ ets:delete(DRef, {Key1, Key2, Key3}),
+ ets:delete(ORef, {Key3, Key2, Key1}),
+ NewKey=ets:next(DRef, {Key1, Key2, Key3}),
+ index_loop_forward(NewKey, DRef, ORef, Left-1);
+
+index_loop_forward({Key1, Key2}, DRef, ORef, Left) ->
+ ets:delete(DRef, {Key1, Key2}),
+ ets:delete(ORef, {Key2, Key1}),
+ NewKey=ets:next(DRef, {Key1, Key2}),
+ index_loop_forward(NewKey, DRef, ORef, Left-1).
+
+index_loop_backward('$end_of_table', _, _, _) ->
+ ok;
+index_loop_backward(_, _, _, 0) ->
+ ok;
+index_loop_backward(Key, undefined, ORef, Left) ->
+ ets:delete(ORef, Key),
+ NewKey=ets:prev(ORef, Key),
+ index_loop_backward(NewKey, undefined, ORef, Left-1);
+index_loop_backward({Key1, Key2}, DRef, ORef, Left) ->
+ ets:delete(DRef, {Key1, Key2}),
+ ets:delete(ORef, {Key2, Key1}),
+ NewKey=ets:prev(DRef, {Key1, Key2}),
+ index_loop_backward(NewKey, DRef, ORef, Left-1);
+index_loop_backward({Key1, Key2, Key3}, DRef, ORef, Left) ->
+ ets:delete(DRef, {Key1, Key2, Key3}),
+ ets:delete(ORef, {Key3, Key2, Key1}),
+ NewKey=ets:prev(DRef, {Key1, Key2, Key3}),
+ index_loop_backward(NewKey, DRef, ORef, Left-1).
+
+%%------------------------------------------------------------
+%% function : add_and_get_event
+%% Arguments: DBRef and Event
+%% Returns : {[], bool()} | {Event, bool()}
+%% Comment : This function is a mixture of ad anf get events.
+%% The intended use to avoid storing an event when
+%% not necessary.
+%%------------------------------------------------------------
+add_and_get_event(DBRef, Event) ->
+ add_and_get_event(DBRef, Event, undefined, undefined, true).
+
+add_and_get_event(DBRef, Event, Delete) ->
+ add_and_get_event(DBRef, Event, undefined, undefined, Delete).
+
+add_and_get_event(DBRef, Event, LifeFilter, PrioFilter) ->
+ add_and_get_event(DBRef, Event, LifeFilter, PrioFilter, true).
+
+add_and_get_event(DBRef, Event, LifeFilter, PrioFilter, Delete) ->
+ case ets:info(?get_OrderRef(DBRef), size) of
+ 0 when ?is_StartTNotSupported(DBRef), ?is_StopTNotSupported(DBRef),
+ Delete == true ->
+ %% No stored events and no timeouts used; just return the event.
+ {Event, false};
+ 0 when ?is_StartTNotSupported(DBRef), ?is_StopTNotSupported(DBRef) ->
+ %% No stored events and no timeouts used; just return the event.
+ {Event, false, []};
+ 0 when ?is_StartTNotSupported(DBRef) ->
+ %% Only deadline supported, lookup values and cehck if ok.
+ DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
+ DOverride),
+ case check_deadline(DL) of
+ true when Delete == true ->
+ %% Expired, just discard the event.
+ {[], false};
+ true ->
+ {[], false, []};
+ _ when Delete == true ->
+ %% Not expired, we can safely return the event.
+ {Event, false};
+ _ ->
+ %% Not expired, we can safely return the event.
+ {Event, false, []}
+ end;
+ 0 when ?is_StopTNotSupported(DBRef) ->
+ %% Only starttime allowed, test if we can deliver the event now.
+ ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
+ ?get_TimeRef(DBRef)),
+ case check_start_time(ST) of
+ false when Delete == true ->
+ DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
+ POverride = get_prio_mapping_value(DBRef, PrioFilter, Event),
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef),
+ ?get_TimeRef(DBRef), DOverride),
+ do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
+ {[], true};
+ false ->
+ DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
+ POverride = get_prio_mapping_value(DBRef, PrioFilter, Event),
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef),
+ ?get_TimeRef(DBRef), DOverride),
+ do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
+ {[], true, []};
+ _ when Delete == true ->
+ %% Starttime ok, just return the event.
+ {Event, false};
+ _ ->
+ %% Starttime ok, just return the event.
+ {Event, false, []}
+ end;
+ _->
+ %% Event already stored, just have to accept the overhead.
+ ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
+ ?get_TimeRef(DBRef)),
+ DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
+ POverride = get_prio_mapping_value(DBRef, PrioFilter, Event),
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef),
+ ?get_TimeRef(DBRef), DOverride),
+ do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
+ get_event(DBRef, Delete)
+ end.
+
+%%------------------------------------------------------------
+%% function : add_event
+%% Arguments: DBRef and Event
+%% Returns : true (or whatever 'ets:insert' returns) |
+%% {'EXCEPTION', #'IMP_LIMIT'{}}
+%% Comment : As default we shall deliver Events in Priority order.
+%% Hence, if AnyOrder set we will still deliver in
+%% Priority order. But we cannot use only the Priority
+%% value since if "all" events have the same priority
+%% there is a risk that some never will be delivered if
+%% the EventDB always contain events.
+%%
+%% When discard and order policy is equal we only use one
+%% DB since all we have to do is to "read from the other
+%% end" to discard the correct event(s).
+%%
+%% In the discard DB we must also store keys necessary to
+%% lookup the event in the order DB.
+%%
+%% If event limit reached 'IMPL_LIMIT' is raised if
+%% the discard policy is RejectNewEvents or AnyOrder.
+%% Theses two policies we currently define to be equal.
+%%------------------------------------------------------------
+
+add_event(DBRef, Event) ->
+ %% Save overhead by first checking if we really need to extract
+ %% Deadline and/or Priority.
+ Deadline = get_life_mapping_value(DBRef, undefined, Event),
+ Priority = get_prio_mapping_value(DBRef, undefined, Event),
+ add_event_helper(DBRef, Event, Deadline, Priority).
+
+add_event(DBRef, Event, LifeFilter, PrioFilter) ->
+ %% Save overhead by first checking if we really need to extract
+ %% Deadline and/or Priority.
+ Deadline = get_life_mapping_value(DBRef, LifeFilter, Event),
+ Priority = get_prio_mapping_value(DBRef, PrioFilter, Event),
+ add_event_helper(DBRef, Event, Deadline, Priority).
+
+add_event_helper(DBRef, Event, DOverride, POverride) ->
+ case ets:info(?get_OrderRef(DBRef), size) of
+ N when N < ?get_MaxEvents(DBRef), N > ?get_GCLimit(DBRef) ->
+ gc_events(DBRef, low),
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
+ DOverride),
+ case check_deadline(DL) of
+ true ->
+ true;
+ _ ->
+ ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
+ ?get_TimeRef(DBRef)),
+ do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride)
+ end;
+ N when N < ?get_MaxEvents(DBRef) ->
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
+ DOverride),
+ case check_deadline(DL) of
+ true ->
+ true;
+ _ ->
+ ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
+ ?get_TimeRef(DBRef)),
+ do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride)
+ end;
+ _N when ?get_DiscardP(DBRef) == ?not_RejectNewEvents ->
+ gc_events(DBRef, low),
+ corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
+ _N when ?get_DiscardP(DBRef) == ?not_AnyOrder ->
+ gc_events(DBRef, low),
+ corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
+ _N when ?get_DiscardP(DBRef) == ?not_LifoOrder ->
+ gc_events(DBRef, low),
+ corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
+ _N ->
+ gc_events(DBRef, low),
+ %% Other discard policy; we must first store the event
+ %% and the look up in the Discard DB which event we
+ %% should remove.
+ DL = extract_deadline(Event, ?get_DefStopT(DBRef),
+ ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
+ DOverride),
+ case check_deadline(DL) of
+ true ->
+ true;
+ _ ->
+ ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
+ ?get_TimeRef(DBRef)),
+ do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
+ discard_events(DBRef, 1)
+ end
+ end.
+
+
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
+ discardRef = DRef, discardPolicy = ?not_PriorityOrder,
+ defPriority = DefPrio, defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
+ Prio = extract_priority(Event, DefPrio, PO),
+ ets:insert(ORef, {{DL, Key, Prio}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{Prio, Key, DL}});
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
+ discardRef = DRef, discardPolicy = ?not_FifoOrder,
+ defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
+ ets:insert(ORef, {{DL, Key}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{Key, DL}});
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
+ discardRef = DRef, discardPolicy = ?not_LifoOrder,
+ defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
+ ets:insert(ORef, {{DL, Key}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{Key, DL}});
+%% Either the same (DeadlineOrder), RejectNewEvents or AnyOrder. No need
+%% to store anything in the discard policy, i.e., if the same we'll just
+%% read "from the other end" and AnyOrder and RejectNewEvents is equal.
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
+ defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
+ ets:insert(ORef, {{DL, Key}, DL, ST, PO, Event});
+
+
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_FifoOrder,
+ discardRef = DRef, discardPolicy = ?not_DeadlineOrder,
+ defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
+ ets:insert(ORef, {{Key, DL}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{DL, Key}});
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_FifoOrder,
+ discardRef = DRef, discardPolicy = ?not_PriorityOrder,
+ defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
+ Prio = extract_priority(Event, DefPrio, PO),
+ ets:insert(ORef, {{Key, Prio}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{Prio, Key}});
+%% The discard policy must RejectNewEvents, AnyOrder, Fifo or Lifo order.
+do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_FifoOrder,
+ discardRef = _DRef}, Event, Key, DL, ST, PO) ->
+ ets:insert(ORef, {Key, DL, ST, PO, Event});
+
+%% Order Policy must be AnyOrder or PriorityOrder.
+do_add_event(#dbRef{orderRef = ORef,
+ discardRef = DRef, discardPolicy = ?not_DeadlineOrder,
+ defPriority = DefPrio, defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
+ Prio = extract_priority(Event, DefPrio, PO),
+ ets:insert(ORef, {{Prio, Key, DL}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{DL, Key, Prio}});
+do_add_event(#dbRef{orderRef = ORef,
+ discardRef = DRef, discardPolicy = ?not_FifoOrder,
+ defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
+ Prio = extract_priority(Event, DefPrio, PO),
+ ets:insert(ORef, {{Prio, Key}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{Key, Prio}});
+
+do_add_event(#dbRef{orderRef = ORef,
+ discardRef = DRef, discardPolicy = ?not_LifoOrder,
+ defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
+ Prio = extract_priority(Event, DefPrio, PO),
+ ets:insert(ORef, {{Prio, Key}, DL, ST, PO, Event}),
+ ets:insert(DRef, {{Key, Prio}});
+
+%% Order Policy must be AnyOrder or PriorityOrder and Discard Policy must be
+%% AnyOrder or RejectNewEvents
+do_add_event(#dbRef{orderRef = ORef, defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
+ Prio = extract_priority(Event, DefPrio, PO),
+ ets:insert(ORef, {{Prio, Key}, DL, ST, PO, Event}).
+
+%%------------------------------------------------------------
+%% function : destroy_db
+%% Arguments: A DB reference
+%% Returns :
+%%------------------------------------------------------------
+destroy_db(#dbRef{orderRef = ORef, discardRef = undefined}) ->
+ ets:delete(ORef);
+destroy_db(#dbRef{orderRef = ORef, discardRef = DRef}) ->
+ ets:delete(ORef),
+ ets:delete(DRef).
+
+%%------------------------------------------------------------
+%% function : destroy_discard_db
+%% Arguments: A DB reference
+%% Returns :
+%%------------------------------------------------------------
+destroy_discard_db(#dbRef{discardRef = undefined}) ->
+ ok;
+destroy_discard_db(#dbRef{discardRef = DRef}) ->
+ ets:delete(DRef).
+
+%%------------------------------------------------------------
+%% function : destroy_order_db
+%% Arguments: A DB reference
+%% Returns :
+%%------------------------------------------------------------
+destroy_order_db(#dbRef{orderRef = ORef}) ->
+ ets:delete(ORef).
+
+%%------------------------------------------------------------
+%% function : create_db
+%% Arguments: QoS (local representation).
+%% Returns : A DB reference
+%%------------------------------------------------------------
+create_db(QoS, GCTime, GCLimit, TimeRef) ->
+ DiscardRef =
+ case {?not_GetDiscardPolicy(QoS), ?not_GetOrderPolicy(QoS)} of
+ {Equal, Equal} ->
+ undefined;
+ {?not_PriorityOrder, ?not_AnyOrder} ->
+ %% NOTE: Any- and Priority-Order delivery policy is equal.
+ undefined;
+ {?not_RejectNewEvents, _} ->
+ undefined;
+ {?not_AnyOrder, _} ->
+ undefined;
+ {?not_LifoOrder, ?not_FifoOrder} ->
+ undefined;
+ _ ->
+ ets:new(oe_ets, [set, public, ordered_set])
+ end,
+ DBRef = ?CreateRef(ets:new(oe_ets, [set, public, ordered_set]),
+ DiscardRef,
+ ?not_GetOrderPolicy(QoS), ?not_GetDiscardPolicy(QoS),
+ ?not_GetPriority(QoS), ?not_GetMaxEventsPerConsumer(QoS),
+ ?not_GetTimeout(QoS), ?not_GetStartTimeSupported(QoS),
+ ?not_GetStopTimeSupported(QoS), GCTime, GCLimit, TimeRef),
+ if
+ ?is_TimeoutNotUsed(DBRef), ?is_StopTNotSupported(DBRef) ->
+ ok;
+ true ->
+ {M,S,U} = now(),
+ put(oe_GC_timestamp, {M,S+GCTime,U})
+ end,
+ DBRef.
+
+%%------------------------------------------------------------
+%% function : get_prio_mapping_value
+%% Arguments: A MappingFilter reference | undefined
+%% Event (Any or Structured)
+%% Returns : undefined | Data
+%%------------------------------------------------------------
+get_prio_mapping_value(DBRef, _, _) when ?get_DiscardP(DBRef) =/= ?not_PriorityOrder,
+ ?get_OrderP(DBRef) =/= ?not_AnyOrder,
+ ?get_OrderP(DBRef) =/= ?not_PriorityOrder ->
+ false;
+get_prio_mapping_value(_, undefined, _) ->
+ undefined;
+get_prio_mapping_value(_, MFilter, Event) when is_record(Event, 'any') ->
+ case catch 'CosNotifyFilter_MappingFilter':match(MFilter, Event) of
+ {false, DefVal} when is_record(DefVal, 'any') ->
+ any:get_value(DefVal);
+ {true, Matched} when is_record(Matched, 'any') ->
+ any:get_value(Matched);
+ _ ->
+ undefined
+ end;
+get_prio_mapping_value(_, MFilter, Event) ->
+ case catch 'CosNotifyFilter_MappingFilter':match_structured(MFilter, Event) of
+ {false, DefVal} when is_record(DefVal, 'any') ->
+ any:get_value(DefVal);
+ {true, Matched} when is_record(Matched, 'any') ->
+ any:get_value(Matched);
+ _ ->
+ undefined
+ end.
+
+%%------------------------------------------------------------
+%% function : get_life_mapping_value
+%% Arguments: A MappingFilter reference | undefined
+%% Event (Any or Structured)
+%% Returns : undefined | Data
+%%------------------------------------------------------------
+get_life_mapping_value(DBRef, _, _) when ?get_DiscardP(DBRef) =/= ?not_DeadlineOrder,
+ ?get_OrderP(DBRef) =/= ?not_DeadlineOrder,
+ ?is_StopTNotSupported(DBRef) ->
+ false;
+get_life_mapping_value(_, undefined, _) ->
+ undefined;
+get_life_mapping_value(_, MFilter, Event) when is_record(Event, 'any') ->
+ case catch 'CosNotifyFilter_MappingFilter':match(MFilter, Event) of
+ {false, DefVal} when is_record(DefVal, 'any') ->
+ any:get_value(DefVal);
+ {true, Matched} when is_record(Matched, 'any') ->
+ any:get_value(Matched);
+ _ ->
+ undefined
+ end;
+get_life_mapping_value(_, MFilter, Event) ->
+ case catch 'CosNotifyFilter_MappingFilter':match_structured(MFilter, Event) of
+ {false, DefVal} when is_record(DefVal, 'any') ->
+ any:get_value(DefVal);
+ {true, Matched} when is_record(Matched, 'any') ->
+ any:get_value(Matched);
+ _ ->
+ undefined
+ end.
+
+%%------------------------------------------------------------
+%% function : validate_event
+%% Arguments: Subscribe data
+%% A sequence of Events, 'structured' or an 'any' record
+%% A list of filter references
+%% Status, i.e., do we have to filter the events or just check subscr.
+%% Returns : A tuple of two lists; list1 the events that passed
+%% and list2 the events that didn't pass.
+%%------------------------------------------------------------
+validate_event(true, Events, Filters, _, 'MATCH') ->
+ filter_events(Events, Filters, false);
+validate_event(true, Events, _Filters, _, _) ->
+ {Events, []};
+validate_event({_Which, _WC}, Event, Filters, _, 'MATCH') when is_record(Event, any) ->
+ filter_events(Event, Filters, false);
+validate_event({_Which, _WC}, Event, _Filters, _, _) when is_record(Event, any) ->
+ {Event, []};
+validate_event({Which, WC}, Events, Filters, DBRef, 'MATCH') ->
+ Passed=validate_event2(DBRef, Events, Which, WC, []),
+ filter_events(Passed, Filters, true);
+validate_event({Which, WC}, Events, _Filters, DBRef, _) ->
+ Passed=validate_event2(DBRef, Events, Which, WC, []),
+ {lists:reverse(Passed), []}.
+
+validate_event2(_, [], _, _, []) ->
+ [];
+validate_event2(_, [], _, _, Acc) ->
+ Acc;
+validate_event2(DBRef, [Event|T], Which, WC, Acc) ->
+ ET = ((Event#'CosNotification_StructuredEvent'.header)
+ #'CosNotification_EventHeader'.fixed_header)
+ #'CosNotification_FixedEventHeader'.event_type,
+ CheckList =
+ case Which of
+ both ->
+ [ET];
+ domain ->
+ [ET,
+ ET#'CosNotification_EventType'{type_name=""},
+ ET#'CosNotification_EventType'{type_name="*"}];
+ type ->
+ [ET,
+ ET#'CosNotification_EventType'{domain_name=""},
+ ET#'CosNotification_EventType'{domain_name="*"}];
+ _ ->
+ [ET,
+ ET#'CosNotification_EventType'{type_name=""},
+ ET#'CosNotification_EventType'{type_name="*"},
+ ET#'CosNotification_EventType'{domain_name=""},
+ ET#'CosNotification_EventType'{domain_name="*"}]
+ end,
+ case check_subscription(DBRef, CheckList) of
+ true ->
+ validate_event2(DBRef, T, Which, WC, [Event|Acc]);
+ _->
+ case catch cosNotification_Filter:match_types(
+ ET#'CosNotification_EventType'.domain_name,
+ ET#'CosNotification_EventType'.type_name,
+ WC) of
+ true ->
+ validate_event2(DBRef, T, Which, WC, [Event|Acc]);
+ _->
+ validate_event2(DBRef, T, Which, WC, Acc)
+ end
+ end.
+
+check_subscription(_, []) ->
+ false;
+check_subscription(DBRef, [H|T]) ->
+ case ets:lookup(DBRef, H) of
+ [] ->
+ check_subscription(DBRef, T);
+ _ ->
+ true
+ end.
+
+
+%%------------------------------------------------------------
+%% function : filter_events
+%% Arguments: A sequence of structured Events or #any
+%% Returns : A tuple of two lists; list1 the events that passed
+%% and list2 the events that didn't pass.
+%%------------------------------------------------------------
+
+filter_events(Events, []) ->
+ {Events, []};
+filter_events(Events, Filters) ->
+ filter_events(Events, Filters, [], [], false).
+
+filter_events(Events, [], false) ->
+ {Events, []};
+filter_events(Events, [], _) ->
+ {lists:reverse(Events), []};
+filter_events(Events, Filters, Reversed) ->
+ filter_events(Events, Filters, [], [], Reversed).
+
+filter_events([], _, AccPassed, AccFailed, false) ->
+ {lists:reverse(AccPassed), lists:reverse(AccFailed)};
+filter_events([], _, AccPassed, AccFailed, _) ->
+ {AccPassed, AccFailed};
+filter_events([H|T], Filters, AccPassed, AccFailed, Reversed) ->
+ case call_filters(Filters, H) of
+ true ->
+ filter_events(T, Filters, [H|AccPassed], AccFailed, Reversed);
+ _ ->
+ filter_events(T, Filters, AccPassed, [H|AccFailed], Reversed)
+ end;
+filter_events(Any, Filters, _AccPassed, _AccFailed, _Reversed) ->
+ case call_filters(Filters, Any) of
+ true ->
+ {Any, []};
+ _ ->
+ {[], Any}
+ end.
+
+call_filters([], _) ->
+ false;
+call_filters([{_,H}|T], Event) when is_record(Event, any) ->
+ case catch 'CosNotifyFilter_Filter':match(H, Event) of
+ true ->
+ true;
+ _->
+ call_filters(T, Event)
+ end;
+call_filters([{_,H}|T], Event) when ?not_isConvertedAny(Event) ->
+ case catch 'CosNotifyFilter_Filter':match(H,
+ Event#'CosNotification_StructuredEvent'.remainder_of_body) of
+ true ->
+ true;
+ _->
+ call_filters(T, Event)
+ end;
+call_filters([{_,H}|T], Event) ->
+ case catch 'CosNotifyFilter_Filter':match_structured(H, Event) of
+ true ->
+ true;
+ _->
+ call_filters(T, Event)
+ end.
+
+
+%%--------------- END OF MODULE ------------------------------