jrmey-eventmachine 0.12.12

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