Class: Arrow::Session::Lock

Inherits:
Arrow::Object show all
Includes:
PluginFactory
Defined in:
lib/arrow/session/lock.rb

Overview

The Arrow::Session::Lock class, which is the abstract superclass for session lock object classes. Locks are objects which fulfill the locking interface of Arrow::Session, providing a way of serializing access to session data.

To derive your own lock manager classes from this class, you’ll need to follow the following interface:

Derivative Interface ===

Locking is achieved via four methods: #acquire_read_lock, #acquire_write_lock, #release_read_lock, and #release_write_lock. These methods provide the #concurrency for sessions shared between multiple servers. You will probably #also want to provide your own initializer to capture the session’s ID.

#initialize( uri=string, id=Arrow::Session::Id )

#acquire_read_lock

Acquire a shared lock on the session data.

#acquire_write_lock

Acquire an exclusive lock on the session data.

#release_read_lock

  Release a shared lock on the session data.
#release_write_lock

Release an exclusive lock on the session data.

Authors

  • Michael Granger

Please see the file LICENSE in the top-level directory for licensing details.

Direct Known Subclasses

FileLock, NullLock, PosixLock

Constant Summary

UNLOCKED =

Lock status flags

0b00
READ =
0b01
WRITE =
0b10

Class Method Summary

Instance Method Summary

Methods inherited from Arrow::Object

deprecate_class_method, deprecate_method, inherited

Methods included from Arrow::Loggable

#log

Constructor Details

- (Lock) initialize(uri, id)

Create a new Arrow::Session::Lock object.



82
83
84
85
# File 'lib/arrow/session/lock.rb', line 82

def initialize( uri, id )
  super()
  @status = UNLOCKED
end

Class Method Details

+ (Object) create(uri, id)

Create a new Arrow::Session::Lock object for the given id of the type specified by uri.



69
70
71
72
73
# File 'lib/arrow/session/lock.rb', line 69

def self::create( uri, id )
  uri = Arrow::Session.parse_uri( uri ) if
    uri.is_a?( String )
  super( uri.scheme.dup, uri, id )
end

+ (Object) derivativeDirs

Returns the Array of directories to search for derivatives; part of the PluginFactory interface.



62
63
64
# File 'lib/arrow/session/lock.rb', line 62

def self::derivativeDirs
  [ 'arrow/session', 'arrow/session/lock' ]
end

Instance Method Details

- (Object) acquire_read_lock(blocking) (protected)

Interface method for concrete derivatives: acquire a read lock through whatever mechanism is being implemented. If blocking is true, the method should only return if the lock was successfully acquired. If blocking is false, this method should attempt the lock and return false immediately if the lock was not able to the acquired. Concrete implementations should not call super for this method.

Raises:

  • (UnimplementedError)


211
212
213
214
215
# File 'lib/arrow/session/lock.rb', line 211

def acquire_read_lock( blocking )
  raise UnimplementedError,
    "%s does not provide an implementation of #acquire_read_lock." %
    self.class.name
end

- (Object) acquire_write_lock(blocking) (protected)

Interface method for concrete derivatives: acquire a write lock through whatever mechanism is being implemented. If blocking is true, the method should only return if the lock was successfully acquired. If blocking is false, this method should attempt the lock and return false immediately if the lock was not able to the acquired. Concrete implementations should not call super for this method.

Raises:

  • (UnimplementedError)


225
226
227
228
229
# File 'lib/arrow/session/lock.rb', line 225

def acquire_write_lock( blocking )
  raise UnimplementedError,
    "%s does not provide an implementation of #acquire_write_lock." %
    self.class.name
end

- (Object) finish

Indicate to the lock that the caller will no longer be using it, and it may free any resources it had been using.



195
196
197
# File 'lib/arrow/session/lock.rb', line 195

def finish
  self.release_all_locks
end

- (Boolean) locked?

Returns true if the lock object currently holds either a read or write lock.

Returns:

  • (Boolean)


146
147
148
# File 'lib/arrow/session/lock.rb', line 146

def locked?
  (@status & (READ|WRITE)).nonzero?
end

- (Object) read_lock(blocking = true)

Acquire a read (shared) lock. If blocking is false, will return false if the lock was not able to be acquired.



94
95
96
97
98
99
100
101
# File 'lib/arrow/session/lock.rb', line 94

