eventmachine-maglev- 0.12.10 → 1.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/.gitignore +7 -0
  2. data/.yardopts +7 -0
  3. data/Gemfile +3 -0
  4. data/README.md +109 -0
  5. data/Rakefile +14 -368
  6. data/docs/DocumentationGuidesIndex.md +27 -0
  7. data/docs/GettingStarted.md +521 -0
  8. data/docs/old/DEFERRABLES +246 -0
  9. data/docs/{KEYBOARD → old/KEYBOARD} +15 -11
  10. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  11. data/docs/old/SMTP +4 -0
  12. data/docs/old/SPAWNED_PROCESSES +148 -0
  13. data/eventmachine.gemspec +20 -26
  14. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  15. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  16. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  17. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  18. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  19. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  20. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  21. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  22. data/examples/{ex_channel.rb → old/ex_channel.rb} +3 -3
  23. data/examples/old/ex_tick_loop_array.rb +15 -0
  24. data/examples/old/ex_tick_loop_counter.rb +32 -0
  25. data/ext/binder.cpp +0 -1
  26. data/ext/cmain.cpp +40 -29
  27. data/ext/ed.cpp +189 -134
  28. data/ext/ed.h +34 -40
  29. data/ext/em.cpp +388 -340
  30. data/ext/em.h +29 -32
  31. data/ext/eventmachine.h +7 -6
  32. data/ext/extconf.rb +57 -48
  33. data/ext/fastfilereader/extconf.rb +5 -3
  34. data/ext/fastfilereader/mapper.cpp +1 -1
  35. data/ext/fastfilereader/rubymain.cpp +0 -1
  36. data/ext/kb.cpp +1 -3
  37. data/ext/pipe.cpp +9 -11
  38. data/ext/project.h +12 -8
  39. data/ext/rubymain.cpp +158 -112
  40. data/java/src/com/rubyeventmachine/EmReactor.java +3 -2
  41. data/lib/em/buftok.rb +35 -63
  42. data/lib/em/callback.rb +43 -11
  43. data/lib/em/channel.rb +22 -15
  44. data/lib/em/completion.rb +303 -0
  45. data/lib/em/connection.rb +341 -208
  46. data/lib/em/deferrable/pool.rb +2 -0
  47. data/lib/em/deferrable.rb +20 -2
  48. data/lib/em/file_watch.rb +37 -18
  49. data/lib/em/iterator.rb +270 -0
  50. data/lib/em/pool.rb +146 -0
  51. data/lib/em/process_watch.rb +5 -4
  52. data/lib/em/processes.rb +8 -4
  53. data/lib/em/protocols/httpclient.rb +27 -11
  54. data/lib/em/protocols/httpclient2.rb +15 -5
  55. data/lib/em/protocols/line_protocol.rb +29 -0
  56. data/lib/em/protocols/memcache.rb +17 -9
  57. data/lib/em/protocols/object_protocol.rb +2 -1
  58. data/lib/em/protocols/postgres3.rb +2 -1
  59. data/lib/em/protocols/smtpclient.rb +19 -11
  60. data/lib/em/protocols/smtpserver.rb +101 -8
  61. data/lib/em/protocols/stomp.rb +9 -7
  62. data/lib/em/protocols/tcptest.rb +3 -2
  63. data/lib/em/protocols.rb +1 -1
  64. data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +188 -205
  65. data/lib/em/queue.rb +23 -13
  66. data/lib/em/resolver.rb +192 -0
  67. data/lib/em/spawnable.rb +9 -10
  68. data/lib/em/streamer.rb +34 -46
  69. data/lib/em/threaded_resource.rb +90 -0
  70. data/lib/em/tick_loop.rb +85 -0
  71. data/lib/em/timers.rb +8 -3
  72. data/lib/em/version.rb +1 -1
  73. data/lib/eventmachine.rb +582 -686
  74. data/lib/jeventmachine.rb +25 -3
  75. data/tasks/package.rake +98 -0
  76. data/tasks/test.rake +8 -0
  77. data/tests/em_test_helper.rb +64 -0
  78. data/tests/test_attach.rb +56 -56
  79. data/tests/test_basic.rb +111 -168
  80. data/tests/test_channel.rb +5 -6
  81. data/tests/test_completion.rb +177 -0
  82. data/tests/test_connection_count.rb +1 -3
  83. data/tests/test_defer.rb +3 -32
  84. data/tests/test_deferrable.rb +35 -0
  85. data/tests/test_epoll.rb +27 -57
  86. data/tests/test_error_handler.rb +10 -7
  87. data/tests/test_exc.rb +6 -33
  88. data/tests/test_file_watch.rb +51 -35
  89. data/tests/test_futures.rb +10 -38
  90. data/tests/test_get_sock_opt.rb +27 -20
  91. data/tests/test_handler_check.rb +1 -3
  92. data/tests/test_hc.rb +49 -112
  93. data/tests/test_httpclient.rb +34 -62
  94. data/tests/test_httpclient2.rb +14 -39
  95. data/tests/test_inactivity_timeout.rb +44 -40
  96. data/tests/test_kb.rb +26 -52
  97. data/tests/test_ltp.rb +27 -71
  98. data/tests/test_ltp2.rb +1 -30
  99. data/tests/test_next_tick.rb +2 -31
  100. data/tests/test_object_protocol.rb +8 -9
  101. data/tests/test_pause.rb +45 -37
  102. data/tests/test_pending_connect_timeout.rb +42 -38
  103. data/tests/test_pool.rb +128 -0
  104. data/tests/test_process_watch.rb +37 -37
  105. data/tests/test_processes.rb +92 -110
  106. data/tests/test_proxy_connection.rb +137 -61
  107. data/tests/test_pure.rb +30 -67
  108. data/tests/test_queue.rb +10 -4
  109. data/tests/test_resolver.rb +55 -0
  110. data/tests/test_running.rb +1 -29
  111. data/tests/test_sasl.rb +8 -33
  112. data/tests/test_send_file.rb +163 -188
  113. data/tests/test_servers.rb +12 -55
  114. data/tests/test_shutdown_hooks.rb +23 -0
  115. data/tests/test_smtpclient.rb +1 -29
  116. data/tests/test_smtpserver.rb +1 -29
  117. data/tests/test_spawn.rb +2 -31
  118. data/tests/test_ssl_args.rb +9 -10
  119. data/tests/test_ssl_methods.rb +1 -3
  120. data/tests/test_ssl_verify.rb +63 -63
  121. data/tests/test_threaded_resource.rb +53 -0
  122. data/tests/test_tick_loop.rb +59 -0
  123. data/tests/test_timers.rb +52 -91
  124. data/tests/test_ud.rb +1 -29
  125. data/tests/test_unbind_reason.rb +31 -0
  126. metadata +113 -70
  127. data/README +0 -82
  128. data/docs/DEFERRABLES +0 -133
  129. data/docs/LIGHTWEIGHT_CONCURRENCY +0 -70
  130. data/docs/SMTP +0 -2
  131. data/docs/SPAWNED_PROCESSES +0 -89
  132. data/ext/cplusplus.cpp +0 -202
  133. data/ext/emwin.cpp +0 -300
  134. data/ext/emwin.h +0 -94
  135. data/ext/epoll.cpp +0 -26
  136. data/ext/epoll.h +0 -25
  137. data/ext/eventmachine_cpp.h +0 -96
  138. data/ext/files.cpp +0 -94
  139. data/ext/files.h +0 -65
  140. data/ext/sigs.cpp +0 -89
  141. data/ext/sigs.h +0 -32
  142. data/java/src/com/rubyeventmachine/application/Application.java +0 -194
  143. data/java/src/com/rubyeventmachine/application/Connection.java +0 -74
  144. data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +0 -37
  145. data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +0 -46
  146. data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +0 -38
  147. data/java/src/com/rubyeventmachine/application/Timer.java +0 -54
  148. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +0 -109
  149. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +0 -148
  150. data/java/src/com/rubyeventmachine/tests/EMTest.java +0 -80
  151. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +0 -53
  152. data/java/src/com/rubyeventmachine/tests/TestServers.java +0 -75
  153. data/java/src/com/rubyeventmachine/tests/TestTimers.java +0 -90
  154. data/lib/evma/callback.rb +0 -32
  155. data/lib/evma/container.rb +0 -75
  156. data/lib/evma/factory.rb +0 -77
  157. data/lib/evma/protocol.rb +0 -87
  158. data/lib/evma/reactor.rb +0 -48
  159. data/lib/evma.rb +0 -32
  160. data/setup.rb +0 -1585
  161. data/tests/test_errors.rb +0 -82
  162. data/tests/testem.rb +0 -31
  163. data/web/whatis +0 -7
  164. /data/{docs/GNU → GNU} +0 -0
  165. /data/{docs/COPYING → LICENSE} +0 -0
  166. /data/docs/{ChangeLog → old/ChangeLog} +0 -0
  167. /data/docs/{EPOLL → old/EPOLL} +0 -0
  168. /data/docs/{INSTALL → old/INSTALL} +0 -0
  169. /data/docs/{LEGAL → old/LEGAL} +0 -0
  170. /data/docs/{PURE_RUBY → old/PURE_RUBY} +0 -0
  171. /data/docs/{RELEASE_NOTES → old/RELEASE_NOTES} +0 -0
  172. /data/docs/{TODO → old/TODO} +0 -0
  173. /data/examples/{ex_queue.rb → old/ex_queue.rb} +0 -0
  174. /data/examples/{helper.rb → old/helper.rb} +0 -0
