servolux 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # PROJ.ignore_file = '.gitignore'
8
+ #
9
+ # For a project with a C extension, the following would be a good set of
10
+ # exclude patterns (uncomment them if you want to use them):
11
+ # *.[oa]
12
+ *~
13
+ *.sw[op]
14
+ announcement.txt
15
+ coverage
16
+ doc
17
+ pkg
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.7.0 / 2009-11-06
2
+
3
+ * 1 Minor Enhancement
4
+ * Added a permissions mask for the server PID file [Avdi Grimm]
5
+ * 1 Bug Fix
6
+ * Fixing up some development / runtime dependencies
7
+
1
8
  == 0.6.2 / 2009-07-16
2
9
 
3
10
  * 1 Minor Enhancement
data/README.rdoc CHANGED
@@ -1,15 +1,15 @@
1
1
  = Serv-O-Lux
2
2
  * by Tim Pease
3
- * http://github.com/TwP/servolux/tree/master
3
+ * http://gemcutter.org/gems/servolux
4
4
 
5
- === DESCRIPTION:
5
+ === DESCRIPTION
6
6
 
7
7
  Serv-O-Lux is a collection of Ruby classes that are useful for daemon and
8
8
  process management, and for writing your own Ruby services. The code is well
9
9
  documented and tested. It works with Ruby and JRuby supporing both 1.8 and 1.9
10
10
  interpreters.
11
11
 
12
- === FEATURES:
12
+ === FEATURES
13
13
 
14
14
  Servolux::Threaded -- when included into your own class, it gives you an
15
15
  activity thread that will run some code at a regular interval. Provides methods
@@ -34,11 +34,11 @@ signal the child process to die if it does not exit in a given amount of time.
34
34
 
35
35
  All the documentation is available online at http://codeforpeople.rubyforge.org/servolux
36
36
 
37
- === INSTALL:
37
+ === INSTALL
38
38
 
39
39
  gem install servolux
40
40
 
41
- === LICENSE:
41
+ === LICENSE
42
42
 
43
43
  (The MIT License)
44
44
 
data/Rakefile CHANGED
@@ -1,16 +1,8 @@
1
- # Look in the tasks/setup.rb file for the various options that can be
2
- # configured in this Rakefile. The .rake files in the tasks directory
3
- # are where the options are used.
4
1
 
5
2
  begin
6
3
  require 'bones'
7
- Bones.setup
8
4
  rescue LoadError
9
- begin
10
- load 'tasks/setup.rb'
11
- rescue LoadError
12
- raise RuntimeError, '### please install the "bones" gem ###'
13
- end
5
+ abort '### please install the "bones" gem ###'
14
6
  end
15
7
 
16
8
  ensure_in_path 'lib'
@@ -18,24 +10,20 @@ require 'servolux'
18
10
 
19
11
  task :default => 'spec:specdoc'
20
12
 
21
- PROJ.name = 'servolux'
22
- PROJ.authors = 'Tim Pease'
23
- PROJ.email = 'tim.pease@gmail.com'
24
- PROJ.url = 'http://codeforpeople.rubyforge.org/servolux'
25
- PROJ.version = Servolux::VERSION
26
- PROJ.rubyforge.name = 'codeforpeople'
27
- PROJ.exclude << 'servolux.gemspec'
28
- PROJ.readme_file = 'README.rdoc'
29
- PROJ.ignore_file = '.gitignore'
30
- PROJ.rdoc.remote_dir = 'servolux'
13
+ Bones {
14
+ name 'servolux'
15
+ authors 'Tim Pease'
16
+ email 'tim.pease@gmail.com'
17
+ url 'http://gemcutter.org/gems/servolux'
18
+ version Servolux::VERSION
19
+ readme_file 'README.rdoc'
20
+ ignore_file '.gitignore'
31
21
 
32
- PROJ.spec.opts << '--color'
22
+ spec.opts << '--color'
33
23
 
34
- PROJ.ann.email[:server] = 'smtp.gmail.com'
35
- PROJ.ann.email[:port] = 587
36
- PROJ.ann.email[:from] = 'Tim Pease'
24
+ use_gmail
37
25
 
38
- depend_on 'logging'
39
- depend_on 'rspec'
40
-
41
- # EOF
26
+ depend_on 'bones-extras', :development => true
27
+ depend_on 'logging', :development => true
28
+ depend_on 'rspec', :development => true
29
+ }
@@ -68,10 +68,10 @@ class Servolux::Child
68
68
  # a signal before trying the next one in the list.
