Add file mutex util module

This commit is contained in:
sophia 2023-01-13 11:46:00 -08:00
parent 817fbdd2d1
commit b91a5d5576
5 changed files with 53 additions and 18 deletions

View File

@ -6,6 +6,7 @@ require "uri"
require "vagrant/box_metadata" require "vagrant/box_metadata"
require "vagrant/util/downloader" require "vagrant/util/downloader"
require "vagrant/util/file_checksum" require "vagrant/util/file_checksum"
require "vagrant/util/file_mutex"
require "vagrant/util/platform" require "vagrant/util/platform"
module Vagrant module Vagrant
@ -22,10 +23,6 @@ module Vagrant
# file already exists. # file already exists.
RESUME_DELAY = 24 * 60 * 60 RESUME_DELAY = 24 * 60 * 60
# When a box file is being downloaded, identify the download is in progress
# by Vagrant with a mutex file named <box file destination>.<MUTEX_SUFFIX>
MUTEX_SUFFIX = ".lock"
def initialize(app, env) def initialize(app, env)
@app = app @app = app
@logger = Log4r::Logger.new("vagrant::action::builtin::box_add") @logger = Log4r::Logger.new("vagrant::action::builtin::box_add")
@ -482,23 +479,22 @@ module Vagrant
end end
end end
mutex_path = d.destination + MUTEX_SUFFIX
if File.file?(mutex_path)
raise Errors::DownloadAlreadyInProgress,
dest_path: d.destination,
lock_file_path: mutex_path
end
begin begin
File.write(mutex_path, "") mutex_path = d.destination + ".lock"
Util::FileMutex.new(mutex_path).with_lock do
begin
d.download! d.download!
rescue Errors::DownloaderInterrupted rescue Errors::DownloaderInterrupted
# The downloader was interrupted, so just return, because that # The downloader was interrupted, so just return, because that
# means we were interrupted as well. # means we were interrupted as well.
@download_interrupted = true @download_interrupted = true
env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted")) env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
ensure end
File.delete(mutex_path) end
rescue Errors::VagrantLocked
raise Errors::DownloadAlreadyInProgress,
dest_path: d.destination,
lock_file_path: mutex_path
end end
Pathname.new(d.destination) Pathname.new(d.destination)

View File

@ -924,6 +924,10 @@ module Vagrant
error_key(:uploader_interrupted) error_key(:uploader_interrupted)
end end
class VagrantLocked < VagrantError
error_key(:vagrant_locked)
end
class VagrantInterrupt < VagrantError class VagrantInterrupt < VagrantError
error_key(:interrupted) error_key(:interrupted)
end end

View File

@ -20,6 +20,7 @@ module Vagrant
autoload :Experimental, 'vagrant/util/experimental' autoload :Experimental, 'vagrant/util/experimental'
autoload :FileChecksum, 'vagrant/util/file_checksum' autoload :FileChecksum, 'vagrant/util/file_checksum'
autoload :FileMode, 'vagrant/util/file_mode' autoload :FileMode, 'vagrant/util/file_mode'
autoload :FileMutex, 'vagrant/util/file_mutex'
autoload :GuestHosts, 'vagrant/util/guest_hosts' autoload :GuestHosts, 'vagrant/util/guest_hosts'
autoload :GuestInspection, 'vagrant/util/guest_inspection' autoload :GuestInspection, 'vagrant/util/guest_inspection'
autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access' autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'

View File

@ -0,0 +1,29 @@
module Vagrant
module Util
class FileMutex
def initialize(mutex_path)
@mutex_path = mutex_path
end
def with_lock(&block)
lock
block.call
ensure
unlock
end
def lock
if File.file?(@mutex_path)
raise Errors::VagrantLocked,
lock_file_path: @mutex_path
end
File.write(@mutex_path, "")
end
def unlock
File.delete(@mutex_path)
end
end
end
end

View File

@ -1675,6 +1675,11 @@ en:
uploader_interrupted: |- uploader_interrupted: |-
The upload was interrupted by an external signal. It did not The upload was interrupted by an external signal. It did not
complete. complete.
vagrant_locked: |-
The requested Vagrant action is locked. This may be caused
by other Vagrant processes attempting to do a similar action.
Lock file path: %{lock_file_path}
vagrantfile_exists: |- vagrantfile_exists: |-
`Vagrantfile` already exists in this directory. Remove it before `Vagrantfile` already exists in this directory. Remove it before
running `vagrant init`. running `vagrant init`.