Class: ZK::Locker::LockerBase
- Inherits:
-
Object
- Object
- ZK::Locker::LockerBase
- Includes:
- Exceptions, ZK::Logger
- Defined in:
- lib/zk/locker/locker_base.rb
Overview
Common code for the shared and exclusive lock implementations
One thing to note about this implementation is that the API unfortunately does not follow the convention where bang ('!') methods raise exceptions when they fail. This was an oversight on the part of the author, and it may be corrected sometime in the future.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#lock_path ⇒ String
readonly
our absolute lock node path.
Instance Method Summary collapse
-
#acquirable? ⇒ Boolean
- If this instance holds the lock is true we return true (as we have already succeeded in acquiring the lock) * If this instance doesn't hold the lock, we'll do a check on the server to see if there are any participants who hold the lock and would prevent us from acquiring the lock.
- #assert ⇒ Object
-
#assert! ⇒ Object
This is for users who wish to check that the assumption is correct that they actually still hold the lock.
-
#initialize(client, name, root_lock_node = nil) ⇒ LockerBase
constructor
Create a new lock instance.
-
#interrupt! ⇒ Object
interrupt caller blocked on acquring a lock by delegating to ZK::NodeDeletionWatcher#interrupt!.
- #lock(opts = {}) ⇒ true, ...
-
#lock!(opts = {}) ⇒ Object
deprecated
Deprecated.
the use of lock! is deprecated and may be removed or have its semantics changed in a future release
-
#lock_basename ⇒ nil, String
the basename of our lock path.
-
#locked? ⇒ true, false
returns our current idea of whether or not we hold the lock, which does not actually check the state on the server.
- #unlock ⇒ true, false
-
#unlock! ⇒ true, false
deprecated
Deprecated.
the use of unlock! is deprecated and may be removed or have its semantics changed in a future release
-
#with_lock(opts = {}) {|lock| ... } ⇒ Object
block caller until lock is aquired, then yield.
Methods included from ZK::Logger
#logger, wrapped_logger, wrapped_logger=
Constructor Details
#initialize(client, name, root_lock_node = nil) ⇒ LockerBase
Create a new lock instance.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/zk/locker/locker_base.rb', line 48 def initialize(client, name, root_lock_node=nil) @zk = client @root_lock_node = root_lock_node || Locker.default_root_lock_node @path = name @locked = false @waiting = false @lock_path = nil @parent_stat = nil @root_lock_path = "#{@root_lock_node}/#{@path.gsub("/", "__")}" @mutex = Monitor.new @cond = @mutex.new_cond @node_deletion_watcher = nil end |
Instance Attribute Details
#lock_path ⇒ String (readonly)
our absolute lock node path
24 25 26 |
# File 'lib/zk/locker/locker_base.rb', line 24 def lock_path @lock_path end |
Instance Method Details
#acquirable? ⇒ Boolean
It should be obvious, but there is no way to guarantee that between the time this method checks the server and taking any action to acquire the lock, another client may grab the lock before us (or converseley, another client may release the lock). This is simply meant as an advisory, and may be useful in some cases.
- If this instance holds the lock is true we return true (as we have already succeeded in acquiring the lock)
- If this instance doesn't hold the lock, we'll do a check on the server
to see if there are any participants who hold the lock and would
prevent us from acquiring the lock.
- If this instance could acquire the lock we will return true.
- If another client would prevent us from acquiring the lock, we return false.
138 139 140 |
# File 'lib/zk/locker/locker_base.rb', line 138 def acquirable? raise NotImplementedError end |
#assert ⇒ Object
287 288 289 290 291 292 |
# File 'lib/zk/locker/locker_base.rb', line 287 def assert assert! true rescue LockAssertionFailedError false end |
#assert! ⇒ Object
This is for users who wish to check that the assumption is correct that they actually still hold the lock. (check for session interruption, perhaps a lock is obtained in one method and handed to another)
This, unlike #locked? will actually go and check the conditions that constitute "holding the lock" with the server.
277 278 279 280 281 282 283 284 285 |
# File 'lib/zk/locker/locker_base.rb', line 277 def assert! @mutex.synchronize do raise LockAssertionFailedError, "have not obtained the lock yet" unless locked? raise LockAssertionFailedError, "lock_path was #{lock_path.inspect}" unless lock_path raise LockAssertionFailedError, "the lock path #{lock_path} did not exist!" unless zk.exists?(lock_path) raise LockAssertionFailedError, "the parent node was replaced!" unless root_lock_path_same? raise LockAssertionFailedError, "we do not actually hold the lock" unless got_lock? end end |
#interrupt! ⇒ Object
interrupt caller blocked on acquring a lock by delegating to ZK::NodeDeletionWatcher#interrupt!
this does nothing if the watcher is not currently blocked.
301 302 303 304 305 |
# File 'lib/zk/locker/locker_base.rb', line 301 def interrupt! synchronize do @node_deletion_watcher and @node_deletion_watcher.interrupt! end end |
#lock(blocking = false) ⇒ true, ... #lock(opts = {}) ⇒ true, ...
200 201 202 203 204 205 206 207 208 209 |
# File 'lib/zk/locker/locker_base.rb', line 200 def lock(opts={}) return true if @mutex.synchronize { @locked } case opts when TrueClass, FalseClass # old style boolean argument opts = { :wait => opts } end lock_with_opts_hash(opts) end |
#lock!(opts = {}) ⇒ Object
the use of lock! is deprecated and may be removed or have its semantics changed in a future release
delegates to #lock
215 216 217 |
# File 'lib/zk/locker/locker_base.rb', line 215 def lock!(opts={}) lock(opts) end |
#lock_basename ⇒ nil, String
the basename of our lock path
101 102 103 |
# File 'lib/zk/locker/locker_base.rb', line 101 def lock_basename synchronize { lock_path and File.basename(lock_path) } end |
#locked? ⇒ true, false
returns our current idea of whether or not we hold the lock, which does not actually check the state on the server.
The reason for the equivocation around thinking we hold the lock is to contrast our current state and the actual state on the server. If you want to make double-triple certain of the state of the lock, use #assert!
120 121 122 |
# File 'lib/zk/locker/locker_base.rb', line 120 def locked? synchronize { !!@locked } end |
#unlock ⇒ true, false
There is more than one way you might not "own the lock" see issue #34
150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/zk/locker/locker_base.rb', line 150 def unlock rval = false @mutex.synchronize do if @locked logger.debug { "unlocking" } rval = cleanup_lock_path! @locked = false @node_deletion_watcher = nil @cond.broadcast end end rval end |
#unlock! ⇒ true, false
the use of unlock! is deprecated and may be removed or have its semantics changed in a future release
There is more than one way you might not "own the lock" see issue #34
167 168 169 |
# File 'lib/zk/locker/locker_base.rb', line 167 def unlock! unlock end |
#with_lock(opts = {}) {|lock| ... } ⇒ Object
block caller until lock is aquired, then yield
there is no non-blocking version of this method
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/zk/locker/locker_base.rb', line 78 def with_lock(opts={}) if opts[:wait].kind_of?(FalseClass) raise ArgumentError, ":wait cannot be false, with_lock is only used in blocking mode" end opts = { :wait => true }.merge(opts) lock(opts) yield self ensure unlock end |