Module: Bricolage::VacuumLock

Included in:
EmbeddedCodeAPI, PSQLDataSource, PSQLTask
Defined in:
lib/bricolage/vacuumlock.rb

Constant Summary collapse

DEFAULT_VACUUM_LOCK_FILE =
'/tmp/bricolage.vacuum.lock'
DEFAULT_VACUUM_LOCK_TIMEOUT =

60min

3600

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cleanup_vacuum_lockObject



89
90
91
92
93
94
95
96
# File 'lib/bricolage/vacuumlock.rb', line 89

def VacuumLock.cleanup_vacuum_lock
  return unless enable_vacuum_lock?
  path, timeout = vacuum_lock_parameters
  if locking?(path)
    $stderr.puts "remove VACUUM lock by #{Process.pid}"
    FileUtils.rm_f path
  end
end

.create_lockfile_cmdObject



43
44
45
# File 'lib/bricolage/vacuumlock.rb', line 43

def create_lockfile_cmd
  Pathname(__FILE__).parent.parent.parent + 'libexec/create-lockfile'
end

.create_vacuum_lock_file(path, timeout) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/bricolage/vacuumlock.rb', line 60

def create_vacuum_lock_file(path, timeout)
  start_time = Time.now
  begin
    File.open(path, File::WRONLY | File::CREAT | File::EXCL) {|f|
      f.puts "#{Time.now}: created by bricolage [#{Process.pid}]"
    }
  rescue Errno::EEXIST
    if Time.now - start_time > timeout
      raise LockTimeout, "could not create lock file: #{path} (timeout #{timeout} seconds)"
    end
    sleep 1
    retry
  end
end

.enable_vacuum_lock?Boolean

Returns:

  • (Boolean)


7
8
9
# File 'lib/bricolage/vacuumlock.rb', line 7

def enable_vacuum_lock?
  !!ENV['BRICOLAGE_VACUUM_LOCK']
end

.locking?(path) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
101
102
103
104
105
106
# File 'lib/bricolage/vacuumlock.rb', line 98

def VacuumLock.locking?(path)
  # do not check file existance, just read to avoid race condition
  locker_pid = File.read(path).slice(/\[(\d+)\]/, 1).to_i
  $stderr.puts "bricolage_pid: #{$$}, vacuum_locked_by: #{locker_pid}"
  locker_pid == Process.pid
rescue
  $stderr.puts "bricolage_pid: #{$$}, vacuum_locked_by: (none)"
  false
end

.psql_serialize_vacuum_beginObject



23
24
25
26
27
28
29
30
# File 'lib/bricolage/vacuumlock.rb', line 23

def psql_serialize_vacuum_begin
  if enable_vacuum_lock?
    path, timeout = vacuum_lock_parameters
    "\\! #{create_lockfile_cmd} #{path} #{timeout}"
  else
    ';'
  end
end

.psql_serialize_vacuum_endObject



33
34
35
36
37
38
39
40
# File 'lib/bricolage/vacuumlock.rb', line 33

def psql_serialize_vacuum_end
  if enable_vacuum_lock?
    path, timeout = vacuum_lock_parameters
    "\\! rm -f #{path}"
  else
    ';'
  end
end

.serialize_vacuumObject



48
49
50
51
52
53
54
55
56
57
# File 'lib/bricolage/vacuumlock.rb', line 48

def serialize_vacuum
  return yield unless enable_vacuum_lock?
  path, timeout = vacuum_lock_parameters
  create_vacuum_lock_file path, timeout
  begin
    yield
  ensure
    FileUtils.rm_f path
  end
end

.usingObject



76
77
78
79
80
81
82
83
# File 'lib/bricolage/vacuumlock.rb', line 76

def VacuumLock.using
  return yield unless enable_vacuum_lock?
  begin
    yield
  ensure
    cleanup_vacuum_lock
  end
end

.vacuum_lock_parametersObject



15
16
17
18
19
20
# File 'lib/bricolage/vacuumlock.rb', line 15

def vacuum_lock_parameters
  return nil unless enable_vacuum_lock?
  path, tm = ENV['BRICOLAGE_VACUUM_LOCK'].split(':', 2)
  timeout = tm ? [tm.to_i, 1].max : DEFAULT_VACUUM_LOCK_TIMEOUT
  return path, timeout
end

Instance Method Details

#using_vacuum_lock(&block) ⇒ Object



85
86
87
# File 'lib/bricolage/vacuumlock.rb', line 85

def using_vacuum_lock(&block)
  VacuumLock.using(&block)
end