einhorn 0.8.2 → 1.0.1

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +15 -0
  3. data/README.md +7 -38
  4. data/einhorn.gemspec +23 -21
  5. data/example/pool_worker.rb +2 -2
  6. data/example/thin_example +8 -8
  7. data/example/time_server +5 -5
  8. data/lib/einhorn/client.rb +8 -8
  9. data/lib/einhorn/command/interface.rb +92 -98
  10. data/lib/einhorn/command.rb +75 -85
  11. data/lib/einhorn/compat.rb +7 -7
  12. data/lib/einhorn/event/abstract_text_descriptor.rb +32 -36
  13. data/lib/einhorn/event/ack_timer.rb +2 -2
  14. data/lib/einhorn/event/command_server.rb +7 -9
  15. data/lib/einhorn/event/connection.rb +1 -3
  16. data/lib/einhorn/event/loop_breaker.rb +2 -1
  17. data/lib/einhorn/event/persistent.rb +2 -2
  18. data/lib/einhorn/event/timer.rb +4 -4
  19. data/lib/einhorn/event.rb +20 -20
  20. data/lib/einhorn/prctl.rb +2 -2
  21. data/lib/einhorn/prctl_linux.rb +13 -14
  22. data/lib/einhorn/safe_yaml.rb +17 -0
  23. data/lib/einhorn/version.rb +1 -1
  24. data/lib/einhorn/worker.rb +26 -30
  25. data/lib/einhorn/worker_pool.rb +9 -9
  26. data/lib/einhorn.rb +120 -125
  27. metadata +37 -110
  28. data/.gitignore +0 -17
  29. data/.travis.yml +0 -10
  30. data/CONTRIBUTORS +0 -6
  31. data/Gemfile +0 -11
  32. data/History.txt +0 -4
  33. data/README.md.in +0 -94
  34. data/Rakefile +0 -27
  35. data/test/_lib.rb +0 -12
  36. data/test/integration/_lib/fixtures/env_printer/env_printer.rb +0 -26
  37. data/test/integration/_lib/fixtures/exit_during_upgrade/exiting_server.rb +0 -23
  38. data/test/integration/_lib/fixtures/exit_during_upgrade/upgrade_reexec.rb +0 -6
  39. data/test/integration/_lib/fixtures/pdeathsig_printer/pdeathsig_printer.rb +0 -29
  40. data/test/integration/_lib/fixtures/signal_timeout/sleepy_server.rb +0 -23
  41. data/test/integration/_lib/fixtures/upgrade_project/upgrading_server.rb +0 -24
  42. data/test/integration/_lib/helpers/einhorn_helpers.rb +0 -148
  43. data/test/integration/_lib/helpers.rb +0 -4
  44. data/test/integration/_lib.rb +0 -6
  45. data/test/integration/pdeathsig.rb +0 -26
  46. data/test/integration/startup.rb +0 -31
  47. data/test/integration/upgrading.rb +0 -204
  48. data/test/unit/_lib/bad_worker.rb +0 -7
  49. data/test/unit/_lib/sleep_worker.rb +0 -5
  50. data/test/unit/einhorn/client.rb +0 -88
  51. data/test/unit/einhorn/command/interface.rb +0 -49
  52. data/test/unit/einhorn/command.rb +0 -135
  53. data/test/unit/einhorn/event.rb +0 -89
  54. data/test/unit/einhorn/worker_pool.rb +0 -39
  55. data/test/unit/einhorn.rb +0 -96
  56. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -1,27 +1,24 @@
1
- require 'pp'
2
- require 'set'
3
- require 'tmpdir'
1
+ require "set"
2
+ require "tmpdir"
4
3
 
5
- require 'einhorn/command/interface'
6
- require 'einhorn/prctl'
4
+ require "einhorn/command/interface"
5
+ require "einhorn/prctl"
7
6
 
8
7
  module Einhorn
9
8
  module Command
10
9
  def self.reap
