eventmachine 1.0.0.beta.4-java → 1.0.0-java

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.
@@ -29,7 +29,7 @@ module EventMachine
29
29
  #
30
30
  # # If we don't care about the result:
31
31
  # pool.perform do |dispatcher|
32
- # # The following blcok executes inside a dedicated thread, and should not
32
+ # # The following block executes inside a dedicated thread, and should not
33
33
  # # access EventMachine things:
34
34
  # dispatcher.dispatch do |cassandra|
35
35
  # cassandra.insert(:Things, '10', 'stuff' => 'things')
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "1.0.0.beta.4"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -82,7 +82,8 @@ module EventMachine
82
82
  @reactor_running = false
83
83
  @next_tick_queue = []
84
84
  @tails = []
85
- @threadpool = nil
85
+ @threadpool = @threadqueue = @resultqueue = nil
86
+ @all_threads_spawned = false
86
87
 
87
88
  # System errnos
88
89
  # @private
@@ -155,7 +156,13 @@ module EventMachine
155
156
  # will start without release_machine being called and will immediately throw
156
157
 
157
158
  #
158
-
159
+ if reactor_running? and @reactor_pid != Process.pid
160
+ # Reactor was started in a different parent, meaning we have forked.
161
+ # Clean up reactor state so a new reactor boots up in this child.
162
+ stop_event_loop
163
+ release_machine
164
+ @reactor_running = false
165
+ end
159
166
 
160
167
  tail and @tails.unshift(tail)
161
168
 
@@ -169,6 +176,7 @@ module EventMachine
169
176
  @next_tick_queue ||= []
170
177
  @tails ||= []
171
178
  begin
179
+ @reactor_pid = Process.pid
172
180
  @reactor_running = true
173
181
  initialize_event_machine
174
182
  (b = blk || block) and add_timer(0, b)
@@ -201,6 +209,7 @@ module EventMachine
201
209
  @threadqueue = nil
202
210
  @resultqueue = nil
203
211
  @threadpool = nil
212
+ @all_threads_spawned = false
204
213
  end
205
214
 
206
215
  @next_tick_queue = []
@@ -252,7 +261,7 @@ module EventMachine
252
261
  if self.reactor_running?
253
262
  self.stop_event_loop
254
263
  self.release_machine
255
- self.instance_variable_set( '@reactor_running', false )
264
+ @reactor_running = false
256
265
  end
257
266
  self.run block
258
267
  end
@@ -425,7 +434,8 @@ module EventMachine
425
434
  # that you must define. When the network server that is started by
426
435
  # start_server accepts a new connection, it instantiates a new
427
436
  # object of an anonymous class that is inherited from {EventMachine::Connection},
428
- # *into which your handler module have been included*.
437
+ # *into which your handler module have been included*. Arguments passed into start_server
438
+ # after the class name are passed into the constructor during the instantiation.
429
439
  #
430
440
  # Your handler module may override any of the methods in {EventMachine::Connection},
431
441
  # such as {EventMachine::Connection#receive_data}, in order to implement the specific behavior
@@ -736,6 +746,7 @@ module EventMachine
736
746
  c = klass.new s, *args
737
747
 
738
748
  c.instance_variable_set(:@io, io)
749
+ c.instance_variable_set(:@watch_mode, watch_mode)
739
750
  c.instance_variable_set(:@fd, fd)
740
751
 
741
752
  @conns[s] = c
@@ -761,7 +772,11 @@ module EventMachine
761
772
  #raise "still connected" if @conns.has_key?(handler.signature)
762
773
  return handler if @conns.has_key?(handler.signature)
763
774
 
764
- s = connect_server server, port
775
+ s = if port
776
+ connect_server server, port
777
+ else
778
+ connect_unix_server server
779
+ end
765
780
  handler.signature = s
766
781
  @conns[s] = handler
767
782
  block_given? and yield handler
