%%--------------------------------------------------------------------
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1997-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: orber_initial_references.erl
%%
%% Description:
%% This file contains the CORBA::InitialReferences interface
%%
%%-----------------------------------------------------------------
-module(orber_initial_references).
-behaviour(gen_server).
-include_lib("orber/include/corba.hrl").
%%-----------------------------------------------------------------
%% External exports
%%-----------------------------------------------------------------
-export([start/1, shutdown/1, init/1,
terminate/2, handle_call/3, code_change/3,
get/2, list/1, add/3, remove/2,
get/1, list/0, add/2, remove/1,
typeID/0, install/2, oe_is_a/1, oe_tc/1, oe_get_interface/0]).
%%-----------------------------------------------------------------
%% Internal exports
%%-----------------------------------------------------------------
-export([handle_cast/2, handle_info/2]).
%%-----------------------------------------------------------------
%% Mnesia Table definition record
%%-----------------------------------------------------------------
-record(orber_references, {key, objref, type}).
-define(DEBUG_LEVEL, 6).
%%-----------------------------------------------------------------
%% External interface functions
%%-----------------------------------------------------------------
start(Env) ->
gen_server:start_link({local, 'orber_init'}, ?MODULE, Env, []).
shutdown(EO_this) ->
gen_server:call(EO_this, stop).
install(Timeout, Options) ->
AllTabs = mnesia:system_info(tables),
DB_Result = case lists:member(orber_references, AllTabs) of
true ->
case lists:member({local_content, true},
Options) of
true->
mnesia:add_table_copy(orber_references,
node(),
ram_copies);
_ ->
mnesia:create_table(orber_references,
[{attributes,
record_info(fields,
orber_references)}
|Options])
end;
_ ->
mnesia:create_table(orber_references,
[{attributes,
record_info(fields,
orber_references)}
|Options])
end,
Wait = mnesia:wait_for_tables([orber_references], Timeout),
%% Check if any error has occured yet. If there are errors, return them.
if
DB_Result == {atomic, ok},
Wait == ok ->
ok;
true ->
{error, {DB_Result, Wait}}
end.
%%-----------------------------------------------------------------
%% InitialReferences Interface
%%-----------------------------------------------------------------
'get'(Id) ->
case read(Id) of
{'EXCEPTION', E} ->
corba:raise(E);
Result ->
Result
end.
list() ->
case list_keys() of
{'EXCEPTION', E} ->
corba:raise(E);
Result ->
Result
end.
add(Id, ObjRef) ->
case write(Id, ObjRef, external) of
{'EXCEPTION', E} ->
corba:raise(E);
Result ->
Result
end.
remove(Id) ->
case delete(Id) of
{'EXCEPTION', E} ->
corba:raise(E);
Result ->
Result
end.
'get'(EO_this, Id) ->
corba:call(EO_this, 'get', [Id], ?MODULE).
list(EO_this) ->
corba:call(EO_this, 'list', [], ?MODULE).
add(EO_this, Id, ObjRef) ->
corba:call(EO_this, 'add', [Id, ObjRef], ?MODULE).
remove(EO_this, Id) ->
corba:call(EO_this, 'remove', [Id], ?MODULE).
typeID() ->
"IDL:Orber/InitialReferences:1.0".
oe_is_a("IDL:Orber/InitialReferences:1.0") ->
true;
oe_is_a(_) ->
false.
%%-----------------------------------------------------------------
%% Internal interface functions
%%-----------------------------------------------------------------
init([]) ->
case mnesia:wait_for_tables(['orber_references'], infinity) of
ok ->
NSObjKey = 'CosNaming_NamingContextExt':oe_create([], [{pseudo, true},
{no_security, orber:partial_security()}]),
rewrite("NameService", NSObjKey),
ErlIfr = 'OrberApp_IFR':oe_create([], [{pseudo, true}]),
rewrite("OrberIFR", ErlIfr),
{ok, []};
StopReason ->
{stop, StopReason}
end.
terminate(_Reason, _State) ->
ok.
%%-----------------------------------------------------------------
%% Handle incomming calls
handle_call({_EO_this, _OE_Context, 'get', [Id]}, _From, State) ->
{'reply', read(Id), State};
handle_call({_EO_this, _OE_Context, 'list', []}, _From, State) ->
{'reply', list_keys(), State};
handle_call({_EO_this, _OE_Context, 'add', [Id, ObjectRef]}, _From, State) ->
{'reply', write(Id, ObjectRef, external), State};
handle_call({_EO_this, _OE_Context, 'remove', [Id]}, _From, State) ->
{'reply', delete(Id), State};
handle_call('stop', _From, State) ->
{'stop', normal, 'ok', State};
handle_call(_Req, _From,State) ->
{'reply', {'ok', 'nil', 'nil'}, State}.
oe_tc(get) ->
{{'tk_objref', 12, "object"}, [{'tk_string', 0}], []};
oe_tc(list) ->
{{'tk_sequence',{'tk_string', 0}, 0}, [], []};
oe_tc(add) ->
{'tk_boolean', [{'tk_string', 0}, {'tk_objref', 12, "object"}], []};
oe_tc(remove) ->
{'tk_boolean', [{'tk_string', 0}], []};
oe_tc(_) ->
undefined.
oe_get_interface() ->
[{"get", oe_tc(get)},
{"list", oe_tc(list)},
{"add", oe_tc(add)}].
%%-----------------------------------------------------------------
%% Standard gen_server cast handle
%%-----------------------------------------------------------------
handle_cast(_, State) ->
{noreply, State}.
%%-----------------------------------------------------------------
%% Standard gen_server handles
%%-----------------------------------------------------------------
handle_info(_, State) ->
{noreply, State}.
%%-----------------------------------------------------------------
%% Func: code_change/3
%%-----------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
read(Key) ->
case mnesia:dirty_read({orber_references, Key}) of
[] ->
corba:create_nil_objref();
[#orber_references{objref = ObjRef}] ->
ObjRef;
What ->
orber:dbg("[~p] orber_initial_references:lookup(~p);~n"
"Failed to read from DB: ~p",
[?LINE, Key, What], ?DEBUG_LEVEL),
{'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
end.
write(Key, ObjRef, Type) ->
_WF = fun() ->
case mnesia:wread({orber_references, Key}) of
[] ->
%% No key exists. Ok to register.
mnesia:write(#orber_references{key=Key, objref = ObjRef,
type=Type});
[X] ->
orber:dbg("[~p] orber_initial_references:write(~p);~n"
"Already bound to: ~p",
[?LINE, Key, X], ?DEBUG_LEVEL),
false;
Why ->
%% Something else occured.
orber:dbg("[~p] orber_initial_references:write(~p);~n"
"Error reading from DB (~p)", [?LINE, Key, Why], ?DEBUG_LEVEL),
mnesia:abort({'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}})
end
end,
case mnesia:transaction(_WF) of
{atomic, ok} ->
true;
{atomic, Result} ->
Result;
{aborted, Reason} ->
Reason
end.
rewrite(Key, ObjRef) ->
rewrite(Key, ObjRef, internal).
rewrite(Key, ObjRef, Type) ->
_WF = fun() ->
mnesia:write(#orber_references{key=Key, objref = ObjRef, type=Type})
end,
case mnesia:transaction(_WF) of
{atomic, ok} ->
true;
{aborted, Reason} ->
orber:dbg("[~p] orber_initial_references:rewrite(~p);~n"
"Error over writing in DB (~p)",
[?LINE, Key, Reason], ?DEBUG_LEVEL),
corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
end.
delete(Key) ->
_DF = fun() ->
case mnesia:read({orber_references, Key}) of
[] ->
%% No key exists.
orber:dbg("[~p] orber_initial_references:delete(~p);~n"
"Does not exist.", [?LINE, Key], ?DEBUG_LEVEL),
false;
[_X] ->
mnesia:delete({orber_references, Key});
Why ->
%% Something else occured.
orber:dbg("[~p] orber_initial_references:delete(~p);~n"
"Error reading from DB (~p)",
[?LINE, Key, Why], ?DEBUG_LEVEL),
mnesia:abort({'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}})
end
end,
case mnesia:transaction(_DF) of
{atomic, ok} ->
true;
{atomic, Result} ->
Result;
{aborted, Reason} ->
Reason
end.
list_keys() ->
_LF = fun() -> mnesia:all_keys(orber_references) end,
case mnesia:transaction(_LF) of
{atomic, Result} ->
%% We do not want OrberIFR to exported, remove it.
lists:delete("OrberIFR", Result);
{aborted, Reason} ->
orber:dbg("[~p] orber_initial_references:list_keys();~n"
"Error reading from DB (~p)", [?LINE, Reason], ?DEBUG_LEVEL),
{'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
end.