lockfile 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/rlock CHANGED
@@ -1,46 +1,50 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  #
4
- # builtin
3
+ # built-in
5
4
  #
6
- require 'rbconfig'
7
- major, minor, teeny = %w(MAJOR MINOR TEENY).map{|k| Config::CONFIG[k].to_i}
8
- unless major >= 1 and minor >= 8
9
- STDERR.puts "ruby-1.8.0 or greater is required, you are running <ruby-#{ major }.#{ minor }.#{ teeny }>"
10
- STDERR.puts "check your PATH setting or install ruby-1.8.0 or greater"
11
- exit 1
12
- end
13
5
  require 'optparse'
14
6
  require 'logger'
15
- require 'yaml'
16
- require 'pp'
17
-
18
7
  #
19
- # RAA
8
+ # http://raa.ruby-lang.org/project/lockfile/
20
9
  #
21
- require 'lockfile.rb'
10
+ require 'lockfile-1.3.0.rb'
22
11
 
23
12
  class Main
24
- #{{{
25
- VERSION = '0.0.0'
26
- PROGNAM = File.basename(File.expand_path($0))
13
+ #--{{{
14
+ VERSION = Lockfile::VERSION
27
15
 
28
16
  USAGE =
29
- #{{{
17
+ #--{{{
30
18
  <<-usage
31
19
  NAME
32
- #{ PROGNAM } v#{ VERSION }
20
+ rlock v#{ VERSION }
33
21
 
34
22
  SYNOPSIS
35
- #{ PROGNAM } [options]+ file.lock [program [-- [options]+] [args]+]
23
+ rlock [options]+ lockfile [program [args]+ | -- program options+ [args]+]
36
24
 
37
25
  DESCRIPTTION
38
- #{ PROGNAM } creates NFS resistent lockfiles
26
+ rlock creates NFS safe lockfiles. it can optionally run a program while
27
+ holding the lock, ensuring lockfile removal on program exit. if a program
28
+ is specified to be run rlock will spawn a background thread to kept the
29
+ lockfile 'fresh' by touching it at a regular interval. in this way a lease
30
+ is maintained on the lockfile and other processes attempting to obtain the
31
+ lock can determine that it is in use. see the '--refresh' option for how to
32
+ control the touch interval. any other process trying to obtain a lock will
33
+ automatically remove a stale lockfile; a stale lockfile is one that is older
34
+ than a certain age. this age be controled via the '--max_age' option.
39
35
 
40
36
  ENVIRONMENT
41
- LOCKFILE_DEBUG=1 will show internal actions of the library
37
+ LOCKFILE_DEBUG=1
38
+ causes internal actions of the library to be shown on STDERR
42
39
 
43
40
  DIAGNOSTICS
41
+ rlock attempts to exit with the status of 'program' except where it
42
+ cannot due to exceptional conditions. in addition the message
43
+
44
+ 'RLOCK SUBCOMMAND FAILURE'
45
+
46
+ will be printed on STDERR if 'program' exits with non-zero status.
47
+
44
48
  success => $? == 0
45
49
  failure => $? != 0
46
50
 
@@ -48,68 +52,78 @@
48
52
  ara.t.howard@noaa.gov
49
53
 
50
54
  BUGS
51
- > 1
55
+ 1 < bugno && bugno < 42
52
56
 
53
57
  OPTIONS
54
58
  usage
55
- #}}}
59
+ #--}}}
56
60
 
57
61
  EXAMPLES =
58
- #{{{
62
+ #--{{{
59
63
  <<-examples
60
64
  EXAMPLES
61
65
 
62
- 0) simple usage - just create a file.lock in an atomic fashion
66
+ 0) simple usage - create lockfile in an atomic fashion (obtain a lock)
63
67
 
64
- ~ > #{ PROGNAM } file.lock
68
+ ~ > rlock lockfile
65
69
 
66
- 1) safe usage - create a file.lock, execute a command, and remove file.lock
70
+ 1) safe usage - create a lockfile, execute a command, and remove lockfile
67
71
 
68
- ~ > #{ PROGNAM } file.lock ls file.lock
72
+ ~ > rlock lockfile ls lockfile
69
73
 
70
74
  2) same as above, but logging verbose messages