69
69
  #
70
70
  def initialize( opts = {} )
71
- @command = opts.getopt :command
72
- @timeout = opts.getopt :timeout
73
- @signals = opts.getopt :signals, %w[TERM QUIT KILL]
74
- @suspend = opts.getopt :suspend, 4
71
+ @command = opts[:command]
72
+ @timeout = opts[:timeout]
73
+ @signals = opts[:signals] || %w[TERM QUIT KILL]
74
+ @suspend = opts[:suspend] || 4
75
75
  @io = @pid = @status = @thread = @timed_out = nil
76
76
  yield self if block_given?
77
77
  end
@@ -75,7 +75,7 @@ class Servolux::Daemon
75
75
  StartupError = Class.new(Error)
76
76
 
77
77
  attr_reader :name
78
- attr_writer :logger
78
+ attr_accessor :logger
79
79
  attr_accessor :pid_file
80
80
  attr_reader :startup_command
81
81
  attr_accessor :shutdown_command
@@ -144,20 +144,20 @@ class Servolux::Daemon
144
144
  # is fully started. The default is nil.
145
145
  #
146
146
  def initialize( opts = {} )
147
- self.server = opts.getopt(:server) || opts.getopt(:startup_command)
147
+ self.server = opts[:server] || opts[:startup_command]
148
148
 
149
149
  @name = opts[:name] if opts.key?(:name)
150
150
  @logger = opts[:logger] if opts.key?(:logger)
151
151
  @pid_file = opts[:pid_file] if opts.key?(:pid_file)
152
- @timeout = opts.getopt(:timeout, 30)
153
- @nochdir = opts.getopt(:nochdir, false)
154
- @noclose = opts.getopt(:noclose, false)
155
- @shutdown_command = opts.getopt(:shutdown_command)
152
+ @timeout = opts[:timeout] || 30
153
+ @nochdir = opts[:nochdir] || false
154
+ @noclose = opts[:noclose] || false
155
+ @shutdown_command = opts[:shutdown_command]
156
156
 
157
157
  @piper = nil
158
158
  @logfile_reader = nil
159
- self.log_file = opts.getopt(:log_file)
160
- self.look_for = opts.getopt(:look_for)
159
+ self.log_file = opts[:log_file]
160
+ self.look_for = opts[:look_for]
161
161
 
162
162
  yield self if block_given?
163
163
 
@@ -256,7 +256,7 @@ class Servolux::Daemon
256
256
  wait_for_shutdown
257
257
  end
258
258
 
259
- # Returns +true+ if the daemon processis currently running. Returns
259
+ # Returns +true+ if the daemon process is currently running. Returns
260
260
  # +false+ if this is not the case. The status of the process is determined
261
261
  # by sending a signal to the process identified by the +pid_file+.
262
262
  #
@@ -301,12 +301,6 @@ class Servolux::Daemon
301
301
  end
302
302
  end
303
303
 
304
- # Returns the logger instance used by the daemon to log messages.
305
- #
306
- def logger
307
- @logger ||= Logging.logger[self]
308
- end
309
-
310
304
 
311
305
  private
312
306
 
@@ -121,7 +121,7 @@ class Servolux::Piper
121
121
  raise ArgumentError, "Unsupported mode #{mode.inspect}"
122
122
  end
123
123
 
124
- @timeout = opts.getopt(:timeout, 0)
124
+ @timeout = opts[:timeout] || 0
125
125
  if defined? ::Encoding
126
126
  @read_io, @write_io = IO.pipe('ASCII-8BIT') # encoding for Ruby 1.9
127
127
  else
@@ -129,9 +129,12 @@ class Servolux::Server
129
129
 