def read_lock( blocking=true )
  return true if self.read_locked?
  self.log.debug "Acquiring read lock"
  self.acquire_read_lock( blocking ) or return false
  @status |= READ
  self.log.debug "Got read lock"
  return true
end

- (Boolean) read_locked?

Returns true if the lock object has acquired a read lock.

Returns:

  • (Boolean)


152
153
154
# File 'lib/arrow/session/lock.rb', line 152

def read_locked?
  (@status & READ).nonzero?
end

- (Object) read_unlock

Give up a read (shared) lock. Raises an exception if no read lock has been acquired.

Raises:

  • (Arrow::LockingError)


165
166
167
168
169
170
171
# File 'lib/arrow/session/lock.rb', line 165

def read_unlock
  raise Arrow::LockingError, "No read lock to release" unless
    self.read_locked?
  self.log.debug "Releasing read lock"
  self.release_read_lock
  @status &= ( @status ^ READ )
end

- (Object) release_all_locks

Release any locks acquired by this lock object.



186
187
188
189
190
# File 'lib/arrow/session/lock.rb', line 186

def release_all_locks
  return false unless self.locked?
  self.write_unlock if self.write_locked?
  self.read_unlock if self.read_locked?
end

- (Object) release_read_lock (protected)

Interface method for concrete derivatives: release a read lock through whatever mechanism is being implemented. Concrete implementations should not call super for this method.

Raises:

  • (UnimplementedError)


235
236
237
238
239
# File 'lib/arrow/session/lock.rb', line 235

def release_read_lock
  raise UnimplementedError,
    "%s does not provide an implementation of #release_read_lock." %
    self.class.name
end

- (Object) release_write_lock (protected)

Interface method for concrete derivatives: release a write lock through whatever mechanism is being implemented. Concrete implementations should not call super for this method.

Raises:

  • (UnimplementedError)


245
246
247
248
249
# File 'lib/arrow/session/lock.rb', line 245

def release_write_lock
  raise UnimplementedError,
    "%s does not provide an implementation of #release_write_lock." %
    self.class.name
end

- (Object) with_read_lock(blocking = true)

Execute the given block after obtaining a read lock, and give up the lock when the block returns. If blocking is false, will raise an Errno::EAGAIN error without calling the block if the lock cannot be immediately established.



120
121
122
123
124
125
126
127
# File 'lib/arrow/session/lock.rb', line 120

def with_read_lock( blocking=true )
  begin
    self.read_lock( blocking ) or raise Errno::EAGAIN
    yield
  ensure
    self.release_read_lock
  end
end

- (Object) with_write_lock(blocking = true)

Execute the given block after obtaining a write lock, and give up the lock when the block returns. If blocking is false, will raise an Errno::EAGAIN error without calling the block if the lock cannot be immediately established.



134
135
136
137
138
139
140
141
# File 'lib/arrow/session/lock.rb', line 134

def with_write_lock( blocking=true )
  begin
    self.write_lock( blocking ) or raise Errno::EAGAIN
    yield
  ensure
    self.release_write_lock
  end
end

- (Object) write_lock(blocking = true)

Acquire a write (exclusive) lock. If blocking is false, will return false if the lock was not able to be acquired.



106
107
108
109
110
111
112
113
# File 'lib/arrow/session/lock.rb', line 106

def write_lock( blocking=true )
  return true if self.write_locked?
  self.log.debug "Acquiring write lock"
  self.acquire_write_lock( blocking ) or return false
  @status |= WRITE
  self.log.debug "Got write lock"
  return true
end

- (Boolean) write_locked?

Returns true if the lock object has acquired a write lock.

Returns:

  • (Boolean)


158
159
160
# File 'lib/arrow/session/lock.rb', line 158

def write_locked?
  (@status & WRITE).nonzero?
end

- (Object) write_unlock

Release a write (exclusive) lock. Raises an exception if no write lock has been acquired.

Raises:

  • (Arrow::LockingError)


176
177
178
179
180
181
182
# File 'lib/arrow/session/lock.rb', line 176

def write_unlock
  raise Arrow::LockingError, "No write lock to release" unless
    self.write_locked?
  self.log.debug "Releasing write lock"
  self.release_write_lock
  @status &= ( @status ^ WRITE )
end