crusher-eventmachine 0.12.11

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 (162) hide show
  1. data/README +81 -0
  2. data/Rakefile +370 -0
  3. data/docs/COPYING +60 -0
  4. data/docs/ChangeLog +211 -0
  5. data/docs/DEFERRABLES +246 -0
  6. data/docs/EPOLL +141 -0
  7. data/docs/GNU +281 -0
  8. data/docs/INSTALL +13 -0
  9. data/docs/KEYBOARD +42 -0
  10. data/docs/LEGAL +25 -0
  11. data/docs/LIGHTWEIGHT_CONCURRENCY +130 -0
  12. data/docs/PURE_RUBY +75 -0
  13. data/docs/RELEASE_NOTES +94 -0
  14. data/docs/SMTP +4 -0
  15. data/docs/SPAWNED_PROCESSES +148 -0
  16. data/docs/TODO +8 -0
  17. data/eventmachine.gemspec +40 -0
  18. data/examples/ex_channel.rb +43 -0
  19. data/examples/ex_queue.rb +2 -0
  20. data/examples/ex_tick_loop_array.rb +15 -0
  21. data/examples/ex_tick_loop_counter.rb +32 -0
  22. data/examples/helper.rb +2 -0
  23. data/ext/binder.cpp +124 -0
  24. data/ext/binder.h +46 -0
  25. data/ext/cmain.cpp +852 -0
  26. data/ext/cplusplus.cpp +202 -0
  27. data/ext/ed.cpp +1884 -0
  28. data/ext/ed.h +418 -0
  29. data/ext/em.cpp +2377 -0
  30. data/ext/em.h +239 -0
  31. data/ext/emwin.cpp +300 -0
  32. data/ext/emwin.h +94 -0
  33. data/ext/epoll.cpp +26 -0
  34. data/ext/epoll.h +25 -0
  35. data/ext/eventmachine.h +124 -0
  36. data/ext/eventmachine_cpp.h +96 -0
  37. data/ext/extconf.rb +150 -0
  38. data/ext/fastfilereader/extconf.rb +85 -0
  39. data/ext/fastfilereader/mapper.cpp +214 -0
  40. data/ext/fastfilereader/mapper.h +59 -0
  41. data/ext/fastfilereader/rubymain.cpp +127 -0
  42. data/ext/files.cpp +94 -0
  43. data/ext/files.h +65 -0
  44. data/ext/kb.cpp +79 -0
  45. data/ext/page.cpp +107 -0
  46. data/ext/page.h +51 -0
  47. data/ext/pipe.cpp +347 -0
  48. data/ext/project.h +157 -0
  49. data/ext/rubymain.cpp +1215 -0
  50. data/ext/sigs.cpp +89 -0
  51. data/ext/sigs.h +32 -0
  52. data/ext/ssl.cpp +460 -0
  53. data/ext/ssl.h +94 -0
  54. data/java/.classpath +8 -0
  55. data/java/.project +17 -0
  56. data/java/src/com/rubyeventmachine/EmReactor.java +571 -0
  57. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
  58. data/java/src/com/rubyeventmachine/EventableChannel.java +69 -0
  59. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +189 -0
  60. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +364 -0
  61. data/java/src/com/rubyeventmachine/application/Application.java +194 -0
  62. data/java/src/com/rubyeventmachine/application/Connection.java +74 -0
  63. data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +37 -0
  64. data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +46 -0
  65. data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +38 -0
  66. data/java/src/com/rubyeventmachine/application/Timer.java +54 -0
  67. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +109 -0
  68. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +148 -0
  69. data/java/src/com/rubyeventmachine/tests/EMTest.java +80 -0
  70. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +53 -0
  71. data/java/src/com/rubyeventmachine/tests/TestServers.java +75 -0
  72. data/java/src/com/rubyeventmachine/tests/TestTimers.java +90 -0
  73. data/lib/em/buftok.rb +138 -0
  74. data/lib/em/callback.rb +26 -0
  75. data/lib/em/channel.rb +57 -0
  76. data/lib/em/connection.rb +569 -0
  77. data/lib/em/deferrable.rb +206 -0
  78. data/lib/em/file_watch.rb +54 -0
  79. data/lib/em/future.rb +61 -0
  80. data/lib/em/iterator.rb +270 -0
  81. data/lib/em/messages.rb +66 -0
  82. data/lib/em/process_watch.rb +44 -0
  83. data/lib/em/processes.rb +119 -0
  84. data/lib/em/protocols.rb +36 -0
  85. data/lib/em/protocols/header_and_content.rb +138 -0
  86. data/lib/em/protocols/httpclient.rb +276 -0
  87. data/lib/em/protocols/httpclient2.rb +590 -0
  88. data/lib/em/protocols/line_and_text.rb +125 -0
  89. data/lib/em/protocols/linetext2.rb +161 -0
  90. data/lib/em/protocols/memcache.rb +323 -0
  91. data/lib/em/protocols/object_protocol.rb +45 -0
  92. data/lib/em/protocols/postgres3.rb +247 -0
  93. data/lib/em/protocols/saslauth.rb +175 -0
  94. data/lib/em/protocols/smtpclient.rb +357 -0
  95. data/lib/em/protocols/smtpserver.rb +640 -0
  96. data/lib/em/protocols/socks4.rb +66 -0
  97. data/lib/em/protocols/stomp.rb +200 -0
  98. data/lib/em/protocols/tcptest.rb +53 -0
  99. data/lib/em/pure_ruby.rb +1019 -0
  100. data/lib/em/queue.rb +62 -0
  101. data/lib/em/spawnable.rb +85 -0
  102. data/lib/em/streamer.rb +130 -0
  103. data/lib/em/tick_loop.rb +85 -0
  104. data/lib/em/timers.rb +57 -0
  105. data/lib/em/version.rb +3 -0
  106. data/lib/eventmachine.rb +1540 -0
  107. data/lib/evma.rb +32 -0
  108. data/lib/evma/callback.rb +32 -0
  109. data/lib/evma/container.rb +75 -0
  110. data/lib/evma/factory.rb +77 -0
  111. data/lib/evma/protocol.rb +87 -0
  112. data/lib/evma/reactor.rb +48 -0
  113. data/lib/jeventmachine.rb +257 -0
  114. data/setup.rb +1585 -0
  115. data/tasks/cpp.rake_example +77 -0
  116. data/tests/client.crt +31 -0
  117. data/tests/client.key +51 -0
  118. data/tests/test_attach.rb +136 -0
  119. data/tests/test_basic.rb +249 -0
  120. data/tests/test_channel.rb +63 -0
  121. data/tests/test_connection_count.rb +35 -0
  122. data/tests/test_defer.rb +49 -0
  123. data/tests/test_deferrable.rb +35 -0
  124. data/tests/test_epoll.rb +160 -0
  125. data/tests/test_error_handler.rb +35 -0
  126. data/tests/test_errors.rb +82 -0
  127. data/tests/test_exc.rb +55 -0
  128. data/tests/test_file_watch.rb +49 -0
  129. data/tests/test_futures.rb +198 -0
  130. data/tests/test_get_sock_opt.rb +30 -0
  131. data/tests/test_handler_check.rb +37 -0
  132. data/tests/test_hc.rb +190 -0
  133. data/tests/test_httpclient.rb +227 -0
  134. data/tests/test_httpclient2.rb +154 -0
  135. data/tests/test_inactivity_timeout.rb +50 -0
  136. data/tests/test_kb.rb +60 -0
  137. data/tests/test_ltp.rb +190 -0
  138. data/tests/test_ltp2.rb +317 -0
  139. data/tests/test_next_tick.rb +133 -0
  140. data/tests/test_object_protocol.rb +37 -0
  141. data/tests/test_pause.rb +70 -0
  142. data/tests/test_pending_connect_timeout.rb +48 -0
  143. data/tests/test_process_watch.rb +50 -0
  144. data/tests/test_processes.rb +128 -0
  145. data/tests/test_proxy_connection.rb +144 -0
  146. data/tests/test_pure.rb +134 -0
  147. data/tests/test_queue.rb +44 -0
  148. data/tests/test_running.rb +42 -0
  149. data/tests/test_sasl.rb +72 -0
  150. data/tests/test_send_file.rb +251 -0
  151. data/tests/test_servers.rb +76 -0
  152. data/tests/test_smtpclient.rb +83 -0
  153. data/tests/test_smtpserver.rb +85 -0
  154. data/tests/test_spawn.rb +322 -0
  155. data/tests/test_ssl_args.rb +79 -0
  156. data/tests/test_ssl_methods.rb +50 -0
  157. data/tests/test_ssl_verify.rb +82 -0
  158. data/tests/test_tick_loop.rb +59 -0
  159. data/tests/test_timers.rb +160 -0
  160. data/tests/test_ud.rb +36 -0
  161. data/tests/testem.rb +31 -0
  162. metadata +251 -0
