[erlang-questions] Understanding global:set_lock/1,2,3

jim rosenblum jim.rosenblum@REDACTED
Fri Dec 11 04:30:08 CET 2015


Roberto,

I use global for a very similar use case. I have a distributed, in-memory
cache that uses Mnesia. The first node of the cluster creates the schema,
subsequent nodes add themselves to the alrady created cluster. Thus I have
need to make sure that the test for being the first node and the cluster
creation is protected.

I use global:trans/4.
The first parameter is an id = {resource, PID of lock requestor}
The second is a function which is executed should the lock be acquired
The third parameter indicates which nodes the lock should range over
The fourth indicates how long to wait for the lock.

My code pings all configured node names to try join the mesh of
participating nodes, then it synchronizes with the global name server
across all nodes in the cluster, then locks the 'resource' jc_mnesia' and,
assuming the lock is acquired, executes the function. Any other node that
tries to execute this same code will block until the first node is out of
the function.

Feel free to look at my code (https://github.com/jr0senblum/jc) or email me
with any questions. I *think* this works... it's been in production for a
while... so... there's that....

    ... snip...
    [Node || Node <- Nodes, pong == net_adm:ping(Node) ],
    global:sync(),
    global:trans({jc_mnesia, self()},
fun() ->
mnesia:start(),
case [Node || Node <- nodes(), jc_loaded(Node)] of
    [] -> % No nodes have jc service, this one is first
mnesia:create_schema([]),
dynamic_db_init([]),
Indexes = application:get_env(jc, indexes, []),
[jc_store:start_indexing(Map, Path) ||
    {Map, Path} <- Indexes];
    Ns -> % Not the first node up, join existing cluster
dynamic_db_init(Ns)
end,
true = global:del_lock({jc_mnesia, self()}),
ok
end,
[node() | nodes()],
infinity).



Dear list,
I'm trying to get an understanding of what global:set_lock/1,2,3 exactly
does.

I read from the docs:

Sets a lock on the specified nodes (or on all nodes if none are specified)
on ResourceId for LockRequesterId.


Let's say that I want to perform a series of operations on mnesia schemas
and want to avoid all other nodes accessing mnesia tables while one node is
busy at it.

Is it enough to write:

global:trans({{?MODULE, lock_mnesia_for_a_while}, self()},
    fun() ->
        do_things_on_mnesia()
    end).


I don't get how this could lock mnesia for the other nodes.

Can some kind soul point me in the right direction?

Thank you,
r.

Robert
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20151210/dcb4c205/attachment.htm>


More information about the erlang-questions mailing list