lib/zfs_mgmt.rb in zfs_mgmt-0.4.7 vs lib/zfs_mgmt.rb in zfs_mgmt-0.4.8

- old
+ new

@@ -6,10 +6,11 @@ require 'date' require 'logger' require 'text-table' require 'open3' require 'filesize' +require 'timeout' $logger = Logger.new(STDERR, progname: 'zfs_mgmt') $date_patterns = { 'hourly' => '%F Hour %H', @@ -35,10 +36,12 @@ $properties_xlate = { 'userrefs' => ->(x) { x.to_i }, 'creation' => ->(x) { x.to_i }, } +$lock = nil + module ZfsMgmt class << self attr_accessor :global_options end class ZfsGetError < StandardError @@ -684,8 +687,44 @@ unless props['zfsmgmt:destination'] $logger.error("#{zfs}: you must specify a destination zfs path via the user property zfsmgmt:destination, even if using --destination on the command line, skipping") next end zfs_send(options,zfs,props,snaps) + end + end + def self.lock(options) + # open lock file, try to lock file until lock_wait has expired or + # lock is obtained, write pid? + return nil unless options[:lock] + begin + lock = File.open(options[:lock_file], File::RDWR|File::CREAT, 0644) + rescue Errno::ENOENT => error + $logger.error("unable to open lock file (#{options[:lock_file]}), possibly the directory doesn't exist") + raise + end + if options[:lock_wait] > 0 + begin + status = Timeout::timeout(options[:lock_wait]) do + return lock if lock.flock(File::LOCK_EX) + $logger.error("flock of #{options[:lock_file]} failed") + raise "flock failed" + end + rescue Timeout::Error => error + $logger.error("timed out waiting to lock") + raise + end + else + # zero is wait forever! + return lock if lock.flock(File::LOCK_EX) + $logger.error("flock of #{options[:lock_file]} failed") + raise "flock failed" + end + $logger.error("unable to obtain lock") + raise "unknown failure in locking file" + end + def self.unlock(lock) + unless lock.nil? + lock.flock(File::LOCK_UN) + lock.close() end end end