11
- begin
12
- while true
13
- Einhorn.log_debug('Going to reap a child process')
14
- pid = Process.wait(-1, Process::WNOHANG)
15
- return unless pid
16
- cleanup(pid)
17
- Einhorn::Event.break_loop
18
- end
19
- rescue Errno::ECHILD
10
+ loop do
11
+ Einhorn.log_debug("Going to reap a child process")
12
+ pid = Process.wait(-1, Process::WNOHANG)
13
+ return unless pid
14
+ cleanup(pid)
15
+ Einhorn::Event.break_loop
20
16
  end
17
+ rescue Errno::ECHILD
21
18
  end
22
19
 
23
20
  def self.cleanup(pid)
24
- unless spec = Einhorn::State.children[pid]
21
+ unless (spec = Einhorn::State.children[pid])
25
22
  Einhorn.log_error("Could not find any config for exited child #{pid.inspect}! This probably indicates a bug in Einhorn.")
26
23
  return
27
24
  end
@@ -31,7 +28,7 @@ module Einhorn
31
28
  # Unacked worker
32
29
  if spec[:type] == :worker && !spec[:acked]
33
30
  Einhorn::State.consecutive_deaths_before_ack += 1
34
- extra = ' before it was ACKed'
31
+ extra = " before it was ACKed"
35
32
  else
36
33
  extra = nil
37
34
  end
@@ -47,7 +44,7 @@ module Einhorn
47
44
  end
48
45
 
49
46
  def self.register_ping(pid, request_id)
50
- unless spec = Einhorn::State.children[pid]
47
+ unless (spec = Einhorn::State.children[pid])
51
48
  Einhorn.log_error("Could not find state for PID #{pid.inspect}; ignoring ACK.")
52
49
  return
53
50
  end
@@ -84,7 +81,7 @@ module Einhorn
84
81
  end
85
82
 
86
83
  def self.register_ack(pid)
87
- unless spec = Einhorn::State.children[pid]
84
+ unless (spec = Einhorn::State.children[pid])
88
85
  Einhorn.log_error("Could not find state for PID #{pid.inspect}; ignoring ACK.")
89
86
  return
90
87
  end
@@ -94,10 +91,8 @@ module Einhorn
94
91
  return
95
92
  end
96
93
 
97
- if Einhorn::State.consecutive_deaths_before_ack > 0
98
- extra = ", breaking the streak of #{Einhorn::State.consecutive_deaths_before_ack} consecutive unacked workers dying"
99
- else
100
- extra = nil
94
+ extra = if Einhorn::State.consecutive_deaths_before_ack > 0
95
+ ", breaking the streak of #{Einhorn::State.consecutive_deaths_before_ack} consecutive unacked workers dying"
101
96
  end
102
97
  Einhorn::State.consecutive_deaths_before_ack = 0
103
98
 
@@ -107,14 +102,14 @@ module Einhorn
107
102
  Einhorn::Event.break_loop
108
103
  end
109
104
 
110
- def self.signal_all(signal, children=nil, record=true)
105
+ def self.signal_all(signal, children = nil, record = true)
111
106
  children ||= Einhorn::WorkerPool.workers
112
107
  signaled = {}
113
108
 
114
109
  Einhorn.log_info("Sending #{signal} to #{children.inspect}", :upgrade)
115
110
 
116
111
  children.each do |child|
117
- unless spec = Einhorn::State.children[child]
112
+ unless (spec = Einhorn::State.children[child])
118
113
  Einhorn.log_error("Trying to send #{signal} to dead child #{child.inspect}. The fact we tried this probably indicates a bug in Einhorn.", :upgrade)
119
114
  next
120
115
  end
@@ -150,10 +145,10 @@ module Einhorn
150
145
 
151
146
  Einhorn.log_info("Child #{child.inspect} is still active after #{Einhorn::State.signal_timeout}s. Sending SIGKILL.")
152
147
  begin
153
- Process.kill('KILL', child)
148
+ Process.kill("KILL", child)
154
149
  rescue Errno::ESRCH
155
150
  end
156
- spec[:signaled].add('KILL')
151
+ spec[:signaled].add("KILL")
157
152
  end
158
153
  end
159
154
 
@@ -161,20 +156,19 @@ module Einhorn
161
156
  end
162
157
  end
163
158
 
164
-
165
159
  def self.increment
