Official API for the 'locks' system.
This module contains the supported interface functions for
await_all_locks/1 | Await the results of all requested locks. |
begin_transaction/0 | Equivalent to begin_transaction([], []). |
begin_transaction/1 | Equivalent to begin_transaction(Objects, []). |
begin_transaction/2 | Starts a transaction agent. |
change_flag/3 | |
end_transaction/1 | Terminates the transaction agent, releasing all locks. |
lock/2 | Equivalent to lock(Agent, OID, write, [node()], all). |
lock/3 | Equivalent to lock(Agent, OID, Mode, [node()], all). |
lock/4 | Equivalent to lock(Agent, OID, Mode, Nodes, all). |
lock/5 | Acquire a lock on object. |
lock_nowait/2 | Equivalent to lock_nowait(Agent, OID, write, [node()], all). |
lock_nowait/3 | Equivalent to lock_nowait(Agent, OID, Mode, [node()], all). |
lock_nowait/4 | Equivalent to lock_nowait(Agent, OID, Mode, Nodes, all). |
lock_objects/2 | Asynchronously locks several objects at once. |
spawn_agent/0 | |
spawn_agent/1 | |
unwatch/2 | Remove a subscription created by watch/2 . |
watch/2 | Subscribe to lock state changes. |
watchers/1 | List the process IDs of watchers of OID on the current node. |
await_all_locks(Agent::agent()) -> lock_result()
Await the results of all requested locks.
This function blocks until all requested locks have been acquired, or it is determined that they cannot be (and the transaction aborts).
The return value is {have_all_locks | have_none, Deadlocks}
,
where Deadlocks
is a list of {OID, Node}
pairs that were either
surrendered or released as a result of an abort triggered by the deadlock
analysis.
begin_transaction() -> {agent(), lock_result()}
Equivalent to begin_transaction([], [])
.
begin_transaction(Objects::objs()) -> {agent(), lock_result()}
Equivalent to begin_transaction(Objects, [])
.
begin_transaction(Objects::objs(), Options::options()) -> {agent(), lock_result()}
Starts a transaction agent.
Valid options are:
{abort_on_deadlock, boolean()}
- default:false
. Normally, when a deadlock is detected, the involved agents will resolve it by one agent surrendering a lock, but this is not always desireable. With this option, agents will abort if a deadlock is detected.{client, pid()}
- defaults toself()
. The agent will accept lock requests only from the designated client.{await_nodes, boolean()}
- default:false
. If nodes required to serve a lock request are off-line, with{await_nodes, false}
, the transaction will abort; with{await_nodes, true}
the transaction will wait for them to return and try to re-acquire the locks.
change_flag(Agent, Option, Bool) -> any()
end_transaction(Agent::pid()) -> ok
Terminates the transaction agent, releasing all locks.
Note that there is no unlock() operation. The way to release locks is to end the transaction.
lock(Agent::agent(), OID::oid()) -> {ok, deadlocks()}
Equivalent to lock(Agent, OID, write, [node()], all)
.
lock(Agent::agent(), OID::oid(), Mode::mode()) -> {ok, deadlocks()}
Equivalent to lock(Agent, OID, Mode, [node()], all)
.
lock(Agent::agent(), OID::oid(), Mode::mode(), Nodes::where()) -> {ok, deadlocks()}
Equivalent to lock(Agent, OID, Mode, Nodes, all)
.
Acquire a lock on object.
This operation requires an active transaction agent
(see begin_transaction/2
).
The object identifier is a non-empty list, where each element represents
a level in a lock tree. For example, in a database Db
, with tables and
objects, object locks could be given as [Db, Table, Key]
, table locks
as [Db, Table]
and schema locks [Db]
.
Mode
can be either read
(shared) or write
(exclusive). If possible,
read locks will be upgraded to write locks when requested. Specifically,
this can be done if no other agent also hold a read lock, and there are
no waiting agents on the lock (directly or indirectly). If the lock cannot
be upgraded, the read lock will be removed and a write lock request will
be inserted in the lock queue.
The lock request is synchronous, and will return when this and all previous
lock requests have been granted. The return value is {ok, Deadlocks}
,
where Deadlocks
is a list of objects that have caused a deadlock.
Equivalent to lock_nowait(Agent, OID, write, [node()], all)
.
Equivalent to lock_nowait(Agent, OID, Mode, [node()], all)
.
Equivalent to lock_nowait(Agent, OID, Mode, Nodes, all)
.
Asynchronously locks several objects at once.
This function is equivalent to repeatedly calling lock_nowait/5
,
essentially:
lists:foreach(
fun({OID, Mode}) -> lock_nowait(Agent, OID, Mode);
({OID, Mode, Nodes}) -> lock_nowait(Agent, OID, Mode, Nodes);
({OID, Mode, Nodes, Req}) -> lock_nowait(Agent,OID,Mode,Nodes,Req)
end, Objects)
spawn_agent() -> {ok, agent()}
unwatch(OID::oid(), Nodes::[node()]) -> ok
Remove a subscription created by watch/2
.
This function removes a subscription created by watch/2
.
watch(OID::oid(), Nodes::[node()]) -> ok
Subscribe to lock state changes.
This function ensures that #lock_info{}
messages are sent for each
lock state change in OID
on Nodes
. The subscription is not
persistent; if a node dies, the knowledge of processes watching locks
on that node will disappear.
watchers(OID::oid()) -> [pid()]
List the process IDs of watchers of OID
on the current node.