@@ -936,10 +951,21 @@ module EventMachine
936
951
  cback.call result if cback
937
952
  end
938
953
 
939
- @next_tick_mutex.synchronize do
940
- jobs, @next_tick_queue = @next_tick_queue, []
941
- jobs
942
- end.each { |j| j.call }
954
+ # Capture the size at the start of this tick...
955
+ size = @next_tick_mutex.synchronize { @next_tick_queue.size }
956
+ size.times do |i|
957
+ callback = @next_tick_mutex.synchronize { @next_tick_queue.shift }
958
+ begin
959
+ callback.call
960
+ ensure
961
+ # This is a little nasty. The problem is, if an exception occurs during
962
+ # the callback, then we need to send a signal to the reactor to actually
963
+ # do some work during the next_tick. The only mechanism we have from the
964
+ # ruby side is next_tick itself, although ideally, we'd just drop a byte
965
+ # on the loopback descriptor.
966
+ EM.next_tick {} if $!
967
+ end
968
+ end
943
969
  end
944
970
 
945
971
 
@@ -991,7 +1017,6 @@ module EventMachine
991
1017
  # has no constructor.
992
1018
 
993
1019
  unless @threadpool
994
- require 'thread'
995
1020
  @threadpool = []
996
1021
  @threadqueue = ::Queue.new
997
1022
  @resultqueue = ::Queue.new
@@ -1016,6 +1041,19 @@ module EventMachine
1016
1041
  end
1017
1042
  @threadpool << thread
1018
1043
  end
1044
+ @all_threads_spawned = true
1045
+ end
1046
+
1047
+ ##
1048
+ # Returns +true+ if all deferred actions are done executing and their
1049
+ # callbacks have been fired.
1050
+ #
1051
+ def self.defers_finished?
1052
+ return false if @threadpool and !@all_threads_spawned
1053
+ return false if @threadqueue and not @threadqueue.empty?
1054
+ return false if @resultqueue and not @resultqueue.empty?
1055
+ return false if @threadpool and @threadqueue.num_waiting != @threadpool.size
1056
+ return true
1019
1057
  end
1020
1058
 
1021
1059
  class << self
@@ -1391,11 +1429,19 @@ module EventMachine
1391
1429
  if opcode == ConnectionUnbound
1392
1430
  if c = @conns.delete( conn_binding )
1393
1431
  begin
1394
- if c.original_method(:unbind).arity == 1
1432
+ if c.original_method(:unbind).arity != 0
1395
1433
  c.unbind(data == 0 ? nil : EventMachine::ERRNOS[data])
1396
1434
  else
1397
1435
  c.unbind
1398
1436
  end
1437
+ # If this is an attached (but not watched) connection, close the underlying io object.
1438
+ if c.instance_variable_defined?(:@io) and !c.instance_variable_get(:@watch_mode)
1439
+ io = c.instance_variable_get(:@io)
1440
+ begin
1441
+ io.close
1442
+ rescue Errno::EBADF, IOError
1443
+ end
1444
+ end
1399
1445
  rescue
1400
1446
  @wrapped_exception = $!
1401
1447
  stop
@@ -203,6 +203,11 @@ module EventMachine
203
203
  Socket.pack_sockaddr_in(*peer)
204
204
  end
205
205
  end
206
+ def self.get_sockname sig
207
+ if sockName = @em.getSockName(sig)
208
+ Socket.pack_sockaddr_in(*sockName)
209
+ end
210
+ end
206
211
  # @private
207
212
  def self.attach_fd fileno, watch_mode
208
213
  # 3Aug09: We could pass in the actual SocketChannel, but then it would be modified (set as non-blocking), and
File without changes
@@ -23,7 +23,7 @@ else
23
23
  def setup_cross_compilation(ext)
24
24
  unless RUBY_PLATFORM =~ /mswin|mingw/
25
25
  ext.cross_compile = true