166
160
  Einhorn::Event.break_loop
167
161
  old = Einhorn::State.config[:number]
168
162
  new = (Einhorn::State.config[:number] += 1)
169
163
  output = "Incrementing number of workers from #{old} -> #{new}"
170
- $stderr.puts(output)
164
+ warn(output)
171
165
  output
172
166
  end
173
167
 
174
168
  def self.decrement
175
169
  if Einhorn::State.config[:number] <= 1
176
170
  output = "Can't decrease number of workers (already at #{Einhorn::State.config[:number]}). Run kill #{$$} if you really want to kill einhorn."
177
- $stderr.puts(output)
171
+ warn(output)
178
172
  return output
179
173
  end
180
174
 
@@ -182,7 +176,7 @@ module Einhorn
182
176
  old = Einhorn::State.config[:number]
183
177
  new = (Einhorn::State.config[:number] -= 1)
184
178
  output = "Decrementing number of workers from #{old} -> #{new}"
185
- $stderr.puts(output)
179
+ warn(output)
186
180
  output
187
181
  end
188
182
 
@@ -195,12 +189,12 @@ module Einhorn
195
189
  old = Einhorn::State.config[:number]
196
190
  Einhorn::State.config[:number] = new
197
191
  output = "Altering worker count, #{old} -> #{new}. Will "
198
- if old < new
199
- output << "spin up additional workers."
192
+ output << if old < new
193
+ "spin up additional workers."
200
194
  else
201
- output << "gracefully terminate workers."
195
+ "gracefully terminate workers."
202
196
  end
203
- $stderr.puts(output)
197
+ warn(output)
204
198
  output
205
199
  end
206
200
 
@@ -211,8 +205,8 @@ module Einhorn
211
205
  end
212
206
 
213
207
  {
214
- :state => global_state,
215
- :persistent_descriptors => descriptor_state,
208
+ state: global_state,
209
+ persistent_descriptors: descriptor_state
216
210
  }
217
211
  end
218
212
 
@@ -257,8 +251,8 @@ module Einhorn
257
251
 
258
252
  begin
259
253
  Einhorn.initialize_reload_environment
260
- respawn_commandline = Einhorn.upgrade_commandline(['--with-state-fd', read.fileno.to_s])
261
- respawn_commandline << { :close_others => false }
254
+ respawn_commandline = Einhorn.upgrade_commandline(["--with-state-fd", read.fileno.to_s])
255
+ respawn_commandline << {close_others: false}
262
256
  Einhorn.log_info("About to re-exec einhorn master as #{respawn_commandline.inspect}", :reload)
263
257
  Einhorn::Compat.exec(*respawn_commandline)
264
258
  rescue SystemCallError => e
@@ -275,16 +269,16 @@ module Einhorn
275
269
  end
276
270
  end
277
271
 
278
- def self.spinup(cmd=nil)
272
+ def self.spinup(cmd = nil)
279
273
  cmd ||= Einhorn::State.cmd
280
274
  index = next_index
281
275
  expected_ppid = Process.pid
282
- if Einhorn::State.preloaded
283
- pid = fork do
276
+ pid = if Einhorn::State.preloaded
277
+ fork do
284
278
  Einhorn::TransientState.whatami = :worker
285
279
  prepare_child_process
286
280
 
287
- Einhorn.log_info('About to tear down Einhorn state and run einhorn_main')
281
+ Einhorn.log_info("About to tear down Einhorn state and run einhorn_main")
288
282
  Einhorn::Command::Interface.uninit
289
283
  Einhorn::Event.close_all_for_worker
290
284
  Einhorn.set_argv(cmd, true)
@@ -297,7 +291,7 @@ module Einhorn
297
291
  einhorn_main
298
292
  end
299
293
  else
300
- pid = fork do
294
+ fork do
301
295
  Einhorn::TransientState.whatami = :worker
302
296
  prepare_child_process
303
297
 
@@ -314,20 +308,20 @@ module Einhorn
314
308
  setup_parent_watch(expected_ppid)
315
309
 
316
310
  prepare_child_environment(index)