data/ext/rubymain.cpp CHANGED
@@ -31,6 +31,8 @@ Statics
31
31
 
32
32
  static VALUE EmModule;
33
33
  static VALUE EmConnection;
34
+ static VALUE EmConnsHash;
35
+ static VALUE EmTimersHash;
34
36
 
35
37
  static VALUE EM_eConnectionError;
36
38
  static VALUE EM_eUnknownTimerFired;
@@ -51,89 +53,121 @@ static VALUE Intern_ssl_verify_peer;
51
53
  static VALUE Intern_notify_readable;
52
54
  static VALUE Intern_notify_writable;
53
55
  static VALUE Intern_proxy_target_unbound;
56
+ static VALUE Intern_proxy_completed;
57
+ static VALUE Intern_connection_completed;
54
58
 
55
59
  static VALUE rb_cProcStatus;
56
60
 
57
61
  struct em_event {
58
- unsigned long a1;
59
- int a2;
60
- const char *a3;
61
- unsigned long a4;
62
+ unsigned long signature;
63
+ int event;
64
+ const char *data_str;
65
+ unsigned long data_num;
62
66
  };
63
67
 
68
+ static inline VALUE ensure_conn(const unsigned long signature)
69
+ {
70
+ VALUE conn = rb_hash_aref (EmConnsHash, ULONG2NUM (signature));
71
+ if (conn == Qnil)
72
+ rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", signature);
73
+ return conn;
74
+ }
75
+
76
+
64
77
  /****************
65
78
  t_event_callback
66
79
  ****************/