71
75
 
72
- ~ > #{ PROGNAM } -v4 file.lock ls file.lock
76
+ ~ > rlock -v4 lockfile ls lockfile
73
77
 
74
- 3) same as above, but logging verbose messages and showing actions internal to
75
- lockfile library
78
+ 3) same as above, but logging verbose messages and showing actions internal
79
+ to lockfile library
76
80
 
77
- ~ > #{ PROGNAM } -v4 -d file.lock ls file.lock
81
+ ~ > rlock -v4 -d lockfile ls lockfile
78
82
 
79
83
  4) same as above
80
84
 
81
- ~ > LOCKFILE_DEBUG=1 #{ PROGNAM } -v4 file.lock ls file.lock
85
+ ~ > LOCKFILE_DEBUG=1 rlock -v4 lockfile ls lockfile
82
86
 
83
87
  5) same as above
84
88
 
85
89
  ~ > export LOCKFILE_DEBUG=1
86
- ~ > #{ PROGNAM } -v4 file.lock ls file.lock
90
+ ~ > rlock -v4 lockfile ls lockfile
91
+
92
+ 6) you need to tell the option parser to stop parsing rlock options if you
93
+ intend to pass options to 'program'
94
+
95
+ ~ > rlock -v4 -d lockfile -- ls -ltar lockfile
96
+
97
+ without the '--' rlock would consume the '-ltar' option as one of
98
+ it's own.
87
99
 
88
- 6) note that you need to tell the option parser to stop parsing #{ PROGNAM }
89
- options if you intend to pass options to 'program'
100
+ 7) lock lockfile and exec 'program' - remove the lockfile if it is older
101
+ than 4242 seconds
90
102
 
91
- ~ > #{ PROGNAM } -v4 -d file.lock -- ls -ltar file.lock
103
+ ~ > rlock --max_age=4242 lockfile program
92
104
 
93
- without the '--' #{ PROGNAM } would consume the '-ltar' options, parsing it
94
- as the logfile name 'tar'
105
+ 8) lock lockfile and exec 'program' - remove the lockfile if it is older
106
+ than 4242 seconds, set the refresh rate to be 8 seconds.
95
107
 
96
- 7) lock file.lock and exec 'program' - remove the file.lock if it is older
97
- than 4242 seconds
108
+ ~ > rlock --max_age=4242 --refresh=8 lockfile program
98
109
 
99
- ~ > #{ PROGNAM } --max_age=4242 file.lock program
110
+ 9) same as above, but fail if lockfile cannot be obtained within 1 minute
100
111
 
101
- 8) lock file.lock and exec 'program' - remove the file.lock if it is older
102
- than 4242 seconds, also spawn a background thread which will refresh
103
- file.lock every 8 seonds will 'program' is executing
112
+ ~ > rlock --max_age=4242 --refresh=8 --timeout=60 lockfile program
104
113
 
105
- ~ > #{ PROGNAM } --max_age=4242 --refresh=8 file.lock program
114
+ 10) lockfile creation involves making some temporary files. normally these
115
+ are cleaned up unless rlock is killed with 'kill -9'. these temp files are
116
+ normally 'sweeped' - searched for and removed - unless the '--dont_sweep'
117
+ option is given. note that sweeping can remove ONLY old temp files created
118
+ by the same host since there is otherwise no way to tell if the offending
119
+ process is still running.
106
120
 
107
- 9) same as above, but fail if file.lock cannot be obtained within 1 minute
121
+ lock lockfile and run program - do not do any sweeping
108
122
 
109
- ~ > #{ PROGNAM } --max_age=4242 --refresh=8 --timeout=60 file.lock program
123
+ ~ > rlock --dont_sweep lockfile program
110
124
 
111
125
  examples
112
- #}}}
126
+ #--}}}
113
127
 
114
128
  EXIT_SUCCESS = 0
115
129
  EXIT_FAILURE = 1
@@ -119,16 +133,24 @@
119
133
  attr :logger
120
134
  attr :config
121
135
 
122
- def initialize argv = cp(ARGV)
123
- #{{{
124
- @argv = argv
136
+ def initialize argv = ARGV
137
+ #--{{{
138
+ @argv = mcp argv
125
139
  parse_opts