317
- Einhorn::Compat.exec(cmd[0], cmd[1..-1], :close_others => false)
311
+ Einhorn::Compat.exec(cmd[0], cmd[1..-1], close_others: false)
318
312
  end
319
313
  end
320
314
 
321
315
  Einhorn.log_info("===> Launched #{pid} (index: #{index})", :upgrade)
322
316
  Einhorn::State.last_spinup = Time.now
323
317
  Einhorn::State.children[pid] = {
324
- :type => :worker,
325
- :version => Einhorn::State.version,
326
- :acked => false,
327
- :signaled => Set.new,
328
- :last_signaled_at => nil,
329
- :index => index,
330
- :spinup_time => Einhorn::State.last_spinup,
318
+ type: :worker,
319
+ version: Einhorn::State.version,
320
+ acked: false,
321
+ signaled: Set.new,
322
+ last_signaled_at: nil,
323
+ index: index,
324
+ spinup_time: Einhorn::State.last_spinup
331
325
  }
332
326
 
333
327
  # Set up whatever's needed for ACKing
@@ -336,6 +330,7 @@ module Einhorn
336
330
  when :timer
337
331
  Einhorn::Event::ACKTimer.open(ack_mode[:timeout], pid)
338
332
  when :manual
333
+ # nothing to do
339
334
  else
340
335
  Einhorn.log_error("Unrecognized ACK mode #{type.inspect}")
341
336
  end
@@ -343,24 +338,18 @@ module Einhorn
343
338
 
344
339
  def self.prepare_child_environment(index)
345
340
  # This is run from the child
346
- ENV['EINHORN_MASTER_PID'] = Process.ppid.to_s
347
- ENV['EINHORN_SOCK_PATH'] = Einhorn::Command::Interface.socket_path
341
+ ENV["EINHORN_MASTER_PID"] = Process.ppid.to_s
342
+ ENV["EINHORN_SOCK_PATH"] = Einhorn::Command::Interface.socket_path
348
343
  if Einhorn::State.command_socket_as_fd
349
344
  socket = UNIXSocket.open(Einhorn::Command::Interface.socket_path)
350
345
  Einhorn::TransientState.socket_handles << socket
351
- ENV['EINHORN_SOCK_FD'] = socket.fileno.to_s
346
+ ENV["EINHORN_SOCK_FD"] = socket.fileno.to_s
352
347
  end
353
348
 
354
- ENV['EINHORN_FD_COUNT'] = Einhorn::State.bind_fds.length.to_s
355
- Einhorn::State.bind_fds.each_with_index {|fd, i| ENV["EINHORN_FD_#{i}"] = fd.to_s}
356
-
357
- ENV['EINHORN_CHILD_INDEX'] = index.to_s
349
+ ENV["EINHORN_FD_COUNT"] = Einhorn::State.bind_fds.length.to_s
350
+ Einhorn::State.bind_fds.each_with_index { |fd, i| ENV["EINHORN_FD_#{i}"] = fd.to_s }
358
351
 
359
- # EINHORN_FDS is deprecated. It was originally an attempt to
360
- # match Upstart's nominal internal support for space-separated
361
- # FD lists, but nobody uses that in practice, and it makes
362
- # finding individual FDs more difficult
363
- ENV['EINHORN_FDS'] = Einhorn::State.bind_fds.map(&:to_s).join(' ')
352
+ ENV["EINHORN_CHILD_INDEX"] = index.to_s
364
353
  end
365
354
 
366
355
  # Reseed common ruby random number generators.
@@ -383,11 +372,11 @@ module Einhorn
383
372
 
384
373
  # reseed OpenSSL::Random if it's loaded
385
374
  if defined?(OpenSSL::Random)
386
- if defined?(Random)
387
- seed = Random.new_seed
375
+ seed = if defined?(Random)
376
+ Random.new_seed
388
377
  else
389
378
  # Ruby 1.8
390
- seed = rand
379
+ rand
391
380
  end
392
381
  OpenSSL::Random.seed(seed.to_s)
393
382
  end
@@ -399,14 +388,14 @@ module Einhorn
399
388
  end
400
389
 
401
390
  def self.setup_parent_watch(expected_ppid)