130
130
  Error = Class.new(::Servolux::Error)
131
131
 
132
+ DEFAULT_PID_FILE_MODE = 0640
133
+
132
134
  attr_reader :name
133
135
  attr_accessor :logger
134
136
  attr_writer :pid_file
137
+ attr_accessor :pid_file_mode
135
138
 
136
139
  # call-seq:
137
140
  # Server.new( name, options = {} ) { block }
@@ -147,14 +150,13 @@ class Servolux::Server
147
150
  #
148
151
  def initialize( name, opts = {}, &block )
149
152
  @name = name
150
- @activity_thread = nil
151
- @activity_thread_running = false
152
153
  @mutex = Mutex.new
153
154
  @shutdown = nil
154
155
 
155
- self.logger = opts.getopt :logger
156
- self.pid_file = opts.getopt :pid_file
157
- self.interval = opts.getopt :interval, 0
156
+ self.logger = opts[:logger]
157
+ self.pid_file = opts[:pid_file]
158
+ self.pid_file_mode = opts[:pid_file_mode] || DEFAULT_PID_FILE_MODE
159
+ self.interval = opts[:interval] || 0
158
160
 
159
161
  if block
160
162
  eg = class << self; self; end
@@ -246,7 +248,7 @@ class Servolux::Server
246
248
 
247
249
  def create_pid_file
248
250
  logger.debug "Server #{name.inspect} creating pid file #{pid_file.inspect}"
249
- File.open(pid_file, 'w') {|fd| fd.write(Process.pid.to_s)}
251
+ File.open(pid_file, 'w', pid_file_mode) {|fd| fd.write(Process.pid.to_s)}
250
252
  end
251
253
 
252
254
  def delete_pid_file
@@ -1,4 +1,3 @@
1
-
2
1
  # == Synopsis
3
2
  # The Threaded module is used to peform some activity at a specified
4
3
  # interval.
@@ -52,35 +51,11 @@ module Servolux::Threaded
52
51
  # after the thread is created.
53
52
  #
54
53
  def start
55
- return self if running?
54
+ return self if _activity_thread.running?
56
55
  logger.debug "Starting"
57
56
 
58
57
  before_starting if self.respond_to?(:before_starting)
59
- @activity_thread_running = true
60
- @activity_thread_iterations = 0
61
- @activity_thread = Thread.new {
62
- begin
63
- loop {
64
- begin
65
- sleep interval if running?
66
- break unless running?
67
- run
68
- @activity_thread_iterations += 1
69
- break if finished_iterations?
70
- rescue SystemExit; raise
71
- rescue Exception => err
72
- if continue_on_error?
73
- logger.error err
74
- else
75
- logger.fatal err
76
- raise err
77
- end
78
- end
79
- }
80
- ensure
81
- @activity_thread_running = false
82
- end
83
- }
58
+ @_activity_thread.start self
84
59
  after_starting if self.respond_to?(:after_starting)
85
60
  self
86
61
  end
@@ -95,14 +70,11 @@ module Servolux::Threaded
95
70
  # has stopped.
96
71
  #
97
72
  def stop( limit = nil )
98
- return self unless running?
73
+ return self unless _activity_thread.running?
99
74
  logger.debug "Stopping"
100
75
 
101
- @activity_thread_running = false
102
76
  before_stopping if self.respond_to?(:before_stopping)
103
- @activity_thread.wakeup
104
- join limit
105
- @activity_thread = nil
77
+ @_activity_thread.stop limit
106
78
  after_stopping if self.respond_to?(:after_stopping)
107
79
  self
108
80
  end
@@ -113,11 +85,12 @@ module Servolux::Threaded
113
85
  # number of iterations has passed since this method was called.
114
86
  #
115
87
  def wait( limit = nil )
116
- return self unless running?
117
- start_waiting_iterations = self.iterations
88
+ return self unless _activity_thread.running?
89
+ initial_iterations = @_activity_thread.iterations
118
90
  loop {
119
- break unless running?
120
- break if limit and self.iterations > ( start_waiting_iterations + limit )
91
+ break unless @_activity_thread.running?
92
+ break if limit and @_activity_thread.iterations > ( initial_iterations + limit )
93
+ Thread.pass
121
94
  }