140
+ if @opt_version
141
+ puts Main::VERSION
142
+ exit EXIT_SUCCESS
143
+ end
144
+ if @opt_help
145
+ usage
146
+ exit EXIT_SUCCESS
147
+ end
126
148
  parse_argv
127
- #}}}
149
+ run
150
+ #--}}}
128
151
  end
129
152
  def run
130
- #{{{
131
- usage and exit EXIT_SUCCESS if @opt_help
153
+ #--{{{
132
154
  init_logging
133
155
 
134
156
  debug{ "lockpath <#{ @lockpath }>" }
@@ -154,7 +176,7 @@
154
176
  case @argv.size
155
177
  when 0
156
178
  opts['dont_clean'] = true
157
- logger.debug{ "opts <#{ pretty opts }>" }
179
+ logger.debug{ "opts <#{ opts.inspect }>" }
158
180
  logger.debug{ "aquiring lock <#{ @lockpath }>..." }
159
181
  #
160
182
  # simple usage - just create the lockfile with opts
@@ -164,27 +186,35 @@
164
186
 
165
187
  logger.debug{ "aquired lock <#{ @lockpath }>" }
166
188
  else
167
- logger.debug{ "opts <#{ pretty opts }>" }
189
+ logger.debug{ "opts <#{ opts.inspect }>" }
168
190
  logger.debug{ "aquiring lock <#{ @lockpath }>..." }
169
191
  #
170
192
  # block usage - create the lockfile with opts, run block, rm lockfile
171
193
  #
194
+ status = 1
195
+
172
196
  lockfile = ::Lockfile.new @lockpath, opts
197
+
173
198
  lockfile.lock do
174
199
  logger.debug{ "aquired lock <#{ @lockpath }>" }
175
- cmd = @argv.join ' '
176
- logger.debug{ "cmd <#{ cmd }>" }
200
+ logger.debug{ "cmd <#{ @argv.join ' ' }>" }
177
201
  v = nil
178
202
  begin
179
203
  v = $VERBOSE
180
204
  $VERBOSE = nil
181
- system cmd
205
+ STDOUT.flush
206
+ STDERR.flush
207
+ fork{ exec(*@argv) }
208
+ pid, status = Process::wait2
182
209
  ensure
183
210
  $VERBOSE = v
184
211
  end
185
212
  logger.debug{ "status <#{ $? }>" }
186
213
  end
187
- exit $?
214
+
215
+ status = status.exitstatus
216
+ STDERR.puts "RLOCK SUBCOMMAND FAILURE" unless status == 0
217
+ exit status
188
218
  end
189
219
  rescue => e
190
220
  logger.fatal{ e }
@@ -192,44 +222,25 @@
192
222
  end
193
223
 
194
224
  exit EXIT_SUCCESS
195
- #}}}
225
+ #--}}}
196
226
  end
197
227
  def parse_opts
198
- #{{{
199
- @op = OptionParser.new
228
+ #--{{{
229
+ @op = OptionParser::new
200
230
  @op.banner = ''
201
231
  define_options
202
- #begin
203
- @op.parse! argv
204
- #rescue OptionParser::InvalidOption => e
205
- # preverve unknown options
206
- #e.recover(argv)
207
- #rescue Exception => e
208
- #STDERR.puts PROGNAM
209
- #STDERR.puts @op
210
- #exit 2
211
- #end
212
-
213
- #}}}
232
+ @op.parse! argv
233
+
234
+ #--}}}
214
235
  end
215
236
  def parse_argv
216
- #{{{
237
+ #--{{{
217
238
  usage and exit EXIT_FAILURE if @argv.empty?
218
239
  @lockpath = @argv.shift
219
- #}}}
220
- end
221
- def usage io = STDOUT
222
- #{{{
223
- io << USAGE
224
- io << "\n"
225
- io << @op
226
- io << "\n"
227
- io << EXAMPLES if defined? EXAMPLES
228
- self
229
- #}}}
240
+ #--}}}
230
241
  end
231
242
  def define_options
