Class: Arrow::Session::FileLock

Inherits:
Lock show all
Defined in:
lib/arrow/session/filelock.rb

Overview

The Arrow::Session::FileLock class, a derivative of Arrow::Session::Lock. Instances of this class provide file-based locking for Arrow sessions using the flock(2) system call. It (obviously) won’t work on platforms which don’t support flock(2), or on filesystems which don’t provide flock-based locking semantics (e.g., NFS).

Authors

  • Michael Granger

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

Constant Summary

DefaultLockDir =

The path to the default lockdir

'/tmp'
LockfileFormat =

The format string that will be used for the name of the lock file. The first ’%s’ will be replaced with a sanitized version of the session id.

"arrow-session-%s.lock"
FileMode =

The mode to open the lockfile in

File::RDWR|File::CREAT

Constants inherited from Lock

READ, UNLOCKED, WRITE

Instance Attribute Summary

Class Method Summary

Instance Method Summary

Methods inherited from Lock

create, derivativeDirs, #locked?, #read_lock, #read_locked?, #read_unlock, #release_all_locks, #with_read_lock, #with_write_lock, #write_lock, #write_locked?, #write_unlock

Methods inherited from Arrow::Object

deprecate_class_method, deprecate_method, inherited

Methods included from Arrow::Loggable

#log

Constructor Details

- (FileLock) initialize(uri, id)

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



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/arrow/session/filelock.rb', line 69

def initialize( uri, id )
  @lockDir = uri.path || DefaultLockDir
  super

  # 'foo de barg blag 0x1f2eca'.gsub( /\W/, '_' ) 
  #  => foo_de_barg_blag_0x1f2eca
  lockfilename = LockfileFormat % id.to_s.gsub( /\W/, '_' )
  File.mkpath( @lockDir )
  @filename = File.join( @lockDir, lockfilename ).untaint
  @lockfile = nil
end

Instance Attribute Details

- (Object) lockDir

The path to the directory where session lockfiles are kept.



87
88
89
# File 'lib/arrow/session/filelock.rb', line 87

def lockDir
  @lockDir
end

Class Method Details

+ (Object) clean(directory = DefaultLockDir, threshold = 3600)

Clean the specified directory of lock files older than threshold seconds.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/arrow/session/filelock.rb', line 39

def self::clean( directory=DefaultLockDir, threshold=3600 )
  pat = File.join( directory, LockfileFormat.gsub(/%s/, '*') )
  threshold = Time.now - threshold
  Dir[ pat ].each do |file|
    if File.mtime( file ) < threshold
      Arrow::Logger[self].info \
        "Removing stale lockfile '%s'" % file
      begin
        fh = File.open( file, FileMode )
        fh.flock( File::LOCK_EX|File::LOCK_NB )
        File.delete( file )
        fh.flock( File::LOCK_UN )
        fh.close
      rescue => err
        Arrow::Logger[self].warning \
          "Could not clean up '%s': %s" %
          [ file, err.message ]
        next
      end
    end
  end
end

Instance Method Details

- (Object) acquire_read_lock(blocking) (protected)

Acquire a read (shared) lock on the lockfile.



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

def acquire_read_lock( blocking )
  flags = File::LOCK_SH
  flags |= File::LOCK_NB if !blocking

  self.lockfile.flock( flags )
end

- (Object) acquire_write_lock(blocking) (protected)

Acquire a write (exclusive) lock on the lockfile.



131
132
133
134
135
136
# File 'lib/arrow/session/filelock.rb', line 131

def acquire_write_lock( blocking )
  flags = File::LOCK_EX
  flags |= File::LOCK_NB if !blocking

  self.lockfile.flock( flags )
end

- (Object) close_lock_file (protected)

Close the lockfile and destroy the File object belonging to this lock.



111
112
113
114
115
116
117
118
# File 'lib/arrow/session/filelock.rb', line 111

def close_lock_file
  if @lockfile
    path = @lockfile.path
    @lockfile.close
    @lockfile = nil
    File.delete( path.untaint ) if File.exist?( path.untaint )
  end
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.



92
93
94
95
# File 'lib/arrow/session/filelock.rb', line 92

def finish
  super
  self.close_lock_file
end

- (Object) lockfile (protected)

Get the File object for the lockfile belonging to this lock, creating it if necessary.



104
105
106
# File 'lib/arrow/session/filelock.rb', line 104

def lockfile
  @lockfile ||= File.open( @filename, FileMode )
end

- (Object) release_read_lock (protected)

Release a previously-acquired read lock.



140
141
142
143
144
145
# File 'lib/arrow/session/filelock.rb', line 140

def release_read_lock
  if !self.write_locked?
    self.lockfile.flock( File::LOCK_UN )
    self.close_lock_file
  end
end

- (Object) release_write_lock (protected)

Release a previously-acquired write lock.



149
150
151
152
153
154
155
156
# File 'lib/arrow/session/filelock.rb', line 149

def release_write_lock
  if self.read_locked?
    self.lockfile.flock( File::LOCK_SH )
  else
    self.lockfile.flock( File::LOCK_UN )
    self.close_lock_file
  end
end