lib/sup/interactive_lock.rb (2664B) - raw
1 require 'fileutils'
2
3 module Redwood
4
5 ## wrap a nice interactive layer on top of anything that has a #lock method
6 ## which throws a LockError which responds to #user, #host, #mtim, #pname, and
7 ## #pid.
8
9 module InteractiveLock
10 def pluralize number_of, kind; "#{number_of} #{kind}" + (number_of == 1 ? "" : "s") end
11
12 def time_ago_in_words time
13 secs = (Time.now - time).to_i
14 mins = secs / 60
15 time = if mins == 0
16 pluralize secs, "second"
17 else
18 pluralize mins, "minute"
19 end
20 end
21
22 DELAY = 5 # seconds
23
24 def lock_interactively stream=$stderr
25 begin
26 Index.lock
27 rescue Index::LockError => e
28 begin
29 Process.kill 0, e.pid.to_i # 0 signal test the existence of PID
30 stream.puts <<EOS
31 Error: the index is locked by another process! User '#{e.user}' on
32 host '#{e.host}' is running #{e.pname} with pid #{e.pid}.
33 The process was alive as of at least #{time_ago_in_words e.mtime} ago.
34
35 EOS
36 stream.print "Should I ask that process to kill itself (y/n)? "
37 stream.flush
38 if $stdin.gets =~ /^\s*y(es)?\s*$/i
39 Process.kill "TERM", e.pid.to_i
40 sleep DELAY
41 stream.puts "Let's try that again."
42 begin
43 Index.lock
44 rescue Index::LockError => e
45 stream.puts "I couldn't lock the index. The lockfile might just be stale."
46 stream.print "Should I just remove it and continue? (y/n) "
47 stream.flush
48 if $stdin.gets =~ /^\s*y(es)?\s*$/i
49 begin
50 FileUtils.rm e.path
51 rescue Errno::ENOENT
52 stream.puts "The lockfile doesn't exists. We continue."
53 end
54 stream.puts "Let's try that one more time."
55 begin
56 Index.lock
57 rescue Index::LockError => e
58 stream.puts "I couldn't unlock the index."
59 return false
60 end
61 return true
62 end
63 end
64 end
65 rescue Errno::ESRCH # no such process
66 stream.puts "I couldn't lock the index. The lockfile might just be stale."
67 begin
68 FileUtils.rm e.path
69 rescue Errno::ENOENT
70 stream.puts "The lockfile doesn't exists. We continue."
71 end
72 stream.puts "Let's try that one more time."
73 begin
74 sleep DELAY
75 Index.lock
76 rescue Index::LockError => e
77 stream.puts "I couldn't unlock the index."
78 return false
79 end
80 return true
81 end
82 stream.puts "Sorry, couldn't unlock the index."
83 return false
84 end
85 return true
86 end
87 end
88
89 end