232
- #{{{
243
+ #--{{{
233
244
  options = [
234
245
  ['--retries=n','-r', "default(#{ Lockfile.retries.inspect }) - (nil => forever)"],
235
246
  ['--max_age=n','-a', "default(#{ Lockfile.max_age.inspect })"],
@@ -242,7 +253,9 @@
242
253
  ['--debug','-d', "default(#{ Lockfile.debug.inspect })"],
243
254
  ['--poll_retries=n','-R', "default(#{ Lockfile.poll_retries.inspect })"],
244
255
  ['--poll_max_sleep=n','-S', "default(#{ Lockfile.poll_max_sleep.inspect })"],
256
+ ['--dont_sweep','-w', "default(#{ Lockfile.dont_sweep.inspect })"],
245
257
 
258
+ ['--version'],
246
259
  ['--verbosity=0-4|debug|info|warn|error|fatal','-v'],
247
260
  ['--log=path','-l'],
248
261
  ['--log_age=log_age'],
@@ -254,20 +267,20 @@
254
267
  get, set = opt_attr opt
255
268
  @op.def_option(*option){|v| self.send(set, (v or true))}
256
269
  end
257
- #}}}
270
+ #--}}}
258
271
  end
259
272
  %w(debug info warn error fatal).each do |m|
260
273
  eval "def #{ m }(*args,&block);@logger.#{ m }(*args,&block);end"
261
274
  end
262
275
  def init_logging
263
- #{{{
276
+ #--{{{
264
277
  if @opt_log_age
265
278
  @opt_log_age = @opt_log_age.to_i if @opt_log_age =~ /\d/
266
279
  end
267
280
  if @opt_log_size
268
281
  @opt_log_size = @opt_log_size.to_i if @opt_log_size =~ /\d/
269
282
  end
270
- $logger = @logger = Logger.new(@opt_log || $stdout, @opt_log_age, @opt_log_size)
283
+ $logger = @logger = Logger::new(@opt_log || STDERR, @opt_log_age, @opt_log_size)
271
284
 
272
285
  level = nil
273
286
  @opt_verbosity ||= 'info'
@@ -292,11 +305,20 @@
292
305
  abort "illegal verbosity setting <#{ @opt_verbosity }>"
293
306
  end
294
307
  @logger.level = 2 - ((@opt_verbosity % 5) - 2)
295
- debug {"logging level <#{ level }>"}
296
- #}}}
308
+ #--}}}
309
+ end
310
+ def usage io = STDOUT
311
+ #--{{{
312
+ io << USAGE
313
+ io << "\n"
314
+ io << @op
315
+ io << "\n"
316
+ io << EXAMPLES if defined? EXAMPLES
317
+ self
318
+ #--}}}
297
319
  end
298
320
  def opt_attr opt
299
- #{{{
321
+ #--{{{
300
322
  get = "opt_#{ opt }"
301
323
  set = "#{ get }="
302
324
  code = <<-code
@@ -307,20 +329,14 @@
307
329
  code
308
330
  instance_eval code
309
331
  [get, set]
310
- #}}}
332
+ #--}}}
311
333
  end
312
- def cp obj
313
- #{{{
314
- Marshal.load(Marshal.dump(obj))
315
- #}}}
334
+ def mcp obj
335
+ #--{{{
336
+ Marshal::load(Marshal::dump(obj))
337
+ #--}}}
316
338
  end
317
- def pretty obj
318
- #{{{
319
- PP::pp obj, ''
320
- #}}}
321
- end
322
- #}}}
339
+ #--}}}
323
340
  end
324
341
 
325
-
326
- Main.new(ARGV).run if $0 == __FILE__
342
+ Main::new if $0 == __FILE__
data/bin/rlock-1.3.0 ADDED
@@ -0,0 +1,342 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # built-in
4
+ #
5
+ require 'optparse'
6
+ require 'logger'
7
+ #
8
+ # http://raa.ruby-lang.org/project/lockfile/
9
+ #
10
+ require 'lockfile-1.3.0.rb'
11
+
12
+ class Main
13
+ #--{{{
14
+ VERSION = Lockfile::VERSION
15
+
16
+ USAGE =
17
+ #--{{{
18
+ <<-usage
19
+ NAME
20
+ rlock v#{ VERSION }
21
+
22
+ SYNOPSIS
23
+ rlock [options]+ lockfile [program [args]+ | -- program options+ [args]+]
24
+
25
+ DESCRIPTTION
26
+ rlock creates NFS safe lockfiles. it can optionally run a program while
27
+ holding the lock, ensuring lockfile removal on program exit. if a program
28
+ is specified to be run rlock will spawn a background thread to kept the
29
+ lockfile 'fresh' by touching it at a regular interval. in this way a lease
30
+ is maintained on the lockfile and other processes attempting to obtain the
31
+ lock can determine that it is in use. see the '--refresh' option for how to
32
+ control the touch interval. any other process trying to obtain a lock will
33
+ automatically remove a stale lockfile; a stale lockfile is one that is older
34
+ than a certain age. this age be controled via the '--max_age' option.
35
+
36
+ ENVIRONMENT
37
+ LOCKFILE_DEBUG=1
38
+ causes internal actions of the library to be shown on STDERR
39
+
40
+ DIAGNOSTICS
41
+ rlock attempts to exit with the status of 'program' except where it
42
+ cannot due to exceptional conditions. in addition the message
43
+
44
+ 'RLOCK SUBCOMMAND FAILURE'
45
+
46
+ will be printed on STDERR if 'program' exits with non-zero status.
47
+
48
+ success => $? == 0
49
+ failure => $? != 0
50
+
51
+ AUTHOR
52
+ ara.t.howard@noaa.gov
53
+
54
+ BUGS
55
+ 1 < bugno && bugno < 42
56
+
57
+ OPTIONS
58
+ usage
59
+ #--}}}
60
+
61
+ EXAMPLES =
62
+ #--{{{
63
+ <<-examples
64
+ EXAMPLES
65
+
66
+ 0) simple usage - create lockfile in an atomic fashion (obtain a lock)
67
+
68
+ ~ > rlock lockfile
69
+
70
+ 1) safe usage - create a lockfile, execute a command, and remove lockfile
71
+
72
+ ~ > rlock lockfile ls lockfile
73
+
74
+ 2) same as above, but logging verbose messages
75
+
76
+ ~ > rlock -v4 lockfile ls lockfile
77
+
78
+ 3) same as above, but logging verbose messages and showing actions internal
79
+ to lockfile library
80
+
81
+ ~ > rlock -v4 -d lockfile ls lockfile
82
+
83
+ 4) same as above
84
+
85
+ ~ > LOCKFILE_DEBUG=1 rlock -v4 lockfile ls lockfile
86
+
87
+ 5) same as above
88
+
89
+ ~ > export LOCKFILE_DEBUG=1
90
+ ~ > rlock -v4 lockfile ls lockfile
91
+
92
+ 6) you need to tell the option parser to stop parsing rlock options if you
93
+ intend to pass options to 'program'
94
+
95
+ ~ > rlock -v4 -d lockfile -- ls -ltar lockfile
96
+
97
+ without the '--' rlock would consume the '-ltar' option as one of
98
+ it's own.
99
+
100
+ 7) lock lockfile and exec 'program' - remove the lockfile if it is older
101
+ than 4242 seconds
102
+
103
+ ~ > rlock --max_age=4242 lockfile program
104
+
105
+ 8) lock lockfile and exec 'program' - remove the lockfile if it is older
106
+ than 4242 seconds, set the refresh rate to be 8 seconds.
107
+
108
+ ~ > rlock --max_age=4242 --refresh=8 lockfile program
109
+
110
+ 9) same as above, but fail if lockfile cannot be obtained within 1 minute
111
+
112
+ ~ > rlock --max_age=4242 --refresh=8 --timeout=60 lockfile program
113
+
114
+ 10) lockfile creation involves making some temporary files. normally these
115
+ are cleaned up unless rlock is killed with 'kill -9'. these temp files are
116
+ normally 'sweeped' - searched for and removed - unless the '--dont_sweep'
117
+ option is given. note that sweeping can remove ONLY old temp files created
118
+ by the same host since there is otherwise no way to tell if the offending
119
+ process is still running.
120
+
121
+ lock lockfile and run program - do not do any sweeping
122
+
123
+ ~ > rlock --dont_sweep lockfile program
124
+
125
+ examples
126
+ #--}}}
127
+
128
+ EXIT_SUCCESS = 0
129
+ EXIT_FAILURE = 1
130
+
131
+ attr :argv
132
+ attr :op
133
+ attr :logger
134
+ attr :config
135
+
136
+ def initialize argv = ARGV
137
+ #--{{{
138
+ @argv = mcp argv
139
+ parse_opts
140
+ if @opt_version
141
+ puts Main::VERSION
142
+ exit EXIT_SUCCESS
143
+ end
144
+ if @opt_help
145
+ usage
146
+ exit EXIT_SUCCESS
147
+ end
148
+ parse_argv
149
+ run
150
+ #--}}}
151
+ end
152
+ def run
153
+ #--{{{
154
+ init_logging
155
+
156
+ debug{ "lockpath <#{ @lockpath }>" }
157
+
158
+ opts = {}
159
+ options =
160
+ %w(retries max_age sleep_inc min_sleep max_sleep suspend timeout refresh poll_retries poll_max_sleep)
161
+ options.each do |opt|
162
+ if((val = eval("opt_#{ opt }")))
163
+ begin
164
+ opts[opt] = Integer val
165
+ logger.debug{ "<#{ opt }> <#{ val }>" }
166
+ rescue
167
+ logger.fatal{ "illegal value <#{ val.inspect }> for opt <#{ opt }>" }
168
+ exit EXIT_FAILURE
169
+ end
170
+ end
171
+ end
172
+
173
+ opts['debug'] = true if opt_debug
174
+
175
+ begin
176
+ case @argv.size
177
+ when 0
178
+ opts['dont_clean'] = true
179
+ logger.debug{ "opts <#{ opts.inspect }>" }
180
+ logger.debug{ "aquiring lock <#{ @lockpath }>..." }
181
+ #
182
+ # simple usage - just create the lockfile with opts
183
+ #
184
+ lockfile = ::Lockfile.new @lockpath, opts
185
+ lockfile.lock
186
+
187
+ logger.debug{ "aquired lock <#{ @lockpath }>" }
188
+ else
189
+ logger.debug{ "opts <#{ opts.inspect }>" }
190
+ logger.debug{ "aquiring lock <#{ @lockpath }>..." }
191
+ #
192
+ # block usage - create the lockfile with opts, run block, rm lockfile
193
+ #
194
+ status = 1
195
+
196
+ lockfile = ::Lockfile.new @lockpath, opts
197
+
198
+ lockfile.lock do
199
+ logger.debug{ "aquired lock <#{ @lockpath }>" }
200
+ logger.debug{ "cmd <#{ @argv.join ' ' }>" }
201
+ v = nil
202
+ begin
203
+ v = $VERBOSE
204
+ $VERBOSE = nil
205
+ STDOUT.flush
206
+ STDERR.flush
207
+ fork{ exec(*@argv) }
208
+ pid, status = Process::wait2
209
+ ensure
210
+ $VERBOSE = v
211
+ end
212
+ logger.debug{ "status <#{ $? }>" }
213
+ end
214
+
215
+ status = status.exitstatus
216
+ STDERR.puts "RLOCK SUBCOMMAND FAILURE" unless status == 0
217
+ exit status
218
+ end
219
+ rescue => e
220
+ logger.fatal{ e }
221
+ exit EXIT_FAILURE
222
+ end
223
+
224
+ exit EXIT_SUCCESS
225
+ #--}}}
226
+ end
227
+ def parse_opts
228
+ #--{{{
229
+ @op = OptionParser::new
230
+ @op.banner = ''
231
+ define_options
232
+ @op.parse! argv
233
+
234
+ #--}}}
235
+ end
236
+ def parse_argv
237
+ #--{{{
238
+ usage and exit EXIT_FAILURE if @argv.empty?
239
+ @lockpath = @argv.shift
240
+ #--}}}
241
+ end
242
+ def define_options
243
+ #--{{{
244
+ options = [
245
+ ['--retries=n','-r', "default(#{ Lockfile.retries.inspect }) - (nil => forever)"],
246
+ ['--max_age=n','-a', "default(#{ Lockfile.max_age.inspect })"],
247
+ ['--sleep_inc=n','-s', "default(#{ Lockfile.sleep_inc.inspect })"],
248
+ ['--max_sleep=n','-p', "default(#{ Lockfile.max_sleep.inspect })"],
249
+ ['--min_sleep=n','-P', "default(#{ Lockfile.min_sleep.inspect })"],
250
+ ['--suspend=n','-u', "default(#{ Lockfile.suspend.inspect })"],
251
+ ['--timeout=n','-t', "default(#{ Lockfile.timeout.inspect }) - (nil => never)"],
252
+ ['--refresh=n','-f', "default(#{ Lockfile.refresh.inspect })"],
253
+ ['--debug','-d', "default(#{ Lockfile.debug.inspect })"],
254
+ ['--poll_retries=n','-R', "default(#{ Lockfile.poll_retries.inspect })"],
255
+ ['--poll_max_sleep=n','-S', "default(#{ Lockfile.poll_max_sleep.inspect })"],
256
+ ['--dont_sweep','-w', "default(#{ Lockfile.dont_sweep.inspect })"],
257
+
258
+ ['--version'],
259
+ ['--verbosity=0-4|debug|info|warn|error|fatal','-v'],
260
+ ['--log=path','-l'],
261
+ ['--log_age=log_age'],
262
+ ['--log_size=log_size'],
263
+ ['--help','-h'],
264
+ ]
265
+ options.each do |option|
266
+ opt = option.first.gsub(%r/(?:--)|(?:=.*$)/o,'').strip
267
+ get, set = opt_attr opt
268
+ @op.def_option(*option){|v| self.send(set, (v or true))}
269
+ end
270
+ #--}}}
271
+ end
272
+ %w(debug info warn error fatal).each do |m|
273
+ eval "def #{ m }(*args,&block);@logger.#{ m }(*args,&block);end"
274
+ end
275
+ def init_logging
276
+ #--{{{
277
+ if @opt_log_age
278
+ @opt_log_age = @opt_log_age.to_i if @opt_log_age =~ /\d/
279
+ end
280
+ if @opt_log_size
281
+ @opt_log_size = @opt_log_size.to_i if @opt_log_size =~ /\d/
282
+ end
283
+ $logger = @logger = Logger::new(@opt_log || STDERR, @opt_log_age, @opt_log_size)
284
+
285
+ level = nil
286
+ @opt_verbosity ||= 'info'
287
+ @opt_verbosity =
288
+ case @opt_verbosity
289
+ when /^\s*(?:4|d|debug)\s*$/io
290
+ level = 'Logging::DEBUG'
291
+ 4
292
+ when /^\s*(?:3|i|info)\s*$/io
293
+ level = 'Logging::INFO'
294
+ 3
295
+ when /^\s*(?:2|w|warn)\s*$/io
296
+ level = 'Logging::WARN'
297
+ 2
298
+ when /^\s*(?:1|e|error)\s*$/io
299
+ level = 'Logging::ERROR'
300
+ 1
301
+ when /^\s*(?:0|f|fatal)\s*$/io
302
+ level = 'Logging::FATAL'
303
+ 0
304
+ else
305
+ abort "illegal verbosity setting <#{ @opt_verbosity }>"
306
+ end
307
+ @logger.level = 2 - ((@opt_verbosity % 5) - 2)
308
+ #--}}}
309
+ end
310
+ def usage io = STDOUT
311
+ #--{{{
312
+ io << USAGE
313
+ io << "\n"
314
+ io << @op
315
+ io << "\n"
316
+ io << EXAMPLES if defined? EXAMPLES
317
+ self
318
+ #--}}}
319
+ end
320
+ def opt_attr opt
321
+ #--{{{
322
+ get = "opt_#{ opt }"
323
+ set = "#{ get }="
324
+ code = <<-code
325
+ class << self
326
+ def #{ get }; defined?(@#{ get }) ? @#{ get } : nil; end
327
+ def #{ set } value; @#{ get } = value; end
328
+ end
329
+ code
330
+ instance_eval code
331
+ [get, set]
332
+ #--}}}
333
+ end
334
+ def mcp obj
335
+ #--{{{
336
+ Marshal::load(Marshal::dump(obj))
337
+ #--}}}
338
+ end
339
+ #--}}}
340
+ end
341
+
342
+ Main::new if $0 == __FILE__