26
- ext.cross_platform = ['x86-mingw32']#, 'x86-mswin32-60']
26
+ ext.cross_platform = ['x86-mingw32', 'x86-mswin32-60']
27
27
 
28
28
  # inject 1.8/1.9 pure-ruby entry point
29
29
  ext.cross_compiling do |spec|
File without changes
@@ -224,4 +224,71 @@ class TestBasic < Test::Unit::TestCase
224
224
  end
225
225
  end
226
226
  end
227
+
228
+ def test_schedule_close
229
+ localhost, port = '127.0.0.1', 9000
230
+ timer_ran = false
231
+ num_close_scheduled = nil
232
+ EM.run do
233
+ assert_equal 0, EM.num_close_scheduled
234
+ EM.add_timer(1) { timer_ran = true; EM.stop }
235
+ EM.start_server localhost, port do |s|
236
+ s.close_connection
237
+ num_close_scheduled = EM.num_close_scheduled
238
+ end
239
+ EM.connect localhost, port do |c|
240
+ def c.unbind
241
+ EM.stop
242
+ end
243
+ end
244
+ end
245
+ assert !timer_ran
246
+ assert_equal 1, num_close_scheduled
247
+ end
248
+
249
+ def test_fork_safe
250
+ return unless cpid = fork { exit! } rescue false
251
+
252
+ read, write = IO.pipe
253
+ EM.run do
254
+ cpid = fork do
255
+ write.puts "forked"
256
+ EM.run do
257
+ EM.next_tick do
258
+ write.puts "EM ran"
259
+ exit!
260
+ end
261
+ end
262
+ end
263
+ EM.stop
264
+ end
265
+ Process.waitall
266
+ assert_equal "forked\n", read.readline
267
+ assert_equal "EM ran\n", read.readline
268
+ ensure
269
+ read.close rescue nil
270
+ write.close rescue nil
271
+ end
272
+
273
+ def test_error_handler_idempotent # issue 185
274
+ errors = []
275
+ ticks = []
276
+ EM.error_handler do |e|
277
+ errors << e
278
+ end
279
+
280
+ EM.run do
281
+ EM.next_tick do
282
+ ticks << :first
283
+ raise
284
+ end
285
+ EM.next_tick do
286
+ ticks << :second
287
+ end
288
+ EM.add_timer(0.001) { EM.stop }
289
+ end
290
+
291
+ assert_equal 1, errors.size
292
+ assert_equal [:first, :second], ticks
293
+ end
227
294
  end
@@ -0,0 +1,23 @@
1
+ require 'em_test_helper'
2
+
3
+ class TestIdleConnection < Test::Unit::TestCase
4
+ if EM.respond_to?(:get_idle_time)
5
+ def test_idle_time
6
+ EM.run{
7
+ conn = EM.connect 'www.google.com', 80
8
+ EM.add_timer(3){
9
+ $idle_time = conn.get_idle_time
10
+ conn.send_data "GET / HTTP/1.0\r\n\r\n"
11
+ EM.next_tick{
12
+ $idle_time_after_send = conn.get_idle_time
13
+ conn.close_connection
14
+ EM.stop
15
+ }
16
+ }
17
+ }
18
+
19
+ assert_in_delta 3, $idle_time, 0.2
20
+ assert_equal 0, $idle_time_after_send
21
+ end
22
+ end
23
+ end
@@ -115,6 +115,41 @@ class TestPool < Test::Unit::TestCase
115
115
  assert_equal [:res], pool.contents
116
116
  end
117
117
 
