Class: ZK::Locker::LockerBase
- Inherits:
-
Object
- Object
- ZK::Locker::LockerBase
- Includes:
- Exceptions, ZK::Logging
- 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.
- #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::Logging
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.
133 134 135 |
# File 'lib/zk/locker/locker_base.rb', line 133 def acquirable? raise NotImplementedError end |
#assert ⇒ Object
283 284 285 286 287 288 |
# File 'lib/zk/locker/locker_base.rb', line 283 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.
272 273 274 275 276 277 278 279 280 281 |
# File 'lib/zk/locker/locker_base.rb', line 272 def assert! @mutex.synchronize do raise LockAssertionFailedError, "have not obtained the lock yet" unless locked? raise LockAssertionFailedError, "not connected" unless zk.connected? 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 |
#lock(blocking = false) ⇒ true, ... #lock(opts = {}) ⇒ true, ...
195 196 197 198 199 200 201 202 203 204 |
# File 'lib/zk/locker/locker_base.rb', line 195 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
210 211 212 |
# File 'lib/zk/locker/locker_base.rb', line 210 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!
115 116 117 |
# File 'lib/zk/locker/locker_base.rb', line 115 def locked? synchronize { !!@locked } end |
#unlock ⇒ true, false
There is more than one way you might not "own the lock" see issue #34
145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/zk/locker/locker_base.rb', line 145 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
162 163 164 |
# File 'lib/zk/locker/locker_base.rb', line 162 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 |