402
- if Einhorn::State.kill_children_on_exit then
391
+ if Einhorn::State.kill_children_on_exit
403
392
  begin
404
393
  # NB: Having the USR2 signal handler set to terminate (the default) at
405
394
  # this point is required. If it's set to a ruby handler, there are
406
395
  # race conditions that could cause the worker to leak.
407
396
 
408
397
  Einhorn::Prctl.set_pdeathsig("USR2")
409
- if Process.ppid != expected_ppid then
398
+ if Process.ppid != expected_ppid
410
399
  Einhorn.log_error("Parent process died before we set pdeathsig; cowardly refusing to exec child process.")
411
400
  exit(1)
412
401
  end
@@ -424,18 +413,19 @@ module Einhorn
424
413
  # upgrade, bring up all the new workers and don't cull any old workers
425
414
  # until they're all up.
426
415
  #
427
- def self.full_upgrade(options={})
428
- options = {:smooth => false}.merge(options)
416
+ def self.full_upgrade(options = {})
417
+ options = {smooth: false}.merge(options)
429
418
 
430
419
  Einhorn::State.smooth_upgrade = options.fetch(:smooth)
431
420
  reload_for_upgrade
432
421
  end
433
422
 
434
423
  def self.full_upgrade_smooth
435
- full_upgrade(:smooth => true)
424
+ full_upgrade(smooth: true)
436
425
  end
426
+
437
427
  def self.full_upgrade_fleet
438
- full_upgrade(:smooth => false)
428
+ full_upgrade(smooth: false)
439
429
  end
440
430
 
441
431
  def self.reload_for_upgrade
@@ -448,8 +438,8 @@ module Einhorn
448
438
  Einhorn.log_info("Currently upgrading (#{Einhorn::WorkerPool.ack_count} / #{Einhorn::WorkerPool.ack_target} ACKs; bumping version and starting over)...", :upgrade)
449
439
  else
450
440
  Einhorn::State.upgrading = true