122
95
  end
123
96
 
@@ -129,15 +102,14 @@ module Servolux::Threaded
129
102
  # with +nil+.
130
103
  #
131
104
  def join( limit = nil )
132
- return if @activity_thread.nil?
133
- @activity_thread.join(limit) ? self : nil
105
+ _activity_thread.join(limit) ? self : nil
134
106
  end
135
107
 
136
108
  # Returns +true+ if the activity thread is running. Returns +false+
137
109
  # otherwise.
138
110
  #
139
111
  def running?
140
- @activity_thread_running
112
+ _activity_thread.running?
141
113
  end
142
114
 
143
115
  # Returns +true+ if the activity thread has finished its maximum
@@ -145,9 +117,8 @@ module Servolux::Threaded
145
117
  # Returns +false+ otherwise.
146
118
  #
147
119
  def finished_iterations?
148
- return true unless running?
149
- return true if maximum_iterations and (iterations >= maximum_iterations)
150
- return false
120
+ return true unless _activity_thread.running?
121
+ @_activity_thread.finished_iterations?
151
122
  end
152
123
 
153
124
  # Returns the status of threaded object.
@@ -162,45 +133,50 @@ module Servolux::Threaded
162
133
  # will cause the exception to be raised in the calling thread.
163
134
  #
164
135
  def status
165
- return false if @activity_thread.nil?
166
- @activity_thread.status
136
+ return false if _activity_thread.thread.nil?
137
+ @_activity_thread.thread.status
167
138
  end
168
139
 
169
140
  # Sets the number of seconds to sleep between invocations of the
170
141
  # threaded object's 'run' method.
171
142
  #
172
143
  def interval=( value )
173
- @activity_thread_interval = value
144
+ value = Float(value)
145
+ raise ArgumentError, "Sleep interval must be >= 0" unless value >= 0
146
+ _activity_thread.interval = value
174
147
  end
175
148
 
176
149
  # Returns the number of seconds to sleep between invocations of the
177
150
  # threaded object's 'run' method.
178
151
  #
179
152
  def interval
180
- @activity_thread_interval ||= 60
153
+ _activity_thread.interval
181
154
  end
182
155
 
183
156
  # Sets the maximum number of invocations of the threaded object's
184
157
  # 'run' method
185
158
  #
186
159
  def maximum_iterations=( value )
187
- raise ArgumentError, "maximum iterations must be >= 1" unless value.to_i >= 1
188
- @activity_thread_maximum_iterations = value.to_i
160
+ unless value.nil?
161
+ value = Integer(value)
162
+ raise ArgumentError, "maximum iterations must be >= 1" unless value >= 1
163
+ end
164
+
165
+ _activity_thread.maximum_iterations = value
189
166
  end
190
167
 
191
168
  # Returns the maximum number of invocations of the threaded
192
169
  # object's 'run' method
193
170
  #
194
171
  def maximum_iterations
195
- return unless defined? @activity_thread_maximum_iterations
196
- @activity_thread_maximum_iterations
172
+ _activity_thread.maximum_iterations
197
173
  end
198
174
 
199
175
  # Returns the number of iterations of the threaded object's 'run' method
200
176
  # completed thus far.
201
177
  #
202
178
  def iterations
203
- @activity_thread_iterations ||= 0
179
+ _activity_thread.iterations
204
180
  end
205
181
 
206
182
  # Set to +true+ to continue running the threaded object even if an error
@@ -211,7 +187,7 @@ module Servolux::Threaded
211
187
  # interpreter to exit.
212
188
  #
213
189
  def continue_on_error=( value )
214
- @activity_thread_continue_on_error = (value ? true : false)
190
+ _activity_thread.continue_on_error = (value ? true : false)
215
191
  end
216
192
 
217
193
  # Returns +true+ if the threded object should continue running even if an
@@ -219,28 +195,64 @@ module Servolux::Threaded
219
195
  # threaded object will stop running when an error is raised.
220
196
  #
221
197
  def continue_on_error?
