Class: Chef::RunLock
- Inherits:
-
Object
- Object
- 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.
- #acquire_lock ⇒ Object
- #create_lock ⇒ Object
-
#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.
45 46 47 48 49 50 |
# File 'lib/chef/run_lock.rb', line 45 def initialize(lockfile) @runlock_file = lockfile @runlock = nil @mutex = nil @runpid = nil end |
Instance Attribute Details
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
39 40 41 |
# File 'lib/chef/run_lock.rb', line 39 def mutex @mutex end |
#runlock ⇒ Object (readonly)
Returns the value of attribute runlock.
38 39 40 |
# File 'lib/chef/run_lock.rb', line 38 def runlock @runlock end |
#runlock_file ⇒ Object (readonly)
Returns the value of attribute runlock_file.
40 41 42 |
# File 'lib/chef/run_lock.rb', line 40 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 and Chef::Config is not set. Otherwise will block for Chef::Config seconds and exit if the lock is not acquired.
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.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/chef/run_lock.rb', line 63 def acquire if timeout_given? begin Timeout.timeout(time_to_wait) do unless test if time_to_wait > 0.0 wait else exit_from_timeout end end end rescue Timeout::Error exit_from_timeout end else wait unless test end end |
#acquire_lock ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/chef/run_lock.rb', line 139 def acquire_lock 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 |
#create_lock ⇒ Object
132 133 134 135 136 |
# File 'lib/chef/run_lock.rb', line 132 def create_lock # ensure the runlock_file path exists create_path(File.dirname(runlock_file)) @runlock = File.open(runlock_file, "a+") end |
#release ⇒ Object
Release the system-wide lock.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/chef/run_lock.rb', line 116 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
106 107 108 109 110 111 112 113 |
# File 'lib/chef/run_lock.rb', line 106 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.
89 90 91 92 |
# File 'lib/chef/run_lock.rb', line 89 def test create_lock acquire_lock end |
#wait ⇒ Object
Waits until acquiring the system-wide lock.
97 98 99 100 101 102 103 104 |
# File 'lib/chef/run_lock.rb', line 97 def wait 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 |