sidekick-client 0.2.1 → 0.2.2

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