67
80
 
68
- static void event_callback (struct em_event* e)
69
- {
70
- const unsigned long a1 = e->a1;
71
- int a2 = e->a2;
72
- const char *a3 = e->a3;
73
- const unsigned long a4 = e->a4;
74
-
75
- if (a2 == EM_CONNECTION_READ) {
76
- VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
77
- VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
78
- if (q == Qnil)
79
- rb_raise (EM_eConnectionNotBound, "received %lu bytes of data for unknown signature: %lu", a4, a1);
80
- rb_funcall (q, Intern_receive_data, 1, rb_str_new (a3, a4));
81
- }
82
- else if (a2 == EM_CONNECTION_NOTIFY_READABLE) {
83
- VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
84
- VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
85
- if (q == Qnil)
86
- rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
87
- rb_funcall (q, Intern_notify_readable, 0);
88
- }
89
- else if (a2 == EM_CONNECTION_NOTIFY_WRITABLE) {
90
- VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
91
- VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
92
- if (q == Qnil)
93
- rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
94
- rb_funcall (q, Intern_notify_writable, 0);
95
- }
96
- else if (a2 == EM_LOOPBREAK_SIGNAL) {
97
- rb_funcall (EmModule, Intern_run_deferred_callbacks, 0);
98
- }
99
- else if (a2 == EM_TIMER_FIRED) {
100
- VALUE t = rb_ivar_get (EmModule, Intern_at_timers);
101
- VALUE q = rb_funcall (t, Intern_delete, 1, ULONG2NUM (a4));
102
- if (q == Qnil) {
103
- rb_raise (EM_eUnknownTimerFired, "no such timer: %lu", a4);
104
- } else if (q == Qfalse) {
105
- /* Timer Canceled */
106
- } else {
107
- rb_funcall (q, Intern_call, 0);
81
+ static inline void event_callback (struct em_event* e)
82
+ {
83
+ const unsigned long signature = e->signature;
84
+ int event = e->event;
85
+ const char *data_str = e->data_str;
86
+ const unsigned long data_num = e->data_num;
87
+
88
+ switch (event) {
89
+ case EM_CONNECTION_READ:
90
+ {
91
+ VALUE conn = rb_hash_aref (EmConnsHash, ULONG2NUM (signature));
92
+ if (conn == Qnil)
93
+ rb_raise (EM_eConnectionNotBound, "received %lu bytes of data for unknown signature: %lu", data_num, signature);
94
+ rb_funcall (conn, Intern_receive_data, 1, rb_str_new (data_str, data_num));
95
+ return;
96
+ }
97
+ case EM_CONNECTION_ACCEPTED:
98
+ {
99
+ rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(signature), INT2FIX(event), ULONG2NUM(data_num));
100
+ return;
101
+ }
102
+ case EM_CONNECTION_UNBOUND:
103
+ {
104
+ rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(signature), INT2FIX(event), ULONG2NUM(data_num));
105
+ return;
106
+ }
107
+ case EM_CONNECTION_COMPLETED:
108
+ {
109
+ VALUE conn = ensure_conn(signature);
110
+ rb_funcall (conn, Intern_connection_completed, 0);
111
+ return;
112
+ }
113
+ case EM_CONNECTION_NOTIFY_READABLE:
114
+ {
115
+ VALUE conn = ensure_conn(signature);
116
+ rb_funcall (conn, Intern_notify_readable, 0);
117
+ return;
118
+ }
119
+ case EM_CONNECTION_NOTIFY_WRITABLE:
120
+ {
121
+ VALUE conn = ensure_conn(signature);
122
+ rb_funcall (conn, Intern_notify_writable, 0);
123
+ return;
124
+ }
125
+ case EM_LOOPBREAK_SIGNAL:
126
+ {
127
+ rb_funcall (EmModule, Intern_run_deferred_callbacks, 0);
128
+ return;
129
+ }
130
+ case EM_TIMER_FIRED:
131
+ {
132
+ VALUE timer = rb_funcall (EmTimersHash, Intern_delete, 1, ULONG2NUM (data_num));
133
+ if (timer == Qnil) {
134
+ rb_raise (EM_eUnknownTimerFired, "no such timer: %lu", data_num);
135
+ } else if (timer == Qfalse) {
136
+ /* Timer Canceled */
137
+ } else {
138
+ rb_funcall (timer, Intern_call, 0);
139
+ }
140
+ return;
141
+ }
142
+ #ifdef WITH_SSL
143
+ case EM_SSL_HANDSHAKE_COMPLETED:
144
+ {
145
+ VALUE conn = ensure_conn(signature);
146
+ rb_funcall (conn, Intern_ssl_handshake_completed, 0);
147
+ return;
148
+ }
149
+ case EM_SSL_VERIFY:
150
+ {
151
+ VALUE conn = ensure_conn(signature);
152
+ VALUE should_accept = rb_funcall (conn, Intern_ssl_verify_peer, 1, rb_str_new(data_str, data_num));
153
+ if (RTEST(should_accept))
154
+ evma_accept_ssl_peer (signature);
155
+ return;
156
+ }
157
+ #endif
158
+ case EM_PROXY_TARGET_UNBOUND:
159
+ {
160
+ VALUE conn = ensure_conn(signature);
161
+ rb_funcall (conn, Intern_proxy_target_unbound, 0);
162
+ return;
163
+ }
164
+ case EM_PROXY_COMPLETED:
165
+ {
166
+ VALUE conn = ensure_conn(signature);
167
+ rb_funcall (conn, Intern_proxy_completed, 0);
168
+ return;
108
169
  }
109
170
  }
110
- #ifdef WITH_SSL
111
- else if (a2 == EM_SSL_HANDSHAKE_COMPLETED) {
112
- VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
113
- VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
114
- if (q == Qnil)
115
- rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
116
- rb_funcall (q, Intern_ssl_handshake_completed, 0);
117
- }
118
- else if (a2 == EM_SSL_VERIFY) {
119
- VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
120
- VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
121
- if (q == Qnil)
122
- rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
123
- VALUE r = rb_funcall (q, Intern_ssl_verify_peer, 1, rb_str_new(a3, a4));
124
- if (RTEST(r))
125
- evma_accept_ssl_peer (a1);
126
- }
127
- #endif
128
- else if (a2 == EM_PROXY_TARGET_UNBOUND) {
129
- VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
130
- VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
131
- if (q == Qnil)
132
- rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
133
- rb_funcall (q, Intern_proxy_target_unbound, 0);
134
- }
135
- else
136
- rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(a1), INT2FIX(a2), a3 ? rb_str_new(a3,a4) : ULONG2NUM(a4));
137
171
  }