data/lib/em/queue.rb ADDED
@@ -0,0 +1,62 @@
1
+ module EventMachine
2
+ # A cross thread, reactor scheduled, linear queue.
3
+ #
4
+ # This class provides a simple "Queue" like abstraction on top of the reactor
5
+ # scheduler. It services two primary purposes:
6
+ # * API sugar for stateful protocols
7
+ # * Pushing processing onto the same thread as the reactor
8
+ #
9
+ # See examples/ex_queue.rb for a detailed example.
10
+ #
11
+ # q = EM::Queue.new
12
+ # q.push('one', 'two', 'three')
13
+ # 3.times do
14
+ # q.pop{ |msg| puts(msg) }
15
+ # end
16
+ #
17
+ class Queue
18
+ # Create a new queue
19
+ def initialize
20
+ @items = []
21
+ @popq = []
22
+ end
23
+
24
+ # Pop items off the queue, running the block on the reactor thread. The pop
25
+ # will not happen immediately, but at some point in the future, either in
26
+ # the next tick, if the queue has data, or when the queue is populated.
27
+ def pop(*a, &b)
28
+ cb = EM::Callback(*a, &b)
29
+ EM.schedule do
30
+ if @items.empty?
31
+ @popq << cb
32
+ else
33
+ cb.call @items.shift
34
+ end
35
+ end
36
+ nil # Always returns nil
37
+ end
38
+
39
+ # Push items onto the queue in the reactor thread. The items will not appear
40
+ # in the queue immediately, but will be scheduled for addition during the
41
+ # next reactor tick.
42
+ def push(*items)
43
+ EM.schedule do
44
+ @items.push(*items)
45
+ @popq.shift.call @items.shift until @items.empty? || @popq.empty?
46
+ end
47
+ end
48
+ alias :<< :push
49
+
50
+ # N.B. This is a peek, it's not thread safe, and may only tend toward
51
+ # accuracy.
52
+ def empty?
53
+ @items.empty?
54
+ end
55
+
56
+ # N.B. This is a peek, it's not thread safe, and may only tend toward
57
+ # accuracy.
58
+ def size
59
+ @items.size
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,85 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 25 Aug 2007
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ module EventMachine
27
+ # Support for Erlang-style processes.
28
+ #
29
+ class SpawnedProcess
30
+ # Send a message to the spawned process
31
+ def notify *x
32
+ me = self
33
+ EM.next_tick {
34
+ # A notification executes in the context of this
35
+ # SpawnedProcess object. That makes self and notify
36
+ # work as one would expect.
37
+ #
38
+ y = me.call(*x)
39
+ if y and y.respond_to?(:pull_out_yield_block)
40
+ a,b = y.pull_out_yield_block
41
+ set_receiver a
42
+ self.notify if b
43
+ end
44
+ }
45
+ end
46
+ alias_method :resume, :notify
47
+ alias_method :run, :notify # for formulations like (EM.spawn {xxx}).run
48
+ #attr_accessor :receiver
49
+
50
+ #--
51
+ # I know I'm missing something stupid, but the inside of class << s
52
+ # can't see locally-bound values. It can see globals, though.
53
+ def set_receiver blk
54
+ $em______tmpglobal = blk
55
+ class << self
56
+ define_method :call, $em______tmpglobal.dup
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ class YieldBlockFromSpawnedProcess # :nodoc:
63
+ def initialize block, notify
64
+ @block = [block,notify]
65
+ end
66
+ def pull_out_yield_block
67
+ @block
68
+ end
69
+ end
70
+
71
+ # Spawn an erlang-style process
72
+ def self.spawn &block
73
+ s = SpawnedProcess.new
74
+ s.set_receiver block
75
+ s
76
+ end
77
+
78
+ def self.yield &block # :nodoc:
79
+ return YieldBlockFromSpawnedProcess.new( block, false )
80
+ end
81
+
82
+ def self.yield_and_notify &block # :nodoc:
83
+ return YieldBlockFromSpawnedProcess.new( block, true )
84
+ end
85
+ end
@@ -0,0 +1,130 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 Jul 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+
27
+ module EventMachine
28
+ class FileStreamer
29
+ include Deferrable
30
+
31
+ # Use mapped streamer for files bigger than 16k
32
+ MappingThreshold = 16384
33
+ # Wait until next tick to send more data when 50k is still in the outgoing buffer
34
+ BackpressureLevel = 50000
35
+ # Send 16k chunks at a time
36
+ ChunkSize = 16384
37
+
38
+ # Stream a file over a given connection. An optional :http_chunks => true argument will
39
+ # use HTTP 1.1 style chunked-encoding semantics.
40
+ #
41
+ # module FileSender
42
+ # def post_init
43
+ # streamer = EventMachine::FileStreamer.new(self, '/tmp/bigfile.tar')
44
+ # streamer.callback{
45
+ # # file was sent successfully
46
+ # close_connection_after_writing
47
+ # }
48
+ # end
49
+ # end
50
+ #
51
+ def initialize connection, filename, args = {}
52
+ @connection = connection
53
+ @http_chunks = args[:http_chunks]
54
+
55
+ if File.exist?(filename)
56
+ @size = File.size?(filename)
57
+ if @size <= MappingThreshold
58
+ stream_without_mapping filename
59
+ else
60
+ stream_with_mapping filename
61
+ end
62
+ else
63
+ fail "file not found"
64
+ end
65
+ end
66
+
67
+ def stream_without_mapping filename # :nodoc:
68
+ if @http_chunks
69
+ @connection.send_data "#{@size.to_s(16)}\r\n"
70
+ @connection.send_file_data filename
71
+ @connection.send_data "\r\n0\r\n\r\n"
72
+ else
73
+ @connection.send_file_data filename
74
+ end
75
+ succeed
76
+ end
77
+ private :stream_without_mapping
78
+
79
+ def stream_with_mapping filename # :nodoc:
80
+ ensure_mapping_extension_is_present
81
+
82
+ @position = 0
83
+ @mapping = EventMachine::FastFileReader::Mapper.new filename
84
+ stream_one_chunk
85
+ end
86
+ private :stream_with_mapping
87
+
88
+ # Used internally to stream one chunk at a time over multiple reactor ticks
89
+ def stream_one_chunk
90
+ loop {
91
+ if @position < @size
92
+ if @connection.get_outbound_data_size > BackpressureLevel
93
+ EventMachine::next_tick {stream_one_chunk}
94
+ break
95
+ else
96
+ len = @size - @position
97
+ len = ChunkSize if (len > ChunkSize)
98
+
99
+ @connection.send_data( "#{len.to_s(16)}\r\n" ) if @http_chunks
100
+ @connection.send_data( @mapping.get_chunk( @position, len ))
101
+ @connection.send_data("\r\n") if @http_chunks
102
+
103
+ @position += len
104
+ end
105
+ else
106
+ @connection.send_data "0\r\n\r\n" if @http_chunks
107
+ @mapping.close
108
+ succeed
109
+ break
110
+ end
111
+ }
112
+ end
113
+
114
+ #--
115
+ # We use an outboard extension class to get memory-mapped files.
116
+ # It's outboard to avoid polluting the core distro, but that means
117
+ # there's a "hidden" dependency on it. The first time we get here in
118
+ # any run, try to load up the dependency extension. User code will see
119
+ # a LoadError if it's not available, but code that doesn't require
120
+ # mapped files will work fine without it. This is a somewhat difficult
121
+ # compromise between usability and proper modularization.
122
+ #
123
+ def ensure_mapping_extension_is_present # :nodoc:
124
+ @@fastfilereader ||= (require 'fastfilereaderext')
125
+ end
126
+ private :ensure_mapping_extension_is_present
127
+
128
+ end
129
+ end
130
+
@@ -0,0 +1,85 @@
1
+ module EventMachine
2
+ # Creates and immediately starts an EventMachine::TickLoop
3
+ def self.tick_loop(*a, &b)
4
+ TickLoop.new(*a, &b).start
5
+ end
6
+
7
+ # A TickLoop is useful when one needs to distribute amounts of work
8
+ # throughout ticks in order to maintain response times. It is also useful for
9
+ # simple repeated checks and metrics.
10
+ #
11
+ # # Here we run through an array one item per tick until it is empty,
12
+ # # printing each element.
13
+ # # When the array is empty, we return :stop from the callback, and the
14
+ # # loop will terminate.
15
+ # # When the loop terminates, the on_stop callbacks will be called.
16
+ # EM.run do
17
+ # array = (1..100).to_a
18
+ #
19
+ # tickloop = EM.tick_loop do
20
+ # if array.empty?
21
+ # :stop
22
+ # else
23
+ # puts array.shift
24
+ # end
25
+ # end
26
+ #
27
+ # tickloop.on_stop { EM.stop }
28
+ # end
29
+ #
30
+ class TickLoop
31
+
32
+ # Arguments: A callback (EM::Callback) to call each tick. If the call
33
+ # returns +:stop+ then the loop will be stopped. Any other value is
34
+ # ignored.
35
+ def initialize(*a, &b)
36
+ @work = EM::Callback(*a, &b)
37
+ @stops = []
38
+ @stopped = true
39
+ end
40
+
41
+ # Arguments: A callback (EM::Callback) to call once on the next stop (or
42
+ # immediately if already stopped).
43
+ def on_stop(*a, &b)
44
+ if @stopped
45
+ EM::Callback(*a, &b).call
46
+ else
47
+ @stops << EM::Callback(*a, &b)
48
+ end
49
+ end
50
+
51
+ # Stop the tick loop immediately, and call it's on_stop callbacks.
52
+ def stop
53
+ @stopped = true
54
+ until @stops.empty?
55
+ @stops.shift.call
56
+ end
57
+ end
58
+
59
+ # Query if the loop is stopped.
60
+ def stopped?
61
+ @stopped
62
+ end
63
+
64
+ # Start the tick loop, will raise argument error if the loop is already
65
+ # running.
66
+ def start
67
+ raise ArgumentError, "double start" unless @stopped
68
+ @stopped = false
69
+ schedule
70
+ end
71
+
72
+ private
73
+ def schedule
74
+ EM.next_tick do
75
+ next if @stopped
76
+ if @work.call == :stop
77
+ stop
78
+ else
79
+ schedule
80
+ end
81
+ end
82
+ self
83
+ end
84
+ end
85
+ end
data/lib/em/timers.rb ADDED
@@ -0,0 +1,57 @@
1
+ module EventMachine
2
+ # Creates a one-time timer
3
+ #
4
+ # timer = EventMachine::Timer.new(5) do
5
+ # # this will never fire because we cancel it
6
+ # end
7
+ # timer.cancel
8
+ #
9
+ class Timer
10
+ # Create a new timer that fires after a given number of seconds
11
+ def initialize interval, callback=nil, &block
12
+ @signature = EventMachine::add_timer(interval, callback || block)
13
+ end
14
+
15
+ # Cancel the timer
16
+ def cancel
17
+ EventMachine.send :cancel_timer, @signature
18
+ end
19
+ end
20
+
21
+ # Creates a periodic timer
22
+ #
23
+ # n = 0
24
+ # timer = EventMachine::PeriodicTimer.new(5) do
25
+ # puts "the time is #{Time.now}"
26
+ # timer.cancel if (n+=1) > 5
27
+ # end
28
+ #
29
+ class PeriodicTimer
30
+ # Create a new periodic timer that executes every interval seconds
31
+ def initialize interval, callback=nil, &block
32
+ @interval = interval
33
+ @code = callback || block
34
+ @cancelled = false
35
+ @work = method(:fire)
36
+ schedule
37
+ end
38
+
39
+ # Cancel the periodic timer
40
+ def cancel
41
+ @cancelled = true
42
+ end
43
+
44
+ # Fire the timer every interval seconds
45
+ attr_accessor :interval
46
+
47
+ def schedule # :nodoc:
48
+ EventMachine::add_timer @interval, @work
49
+ end
50
+ def fire # :nodoc:
51
+ unless @cancelled
52
+ @code.call
53
+ schedule
54
+ end
55
+ end
56
+ end
57
+ end
data/lib/em/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module EventMachine
2
+ VERSION = "0.12.11"
3
+ end
@@ -0,0 +1,1540 @@
1
+ if RUBY_PLATFORM =~ /java/
2
+ require 'java'
3
+ require 'jeventmachine'
4
+ else
5
+ begin
6
+ require 'rubyeventmachine'
7
+ rescue LoadError
8
+ warn "Unable to load the EventMachine C extension; To use the pure-ruby reactor, require 'em/pure_ruby'"
9
+ raise
10
+ end
11
+ end
12
+
13
+ require "em/version"
14
+ require 'em/deferrable'
15
+ require 'em/future'
16
+ require 'em/streamer'
17
+ require 'em/spawnable'
18
+ require 'em/processes'
19
+ require 'em/iterator'
20
+ require 'em/buftok'
21
+ require 'em/timers'
22
+ require 'em/protocols'
23
+ require 'em/connection'
24
+ require 'em/callback'
25
+ require 'em/queue'
26
+ require 'em/channel'
27
+ require 'em/file_watch'
28
+ require 'em/process_watch'
29
+ require 'em/tick_loop'
30
+
31
+ require 'shellwords'
32
+ require 'thread'
33
+
34
+ # == Introduction
35
+ # EventMachine provides a fast, lightweight framework for implementing
36
+ # Ruby programs that can use the network to communicate with other
37
+ # processes. Using EventMachine, Ruby programmers can easily connect
38
+ # to remote servers and act as servers themselves. EventMachine does not
39
+ # supplant the Ruby IP libraries. It does provide an alternate technique
40
+ # for those applications requiring better performance, scalability,
41
+ # and discipline over the behavior of network sockets, than is easily
42
+ # obtainable using the built-in libraries, especially in applications
43
+ # which are structurally well-suited for the event-driven programming model.
44
+ #
45
+ # EventMachine provides a perpetual event-loop which your programs can
46
+ # start and stop. Within the event loop, TCP network connections are
47
+ # initiated and accepted, based on EventMachine methods called by your
48
+ # program. You also define callback methods which are called by EventMachine
49
+ # when events of interest occur within the event-loop.
50
+ #
51
+ # User programs will be called back when the following events occur:
52
+ # * When the event loop accepts network connections from remote peers
53
+ # * When data is received from network connections
54
+ # * When connections are closed, either by the local or the remote side
55
+ # * When user-defined timers expire
56
+ #
57
+ # == Usage example
58
+ #
59
+ # Here's a fully-functional echo server implemented in EventMachine:
60
+ #
61
+ # require 'eventmachine'
62
+ #
63
+ # module EchoServer
64
+ # def post_init
65
+ # puts "-- someone connected to the echo server!"
66
+ # end
67
+ #
68
+ # def receive_data data
69
+ # send_data ">>>you sent: #{data}"
70
+ # close_connection if data =~ /quit/i
71
+ # end
72
+ #
73
+ # def unbind
74
+ # puts "-- someone disconnected from the echo server!"
75
+ # end
76
+ # end
77
+ #
78
+ # EventMachine::run {
79
+ # EventMachine::start_server "127.0.0.1", 8081, EchoServer
80
+ # }
81
+ #
82
+ # What's going on here? Well, we have defined the module EchoServer to
83
+ # implement the semantics of the echo protocol (more about that shortly).
84
+ # The last three lines invoke the event-machine itself, which runs forever
85
+ # unless one of your callbacks terminates it. The block that you supply
86
+ # to EventMachine::run contains code that runs immediately after the event
87
+ # machine is initialized and before it starts looping. This is the place
88
+ # to open up a TCP server by specifying the address and port it will listen
89
+ # on, together with the module that will process the data.
90
+ #
91
+ # Our EchoServer is extremely simple as the echo protocol doesn't require
92
+ # much work. Basically you want to send back to the remote peer whatever
93
+ # data it sends you. We'll dress it up with a little extra text to make it
94
+ # interesting. Also, we'll close the connection in case the received data
95
+ # contains the word "quit."
96
+ #
97
+ # So what about this module EchoServer? Well, whenever a network connection
98
+ # (either a client or a server) starts up, EventMachine instantiates an anonymous
99
+ # class, that your module has been mixed into. Exactly one of these class
100
+ # instances is created for each connection. Whenever an event occurs on a
101
+ # given connection, its corresponding object automatically calls specific
102
+ # instance methods which your module may redefine. The code in your module
103
+ # always runs in the context of a class instance, so you can create instance
104
+ # variables as you wish and they will be carried over to other callbacks
105
+ # made on that same connection.
106
+ #
107
+ # Looking back up at EchoServer, you can see that we've defined the method
108
+ # receive_data which (big surprise) is called whenever data has been received
109
+ # from the remote end of the connection. Very simple. We get the data
110
+ # (a String object) and can do whatever we wish with it. In this case,
111
+ # we use the method send_data to return the received data to the caller,
112
+ # with some extra text added in. And if the user sends the word "quit,"
113
+ # we'll close the connection with (naturally) close_connection.
114
+ # (Notice that closing the connection doesn't terminate the processing loop,
115
+ # or change the fact that your echo server is still accepting connections!)
116
+ #
117
+ # == Questions and Futures
118
+ # Would it be useful for EventMachine to incorporate the Observer pattern
119
+ # and make use of the corresponding Ruby <tt>observer</tt> package?
120
+ # Interesting thought.
121
+ #
122
+ module EventMachine
123
+ class <<self
124
+ # Exposed to allow joining on the thread, when run in a multithreaded
125
+ # environment. Performing other actions on the thread has undefined
126
+ # semantics.
127
+ attr_reader :reactor_thread
128
+ end
129
+ @next_tick_mutex = Mutex.new
130
+ @reactor_running = false
131
+ @next_tick_queue = []
132
+ @threadpool = nil
133
+
134
+
135
+ # EventMachine::run initializes and runs an event loop.
136
+ # This method only returns if user-callback code calls stop_event_loop.
137
+ # Use the supplied block to define your clients and servers.
138
+ # The block is called by EventMachine::run immediately after initializing
139
+ # its internal event loop but <i>before</i> running the loop.
140
+ # Therefore this block is the right place to call start_server if you
141
+ # want to accept connections from remote clients.
142
+ #
143
+ # For programs that are structured as servers, it's usually appropriate
144
+ # to start an event loop by calling EventMachine::run, and let it
145
+ # run forever. It's also possible to use EventMachine::run to make a single
146
+ # client-connection to a remote server, process the data flow from that
147
+ # single connection, and then call stop_event_loop to force EventMachine::run
148
+ # to return. Your program will then continue from the point immediately
149
+ # following the call to EventMachine::run.
150
+ #
151
+ # You can of course do both client and servers simultaneously in the same program.
152
+ # One of the strengths of the event-driven programming model is that the
153
+ # handling of network events on many different connections will be interleaved,
154
+ # and scheduled according to the actual events themselves. This maximizes
155
+ # efficiency.
156
+ #
157
+ # === Server usage example
158
+ #
159
+ # See EventMachine.start_server
160
+ #
161
+ # === Client usage example
162
+ #
163
+ # See EventMachine.connect
164
+ #
165
+ #--
166
+ # Obsoleted the use_threads mechanism.
167
+ # 25Nov06: Added the begin/ensure block. We need to be sure that release_machine
168
+ # gets called even if an exception gets thrown within any of the user code
169
+ # that the event loop runs. The best way to see this is to run a unit
170
+ # test with two functions, each of which calls EventMachine#run and each of
171
+ # which throws something inside of #run. Without the ensure, the second test
172
+ # will start without release_machine being called and will immediately throw
173
+ # a C++ runtime error.
174
+ #
175
+ def self.run blk=nil, tail=nil, &block
176
+ @tails ||= []
177
+ tail and @tails.unshift(tail)
178
+
179
+ if reactor_running?
180
+ (b = blk || block) and b.call # next_tick(b)
181
+ else
182
+ @conns = {}
183
+ @acceptors = {}
184
+ @timers = {}
185
+ @wrapped_exception = nil
186
+ @next_tick_queue ||= []
187
+ begin
188
+ @reactor_running = true
189
+ initialize_event_machine
190
+ (b = blk || block) and add_timer(0, b)
191
+ if @next_tick_queue && !@next_tick_queue.empty?
192
+ add_timer(0) { signal_loopbreak }
193
+ end
194
+ @reactor_thread = Thread.current
195
+ run_machine
196
+ ensure
197
+ until @tails.empty?
198
+ @tails.pop.call
199
+ end
200
+
201
+ begin
202
+ release_machine
203
+ ensure
204
+ if @threadpool
205
+ @threadpool.each { |t| t.exit }
206
+ @threadpool.each do |t|
207
+ next unless t.alive?
208
+ # ruby 1.9 has no kill!
209
+ t.respond_to?(:kill!) ? t.kill! : t.kill
210
+ end
211
+ @threadqueue = nil
212
+ @resultqueue = nil
213
+ @threadpool = nil
214
+ end
215
+
216
+ @next_tick_queue = []
217
+ end
218
+ @reactor_running = false
219
+ @reactor_thread = nil
220
+ end
221
+
222
+ raise @wrapped_exception if @wrapped_exception
223
+ end
224
+ end
225
+
226
+ # Sugars a common use case. Will pass the given block to #run, but will terminate
227
+ # the reactor loop and exit the function as soon as the code in the block completes.
228
+ # (Normally, #run keeps running indefinitely, even after the block supplied to it
229
+ # finishes running, until user code calls #stop.)
230
+ #
231
+ def self.run_block &block
232
+ pr = proc {
233
+ block.call
234
+ EventMachine::stop
235
+ }
236
+ run(&pr)
237
+ end
238
+
239
+ # Returns true if the calling thread is the same thread as the reactor.
240
+ def self.reactor_thread?
241
+ Thread.current == @reactor_thread
242
+ end
243
+
244
+ # Runs the given callback on the reactor thread, or immediately if called
245
+ # from the reactor thread. Accepts the same arguments as EM::Callback
246
+ def self.schedule(*a, &b)
247
+ cb = Callback(*a, &b)
248
+ if reactor_running? && reactor_thread?
249
+ cb.call
250
+ else
251
+ next_tick { cb.call }
252
+ end
253
+ end
254
+
255
+ # fork_reactor forks a new process and calls EM#run inside of it, passing your block.
256
+ #--
257
+ # This implementation is subject to change, especially if we clean up the relationship
258
+ # of EM#run to @reactor_running.
259
+ # Original patch by Aman Gupta.
260
+ #
261
+ def self.fork_reactor &block
262
+ Kernel.fork do
263
+ if self.reactor_running?
264
+ self.stop_event_loop
265
+ self.release_machine
266
+ self.instance_variable_set( '@reactor_running', false )
267
+ end
268
+ self.run block
269
+ end
270
+ end
271
+
272
+ # EventMachine#add_timer adds a one-shot timer to the event loop.
273
+ # Call it with one or two parameters. The first parameters is a delay-time
274
+ # expressed in <i>seconds</i> (not milliseconds). The second parameter, if
275
+ # present, must be a proc object. If a proc object is not given, then you
276
+ # can also simply pass a block to the method call.
277
+ #
278
+ # EventMachine#add_timer may be called from the block passed to EventMachine#run
279
+ # or from any callback method. It schedules execution of the proc or block
280
+ # passed to add_timer, after the passage of an interval of time equal to
281
+ # <i>at least</i> the number of seconds specified in the first parameter to
282
+ # the call.
283
+ #
284
+ # EventMachine#add_timer is a <i>non-blocking</i> call. Callbacks can and will
285
+ # be called during the interval of time that the timer is in effect.
286
+ # There is no built-in limit to the number of timers that can be outstanding at
287
+ # any given time.
288
+ #
289
+ # === Usage example
290
+ #
291
+ # This example shows how easy timers are to use. Observe that two timers are
292
+ # initiated simultaneously. Also, notice that the event loop will continue
293
+ # to run even after the second timer event is processed, since there was
294
+ # no call to EventMachine#stop_event_loop. There will be no activity, of
295
+ # course, since no network clients or servers are defined. Stop the program
296
+ # with Ctrl-C.
297
+ #
298
+ # EventMachine::run {
299
+ # puts "Starting the run now: #{Time.now}"
300
+ # EventMachine::add_timer 5, proc { puts "Executing timer event: #{Time.now}" }
301
+ # EventMachine::add_timer( 10 ) { puts "Executing timer event: #{Time.now}" }
302
+ # }
303
+ #
304
+ #
305
+ # Also see EventMachine::Timer
306
+ #--
307
+ # Changed 04Oct06: We now pass the interval as an integer number of milliseconds.
308
+ #
309
+ def self.add_timer *args, &block
310
+ interval = args.shift
311
+ code = args.shift || block
312
+ if code
313
+ # check too many timers!
314
+ s = add_oneshot_timer((interval.to_f * 1000).to_i)
315
+ @timers[s] = code
316
+ s
317
+ end
318
+ end
319
+
320
+ # EventMachine#add_periodic_timer adds a periodic timer to the event loop.
321
+ # It takes the same parameters as the one-shot timer method, EventMachine#add_timer.
322
+ # This method schedules execution of the given block repeatedly, at intervals
323
+ # of time <i>at least</i> as great as the number of seconds given in the first
324
+ # parameter to the call.
325
+ #
326
+ # === Usage example
327
+ #
328
+ # The following sample program will write a dollar-sign to stderr every five seconds.
329
+ # (Of course if the program defined network clients and/or servers, they would
330
+ # be doing their work while the periodic timer is counting off.)
331
+ #
332
+ # EventMachine::run {
333
+ # EventMachine::add_periodic_timer( 5 ) { $stderr.write "$" }
334
+ # }
335
+ #
336
+ #
337
+ # Also see EventMachine::PeriodicTimer
338
+ #
339
+ def self.add_periodic_timer *args, &block
340
+ interval = args.shift
341
+ code = args.shift || block
342
+
343
+ EventMachine::PeriodicTimer.new(interval, code)
344
+ end
345
+
346
+ # Cancel a timer using its signature. You can also use EventMachine::Timer#cancel
347
+ #
348
+ def self.cancel_timer timer_or_sig
349
+ if timer_or_sig.respond_to? :cancel
350
+ timer_or_sig.cancel
351
+ else
352
+ @timers[timer_or_sig] = false if @timers.has_key?(timer_or_sig)
353
+ end
354
+ end
355
+
356
+
357
+ # stop_event_loop may called from within a callback method
358
+ # while EventMachine's processing loop is running.
359
+ # It causes the processing loop to stop executing, which
360
+ # will cause all open connections and accepting servers
361
+ # to be run down and closed. <i>Callbacks for connection-termination
362
+ # will be called</i> as part of the processing of stop_event_loop.
363
+ # (There currently is no option to panic-stop the loop without
364
+ # closing connections.) When all of this processing is complete,
365
+ # the call to EventMachine::run which started the processing loop
366
+ # will return and program flow will resume from the statement
367
+ # following EventMachine::run call.
368
+ #
369
+ # === Usage example
370
+ #
371
+ # require 'rubygems'
372
+ # require 'eventmachine'
373
+ #
374
+ # module Redmond
375
+ # def post_init
376
+ # puts "We're sending a dumb HTTP request to the remote peer."
377
+ # send_data "GET / HTTP/1.1\r\nHost: www.microsoft.com\r\n\r\n"
378
+ # end
379
+ #
380
+ # def receive_data data
381
+ # puts "We received #{data.length} bytes from the remote peer."
382
+ # puts "We're going to stop the event loop now."
383
+ # EventMachine::stop_event_loop
384
+ # end
385
+ #
386
+ # def unbind
387
+ # puts "A connection has terminated."
388
+ # end
389
+ # end
390
+ #
391
+ # puts "We're starting the event loop now."
392
+ # EventMachine::run {
393
+ # EventMachine::connect "www.microsoft.com", 80, Redmond
394
+ # }
395
+ # puts "The event loop has stopped."
396
+ #
397
+ # This program will produce approximately the following output:
398
+ #
399
+ # We're starting the event loop now.
400
+ # We're sending a dumb HTTP request to the remote peer.
401
+ # We received 1440 bytes from the remote peer.
402
+ # We're going to stop the event loop now.
403
+ # A connection has terminated.
404
+ # The event loop has stopped.
405
+ #
406
+ #
407
+ def self.stop_event_loop
408
+ EventMachine::stop
409
+ end
410
+
411
+ # EventMachine::start_server initiates a TCP server (socket
412
+ # acceptor) on the specified IP address and port.
413
+ # The IP address must be valid on the machine where the program
414
+ # runs, and the process must be privileged enough to listen
415
+ # on the specified port (on Unix-like systems, superuser privileges
416
+ # are usually required to listen on any port lower than 1024).
417
+ # Only one listener may be running on any given address/port
418
+ # combination. start_server will fail if the given address and port
419
+ # are already listening on the machine, either because of a prior call
420
+ # to start_server or some unrelated process running on the machine.
421
+ # If start_server succeeds, the new network listener becomes active
422
+ # immediately and starts accepting connections from remote peers,
423
+ # and these connections generate callback events that are processed
424
+ # by the code specified in the handler parameter to start_server.
425
+ #
426
+ # The optional handler which is passed to start_server is the key
427
+ # to EventMachine's ability to handle particular network protocols.
428
+ # The handler parameter passed to start_server must be a Ruby Module
429
+ # that you must define. When the network server that is started by
430
+ # start_server accepts a new connection, it instantiates a new
431
+ # object of an anonymous class that is inherited from EventMachine::Connection,
432
+ # <i>into which the methods from your handler have been mixed.</i>
433
+ # Your handler module may redefine any of the methods in EventMachine::Connection
434
+ # in order to implement the specific behavior of the network protocol.
435
+ #
436
+ # Callbacks invoked in response to network events <i>always</i> take place
437
+ # within the execution context of the object derived from EventMachine::Connection
438
+ # extended by your handler module. There is one object per connection, and
439
+ # all of the callbacks invoked for a particular connection take the form
440
+ # of instance methods called against the corresponding EventMachine::Connection
441
+ # object. Therefore, you are free to define whatever instance variables you
442
+ # wish, in order to contain the per-connection state required by the network protocol you are
443
+ # implementing.
444
+ #
445
+ # start_server is often called inside the block passed to EventMachine::run,
446
+ # but it can be called from any EventMachine callback. start_server will fail
447
+ # unless the EventMachine event loop is currently running (which is why
448
+ # it's often called in the block suppled to EventMachine::run).
449
+ #
450
+ # You may call start_server any number of times to start up network
451
+ # listeners on different address/port combinations. The servers will
452
+ # all run simultaneously. More interestingly, each individual call to start_server
453
+ # can specify a different handler module and thus implement a different
454
+ # network protocol from all the others.
455
+ #
456
+ # === Usage example
457
+ # Here is an example of a server that counts lines of input from the remote
458
+ # peer and sends back the total number of lines received, after each line.
459
+ # Try the example with more than one client connection opened via telnet,
460
+ # and you will see that the line count increments independently on each
461
+ # of the client connections. Also very important to note, is that the
462
+ # handler for the receive_data function, which our handler redefines, may
463
+ # not assume that the data it receives observes any kind of message boundaries.
464
+ # Also, to use this example, be sure to change the server and port parameters
465
+ # to the start_server call to values appropriate for your environment.
466
+ #
467
+ # require 'rubygems'
468
+ # require 'eventmachine'
469
+ #
470
+ # module LineCounter
471
+ # MaxLinesPerConnection = 10
472
+ #
473
+ # def post_init
474
+ # puts "Received a new connection"
475
+ # @data_received = ""
476
+ # @line_count = 0
477
+ # end
478
+ #
479
+ # def receive_data data
480
+ # @data_received << data
481
+ # while @data_received.slice!( /^[^\n]*[\n]/m )
482
+ # @line_count += 1
483
+ # send_data "received #{@line_count} lines so far\r\n"
484
+ # @line_count == MaxLinesPerConnection and close_connection_after_writing
485
+ # end
486
+ # end
487
+ # end
488
+ #
489
+ # EventMachine::run {
490
+ # host,port = "192.168.0.100", 8090
491
+ # EventMachine::start_server host, port, LineCounter
492
+ # puts "Now accepting connections on address #{host}, port #{port}..."
493
+ # EventMachine::add_periodic_timer( 10 ) { $stderr.write "*" }
494
+ # }
495
+ #
496
+ #
497
+ def self.start_server server, port=nil, handler=nil, *args, &block
498
+ begin
499
+ port = Integer(port)
500
+ rescue ArgumentError, TypeError
501
+ # there was no port, so server must be a unix domain socket
502
+ # the port argument is actually the handler, and the handler is one of the args
503
+ args.unshift handler if handler
504
+ handler = port
505
+ port = nil
506
+ end if port
507
+
508
+ klass = klass_from_handler(Connection, handler, *args)
509
+
510
+ s = if port
511
+ start_tcp_server server, port
512
+ else
513
+ start_unix_server server
514
+ end
515
+ @acceptors[s] = [klass,args,block]
516
+ s
517
+ end
518
+
519
+
520
+ # Stop a TCP server socket that was started with EventMachine#start_server.
521
+ #--
522
+ # Requested by Kirk Haines. TODO, this isn't OOP enough. We ought somehow
523
+ # to have #start_server return an object that has a close or a stop method on it.
524
+ #
525
+ def self.stop_server signature
526
+ EventMachine::stop_tcp_server signature
527
+ end
528
+
529
+ # Start a Unix-domain server
530
+ #
531
+ # Note that this is an alias for EventMachine::start_server, which can be used to start both
532
+ # TCP and Unix-domain servers
533
+ def self.start_unix_domain_server filename, *args, &block
534
+ start_server filename, *args, &block
535
+ end
536
+
537
+ # EventMachine#connect initiates a TCP connection to a remote
538
+ # server and sets up event-handling for the connection.
539
+ # You can call EventMachine#connect in the block supplied
540
+ # to EventMachine#run or in any callback method.
541
+ #
542
+ # EventMachine#connect takes the IP address (or hostname) and
543
+ # port of the remote server you want to connect to.
544
+ # It also takes an optional handler Module which you must define, that
545
+ # contains the callbacks that will be invoked by the event loop
546
+ # on behalf of the connection.
547
+ #
548
+ # See the description of EventMachine#start_server for a discussion
549
+ # of the handler Module. All of the details given in that description
550
+ # apply for connections created with EventMachine#connect.
551
+ #
552
+ # === Usage Example
553
+ #
554
+ # Here's a program which connects to a web server, sends a naive
555
+ # request, parses the HTTP header of the response, and then
556
+ # (antisocially) ends the event loop, which automatically drops the connection
557
+ # (and incidentally calls the connection's unbind method).
558
+ #
559
+ # module DumbHttpClient
560
+ # def post_init
561
+ # send_data "GET / HTTP/1.1\r\nHost: _\r\n\r\n"
562
+ # @data = ""
563
+ # @parsed = false
564
+ # end
565
+ #
566
+ # def receive_data data
567
+ # @data << data
568
+ # if !@parsed and @data =~ /[\n][\r]*[\n]/m
569
+ # @parsed = true
570
+ # puts "RECEIVED HTTP HEADER:"
571
+ # $`.each {|line| puts ">>> #{line}" }
572
+ #
573
+ # puts "Now we'll terminate the loop, which will also close the connection"
574
+ # EventMachine::stop_event_loop
575
+ # end
576
+ # end
577
+ #
578
+ # def unbind
579
+ # puts "A connection has terminated"
580
+ # end
581
+ # end
582
+ #
583
+ # EventMachine::run {
584
+ # EventMachine::connect "www.bayshorenetworks.com", 80, DumbHttpClient
585
+ # }
586
+ # puts "The event loop has ended"
587
+ #
588
+ #
589
+ # There are times when it's more convenient to define a protocol handler
590
+ # as a Class rather than a Module. Here's how to do this:
591
+ #
592
+ # class MyProtocolHandler < EventMachine::Connection
593
+ # def initialize *args
594
+ # super
595
+ # # whatever else you want to do here
596
+ # end
597
+ #
598
+ # #.......your other class code
599
+ # end
600
+ #
601
+ # If you do this, then an instance of your class will be instantiated to handle
602
+ # every network connection created by your code or accepted by servers that you
603
+ # create. If you redefine #post_init in your protocol-handler class, your
604
+ # #post_init method will be called _inside_ the call to #super that you will
605
+ # make in your #initialize method (if you provide one).
606
+ #
607
+ #--
608
+ # EventMachine::connect initiates a TCP connection to a remote
609
+ # server and sets up event-handling for the connection.
610
+ # It internally creates an object that should not be handled
611
+ # by the caller. HOWEVER, it's often convenient to get the
612
+ # object to set up interfacing to other objects in the system.
613
+ # We return the newly-created anonymous-class object to the caller.
614
+ # It's expected that a considerable amount of code will depend
615
+ # on this behavior, so don't change it.
616
+ #
617
+ # Ok, added support for a user-defined block, 13Apr06.
618
+ # This leads us to an interesting choice because of the
619
+ # presence of the post_init call, which happens in the
620
+ # initialize method of the new object. We call the user's
621
+ # block and pass the new object to it. This is a great
622
+ # way to do protocol-specific initiation. It happens
623
+ # AFTER post_init has been called on the object, which I
624
+ # certainly hope is the right choice.
625
+ # Don't change this lightly, because accepted connections
626
+ # are different from connected ones and we don't want
627
+ # to have them behave differently with respect to post_init
628
+ # if at all possible.
629
+ #
630
+ def self.connect server, port=nil, handler=nil, *args, &blk
631
+ bind_connect nil, nil, server, port, handler, *args, &blk
632
+ end
633
+
634
+ # EventMachine::bind_connect is like EventMachine::connect, but allows for a local address/port
635
+ # to bind the connection to.
636
+ def self.bind_connect bind_addr, bind_port, server, port=nil, handler=nil, *args
637
+ begin
638
+ port = Integer(port)
639
+ rescue ArgumentError, TypeError
640
+ # there was no port, so server must be a unix domain socket
641
+ # the port argument is actually the handler, and the handler is one of the args
642
+ args.unshift handler if handler
643
+ handler = port
644
+ port = nil
645
+ end if port
646
+
647
+ klass = klass_from_handler(Connection, handler, *args)
648
+
649
+ s = if port
650
+ if bind_addr
651
+ bind_connect_server bind_addr, bind_port.to_i, server, port
652
+ else
653
+ connect_server server, port
654
+ end
655
+ else
656
+ connect_unix_server server
657
+ end
658
+
659
+ c = klass.new s, *args
660
+ @conns[s] = c
661
+ block_given? and yield c
662
+ c
663
+ end
664
+
665
+ # EventMachine::watch registers a given file descriptor or IO object with the eventloop. The
666
+ # file descriptor will not be modified (it will remain blocking or non-blocking).
667
+ #
668
+ # The eventloop can be used to process readable and writable events on the file descriptor, using
669
+ # EventMachine::Connection#notify_readable= and EventMachine::Connection#notify_writable=
670
+ #
671
+ # EventMachine::Connection#notify_readable? and EventMachine::Connection#notify_writable? can be used
672
+ # to check what events are enabled on the connection.
673
+ #
674
+ # To detach the file descriptor, use EventMachine::Connection#detach
675
+ #
676
+ # === Usage Example
677
+ #
678
+ # module SimpleHttpClient
679
+ # def notify_readable
680
+ # header = @io.readline
681
+ #
682
+ # if header == "\r\n"
683
+ # # detach returns the file descriptor number (fd == @io.fileno)
684
+ # fd = detach
685
+ # end
686
+ # rescue EOFError
687
+ # detach
688
+ # end
689
+ #
690
+ # def unbind
691
+ # EM.next_tick do
692
+ # # socket is detached from the eventloop, but still open
693
+ # data = @io.read
694
+ # end
695
+ # end
696
+ # end
697
+ #
698
+ # EM.run{
699
+ # $sock = TCPSocket.new('site.com', 80)
700
+ # $sock.write("GET / HTTP/1.0\r\n\r\n")
701
+ # conn = EM.watch $sock, SimpleHttpClient
702
+ # conn.notify_readable = true
703
+ # }
704
+ #
705
+ #--
706
+ # Thanks to Riham Aldakkak (eSpace Technologies) for the initial patch
707
+ def EventMachine::watch io, handler=nil, *args, &blk
708
+ attach_io io, true, handler, *args, &blk
709
+ end
710
+
711
+ # Attaches an IO object or file descriptor to the eventloop as a regular connection.
712
+ # The file descriptor will be set as non-blocking, and EventMachine will process
713
+ # receive_data and send_data events on it as it would for any other connection.
714
+ #
715
+ # To watch a fd instead, use EventMachine::watch, which will not alter the state of the socket
716
+ # and fire notify_readable and notify_writable events instead.
717
+ def EventMachine::attach io, handler=nil, *args, &blk
718
+ attach_io io, false, handler, *args, &blk
719
+ end
720
+
721
+ def EventMachine::attach_io io, watch_mode, handler=nil, *args # :nodoc:
722
+ klass = klass_from_handler(Connection, handler, *args)
723
+
724
+ if !watch_mode and klass.public_instance_methods.any?{|m| [:notify_readable, :notify_writable].include? m.to_sym }
725
+ raise ArgumentError, "notify_readable/writable with EM.attach is not supported. Use EM.watch(io){ |c| c.notify_readable = true }"
726
+ end
727
+
728
+ if io.respond_to?(:fileno)
729
+ fd = defined?(JRuby) ? JRuby.runtime.getDescriptorByFileno(io.fileno).getChannel : io.fileno
730
+ else
731
+ fd = io
732
+ end
733
+
734
+ s = attach_fd fd, watch_mode
735
+ c = klass.new s, *args
736
+
737
+ c.instance_variable_set(:@io, io)
738
+ c.instance_variable_set(:@fd, fd)
739
+
740
+ @conns[s] = c
741
+ block_given? and yield c
742
+ c
743
+ end
744
+
745
+
746
+ # Connect to a given host/port and re-use the provided EventMachine::Connection instance
747
+ #--
748
+ # Observe, the test for already-connected FAILS if we call a reconnect inside post_init,
749
+ # because we haven't set up the connection in @conns by that point.
750
+ # RESIST THE TEMPTATION to "fix" this problem by redefining the behavior of post_init.
751
+ #
752
+ # Changed 22Nov06: if called on an already-connected handler, just return the
753
+ # handler and do nothing more. Originally this condition raised an exception.
754
+ # We may want to change it yet again and call the block, if any.
755
+ #
756
+ def self.reconnect server, port, handler # :nodoc:
757
+ raise "invalid handler" unless handler.respond_to?(:connection_completed)
758
+ #raise "still connected" if @conns.has_key?(handler.signature)
759
+ return handler if @conns.has_key?(handler.signature)
760
+
761
+ s = connect_server server, port
762
+ handler.signature = s
763
+ @conns[s] = handler
764
+ block_given? and yield handler
765
+ handler
766
+ end
767
+
768
+
769
+ # Make a connection to a Unix-domain socket. This is not implemented on Windows platforms.
770
+ # The parameter socketname is a String which identifies the Unix-domain socket you want
771
+ # to connect to. socketname is the name of a file on your local system, and in most cases
772
+ # is a fully-qualified path name. Make sure that your process has enough local permissions
773
+ # to open the Unix-domain socket.
774
+ # See also the documentation for #connect. This method behaves like #connect
775
+ # in all respects except for the fact that it connects to a local Unix-domain
776
+ # socket rather than a TCP socket.
777
+ #
778
+ # Note that this method is simply an alias for #connect, which can connect to both TCP
779
+ # and Unix-domain sockets
780
+ #--
781
+ # For making connections to Unix-domain sockets.
782
+ # Eventually this has to get properly documented and unified with the TCP-connect methods.
783
+ # Note how nearly identical this is to EventMachine#connect
784
+ def self.connect_unix_domain socketname, *args, &blk
785
+ connect socketname, *args, &blk
786
+ end
787
+
788
+
789
+ # EventMachine#open_datagram_socket is for support of UDP-based
790
+ # protocols. Its usage is similar to that of EventMachine#start_server.
791
+ # It takes three parameters: an IP address (which must be valid
792
+ # on the machine which executes the method), a port number,
793
+ # and an optional Module name which will handle the data.
794
+ # This method will create a new UDP (datagram) socket and
795
+ # bind it to the address and port that you specify.
796
+ # The normal callbacks (see EventMachine#start_server) will
797
+ # be called as events of interest occur on the newly-created
798
+ # socket, but there are some differences in how they behave.
799
+ #
800
+ # Connection#receive_data will be called when a datagram packet
801
+ # is received on the socket, but unlike TCP sockets, the message
802
+ # boundaries of the received data will be respected. In other words,
803
+ # if the remote peer sent you a datagram of a particular size,
804
+ # you may rely on Connection#receive_data to give you the
805
+ # exact data in the packet, with the original data length.
806
+ # Also observe that Connection#receive_data may be called with a
807
+ # <i>zero-length</i> data payload, since empty datagrams are permitted
808
+ # in UDP.
809
+ #
810
+ # Connection#send_data is available with UDP packets as with TCP,
811
+ # but there is an important difference. Because UDP communications
812
+ # are <i>connectionless,</i> there is no implicit recipient for the packets you
813
+ # send. Ordinarily you must specify the recipient for each packet you send.
814
+ # However, EventMachine
815
+ # provides for the typical pattern of receiving a UDP datagram
816
+ # from a remote peer, performing some operation, and then sending
817
+ # one or more packets in response to the same remote peer.
818
+ # To support this model easily, just use Connection#send_data
819
+ # in the code that you supply for Connection:receive_data.
820
+ # EventMachine will
821
+ # provide an implicit return address for any messages sent to
822
+ # Connection#send_data within the context of a Connection#receive_data callback,
823
+ # and your response will automatically go to the correct remote peer.
824
+ # (TODO: Example-code needed!)
825
+ #
826
+ # Observe that the port number that you supply to EventMachine#open_datagram_socket
827
+ # may be zero. In this case, EventMachine will create a UDP socket
828
+ # that is bound to an <i>ephemeral</i> (not well-known) port.
829
+ # This is not appropriate for servers that must publish a well-known
830
+ # port to which remote peers may send datagrams. But it can be useful
831
+ # for clients that send datagrams to other servers.
832
+ # If you do this, you will receive any responses from the remote
833
+ # servers through the normal Connection#receive_data callback.
834
+ # Observe that you will probably have issues with firewalls blocking
835
+ # the ephemeral port numbers, so this technique is most appropriate for LANs.
836
+ # (TODO: Need an example!)
837
+ #
838
+ # If you wish to send datagrams to arbitrary remote peers (not
839
+ # necessarily ones that have sent data to which you are responding),
840
+ # then see Connection#send_datagram.
841
+ #
842
+ # DO NOT call send_data from a datagram socket
843
+ # outside of a #receive_data method. Use #send_datagram. If you do use #send_data
844
+ # outside of a #receive_data method, you'll get a confusing error
845
+ # because there is no "peer," as #send_data requires. (Inside of #receive_data,
846
+ # #send_data "fakes" the peer as described above.)
847
+ #
848
+ #--
849
+ # Replaced the implementation on 01Oct06. Thanks to Tobias Gustafsson for pointing
850
+ # out that this originally did not take a class but only a module.
851
+ #
852
+ def self.open_datagram_socket address, port, handler=nil, *args
853
+ klass = klass_from_handler(Connection, handler, *args)
854
+ s = open_udp_socket address, port.to_i
855
+ c = klass.new s, *args
856
+ @conns[s] = c
857
+ block_given? and yield c
858
+ c
859
+ end
860
+
861
+
862
+ # For advanced users. This function sets the default timer granularity, which by default is
863
+ # slightly smaller than 100 milliseconds. Call this function to set a higher or lower granularity.
864
+ # The function affects the behavior of #add_timer and #add_periodic_timer. Most applications
865
+ # will not need to call this function.
866
+ #
867
+ # The argument is a number of milliseconds. Avoid setting the quantum to very low values because
868
+ # that may reduce performance under some extreme conditions. We recommend that you not set a quantum
869
+ # lower than 10.
870
+ #
871
+ # You may only call this function while an EventMachine loop is running (that is, after a call to
872
+ # EventMachine#run and before a subsequent call to EventMachine#stop).
873
+ #
874
+ def self.set_quantum mills
875
+ set_timer_quantum mills.to_i
876
+ end
877
+
878
+ # Sets the maximum number of timers and periodic timers that may be outstanding at any
879
+ # given time. You only need to call #set_max_timers if you need more than the default
880
+ # number of timers, which on most platforms is 1000.
881
+ # Call this method before calling EventMachine#run.
882
+ #
883
+ def self.set_max_timers ct
884
+ set_max_timer_count ct
885
+ end
886
+
887
+ # Gets the current maximum number of allowed timers
888
+ #
889
+ def self.get_max_timers
890
+ get_max_timer_count
891
+ end
892
+
893
+ # Returns the total number of connections (file descriptors) currently held by the reactor.
894
+ # Note that a tick must pass after the 'initiation' of a connection for this number to increment.
895
+ # It's usually accurate, but don't rely on the exact precision of this number unless you really know EM internals.
896
+ #
897
+ # For example, $count will be 0 in this case:
898
+ #
899
+ # EM.run {
900
+ # EM.connect("rubyeventmachine.com", 80)
901
+ # $count = EM.connection_count
902
+ # }
903
+ #
904
+ # In this example, $count will be 1 since the connection has been established in the next loop of the reactor.
905
+ #
906
+ # EM.run {
907
+ # EM.connect("rubyeventmachine.com", 80)
908
+ # EM.next_tick {
909
+ # $count = EM.connection_count
910
+ # }
911
+ # }
912
+ #
913
+ def self.connection_count
914
+ self.get_connection_count
915
+ end
916
+
917
+ #--
918
+ # The is the responder for the loopback-signalled event.
919
+ # It can be fired either by code running on a separate thread (EM#defer) or on
920
+ # the main thread (EM#next_tick).
921
+ # It will often happen that a next_tick handler will reschedule itself. We
922
+ # consume a copy of the tick queue so that tick events scheduled by tick events
923
+ # have to wait for the next pass through the reactor core.
924
+ #
925
+ def self.run_deferred_callbacks # :nodoc:
926
+ until (@resultqueue ||= []).empty?
927
+ result,cback = @resultqueue.pop
928
+ cback.call result if cback
929
+ end
930
+
931
+ @next_tick_mutex.synchronize do
932
+ jobs, @next_tick_queue = @next_tick_queue, []
933
+ jobs
934
+ end.each { |j| j.call }
935
+ end
936
+
937
+
938
+ # #defer is for integrating blocking operations into EventMachine's control flow.
939
+ # Call #defer with one or two blocks, as shown below (the second block is <i>optional</i>):
940
+ #
941
+ # operation = proc {
942
+ # # perform a long-running operation here, such as a database query.
943
+ # "result" # as usual, the last expression evaluated in the block will be the return value.
944
+ # }
945
+ # callback = proc {|result|
946
+ # # do something with result here, such as send it back to a network client.
947
+ # }
948
+ #
949
+ # EventMachine.defer( operation, callback )
950
+ #
951
+ # The action of #defer is to take the block specified in the first parameter (the "operation")
952
+ # and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
953
+ # When the operation completes, it will pass the result computed by the block (if any)
954
+ # back to the EventMachine reactor. Then, EventMachine calls the block specified in the
955
+ # second parameter to #defer (the "callback"), as part of its normal, synchronous
956
+ # event handling loop. The result computed by the operation block is passed as a parameter
957
+ # to the callback. You may omit the callback parameter if you don't need to execute any code
958
+ # after the operation completes.
959
+ #
960
+ # == Caveats
961
+ # Note carefully that the code in your deferred operation will be executed on a separate
962
+ # thread from the main EventMachine processing and all other Ruby threads that may exist in
963
+ # your program. Also, multiple deferred operations may be running at once! Therefore, you
964
+ # are responsible for ensuring that your operation code is threadsafe. [Need more explanation
965
+ # and examples.]
966
+ # Don't write a deferred operation that will block forever. If so, the current implementation will
967
+ # not detect the problem, and the thread will never be returned to the pool. EventMachine limits
968
+ # the number of threads in its pool, so if you do this enough times, your subsequent deferred
969
+ # operations won't get a chance to run. [We might put in a timer to detect this problem.]
970
+ #
971
+ #--
972
+ # OBSERVE that #next_tick hacks into this mechanism, so don't make any changes here
973
+ # without syncing there.
974
+ #
975
+ # Running with $VERBOSE set to true gives a warning unless all ivars are defined when
976
+ # they appear in rvalues. But we DON'T ever want to initialize @threadqueue unless we
977
+ # need it, because the Ruby threads are so heavyweight. We end up with this bizarre
978
+ # way of initializing @threadqueue because EventMachine is a Module, not a Class, and
979
+ # has no constructor.
980
+ #
981
+ def self.defer op = nil, callback = nil, &blk
982
+ unless @threadpool
983
+ require 'thread'
984
+ @threadpool = []
985
+ @threadqueue = ::Queue.new
986
+ @resultqueue = ::Queue.new
987
+ spawn_threadpool
988
+ end
989
+
990
+ @threadqueue << [op||blk,callback]
991
+ end
992
+
993
+ def self.spawn_threadpool # :nodoc:
994
+ until @threadpool.size == @threadpool_size.to_i
995
+ thread = Thread.new do
996
+ Thread.current.abort_on_exception = true
997
+ while true
998
+ op, cback = *@threadqueue.pop
999
+ result = op.call
1000
+ @resultqueue << [result, cback]
1001
+ EventMachine.signal_loopbreak
1002
+ end
1003
+ end
1004
+ @threadpool << thread
1005
+ end
1006
+ end
1007
+
1008
+ class << self
1009
+ attr_reader :threadpool # :nodoc:
1010
+
1011
+ # Size of the EventMachine.defer threadpool (defaults to 20)
1012
+ attr_accessor :threadpool_size
1013
+ EventMachine.threadpool_size = 20
1014
+ end
1015
+
1016
+ # Schedules a proc for execution immediately after the next "turn" through the reactor
1017
+ # core. An advanced technique, this can be useful for improving memory management and/or
1018
+ # application responsiveness, especially when scheduling large amounts of data for
1019
+ # writing to a network connection. TODO, we need a FAQ entry on this subject.
1020
+ #
1021
+ # #next_tick takes either a single argument (which must be a Proc) or a block.
1022
+ #--
1023
+ # This works by adding to the @resultqueue that's used for #defer.
1024
+ # The general idea is that next_tick is used when we want to give the reactor a chance
1025
+ # to let other operations run, either to balance the load out more evenly, or to let
1026
+ # outbound network buffers drain, or both. So we probably do NOT want to block, and
1027
+ # we probably do NOT want to be spinning any threads. A program that uses next_tick
1028
+ # but not #defer shouldn't suffer the penalty of having Ruby threads running. They're
1029
+ # extremely expensive even if they're just sleeping.
1030
+ #
1031
+ def self.next_tick pr=nil, &block
1032
+ raise ArgumentError, "no proc or block given" unless ((pr && pr.respond_to?(:call)) or block)
1033
+ @next_tick_mutex.synchronize do
1034
+ @next_tick_queue << ( pr || block )
1035
+ end
1036
+ signal_loopbreak if reactor_running?
1037
+ end
1038
+
1039
+ # A wrapper over the setuid system call. Particularly useful when opening a network
1040
+ # server on a privileged port because you can use this call to drop privileges
1041
+ # after opening the port. Also very useful after a call to #set_descriptor_table_size,
1042
+ # which generally requires that you start your process with root privileges.
1043
+ #
1044
+ # This method has no effective implementation on Windows or in the pure-Ruby
1045
+ # implementation of EventMachine.
1046
+ # Call #set_effective_user by passing it a string containing the effective name
1047
+ # of the user whose privilege-level your process should attain.
1048
+ # This method is intended for use in enforcing security requirements, consequently
1049
+ # it will throw a fatal error and end your program if it fails.
1050
+ #
1051
+ def self.set_effective_user username
1052
+ EventMachine::setuid_string username
1053
+ end
1054
+
1055
+
1056
+ # Sets the maximum number of file or socket descriptors that your process may open.
1057
+ # You can pass this method an integer specifying the new size of the descriptor table.
1058
+ # Returns the new descriptor-table size, which may be less than the number you
1059
+ # requested. If you call this method with no arguments, it will simply return
1060
+ # the current size of the descriptor table without attempting to change it.
1061
+ #
1062
+ # The new limit on open descriptors ONLY applies to sockets and other descriptors
1063
+ # that belong to EventMachine. It has NO EFFECT on the number of descriptors
1064
+ # you can create in ordinary Ruby code.
1065
+ #
1066
+ # Not available on all platforms. Increasing the number of descriptors beyond its
1067
+ # default limit usually requires superuser privileges. (See #set_effective_user
1068
+ # for a way to drop superuser privileges while your program is running.)
1069
+ #
1070
+ def self.set_descriptor_table_size n_descriptors=nil
1071
+ EventMachine::set_rlimit_nofile n_descriptors
1072
+ end
1073
+
1074
+
1075
+
1076
+ # Run an external process. This does not currently work on Windows.
1077
+ #
1078
+ # module RubyCounter
1079
+ # def post_init
1080
+ # # count up to 5
1081
+ # send_data "5\n"
1082
+ # end
1083
+ # def receive_data data
1084
+ # puts "ruby sent me: #{data}"
1085
+ # end
1086
+ # def unbind
1087
+ # puts "ruby died with exit status: #{get_status.exitstatus}"
1088
+ # end
1089
+ # end
1090
+ #
1091
+ # EM.run{
1092
+ # EM.popen("ruby -e' $stdout.sync = true; gets.to_i.times{ |i| puts i+1; sleep 1 } '", RubyCounter)
1093
+ # }
1094
+ #
1095
+ # Also see EventMachine::DeferrableChildProcess and EventMachine.system
1096
+ #--
1097
+ # At this moment, it's only available on Unix.
1098
+ # Perhaps misnamed since the underlying function uses socketpair and is full-duplex.
1099
+ #
1100
+ def self.popen cmd, handler=nil, *args
1101
+ klass = klass_from_handler(Connection, handler, *args)
1102
+ w = Shellwords::shellwords( cmd )
1103
+ w.unshift( w.first ) if w.first
1104
+ s = invoke_popen( w )
1105
+ c = klass.new s, *args
1106
+ @conns[s] = c
1107
+ yield(c) if block_given?
1108
+ c
1109
+ end
1110
+
1111
+
1112
+ # Tells you whether the EventMachine reactor loop is currently running. Returns true or
1113
+ # false. Useful when writing libraries that want to run event-driven code, but may
1114
+ # be running in programs that are already event-driven. In such cases, if EventMachine#reactor_running?
1115
+ # returns false, your code can invoke EventMachine#run and run your application code inside
1116
+ # the block passed to that method. If EventMachine#reactor_running? returns true, just
1117
+ # execute your event-aware code.
1118
+ #
1119
+ # This method is necessary because calling EventMachine#run inside of another call to
1120
+ # EventMachine#run generates a fatal error.
1121
+ #
1122
+ def self.reactor_running?
1123
+ (@reactor_running || false)
1124
+ end
1125
+
1126
+
1127
+ # (Experimental)
1128
+ #
1129
+ #
1130
+ def self.open_keyboard handler=nil, *args
1131
+ klass = klass_from_handler(Connection, handler, *args)
1132
+
1133
+ s = read_keyboard
1134
+ c = klass.new s, *args
1135
+ @conns[s] = c
1136
+ block_given? and yield c
1137
+ c
1138
+ end
1139
+
1140
+ # EventMachine's file monitoring API. Currently supported are the following events
1141
+ # on individual files, using inotify on Linux systems, and kqueue for OSX/BSD:
1142
+ #
1143
+ # * File modified (written to)
1144
+ # * File moved/renamed
1145
+ # * File deleted
1146
+ #
1147
+ # EventMachine::watch_file takes a filename and a handler Module containing your custom callback methods.
1148
+ # This will setup the low level monitoring on the specified file, and create a new EventMachine::FileWatch
1149
+ # object with your Module mixed in. FileWatch is a subclass of EM::Connection, so callbacks on this object
1150
+ # work in the familiar way. The callbacks that will be fired by EventMachine are:
1151
+ #
1152
+ # * file_modified
1153
+ # * file_moved
1154
+ # * file_deleted
1155
+ #
1156
+ # You can access the filename being monitored from within this object using FileWatch#path.
1157
+ #
1158
+ # When a file is deleted, FileWatch#stop_watching will be called after your file_deleted callback,
1159
+ # to clean up the underlying monitoring and remove EventMachine's reference to the now-useless FileWatch.
1160
+ # This will in turn call unbind, if you wish to use it.
1161
+ #
1162
+ # The corresponding system-level Errno will be raised when attempting to monitor non-existent files,
1163
+ # files with wrong permissions, or if an error occurs dealing with inotify/kqueue.
1164
+ #
1165
+ # === Usage example:
1166
+ #
1167
+ # Make sure we have a file to monitor:
1168
+ # $ echo "bar" > /tmp/foo
1169
+ #
1170
+ # module Handler
1171
+ # def file_modified
1172
+ # puts "#{path} modified"
1173
+ # end
1174
+ #
1175
+ # def file_moved
1176
+ # puts "#{path} moved"
1177
+ # end
1178
+ #
1179
+ # def file_deleted
1180
+ # puts "#{path} deleted"
1181
+ # end
1182
+ #
1183
+ # def unbind
1184
+ # puts "#{path} monitoring ceased"
1185
+ # end
1186
+ # end
1187
+ #
1188
+ # EM.kqueue = true if EM.kqueue? # file watching requires kqueue on OSX
1189
+ #
1190
+ # EM.run {
1191
+ # EM.watch_file("/tmp/foo", Handler)
1192
+ # }
1193
+ #
1194
+ # $ echo "baz" >> /tmp/foo => "/tmp/foo modified"
1195
+ # $ mv /tmp/foo /tmp/oof => "/tmp/foo moved"
1196
+ # $ rm /tmp/oof => "/tmp/foo deleted"
1197
+ # => "/tmp/foo monitoring ceased"
1198
+ #
1199
+ # Note that we have not implemented the ability to pick up on the new filename after a rename.
1200
+ # Calling #path will always return the filename you originally used.
1201
+ #
1202
+ def self.watch_file(filename, handler=nil, *args)
1203
+ klass = klass_from_handler(FileWatch, handler, *args)
1204
+
1205
+ s = EM::watch_filename(filename)
1206
+ c = klass.new s, *args
1207
+ # we have to set the path like this because of how Connection.new works
1208
+ c.instance_variable_set("@path", filename)
1209
+ @conns[s] = c
1210
+ block_given? and yield c
1211
+ c
1212
+ end
1213
+
1214
+ # EventMachine's process monitoring API. Currently supported using kqueue for OSX/BSD.
1215
+ #
1216
+ # === Usage example:
1217
+ #
1218
+ # module ProcessWatcher
1219
+ # def process_exited
1220
+ # put 'the forked child died!'
1221
+ # end
1222
+ # end
1223
+ #
1224
+ # pid = fork{ sleep }
1225
+ #
1226
+ # EM.run{
1227
+ # EM.watch_process(pid, ProcessWatcher)
1228
+ # EM.add_timer(1){ Process.kill('TERM', pid) }
1229
+ # }
1230
+ #
1231
+ def self.watch_process(pid, handler=nil, *args)
1232
+ pid = pid.to_i
1233
+
1234
+ klass = klass_from_handler(ProcessWatch, handler, *args)
1235
+
1236
+ s = EM::watch_pid(pid)
1237
+ c = klass.new s, *args
1238
+ # we have to set the path like this because of how Connection.new works
1239
+ c.instance_variable_set("@pid", pid)
1240
+ @conns[s] = c
1241
+ block_given? and yield c
1242
+ c
1243
+ end
1244
+
1245
+ # Catch-all for errors raised during event loop callbacks.
1246
+ #
1247
+ # EM.error_handler{ |e|
1248
+ # puts "Error raised during event loop: #{e.message}"
1249
+ # }
1250
+ #
1251
+ def self.error_handler cb = nil, &blk
1252
+ if cb or blk
1253
+ @error_handler = cb || blk
1254
+ elsif instance_variable_defined? :@error_handler
1255
+ remove_instance_variable :@error_handler
1256
+ end
1257
+ end
1258
+
1259
+ # enable_proxy allows for direct writing of incoming data back out to another descriptor, at the C++ level in the reactor.
1260
+ # This is especially useful for proxies where high performance is required. Propogating data from a server response
1261
+ # all the way up to Ruby, and then back down to the reactor to be sent back to the client, is often unnecessary and
1262
+ # incurs a significant performance decrease.
1263
+ #
1264
+ # The two arguments are Connections, 'from' and 'to'. 'from' is the connection whose inbound data you want
1265
+ # relayed back out. 'to' is the connection to write it to.
1266
+ #
1267
+ # Once you call this method, the 'from' connection will no longer get receive_data callbacks from the reactor,
1268
+ # except in the case that 'to' connection has already closed when attempting to write to it. You can see
1269
+ # in the example, that proxy_target_unbound will be called when this occurs. After that, further incoming
1270
+ # data will be passed into receive_data as normal.
1271
+ #
1272
+ # Note also that this feature supports different types of descriptors - TCP, UDP, and pipes. You can relay
1273
+ # data from one kind to another.
1274
+ #
1275
+ # Example:
1276
+ #
1277
+ # module ProxyConnection
1278
+ # def initialize(client, request)
1279
+ # @client, @request = client, request
1280
+ # end
1281
+ #
1282
+ # def post_init
1283
+ # EM::enable_proxy(self, @client)
1284
+ # end
1285
+ #
1286
+ # def connection_completed
1287
+ # send_data @request
1288
+ # end
1289
+ #
1290
+ # def proxy_target_unbound
1291
+ # close_connection
1292
+ # end
1293
+ #
1294
+ # def unbind
1295
+ # @client.close_connection_after_writing
1296
+ # end
1297
+ # end
1298
+ #
1299
+ # module ProxyServer
1300
+ # def receive_data(data)
1301
+ # (@buf ||= "") << data
1302
+ # if @buf =~ /\r\n\r\n/ # all http headers received
1303
+ # EM.connect("10.0.0.15", 80, ProxyConnection, self, data)
1304
+ # end
1305
+ # end
1306
+ # end
1307
+ #
1308
+ # EM.run {
1309
+ # EM.start_server("127.0.0.1", 8080, ProxyServer)
1310
+ # }
1311
+ def self.enable_proxy(from, to, bufsize=0, length=0)
1312
+ EM::start_proxy(from.signature, to.signature, bufsize, length)
1313
+ end
1314
+
1315
+ # disable_proxy takes just one argument, a Connection that has proxying enabled via enable_proxy.
1316
+ # Calling this method will remove that functionality and your connection will begin receiving
1317
+ # data via receive_data again.
1318
+ def self.disable_proxy(from)
1319
+ EM::stop_proxy(from.signature)
1320
+ end
1321
+
1322
+ # Retrieve the heartbeat interval. This is how often EventMachine will check for dead connections
1323
+ # that have had an InactivityTimeout set via Connection#set_comm_inactivity_timeout.
1324
+ # Default is 2 seconds.
1325
+ def self.heartbeat_interval
1326
+ EM::get_heartbeat_interval
1327
+ end
1328
+
1329
+ # Set the heartbeat interval. This is how often EventMachine will check for dead connections
1330
+ # that have had an InactivityTimeout set via Connection#set_comm_inactivity_timeout.
1331
+ # Takes a Numeric number of seconds. Default is 2.
1332
+ def self.heartbeat_interval= (time)
1333
+ EM::set_heartbeat_interval time.to_f
1334
+ end
1335
+
1336
+ private
1337
+
1338
+ def self.event_callback conn_binding, opcode, data # :nodoc:
1339
+ #
1340
+ # Changed 27Dec07: Eliminated the hookable error handling.
1341
+ # No one was using it, and it degraded performance significantly.
1342
+ # It's in original_event_callback, which is dead code.
1343
+ #
1344
+ # Changed 25Jul08: Added a partial solution to the problem of exceptions
1345
+ # raised in user-written event-handlers. If such exceptions are not caught,
1346
+ # we must cause the reactor to stop, and then re-raise the exception.
1347
+ # Otherwise, the reactor doesn't stop and it's left on the call stack.
1348
+ # This is partial because we only added it to #unbind, where it's critical
1349
+ # (to keep unbind handlers from being re-entered when a stopping reactor
1350
+ # runs down open connections). It should go on the other calls to user
1351
+ # code, but the performance impact may be too large.
1352
+ #
1353
+ if opcode == ConnectionUnbound
1354
+ if c = @conns.delete( conn_binding )
1355
+ begin
1356
+ c.unbind
1357
+ rescue
1358
+ @wrapped_exception = $!
1359
+ stop
1360
+ end
1361
+ elsif c = @acceptors.delete( conn_binding )
1362
+ # no-op
1363
+ else
1364
+ if $! # Bubble user generated errors.
1365
+ @wrapped_exception = $!
1366
+ EM.stop
1367
+ else
1368
+ raise ConnectionNotBound, "recieved ConnectionUnbound for an unknown signature: #{conn_binding}"
1369
+ end
1370
+ end
1371
+ elsif opcode == ConnectionAccepted
1372
+ accep,args,blk = @acceptors[conn_binding]
1373
+ raise NoHandlerForAcceptedConnection unless accep
1374
+ c = accep.new data, *args
1375
+ @conns[data] = c
1376
+ blk and blk.call(c)
1377
+ c # (needed?)
1378
+ ##
1379
+ # The remaining code is a fallback for the pure ruby and java reactors.
1380
+ # In the C++ reactor, these events are handled in the C event_callback() in rubymain.cpp
1381
+ elsif opcode == ConnectionCompleted
1382
+ c = @conns[conn_binding] or raise ConnectionNotBound, "received ConnectionCompleted for unknown signature: #{conn_binding}"
1383
+ c.connection_completed
1384
+ elsif opcode == TimerFired
1385
+ t = @timers.delete( data )
1386
+ return if t == false # timer cancelled
1387
+ t or raise UnknownTimerFired, "timer data: #{data}"
1388
+ t.call
1389
+ elsif opcode == ConnectionData
1390
+ c = @conns[conn_binding] or raise ConnectionNotBound, "received data #{data} for unknown signature: #{conn_binding}"
1391
+ c.receive_data data
1392
+ elsif opcode == LoopbreakSignalled
1393
+ run_deferred_callbacks
1394
+ elsif opcode == ConnectionNotifyReadable
1395
+ c = @conns[conn_binding] or raise ConnectionNotBound
1396
+ c.notify_readable
1397
+ elsif opcode == ConnectionNotifyWritable
1398
+ c = @conns[conn_binding] or raise ConnectionNotBound
1399
+ c.notify_writable
1400
+ end
1401
+ end
1402
+
1403
+ #--
1404
+ # The original event_callback below handled runtime errors in ruby and degraded performance significantly.
1405
+ # An optional C-based error handler is now available via EM::error_handler
1406
+ #
1407
+ # private
1408
+ # def EventMachine::original_event_callback conn_binding, opcode, data
1409
+ # #
1410
+ # # Added 03Oct07: Any code path that invokes user-written code must
1411
+ # # wrap itself in a begin/rescue for RuntimeErrors, that calls the
1412
+ # # user-overridable class method #handle_runtime_error.
1413
+ # #
1414
+ # if opcode == ConnectionData
1415
+ # c = @conns[conn_binding] or raise ConnectionNotBound
1416
+ # begin
1417
+ # c.receive_data data
1418
+ # rescue
1419
+ # EventMachine.handle_runtime_error
1420
+ # end
1421
+ # elsif opcode == ConnectionUnbound
1422
+ # if c = @conns.delete( conn_binding )
1423
+ # begin
1424
+ # c.unbind
1425
+ # rescue
1426
+ # EventMachine.handle_runtime_error
1427
+ # end
1428
+ # elsif c = @acceptors.delete( conn_binding )
1429
+ # # no-op
1430
+ # else
1431
+ # raise ConnectionNotBound
1432
+ # end
1433
+ # elsif opcode == ConnectionAccepted
1434
+ # accep,args,blk = @acceptors[conn_binding]
1435
+ # raise NoHandlerForAcceptedConnection unless accep
1436
+ # c = accep.new data, *args
1437
+ # @conns[data] = c
1438
+ # begin
1439
+ # blk and blk.call(c)
1440
+ # rescue
1441
+ # EventMachine.handle_runtime_error
1442
+ # end
1443
+ # c # (needed?)
1444
+ # elsif opcode == TimerFired
1445
+ # t = @timers.delete( data ) or raise UnknownTimerFired
1446
+ # begin
1447
+ # t.call
1448
+ # rescue
1449
+ # EventMachine.handle_runtime_error
1450
+ # end
1451
+ # elsif opcode == ConnectionCompleted
1452
+ # c = @conns[conn_binding] or raise ConnectionNotBound
1453
+ # begin
1454
+ # c.connection_completed
1455
+ # rescue
1456
+ # EventMachine.handle_runtime_error
1457
+ # end
1458
+ # elsif opcode == LoopbreakSignalled
1459
+ # begin
1460
+ # run_deferred_callbacks
1461
+ # rescue
1462
+ # EventMachine.handle_runtime_error
1463
+ # end
1464
+ # end
1465
+ # end
1466
+ #
1467
+ #
1468
+ # # Default handler for RuntimeErrors that are raised in user code.
1469
+ # # The default behavior is to re-raise the error, which ends your program.
1470
+ # # To override the default behavior, re-implement this method in your code.
1471
+ # # For example:
1472
+ # #
1473
+ # # module EventMachine
1474
+ # # def self.handle_runtime_error
1475
+ # # $>.puts $!
1476
+ # # end
1477
+ # # end
1478
+ # #
1479
+ # #--
1480
+ # # We need to ensure that any code path which invokes user code rescues RuntimeError
1481
+ # # and calls this method. The obvious place to do that is in #event_callback,
1482
+ # # but, scurrilously, it turns out that we need to be finer grained that that.
1483
+ # # Periodic timers, in particular, wrap their invocations of user code inside
1484
+ # # procs that do other stuff we can't not do, like schedule the next invocation.
1485
+ # # This is a potential non-robustness, since we need to remember to hook in the
1486
+ # # error handler whenever and wherever we change how user code is invoked.
1487
+ # #
1488
+ # def EventMachine::handle_runtime_error
1489
+ # @runtime_error_hook ? @runtime_error_hook.call : raise
1490
+ # end
1491
+ #
1492
+ # # Sets a handler for RuntimeErrors that are raised in user code.
1493
+ # # Pass a block with no parameters. You can also call this method without a block,
1494
+ # # which restores the default behavior (see #handle_runtime_error).
1495
+ # #
1496
+ # def EventMachine::set_runtime_error_hook &blk
1497
+ # @runtime_error_hook = blk
1498
+ # end
1499
+
1500
+ #--
1501
+ # This is a provisional implementation of a stream-oriented file access object.
1502
+ # We also experiment with wrapping up some better exception reporting.
1503
+ def self._open_file_for_writing filename, handler=nil # :nodoc:
1504
+ klass = klass_from_handler(Connection, handler)
1505
+
1506
+ s = _write_file filename
1507
+ c = klass.new s
1508
+ @conns[s] = c
1509
+ block_given? and yield c
1510
+ c
1511
+ end
1512
+
1513
+ private
1514
+ def self.klass_from_handler(klass = Connection, handler = nil, *args)
1515
+ klass = if handler and handler.is_a?(Class)
1516
+ raise ArgumentError, "must provide module or subclass of #{klass.name}" unless klass >= handler
1517
+ handler
1518
+ elsif handler
1519
+ begin
1520
+ handler::EM_CONNECTION_CLASS
1521
+ rescue NameError
1522
+ handler::const_set(:EM_CONNECTION_CLASS, Class.new(klass) {include handler})
1523
+ end
1524
+ else
1525
+ klass
1526
+ end
1527
+
1528
+ arity = klass.instance_method(:initialize).arity
1529
+ expected = arity >= 0 ? arity : -(arity + 1)
1530
+ if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
1531
+ raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
1532
+ end
1533
+
1534
+ klass
1535
+ end
1536
+ end # module EventMachine
1537
+
1538
+ # Save everyone some typing.
1539
+ EM = EventMachine
1540
+ EM::P = EventMachine::Protocols