1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1998-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(global_search). 21 22%% Search for globally registered names in the global groups. 23%% This is a help module to the global_group.erl 24 25 26%% External exports 27-export([start/2]). 28-export([init_send/1]). 29-export([init_whereis/1]). 30-export([init_names/1]). 31 32 33%% ONLY for test purpose 34-export([send_test/1]). 35-export([whereis_test/1]). 36-export([names_test/1]). 37 38 39 40 41%%%==================================================================================== 42%%% The search is done in a process separate from the global_group process 43%%%==================================================================================== 44start(Flag, Arg) -> 45 case Flag of 46 send -> 47 spawn_link(?MODULE, init_send, [Arg]); 48 whereis -> 49 spawn_link(?MODULE, init_whereis, [Arg]); 50 names -> 51 spawn_link(?MODULE, init_names, [Arg]); 52 %% ONLY for test suites, tests what happens when this process exits. 53 send_test -> 54 spawn_link(?MODULE, send_test, [Arg]); 55 whereis_test -> 56 spawn_link(?MODULE, whereis_test, [Arg]); 57 names_test -> 58 spawn_link(?MODULE, names_test, [Arg]) 59 end. 60 61 62%%%==================================================================================== 63%%%==================================================================================== 64%%%==================================================================================== 65%%% Search after a registered global Name anywhere (any), in a specified group or 66%%% in a specified node. 67%%% Return the result to the global_group process in own node and wait for 68%%% this process to be killed. 69%%%==================================================================================== 70%%%==================================================================================== 71%%%==================================================================================== 72 73-spec init_send(_) -> no_return(). 74init_send({any, NodesList, Name, Msg, From}) -> 75 case whereis_any_loop(NodesList, Name) of 76 undefined -> 77 Res = {badarg,{Name, Msg}}, 78 gen_server:cast(global_group, {send_res, Res, Name, Msg, self(), From}); 79 Pid -> 80 gen_server:cast(global_group, {send_res, Pid, Name, Msg, self(), From}) 81 end, 82 end_loop(); 83init_send({group, Nodes, Name, Msg, From}) -> 84 case whereis_group_loop(Nodes, Name) of 85 group_down -> 86 Res = {badarg,{Name, Msg}}, 87 gen_server:cast(global_group, {send_res, Res, Name, Msg, self(), From}); 88 undefined -> 89 Res = {badarg,{Name, Msg}}, 90 gen_server:cast(global_group, {send_res, Res, Name, Msg, self(), From}); 91 Pid -> 92 gen_server:cast(global_group, {send_res, Pid, Name, Msg, self(), From}) 93 end, 94 end_loop(); 95init_send({node, Node, Name, Msg, From}) -> 96 case whereis_check_node(Node, Name) of 97 node_down -> 98 Res = {badarg,{Name, Msg}}, 99 gen_server:cast(global_group, {send_res, Res, Name, Msg, self(), From}); 100 undefined -> 101 Res = {badarg,{Name, Msg}}, 102 gen_server:cast(global_group, {send_res, Res, Name, Msg, self(), From}); 103 Pid -> 104 gen_server:cast(global_group, {send_res, Pid, Name, Msg, self(), From}) 105 end, 106 end_loop(). 107 108 109%%%==================================================================================== 110%%%==================================================================================== 111%%%==================================================================================== 112%%% Search after a registered global Name anywhere (any), in a specified group or 113%%% in a specified node. 114%%% Return the result to the global_group process in own node and wait for 115%%% this process to be killed. 116%%%==================================================================================== 117%%%==================================================================================== 118%%%==================================================================================== 119 120-spec init_whereis(_) -> no_return(). 121init_whereis({any, NodesList, Name, From}) -> 122 R = whereis_any_loop(NodesList, Name), 123 gen_server:cast(global_group, {find_name_res, R, self(), From}), 124 end_loop(); 125init_whereis({group, Nodes, Name, From}) -> 126 case whereis_group_loop(Nodes, Name) of 127 group_down -> 128 gen_server:cast(global_group, {find_name_res, undefined, self(), From}); 129 R -> 130 gen_server:cast(global_group, {find_name_res, R, self(), From}) 131 end, 132 end_loop(); 133init_whereis({node, Node, Name, From}) -> 134 case whereis_check_node(Node, Name) of 135 node_down -> 136 gen_server:cast(global_group, {find_name_res, undefined, self(), From}); 137 R -> 138 gen_server:cast(global_group, {find_name_res, R, self(), From}) 139 end, 140 end_loop(). 141 142 143%%%==================================================================================== 144%%%==================================================================================== 145%%%==================================================================================== 146%%% Get the registered names, in a specified group or in a specified node. 147%%% Return the result to the global_group process in own node and wait for 148%%% this process to be killed. 149%%%==================================================================================== 150%%%==================================================================================== 151%%%==================================================================================== 152-spec init_names(_) -> no_return(). 153init_names({group, Nodes, From}) -> 154 case names_group_loop(Nodes) of 155 group_down -> 156 gen_server:cast(global_group, {registered_names_res, [], self(), From}); 157 R -> 158 gen_server:cast(global_group, {registered_names_res, R, self(), From}) 159 end, 160 end_loop(); 161init_names({node, Node, From}) -> 162 case names_check_node(Node) of 163 node_down -> 164 gen_server:cast(global_group, {registered_names_res, [], self(), From}); 165 R -> 166 gen_server:cast(global_group, {registered_names_res, R, self(), From}) 167 end, 168 end_loop(). 169 170%%%==================================================================================== 171%%% Wait for the kill message. 172%%%==================================================================================== 173 174-spec end_loop() -> no_return(). 175 176end_loop() -> 177 receive 178 kill -> 179 exit(normal) 180 end. 181 182%%%==================================================================================== 183%%% Search for the globally registered name in the whole known world. 184%%%==================================================================================== 185whereis_any_loop([], _Name) -> 186 undefined; 187whereis_any_loop([{_Group_name, Nodes}|T], Name) -> 188 case whereis_group_loop(Nodes, Name) of 189 group_down -> 190 whereis_any_loop(T, Name); 191 undefined -> 192 whereis_any_loop(T, Name); 193 R -> 194 R 195 end. 196 197%%%==================================================================================== 198%%% Search for the globally registered name in a specified global group. 199%%%==================================================================================== 200whereis_group_loop([], _Name) -> 201 group_down; 202whereis_group_loop([Node|T], Name) -> 203 case whereis_check_node(Node, Name) of 204 node_down -> 205 whereis_group_loop(T, Name); 206 R -> 207 R 208 end. 209%%%==================================================================================== 210%%% Search for the globally registered name on a specified node. 211%%%==================================================================================== 212whereis_check_node(Node, Name) -> 213 case net_adm:ping(Node) of 214 pang -> 215 node_down; 216 pong -> 217 monitor_node(Node, true), 218 gen_server:cast({global_group, Node},{find_name, self(), Name}), 219 receive 220 {nodedown, Node} -> 221 node_down; 222 {find_name_res, Result} -> 223 monitor_node(Node, false), 224 Result 225 end 226 end. 227 228 229 230 231%%%==================================================================================== 232%%% Search for all globally registered name in a specified global group. 233%%%==================================================================================== 234names_group_loop([]) -> 235 group_down; 236names_group_loop([Node|T]) -> 237 case names_check_node(Node) of 238 node_down -> 239 names_group_loop(T); 240 R -> 241 R 242 end. 243%%%==================================================================================== 244%%% Search for all globally registered name on a specified node. 245%%%==================================================================================== 246names_check_node(Node) -> 247 case net_adm:ping(Node) of 248 pang -> 249 node_down; 250 pong -> 251 monitor_node(Node, true), 252 gen_server:cast({global_group, Node},{registered_names, self()}), 253 receive 254 {nodedown, Node} -> 255 node_down; 256 {registered_names_res, Result} -> 257 monitor_node(Node, false), 258 Result 259 end 260 end. 261 262 263 264 265 266 267%%%==================================================================================== 268%%% Test what happens when this process exits. 269%%%==================================================================================== 270send_test(_Args) -> 271 timer:sleep(5000), 272 exit(testing_exit). 273 274whereis_test(_Args) -> 275 timer:sleep(5000), 276 exit(testing_exit). 277 278names_test(_Args) -> 279 timer:sleep(5000), 280 exit(testing_exit). 281 282 283 284