138
172
 
139
173
  /*******************
@@ -150,13 +184,13 @@ static void event_error_handler(VALUE unused, VALUE err)
150
184
  event_callback_wrapper
151
185
  **********************/
152
186
 
153
- static void event_callback_wrapper (const unsigned long a1, int a2, const char *a3, const unsigned long a4)
187
+ static void event_callback_wrapper (const unsigned long signature, int event, const char *data_str, const unsigned long data_num)
154
188
  {
155
189
  struct em_event e;
156
- e.a1 = a1;
157
- e.a2 = a2;
158
- e.a3 = a3;
159
- e.a4 = a4;
190
+ e.signature = signature;
191
+ e.event = event;
192
+ e.data_str = data_str;
193
+ e.data_num = data_num;
160
194
 
161
195
  if (!rb_ivar_defined(EmModule, Intern_at_error_handler))
162
196
  event_callback(&e);
@@ -170,7 +204,11 @@ t_initialize_event_machine
170
204
 
171
205
  static VALUE t_initialize_event_machine (VALUE self)
172
206
  {
173
- evma_initialize_library (event_callback_wrapper);
207
+ EmConnsHash = rb_ivar_get (EmModule, Intern_at_conns);
208
+ EmTimersHash = rb_ivar_get (EmModule, Intern_at_timers);
209
+ assert(EmConnsHash != Qnil);
210
+ assert(EmTimersHash != Qnil);
211
+ evma_initialize_library ((EMCallback)event_callback_wrapper);
174
212
  return Qnil;
175
213
  }
176
214
 
@@ -208,7 +246,7 @@ static VALUE t_start_server (VALUE self, VALUE server, VALUE port)
208
246
  {
209
247
  const unsigned long f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
210
248
  if (!f)
211
- rb_raise (rb_eRuntimeError, "no acceptor");
249
+ rb_raise (rb_eRuntimeError, "no acceptor (port is in use or requires root privileges)");
212
250
  return ULONG2NUM (f);
213
251
  }
214
252
 
@@ -307,9 +345,10 @@ t_get_peername
307
345
 
308
346
  static VALUE t_get_peername (VALUE self, VALUE signature)
309
347
  {
310
- struct sockaddr s;
311
- if (evma_get_peername (NUM2ULONG (signature), &s)) {
312
- return rb_str_new ((const char*)&s, sizeof(s));
348
+ char buf[1024];
349
+ socklen_t len = sizeof buf;
350
+ if (evma_get_peername (NUM2ULONG (signature), (struct sockaddr*)buf, &len)) {
351
+ return rb_str_new (buf, len);
313
352
  }
314
353
 
315
354
  return Qnil;
@@ -321,9 +360,10 @@ t_get_sockname
321
360
 
322
361
  static VALUE t_get_sockname (VALUE self, VALUE signature)
323
362
  {
324
- struct sockaddr s;
325
- if (evma_get_sockname (NUM2ULONG (signature), &s)) {
326
- return rb_str_new ((const char*)&s, sizeof(s));
363
+ char buf[1024];
364
+ socklen_t len = sizeof buf;
365
+ if (evma_get_sockname (NUM2ULONG (signature), (struct sockaddr*)buf, &len)) {
366
+ return rb_str_new (buf, len);
327
367
  }
328
368
 
329
369
  return Qnil;
@@ -390,8 +430,9 @@ t_set_comm_inactivity_timeout
390
430
  static VALUE t_set_comm_inactivity_timeout (VALUE self, VALUE signature, VALUE timeout)
391
431
  {
392
432
  float ti = RFLOAT_VALUE(timeout);
393
- if (evma_set_comm_inactivity_timeout (NUM2ULONG (signature), ti));
433
+ if (evma_set_comm_inactivity_timeout(NUM2ULONG(signature), ti)) {
394
434
  return Qtrue;
435
+ }
395
436
  return Qfalse;
396
437
  }
397
438
 
@@ -411,8 +452,9 @@ t_set_pending_connect_timeout
411
452
  static VALUE t_set_pending_connect_timeout (VALUE self, VALUE signature, VALUE timeout)
412
453
  {
413
454
  float ti = RFLOAT_VALUE(timeout);
414
- if (evma_set_pending_connect_timeout (NUM2ULONG (signature), ti));
455
+ if (evma_set_pending_connect_timeout(NUM2ULONG(signature), ti)) {
415
456
  return Qtrue;
457
+ }
416
458
  return Qfalse;
417
459
  }
418
460
 
@@ -467,6 +509,7 @@ static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
467
509
  } catch (std::runtime_error e) {
468
510
  rb_raise (EM_eConnectionError, e.what());
469
511
  }
512
+ return Qnil;
470
513
  }
471
514
 
472
515
  /*********************
@@ -487,6 +530,7 @@ static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port
487
530
  } catch (std::runtime_error e) {
488
531
  rb_raise (EM_eConnectionError, e.what());
489
532
  }
533
+ return Qnil;
490
534
  }
491
535
 
492
536
  /*********************
@@ -701,18 +745,6 @@ static VALUE t_setuid_string (VALUE self, VALUE username)
701
745
 
702
746
 
703
747
 
704
- /*************
705
- t__write_file
706
- *************/
707
-
708
- static VALUE t__write_file (VALUE self, VALUE filename)
709
- {
710
- const unsigned long f = evma__write_file (StringValuePtr (filename));
711
- if (!f)
712
- rb_raise (rb_eRuntimeError, "file not opened");
713
- return ULONG2NUM (f);
714
- }
715
-
716
748
  /**************
717
749
  t_invoke_popen
718
750
  **************/
@@ -725,13 +757,17 @@ static VALUE t_invoke_popen (VALUE self, VALUE cmd)
725
757
  #else
726
758
  int len = RARRAY (cmd)->len;
727
759
  #endif
728
- if (len > 98)
760
+ if (len >= 2048)
729
761
  rb_raise (rb_eRuntimeError, "too many arguments to popen");
730
- char *strings [100];
762
+ char *strings [2048];
731
763
  for (int i=0; i < len; i++) {
732
764
  VALUE ix = INT2FIX (i);
733
765
  VALUE s = rb_ary_aref (1, &ix, cmd);
766
+ #ifdef BUILD_FOR_MAGLEV
734
767
  strings[i] = (char*)StringValuePtr (s);
768
+ #else
769
+ strings[i] = StringValuePtr (s);
770
+ #endif
735
771
  }
736
772
  strings[len] = NULL;
737
773
 
@@ -769,8 +805,9 @@ static VALUE t_watch_filename (VALUE self, VALUE fname)
769
805
  try {
770
806
  return ULONG2NUM(evma_watch_filename(StringValuePtr(fname)));
771
807
  } catch (std::runtime_error e) {
772
- rb_sys_fail(e.what());
808
+ rb_raise (EM_eUnsupported, e.what());
773
809
  }
810
+ return Qnil;
774
811
  }
775
812
 
776
813
 
@@ -794,8 +831,9 @@ static VALUE t_watch_pid (VALUE self, VALUE pid)
794
831
  try {
795
832
  return ULONG2NUM(evma_watch_pid(NUM2INT(pid)));
796
833
  } catch (std::runtime_error e) {
797
- rb_sys_fail(e.what());
834
+ rb_raise (EM_eUnsupported, e.what());
798
835
  }
836
+ return Qnil;
799
837
  }
800
838
 
801
839
 
@@ -972,11 +1010,12 @@ static VALUE t_get_loop_time (VALUE self)
972
1010
  static ID at = rb_intern("at");
973
1011
  #endif
974
1012
 
975
- if (gCurrentLoopTime != 0) {
1013
+ uint64_t current_time = evma_get_current_loop_time();
1014
+ if (current_time != 0) {
976
1015
  #ifndef HAVE_RB_TIME_NEW
977
- return rb_funcall(cTime, at, 2, INT2NUM(gCurrentLoopTime / 1000000), INT2NUM(gCurrentLoopTime % 1000000));
1016
+ return rb_funcall(cTime, at, 2, INT2NUM(current_time / 1000000), INT2NUM(current_time % 1000000));
978
1017
  #else
979
- return rb_time_new(gCurrentLoopTime / 1000000, gCurrentLoopTime % 1000000);
1018
+ return rb_time_new(current_time / 1000000, current_time % 1000000);
980
1019
  #endif
981
1020
  }
982
1021
  return Qnil;
@@ -987,9 +1026,13 @@ static VALUE t_get_loop_time (VALUE self)
987
1026
  t_start_proxy
988
1027
  **************/
989
1028
 
990
- static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to, VALUE bufsize)
1029
+ static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to, VALUE bufsize, VALUE length)
991
1030
  {
992
- evma_start_proxy(NUM2ULONG (from), NUM2ULONG (to), NUM2ULONG(bufsize));
1031
+ try {
1032
+ evma_start_proxy(NUM2ULONG (from), NUM2ULONG (to), NUM2ULONG(bufsize), NUM2ULONG(length));
1033
+ } catch (std::runtime_error e) {
1034
+ rb_raise (EM_eConnectionError, e.what());
1035
+ }
993
1036
  return Qnil;
994
1037
  }