118
+ def test_contents_when_perform_errors_and_on_error_is_not_set
119
+ pool.add :res
120
+ assert_equal [:res], pool.contents
121
+
122
+ pool.perform do |r|
123
+ d = EM::DefaultDeferrable.new
124
+ d.fail
125
+ d
126
+ end
127
+
128
+ EM.run { EM.next_tick { EM.stop } }
129
+
130
+ assert_equal [:res], pool.contents
131
+ end
132
+
133
+ def test_contents_when_perform_errors_and_on_error_is_set
134
+ pool.add :res
135
+ res = nil
136
+ pool.on_error do |r|
137
+ res = r
138
+ end
139
+ assert_equal [:res], pool.contents
140
+
141
+ pool.perform do |r|
142
+ d = EM::DefaultDeferrable.new
143
+ d.fail 'foo'
144
+ d
145
+ end
146
+
147
+ EM.run { EM.next_tick { EM.stop } }
148
+
149
+ assert_equal :res, res
150
+ assert_equal [], pool.contents
151
+ end
152
+
118
153
  def test_num_waiting
119
154
  pool.add :res
120
155
  assert_equal 0, pool.num_waiting
@@ -125,4 +160,35 @@ class TestPool < Test::Unit::TestCase
125
160
  assert_equal 10, pool.num_waiting
126
161
  end
127
162
 
128
- end
163
+ def test_exceptions_in_the_work_block_bubble_up_raise_and_fail_the_resource
164
+ pool.add :res
165
+
166
+ res = nil
167
+ pool.on_error { |r| res = r }
168
+ pool.perform { raise 'boom' }
169
+
170
+ assert_raises(RuntimeError) do
171
+ EM.run { EM.next_tick { EM.stop } }
172
+ end
173
+
174
+ assert_equal [], pool.contents
175
+ assert_equal :res, res
176
+ end
177
+
178
+ def test_removed_list_does_not_leak_on_errors
179
+ pool.add :res
180
+
181
+ pool.on_error do |r|
182
+ # This is actually the wrong thing to do, and not required, but some users
183
+ # might do it. When they do, they would find that @removed would cause a
184
+ # slow leak.
185
+ pool.remove r
186
+ end
187
+
188
+ pool.perform { d = EM::DefaultDeferrable.new; d.fail; d }
189
+
190
+ EM.run { EM.next_tick { EM.stop } }
191
+ assert_equal [], pool.instance_variable_get(:@removed)
192
+ end
193
+
194
+ end
@@ -24,6 +24,7 @@ class TestProxyConnection < Test::Unit::TestCase
24
24
  end
25
25
 
26
26
  def unbind
27
+ $proxied_bytes = self.get_proxied_bytes
27
28
  @client.close_connection_after_writing
28
29
  end
29
30
  end
@@ -94,7 +95,7 @@ class TestProxyConnection < Test::Unit::TestCase
94
95
  end
95
96
 
96
97
  def receive_data(data)
97
- EM.connect("127.0.0.1", @port, ProxyConnection, self, data)
98
+ @proxy = EM.connect("127.0.0.1", @port, ProxyConnection, self, data)
98
99
  end
99
100
  end
100
101
 
@@ -134,6 +135,17 @@ class TestProxyConnection < Test::Unit::TestCase
134
135
  assert_equal("I know!", $client_data)
135
136
  end
136
137
 
138
+ def test_proxied_bytes
139
+ EM.run {
140
+ EM.start_server("127.0.0.1", @port, Server)
141
+ EM.start_server("127.0.0.1", @proxy_port, ProxyServer, @port)
142
+ EM.connect("127.0.0.1", @proxy_port, Client)
143
+ }
144
+
145
+ assert_equal("I know!", $client_data)
146
+ assert_equal("I know!".bytesize, $proxied_bytes)
147
+ end
148
+
137
149
  def test_partial_proxy_connection
138
150
  EM.run {
139
151
  EM.start_server("127.0.0.1", @port, Server)
@@ -2,6 +2,15 @@ require 'em_test_helper'
2
2
  require 'socket'
3
3
 
4
4
  class TestUnbindReason < Test::Unit::TestCase
5
+
6
+ class StubConnection < EM::Connection
7
+ attr_reader :error
8
+ def unbind(reason = nil)
9
+ @error = reason
10
+ EM.stop
11
+ end
12
+ end
13
+
5
14
  def test_connect_timeout
6
15
  error = nil
7
16
  EM.run {
@@ -13,7 +22,7 @@ class TestUnbindReason < Test::Unit::TestCase
13
22
  }
14
23
  conn.pending_connect_timeout = 0.1
15
24
  }
