gproc.erl 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681
  1. %% ``The contents of this file are subject to the Erlang Public License,
  2. %% Version 1.1, (the "License"); you may not use this file except in
  3. %% compliance with the License. You should have received a copy of the
  4. %% Erlang Public License along with this software. If not, it can be
  5. %% retrieved via the world wide web at http://www.erlang.org/.
  6. %%
  7. %% Software distributed under the License is distributed on an "AS IS"
  8. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. %% the License for the specific language governing rights and limitations
  10. %% under the License.
  11. %%
  12. %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. %% AB. All Rights Reserved.''
  15. %%
  16. %% @author Ulf Wiger <ulf.wiger@erlang-consulting.com>
  17. %%
  18. %% @doc Extended process registry
  19. %% <p>This module implements an extended process registry</p>
  20. %% <p>For a detailed description, see
  21. %% <a href="erlang07-wiger.pdf">erlang07-wiger.pdf</a>.</p>
  22. %%
  23. %% Type and scope for registration and lookup:
  24. %%
  25. %% @type type() = n | p | c | a. n = name; p = property; c = counter;
  26. %% a = aggregate_counter
  27. %% @type scope() = l | g. l = local registration; g = global registration
  28. %%
  29. %% @type reg_id() = {type(), scope(), any()}.
  30. %% @type unique_id() = {n | a, scope(), any()}.
  31. %%
  32. %% Type and scope for select(), qlc() and stepping:
  33. %%
  34. %% @type sel_scope() = scope | all | global | local.
  35. %% @type sel_type() = type() | names | props | counters | aggr_counters.
  36. %% @type context() = {scope(), type()} | type(). {'all','all'} is the default
  37. %%
  38. %% @type headpat() = {keypat(),pidpat(),ValPat}.
  39. %% @type keypat() = {sel_type() | sel_var(),
  40. %% l | g | sel_var(),
  41. %% any()}.
  42. %% @type pidpat() = pid() | sel_var().
  43. %% sel_var() = DollarVar | '_'.
  44. %% @type sel_pattern() = [{headpat(), Guards, Prod}].
  45. %% @type key() = {type(), scope(), any()}
  46. %% @end
  47. -module(gproc).
  48. -behaviour(gen_server).
  49. -export([start_link/0,
  50. reg/1, reg/2, unreg/1,
  51. mreg/3,
  52. munreg/3,
  53. set_value/2,
  54. get_value/1,
  55. where/1,
  56. await/1, await/2,
  57. nb_wait/1,
  58. cancel_wait/2,
  59. lookup_pid/1,
  60. lookup_pids/1,
  61. lookup_value/1,
  62. lookup_values/1,
  63. update_counter/2,
  64. give_away/2,
  65. send/2,
  66. info/1, info/2,
  67. select/1, select/2, select/3,
  68. first/1,
  69. next/2,
  70. prev/2,
  71. last/1,
  72. table/1, table/2]).
  73. %% Environment handling
  74. -export([get_env/3, get_env/4,
  75. get_set_env/3, get_set_env/4,
  76. set_env/5]).
  77. %% Convenience functions
  78. -export([add_local_name/1,
  79. add_global_name/1,
  80. add_local_property/2,
  81. add_global_property/2,
  82. add_local_counter/2,
  83. add_global_counter/2,
  84. add_local_aggr_counter/1,
  85. add_global_aggr_counter/1,
  86. lookup_local_name/1,
  87. lookup_global_name/1,
  88. lookup_local_properties/1,
  89. lookup_global_properties/1,
  90. lookup_local_counters/1,
  91. lookup_global_counters/1,
  92. lookup_local_aggr_counter/1,
  93. lookup_global_aggr_counter/1]).
  94. %% Callbacks for behaviour support
  95. -export([whereis_name/1,
  96. unregister_name/1]).
  97. -export([default/1]).
  98. %%% internal exports
  99. -export([init/1,
  100. handle_cast/2,
  101. handle_call/3,
  102. handle_info/2,
  103. code_change/3,
  104. terminate/2]).
  105. %% this shouldn't be necessary
  106. -export([audit_process/1]).
  107. -include("gproc.hrl").
  108. -include_lib("eunit/include/eunit.hrl").
  109. -define(SERVER, ?MODULE).
  110. %%-define(l, l(?LINE)). % when activated, calls a traceable empty function
  111. -define(l, ignore).
  112. -define(CHK_DIST,
  113. case whereis(gproc_dist) of
  114. undefined ->
  115. erlang:error(local_only);
  116. _ ->
  117. ok
  118. end).
  119. -record(state, {}).
  120. %% @spec () -> {ok, pid()}
  121. %%
  122. %% @doc Starts the gproc server.
  123. %%
  124. %% This function is intended to be called from gproc_sup, as part of
  125. %% starting the gproc application.
  126. %% @end
  127. start_link() ->
  128. _ = create_tabs(),
  129. gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
  130. %% spec(Name::any()) -> true
  131. %%
  132. %% @doc Registers a local (unique) name. @equiv reg({n,l,Name})
  133. %% @end
  134. %%
  135. add_local_name(Name) -> reg({n,l,Name}, undefined).
  136. %% spec(Name::any()) -> true
  137. %%
  138. %% @doc Registers a global (unique) name. @equiv reg({n,g,Name})
  139. %% @end
  140. %%
  141. add_global_name(Name) -> reg({n,g,Name}, undefined).
  142. %% spec(Name::any(), Value::any()) -> true
  143. %%
  144. %% @doc Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
  145. %% @end
  146. %%
  147. add_local_property(Name , Value) -> reg({p,l,Name}, Value).
  148. %% spec(Name::any(), Value::any()) -> true
  149. %%
  150. %% @doc Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
  151. %% @end
  152. %%
  153. add_global_property(Name, Value) -> reg({p,g,Name}, Value).
  154. %% spec(Name::any(), Initial::integer()) -> true
  155. %%
  156. %% @doc Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
  157. %% @end
  158. %%
  159. add_local_counter(Name, Initial) when is_integer(Initial) ->
  160. reg({c,l,Name}, Initial).
  161. %% spec(Name::any(), Initial::integer()) -> true
  162. %%
  163. %% @doc Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
  164. %% @end
  165. %%
  166. add_global_counter(Name, Initial) when is_integer(Initial) ->
  167. reg({c,g,Name}, Initial).
  168. %% spec(Name::any()) -> true
  169. %%
  170. %% @doc Registers a local (unique) aggregated counter.
  171. %% @equiv reg({a,l,Name})
  172. %% @end
  173. %%
  174. add_local_aggr_counter(Name) -> reg({a,l,Name}).
  175. %% spec(Name::any()) -> true
  176. %%
  177. %% @doc Registers a global (unique) aggregated counter.
  178. %% @equiv reg({a,g,Name})
  179. %% @end
  180. %%
  181. add_global_aggr_counter(Name) -> reg({a,g,Name}).
  182. %% @spec (Name::any()) -> pid()
  183. %%
  184. %% @doc Lookup a local unique name. Fails if there is no such name.
  185. %% @equiv where({n,l,Name})
  186. %% @end
  187. %%
  188. lookup_local_name(Name) -> where({n,l,Name}).
  189. %% @spec (Name::any()) -> pid()
  190. %%
  191. %% @doc Lookup a global unique name. Fails if there is no such name.
  192. %% @equiv where({n,g,Name})
  193. %% @end
  194. %%
  195. lookup_global_name(Name) -> where({n,g,Name}).
  196. %% @spec (Name::any()) -> integer()
  197. %%
  198. %% @doc Lookup a local (unique) aggregated counter and returns its value.
  199. %% Fails if there is no such object.
  200. %% @equiv where({a,l,Name})
  201. %% @end
  202. %%
  203. lookup_local_aggr_counter(Name) -> lookup_value({a,l,Name}).
  204. %% @spec (Name::any()) -> integer()
  205. %%
  206. %% @doc Lookup a global (unique) aggregated counter and returns its value.
  207. %% Fails if there is no such object.
  208. %% @equiv where({a,g,Name})
  209. %% @end
  210. %%
  211. lookup_global_aggr_counter(Name) -> lookup_value({a,g,Name}).
  212. %% @spec (Property::any()) -> [{pid(), Value}]
  213. %%
  214. %% @doc Look up all local (non-unique) instances of a given Property.
  215. %% Returns a list of {Pid, Value} tuples for all matching objects.
  216. %% @equiv lookup_values({p, l, Property})
  217. %% @end
  218. %%
  219. lookup_local_properties(P) -> lookup_values({p,l,P}).
  220. %% @spec (Property::any()) -> [{pid(), Value}]
  221. %%
  222. %% @doc Look up all global (non-unique) instances of a given Property.
  223. %% Returns a list of {Pid, Value} tuples for all matching objects.
  224. %% @equiv lookup_values({p, g, Property})
  225. %% @end
  226. %%
  227. lookup_global_properties(P) -> lookup_values({p,g,P}).
  228. %% @spec (Counter::any()) -> [{pid(), Value::integer()}]
  229. %%
  230. %% @doc Look up all local (non-unique) instances of a given Counter.
  231. %% Returns a list of {Pid, Value} tuples for all matching objects.
  232. %% @equiv lookup_values({c, l, Counter})
  233. %% @end
  234. %%
  235. lookup_local_counters(P) -> lookup_values({c,l,P}).
  236. %% @spec (Counter::any()) -> [{pid(), Value::integer()}]
  237. %%
  238. %% @doc Look up all global (non-unique) instances of a given Counter.
  239. %% Returns a list of {Pid, Value} tuples for all matching objects.
  240. %% @equiv lookup_values({c, g, Counter})
  241. %% @end
  242. %%
  243. lookup_global_counters(P) -> lookup_values({c,g,P}).
  244. %% @spec get_env(Scope::scope(), App::atom(), Key::atom()) -> term()
  245. %% @equiv get_env(Scope, App, Key, [app_env])
  246. get_env(Scope, App, Key) ->
  247. get_env(Scope, App, Key, [app_env]).
  248. %% @spec (Scope::scope(), App::atom(), Key::atom(), Strategy) -> term()
  249. %% Strategy = [Alternative]
  250. %% Alternative = app_env
  251. %% | os_env
  252. %% | inherit | {inherit, pid()} | {inherit, unique_id()}
  253. %% | init_arg
  254. %% | {mnesia, ActivityType, Oid, Pos}
  255. %% | {default, term()}
  256. %% | error
  257. %% @doc Fetch an environment value, potentially cached as a `gproc_env' property.
  258. %%
  259. %% This function first tries to read the value of a cached property,
  260. %% `{p, Scope, {gproc_env, App, Key}}'. If this fails, it will try the provided
  261. %% alternative strategy. `Strategy' is a list of alternatives, tried in order.
  262. %% Each alternative can be one of:
  263. %%
  264. %% * `app_env' - try `application:get_env(App, Key)'
  265. %% * `os_env' - try `os:getenv(ENV)', where `ENV' is `Key' converted into an
  266. %% uppercase string
  267. %% * `{os_env, ENV}' - try `os:getenv(ENV)'
  268. %% * `inherit' - inherit the cached value, if any, held by the (proc_lib) parent.
  269. %% * `{inherit, Pid}' - inherit the cached value, if any, held by `Pid'.
  270. %% * `{inherit, Id}' - inherit the cached value, if any, held by the process
  271. %% registered in `gproc' as `Id'.
  272. %% * `init_arg' - try `init:get_argument(Key)'; expects a single value, if any.
  273. %% * `{mnesia, ActivityType, Oid, Pos}' - try
  274. %% `mnesia:activity(ActivityType, fun() -> mnesia:read(Oid) end)'; retrieve the
  275. %% value in position `Pos' if object found.
  276. %% * `{default, Value}' - set a default value to return once alternatives have been
  277. %% exhausted; if not set, `undefined' will be returned.
  278. %% * `error' - raise an exception, `erlang:error(gproc_env, [App, Key, Scope])'.
  279. %%
  280. %% While any alternative can occur more than once, the only one that might make
  281. %% sense to use multiple times is `{default, Value}'.
  282. %%
  283. %% The return value will be one of:
  284. %%
  285. %% * The value of the first matching alternative, or exception caused by `error',
  286. %% whichever comes first
  287. %% * The last instance of `{default, Value}', or `undefined', if there is no
  288. %% matching alternative, default or `error' entry in the list.
  289. %%
  290. %% The `error' option can be used to assert that a value has been previously
  291. %% cached. Alternatively, it can be used to assert that a value is either cached
  292. %% or at least defined somewhere, e.g. `get_env(l, mnesia, dir, [app_env, error])'.
  293. %% @end
  294. get_env(Scope, App, Key, Strategy)
  295. when Scope==l, is_atom(App), is_atom(Key);
  296. Scope==g, is_atom(App), is_atom(Key) ->
  297. do_get_env(Scope, App, Key, Strategy, false).
  298. %% @spec get_set_env(Scope::scope(), App::atom(), Key::atom()) -> term()
  299. %% @equiv get_set_env(Scope, App, Key, [app_env])
  300. get_set_env(Scope, App, Key) ->
  301. get_set_env(Scope, App, Key, [app_env]).
  302. %% @spec get_set_env(Scope::scope(), App::atom(), Key::atom(), Strategy) -> Value
  303. %% @doc Fetch and cache an environment value, if not already cached.
  304. %%
  305. %% This function does the same thing as {@link get_env/4}, but also updates the
  306. %% cache. Note that the cache will be updated even if the result of the lookup
  307. %% is `undefined'.
  308. %%
  309. %% @see get_env/4.
  310. %% @end
  311. %%
  312. get_set_env(Scope, App, Key, Strategy)
  313. when Scope==l, is_atom(App), is_atom(Key);
  314. Scope==g, is_atom(App), is_atom(Key) ->
  315. do_get_env(Scope, App, Key, Strategy, true).
  316. do_get_env(Context, App, Key, Alternatives, Set) ->
  317. case lookup_env(Context, App, Key, self()) of
  318. undefined ->
  319. check_alternatives(Alternatives, Context, App, Key, undefined, Set);
  320. {ok, Value} ->
  321. Value
  322. end.
  323. %% @spec set_env(Scope::scope(), App::atom(),
  324. %% Key::atom(), Value::term(), Strategy) -> Value
  325. %% Strategy = [Alternative]
  326. %% Alternative = app_env | os_env | {os_env, VAR}
  327. %% | {mnesia, ActivityType, Oid, Pos}
  328. %%
  329. %% @doc Updates the cached value as well as underlying environment.
  330. %%
  331. %% This function should be exercised with caution, as it affects the larger
  332. %% environment outside gproc. This function modifies the cached value, and then
  333. %% proceeds to update the underlying environment (OS environment variable or
  334. %% application environment variable).
  335. %%
  336. %% When the `mnesia' alternative is used, gproc will try to update any existing
  337. %% object, changing only the `Pos' position. If no such object exists, it will
  338. %% create a new object, setting any other attributes (except `Pos' and the key)
  339. %% to `undefined'.
  340. %% @end
  341. %%
  342. set_env(Scope, App, Key, Value, Strategy)
  343. when Scope==l, is_atom(App), is_atom(Key);
  344. Scope==g, is_atom(App), is_atom(Key) ->
  345. case is_valid_set_strategy(Strategy, Value) of
  346. true ->
  347. update_cached_env(Scope, App, Key, Value),
  348. set_strategy(Strategy, App, Key, Value);
  349. false ->
  350. erlang:error(badarg)
  351. end.
  352. check_alternatives([{default, Val}|Alts], Scope, App, Key, _, Set) ->
  353. check_alternatives(Alts, Scope, App, Key, Val, Set);
  354. check_alternatives([H|T], Scope, App, Key, Def, Set) ->
  355. case try_alternative(H, App, Key, Scope) of
  356. undefined ->
  357. check_alternatives(T, Scope, App, Key, Def, Set);
  358. {ok, Value} ->
  359. if Set ->
  360. cache_env(Scope, App, Key, Value),
  361. Value;
  362. true ->
  363. Value
  364. end
  365. end;
  366. check_alternatives([], Scope, App, Key, Def, Set) ->
  367. if Set ->
  368. cache_env(Scope, App, Key, Def);
  369. true ->
  370. ok
  371. end,
  372. Def.
  373. try_alternative(error, App, Key, Scope) ->
  374. erlang:error(gproc_env, [App, Key, Scope]);
  375. try_alternative(inherit, App, Key, Scope) ->
  376. case get('$ancestors') of
  377. [P|_] ->
  378. lookup_env(Scope, App, Key, P);
  379. _ ->
  380. undefined
  381. end;
  382. try_alternative({inherit, P}, App, Key, Scope) when is_pid(P) ->
  383. lookup_env(Scope, App, Key, P);
  384. try_alternative({inherit, P}, App, Key, Scope) ->
  385. case where(P) of
  386. undefined -> undefined;
  387. Pid when is_pid(Pid) ->
  388. lookup_env(Scope, App, Key, Pid)
  389. end;
  390. try_alternative(app_env, App, Key, _Scope) ->
  391. case application:get_env(App, Key) of
  392. undefined -> undefined;
  393. {ok, undefined} -> undefined;
  394. {ok, Value} -> {ok, Value}
  395. end;
  396. try_alternative(os_env, _App, Key, _) ->
  397. case os:getenv(os_env_key(Key)) of
  398. "" -> undefined;
  399. Val -> {ok, Val}
  400. end;
  401. try_alternative({os_env, Key}, _, _, _) ->
  402. case os:getenv(Key) of
  403. "" -> undefined;
  404. Val -> {ok, Val}
  405. end;
  406. try_alternative(init_arg, _, Key, _) ->
  407. case init:get_argument(Key) of
  408. {ok, [[Value]]} ->
  409. {ok, Value};
  410. error ->
  411. undefined
  412. end;
  413. try_alternative({mnesia,Type,Key,Pos}, _, _, _) ->
  414. case mnesia:activity(Type, fun() -> mnesia:read(Key) end) of
  415. [] -> undefined;
  416. [Found] ->
  417. {ok, element(Pos, Found)}
  418. end.
  419. os_env_key(Key) ->
  420. string:to_upper(atom_to_list(Key)).
  421. lookup_env(Scope, App, Key, P) ->
  422. case ets:lookup(?TAB, {{p, Scope, {gproc_env, App, Key}}, P}) of
  423. [] ->
  424. undefined;
  425. [{_, _, Value}] ->
  426. {ok, Value}
  427. end.
  428. cache_env(Scope, App, Key, Value) ->
  429. reg({p, Scope, {gproc_env, App, Key}}, Value).
  430. update_cached_env(Scope, App, Key, Value) ->
  431. case lookup_env(Scope, App, Key, self()) of
  432. undefined ->
  433. cache_env(Scope, App, Key, Value);
  434. {ok, _} ->
  435. set_value({p, Scope, {gproc_env, App, Key}}, Value)
  436. end.
  437. is_valid_set_strategy([os_env|T], Value) ->
  438. is_string(Value) andalso is_valid_set_strategy(T, Value);
  439. is_valid_set_strategy([{os_env, _}|T], Value) ->
  440. is_string(Value) andalso is_valid_set_strategy(T, Value);
  441. is_valid_set_strategy([app_env|T], Value) ->
  442. is_valid_set_strategy(T, Value);
  443. is_valid_set_strategy([{mnesia,_Type,_Oid,_Pos}|T], Value) ->
  444. is_valid_set_strategy(T, Value);
  445. is_valid_set_strategy([], _) ->
  446. true;
  447. is_valid_set_strategy(_, _) ->
  448. false.
  449. set_strategy([H|T], App, Key, Value) ->
  450. case H of
  451. app_env ->
  452. application:set_env(App, Key, Value);
  453. os_env ->
  454. os:putenv(os_env_key(Key), Value);
  455. {os_env, ENV} ->
  456. os:putenv(ENV, Value);
  457. {mnesia,Type,Oid,Pos} ->
  458. mnesia:activity(
  459. Type,
  460. fun() ->
  461. Rec = case mnesia:read(Oid) of
  462. [] ->
  463. {Tab,K} = Oid,
  464. Tag = mnesia:table_info(Tab, record_name),
  465. Attrs = mnesia:table_info(Tab, attributes),
  466. list_to_tuple(
  467. [Tag,K |
  468. [undefined || _ <- tl(Attrs)]]);
  469. [Old] ->
  470. Old
  471. end,
  472. mnesia:write(setelement(Pos, Rec, Value))
  473. end)
  474. end,
  475. set_strategy(T, App, Key, Value);
  476. set_strategy([], _, _, Value) ->
  477. Value.
  478. is_string(S) ->
  479. try begin _ = iolist_to_binary(S),
  480. true
  481. end
  482. catch
  483. error:_ ->
  484. false
  485. end.
  486. %% @spec reg(Key::key()) -> true
  487. %%
  488. %% @doc
  489. %% @equiv reg(Key, default(Key))
  490. %% @end
  491. reg(Key) ->
  492. reg(Key, default(Key)).
  493. default({T,_,_}) when T==c -> 0;
  494. default(_) -> undefined.
  495. %% @spec await(Key::key()) -> {pid(),Value}
  496. %% @equiv await(Key,infinity)
  497. %%
  498. await(Key) ->
  499. await(Key, infinity).
  500. %% @spec await(Key::key(), Timeout) -> {pid(),Value}
  501. %% Timeout = integer() | infinity
  502. %%
  503. %% @doc Wait for a local name to be registered.
  504. %% The function raises an exception if the timeout expires. Timeout must be
  505. %% either an interger &gt; 0 or 'infinity'.
  506. %% A small optimization: we first perform a lookup, to see if the name
  507. %% is already registered. This way, the cost of the operation will be
  508. %% roughly the same as of where/1 in the case where the name is already
  509. %% registered (the difference: await/2 also returns the value).
  510. %% @end
  511. %%
  512. await({n,g,_} = Key, Timeout) ->
  513. ?CHK_DIST,
  514. request_wait(Key, Timeout);
  515. await({n,l,_} = Key, Timeout) ->
  516. case ets:lookup(?TAB, {Key, n}) of
  517. [{_, Pid, Value}] ->
  518. {Pid, Value};
  519. _ ->
  520. request_wait(Key, Timeout)
  521. end;
  522. await(K, T) ->
  523. erlang:error(badarg, [K, T]).
  524. request_wait({n,C,_} = Key, Timeout) when C==l; C==g ->
  525. TRef = case Timeout of
  526. infinity -> no_timer;
  527. T when is_integer(T), T > 0 ->
  528. erlang:start_timer(T, self(), gproc_timeout);
  529. _ ->
  530. erlang:error(badarg, [Key, Timeout])
  531. end,
  532. WRef = case {call({await,Key,self()}, C), C} of
  533. {{R, {Kg,Pg,Vg}}, g} ->
  534. self() ! {gproc, R, registered, {Kg,Pg,Vg}},
  535. R;
  536. {R,_} ->
  537. R
  538. end,
  539. receive
  540. {gproc, WRef, registered, {_K, Pid, V}} ->
  541. case TRef of
  542. no_timer -> ignore;
  543. _ -> erlang:cancel_timer(TRef)
  544. end,
  545. {Pid, V};
  546. {timeout, TRef, gproc_timeout} ->
  547. cancel_wait(Key, WRef),
  548. erlang:error(timeout, [Key, Timeout])
  549. end.
  550. %% @spec nb_wait(Key::key()) -> Ref
  551. %%
  552. %% @doc Wait for a local name to be registered.
  553. %% The caller can expect to receive a message,
  554. %% {gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
  555. %% @end
  556. %%
  557. nb_wait({n,g,_} = Key) ->
  558. ?CHK_DIST,
  559. call({await, Key, self()}, g);
  560. nb_wait({n,l,_} = Key) ->
  561. call({await, Key, self()}, l);
  562. nb_wait(Key) ->
  563. erlang:error(badarg, [Key]).
  564. cancel_wait({_,g,_} = Key, Ref) ->
  565. ?CHK_DIST,
  566. cast({cancel_wait, self(), Key, Ref}, g),
  567. ok;
  568. cancel_wait({_,l,_} = Key, Ref) ->
  569. cast({cancel_wait, self(), Key, Ref}, l),
  570. ok.
  571. %% @spec reg(Key::key(), Value) -> true
  572. %%
  573. %% @doc Register a name or property for the current process
  574. %%
  575. %%
  576. reg({_,g,_} = Key, Value) ->
  577. %% anything global
  578. ?CHK_DIST,
  579. gproc_dist:reg(Key, Value);
  580. reg({p,l,_} = Key, Value) ->
  581. local_reg(Key, Value);
  582. reg({a,l,_} = Key, undefined) ->
  583. call({reg, Key, undefined});
  584. reg({c,l,_} = Key, Value) when is_integer(Value) ->
  585. call({reg, Key, Value});
  586. reg({n,l,_} = Key, Value) ->
  587. call({reg, Key, Value});
  588. reg(_, _) ->
  589. erlang:error(badarg).
  590. %% @spec mreg(type(), scope(), [{Key::any(), Value::any()}]) -> true
  591. %%
  592. %% @doc Register multiple {Key,Value} pairs of a given type and scope.
  593. %%
  594. %% This function is more efficient than calling {@link reg/2} repeatedly.
  595. %% It is also atomic in regard to unique names; either all names are registered
  596. %% or none are.
  597. %% @end
  598. mreg(T, g, KVL) ->
  599. ?CHK_DIST,
  600. gproc_dist:mreg(T, KVL);
  601. mreg(T, l, KVL) when T==a; T==n ->
  602. if is_list(KVL) ->
  603. call({mreg, T, l, KVL});
  604. true ->
  605. erlang:error(badarg)
  606. end;
  607. mreg(p, l, KVL) ->
  608. local_mreg(p, KVL);
  609. mreg(_, _, _) ->
  610. erlang:error(badarg).
  611. %% @spec munreg(type(), scope(), [Key::any()]) -> true
  612. %%
  613. %% @doc Unregister multiple Key items of a given type and scope.
  614. %%
  615. %% This function is usually more efficient than calling {@link unreg/1}
  616. %% repeatedly.
  617. %% @end
  618. munreg(T, g, L) ->
  619. ?CHK_DIST,
  620. gproc_dist:munreg(T, existing(T,g,L));
  621. munreg(T, l, L) when T==a; T==n ->
  622. if is_list(L) ->
  623. call({munreg, T, l, existing(T,l,L)});
  624. true ->
  625. erlang:error(badarg)
  626. end;
  627. munreg(p, l, L) ->
  628. local_munreg(p, existing(p,l,L));
  629. munreg(_, _, _) ->
  630. erlang:error(badarg).
  631. existing(T,Scope,L) ->
  632. Keys = if T==p; T==c ->
  633. [{{T,Scope,K}, self()} || K <- L];
  634. T==a; T==n ->
  635. [{{T,Scope,K}, T} || K <- L]
  636. end,
  637. _ = [case ets:member(?TAB, K) of
  638. false -> erlang:error(badarg);
  639. true -> true
  640. end || K <- Keys],
  641. L.
  642. %% @spec (Key:: key()) -> true
  643. %%
  644. %% @doc Unregister a name or property.
  645. %% @end
  646. unreg(Key) ->
  647. case Key of
  648. {_, g, _} ->
  649. ?CHK_DIST,
  650. gproc_dist:unreg(Key);
  651. {T, l, _} when T == n;
  652. T == a -> call({unreg, Key});
  653. {_, l, _} ->
  654. case ets:member(?TAB, {Key,self()}) of
  655. true ->
  656. _ = gproc_lib:remove_reg(Key, self()),
  657. true;
  658. false ->
  659. erlang:error(badarg)
  660. end
  661. end.
  662. %% @equiv unreg/1
  663. unregister_name(Key) ->
  664. unreg(Key).
  665. %% @spec (select_pattern()) -> list(sel_object())
  666. %% @doc
  667. %% @equiv select(all, Pat)
  668. %% @end
  669. select(Pat) ->
  670. select(all, Pat).
  671. %% @spec (Context::context(), Pat::sel_pattern()) -> [{Key, Pid, Value}]
  672. %%
  673. %% @doc Perform a select operation on the process registry.
  674. %%
  675. %% The physical representation in the registry may differ from the above,
  676. %% but the select patterns are transformed appropriately.
  677. %% @end
  678. select(Context, Pat) ->
  679. ets:select(?TAB, pattern(Pat, Context)).
  680. %% @spec (Context::context(), Pat::sel_patten(), Limit::integer()) ->
  681. %% [{Key, Pid, Value}]
  682. %% @doc Like {@link select/2} but returns Limit objects at a time.
  683. %%
  684. %% See [http://www.erlang.org/doc/man/ets.html#select-3].
  685. %% @end
  686. select(Context, Pat, Limit) ->
  687. ets:select(?TAB, pattern(Pat, Context), Limit).
  688. %%% Local properties can be registered in the local process, since
  689. %%% no other process can interfere.
  690. %%%
  691. local_reg(Key, Value) ->
  692. case gproc_lib:insert_reg(Key, Value, self(), l) of
  693. false -> erlang:error(badarg);
  694. true -> monitor_me()
  695. end.
  696. local_mreg(_, []) -> true;
  697. local_mreg(T, [_|_] = KVL) ->
  698. case gproc_lib:insert_many(T, l, KVL, self()) of
  699. false -> erlang:error(badarg);
  700. {true,_} -> monitor_me()
  701. end.
  702. local_munreg(T, L) when T==p; T==c ->
  703. _ = [gproc_lib:remove_reg({T,l,K}, self()) || K <- L],
  704. true.
  705. %% @spec (Key :: key(), Value) -> true
  706. %% @doc Sets the value of the registeration entry given by Key
  707. %%
  708. %% Key is assumed to exist and belong to the calling process.
  709. %% If it doesn't, this function will exit.
  710. %%
  711. %% Value can be any term, unless the object is a counter, in which case
  712. %% it must be an integer.
  713. %% @end
  714. %%
  715. set_value({_,g,_} = Key, Value) ->
  716. ?CHK_DIST,
  717. gproc_dist:set_value(Key, Value);
  718. set_value({a,l,_} = Key, Value) when is_integer(Value) ->
  719. call({set, Key, Value});
  720. set_value({n,l,_} = Key, Value) ->
  721. %% we cannot do this locally, since we have to check that the object
  722. %% exists first - not an atomic update.
  723. call({set, Key, Value});
  724. set_value({p,l,_} = Key, Value) ->
  725. %% we _can_ to this locally, since there is no race condition - no
  726. %% other process can update our properties.
  727. case gproc_lib:do_set_value(Key, Value, self()) of
  728. true -> true;
  729. false ->
  730. erlang:error(badarg)
  731. end;
  732. set_value({c,l,_} = Key, Value) when is_integer(Value) ->
  733. gproc_lib:do_set_counter_value(Key, Value, self());
  734. set_value(_, _) ->
  735. erlang:error(badarg).
  736. %% @spec (Key) -> Value
  737. %% @doc Read the value stored with a key registered to the current process.
  738. %%
  739. %% If no such key is registered to the current process, this function exits.
  740. %% @end
  741. get_value(Key) ->
  742. get_value(Key, self()).
  743. get_value({T,_,_} = Key, Pid) when is_pid(Pid) ->
  744. if T==n orelse T==a ->
  745. case ets:lookup(?TAB, {Key, T}) of
  746. [{_, P, Value}] when P == Pid -> Value;
  747. _ -> erlang:error(badarg)
  748. end;
  749. true ->
  750. ets:lookup_element(?TAB, {Key, Pid}, 3)
  751. end;
  752. get_value(_, _) ->
  753. erlang:error(badarg).
  754. %% @spec (Key) -> Pid
  755. %% @doc Lookup the Pid stored with a key.
  756. %%
  757. lookup_pid({_T,_,_} = Key) ->
  758. case where(Key) of
  759. undefined -> erlang:error(badarg);
  760. P -> P
  761. end.
  762. %% @spec (Key) -> Value
  763. %% @doc Lookup the value stored with a key.
  764. %%
  765. lookup_value({T,_,_} = Key) ->
  766. if T==n orelse T==a ->
  767. ets:lookup_element(?TAB, {Key,T}, 3);
  768. true ->
  769. erlang:error(badarg)
  770. end.
  771. %% @spec (Key::key()) -> pid()
  772. %%
  773. %% @doc Returns the pid registered as Key
  774. %%
  775. %% The type of registration entry must be either name or aggregated counter.
  776. %% Otherwise this function will exit. Use {@link lookup_pids/1} in these
  777. %% cases.
  778. %% @end
  779. %%
  780. where({T,_,_}=Key) ->
  781. if T==n orelse T==a ->
  782. case ets:lookup(?TAB, {Key,T}) of
  783. [{_, P, _Value}] ->
  784. case my_is_process_alive(P) of
  785. true -> P;
  786. false ->
  787. undefined
  788. end;
  789. _ -> % may be [] or [{Key,Waiters}]
  790. undefined
  791. end;
  792. true ->
  793. erlang:error(badarg)
  794. end.
  795. %% @equiv where/1
  796. whereis_name(Key) ->
  797. where(Key).
  798. %% @spec (Key::key()) -> [pid()]
  799. %%
  800. %% @doc Returns a list of pids with the published key Key
  801. %%
  802. %% If the type of registration entry is either name or aggregated counter,
  803. %% this function will return either an empty list, or a list of one pid.
  804. %% For non-unique types, the return value can be a list of any length.
  805. %% @end
  806. %%
  807. lookup_pids({T,_,_} = Key) ->
  808. L = if T==n orelse T==a ->
  809. ets:select(?TAB, [{{{Key,T}, '$1', '_'},[],['$1']}]);
  810. true ->
  811. ets:select(?TAB, [{{{Key,'_'}, '$1', '_'},[],['$1']}])
  812. end,
  813. [P || P <- L, my_is_process_alive(P)].
  814. %% @spec (pid()) -> boolean()
  815. %%
  816. my_is_process_alive(P) when node(P) =:= node() ->
  817. is_process_alive(P);
  818. my_is_process_alive(_) ->
  819. %% remote pid - assume true (too costly to find out)
  820. true.
  821. %% @spec (Key::key()) -> [{pid(), Value}]
  822. %%
  823. %% @doc Retrieve the `{Pid,Value}' pairs corresponding to Key.
  824. %%
  825. %% Key refer to any type of registry object. If it refers to a unique
  826. %% object, the list will be of length 0 or 1. If it refers to a non-unique
  827. %% object, the return value can be a list of any length.
  828. %% @end
  829. %%
  830. lookup_values({T,_,_} = Key) ->
  831. L = if T==n orelse T==a ->
  832. ets:select(?TAB, [{{{Key,T}, '$1', '$2'},[],[{{'$1','$2'}}]}]);
  833. true ->
  834. ets:select(?TAB, [{{{Key,'_'}, '$1', '$2'},[],[{{'$1','$2'}}]}])
  835. end,
  836. [Pair || {P,_} = Pair <- L, my_is_process_alive(P)].
  837. %% @spec (Key::key(), Incr::integer()) -> integer()
  838. %%
  839. %% @doc Updates the counter registered as Key for the current process.
  840. %%
  841. %% This function works like ets:update_counter/3
  842. %% (see [http://www.erlang.org/doc/man/ets.html#update_counter-3]), but
  843. %% will fail if the type of object referred to by Key is not a counter.
  844. %% @end
  845. %%
  846. update_counter({c,l,_} = Key, Incr) when is_integer(Incr) ->
  847. gproc_lib:update_counter(Key, Incr, self());
  848. update_counter({c,g,_} = Key, Incr) when is_integer(Incr) ->
  849. ?CHK_DIST,
  850. gproc_dist:update_counter(Key, Incr);
  851. update_counter(_, _) ->
  852. erlang:error(badarg).
  853. %% @spec (From::key(), To::pid() | key()) -> undefined | pid()
  854. %%
  855. %% @doc Atomically transfers the key `From' to the process identified by `To'.
  856. %%
  857. %% This function transfers any gproc key (name, property, counter, aggr. counter)
  858. %% from one process to another, and returns the pid of the new owner.
  859. %%
  860. %% `To' must be either a pid or a unique name (name or aggregated counter), but
  861. %% does not necessarily have to resolve to an existing process. If there is
  862. %% no process registered with the `To' key, `give_away/2' returns `undefined',
  863. %% and the `From' key is effectively unregistered.
  864. %%
  865. %% It is allowed to give away a key to oneself, but of course, this operation
  866. %% will have no effect.
  867. %%
  868. %% Fails with `badarg' if the calling process does not have a `From' key
  869. %% registered.
  870. %% @end
  871. give_away({_,l,_} = Key, ToPid) when is_pid(ToPid), node(ToPid) == node() ->
  872. call({give_away, Key, ToPid});
  873. give_away({_,l,_} = Key, {n,l,_} = ToKey) ->
  874. call({give_away, Key, ToKey});
  875. give_away({_,g,_} = Key, To) ->
  876. ?CHK_DIST,
  877. gproc_dist:give_away(Key, To).
  878. %% @spec (Key::key(), Msg::any()) -> Msg
  879. %%
  880. %% @doc Sends a message to the process, or processes, corresponding to Key.
  881. %%
  882. %% If Key belongs to a unique object (name or aggregated counter), this
  883. %% function will send a message to the corresponding process, or fail if there
  884. %% is no such process. If Key is for a non-unique object type (counter or
  885. %% property), Msg will be send to all processes that have such an object.
  886. %% @end
  887. %%
  888. send({T,C,_} = Key, Msg) when C==l; C==g ->
  889. if T == n orelse T == a ->
  890. case ets:lookup(?TAB, {Key, T}) of
  891. [{_, Pid, _}] ->
  892. Pid ! Msg;
  893. _ ->
  894. erlang:error(badarg)
  895. end;
  896. T==p orelse T==c ->
  897. %% BUG - if the key part contains select wildcards, we may end up
  898. %% sending multiple messages to the same pid
  899. lists:foreach(fun(Pid) ->
  900. Pid ! Msg
  901. end, lookup_pids(Key)),
  902. Msg;
  903. true ->
  904. erlang:error(badarg)
  905. end;
  906. send(_, _) ->
  907. erlang:error(badarg).
  908. %% @spec (Context :: context()) -> key() | '$end_of_table'
  909. %%
  910. %% @doc Behaves as ets:first(Tab) for a given type of registration object.
  911. %%
  912. %% See [http://www.erlang.org/doc/man/ets.html#first-1].
  913. %% The registry behaves as an ordered_set table.
  914. %% @end
  915. %%
  916. first(Context) ->
  917. {S, T} = get_s_t(Context),
  918. {HeadPat,_} = headpat({S, T}, '_', '_', '_'),
  919. case ets:select(?TAB, [{HeadPat,[],[{element,1,'$_'}]}], 1) of
  920. {[First], _} ->
  921. First;
  922. _ ->
  923. '$end_of_table'
  924. end.
  925. %% @spec (Context :: context()) -> key() | '$end_of_table'
  926. %%
  927. %% @doc Behaves as ets:last(Tab) for a given type of registration object.
  928. %%
  929. %% See [http://www.erlang.org/doc/man/ets.html#last-1].
  930. %% The registry behaves as an ordered_set table.
  931. %% @end
  932. %%
  933. last(Context) ->
  934. {S, T} = get_s_t(Context),
  935. S1 = if S == '_'; S == l -> m; % 'm' comes after 'l'
  936. S == g -> h % 'h' comes between 'g' & 'l'
  937. end,
  938. Beyond = {{T,S1,[]},[]},
  939. step(ets:prev(?TAB, Beyond), S, T).
  940. %% @spec (Context::context(), Key::key()) -> key() | '$end_of_table'
  941. %%
  942. %% @doc Behaves as ets:next(Tab,Key) for a given type of registration object.
  943. %%
  944. %% See [http://www.erlang.org/doc/man/ets.html#next-2].
  945. %% The registry behaves as an ordered_set table.
  946. %% @end
  947. %%
  948. next(Context, K) ->
  949. {S,T} = get_s_t(Context),
  950. step(ets:next(?TAB,K), S, T).
  951. %% @spec (Context::context(), Key::key()) -> key() | '$end_of_table'
  952. %%
  953. %% @doc Behaves as ets:prev(Tab,Key) for a given type of registration object.
  954. %%
  955. %% See [http://www.erlang.org/doc/man/ets.html#prev-2].
  956. %% The registry behaves as an ordered_set table.
  957. %% @end
  958. %%
  959. prev(Context, K) ->
  960. {S, T} = get_s_t(Context),
  961. step(ets:prev(?TAB, K), S, T).
  962. step(Key, '_', '_') ->
  963. case Key of
  964. {{_,_,_},_} -> Key;
  965. _ -> '$end_of_table'
  966. end;
  967. step(Key, '_', T) ->
  968. case Key of
  969. {{T,_,_},_} -> Key;
  970. _ -> '$end_of_table'
  971. end;
  972. step(Key, S, '_') ->
  973. case Key of
  974. {{_, S, _}, _} -> Key;
  975. _ -> '$end_of_table'
  976. end;
  977. step(Key, S, T) ->
  978. case Key of
  979. {{T, S, _}, _} -> Key;
  980. _ -> '$end_of_table'
  981. end.
  982. %% @spec (Pid::pid()) -> ProcessInfo
  983. %% ProcessInfo = [{gproc, [{Key,Value}]} | ProcessInfo]
  984. %%
  985. %% @doc Similar to `process_info(Pid)' but with additional gproc info.
  986. %%
  987. %% Returns the same information as process_info(Pid), but with the
  988. %% addition of a `gproc' information item, containing the `{Key,Value}'
  989. %% pairs registered to the process.
  990. %% @end
  991. info(Pid) when is_pid(Pid) ->
  992. Items = [?MODULE | [ I || {I,_} <- process_info(self())]],
  993. [info(Pid,I) || I <- Items].
  994. %% @spec (Pid::pid(), Item::atom()) -> {Item, Info}
  995. %%
  996. %% @doc Similar to process_info(Pid, Item), but with additional gproc info.
  997. %%
  998. %% For `Item = gproc', this function returns a list of `{Key, Value}' pairs
  999. %% registered to the process Pid. For other values of Item, it returns the
  1000. %% same as [http://www.erlang.org/doc/man/erlang.html#process_info-2].
  1001. %% @end
  1002. info(Pid, ?MODULE) ->
  1003. Keys = ets:select(?TAB, [{ {{Pid,'$1'}, r}, [], ['$1'] }]),
  1004. {?MODULE, lists:zf(
  1005. fun(K) ->
  1006. try V = get_value(K, Pid),
  1007. {true, {K,V}}
  1008. catch
  1009. error:_ ->
  1010. false
  1011. end
  1012. end, Keys)};
  1013. info(Pid, I) ->
  1014. process_info(Pid, I).
  1015. %%% ==========================================================
  1016. %% @hidden
  1017. handle_cast({monitor_me, Pid}, S) ->
  1018. erlang:monitor(process, Pid),
  1019. {noreply, S};
  1020. handle_cast({cancel_wait, Pid, {T,_,_} = Key, Ref}, S) ->
  1021. Rev = {Pid,Key},
  1022. case ets:lookup(?TAB, {Key,T}) of
  1023. [{K, Waiters}] ->
  1024. case Waiters -- [{Pid,Ref}] of
  1025. [] ->
  1026. ets:delete(?TAB, K),
  1027. ets:delete(?TAB, Rev);
  1028. NewWaiters ->
  1029. ets:insert(?TAB, {K, NewWaiters}),
  1030. case lists:keymember(Pid, 1, NewWaiters) of
  1031. true ->
  1032. %% should be extremely unlikely
  1033. ok;
  1034. false ->
  1035. %% delete the reverse entry
  1036. ets:delete(?TAB, Rev)
  1037. end
  1038. end;
  1039. _ ->
  1040. ignore
  1041. end,
  1042. {noreply, S}.
  1043. %% @hidden
  1044. handle_call({reg, {_T,l,_} = Key, Val}, {Pid,_}, S) ->
  1045. case try_insert_reg(Key, Val, Pid) of
  1046. true ->
  1047. gproc_lib:ensure_monitor(Pid,l),
  1048. {reply, true, S};
  1049. false ->
  1050. {reply, badarg, S}
  1051. end;
  1052. handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
  1053. case ets:member(?TAB, {Pid,Key}) of
  1054. true ->
  1055. _ = gproc_lib:remove_reg(Key, Pid),
  1056. {reply, true, S};
  1057. false ->
  1058. {reply, badarg, S}
  1059. end;
  1060. handle_call({await, {_,l,_} = Key, Pid}, From, S) ->
  1061. %% Passing the pid explicitly is needed when leader_call is used,
  1062. %% since the Pid given as From in the leader is the local gen_leader
  1063. %% instance on the calling node.
  1064. case gproc_lib:await(Key, Pid, From) of
  1065. noreply ->
  1066. {noreply, S};
  1067. {reply, Reply, _} ->
  1068. {reply, Reply, S}
  1069. end;
  1070. handle_call({mreg, T, l, L}, {Pid,_}, S) ->
  1071. try gproc_lib:insert_many(T, l, L, Pid) of
  1072. {true,_} -> {reply, true, S};
  1073. false -> {reply, badarg, S}
  1074. catch
  1075. error:_ -> {reply, badarg, S}
  1076. end;
  1077. handle_call({munreg, T, l, L}, {Pid,_}, S) ->
  1078. _ = gproc_lib:remove_many(T, l, L, Pid),
  1079. {reply, true, S};
  1080. handle_call({set, {_,l,_} = Key, Value}, {Pid,_}, S) ->
  1081. case gproc_lib:do_set_value(Key, Value, Pid) of
  1082. true ->
  1083. {reply, true, S};
  1084. false ->
  1085. {reply, badarg, S}
  1086. end;
  1087. handle_call({audit_process, Pid}, _, S) ->
  1088. case is_process_alive(Pid) of
  1089. false ->
  1090. process_is_down(Pid);
  1091. true ->
  1092. ignore
  1093. end,
  1094. {reply, ok, S};
  1095. handle_call({give_away, Key, To}, {Pid,_}, S) ->
  1096. Reply = do_give_away(Key, To, Pid),
  1097. {reply, Reply, S};
  1098. handle_call(_, _, S) ->
  1099. {reply, badarg, S}.
  1100. %% @hidden
  1101. handle_info({'DOWN', _MRef, process, Pid, _}, S) ->
  1102. process_is_down(Pid),
  1103. {noreply, S};
  1104. handle_info(_, S) ->
  1105. {noreply, S}.
  1106. %% @hidden
  1107. code_change(_FromVsn, S, _Extra) ->
  1108. %% We have changed local monitor markers from {Pid} to {Pid,l}.
  1109. case ets:select(?TAB, [{{'$1'},[],['$1']}]) of
  1110. [] ->
  1111. ok;
  1112. Pids ->
  1113. ets:insert(?TAB, [{P,l} || P <- Pids]),
  1114. ets:select_delete(?TAB, [{{'_'},[],[true]}])
  1115. end,
  1116. {ok, S}.
  1117. %% @hidden
  1118. terminate(_Reason, _S) ->
  1119. ok.
  1120. call(Req) ->
  1121. call(Req, l).
  1122. call(Req, l) ->
  1123. chk_reply(gen_server:call(?MODULE, Req), Req);
  1124. call(Req, g) ->
  1125. chk_reply(gproc_dist:leader_call(Req), Req).
  1126. chk_reply(Reply, Req) ->
  1127. case Reply of
  1128. badarg -> erlang:error(badarg, Req);
  1129. _ -> Reply
  1130. end.
  1131. cast(Msg) ->
  1132. cast(Msg, l).
  1133. cast(Msg, l) ->
  1134. gen_server:cast(?MODULE, Msg);
  1135. cast(Msg, g) ->
  1136. gproc_dist:leader_cast(Msg).
  1137. try_insert_reg({T,l,_} = Key, Val, Pid) ->
  1138. case gproc_lib:insert_reg(Key, Val, Pid, l) of
  1139. false ->
  1140. case ets:lookup(?TAB, {Key,T}) of
  1141. %% In this particular case, the lookup cannot result in
  1142. %% [{_, Waiters}], since the insert_reg/4 function would
  1143. %% have succeeded then.
  1144. [{_, OtherPid, _}] ->
  1145. case is_process_alive(OtherPid) of
  1146. true ->
  1147. false;
  1148. false ->
  1149. process_is_down(OtherPid),
  1150. true = gproc_lib:insert_reg(Key, Val, Pid, l)
  1151. end;
  1152. [] ->
  1153. false
  1154. end;
  1155. true ->
  1156. true
  1157. end.
  1158. -spec audit_process(pid()) -> ok.
  1159. audit_process(Pid) when is_pid(Pid) ->
  1160. ok = gen_server:call(gproc, {audit_process, Pid}, infinity).
  1161. -spec process_is_down(pid()) -> ok.
  1162. process_is_down(Pid) when is_pid(Pid) ->
  1163. %% delete the monitor marker
  1164. %% io:fwrite(user, "process_is_down(~p) - ~p~n", [Pid,ets:tab2list(?TAB)]),
  1165. ets:delete(?TAB, {Pid,l}),
  1166. Revs = ets:select(?TAB, [{{{Pid,'$1'},r},
  1167. [{'==',{element,2,'$1'},l}], ['$1']}]),
  1168. lists:foreach(
  1169. fun({n,l,_}=K) ->
  1170. Key = {K,n},
  1171. case ets:lookup(?TAB, Key) of
  1172. [{_, Pid, _}] ->
  1173. ets:delete(?TAB, Key);
  1174. [{_, Waiters}] ->
  1175. case [W || {P,_} = W <- Waiters,
  1176. P =/= Pid] of
  1177. [] ->
  1178. ets:delete(?TAB, Key);
  1179. Waiters1 ->
  1180. ets:insert(?TAB, {Key, Waiters1})
  1181. end;
  1182. [] ->
  1183. true
  1184. end;
  1185. ({c,l,C} = K) ->
  1186. Key = {K, Pid},
  1187. [{_, _, Value}] = ets:lookup(?TAB, Key),
  1188. ets:delete(?TAB, Key),
  1189. gproc_lib:update_aggr_counter(l, C, -Value);
  1190. ({a,l,_} = K) ->
  1191. ets:delete(?TAB, {K,a});
  1192. ({p,_,_} = K) ->
  1193. ets:delete(?TAB, {K, Pid})
  1194. end, Revs),
  1195. ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
  1196. ok.
  1197. do_give_away({T,l,_} = K, To, Pid) when T==n; T==a ->
  1198. Key = {K, T},
  1199. case ets:lookup(?TAB, Key) of
  1200. [{_, Pid, Value}] ->
  1201. %% Pid owns the reg; allowed to give_away
  1202. case pid_to_give_away_to(To) of
  1203. Pid ->
  1204. %% Give away to ourselves? Why not? We'll allow it,
  1205. %% but nothing needs to be done.
  1206. Pid;
  1207. ToPid when is_pid(ToPid) ->
  1208. ets:insert(?TAB, [{Key, ToPid, Value},
  1209. {{ToPid, K}, r}]),
  1210. ets:delete(?TAB, {Pid, K}),
  1211. gproc_lib:ensure_monitor(ToPid, l),
  1212. ToPid;
  1213. undefined ->
  1214. _ = gproc_lib:remove_reg(K, Pid),
  1215. undefined
  1216. end;
  1217. _ ->
  1218. badarg
  1219. end;
  1220. do_give_away({T,l,_} = K, To, Pid) when T==c; T==p ->
  1221. Key = {K, Pid},
  1222. case ets:lookup(?TAB, Key) of
  1223. [{_, Pid, Value}] ->
  1224. case pid_to_give_away_to(To) of
  1225. ToPid when is_pid(ToPid) ->
  1226. ToKey = {K, ToPid},
  1227. case ets:member(?TAB, ToKey) of
  1228. true ->
  1229. badarg;
  1230. false ->
  1231. ets:insert(?TAB, [{ToKey, ToPid, Value},
  1232. {{ToPid, K}, r}]),
  1233. ets:delete(?TAB, {Pid, K}),
  1234. ets:delete(?TAB, Key),
  1235. gproc_lib:ensure_monitor(ToPid, l),
  1236. ToPid
  1237. end;
  1238. undefined ->
  1239. _ = gproc_lib:remove_reg(K, Pid),
  1240. undefined
  1241. end;
  1242. _ ->
  1243. badarg
  1244. end.
  1245. pid_to_give_away_to(P) when is_pid(P), node(P) == node() ->
  1246. P;
  1247. pid_to_give_away_to({T,l,_} = Key) when T==n; T==a ->
  1248. case ets:lookup(?TAB, {Key, T}) of
  1249. [{_, Pid, _}] ->
  1250. Pid;
  1251. _ ->
  1252. undefined
  1253. end.
  1254. create_tabs() ->
  1255. case ets:info(?TAB, name) of
  1256. undefined ->
  1257. ets:new(?TAB, [ordered_set, public, named_table]);
  1258. _ ->
  1259. ok
  1260. end.
  1261. %% @hidden
  1262. init([]) ->
  1263. set_monitors(),
  1264. {ok, #state{}}.
  1265. set_monitors() ->
  1266. set_monitors(ets:select(?TAB, [{{{'$1',l}},[],['$1']}], 100)).
  1267. set_monitors('$end_of_table') ->
  1268. ok;
  1269. set_monitors({Pids, Cont}) ->
  1270. [erlang:monitor(process,Pid) || Pid <- Pids],
  1271. set_monitors(ets:select(Cont)).
  1272. monitor_me() ->
  1273. case ets:insert_new(?TAB, {{self(),l}}) of
  1274. false -> true;
  1275. true ->
  1276. cast({monitor_me,self()}),
  1277. true
  1278. end.
  1279. pattern([{'_', Gs, As}], T) ->
  1280. ?l,
  1281. {HeadPat, Vs} = headpat(T, '$1', '$2', '$3'),
  1282. [{HeadPat, rewrite(Gs,Vs), rewrite(As,Vs)}];
  1283. pattern([{{A,B,C},Gs,As}], Scope) ->
  1284. ?l,
  1285. {HeadPat, Vars} = headpat(Scope, A,B,C),
  1286. [{HeadPat, rewrite(Gs,Vars), rewrite(As,Vars)}];
  1287. pattern([{Head, Gs, As}], Scope) ->
  1288. ?l,
  1289. {S, T} = get_s_t(Scope),
  1290. case is_var(Head) of
  1291. {true,_N} ->
  1292. HeadPat = {{{T,S,'_'},'_'},'_','_'},
  1293. Vs = [{Head, obj_prod()}],
  1294. %% {HeadPat, Vs} = headpat(Scope, A,B,C),
  1295. %% the headpat function should somehow verify that Head is
  1296. %% consistent with Scope (or should we add a guard?)
  1297. [{HeadPat, rewrite(Gs, Vs), rewrite(As, Vs)}];
  1298. false ->
  1299. erlang:error(badarg)
  1300. end.
  1301. %% This is the expression to use in guards and the RHS to address the whole
  1302. %% object, in its logical representation.
  1303. obj_prod() ->
  1304. {{ {element,1,{element,1,'$_'}},
  1305. {element,2,'$_'},
  1306. {element,3,'$_'} }}.
  1307. obj_prod_l() ->
  1308. [ {element,1,{element,1,'$_'}},
  1309. {element,2,'$_'},
  1310. {element,3,'$_'} ].
  1311. headpat({S, T}, V1,V2,V3) ->
  1312. headpat(type(T), scope(S), V1,V2,V3);
  1313. headpat(T, V1, V2, V3) when is_atom(T) ->
  1314. headpat(type(T), l, V1, V2, V3);
  1315. headpat(_, _, _, _) -> erlang:error(badarg).
  1316. headpat(T, C, V1,V2,V3) ->
  1317. Rf = fun(Pos) ->
  1318. {element,Pos,{element,1,{element,1,'$_'}}}
  1319. end,
  1320. K2 = if T==n orelse T==a -> T;
  1321. true -> '_'
  1322. end,
  1323. {Kp,Vars} = case V1 of
  1324. {Vt,Vc,Vn} ->
  1325. ?l,
  1326. {T1,Vs1} = subst(T,Vt,fun() -> Rf(1) end,[]),
  1327. {C1,Vs2} = subst(C,Vc,fun() -> Rf(2) end,Vs1),
  1328. {{T1,C1,Vn}, Vs2};
  1329. '_' ->
  1330. ?l,
  1331. {{T,C,'_'}, []};
  1332. _ ->
  1333. ?l,
  1334. case is_var(V1) of
  1335. {true,_} ->
  1336. {{T,C,V1}, [{V1, {element,1,
  1337. {element,1,'$_'}}}]};
  1338. false ->
  1339. erlang:error(badarg)
  1340. end
  1341. end,
  1342. {{{Kp,K2},V2,V3}, Vars}.
  1343. %% l(L) -> L.
  1344. subst(X, '_', _F, Vs) ->
  1345. {X, Vs};
  1346. subst(X, V, F, Vs) ->
  1347. case is_var(V) of
  1348. {true,_} ->
  1349. {X, [{V,F()}|Vs]};
  1350. false ->
  1351. {V, Vs}
  1352. end.
  1353. scope('_') -> '_';
  1354. scope(all) -> '_';
  1355. scope(global) -> g;
  1356. scope(local) -> l;
  1357. scope(S) when S==l; S==g -> S.
  1358. type('_') -> '_';
  1359. type(all) -> '_';
  1360. type(T) when T==n; T==p; T==c; T==a -> T;
  1361. type(names) -> n;
  1362. type(props) -> p;
  1363. type(counters) -> c;
  1364. type(aggr_counters) -> a.
  1365. rev_keypat(Context) ->
  1366. {S,T} = get_s_t(Context),
  1367. {T,S,'_'}.
  1368. get_s_t({S,T}) -> {scope(S), type(T)};
  1369. get_s_t(T) when is_atom(T) ->
  1370. {scope(all), type(T)}.
  1371. is_var('$1') -> {true,1};
  1372. is_var('$2') -> {true,2};
  1373. is_var('$3') -> {true,3};
  1374. is_var('$4') -> {true,4};
  1375. is_var('$5') -> {true,5};
  1376. is_var('$6') -> {true,6};
  1377. is_var('$7') -> {true,7};
  1378. is_var('$8') -> {true,8};
  1379. is_var('$9') -> {true,9};
  1380. is_var(X) when is_atom(X) ->
  1381. case atom_to_list(X) of
  1382. "$" ++ Tl ->
  1383. try N = list_to_integer(Tl),
  1384. {true,N}
  1385. catch
  1386. error:_ ->
  1387. false
  1388. end;
  1389. _ ->
  1390. false
  1391. end;
  1392. is_var(_) -> false.
  1393. rewrite(Gs, R) ->
  1394. [rewrite1(G, R) || G <- Gs].
  1395. rewrite1('$_', _) ->
  1396. obj_prod();
  1397. rewrite1('$$', _) ->
  1398. obj_prod_l();
  1399. rewrite1(Guard, R) when is_tuple(Guard) ->
  1400. list_to_tuple([rewrite1(G, R) || G <- tuple_to_list(Guard)]);
  1401. rewrite1(Exprs, R) when is_list(Exprs) ->
  1402. [rewrite1(E, R) || E <- Exprs];
  1403. rewrite1(V, R) when is_atom(V) ->
  1404. case is_var(V) of
  1405. {true,_N} ->
  1406. case lists:keysearch(V, 1, R) of
  1407. {value, {_, V1}} ->
  1408. V1;
  1409. false ->
  1410. V
  1411. end;
  1412. false ->
  1413. V
  1414. end;
  1415. rewrite1(Expr, _) ->
  1416. Expr.
  1417. %% @spec (Context::context()) -> any()
  1418. %%
  1419. %% @doc
  1420. %% @equiv table(Context, [])
  1421. %% @end
  1422. %%
  1423. table(Context) ->
  1424. table(Context, []).
  1425. %% @spec (Context::context(), Opts) -> any()
  1426. %%
  1427. %% @doc QLC table generator for the gproc registry.
  1428. %% Context specifies which subset of the registry should be queried.
  1429. %% See [http://www.erlang.org/doc/man/qlc.html].
  1430. %% @end
  1431. table(Context, Opts) ->
  1432. Ctxt = {_, Type} = get_s_t(Context),
  1433. [Traverse, NObjs] = [proplists:get_value(K,Opts,Def) ||
  1434. {K,Def} <- [{traverse,select}, {n_objects,100}]],
  1435. TF = case Traverse of
  1436. first_next ->
  1437. fun() -> qlc_next(Ctxt, first(Ctxt)) end;
  1438. last_prev -> fun() -> qlc_prev(Ctxt, last(Ctxt)) end;
  1439. select ->
  1440. fun(MS) -> qlc_select(select(Ctxt, MS, NObjs)) end;
  1441. {select,MS} ->
  1442. fun() -> qlc_select(select(Ctxt, MS, NObjs)) end;
  1443. _ ->
  1444. erlang:error(badarg, [Ctxt,Opts])
  1445. end,
  1446. InfoFun = fun(indices) -> [2];
  1447. (is_unique_objects) -> is_unique(Type);
  1448. (keypos) -> 1;
  1449. (is_sorted_key) -> true;
  1450. (num_of_objects) ->
  1451. %% this is just a guesstimate.
  1452. trunc(ets:info(?TAB,size) / 2.5)
  1453. end,
  1454. LookupFun =
  1455. case Traverse of
  1456. {select, _MS} -> undefined;
  1457. _ -> fun(Pos, Ks) -> qlc_lookup(Ctxt, Pos, Ks) end
  1458. end,
  1459. qlc:table(TF, [{info_fun, InfoFun},
  1460. {lookup_fun, LookupFun}] ++ [{K,V} || {K,V} <- Opts,
  1461. K =/= traverse,
  1462. K =/= n_objects]).
  1463. qlc_lookup(_Scope, 1, Keys) ->
  1464. lists:flatmap(
  1465. fun(Key) ->
  1466. ets:select(?TAB, [{ {{Key,'_'},'_','_'}, [],
  1467. [{{ {element,1,{element,1,'$_'}},
  1468. {element,2,'$_'},
  1469. {element,3,'$_'} }}] }])
  1470. end, Keys);
  1471. qlc_lookup(Scope, 2, Pids) ->
  1472. lists:flatmap(fun(Pid) ->
  1473. Found =
  1474. ets:select(?TAB, [{ {{Pid, rev_keypat(Scope)}, r},
  1475. [], ['$_']}]),
  1476. lists:flatmap(
  1477. fun({{_,{T,_,_}=K}, r}) ->
  1478. K2 = if T==n orelse T==a -> T;
  1479. true -> Pid
  1480. end,
  1481. case ets:lookup(?TAB, {K,K2}) of
  1482. [{{Key,_},_,Value}] ->
  1483. [{Key, Pid, Value}];
  1484. [] ->
  1485. []
  1486. end
  1487. end, Found)
  1488. end, Pids).
  1489. qlc_next(_, '$end_of_table') -> [];
  1490. qlc_next(Scope, K) ->
  1491. case ets:lookup(?TAB, K) of
  1492. [{{Key,_}, Pid, V}] ->
  1493. [{Key,Pid,V}] ++ fun() -> qlc_next(Scope, next(Scope, K)) end;
  1494. [] ->
  1495. qlc_next(Scope, next(Scope, K))
  1496. end.
  1497. qlc_prev(_, '$end_of_table') -> [];
  1498. qlc_prev(Scope, K) ->
  1499. case ets:lookup(?TAB, K) of
  1500. [{{Key,_},Pid,V}] ->
  1501. [{Key,Pid,V}] ++ fun() -> qlc_prev(Scope, prev(Scope, K)) end;
  1502. [] ->
  1503. qlc_prev(Scope, prev(Scope, K))
  1504. end.
  1505. qlc_select('$end_of_table') ->
  1506. [];
  1507. qlc_select({Objects, Cont}) ->
  1508. Objects ++ fun() -> qlc_select(ets:select(Cont)) end.
  1509. is_unique(n) -> true;
  1510. is_unique(a) -> true;
  1511. is_unique(_) -> false.