995
1038
 
@@ -1000,7 +1043,11 @@ t_stop_proxy
1000
1043
 
1001
1044
  static VALUE t_stop_proxy (VALUE self, VALUE from)
1002
1045
  {
1003
- evma_stop_proxy(NUM2ULONG (from));
1046
+ try{
1047
+ evma_stop_proxy(NUM2ULONG (from));
1048
+ } catch (std::runtime_error e) {
1049
+ rb_raise (EM_eConnectionError, e.what());
1050
+ }
1004
1051
  return Qnil;
1005
1052
  }
1006
1053
 
@@ -1054,6 +1101,8 @@ extern "C" void Init_rubyeventmachine()
1054
1101
  Intern_notify_readable = rb_intern ("notify_readable");
1055
1102
  Intern_notify_writable = rb_intern ("notify_writable");
1056
1103
  Intern_proxy_target_unbound = rb_intern ("proxy_target_unbound");
1104
+ Intern_proxy_completed = rb_intern ("proxy_completed");
1105
+ Intern_connection_completed = rb_intern ("connection_completed");
1057
1106
 
1058
1107
  // INCOMPLETE, we need to define class Connections inside module EventMachine
1059
1108
  // run_machine and run_machine_without_threads are now identical.
@@ -1097,7 +1146,7 @@ extern "C" void Init_rubyeventmachine()
1097
1146
  rb_define_module_function (EmModule, "resume_connection", (VALUE (*)(...))t_resume, 1);
