aboutsummaryrefslogtreecommitdiffstats
path: root/lib/orber/src/orber_objectkeys.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/orber/src/orber_objectkeys.erl')
-rw-r--r--lib/orber/src/orber_objectkeys.erl571
1 files changed, 0 insertions, 571 deletions
diff --git a/lib/orber/src/orber_objectkeys.erl b/lib/orber/src/orber_objectkeys.erl
deleted file mode 100644
index 12ed1a2f85..0000000000
--- a/lib/orber/src/orber_objectkeys.erl
+++ /dev/null
@@ -1,571 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_objectkeys.erl
-%%
-%% Description:
-%% This file contains the object keyserver in Orber
-%%
-%%-----------------------------------------------------------------
--module(orber_objectkeys).
-
--behaviour(gen_server).
-
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/1, stop/0, stop_all/0, get_pid/1, is_persistent/1,
- register/2, register/3, delete/1, create_schema/1, check/1,
- remove_old_keys/0]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, install/2, handle_call/3, handle_info/2, code_change/3]).
--export([handle_cast/2, dump/0, get_key_from_pid/1, gc/1]).
-
-%%-----------------------------------------------------------------
-%% Mnesia Table definition record
-%%-----------------------------------------------------------------
--record(orber_objkeys, {object_key, pid, persistent=false, timestamp}).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(dirty_query_context, true).
-
-%% This macro returns a read fun suitable for evaluation in a transaction
--define(read_function(Objkey),
- fun() ->
- mnesia:dirty_read(Objkey)
- end).
-
-%% This macro returns a write fun suitable for evaluation in a transaction
--define(write_function(R),
- fun() ->
- mnesia:dirty_write(R)
- end).
-
-%% This macro returns a delete fun suitable for evaluation in a transaction
--define(delete_function(R),
- fun() ->
- mnesia:delete(R)
- end).
-
-%% Use this fun inside a transaction to get a list of all keys.
--define(match_function(),
- fun() ->
- mnesia:match_object({orber_objkeys, '_', '_','_','_'})
- end).
-
--ifdef(dirty_query_context).
--define(query_check(Q_res), Q_res).
--else.
--define(query_check(Q_res), {atomic, Q_res}).
--endif.
-
-
--define(CHECK_EXCEPTION(Res), case Res of
- {'EXCEPTION', E} ->
- corba:raise(E);
- R ->
- R
- end).
-
--define(DEBUG_LEVEL, 6).
-
-
-
-%%-----------------------------------------------------------------
-%% Debugging function
-%%-----------------------------------------------------------------
-dump() ->
- case catch mnesia:dirty_first('orber_objkeys') of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_loop(PreviousKey) ->
- case catch mnesia:dirty_next('orber_objkeys', PreviousKey) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- '$end_of_table' ->
- ok;
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_print(Key) ->
- case catch mnesia:dirty_read({'orber_objkeys', Key}) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- [X] ->
- io:format("object_key: ~p, pid: ~p, persistent: ~p, timestamp: ~p\n",
- [binary_to_term(X#orber_objkeys.object_key),
- X#orber_objkeys.pid,
- X#orber_objkeys.persistent,
- X#orber_objkeys.timestamp]);
- _ ->
- ok
- end.
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start(Opts) ->
- gen_server:start_link({local, orber_objkeyserver}, orber_objectkeys, Opts, []).
-
-stop() ->
- gen_server:call(orber_objkeyserver, stop, infinity).
-
-remove_old_keys() ->
- %% This function may ONLY be used when restarting a crashed node.
- %% We must remove all objects started with {global, "name"} otherwise
- %% we cannot restart the node using the same name.
- Fun = fun() ->
- Node = node(),
- mnesia:write_lock_table(orber_objkeys),
- Objects = mnesia:match_object(orber_objkeys,
- mnesia:table_info(orber_objkeys,
- wild_pattern),
- read),
- lists:foreach(fun(Obj) ->
- case node(Obj#orber_objkeys.pid) of
- Node ->
- mnesia:delete({orber_objkeys,
- Obj#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- Objects),
- ok
- end,
- write_result(mnesia:transaction(Fun)).
-
-stop_and_remove_local(Reason) ->
- %% This function may ONLY be used when this server terminates with reason
- %% normal or shutdown.
- Fun = fun() ->
- Node = node(),
- mnesia:write_lock_table(orber_objkeys),
- Objects = mnesia:match_object(orber_objkeys,
- mnesia:table_info(orber_objkeys,
- wild_pattern),
- read),
- lists:foreach(fun(Obj) ->
- case node(Obj#orber_objkeys.pid) of
- Node ->
- exit(Obj#orber_objkeys.pid, Reason),
- mnesia:delete({orber_objkeys,
- Obj#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- Objects),
- ok
- end,
- write_result(mnesia:transaction(Fun)).
-
-stop_all() ->
- Fun = ?match_function(),
- case mnesia:transaction(Fun) of
- {atomic, Objects} ->
- lists:foreach(fun(Obj) ->
- gen_server:call(Obj#orber_objkeys.pid,
- stop, infinity)
- end,
- Objects);
- R ->
- R
- end.
-
-get_pid(Objkey) ->
- case catch ets:lookup_element(orber_objkeys, Objkey, 3) of
- Pid when is_pid(Pid) ->
- Pid;
- dead ->
- {error, "unable to contact object"};
- _ ->
- %% This call is necessary if a persistent object have died
- %% and the objectkey server is currently updating the Pid
- %% to equal 'dead'. Without this case 'OBJECT_NOT_EXIST'
- %% would be raised which is uncorrect if the object is
- %% persistent.
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {get_pid, Objkey},
- infinity))
- end.
-
-is_persistent(Pid) when is_pid(Pid) ->
- case catch get_key_from_pid(Pid) of
- {'EXCEPTION', _} ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- Key ->
- is_persistent(Key)
- end;
-is_persistent(Objkey) ->
- case catch ets:lookup_element(orber_objkeys, Objkey, 4) of
- {'EXIT', _R} ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- Boolean ->
- Boolean
- end.
-
-
-gc(Sec) when is_integer(Sec) ->
- Fun = fun() ->
- mnesia:write_lock_table(orber_objkeys),
- Objects = mnesia:match_object({orber_objkeys, '_', dead, true,'_'}),
- lists:foreach(fun(Obj) ->
- case timetest(Sec, Obj#orber_objkeys.timestamp) of
- true ->
- mnesia:delete({orber_objkeys,
- Obj#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- Objects),
- ok
- end,
- write_result(mnesia:transaction(Fun)).
-
-register(Objkey, Pid) ->
- 'register'(Objkey, Pid, false).
-
-register(Objkey, Pid, Type) when is_pid(Pid) ->
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {register, Objkey, Pid, Type},
- infinity));
-register(Objkey, Pid, Type) ->
- orber:dbg("[~p] orber_objectkeys:register(~p, ~p); Not a Pid ~p",
- [?LINE, Objkey, Type, Pid], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-delete(Objkey) ->
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {delete, Objkey}, infinity)).
-
-check(Objkey) ->
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {check, Objkey}, infinity)).
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-init(_Env) ->
- case mnesia:wait_for_tables(['orber_objkeys'], infinity) of
- ok ->
- process_flag(trap_exit, true),
- start_gc_timer(orber:objectkeys_gc_time());
- StopReason ->
- {stop, StopReason}
- end.
-
-terminate(shutdown, _State) ->
- stop_and_remove_local(shutdown),
- ok;
-terminate(normal, _State) ->
- stop_and_remove_local(normal),
- ok;
-terminate(_Reason, _State) ->
- ok.
-
-start_gc_timer(infinity) ->
- {ok, []};
-start_gc_timer(Time) ->
- timer:start(),
- case timer:send_after(timer:seconds(Time),
- orber_objkeyserver, {oe_gc, Time}) of
- {ok, _} ->
- {ok, []};
- StopReason ->
- {stop, StopReason}
- end.
-
-install(Timeout, Options) ->
- %% check if there already exists a database. If not, create one.
- %% DB_initialized = perhaps_create_schema(Nodelist),
- %% check if mnesia is running. If not, start mnesia.
- perhaps_start_mnesia(),
-
- %% Do we have a complete set of IFR tables? If not, create them.
- AllTabs = mnesia:system_info(tables),
-
- DB_Result = case lists:member(orber_objkeys, AllTabs) of
- true ->
- case lists:member({local_content, true},
- Options) of
- true->
- mnesia:add_table_copy(orber_objkeys,
- node(),
- ram_copies);
- _ ->
- mnesia:create_table(orber_objkeys,
- [{attributes,
- record_info(fields,
- orber_objkeys)}
- |Options])
- end;
- _ ->
- mnesia:create_table(orber_objkeys,
- [{attributes,
- record_info(fields,
- orber_objkeys)}
- |Options])
- end,
-
- Wait = mnesia:wait_for_tables([orber_objkeys], Timeout),
- %% Check if any error has occurred yet. If there are errors, return them.
- if
- DB_Result == {atomic, ok},
- Wait == ok ->
- ok;
- true ->
- {error, {DB_Result, Wait}}
- end.
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%
-%% Comment:
-%% In objectkey gen_server all exceptions are tupples and corba:raise
-%% may not be used. It is too time consuming to add catches in every
-%% function before returning. On the client side there is a case which
-%% maps every tupple on the format {'exception', E} to corba:raise(E).
-%%-----------------------------------------------------------------
-handle_call(stop, _From, State) ->
- {stop, normal, [], State};
-handle_call({get, Objkey}, _From, State) ->
- R = query_result(mnesia:dirty_read({orber_objkeys, Objkey})),
- {reply, R, State};
-
-handle_call({register, Objkey, Pid, Type}, _From, State) ->
- _WF = fun() ->
- case mnesia:wread({orber_objkeys, Objkey}) of
- [] ->
- %% No key exists. Ok to register.
- mnesia:write(#orber_objkeys{object_key=Objkey, pid=Pid,
- persistent=Type,
- timestamp=erlang:monotonic_time(seconds)});
- [X] when X#orber_objkeys.persistent==true,
- X#orber_objkeys.pid == dead ->
- %% A persistent object is being restarted. Update Pid & time.
- mnesia:write(X#orber_objkeys{pid=Pid, timestamp=erlang:monotonic_time(seconds)});
- [X] when is_pid(X#orber_objkeys.pid) ->
- %% Object exists, i.e., trying to create an object with
- %% the same name.
- orber:dbg("[~p] orber_objectkeys:register(~p, ~p); Object already exists.",
- [?LINE, Objkey, Type], ?DEBUG_LEVEL),
- {'EXCEPTION', #'BAD_PARAM'{completion_status=?COMPLETED_NO}};
- Why ->
- %% Something else occured.
- orber:dbg("[~p] orber_objectkeys:register(~p, ~p); error reading from DB(~p)",
- [?LINE, Objkey, Type, Why], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end
- end,
- R = write_result(mnesia:transaction(_WF)),
- if
- R == ok andalso is_pid(Pid) ->
- link(Pid);
- true ->
- true
- end,
- {reply, R, State};
-
-handle_call({delete, Objkey}, _From, State) ->
- ?query_check(Qres) = mnesia:dirty_read({orber_objkeys, Objkey}),
- case Qres of
- [] ->
- true;
- [X] when is_pid(X#orber_objkeys.pid) ->
- unlink(X#orber_objkeys.pid);
- _ ->
- true
- end,
- _F = ?delete_function({orber_objkeys, Objkey}),
- R = write_result(mnesia:transaction(_F)),
- {reply, R, State};
-
-handle_call({get_pid, Objkey}, _From, State) ->
- _F = fun() ->
- mnesia:read({orber_objkeys, Objkey})
- end,
- case mnesia:transaction(_F) of
- {atomic, [X]} when is_pid(X#orber_objkeys.pid) ->
- {reply, X#orber_objkeys.pid, State};
- {atomic, [X]} when X#orber_objkeys.pid == dead ->
- {reply,
- {'EXCEPTION', #'TRANSIENT'{completion_status=?COMPLETED_NO}},
- State};
- _Res ->
- {reply,
- {'EXCEPTION', #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}},
- State}
- end;
-handle_call({check, {_, 'key', Objkey, _, _, _}}, _From, State) ->
- ?query_check(Qres) = mnesia:dirty_read({orber_objkeys, Objkey}),
- case Qres of
- [_X] ->
- {reply, 'object_here', State};
- _ ->
- {reply, 'unknown_object', State}
- end;
-handle_call({check, {_, 'registered', Objkey, _, _, _}}, _From, State) ->
- case whereis(Objkey) of
- undefined ->
- case catch ets:lookup_element(orber_objkeys, Objkey, 4) of
- true ->
- {reply, 'object_here', State};
- _->
- {reply, 'unknown_object', State}
- end;
- _ ->
- {reply, 'object_here', State}
- end;
-handle_call({check, {_, 'pseudo', Module, _, _, _}}, _From, State) ->
- case code:is_loaded(Module) of
- false ->
- {reply, 'unknown_object', State};
- _ ->
- {reply, 'object_here', State}
- end;
-
-handle_call({check, "INIT"}, _From, State) ->
- {reply, 'object_here', State};
-handle_call({check, _}, _From, State) ->
- {reply, 'unknown_object', State}.
-
-
-handle_info({'EXIT', Pid, Reason}, State) when is_pid(Pid) ->
- _WF = fun() ->
- case mnesia:match_object({orber_objkeys, '_', Pid,'_','_'}) of
- [] ->
- ok;
- [X] when X#orber_objkeys.persistent==false ->
- mnesia:delete({orber_objkeys, X#orber_objkeys.object_key});
- [X] when is_pid(X#orber_objkeys.pid) andalso
- X#orber_objkeys.persistent==true andalso
- Reason /= normal andalso
- Reason /= shutdown ->
- mnesia:write(X#orber_objkeys{pid=dead,
- timestamp=erlang:monotonic_time(seconds)});
- [X] when X#orber_objkeys.persistent==true ->
- mnesia:delete({orber_objkeys, X#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- case write_result(mnesia:transaction(_WF)) of
- ok ->
- unlink(Pid);
- _->
- true
- end,
- {noreply, State};
-
-handle_info({oe_gc, Secs}, State) ->
- catch gc(Secs),
- {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Internal Functions
-%%-----------------------------------------------------------------
-
-timetest(S, TimeStamp) ->
- TimeStamp+S < erlang:monotonic_time(seconds).
-
-get_key_from_pid(Pid) ->
- case mnesia:dirty_match_object({orber_objkeys, '_', Pid,'_','_'}) of
- [Keys] ->
- Keys#orber_objkeys.object_key;
- _ ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO})
- end.
-
-%remove_keys([], _) ->
-% ok;
-%remove_keys([H|T], R) when H#orber_objkeys.persistent==false ->
-% _F = ?delete_function({orber_objkeys, H#orber_objkeys.object_key}),
-% write_result(mnesia:transaction(_F)),
-% remove_keys(T, R).
-
-%%-----------------------------------------------------------------
-%% Check a read transaction
-query_result(?query_check(Qres)) ->
- case Qres of
- [Hres] ->
- Hres#orber_objkeys.pid;
- [] ->
- {'EXCEPTION', #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}};
- Other ->
- orber:dbg("[~p] orber_objectkeys:query_result(); DB lookup failed(~p)",
- [?LINE, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end.
-
-%%-----------------------------------------------------------------
-%% Check a write transaction
-write_result({atomic,ok}) -> ok;
-write_result(Foo) ->
- orber:dbg("[~p] orber_objectkeys:query_result(); DB write failed(~p)",
- [?LINE, Foo], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}.
-
-
-create_schema(Nodes) ->
- case mnesia:system_info(use_dir) of
- false ->
- mnesia:create_schema(Nodes);
- _ ->
- ok
- end.
-
-perhaps_start_mnesia() ->
- case mnesia:system_info(is_running) of
- no ->
- mnesia:start();
- _ ->
- ok
- end.
-
-
-%%------------------------------------------------------------
-%% Standard gen_server cast handle
-%%
-handle_cast(_, State) ->
- {noreply, State}.
-
-