sensu-em 2.4.0-x86-mingw32

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