1098
1147
  rb_define_module_function (EmModule, "connection_paused?", (VALUE (*)(...))t_paused_p, 1);
1099
1148
 
1100
- rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 3);
1149
+ rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 4);
1101
1150
  rb_define_module_function (EmModule, "stop_proxy", (VALUE (*)(...))t_stop_proxy, 1);
1102
1151
 
1103
1152
  rb_define_module_function (EmModule, "watch_filename", (VALUE (*)(...))t_watch_filename, 1);
@@ -1123,9 +1172,6 @@ extern "C" void Init_rubyeventmachine()
1123
1172
  rb_define_module_function (EmModule, "get_heartbeat_interval", (VALUE(*)(...))t_get_heartbeat_interval, 0);
1124
1173
  rb_define_module_function (EmModule, "set_heartbeat_interval", (VALUE(*)(...))t_set_heartbeat_interval, 1);
1125
1174
 
1126
- // Provisional:
1127
- rb_define_module_function (EmModule, "_write_file", (VALUE(*)(...))t__write_file, 1);
1128
-
1129
1175
  rb_define_module_function (EmModule, "get_peername", (VALUE(*)(...))t_get_peername, 1);
1130
1176
  rb_define_module_function (EmModule, "get_sockname", (VALUE(*)(...))t_get_sockname, 1);
1131
1177
  rb_define_module_function (EmModule, "get_subprocess_pid", (VALUE(*)(...))t_get_subprocess_pid, 1);