16
- assert_equal error, Errno::ETIMEDOUT
25
+ assert_equal Errno::ETIMEDOUT, error
17
26
  end
18
27
 
19
28
  def test_connect_refused
@@ -26,6 +35,14 @@ class TestUnbindReason < Test::Unit::TestCase
26
35
  end
27
36
  }
28
37
  }
29
- assert_equal error, Errno::ECONNREFUSED
38
+ assert_equal Errno::ECONNREFUSED, error
39
+ end
40
+
41
+ def test_optional_argument
42
+ conn = nil
43
+ EM.run {
44
+ conn = EM.connect '127.0.0.1', 12388, StubConnection
45
+ }
46
+ assert_equal Errno::ECONNREFUSED, conn.error
30
47
  end
31
48
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventmachine
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 1.0.0.beta.4
4
+ prerelease:
5
+ version: 1.0.0
6
6
  platform: java
7
7
  authors:
8
8
  - Francis Cianfrocca
@@ -11,8 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-09-15 00:00:00 -07:00
15
- default_executable:
14
+ date: 2012-09-08 00:00:00 Z
16
15
  dependencies:
17
16
  - !ruby/object:Gem::Dependency
18
17
  name: rake-compiler
@@ -20,9 +19,9 @@ dependencies:
20
19
  requirement: &id001 !ruby/object:Gem::Requirement
21
20
  none: false
22
21
  requirements:
23
- - - "="
22
+ - - ~>
24
23
  - !ruby/object:Gem::Version
25
- version: 0.7.9
24
+ version: 0.8.1
26
25
  type: :development
27
26
  version_requirements: *id001
28
27
  - !ruby/object:Gem::Dependency
@@ -186,9 +185,9 @@ files:
186
185
  - lib/em/version.rb
187
186
  - lib/eventmachine.rb
188
187
  - lib/jeventmachine.rb
189
- - tasks/cpp.rake_example
190
- - tasks/package.rake
191
- - tasks/test.rake
188
+ - rakelib/cpp.rake_example
189
+ - rakelib/package.rake
190
+ - rakelib/test.rake
192
191
  - tests/client.crt
193
192
  - tests/client.key
194
193
  - tests/em_test_helper.rb
@@ -209,6 +208,7 @@ files:
209
208
  - tests/test_hc.rb
210
209
  - tests/test_httpclient.rb
211
210
  - tests/test_httpclient2.rb
211
+ - tests/test_idle_connection.rb
212
212
  - tests/test_inactivity_timeout.rb
213
213
  - tests/test_kb.rb
214
214
  - tests/test_ltp.rb
@@ -242,7 +242,6 @@ files:
242
242
  - tests/test_ud.rb
243
243
  - tests/test_unbind_reason.rb
244
244
  - lib/rubyeventmachine.jar
245
- has_rdoc: true
246
245
  homepage: http://rubyeventmachine.com
247
246
  licenses: []
248
247
 
@@ -267,13 +266,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
267
266
  required_rubygems_version: !ruby/object:Gem::Requirement
268
267
  none: false
269
268
  requirements:
270
- - - ">"
269
+ - - ">="
271
270
  - !ruby/object:Gem::Version
272
- version: 1.3.1
271
+ version: "0"
273
272
  requirements: []
274
273
 
275
274
  rubyforge_project: eventmachine
276
- rubygems_version: 1.5.1
275
+ rubygems_version: 1.8.15
277
276
  signing_key:
278
277
  specification_version: 3
279
278
  summary: Ruby/EventMachine library