core: Environment#lock is more useful now
This commit is contained in:
parent
32c9707aa1
commit
dc2f729fd3
|
@ -73,7 +73,6 @@ module Vagrant
|
||||||
:cwd => nil,
|
:cwd => nil,
|
||||||
:home_path => nil,
|
:home_path => nil,
|
||||||
:local_data_path => nil,
|
:local_data_path => nil,
|
||||||
:lock_path => nil,
|
|
||||||
:ui_class => nil,
|
:ui_class => nil,
|
||||||
:vagrantfile_name => nil,
|
:vagrantfile_name => nil,
|
||||||
}.merge(opts || {})
|
}.merge(opts || {})
|
||||||
|
@ -99,7 +98,6 @@ module Vagrant
|
||||||
# Set instance variables for all the configuration parameters.
|
# Set instance variables for all the configuration parameters.
|
||||||
@cwd = opts[:cwd]
|
@cwd = opts[:cwd]
|
||||||
@home_path = opts[:home_path]
|
@home_path = opts[:home_path]
|
||||||
@lock_path = opts[:lock_path]
|
|
||||||
@vagrantfile_name = opts[:vagrantfile_name]
|
@vagrantfile_name = opts[:vagrantfile_name]
|
||||||
@ui = opts[:ui_class].new
|
@ui = opts[:ui_class].new
|
||||||
@ui_class = opts[:ui_class]
|
@ui_class = opts[:ui_class]
|
||||||
|
@ -108,7 +106,7 @@ module Vagrant
|
||||||
# runs at a time from {#batch}.
|
# runs at a time from {#batch}.
|
||||||
@batch_lock = Mutex.new
|
@batch_lock = Mutex.new
|
||||||
|
|
||||||
@lock_acquired = false
|
@locks = {}
|
||||||
|
|
||||||
@logger = Log4r::Logger.new("vagrant::environment")
|
@logger = Log4r::Logger.new("vagrant::environment")
|
||||||
@logger.info("Environment initialized (#{self})")
|
@logger.info("Environment initialized (#{self})")
|
||||||
|
@ -341,38 +339,46 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This returns the path which Vagrant uses to determine the location
|
# This acquires a process-level lock with the given name.
|
||||||
# of the file lock. This is specific to each operating system.
|
#
|
||||||
def lock_path
|
# The lock file is held within the data directory of this environment,
|
||||||
@lock_path || tmp_path.join("vagrant.lock")
|
# so make sure that all environments that are locking are sharing
|
||||||
end
|
# the same data directory.
|
||||||
|
#
|
||||||
# This locks Vagrant for the duration of the block passed to this
|
# This will raise Errors::EnvironmentLockedError if the lock can't
|
||||||
# method. During this time, any other environment which attempts
|
# be obtained.
|
||||||
# to lock which points to the same lock file will fail.
|
#
|
||||||
def lock
|
# @param [String] name Name of the lock, since multiple locks can
|
||||||
|
# be held at one time.
|
||||||
|
def lock(name="global", **opts)
|
||||||
# If we don't have a block, then locking is useless, so ignore it
|
# If we don't have a block, then locking is useless, so ignore it
|
||||||
return if !block_given?
|
return if !block_given?
|
||||||
|
|
||||||
# This allows multiple locks in the same process to be nested
|
# This allows multiple locks in the same process to be nested
|
||||||
return yield if @lock_acquired
|
return yield if @locks[name]
|
||||||
|
|
||||||
|
# The path to this lock
|
||||||
|
lock_path = data_dir.join("lock.#{name}.lock")
|
||||||
|
|
||||||
File.open(lock_path, "w+") do |f|
|
File.open(lock_path, "w+") do |f|
|
||||||
# The file locking fails only if it returns "false." If it
|
# The file locking fails only if it returns "false." If it
|
||||||
# succeeds it returns a 0, so we must explicitly check for
|
# succeeds it returns a 0, so we must explicitly check for
|
||||||
# the proper error case.
|
# the proper error case.
|
||||||
raise Errors::EnvironmentLockedError if f.flock(File::LOCK_EX | File::LOCK_NB) === false
|
if f.flock(File::LOCK_EX | File::LOCK_NB) === false
|
||||||
|
raise Errors::EnvironmentLockedError,
|
||||||
|
name: name
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Mark that we have a lock
|
# Mark that we have a lock
|
||||||
@lock_acquired = true
|
@locks[name] = true
|
||||||
|
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
# We need to make sure that no matter what this is always
|
# We need to make sure that no matter what this is always
|
||||||
# reset to false so we don't think we have a lock when we
|
# reset to false so we don't think we have a lock when we
|
||||||
# actually don't.
|
# actually don't.
|
||||||
@lock_acquired = false
|
@locks.delete(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -658,10 +658,9 @@ en:
|
||||||
The download was interrupted by an external signal. It did not
|
The download was interrupted by an external signal. It did not
|
||||||
complete.
|
complete.
|
||||||
environment_locked: |-
|
environment_locked: |-
|
||||||
An instance of Vagrant is already running. Only one instance of Vagrant
|
Vagrant attempted to acquire a lock named '%{name}', but this
|
||||||
may run at any given time to avoid problems with VirtualBox inconsistencies
|
lock is being held by another instance of Vagrant already. Please
|
||||||
occurring. Please wait for the other instance of Vagrant to end and then
|
wait and try again.
|
||||||
try again.
|
|
||||||
environment_non_existent_cwd: |-
|
environment_non_existent_cwd: |-
|
||||||
The working directory for Vagrant doesn't exist! This is the
|
The working directory for Vagrant doesn't exist! This is the
|
||||||
specified working directory:
|
specified working directory:
|
||||||
|
|
Loading…
Reference in New Issue