1%%--------------------------------------------------------------------
2%%
3%% %CopyrightBegin%
4%%
5%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
6%%
7%% Licensed under the Apache License, Version 2.0 (the "License");
8%% you may not use this file except in compliance with the License.
9%% You may obtain a copy of the License at
10%%
11%%     http://www.apache.org/licenses/LICENSE-2.0
12%%
13%% Unless required by applicable law or agreed to in writing, software
14%% distributed under the License is distributed on an "AS IS" BASIS,
15%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16%% See the License for the specific language governing permissions and
17%% limitations under the License.
18%%
19%% %CopyrightEnd%
20%%
21%%
22%%----------------------------------------------------------------------
23%% File    : cosTime.erl
24%% Purpose :
25%%----------------------------------------------------------------------
26
27-module(cosTime).
28
29%%--------------- INCLUDES -----------------------------------
30-include("cosTimeApp.hrl").
31
32%%--------------- EXPORTS-------------------------------------
33%% cosTime API external
34-export([start/0, stop/0,
35	 install_time/0, uninstall_time/0,
36	 install_timerevent/0, uninstall_timerevent/0,
37	 start_time_service/2, start_timerevent_service/1, stop_timerevent_service/1,
38	 stop_time_service/1]).
39
40%% cosTime API internal
41-export([create_link/3, get_option/3, type_check/2, start_event_handler/1]).
42
43%% Application callbacks
44-export([start/2, init/1, stop/1]).
45
46%%--------------- DEFINES ------------------------------------
47-define(IDL_TIME_MODULES, ['oe_TimeBase',
48			   'oe_CosTime']).
49-define(IDL_TIMEREVENT_MODULES, ['oe_CosTimerEvent']).
50-define(SUPERVISOR_NAME, oe_cosTimeSup).
51-define(SUP_FLAG,        {simple_one_for_one,50,10}).
52-define(SUP_TIMESERVICE_SPEC(T,I),
53        ['CosTime_TimeService',[T, I],
54         [{sup_child, true}, {regname, {global, "oe_cosTimeService"}}]]).
55-define(SUP_TIMEREVENTSERVICE_SPEC(Args),
56        ['CosTimerEvent_TimerEventService', Args,
57         [{sup_child, true}, {regname, {local, 'oe_cosTimerEventService'}}]]).
58-define(SUP_TIMEREVENTHANDLER_SPEC(Name, Args),
59        ['CosTimerEvent_TimerEventHandler',Args,
60         [{sup_child, true}, {regname, {global, Name}}]]).
61-define(SUP_CHILD,
62        {"oe_TimeChild",
63         {cosTime,create_link, []},
64	 transient,100000,worker,
65         []}).
66
67%%------------------------------------------------------------
68%% function : install_*/X
69%% Arguments: - | Time (seconds)
70%% Returns  : ok | EXIT | EXCEPTION
71%% Effect   : Install necessary data in the IFR DB
72%%------------------------------------------------------------
73
74install_time() ->
75    case install_loop(?IDL_TIME_MODULES,[]) of
76	ok ->
77	    ok;
78	{error, Reason} ->
79	    exit(Reason)
80    end.
81
82install_timerevent() ->
83    case install_loop(?IDL_TIMEREVENT_MODULES,[]) of
84	ok ->
85	    ok;
86	{error, Reason} ->
87	    exit(Reason)
88    end.
89
90install_loop([], _) ->
91    ok;
92install_loop([H|T], Accum) ->
93    case catch H:'oe_register'() of
94	{'EXIT',{unregistered,App}} ->
95	    ?write_ErrorMsg("Unable to register '~p'; application ~p not registered.\n"
96			    "Trying to unregister ~p\n", [H,App,Accum]),
97	    uninstall_loop(Accum, {exit, register});
98	{'EXCEPTION',_} ->
99	    ?write_ErrorMsg("Unable to register '~p'; propably already registered.\n"
100			    "You are adviced to confirm this.\n"
101			    "Trying to unregister ~p\n", [H,Accum]),
102	    uninstall_loop(Accum, {exit, register});
103	ok ->
104	    install_loop(T, [H|Accum]);
105	_ ->
106 	    ?write_ErrorMsg("Unable to register '~p'; reason unknown.\n"
107			    "Trying to unregister ~p\n", [H,Accum]),
108	    uninstall_loop(Accum, {exit, register})
109    end.
110
111%%------------------------------------------------------------
112%% function : uninstall_*/X
113%% Arguments: - | Time (seconds)
114%% Returns  : ok | EXIT | EXCEPTION
115%% Effect   : Remove data related to cosTime from the IFR DB
116%%------------------------------------------------------------
117
118uninstall_time() ->
119    case uninstall_loop(lists:reverse(?IDL_TIME_MODULES),ok) of
120	ok ->
121	    ok;
122	{error, Reason} ->
123	    exit(Reason)
124    end.
125
126uninstall_timerevent() ->
127    case uninstall_loop(lists:reverse(?IDL_TIMEREVENT_MODULES),ok) of
128	ok ->
129	    ok;
130	{error, Reason} ->
131	    exit(Reason)
132    end.
133
134uninstall_loop([],ok) ->
135    ok;
136uninstall_loop([],{exit, register}) ->
137    {error, {?MODULE, "oe_register failed"}};
138uninstall_loop([],{exit, unregister}) ->
139    {error, {?MODULE, "oe_unregister failed"}};
140uninstall_loop([],{exit, both}) ->
141    {error, {?MODULE, "oe_register and, for some of those already registered, oe_unregister failed"}};
142uninstall_loop([H|T], Status) ->
143    case catch H:'oe_unregister'() of
144	ok ->
145	    uninstall_loop(T, Status);
146	_ when Status == ok ->
147	    ?write_ErrorMsg("Unable to unregister '~p'; propably already unregistered.\n"
148			    "You are adviced to confirm this.~n",[H]),
149	    uninstall_loop(T, {exit, unregister});
150	_ ->
151 	    ?write_ErrorMsg("Unable to unregister '~p'; propably already unregistered.\n"
152			    "You are adviced to confirm this.~n",[H]),
153	    uninstall_loop(T, {exit, both})
154    end.
155
156%%------------------------------------------------------------
157%% function : start/stop
158%% Arguments:
159%% Returns  :
160%% Effect   : Starts or stops the cosTime application.
161%%------------------------------------------------------------
162
163start() ->
164    application:start(cosTime).
165stop() ->
166    application:stop(cosTime).
167
168%%------------------------------------------------------------
169%% function : start
170%% Arguments: Type - see module application
171%%            Arg  - see module application
172%% Returns  :
173%% Effect   : Module callback for application
174%%------------------------------------------------------------
175
176start(_, _) ->
177    supervisor:start_link({local, ?SUPERVISOR_NAME}, cosTime, app_init).
178
179
180%%------------------------------------------------------------
181%% function : stop
182%% Arguments: Arg - see module application
183%% Returns  :
184%% Effect   : Module callback for application
185%%------------------------------------------------------------
186
187stop(_) ->
188    ok.
189
190%%------------------------------------------------------------
191%% function : start_time_service
192%% Arguments: Tdf - time difference to UTC
193%%            Inaccuracy - ulonglong
194%%            Upper - inaccuracy high
195%% Returns  :
196%% Effect   :
197%%------------------------------------------------------------
198start_time_service(Tdf, Inaccuracy) when is_integer(Tdf) andalso is_integer(Inaccuracy) ->
199    case supervisor:start_child(?SUPERVISOR_NAME,
200				?SUP_TIMESERVICE_SPEC(Tdf, Inaccuracy)) of
201	{ok, Pid, Obj} when is_pid(Pid) ->
202	    Obj;
203	_Other->
204	    corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
205    end;
206start_time_service(_Tdf, _Inaccuracy) ->
207    corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
208
209
210%%------------------------------------------------------------
211%% function : stop_time_service
212%% Arguments: Obj - TimeService objref
213%% Returns  :
214%% Effect   :
215%%------------------------------------------------------------
216stop_time_service(Obj) ->
217    corba:dispose(Obj).
218
219%%------------------------------------------------------------
220%% function : start_timerevent_service
221%% Arguments: Timer - Timer Service Reference
222%% Returns  :
223%% Effect   :
224%%------------------------------------------------------------
225start_timerevent_service(Timer) ->
226    case supervisor:start_child(?SUPERVISOR_NAME,
227				?SUP_TIMEREVENTSERVICE_SPEC([Timer])) of
228	{ok, Pid, Obj} when is_pid(Pid) ->
229	    Obj;
230	_Other->
231	    corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
232    end.
233
234%%-----------------------------------------------------------%
235%% function : stop_timerevent_service
236%% Arguments: Obj - TimerEventService objref
237%% Returns  :
238%% Effect   :
239%%------------------------------------------------------------
240stop_timerevent_service(Obj) ->
241    corba:dispose(Obj).
242
243%%-----------------------------------------------------------%
244%% function : init
245%% Arguments:
246%% Returns  :
247%% Effect   :
248%%------------------------------------------------------------
249
250%% Starting using create_factory/X
251init(own_init) ->
252    {ok,{?SUP_FLAG, [?SUP_CHILD]}};
253%% When starting as an application.
254init(app_init) ->
255    {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
256
257%%-----------------------------------------------------------%
258%% function : create_link
259%% Arguments: Module - which Module to call
260%%            Env/ArgList - ordinary oe_create arguments.
261%% Returns  :
262%% Exception:
263%% Effect   : Necessary since we want the supervisor to be a
264%%            'simple_one_for_one'. Otherwise, using for example,
265%%            'one_for_one', we have to call supervisor:delete_child
266%%            to remove the childs startspecification from the
267%%            supervisors internal state.
268%%------------------------------------------------------------
269create_link(Module, Env, ArgList) ->
270    Module:oe_create_link(Env, ArgList).
271
272%%-----------------------------------------------------------%
273%% function : start_event_handler
274%% Arguments:
275%% Returns  :
276%% Exception:
277%% Effect   :
278%%------------------------------------------------------------
279
280start_event_handler(Args) ->
281    Name = create_name(eventhandler),
282    case supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TIMEREVENTHANDLER_SPEC(Name,Args)) of
283	{ok, Pid, Obj} when is_pid(Pid) ->
284	    Obj;
285	_Other->
286	    corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
287    end.
288
289
290%%-----------------------------------------------------------%
291%% function : get_option
292%% Arguments:
293%% Returns  :
294%% Exception:
295%% Effect   :
296%%------------------------------------------------------------
297
298get_option(Key, OptionList, DefaultList) ->
299    case lists:keysearch(Key, 1, OptionList) of
300        {value,{Key,Value}} ->
301            Value;
302        _ ->
303            case lists:keysearch(Key, 1, DefaultList) of
304                {value,{Key,Value}} ->
305                    Value;
306                _->
307                    {error, "Invalid option"}
308            end
309    end.
310
311%%-----------------------------------------------------------%
312%% function : type_check
313%% Arguments: Obj  - objectrefernce to test.
314%%            Mod  - Module which contains typeID/0.
315%% Returns  : 'ok' or raises exception.
316%% Effect   :
317%%------------------------------------------------------------
318
319type_check(Obj, Mod) ->
320    case catch corba_object:is_a(Obj,Mod:typeID()) of
321        true ->
322            ok;
323        _ ->
324	    corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
325    end.
326
327
328%%-----------------------------------------------------------%
329%% function : create_name/1
330%% Arguments:
331%% Returns  :
332%% Exception:
333%% Effect   :
334%%------------------------------------------------------------
335
336create_name(Type) ->
337    Time = erlang:system_time(),
338    Unique = erlang:unique_integer([positive]),
339    lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
340
341%%--------------- END OF MODULE ------------------------------
342
343
344