@@ -48,6 +48,7 @@ public class EmReactor {
48
48
  public final int EM_SSL_HANDSHAKE_COMPLETED = 108;
49
49
  public final int EM_SSL_VERIFY = 109;
50
50
  public final int EM_PROXY_TARGET_UNBOUND = 110;
51
+ public final int EM_PROXY_COMPLETED = 111;
51
52
 
52
53
  private Selector mySelector;
53
54
  private TreeMap<Long, ArrayList<Long>> Timers;
@@ -441,8 +442,8 @@ public class EmReactor {
441
442
  Connections.get(sig).setCommInactivityTimeout (mills);
442
443
  }
443
444
 
444
- public void sendDatagram (long sig, String data, int length, String recipAddress, int recipPort) {
445
- sendDatagram (sig, ByteBuffer.wrap(data.getBytes()), recipAddress, recipPort);
445
+ public void sendDatagram (long sig, byte[] data, int length, String recipAddress, int recipPort) {
446
+ sendDatagram (sig, ByteBuffer.wrap(data), recipAddress, recipPort);
446
447
  }
447
448
 
448
449
  public void sendDatagram (long sig, ByteBuffer bb, String recipAddress, int recipPort) {
data/lib/em/buftok.rb CHANGED
@@ -1,43 +1,29 @@
1
- # BufferedTokenizer - Statefully split input data by a specifiable token
2
- #
3
- # Authors:: Tony Arcieri, Martin Emde
4
- #
5
- #----------------------------------------------------------------------------
6
- #
7
- # Copyright (C) 2006-07 by Tony Arcieri and Martin Emde
8
- #
9
- # Distributed under the Ruby license (http://www.ruby-lang.org/en/LICENSE.txt)
10
- #
11
- #---------------------------------------------------------------------------
12
- #
13
-
14
- # (C)2006 Tony Arcieri, Martin Emde
15
- # Distributed under the Ruby license (http://www.ruby-lang.org/en/LICENSE.txt)
16
-
17
1
  # BufferedTokenizer takes a delimiter upon instantiation, or acts line-based
18
2
  # by default. It allows input to be spoon-fed from some outside source which
19
3
  # receives arbitrary length datagrams which may-or-may-not contain the token
20
4
  # by which entities are delimited.
21
5
  #
22
- # Commonly used to parse lines out of incoming data:
6
+ # By default, new BufferedTokenizers will operate on lines delimited by "\n" by default
7
+ # or allow you to specify any delimiter token you so choose, which will then
8
+ # be used by String#split to tokenize the input data
23
9
  #
24
- # module LineBufferedConnection
25
- # def receive_data(data)
26
- # (@buffer ||= BufferedTokenizer.new).extract(data).each do |line|
27
- # receive_line(line)
28
- # end
29
- # end
30
- # end
31
-
10
+ # @example Using BufferedTokernizer to parse lines out of incoming data
11
+ #
12
+ # module LineBufferedConnection
13
+ # def receive_data(data)
14
+ # (@buffer ||= BufferedTokenizer.new).extract(data).each do |line|
15
+ # receive_line(line)
16
+ # end
17
+ # end
18
+ # end
19
+ #
20
+ # @author Tony Arcieri
21
+ # @author Martin Emde
32
22
  class BufferedTokenizer
33
- # New BufferedTokenizers will operate on lines delimited by "\n" by default
34
- # or allow you to specify any delimiter token you so choose, which will then
35
- # be used by String#split to tokenize the input data
23
+ # @param [String] delimiter
24
+ # @param [Integer] size_limit
36
25
  def initialize(delimiter = "\n", size_limit = nil)
37
- # Store the specified delimiter
38
- @delimiter = delimiter
39
-
40
- # Store the specified size limitation
26
+ @delimiter = delimiter
41
27
  @size_limit = size_limit
42
28
 
43
29
  # The input buffer is stored as an array. This is by far the most efficient
@@ -52,14 +38,18 @@ class BufferedTokenizer
52
38
  end
53
39
 
54
40
  # Extract takes an arbitrary string of input data and returns an array of
55
- # tokenized entities, provided there were any available to extract. This
56
- # makes for easy processing of datagrams using a pattern like:
41
+ # tokenized entities, provided there were any available to extract.
57
42
  #
58
- # tokenizer.extract(data).map { |entity| Decode(entity) }.each do ...
43
+ # @example
44
+ #
45
+ # tokenizer.extract(data).
46
+ # map { |entity| Decode(entity) }.each { ... }
47
+ #
48
+ # @param [String] data
59
49
  def extract(data)
60
50
  # Extract token-delimited entities from the input string with the split command.
61
51
  # There's a bit of craftiness here with the -1 parameter. Normally split would
62
- # behave no differently regardless of if the token lies at the very end of the
52
+ # behave no differently regardless of if the token lies at the very end of the
63
53
  # input buffer or not (i.e. a literal edge case) Specifying -1 forces split to
64
54
  # return "" in this case, meaning that the last entry in the list represents a
65
55
  # new segment of data where the token has not been encountered
@@ -70,7 +60,7 @@ class BufferedTokenizer
70
60
  raise 'input buffer full' if @input_size + entities.first.size > @size_limit
71
61
  @input_size += entities.first.size
72
62
  end
73
-
63
+
74
64
  # Move the first entry in the resulting array into the input buffer. It represents
75
65
  # the last segment of a token-delimited entity unless it's the only entry in the list.
76
66
  @input << entities.shift
@@ -85,36 +75,16 @@ class BufferedTokenizer
85
75
  # and add it to our list of discovered entities.
86
76
  entities.unshift @input.join
87
77
 
88
- =begin
89
- # Note added by FC, 10Jul07. This paragraph contains a regression. It breaks
90
- # empty tokens. Think of the empty line that delimits an HTTP header. It will have
91
- # two "\n" delimiters in a row, and this code mishandles the resulting empty token.
92
- # It someone figures out how to fix the problem, we can re-enable this code branch.
93
- # Multi-character token support.
94
- # Split any tokens that were incomplete on the last iteration buf complete now.
95
- entities.map! do |e|
96
- e.split @delimiter, -1
97
- end
98
- # Flatten the resulting array. This has the side effect of removing the empty
99
- # entry at the end that was produced by passing -1 to split. Add it again if
100
- # necessary.
101
- if (entities[-1] == [])
102
- entities.flatten! << []
103
- else
104
- entities.flatten!
105
- end
106
- =end
107
-
108
78
  # Now that we've hit a token, joined the input buffer and added it to the entities
109
79
  # list, we can go ahead and clear the input buffer. All of the segments that were
110
80
  # stored before the join can now be garbage collected.
111
81
  @input.clear
112
-
82
+
113
83
  # The last entity in the list is not token delimited, however, thanks to the -1
114
- # passed to split. It represents the beginning of a new list of as-yet-untokenized
84
+ # passed to split. It represents the beginning of a new list of as-yet-untokenized
115
85
  # data, so we add it to the start of the list.
116
86
  @input << entities.pop
117
-
87
+
118
88
  # Set the new input buffer size, provided we're keeping track
119
89
  @input_size = @input.first.size if @size_limit
120
90
 
@@ -122,16 +92,18 @@ class BufferedTokenizer
122
92
  # in the first place. Hooray!
123
93
  entities
124
94
  end
125
-
95
+
126
96
  # Flush the contents of the input buffer, i.e. return the input buffer even though
127
- # a token has not yet been encountered
97
+ # a token has not yet been encountered.
98
+ #
99
+ # @return [String]
128
100
  def flush
129
101
  buffer = @input.join
130
102
  @input.clear
131
103
  buffer
132
104
  end
133
105
 
134
- # Is the buffer empty?
106
+ # @return [Boolean]
135
107
  def empty?
136
108
  @input.empty?
137
109
  end
data/lib/em/callback.rb CHANGED
@@ -1,26 +1,58 @@
1
1
  module EventMachine
2
- # Utility method for coercing arguments to an object that responds to #call
2
+ # Utility method for coercing arguments to an object that responds to :call.
3
3
  # Accepts an object and a method name to send to, or a block, or an object
4
- # that responds to call.
4
+ # that responds to :call.
5
5
  #
6
- # cb = EM.Callback{ |msg| puts(msg) }
6
+ # @example EventMachine.Callback used with a block. Returns that block.
7
+ #
8
+ # cb = EventMachine.Callback do |msg|
9
+ # puts(msg)
10
+ # end
11
+ # # returned object is a callable
7
12
  # cb.call('hello world')
8
13
  #
9
- # cb = EM.Callback(Object, :puts)
14
+ #
15
+ # @example EventMachine.Callback used with an object (to be more specific, class object) and a method name, returns an object that responds to #call
16
+ #
17
+ # cb = EventMachine.Callback(Object, :puts)
18
+ # # returned object is a callable that delegates to Kernel#puts (in this case Object.puts)
10
19
  # cb.call('hello world')
11
20
  #
12
- # cb = EM.Callback(proc{ |msg| puts(msg) })
21
+ #
22
+ # @example EventMachine.Callback used with an object that responds to #call. Returns the argument.
23
+ #
24
+ # cb = EventMachine.Callback(proc{ |msg| puts(msg) })
25
+ # # returned object is a callable
13
26
  # cb.call('hello world')
14
27
  #
28
+ #
29
+ # @overload Callback(object, method)
30
+ # Wraps `method` invocation on `object` into an object that responds to #call that proxies all the arguments to that method
31
+ # @param [Object] Object to invoke method on
32
+ # @param [Symbol] Method name
33
+ # @return [<#call>] An object that responds to #call that takes any number of arguments and invokes method on object with those arguments
34
+ #
35
+ # @overload Callback(object)
36
+ # Returns callable object as is, without any coercion
37
+ # @param [<#call>] An object that responds to #call
38
+ # @return [<#call>] Its argument
39
+ #
40
+ # @overload Callback(&block)
41
+ # Returns block passed to it without any coercion
42
+ # @return [<#call>] Block passed to this method
43
+ #
44
+ # @raise [ArgumentError] When argument doesn't respond to #call, method name is missing or when invoked without arguments and block isn't given
45
+ #
46
+ # @return [<#call>]
15
47
  def self.Callback(object = nil, method = nil, &blk)
16
48
  if object && method
17
- lambda { |*args| object.send method, *args }
49
+ lambda { |*args| object.__send__ method, *args }
18
50
  else
19
51
  if object.respond_to? :call
20
52
  object
21
- else
53
+ else
22
54
  blk || raise(ArgumentError)
23
- end
24
- end
25
- end
26
- end
55
+ end # if
56
+ end # if
57
+ end # self.Callback
58
+ end # EventMachine