lockfile 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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__