222
- return @activity_thread_continue_on_error if defined? @activity_thread_continue_on_error
223
- @activity_thread_continue_on_error = false
198
+ _activity_thread.continue_on_error
224
199
  end
225
200
 
226
201
  # :stopdoc:
227
- #
228
- # The JRuby platform has an implementation error in it's Thread#join
229
- # method. In the Matz Ruby Interpreter, Thread#join with a +nil+ argument
230
- # will sleep forever; in the JRuby implementation, join will return
231
- # immediately.
232
- #
233
- if 'java' == RUBY_PLATFORM
234
- undef :join
202
+
203
+ def _activity_thread
204
+ @_activity_thread ||= ::Servolux::Threaded::ThreadContainer.new(nil, false, 60, 0, nil, false);
205
+ end
206
+
207
+ ThreadContainer = Struct.new( :thread, :running, :interval, :iterations, :maximum_iterations, :continue_on_error ) {
208
+ def start( threaded )
209
+ self.running = true
210
+ self.iterations = 0
211
+ self.thread = Thread.new { run threaded }
212
+ Thread.pass
213
+ end
214
+
215
+ def stop( limit )
216
+ self.running = false
217
+ thread.wakeup
218
+ join limit
219
+ self.thread = nil
220
+ end
221
+
222
+ def run( threaded )
223
+ loop {
224
+ begin
225
+ sleep interval if running?
226
+ break unless running?
227
+ threaded.run
228
+ self.iterations += 1
229
+ break if finished_iterations?
230
+ rescue SystemExit; raise
231
+ rescue Exception => err
232
+ if continue_on_error
233
+ threaded.logger.error err
234
+ else
235
+ threaded.logger.fatal err
236
+ raise err
237
+ end
238
+ end
239
+ }
240
+ ensure
241
+ self.running = false
242
+ end
243
+
235
244
  def join( limit = nil )
236
- return if @activity_thread.nil?
237
- if limit.nil?
238
- @activity_thread.join ? self : nil
239
- else
240
- @activity_thread.join(limit) ? self : nil
241
- end
245
+ return if thread.nil?
246
+ limit ? thread.join(limit) : thread.join
242
247
  end
243
- end
248
+
249
+ def finished_iterations?
250
+ return true if maximum_iterations and (iterations >= maximum_iterations)
251
+ return false
252
+ end
253
+
254
+ alias :running? :running
255
+ }
244
256
  # :startdoc:
245
257
 
246
258
  end # module Servolux::Threaded
data/lib/servolux.rb CHANGED
@@ -1,14 +1,12 @@
1
1
 
2
- require 'logging'
3
-
4
2
  module Servolux
5
3
 
6
4
  # :stopdoc:
7
- VERSION = '0.6.2'
5
+ VERSION = '0.7.0'
8
6
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
9
7
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
10
8
  # :startdoc:
11
-
9
+
12
10
  # Generic Servolux Error class.
13
11
  Error = Class.new(StandardError)
14
12
 
data/spec/server_spec.rb CHANGED
@@ -30,6 +30,19 @@ describe Servolux::Server do
30
30
  test(?e, @server.pid_file).should be_false
31
31
  end
32
32
 
33
+ it 'generates a PID file with mode rw-r----- by default' do
34
+ t = Thread.new {@server.startup}
35
+ Thread.pass until @server.status == 'sleep'
36
+ (File.stat(@server.pid_file).mode & 0777).should == 0640
37
+ end
38
+
39
+ it 'generates PID file with the specified permissions' do
40
+ @server.pid_file_mode = 0400
41
+ t = Thread.new {@server.startup}
42
+ Thread.pass until @server.status == 'sleep'
43
+ (File.stat(@server.pid_file).mode & 0777).should == 0400
44
+ end
45
+
33
46
  it 'shuts down gracefully when signaled' do
34
47
  t = Thread.new {@server.startup}
35
48
  Thread.pass until @server.status == 'sleep'
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ unless defined? SERVOLUX_SPEC_HELPER
3
3
  SERVOLUX_SPEC_HELPER = true
4
4
 
5
5
  require 'rubygems'