451
- u_type = Einhorn::State.smooth_upgrade ? 'smooth' : 'fleet'
452
- Einhorn.log_info("Starting #{u_type} upgrade from version" +
441
+ u_type = Einhorn::State.smooth_upgrade ? "smooth" : "fleet"
442
+ Einhorn.log_info("Starting #{u_type} upgrade from version" \
453
443
  " #{Einhorn::State.version}...", :upgrade)
454
444
  end
455
445
 
@@ -496,7 +486,7 @@ module Einhorn
496
486
  end
497
487
 
498
488
  if unsignaled > target
499
- excess = Einhorn::WorkerPool.unsignaled_modern_workers_with_priority[0...(unsignaled-target)]
489
+ excess = Einhorn::WorkerPool.unsignaled_modern_workers_with_priority[0...(unsignaled - target)]
500
490
  Einhorn.log_info("Have too many workers at the current version, so killing off #{excess.length} of them.")
501
491
  signal_all("USR2", excess)
502
492
  end
@@ -507,13 +497,13 @@ module Einhorn
507
497
 
508
498
  def self.kill_expired_signaled_workers
509
499
  now = Time.now
510
- children = Einhorn::State.children.select do |_,c|
500
+ children = Einhorn::State.children.select do |_, c|
511
501
  # Only interested in USR2 signaled workers
512
502
  next unless c[:signaled] && c[:signaled].length > 0
513
- next unless c[:signaled].include?('USR2')
503
+ next unless c[:signaled].include?("USR2")
514
504
 
515
505
  # Ignore processes that have received KILL since it can't be trapped.
516
- next if c[:signaled].include?('KILL')
506
+ next if c[:signaled].include?("KILL")
517
507
 
518
508
  # Filter out those children that have not reached signal_timeout yet.
519
509
  next unless c[:last_signaled_at]
@@ -527,12 +517,12 @@ module Einhorn
527
517
  children.each do |pid, child|
528
518
  Einhorn.log_info("Child #{pid.inspect} was signaled #{(child[:last_signaled_at] - now).abs.to_i}s ago. Sending SIGKILL as it is still active after #{Einhorn::State.signal_timeout}s timeout.", :upgrade)
529
519
  begin
530
- Process.kill('KILL', pid)
520
+ Process.kill("KILL", pid)
531
521
  rescue Errno::ESRCH
532
522
  Einhorn.log_debug("Attempted to SIGKILL child #{pid.inspect} but the process does not exist.")
533
523
  end
534
524
 
535
- child[:signaled].add('KILL')
525
+ child[:signaled].add("KILL")
536
526
  child[:last_signaled_at] = Time.now
537
527
  end
538
528
  end
@@ -559,7 +549,7 @@ module Einhorn
559
549
  return
560
550
  end
561
551
  Einhorn.log_info("Launching #{missing} new workers")
562
- missing.times {spinup}
552
+ missing.times { spinup }
563
553
  end
564
554
 
565
555
  # Unbounded exponential backoff is not a thing: we run into problems if
@@ -568,7 +558,7 @@ module Einhorn
568
558
  # don't wait until the heat death of the universe to spin up new capacity.
569
559
  MAX_SPINUP_INTERVAL = 30.0
570
560
 
571
- def self.replenish_gradually(max_unacked=nil)
561
+ def self.replenish_gradually(max_unacked = nil)
572
562
  return if Einhorn::TransientState.has_outstanding_spinup_timer
573
563
  return unless Einhorn::WorkerPool.missing_worker_count > 0
574
564
 
@@ -591,7 +581,7 @@ module Einhorn
591
581
 
592
582
  # Exponentially backoff automated spinup if we're just having
593
583
  # things die before ACKing
594
- spinup_interval = Einhorn::State.config[:seconds] * (1.5 ** Einhorn::State.consecutive_deaths_before_ack)
584
+ spinup_interval = Einhorn::State.config[:seconds] * (1.5**Einhorn::State.consecutive_deaths_before_ack)
595
585
  spinup_interval = [spinup_interval, MAX_SPINUP_INTERVAL].min
596
586
  seconds_ago = (Time.now - Einhorn::State.last_spinup).to_f
597
587
 
@@ -618,14 +608,14 @@ module Einhorn
618
608
  end
619
609
  end
620
610
 
621
- def self.quieter(log=true)
611
+ def self.quieter(log = true)
622
612
  Einhorn::State.verbosity += 1 if Einhorn::State.verbosity < 2
623
613
  output = "Verbosity set to #{Einhorn::State.verbosity}"
624
614
  Einhorn.log_info(output) if log
625
615
  output
626
616
  end
627
617
 
628
- def self.louder(log=true)
618
+ def self.louder(log = true)
629
619
  Einhorn::State.verbosity -= 1 if Einhorn::State.verbosity > 0
630
620
  output = "Verbosity set to #{Einhorn::State.verbosity}"
631
621
  Einhorn.log_info(output) if log
@@ -11,10 +11,10 @@ module Einhorn
11
11
 
12
12
  def self.cloexec!(fd, enable)
13
13
  original = fd.fcntl(Fcntl::F_GETFD)
14
- if enable
15
- new = original | Fcntl::FD_CLOEXEC
14
+ new = if enable
15
+ original | Fcntl::FD_CLOEXEC
16
16
  else
17
- new = original & (-Fcntl::FD_CLOEXEC-1)
17
+ original & (-Fcntl::FD_CLOEXEC - 1)
18
18
  end
19
19
  fd.fcntl(Fcntl::F_SETFD, new)
20
20
  end
@@ -24,7 +24,7 @@ module Einhorn
24
24
  end
25
25
 
26
26
  # Opts are ignored in Ruby 1.8
27
- def self.exec(script, args, opts={})
27
+ def self.exec(script, args, opts = {})
28
28
  cmd = [script, script]
29
29
  begin
30
30
  Kernel.exec(cmd, *(args + [opts]))
@@ -53,18 +53,18 @@ module Einhorn
53
53
 
54
54
  # linux / friends
55
55
  begin
56
- return File.read('/proc/cpuinfo').scan(/^processor\s*:/).count
56
+ return File.read("/proc/cpuinfo").scan(/^processor\s*:/).count
57
57
  rescue Errno::ENOENT
58
58
  end
59
59
 
60
60
  # OS X
61
- if RUBY_PLATFORM =~ /darwin/
61
+ if RUBY_PLATFORM.match?(/darwin/)
62
62
  return Integer(`sysctl -n hw.logicalcpu`)
63
63
  end
64
64
 
65
65
  # windows / friends
66
66
  begin
67
- require 'win32ole'
67
+ require "win32ole"
68
68
  rescue LoadError
69
69
  else
70
70
  wmi = WIN32OLE.connect("winmgmts://")
@@ -6,7 +6,7 @@ module Einhorn::Event
6
6
  @@instance_counter = 0
7
7
 
8
8
  def self.open(sock)
9
- self.new(sock)
9
+ new(sock)
10
10
  end
11
11
 
12
12
  def initialize(sock)
@@ -16,7 +16,7 @@ module Einhorn::Event
16
16
  @client_id = "#{@@instance_counter}:#{sock.fileno}"
17
17
 
18
18
  @read_buffer = ""
19
- @write_buffer = ""
19
+ @write_buffer = +""
20
20
 
21
21
  @closed = false
22
22
 
@@ -40,24 +40,22 @@ module Einhorn::Event
40
40
  end
41
41
 
42
42
  def notify_readable
43
- while true
44
- begin
45
- return if @closed
46
- chunk = @socket.read_nonblock(1024)
47
- rescue Errno::EAGAIN
48
- break
49
- rescue EOFError, Errno::EPIPE, Errno::ECONNRESET
50
- close
51
- break
52
- rescue StandardError => e
53
- log_error("Caught unrecognized error while reading from socket: #{e} (#{e.class})")
54
- close
55
- break
56
- else
57
- log_debug("read #{chunk.length} bytes (#{chunk.inspect[0..20]})")
58
- @read_buffer << chunk
59
- process_read_buffer
60
- end
43
+ loop do
44
+ return if @closed
45
+ chunk = @socket.read_nonblock(1024)
46
+ rescue Errno::EAGAIN
47
+ break
48
+ rescue EOFError, Errno::EPIPE, Errno::ECONNRESET
49
+ close
50
+ break
51
+ rescue => e
52
+ log_error("Caught unrecognized error while reading from socket: #{e} (#{e.class})")
53
+ close
54
+ break
55
+ else
56
+ log_debug("read #{chunk.length} bytes (#{chunk.inspect[0..20]})")
57
+ @read_buffer << chunk
58
+ process_read_buffer
61
59
  end
62
60
  end
63
61
 
@@ -72,19 +70,17 @@ module Einhorn::Event
72
70
  end
73
71
 
74
72
  def notify_writeable
75
- begin
76
- return if @closed
77
- written = @socket.write_nonblock(@write_buffer)
78
- rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
79
- rescue Errno::EPIPE, Errno::ECONNRESET
80
- close
81
- rescue StandardError => e
82
- log_error("Caught unrecognized error while writing to socket: #{e} (#{e.class})")
83
- close
84
- else
85
- log_debug("wrote #{written} bytes")
86
- @write_buffer = @write_buffer[written..-1]
87
- end
73
+ return if @closed
74
+ written = @socket.write_nonblock(@write_buffer)
75
+ rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
76
+ rescue Errno::EPIPE, Errno::ECONNRESET
77
+ close
78
+ rescue => e
79
+ log_error("Caught unrecognized error while writing to socket: #{e} (#{e.class})")
80
+ close
81
+ else
82
+ log_debug("wrote #{written} bytes")
83
+ @write_buffer = @write_buffer[written..-1]
88
84
  end
89
85
 
90
86
  def to_io
@@ -102,9 +98,9 @@ module Einhorn::Event
102
98
  end
103
99
 
104
100
  def process_read_buffer
105
- while true
101
+ loop do
106
102
  if @read_buffer.length > 0
107
- break unless split = parse_record
103
+ break unless (split = parse_record)
108
104
  record, remainder = split
109
105
  log_debug("Read a record of #{record.length} bytes.")
110
106
  @read_buffer = remainder
@@ -117,7 +113,7 @@ module Einhorn::Event
117
113
 
118
114
  # Override in subclass. This lets you do streaming reads.
119
115
  def parse_record
120
- [@read_buffer, '']
116
+ [@read_buffer, ""]
121
117
  end
122
118
 
123
119
  def consume_record(record)
@@ -2,7 +2,7 @@ module Einhorn::Event
2
2
  class ACKTimer < Timer
3
3
  include Persistent
4
4
 
5
- def initialize(time, pid, start=nil)
5
+ def initialize(time, pid, start = nil)
6
6
  super(time, start) do
7
7
  Einhorn::Command.register_timer_ack(time, pid)
8
8
  end
@@ -10,7 +10,7 @@ module Einhorn::Event
10
10
  end
11
11
 
12
12
  def to_state
13
- {:class => self.class.to_s, :time => @time, :start => @start, :pid => @pid}
13
+ {class: self.class.to_s, time: @time, start: @start, pid: @pid}
14
14
  end
15
15
 
16
16
  def self.from_state(state)
@@ -3,7 +3,7 @@ module Einhorn::Event
3
3
  include Persistent
4
4
 
5
5
  def self.open(server)
6
- self.new(server)
6
+ new(server)
7
7
  end
8
8
 
9
9
  def initialize(server)
@@ -15,14 +15,12 @@ module Einhorn::Event
15
15
  end
16
16
 
17
17
  def notify_readable
18
- begin
19
- while true
20
- return if @closed
21
- sock = Einhorn::Compat.accept_nonblock(@server)
22
- Connection.open(sock)
23
- end
24
- rescue Errno::EAGAIN
18
+ loop do
19
+ return if @closed
20
+ sock = Einhorn::Compat.accept_nonblock(@server)
21
+ Connection.open(sock)
25
22
  end
23
+ rescue Errno::EAGAIN
26
24
  end
27
25
 
28
26
  def to_io
@@ -30,7 +28,7 @@ module Einhorn::Event
30
28
  end
31
29
 
32
30
  def to_state
33
- {:class => self.class.to_s, :server => @server.fileno}
31
+ {class: self.class.to_s, server: @server.fileno}
34
32
  end
35
33
 
36
34
  def self.from_state(state)
@@ -11,8 +11,6 @@ module Einhorn::Event
11
11
  split = @read_buffer.split("\n", 2)
12
12
  if split.length > 1
13
13
  split
14
- else
15
- nil
16
14
  end
17
15
  end
18
16
 
@@ -21,7 +19,7 @@ module Einhorn::Event
21
19
  end
22
20
 
23
21
  def to_state
24
- state = {:class => self.class.to_s, :socket => @socket.fileno}
22
+ state = {class: self.class.to_s, socket: @socket.fileno}
25
23
  # Don't include by default because it's not that pretty
26
24
  state[:read_buffer] = @read_buffer if @read_buffer.length > 0
27
25
  state[:write_buffer] = @write_buffer if @write_buffer.length > 0
@@ -1,6 +1,7 @@
1
1
  # TODO: set lots of cloexecs
2
2
  module Einhorn::Event
3
3
  class LoopBreaker < AbstractTextDescriptor
4
- def consume_record(record); end
4
+ def consume_record(record)
5
+ end
5
6
  end
6
7
  end
@@ -8,7 +8,7 @@ module Einhorn::Event
8
8
 
9
9
  def self.from_state(state)
10
10
  klass_name = state[:class]
11
- if klass = @@persistent[klass_name]
11
+ if (klass = @@persistent[klass_name])
12
12
  klass.from_state(state)
13
13
  else
14
14
  Einhorn.log_error("Unrecognized persistent descriptor class #{klass_name.inspect}. Ignoring. This most likely indicates that your Einhorn version has upgraded. Everything should still be working, but it may be worth a restart.", :upgrade)
@@ -17,7 +17,7 @@ module Einhorn::Event
17
17
  end
18
18
 
19
19
  def self.persistent?(descriptor)
20
- @@persistent.values.any? {|klass| descriptor.kind_of?(klass)}
20
+ @@persistent.values.any? { |klass| descriptor.is_a?(klass) }
21
21
  end
22
22
  end
23
23
  end