Class: Chef::RunLock
- Includes:
- Mixin::CreatePath
- Defined in:
- lib/chef/run_lock.rb
Overview
Chef::RunLock
Provides an interface for acquiring and releasing a system-wide exclusive lock.
Used by Chef::Client to ensure only one instance of chef-client (or solo) is modifying the system at a time.
Instance Attribute Summary collapse
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
-
#runlock ⇒ Object
readonly
Returns the value of attribute runlock.
-
#runlock_file ⇒ Object
readonly
Returns the value of attribute runlock_file.
Instance Method Summary collapse
-
#acquire ⇒ Object
Acquire the system-wide lock.
-
#initialize(lockfile) ⇒ RunLock
constructor
- Create a new instance of RunLock === Arguments * :lockfile:
-
the full path to the lockfile.
-
#release ⇒ Object
Release the system-wide lock.
- #save_pid ⇒ Object
-
#test ⇒ Object
Tests and if successful acquires the system-wide lock.
-
#wait ⇒ Object
Waits until acquiring the system-wide lock.
Methods included from Mixin::CreatePath
Constructor Details
#initialize(lockfile) ⇒ RunLock
Create a new instance of RunLock
Arguments
- :lockfile:
-
the full path to the lockfile.
42 43 44 45 46 |
# File 'lib/chef/run_lock.rb', line 42 def initialize(lockfile) @runlock_file = lockfile @runlock = nil @mutex = nil end |
Instance Attribute Details
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
36 37 38 |
# File 'lib/chef/run_lock.rb', line 36 def mutex @mutex end |
#runlock ⇒ Object (readonly)
Returns the value of attribute runlock.
35 36 37 |
# File 'lib/chef/run_lock.rb', line 35 def runlock @runlock end |
#runlock_file ⇒ Object (readonly)
Returns the value of attribute runlock_file.
37 38 39 |
# File 'lib/chef/run_lock.rb', line 37 def runlock_file @runlock_file end |
Instance Method Details
#acquire ⇒ Object
Acquire the system-wide lock. Will block indefinitely if another process already has the lock.
Each call to acquire should have a corresponding call to #release.
The implementation is based on File#flock (see also: flock(2)).
Either acquire() or test() methods should be called in order to get the ownership of run_lock.
57 58 59 |
# File 'lib/chef/run_lock.rb', line 57 def acquire wait unless test end |
#release ⇒ Object
Release the system-wide lock.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/chef/run_lock.rb', line 114 def release if runlock if Chef::Platform.windows? mutex.release else runlock.flock(File::LOCK_UN) end runlock.close # Don't unlink the pid file, if another chef-client was waiting, it # won't be recreated. Better to leave a "dead" pid file than not have # it available if you need to break the lock. reset end end |
#save_pid ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/chef/run_lock.rb', line 104 def save_pid runlock.truncate(0) runlock.rewind # truncate doesn't reset position to 0. runlock.write(Process.pid.to_s) # flush the file fsync flushes the system buffers # in addition to ruby buffers runlock.fsync end |
#test ⇒ Object
Tests and if successful acquires the system-wide lock. Returns true if the lock is acquired, false otherwise.
Either acquire() or test() methods should be called in order to get the ownership of run_lock.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/chef/run_lock.rb', line 67 def test # ensure the runlock_file path exists create_path(File.dirname(runlock_file)) @runlock = File.open(runlock_file,'a+') if Chef::Platform.windows? acquire_win32_mutex else # If we support FD_CLOEXEC, then use it. # NB: ruby-2.0.0-p195 sets FD_CLOEXEC by default, but not # ruby-1.8.7/1.9.3 if Fcntl.const_defined?('F_SETFD') && Fcntl.const_defined?('FD_CLOEXEC') runlock.fcntl(Fcntl::F_SETFD, runlock.fcntl(Fcntl::F_GETFD, 0) | Fcntl::FD_CLOEXEC) end # Flock will return 0 if it can acquire the lock otherwise it # will return false if runlock.flock(File::LOCK_NB|File::LOCK_EX) == 0 true else false end end end |
#wait ⇒ Object
Waits until acquiring the system-wide lock.
94 95 96 97 98 99 100 101 102 |
# File 'lib/chef/run_lock.rb', line 94 def wait runpid = runlock.read.strip.chomp Chef::Log.warn("Chef client #{runpid} is running, will wait for it to finish and then run.") if Chef::Platform.windows? mutex.wait else runlock.flock(File::LOCK_EX) end end |