6
+ require 'logging'
6
7
  require 'spec'
7
8
  require 'spec/logging_helper'
8
9
 
@@ -6,8 +6,7 @@ describe Servolux::Threaded do
6
6
  base = Class.new do
7
7
  include Servolux::Threaded
8
8
  def initialize
9
- @activity_thread_running = false
10
- @activity_thread_interval = 0
9
+ self.interval = 0
11
10
  end
12
11
  def pass( val = 'sleep' )
13
12
  Thread.pass until status == val
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servolux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Pease
@@ -9,28 +9,38 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-16 00:00:00 -06:00
12
+ date: 2009-11-06 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bones-extras
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.0
24
+ version:
15
25
  - !ruby/object:Gem::Dependency
16
26
  name: logging
17
- type: :runtime
27
+ type: :development
18
28
  version_requirement:
19
29
  version_requirements: !ruby/object:Gem::Requirement
20
30
  requirements:
21
31
  - - ">="
22
32
  - !ruby/object:Gem::Version
23
- version: 1.1.2
33
+ version: 1.2.2
24
34
  version:
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: rspec
27
- type: :runtime
37
+ type: :development
28
38
  version_requirement:
29
39
  version_requirements: !ruby/object:Gem::Requirement
30
40
  requirements:
31
41
  - - ">="
32
42
  - !ruby/object:Gem::Version
33
- version: 1.2.2
43
+ version: 1.2.8
34
44
  version:
35
45
  - !ruby/object:Gem::Dependency
36
46
  name: bones
@@ -40,9 +50,13 @@ dependencies:
40
50
  requirements:
41
51
  - - ">="
42
52
  - !ruby/object:Gem::Version
43
- version: 2.5.0
53
+ version: 3.0.0
44
54
  version:
45
- description: Serv-O-Lux is a collection of Ruby classes that are useful for daemon and process management, and for writing your own Ruby services. The code is well documented and tested. It works with Ruby and JRuby supporing both 1.8 and 1.9 interpreters.
55
+ description: |-
56
+ Serv-O-Lux is a collection of Ruby classes that are useful for daemon and
57
+ process management, and for writing your own Ruby services. The code is well
58
+ documented and tested. It works with Ruby and JRuby supporing both 1.8 and 1.9
59
+ interpreters.
46
60
  email: tim.pease@gmail.com
47
61
  executables: []
48
62
 
@@ -52,6 +66,7 @@ extra_rdoc_files:
52
66
  - History.txt
53
67
  - README.rdoc
54
68
  files:
69
+ - .gitignore
55
70
  - History.txt
56
71
  - README.rdoc
57
72
  - Rakefile
@@ -67,21 +82,10 @@ files:
67
82
  - spec/servolux_spec.rb
68
83
  - spec/spec_helper.rb
69
84
  - spec/threaded_spec.rb
70
- - tasks/ann.rake
71
- - tasks/bones.rake
72
- - tasks/gem.rake
73
- - tasks/git.rake
74
- - tasks/notes.rake
75
- - tasks/post_load.rake
76
- - tasks/rdoc.rake
77
- - tasks/rubyforge.rake
78
- - tasks/setup.rb
79
- - tasks/spec.rake
80
- - tasks/svn.rake
81
- - tasks/test.rake
82
- - tasks/zentest.rake
83
85
  has_rdoc: true
84
- homepage: http://codeforpeople.rubyforge.org/servolux
86
+ homepage: http://gemcutter.org/gems/servolux
87
+ licenses: []
88
+
85
89
  post_install_message:
86
90
  rdoc_options:
87
91
  - --main
@@ -102,10 +106,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
106
  version:
103
107
  requirements: []
104
108
 
105
- rubyforge_project: codeforpeople
106
- rubygems_version: 1.3.1
109
+ rubyforge_project: servolux
110
+ rubygems_version: 1.3.5
107
111
  signing_key:
108
- specification_version: 2
112
+ specification_version: 3
109
113
  summary: Serv-O-Lux is a collection of Ruby classes that are useful for daemon and process management, and for writing your own Ruby services
110
114
  test_files: []
111
115