eventmachine-maglev- 1.0.0.beta.4 → 1.0.0.rc.4
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.
- data/README.md +1 -1
- data/Rakefile +11 -11
- data/eventmachine.gemspec +1 -1
- data/ext/cmain.cpp +41 -3
- data/ext/ed.cpp +31 -6
- data/ext/ed.h +9 -5
- data/ext/em.cpp +33 -10
- data/ext/em.h +11 -1
- data/ext/eventmachine.h +4 -0
- data/ext/extconf.rb +24 -5
- data/ext/fastfilereader/extconf.rb +20 -2
- data/ext/pipe.cpp +2 -2
- data/ext/project.h +3 -2
- data/ext/rubymain.cpp +108 -19
- data/ext/ssl.cpp +9 -1
- data/java/src/com/rubyeventmachine/EmReactor.java +4 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +1 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +6 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +6 -0
- data/lib/em/completion.rb +4 -3
- data/lib/em/connection.rb +17 -2
- data/lib/em/iterator.rb +42 -42
- data/lib/em/pool.rb +7 -2
- data/lib/em/protocols/postgres3.rb +6 -8
- data/lib/em/protocols/smtpclient.rb +28 -28
- data/lib/em/pure_ruby.rb +12 -0
- data/lib/em/threaded_resource.rb +1 -1
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +57 -11
- data/lib/jeventmachine.rb +5 -0
- data/{tasks → rakelib}/cpp.rake_example +0 -0
- data/{tasks → rakelib}/package.rake +0 -0
- data/{tasks → rakelib}/test.rake +0 -0
- data/tests/test_basic.rb +67 -0
- data/tests/test_idle_connection.rb +23 -0
- data/tests/test_pool.rb +67 -1
- data/tests/test_processes.rb +18 -0
- data/tests/test_proxy_connection.rb +13 -1
- data/tests/test_set_sock_opt.rb +37 -0
- data/tests/test_unbind_reason.rb +19 -2
- metadata +15 -13
data/ext/rubymain.cpp
CHANGED
@@ -233,7 +233,7 @@ static VALUE t_add_oneshot_timer (VALUE self, VALUE interval)
|
|
233
233
|
{
|
234
234
|
const unsigned long f = evma_install_oneshot_timer (FIX2INT (interval));
|
235
235
|
if (!f)
|
236
|
-
rb_raise (rb_eRuntimeError, "ran out of timers; use #set_max_timers to increase limit");
|
236
|
+
rb_raise (rb_eRuntimeError, "%s", "ran out of timers; use #set_max_timers to increase limit");
|
237
237
|
return ULONG2NUM (f);
|
238
238
|
}
|
239
239
|
|
@@ -246,7 +246,7 @@ static VALUE t_start_server (VALUE self, VALUE server, VALUE port)
|
|
246
246
|
{
|
247
247
|
const unsigned long f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
|
248
248
|
if (!f)
|
249
|
-
rb_raise (rb_eRuntimeError, "no acceptor (port is in use or requires root privileges)");
|
249
|
+
rb_raise (rb_eRuntimeError, "%s", "no acceptor (port is in use or requires root privileges)");
|
250
250
|
return ULONG2NUM (f);
|
251
251
|
}
|
252
252
|
|
@@ -269,7 +269,7 @@ static VALUE t_start_unix_server (VALUE self, VALUE filename)
|
|
269
269
|
{
|
270
270
|
const unsigned long f = evma_create_unix_domain_server (StringValuePtr(filename));
|
271
271
|
if (!f)
|
272
|
-
rb_raise (rb_eRuntimeError, "no unix-domain acceptor");
|
272
|
+
rb_raise (rb_eRuntimeError, "%s", "no unix-domain acceptor");
|
273
273
|
return ULONG2NUM (f);
|
274
274
|
}
|
275
275
|
|
@@ -504,10 +504,10 @@ static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
|
|
504
504
|
try {
|
505
505
|
const unsigned long f = evma_connect_to_server (NULL, 0, StringValuePtr(server), NUM2INT(port));
|
506
506
|
if (!f)
|
507
|
-
rb_raise (EM_eConnectionError, "no connection");
|
507
|
+
rb_raise (EM_eConnectionError, "%s", "no connection");
|
508
508
|
return ULONG2NUM (f);
|
509
509
|
} catch (std::runtime_error e) {
|
510
|
-
rb_raise (EM_eConnectionError, e.what());
|
510
|
+
rb_raise (EM_eConnectionError, "%s", e.what());
|
511
511
|
}
|
512
512
|
return Qnil;
|
513
513
|
}
|
@@ -525,10 +525,10 @@ static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port
|
|
525
525
|
try {
|
526
526
|
const unsigned long f = evma_connect_to_server (StringValuePtr(bind_addr), NUM2INT(bind_port), StringValuePtr(server), NUM2INT(port));
|
527
527
|
if (!f)
|
528
|
-
rb_raise (EM_eConnectionError, "no connection");
|
528
|
+
rb_raise (EM_eConnectionError, "%s", "no connection");
|
529
529
|
return ULONG2NUM (f);
|
530
530
|
} catch (std::runtime_error e) {
|
531
|
-
rb_raise (EM_eConnectionError, e.what());
|
531
|
+
rb_raise (EM_eConnectionError, "%s", e.what());
|
532
532
|
}
|
533
533
|
return Qnil;
|
534
534
|
}
|
@@ -541,7 +541,7 @@ static VALUE t_connect_unix_server (VALUE self, VALUE serversocket)
|
|
541
541
|
{
|
542
542
|
const unsigned long f = evma_connect_to_unix_server (StringValuePtr(serversocket));
|
543
543
|
if (!f)
|
544
|
-
rb_raise (rb_eRuntimeError, "no connection");
|
544
|
+
rb_raise (rb_eRuntimeError, "%s", "no connection");
|
545
545
|
return ULONG2NUM (f);
|
546
546
|
}
|
547
547
|
|
@@ -553,7 +553,7 @@ static VALUE t_attach_fd (VALUE self, VALUE file_descriptor, VALUE watch_mode)
|
|
553
553
|
{
|
554
554
|
const unsigned long f = evma_attach_fd (NUM2INT(file_descriptor), watch_mode == Qtrue);
|
555
555
|
if (!f)
|
556
|
-
rb_raise (rb_eRuntimeError, "no connection");
|
556
|
+
rb_raise (rb_eRuntimeError, "%s", "no connection");
|
557
557
|
return ULONG2NUM (f);
|
558
558
|
}
|
559
559
|
|
@@ -583,6 +583,44 @@ static VALUE t_get_sock_opt (VALUE self, VALUE signature, VALUE lev, VALUE optna
|
|
583
583
|
return rb_str_new(buf, len);
|
584
584
|
}
|
585
585
|
|
586
|
+
/**************
|
587
|
+
t_set_sock_opt
|
588
|
+
**************/
|
589
|
+
|
590
|
+
static VALUE t_set_sock_opt (VALUE self, VALUE signature, VALUE lev, VALUE optname, VALUE optval)
|
591
|
+
{
|
592
|
+
int fd = evma_get_file_descriptor (NUM2ULONG (signature));
|
593
|
+
int level = NUM2INT(lev), option = NUM2INT(optname);
|
594
|
+
int i;
|
595
|
+
void *v;
|
596
|
+
socklen_t len;
|
597
|
+
|
598
|
+
switch (TYPE(optval)) {
|
599
|
+
case T_FIXNUM:
|
600
|
+
i = FIX2INT(optval);
|
601
|
+
goto numval;
|
602
|
+
case T_FALSE:
|
603
|
+
i = 0;
|
604
|
+
goto numval;
|
605
|
+
case T_TRUE:
|
606
|
+
i = 1;
|
607
|
+
numval:
|
608
|
+
v = (void*)&i; len = sizeof(i);
|
609
|
+
break;
|
610
|
+
default:
|
611
|
+
StringValue(optval);
|
612
|
+
v = RSTRING_PTR(optval);
|
613
|
+
len = RSTRING_LENINT(optval);
|
614
|
+
break;
|
615
|
+
}
|
616
|
+
|
617
|
+
|
618
|
+
if (setsockopt(fd, level, option, (char *)v, len) < 0)
|
619
|
+
rb_sys_fail("setsockopt");
|
620
|
+
|
621
|
+
return INT2FIX(0);
|
622
|
+
}
|
623
|
+
|
586
624
|
/********************
|
587
625
|
t_is_notify_readable
|
588
626
|
********************/
|
@@ -648,6 +686,15 @@ static VALUE t_paused_p (VALUE self, VALUE signature)
|
|
648
686
|
return evma_is_paused(NUM2ULONG (signature)) ? Qtrue : Qfalse;
|
649
687
|
}
|
650
688
|
|
689
|
+
/*********************
|
690
|
+
t_num_close_scheduled
|
691
|
+
*********************/
|
692
|
+
|
693
|
+
static VALUE t_num_close_scheduled (VALUE self)
|
694
|
+
{
|
695
|
+
return INT2FIX(evma_num_close_scheduled());
|
696
|
+
}
|
697
|
+
|
651
698
|
/*****************
|
652
699
|
t_open_udp_socket
|
653
700
|
*****************/
|
@@ -656,7 +703,7 @@ static VALUE t_open_udp_socket (VALUE self, VALUE server, VALUE port)
|
|
656
703
|
{
|
657
704
|
const unsigned long f = evma_open_datagram_socket (StringValuePtr(server), FIX2INT(port));
|
658
705
|
if (!f)
|
659
|
-
rb_raise (rb_eRuntimeError, "no datagram socket");
|
706
|
+
rb_raise (rb_eRuntimeError, "%s", "no datagram socket");
|
660
707
|
return ULONG2NUM (f);
|
661
708
|
}
|
662
709
|
|
@@ -758,7 +805,7 @@ static VALUE t_invoke_popen (VALUE self, VALUE cmd)
|
|
758
805
|
int len = RARRAY (cmd)->len;
|
759
806
|
#endif
|
760
807
|
if (len >= 2048)
|
761
|
-
rb_raise (rb_eRuntimeError, "too many arguments to popen");
|
808
|
+
rb_raise (rb_eRuntimeError, "%s", "too many arguments to popen");
|
762
809
|
char *strings [2048];
|
763
810
|
for (int i=0; i < len; i++) {
|
764
811
|
VALUE ix = INT2FIX (i);
|
@@ -791,7 +838,7 @@ static VALUE t_read_keyboard (VALUE self)
|
|
791
838
|
{
|
792
839
|
const unsigned long f = evma_open_keyboard();
|
793
840
|
if (!f)
|
794
|
-
rb_raise (rb_eRuntimeError, "no keyboard reader");
|
841
|
+
rb_raise (rb_eRuntimeError, "%s", "no keyboard reader");
|
795
842
|
return ULONG2NUM (f);
|
796
843
|
}
|
797
844
|
|
@@ -805,7 +852,7 @@ static VALUE t_watch_filename (VALUE self, VALUE fname)
|
|
805
852
|
try {
|
806
853
|
return ULONG2NUM(evma_watch_filename(StringValuePtr(fname)));
|
807
854
|
} catch (std::runtime_error e) {
|
808
|
-
rb_raise (EM_eUnsupported, e.what());
|
855
|
+
rb_raise (EM_eUnsupported, "%s", e.what());
|
809
856
|
}
|
810
857
|
return Qnil;
|
811
858
|
}
|
@@ -831,7 +878,7 @@ static VALUE t_watch_pid (VALUE self, VALUE pid)
|
|
831
878
|
try {
|
832
879
|
return ULONG2NUM(evma_watch_pid(NUM2INT(pid)));
|
833
880
|
} catch (std::runtime_error e) {
|
834
|
-
rb_raise (EM_eUnsupported, e.what());
|
881
|
+
rb_raise (EM_eUnsupported, "%s", e.what());
|
835
882
|
}
|
836
883
|
return Qnil;
|
837
884
|
}
|
@@ -878,7 +925,7 @@ t__epoll_set
|
|
878
925
|
static VALUE t__epoll_set (VALUE self, VALUE val)
|
879
926
|
{
|
880
927
|
if (t__epoll_p(self) == Qfalse)
|
881
|
-
rb_raise (EM_eUnsupported, "epoll is not supported on this platform");
|
928
|
+
rb_raise (EM_eUnsupported, "%s", "epoll is not supported on this platform");
|
882
929
|
|
883
930
|
evma_set_epoll (val == Qtrue ? 1 : 0);
|
884
931
|
return val;
|
@@ -915,7 +962,7 @@ t__kqueue_set
|
|
915
962
|
static VALUE t__kqueue_set (VALUE self, VALUE val)
|
916
963
|
{
|
917
964
|
if (t__kqueue_p(self) == Qfalse)
|
918
|
-
rb_raise (EM_eUnsupported, "kqueue is not supported on this platform");
|
965
|
+
rb_raise (EM_eUnsupported, "%s", "kqueue is not supported on this platform");
|
919
966
|
|
920
967
|
evma_set_kqueue (val == Qtrue ? 1 : 0);
|
921
968
|
return val;
|
@@ -953,7 +1000,7 @@ static VALUE t_send_file_data (VALUE self, VALUE signature, VALUE filename)
|
|
953
1000
|
|
954
1001
|
int b = evma_send_file_data_to_connection (NUM2ULONG (signature), StringValuePtr(filename));
|
955
1002
|
if (b == -1)
|
956
|
-
rb_raise(rb_eRuntimeError, "File too large. send_file_data() supports files under 32k.");
|
1003
|
+
rb_raise(rb_eRuntimeError, "%s", "File too large. send_file_data() supports files under 32k.");
|
957
1004
|
if (b > 0) {
|
958
1005
|
char *err = strerror (b);
|
959
1006
|
char buf[1024];
|
@@ -1031,7 +1078,7 @@ static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to, VALUE bufsize, VAL
|
|
1031
1078
|
try {
|
1032
1079
|
evma_start_proxy(NUM2ULONG (from), NUM2ULONG (to), NUM2ULONG(bufsize), NUM2ULONG(length));
|
1033
1080
|
} catch (std::runtime_error e) {
|
1034
|
-
rb_raise (EM_eConnectionError, e.what());
|
1081
|
+
rb_raise (EM_eConnectionError, "%s", e.what());
|
1035
1082
|
}
|
1036
1083
|
return Qnil;
|
1037
1084
|
}
|
@@ -1046,11 +1093,49 @@ static VALUE t_stop_proxy (VALUE self, VALUE from)
|
|
1046
1093
|
try{
|
1047
1094
|
evma_stop_proxy(NUM2ULONG (from));
|
1048
1095
|
} catch (std::runtime_error e) {
|
1049
|
-
rb_raise (EM_eConnectionError, e.what());
|
1096
|
+
rb_raise (EM_eConnectionError, "%s", e.what());
|
1050
1097
|
}
|
1051
1098
|
return Qnil;
|
1052
1099
|
}
|
1053
1100
|
|
1101
|
+
/***************
|
1102
|
+
t_proxied_bytes
|
1103
|
+
****************/
|
1104
|
+
|
1105
|
+
static VALUE t_proxied_bytes (VALUE self, VALUE from)
|
1106
|
+
{
|
1107
|
+
try{
|
1108
|
+
return ULONG2NUM(evma_proxied_bytes(NUM2ULONG (from)));
|
1109
|
+
} catch (std::runtime_error e) {
|
1110
|
+
rb_raise (EM_eConnectionError, "%s", e.what());
|
1111
|
+
}
|
1112
|
+
return Qnil;
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
/***************
|
1116
|
+
t_get_idle_time
|
1117
|
+
****************/
|
1118
|
+
|
1119
|
+
static VALUE t_get_idle_time (VALUE self, VALUE from)
|
1120
|
+
{
|
1121
|
+
try{
|
1122
|
+
uint64_t current_time = evma_get_current_loop_time();
|
1123
|
+
uint64_t time = evma_get_last_activity_time(NUM2ULONG (from));
|
1124
|
+
if (current_time != 0 && time != 0) {
|
1125
|
+
if (time >= current_time)
|
1126
|
+
return ULONG2NUM(0);
|
1127
|
+
else {
|
1128
|
+
uint64_t diff = current_time - time;
|
1129
|
+
float seconds = diff / (1000.0*1000.0);
|
1130
|
+
return rb_float_new(seconds);
|
1131
|
+
}
|
1132
|
+
return Qnil;
|
1133
|
+
}
|
1134
|
+
} catch (std::runtime_error e) {
|
1135
|
+
rb_raise (EM_eConnectionError, "%s", e.what());
|
1136
|
+
}
|
1137
|
+
return Qnil;
|
1138
|
+
}
|
1054
1139
|
|
1055
1140
|
/************************
|
1056
1141
|
t_get_heartbeat_interval
|
@@ -1137,6 +1222,7 @@ extern "C" void Init_rubyeventmachine()
|
|
1137
1222
|
rb_define_module_function (EmModule, "attach_fd", (VALUE (*)(...))t_attach_fd, 2);
|
1138
1223
|
rb_define_module_function (EmModule, "detach_fd", (VALUE (*)(...))t_detach_fd, 1);
|
1139
1224
|
rb_define_module_function (EmModule, "get_sock_opt", (VALUE (*)(...))t_get_sock_opt, 3);
|
1225
|
+
rb_define_module_function (EmModule, "set_sock_opt", (VALUE (*)(...))t_set_sock_opt, 4);
|
1140
1226
|
rb_define_module_function (EmModule, "set_notify_readable", (VALUE (*)(...))t_set_notify_readable, 2);
|
1141
1227
|
rb_define_module_function (EmModule, "set_notify_writable", (VALUE (*)(...))t_set_notify_writable, 2);
|
1142
1228
|
rb_define_module_function (EmModule, "is_notify_readable", (VALUE (*)(...))t_is_notify_readable, 1);
|
@@ -1145,9 +1231,11 @@ extern "C" void Init_rubyeventmachine()
|
|
1145
1231
|
rb_define_module_function (EmModule, "pause_connection", (VALUE (*)(...))t_pause, 1);
|
1146
1232
|
rb_define_module_function (EmModule, "resume_connection", (VALUE (*)(...))t_resume, 1);
|
1147
1233
|
rb_define_module_function (EmModule, "connection_paused?", (VALUE (*)(...))t_paused_p, 1);
|
1234
|
+
rb_define_module_function (EmModule, "num_close_scheduled", (VALUE (*)(...))t_num_close_scheduled, 0);
|
1148
1235
|
|
1149
1236
|
rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 4);
|
1150
1237
|
rb_define_module_function (EmModule, "stop_proxy", (VALUE (*)(...))t_stop_proxy, 1);
|
1238
|
+
rb_define_module_function (EmModule, "get_proxied_bytes", (VALUE (*)(...))t_proxied_bytes, 1);
|
1151
1239
|
|
1152
1240
|
rb_define_module_function (EmModule, "watch_filename", (VALUE (*)(...))t_watch_filename, 1);
|
1153
1241
|
rb_define_module_function (EmModule, "unwatch_filename", (VALUE (*)(...))t_unwatch_filename, 1);
|
@@ -1171,6 +1259,7 @@ extern "C" void Init_rubyeventmachine()
|
|
1171
1259
|
rb_define_module_function (EmModule, "send_file_data", (VALUE(*)(...))t_send_file_data, 2);
|
1172
1260
|
rb_define_module_function (EmModule, "get_heartbeat_interval", (VALUE(*)(...))t_get_heartbeat_interval, 0);
|
1173
1261
|
rb_define_module_function (EmModule, "set_heartbeat_interval", (VALUE(*)(...))t_set_heartbeat_interval, 1);
|
1262
|
+
rb_define_module_function (EmModule, "get_idle_time", (VALUE(*)(...))t_get_idle_time, 1);
|
1174
1263
|
|
1175
1264
|
rb_define_module_function (EmModule, "get_peername", (VALUE(*)(...))t_get_peername, 1);
|
1176
1265
|
rb_define_module_function (EmModule, "get_sockname", (VALUE(*)(...))t_get_sockname, 1);
|
data/ext/ssl.cpp
CHANGED
@@ -137,7 +137,7 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
137
137
|
bLibraryInitialized = true;
|
138
138
|
SSL_library_init();
|
139
139
|
OpenSSL_add_ssl_algorithms();
|
140
|
-
|
140
|
+
OpenSSL_add_all_algorithms();
|
141
141
|
SSL_load_error_strings();
|
142
142
|
ERR_load_crypto_strings();
|
143
143
|
|
@@ -151,6 +151,9 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
151
151
|
|
152
152
|
SSL_CTX_set_options (pCtx, SSL_OP_ALL);
|
153
153
|
//SSL_CTX_set_options (pCtx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3));
|
154
|
+
#ifdef SSL_MODE_RELEASE_BUFFERS
|
155
|
+
SSL_CTX_set_mode (pCtx, SSL_MODE_RELEASE_BUFFERS);
|
156
|
+
#endif
|
154
157
|
|
155
158
|
if (is_server) {
|
156
159
|
// The SSL_CTX calls here do NOT allocate memory.
|
@@ -159,11 +162,14 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
159
162
|
e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM);
|
160
163
|
else
|
161
164
|
e = SSL_CTX_use_PrivateKey (pCtx, DefaultPrivateKey);
|
165
|
+
if (e <= 0) ERR_print_errors_fp(stderr);
|
162
166
|
assert (e > 0);
|
167
|
+
|
163
168
|
if (certchainfile.length() > 0)
|
164
169
|
e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str());
|
165
170
|
else
|
166
171
|
e = SSL_CTX_use_certificate (pCtx, DefaultCertificate);
|
172
|
+
if (e <= 0) ERR_print_errors_fp(stderr);
|
167
173
|
assert (e > 0);
|
168
174
|
}
|
169
175
|
|
@@ -177,10 +183,12 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
177
183
|
int e;
|
178
184
|
if (privkeyfile.length() > 0) {
|
179
185
|
e = SSL_CTX_use_PrivateKey_file (pCtx, privkeyfile.c_str(), SSL_FILETYPE_PEM);
|
186
|
+
if (e <= 0) ERR_print_errors_fp(stderr);
|
180
187
|
assert (e > 0);
|
181
188
|
}
|
182
189
|
if (certchainfile.length() > 0) {
|
183
190
|
e = SSL_CTX_use_certificate_chain_file (pCtx, certchainfile.c_str());
|
191
|
+
if (e <= 0) ERR_print_errors_fp(stderr);
|
184
192
|
assert (e > 0);
|
185
193
|
}
|
186
194
|
}
|
@@ -524,6 +524,10 @@ public class EmReactor {
|
|
524
524
|
return Connections.get(sig).getPeerName();
|
525
525
|
}
|
526
526
|
|
527
|
+
public Object[] getSockName (long sig) {
|
528
|
+
return Connections.get(sig).getSockName();
|
529
|
+
}
|
530
|
+
|
527
531
|
public long attachChannel (SocketChannel sc, boolean watch_mode) {
|
528
532
|
long b = createBinding();
|
529
533
|
|
@@ -183,6 +183,12 @@ public class EventableDatagramChannel implements EventableChannel {
|
|
183
183
|
}
|
184
184
|
}
|
185
185
|
|
186
|
+
public Object[] getSockName () {
|
187
|
+
DatagramSocket socket = channel.socket();
|
188
|
+
return new Object[]{ socket.getLocalPort(),
|
189
|
+
socket.getLocalAddress().getHostAddress() };
|
190
|
+
}
|
191
|
+
|
186
192
|
public boolean isWatchOnly() { return false; }
|
187
193
|
public boolean isNotifyReadable() { return false; }
|
188
194
|
public boolean isNotifyWritable() { return false; }
|
@@ -302,6 +302,12 @@ public class EventableSocketChannel implements EventableChannel {
|
|
302
302
|
return new Object[]{ sock.getPort(), sock.getInetAddress().getHostAddress() };
|
303
303
|
}
|
304
304
|
|
305
|
+
public Object[] getSockName () {
|
306
|
+
Socket sock = channel.socket();
|
307
|
+
return new Object[]{ sock.getLocalPort(),
|
308
|
+
sock.getLocalAddress().getHostAddress() };
|
309
|
+
}
|
310
|
+
|
305
311
|
public void setWatchOnly() {
|
306
312
|
bWatchOnly = true;
|
307
313
|
updateEvents();
|
data/lib/em/completion.rb
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
#
|
17
17
|
# == Basic Usage
|
18
18
|
#
|
19
|
-
# As already mentioned, the basic usage of a Completion is simply for
|
19
|
+
# As already mentioned, the basic usage of a Completion is simply for its two
|
20
20
|
# final states, :succeeded and :failed.
|
21
21
|
#
|
22
22
|
# An asynchronous operation will complete at some future point in time, and
|
@@ -24,8 +24,8 @@
|
|
24
24
|
# some common interface to react to these events.
|
25
25
|
#
|
26
26
|
# In the following example, the user wants to know when a short lived
|
27
|
-
# connection has completed
|
28
|
-
# protocol just waits for an ack to
|
27
|
+
# connection has completed its exchange with the remote server. The simple
|
28
|
+
# protocol just waits for an ack to its message.
|
29
29
|
#
|
30
30
|
# class Protocol < EM::Connection
|
31
31
|
# include EM::P::LineText2
|
@@ -199,6 +199,7 @@ module EventMachine
|
|
199
199
|
@callbacks[state] << EM::Callback(*a, &b)
|
200
200
|
end
|
201
201
|
execute_callbacks
|
202
|
+
self
|
202
203
|
end
|
203
204
|
|
204
205
|
# Callbacks are called when you enter (or are in) a :succeeded state.
|
data/lib/em/connection.rb
CHANGED
@@ -121,7 +121,7 @@ module EventMachine
|
|
121
121
|
# been completed, as a result of calling #start_tls to initiate SSL/TLS on the connection.
|
122
122
|
#
|
123
123
|
# This callback exists because {#post_init} and {#connection_completed} are **not** reliable
|
124
|
-
# for indicating when an SSL/TLS connection is ready to have
|
124
|
+
# for indicating when an SSL/TLS connection is ready to have its certificate queried for.
|
125
125
|
#
|
126
126
|
# @see #get_peer_cert
|
127
127
|
def ssl_handshake_completed
|
@@ -238,6 +238,12 @@ module EventMachine
|
|
238
238
|
EventMachine::disable_proxy(self)
|
239
239
|
end
|
240
240
|
|
241
|
+
# The number of bytes proxied to another connection. Reset to zero when
|
242
|
+
# EventMachine::Connection#proxy_incoming_to is called, and incremented whenever data is proxied.
|
243
|
+
def get_proxied_bytes
|
244
|
+
EventMachine::get_proxied_bytes(@signature)
|
245
|
+
end
|
246
|
+
|
241
247
|
# EventMachine::Connection#close_connection is called only by user code, and never
|
242
248
|
# by the event loop. You may call this method against a connection object in any
|
243
249
|
# callback handler, whether or not the callback was made against the connection
|
@@ -270,6 +276,10 @@ module EventMachine
|
|
270
276
|
EventMachine::get_sock_opt @signature, level, option
|
271
277
|
end
|
272
278
|
|
279
|
+
def set_sock_opt level, optname, optval
|
280
|
+
EventMachine::set_sock_opt @signature, level, optname, optval
|
281
|
+
end
|
282
|
+
|
273
283
|
# A variant of {#close_connection}.
|
274
284
|
# All of the descriptive comments given for close_connection also apply to
|
275
285
|
# close_connection_after_writing, *with one exception*: if the connection has
|
@@ -467,7 +477,7 @@ module EventMachine
|
|
467
477
|
# # -----END CERTIFICATE-----
|
468
478
|
#
|
469
479
|
# You can do whatever you want with the certificate String, such as load it
|
470
|
-
# as a certificate object using the OpenSSL library, and check
|
480
|
+
# as a certificate object using the OpenSSL library, and check its fields.
|
471
481
|
#
|
472
482
|
# @return [String] the remote [X509 certificate](http://en.wikipedia.org/wiki/X.509), in the popular [PEM format](http://en.wikipedia.org/wiki/Privacy_Enhanced_Mail),
|
473
483
|
# if TLS is active on the connection
|
@@ -566,6 +576,11 @@ module EventMachine
|
|
566
576
|
EventMachine::get_subprocess_status @signature
|
567
577
|
end
|
568
578
|
|
579
|
+
# The number of seconds since the last send/receive activity on this connection.
|
580
|
+
def get_idle_time
|
581
|
+
EventMachine::get_idle_time @signature
|
582
|
+
end
|
583
|
+
|
569
584
|
# comm_inactivity_timeout returns the current value (float in seconds) of the inactivity-timeout
|
570
585
|
# property of network-connection and datagram-socket objects. A nonzero value
|
571
586
|
# indicates that the connection or socket will automatically be closed if no read or write
|
data/lib/em/iterator.rb
CHANGED
@@ -4,46 +4,46 @@ module EventMachine
|
|
4
4
|
# Unlike ruby's built-in iterators, the end of the current iteration cycle is signaled manually,
|
5
5
|
# instead of happening automatically after the yielded block finishes executing. For example:
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# (0..10).each{ |num| }
|
8
8
|
#
|
9
9
|
# becomes:
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# EM::Iterator.new(0..10).each{ |num,iter| iter.next }
|
12
12
|
#
|
13
13
|
# This is especially useful when doing asynchronous work via reactor libraries and
|
14
14
|
# functions. For example, given a sync and async http api:
|
15
15
|
#
|
16
|
-
#
|
17
|
-
#
|
16
|
+
# response = sync_http_get(url); ...
|
17
|
+
# async_http_get(url){ |response| ... }
|
18
18
|
#
|
19
19
|
# a synchronous iterator such as:
|
20
20
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
21
|
+
# responses = urls.map{ |url| sync_http_get(url) }
|
22
|
+
# ...
|
23
|
+
# puts 'all done!'
|
24
24
|
#
|
25
25
|
# could be written as:
|
26
26
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
27
|
+
# EM::Iterator.new(urls).map(proc{ |url,iter|
|
28
|
+
# async_http_get(url){ |res|
|
29
|
+
# iter.return(res)
|
30
|
+
# }
|
31
|
+
# }, proc{ |responses|
|
32
|
+
# ...
|
33
|
+
# puts 'all done!'
|
34
|
+
# })
|
35
35
|
#
|
36
36
|
# Now, you can take advantage of the asynchronous api to issue requests in parallel. For example,
|
37
37
|
# to fetch 10 urls at a time, simply pass in a concurrency of 10:
|
38
38
|
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
39
|
+
# EM::Iterator.new(urls, 10).each do |url,iter|
|
40
|
+
# async_http_get(url){ iter.next }
|
41
|
+
# end
|
42
42
|
#
|
43
43
|
class Iterator
|
44
44
|
# Create a new parallel async iterator with specified concurrency.
|
45
45
|
#
|
46
|
-
#
|
46
|
+
# i = EM::Iterator.new(1..100, 10)
|
47
47
|
#
|
48
48
|
# will create an iterator over the range that processes 10 items at a time. Iteration
|
49
49
|
# is started via #each, #map or #inject
|
@@ -70,17 +70,17 @@ module EventMachine
|
|
70
70
|
|
71
71
|
# Iterate over a set of items using the specified block or proc.
|
72
72
|
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
73
|
+
# EM::Iterator.new(1..100).each do |num, iter|
|
74
|
+
# puts num
|
75
|
+
# iter.next
|
76
|
+
# end
|
77
77
|
#
|
78
78
|
# An optional second proc is invoked after the iteration is complete.
|
79
79
|
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
80
|
+
# EM::Iterator.new(1..100).each(
|
81
|
+
# proc{ |num,iter| iter.next },
|
82
|
+
# proc{ puts 'all done' }
|
83
|
+
# )
|
84
84
|
#
|
85
85
|
def each(foreach=nil, after=nil, &blk)
|
86
86
|
raise ArgumentError, 'proc or block required for iteration' unless foreach ||= blk
|
@@ -136,13 +136,13 @@ module EventMachine
|
|
136
136
|
|
137
137
|
# Collect the results of an asynchronous iteration into an array.
|
138
138
|
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
139
|
+
# EM::Iterator.new(%w[ pwd uptime uname date ], 2).map(proc{ |cmd,iter|
|
140
|
+
# EM.system(cmd){ |output,status|
|
141
|
+
# iter.return(output)
|
142
|
+
# }
|
143
|
+
# }, proc{ |results|
|
144
|
+
# p results
|
145
|
+
# })
|
146
146
|
#
|
147
147
|
def map(foreach, after)
|
148
148
|
index = 0
|
@@ -174,14 +174,14 @@ module EventMachine
|
|
174
174
|
|
175
175
|
# Inject the results of an asynchronous iteration onto a given object.
|
176
176
|
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
177
|
+
# EM::Iterator.new(%w[ pwd uptime uname date ], 2).inject({}, proc{ |hash,cmd,iter|
|
178
|
+
# EM.system(cmd){ |output,status|
|
179
|
+
# hash[cmd] = status.exitstatus == 0 ? output.strip : nil
|
180
|
+
# iter.return(hash)
|
181
|
+
# }
|
182
|
+
# }, proc{ |results|
|
183
|
+
# p results
|
184
|
+
# })
|
185
185
|
#
|
186
186
|
def inject(obj, foreach, after)
|
187
187
|
each(proc{ |item,iter|
|
data/lib/em/pool.rb
CHANGED
@@ -122,7 +122,10 @@ module EventMachine
|
|
122
122
|
|
123
123
|
def failure resource
|
124
124
|
if @on_error
|
125
|
+
@contents.delete resource
|
125
126
|
@on_error.call resource
|
127
|
+
# Prevent users from calling a leak.
|
128
|
+
@removed.delete resource
|
126
129
|
else
|
127
130
|
requeue resource
|
128
131
|
end
|
@@ -140,7 +143,9 @@ module EventMachine
|
|
140
143
|
else
|
141
144
|
raise ArgumentError, "deferrable expected from work"
|
142
145
|
end
|
146
|
+
rescue Exception
|
147
|
+
failure resource
|
148
|
+
raise
|
143
149
|
end
|
144
|
-
|
145
150
|
end
|
146
|
-
end
|
151
|
+
end
|
@@ -24,7 +24,6 @@
|
|
24
24
|
#
|
25
25
|
#
|
26
26
|
|
27
|
-
require 'readbytes'
|
28
27
|
require 'postgres-pr/message'
|
29
28
|
require 'postgres-pr/connection'
|
30
29
|
require 'stringio'
|
@@ -35,15 +34,14 @@ class StringIO
|
|
35
34
|
#
|
36
35
|
# If the data read is nil an EOFError is raised.
|
37
36
|
#
|
38
|
-
# If the data read is too short
|
39
|
-
# data is obtainable via its #data method.
|
37
|
+
# If the data read is too short an IOError is raised
|
40
38
|
def readbytes(n)
|
41
39
|
str = read(n)
|
42
40
|
if str == nil
|
43
41
|
raise EOFError, "End of file reached"
|
44
42
|
end
|
45
43
|
if str.size < n
|
46
|
-
raise
|
44
|
+
raise IOError, "data truncated"
|
47
45
|
end
|
48
46
|
str
|
49
47
|
end
|
@@ -68,15 +66,15 @@ module EventMachine
|
|
68
66
|
# in basically a production-ready state, and the wire protocol isn't that complicated
|
69
67
|
# anyway.
|
70
68
|
#
|
71
|
-
# We need to monkeypatch StringIO because it lacks the #readbytes method needed
|
72
|
-
# by postgres-pr.
|
73
|
-
#
|
74
69
|
# We're tucking in a bunch of require statements that may not be present in garden-variety
|
75
70
|
# EM installations. Until we find a good way to only require these if a program
|
76
71
|
# requires postgres, this file will need to be required explicitly.
|
77
72
|
#
|
78
|
-
#
|
73
|
+
# We need to monkeypatch StringIO because it lacks the #readbytes method needed
|
74
|
+
# by postgres-pr.
|
75
|
+
# The StringIO monkeypatch is lifted from the standard library readbytes.rb,
|
79
76
|
# which adds method #readbytes directly to class IO. But StringIO is not a subclass of IO.
|
77
|
+
# It is modified to raise an IOError instead of TruncatedDataException since the exception is unused.
|
80
78
|
#
|
81
79
|
# We cloned the handling of postgres messages from lib/postgres-pr/connection.rb
|
82
80
|
# in the postgres-pr library, and modified it for event-handling.
|