eventmachine-eventmachine 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +169 -0
- data/docs/COPYING +60 -0
- data/docs/ChangeLog +183 -0
- data/docs/DEFERRABLES +138 -0
- data/docs/EPOLL +141 -0
- data/docs/GNU +281 -0
- data/docs/INSTALL +15 -0
- data/docs/KEYBOARD +38 -0
- data/docs/LEGAL +25 -0
- data/docs/LIGHTWEIGHT_CONCURRENCY +72 -0
- data/docs/PURE_RUBY +77 -0
- data/docs/README +74 -0
- data/docs/RELEASE_NOTES +96 -0
- data/docs/SMTP +9 -0
- data/docs/SPAWNED_PROCESSES +93 -0
- data/docs/TODO +10 -0
- data/ext/binder.cpp +126 -0
- data/ext/binder.h +48 -0
- data/ext/cmain.cpp +530 -0
- data/ext/cplusplus.cpp +172 -0
- data/ext/ed.cpp +1473 -0
- data/ext/ed.h +361 -0
- data/ext/em.cpp +1895 -0
- data/ext/em.h +170 -0
- data/ext/emwin.cpp +300 -0
- data/ext/emwin.h +94 -0
- data/ext/epoll.cpp +26 -0
- data/ext/epoll.h +25 -0
- data/ext/eventmachine.h +90 -0
- data/ext/eventmachine_cpp.h +94 -0
- data/ext/extconf.rb +150 -0
- data/ext/files.cpp +94 -0
- data/ext/files.h +65 -0
- data/ext/kb.cpp +368 -0
- data/ext/page.cpp +107 -0
- data/ext/page.h +51 -0
- data/ext/pipe.cpp +327 -0
- data/ext/project.h +119 -0
- data/ext/rubymain.cpp +683 -0
- data/ext/sigs.cpp +89 -0
- data/ext/sigs.h +32 -0
- data/ext/ssl.cpp +408 -0
- data/ext/ssl.h +86 -0
- data/java/src/com/rubyeventmachine/Application.java +196 -0
- data/java/src/com/rubyeventmachine/Connection.java +74 -0
- data/java/src/com/rubyeventmachine/ConnectionFactory.java +37 -0
- data/java/src/com/rubyeventmachine/DefaultConnectionFactory.java +46 -0
- data/java/src/com/rubyeventmachine/EmReactor.java +408 -0
- data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +57 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +171 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +244 -0
- data/java/src/com/rubyeventmachine/PeriodicTimer.java +38 -0
- data/java/src/com/rubyeventmachine/Timer.java +54 -0
- data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +108 -0
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +124 -0
- data/java/src/com/rubyeventmachine/tests/EMTest.java +80 -0
- data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +53 -0
- data/java/src/com/rubyeventmachine/tests/TestServers.java +74 -0
- data/java/src/com/rubyeventmachine/tests/TestTimers.java +89 -0
- data/lib/em/deferrable.rb +208 -0
- data/lib/em/eventable.rb +39 -0
- data/lib/em/future.rb +62 -0
- data/lib/em/messages.rb +66 -0
- data/lib/em/processes.rb +68 -0
- data/lib/em/spawnable.rb +88 -0
- data/lib/em/streamer.rb +112 -0
- data/lib/eventmachine.rb +1763 -0
- data/lib/eventmachine_version.rb +31 -0
- data/lib/evma.rb +32 -0
- data/lib/evma/callback.rb +32 -0
- data/lib/evma/container.rb +75 -0
- data/lib/evma/factory.rb +77 -0
- data/lib/evma/protocol.rb +87 -0
- data/lib/evma/reactor.rb +48 -0
- data/lib/jeventmachine.rb +137 -0
- data/lib/pr_eventmachine.rb +1011 -0
- data/lib/protocols/buftok.rb +127 -0
- data/lib/protocols/header_and_content.rb +129 -0
- data/lib/protocols/httpcli2.rb +794 -0
- data/lib/protocols/httpclient.rb +270 -0
- data/lib/protocols/line_and_text.rb +122 -0
- data/lib/protocols/linetext2.rb +163 -0
- data/lib/protocols/postgres.rb +261 -0
- data/lib/protocols/saslauth.rb +179 -0
- data/lib/protocols/smtpclient.rb +308 -0
- data/lib/protocols/smtpserver.rb +556 -0
- data/lib/protocols/stomp.rb +130 -0
- data/lib/protocols/tcptest.rb +57 -0
- data/tasks/cpp.rake +77 -0
- data/tasks/project.rake +78 -0
- data/tasks/tests.rake +192 -0
- data/tests/test_attach.rb +66 -0
- data/tests/test_basic.rb +231 -0
- data/tests/test_defer.rb +47 -0
- data/tests/test_epoll.rb +161 -0
- data/tests/test_errors.rb +82 -0
- data/tests/test_eventables.rb +78 -0
- data/tests/test_exc.rb +58 -0
- data/tests/test_futures.rb +214 -0
- data/tests/test_hc.rb +218 -0
- data/tests/test_httpclient.rb +215 -0
- data/tests/test_httpclient2.rb +133 -0
- data/tests/test_kb.rb +61 -0
- data/tests/test_ltp.rb +192 -0
- data/tests/test_ltp2.rb +320 -0
- data/tests/test_next_tick.rb +102 -0
- data/tests/test_processes.rb +56 -0
- data/tests/test_pure.rb +129 -0
- data/tests/test_running.rb +47 -0
- data/tests/test_sasl.rb +74 -0
- data/tests/test_send_file.rb +245 -0
- data/tests/test_servers.rb +80 -0
- data/tests/test_smtpclient.rb +81 -0
- data/tests/test_smtpserver.rb +93 -0
- data/tests/test_spawn.rb +329 -0
- data/tests/test_ssl_args.rb +68 -0
- data/tests/test_timers.rb +146 -0
- data/tests/test_ud.rb +43 -0
- data/tests/testem.rb +31 -0
- metadata +197 -0
data/Rakefile
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
#--
|
3
|
+
# Ruby/EventMachine
|
4
|
+
# http://rubyeventmachine.com
|
5
|
+
# Copyright (C) 2006-07 by Francis Cianfrocca
|
6
|
+
#
|
7
|
+
# This program is copyrighted free software. You may use it under
|
8
|
+
# the terms of either the GPL or Ruby's License. See the file
|
9
|
+
# COPYING in the EventMachine distribution for full licensing
|
10
|
+
# information.
|
11
|
+
#
|
12
|
+
# $Id$
|
13
|
+
#++
|
14
|
+
|
15
|
+
### OLD RAKE: ###
|
16
|
+
# # The tasks and external gemspecs we used to generate binary gems are now
|
17
|
+
# # obsolete. Use Patrick Hurley's gembuilder to build binary gems for any
|
18
|
+
# # desired platform.
|
19
|
+
# # To build a binary gem on Win32, ensure that the include and lib paths
|
20
|
+
# # both contain the proper references to OPENSSL. Use the static version
|
21
|
+
# # of the libraries, not the dynamic, otherwise we expose the user to a
|
22
|
+
# # runtime dependency.
|
23
|
+
#
|
24
|
+
# # To build a binary gem for win32, first build rubyeventmachine.so
|
25
|
+
# # using VC6 outside of the build tree (the normal way: ruby extconf.rb,
|
26
|
+
# # and then nmake). Then copy rubyeventmachine.so into the lib directory,
|
27
|
+
# # and run rake gemwin32.
|
28
|
+
#
|
29
|
+
|
30
|
+
require 'rubygems' unless defined?(Gem)
|
31
|
+
require 'rake' unless defined?(Rake)
|
32
|
+
require 'rake/gempackagetask'
|
33
|
+
|
34
|
+
Package = false # Build zips and tarballs?
|
35
|
+
Dir.glob('tasks/*.rake').each { |r| Rake.application.add_import r }
|
36
|
+
|
37
|
+
# e.g. rake EVENTMACHINE_LIBRARY=java for forcing java build tasks as defaults!
|
38
|
+
$eventmachine_library = :java if RUBY_PLATFORM =~ /java/ || ENV['EVENTMACHINE_LIBRARY'] == 'java'
|
39
|
+
$eventmachine_library = :pure_ruby if ENV['EVENTMACHINE_LIBRARY'] == 'pure_ruby'
|
40
|
+
|
41
|
+
MAKE = ENV['MAKE'] || if RUBY_PLATFORM =~ /mswin/ # mingw uses make.
|
42
|
+
'nmake'
|
43
|
+
else
|
44
|
+
'make'
|
45
|
+
end
|
46
|
+
|
47
|
+
# If running under rubygems...
|
48
|
+
__DIR__ ||= File.expand_path(File.dirname(__FILE__))
|
49
|
+
if Gem.path.any? {|path| %r(^#{Regexp.escape path}) =~ __DIR__}
|
50
|
+
task :default => :gem_build
|
51
|
+
else
|
52
|
+
desc "Build gemspec, then build eventmachine, then run tests."
|
53
|
+
task :default => [:gemspec, :build, :test]
|
54
|
+
end
|
55
|
+
|
56
|
+
desc ":default build when running under rubygems."
|
57
|
+
task :gem_build => :build
|
58
|
+
|
59
|
+
desc "Build extension (or EVENTMACHINE_LIBRARY) and place in lib"
|
60
|
+
build_task = 'ext:build'
|
61
|
+
build_task = 'java:build' if $eventmachine_library == :java
|
62
|
+
build_task = :dummy_build if $eventmachine_library == :pure_ruby
|
63
|
+
task :build => build_task do |t|
|
64
|
+
Dir.glob('{ext,java/src}/*.{so,bundle,dll,jar}').each do |f|
|
65
|
+
mv f, "lib"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
task :dummy_build
|
70
|
+
|
71
|
+
# Basic clean definition, this is enhanced by imports aswell.
|
72
|
+
task :clean do
|
73
|
+
chdir 'ext' do
|
74
|
+
sh "#{MAKE} clean" if test ?e, 'Makefile'
|
75
|
+
end
|
76
|
+
Dir.glob('**/Makefile').each { |file| rm file }
|
77
|
+
Dir.glob('**/*.{o,so,bundle,class,jar,dll,log}').each { |file| rm file }
|
78
|
+
end
|
79
|
+
|
80
|
+
Spec = Gem::Specification.new do |s|
|
81
|
+
s.name = "eventmachine"
|
82
|
+
s.summary = "Ruby/EventMachine library"
|
83
|
+
s.platform = Gem::Platform::RUBY
|
84
|
+
|
85
|
+
s.has_rdoc = true
|
86
|
+
s.rdoc_options = %w(--title EventMachine --main docs/README --line-numbers)
|
87
|
+
s.extra_rdoc_files = Dir['docs/*']
|
88
|
+
|
89
|
+
s.files = %w(Rakefile) + Dir["{bin,tests,lib,ext,java,tasks}/**/*"]
|
90
|
+
|
91
|
+
s.require_path = 'lib'
|
92
|
+
|
93
|
+
# TODO / XXX - should we enable this? rubygems fails the install if anything
|
94
|
+
# is broken. What we could do is CI submission, though, and always terminate
|
95
|
+
# with a positive code...
|
96
|
+
# s.test_file = "tests/testem.rb"
|
97
|
+
s.extensions = "Rakefile"
|
98
|
+
|
99
|
+
s.author = "Francis Cianfrocca"
|
100
|
+
s.email = "garbagecat10@gmail.com"
|
101
|
+
s.rubyforge_project = 'eventmachine'
|
102
|
+
s.homepage = "http://rubyeventmachine.com"
|
103
|
+
|
104
|
+
# Pulled in from readme, as code to pull from readme was not working!
|
105
|
+
# Might be worth removing as no one seems to use gem info anyway.
|
106
|
+
s.description = <<-EOD
|
107
|
+
EventMachine implements a fast, single-threaded engine for arbitrary network
|
108
|
+
communications. It's extremely easy to use in Ruby. EventMachine wraps all
|
109
|
+
interactions with IP sockets, allowing programs to concentrate on the
|
110
|
+
implementation of network protocols. It can be used to create both network
|
111
|
+
servers and clients. To create a server or client, a Ruby program only needs
|
112
|
+
to specify the IP address and port, and provide a Module that implements the
|
113
|
+
communications protocol. Implementations of several standard network protocols
|
114
|
+
are provided with the package, primarily to serve as examples. The real goal
|
115
|
+
of EventMachine is to enable programs to easily interface with other programs
|
116
|
+
using TCP/IP, especially if custom protocols are required.
|
117
|
+
EOD
|
118
|
+
|
119
|
+
require 'lib/eventmachine_version'
|
120
|
+
s.version = EventMachine::VERSION
|
121
|
+
end
|
122
|
+
|
123
|
+
namespace :ext do
|
124
|
+
desc "Build C++ extension"
|
125
|
+
task :build => [:clean, :make]
|
126
|
+
|
127
|
+
desc "make extension"
|
128
|
+
task :make => [:makefile] do
|
129
|
+
chdir 'ext' do
|
130
|
+
sh MAKE
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
desc 'Compile the makefile'
|
135
|
+
task :makefile do |t|
|
136
|
+
chdir 'ext' do
|
137
|
+
ruby 'extconf.rb'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
namespace :java do
|
143
|
+
# This task creates the JRuby JAR file and leaves it in the lib directory.
|
144
|
+
# This step is required before executing the jgem task.
|
145
|
+
desc "Build java extension"
|
146
|
+
task :build => [:jar] do |t|
|
147
|
+
chdir('java/src') do
|
148
|
+
mv 'em_reactor.jar', '../../lib/em_reactor.jar'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
desc "compile .java to .class"
|
153
|
+
task :compile do
|
154
|
+
chdir('java/src') do
|
155
|
+
sh 'javac com/rubyeventmachine/*.java'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
desc "compile .classes to .jar"
|
160
|
+
task :jar => [:compile] do
|
161
|
+
chdir('java/src') do
|
162
|
+
sh "jar -cf em_reactor.jar com/rubyeventmachine/*.class"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
task :gemspec => :clean do
|
168
|
+
open("eventmachine.gemspec", 'w') { |f| f.write Spec.to_ruby }
|
169
|
+
end
|
data/docs/COPYING
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
EventMachine is copyrighted free software owned by Francis Cianfrocca
|
2
|
+
(blackhedd ... gmail.com). The Owner of this software permits you to
|
3
|
+
redistribute and/or modify the software under either the terms of the GPL
|
4
|
+
version 2 (see the file GPL), or the conditions below ("Ruby License"):
|
5
|
+
|
6
|
+
1. You may make and give away verbatim copies of the source form of this
|
7
|
+
software without restriction, provided that you retain ALL of the
|
8
|
+
original copyright notices and associated disclaimers.
|
9
|
+
|
10
|
+
2. You may modify your copy of the software in any way, provided that
|
11
|
+
you do at least ONE of the following:
|
12
|
+
|
13
|
+
a) place your modifications in the Public Domain or otherwise
|
14
|
+
make them Freely Available, such as by posting said
|
15
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
16
|
+
the author to include your modifications in the software.
|
17
|
+
|
18
|
+
b) use the modified software only within your corporation or
|
19
|
+
organization.
|
20
|
+
|
21
|
+
c) give non-standard binaries non-standard names, with
|
22
|
+
instructions on where to get the original software distribution.
|
23
|
+
|
24
|
+
d) make other distribution arrangements with the Owner.
|
25
|
+
|
26
|
+
3. You may distribute the software in object code or binary form,
|
27
|
+
provided that you do at least ONE of the following:
|
28
|
+
|
29
|
+
a) distribute the binaries and library files of the software,
|
30
|
+
together with instructions (in a manual page or equivalent)
|
31
|
+
on where to get the original distribution.
|
32
|
+
|
33
|
+
b) accompany the distribution with the machine-readable source of
|
34
|
+
the software.
|
35
|
+
|
36
|
+
c) give non-standard binaries non-standard names, with
|
37
|
+
instructions on where to get the original software distribution.
|
38
|
+
|
39
|
+
d) make other distribution arrangements with the Owner.
|
40
|
+
|
41
|
+
4. You may modify and include parts of the software into any other
|
42
|
+
software (possibly commercial), provided you comply with the terms in
|
43
|
+
Sections 1, 2, and 3 above. But some files in the distribution
|
44
|
+
are not written by the Owner, so they may be made available to you
|
45
|
+
under different terms.
|
46
|
+
|
47
|
+
For the list of those files and their copying conditions, see the
|
48
|
+
file LEGAL.
|
49
|
+
|
50
|
+
5. The scripts and library files supplied as input to or produced as
|
51
|
+
output from the software do not automatically fall under the
|
52
|
+
copyright of the software, but belong to whoever generated them,
|
53
|
+
and may be sold commercially, and may be aggregated with this
|
54
|
+
software.
|
55
|
+
|
56
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
57
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
58
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
59
|
+
PURPOSE.
|
60
|
+
|
data/docs/ChangeLog
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
# $Id$
|
2
|
+
#
|
3
|
+
#
|
4
|
+
|
5
|
+
#-------------------------------------------------------------
|
6
|
+
01Oct06: Replaced EventMachine#open_datagram_server with a version that can take
|
7
|
+
a Class or a Module, instead of just a Module. Thanks to Tobias Gustafsson for
|
8
|
+
pointing out the missing case.
|
9
|
+
|
10
|
+
04Oct06: Supported subsecond timer resolutions, per request by Jason Roelofs.
|
11
|
+
05Oct06: Added EventMachine#set_quantum, which sets the timer resolution.
|
12
|
+
15Nov06: Added Connection#set_comm_inactivity_timeout.
|
13
|
+
15Nov06: Checked in a Line-and-Text Protocol Handler.
|
14
|
+
18Nov06: Checked in a Header-and-Body Protocol Handler.
|
15
|
+
22Nov06: Changed EventMachine#reconnect: no longer excepts when called on an
|
16
|
+
already-connected handler.
|
17
|
+
28Nov06: Supported a binary-unix gem.
|
18
|
+
19Dec06: Added EventMachine#set_effective_user.
|
19
|
+
05Jan07: Upped max outstanding timers to 1000.
|
20
|
+
15May07: Applied Solaris patches from Brett Eisenberg
|
21
|
+
22May07: Cleaned up the license text in all the source files.
|
22
|
+
22May07: Released version 0.7.2
|
23
|
+
|
24
|
+
23May07: Per suggestion from Bill Kelly, fixed a bug with the initialization
|
25
|
+
of the network libraries under Windows. The goal is to enable EM to
|
26
|
+
be used without Ruby.
|
27
|
+
28May07: Applied patch from Bill Kelly, refactors the declarations of
|
28
|
+
event names to make EM easier to use from C programs without Ruby.
|
29
|
+
31May07: Added a preliminary implementation of EventMachine#popen.
|
30
|
+
01Jun07: Added EM, a "pseudo-alias" for EventMachine.
|
31
|
+
01Jun07: Added EM#next_tick.
|
32
|
+
01Jun07: Added EM::Connection#get_outbound_data_size
|
33
|
+
05Jun07: Removed the code which loads a pure-Ruby EM library in case the
|
34
|
+
compiled extension is unavailable. Suggested by Moshe Litvin.
|
35
|
+
06Jun07: Preliminary epoll implementation.
|
36
|
+
12Jun07: Added an evented popen implementation that, like Ruby's, is
|
37
|
+
full-duplex and makes the subprocess PID available to the caller.
|
38
|
+
06Jul07: Performance-tweaked the callback dispatcher in eventmachine.rb.
|
39
|
+
10Jul07: Released version 0.8.0.
|
40
|
+
12Jul07: Applied patches from Tim Pease to fix Solaris build problems.
|
41
|
+
15Jul07: Created a new provisional source branch, experiments/jruby-1.
|
42
|
+
This is a preliminary implementation of the EM reactor in Java,
|
43
|
+
suitable for use with JRuby.
|
44
|
+
17Jul07: Added EventMachine#stop_server, per request from Kirk Haines,
|
45
|
+
and associated unit tests.
|
46
|
+
22Jul07: Added EventMachine#stream_file_data. This is a very fast and scalable
|
47
|
+
way of sending data from static files over network connections. It
|
48
|
+
has separate implementations for small files and large file, and
|
49
|
+
has tunings to minimize memory consumption.
|
50
|
+
26Jul07: Added some patches by Kirk Haines to improve the behavior of
|
51
|
+
EM::Connection#send_file_data_to_connection.
|
52
|
+
26Jul07: Added a C++ module for directly integrating EM into C++ programs
|
53
|
+
with no Ruby dependencies. Needs example code.
|
54
|
+
29Jul07: Added EventMachine::Protocols::LineText2.
|
55
|
+
29Jul07: Added EventMachine::Protocols::Stomp.
|
56
|
+
30Jul07: Added sys/stat.h to project.h to fix compilation bug on Darwin.
|
57
|
+
13Aug07: Added EventMachine#reactor_running?
|
58
|
+
15Aug07: Added parameters for EventMachine::Connection:start_tls that can be
|
59
|
+
used to specify client-side private keys and certificates.
|
60
|
+
17Aug07: Added EventMachine#run_block, a sugaring for a common use case.
|
61
|
+
24Aug07: Added a preliminary keyboard handler. Needs docs and testing on
|
62
|
+
windows.
|
63
|
+
26Aug07: Created EventMachine::Spawnable, an implementation of Erlang-like
|
64
|
+
processes.
|
65
|
+
27Aug07: Silenced some -w warnings, requested by James Edward Gray II.
|
66
|
+
30Aug07: Added cookies to EM::HttpClient#request.
|
67
|
+
04Sep07: Added an initial implementation of an evented SMTP client.
|
68
|
+
04Sep07: Added an initial implementation of an evented SMTP server.
|
69
|
+
10Sep07: Changed EM#spawn to run spawned blocks in the context of the
|
70
|
+
SpawnedProcess object, not of whatever was the active object at the
|
71
|
+
time of the spawn.
|
72
|
+
14Sep07: Heartbeats weren't working with EPOLL. Noticed by Brian Candler.
|
73
|
+
15Sep07: Added some features, tests and documents to Deferrable.
|
74
|
+
16Sep07: Added [:content] parameter to EM::Protocols::SmtpClient#send.
|
75
|
+
16Sep07: Bumped version to 0.9.0 in anticipation of a release.
|
76
|
+
18Sep07: Released version 0.9.0.
|
77
|
+
19Sep07: Added #receive_reset to EM::Protocols::SmtpServer.
|
78
|
+
19Sep07: User overrides of EM::Protocols::SmtpServer#receive_recipient can now
|
79
|
+
return a Deferrable. Also fixed bug: SmtpClient now raises a protocol
|
80
|
+
error if none of its RCPT TO: commands are accepted by the server.
|
81
|
+
26Sep07: Fixed missing keyboard support for Windows.
|
82
|
+
03Oct07: Added a default handler for RuntimeErrors emitted from user-written
|
83
|
+
code. Suggested by Brian Candler.
|
84
|
+
19Oct07: Set the SO_BROADCAST option automatically on all UDP sockets.
|
85
|
+
10Nov07: Forced integer conversion of send_datagram's port parameter.
|
86
|
+
Suggested by Matthieu Riou.
|
87
|
+
12Nov07: Added saslauth.rb, a protocol module to replace the Cyrus SASL
|
88
|
+
daemons saslauthd and pwcheck.
|
89
|
+
15Nov07: Fixed bug reported by Mark Zvillius. We were failing to dispatch
|
90
|
+
zero-length datagrams under certain conditions.
|
91
|
+
19Nov07: Added EventMachine#set_max_timers. Requested by Matthieu Riou and
|
92
|
+
others.
|
93
|
+
19Nov07: Fixed bug with EM::Connection#start_tls. Was not working with server
|
94
|
+
connections. Reported by Michael S. Fischer.
|
95
|
+
26Nov07: Supported a hack for EventMachine#popen so it can return an exit
|
96
|
+
status from subprocesses. Requested by Michael S. Fischer.
|
97
|
+
30Nov07: Changed Pipe descriptors so that the child-side of the socketpair is
|
98
|
+
NOT set nonblocking. Suggested by Duane Johnson.
|
99
|
+
05Dec07: Re-enabled the pure-Ruby implementation.
|
100
|
+
06Dec07: Released Version 0.10.0.
|
101
|
+
13Dec07: Added EM::DeferrableChildProcess
|
102
|
+
24Dec07: Added a SASL client for simple password authentication.
|
103
|
+
27Dec07: Removed the hookable error handler. No one was using it and it significantly
|
104
|
+
degraded performance.
|
105
|
+
30Dec07: Implemented Kqueue support for OSX and BSD.
|
106
|
+
04Jan08: Fixed bug in epoll ("Bad file descriptor"), patch supplied by Chris
|
107
|
+
Heath.
|
108
|
+
04Jan08: Fixed bug reported by Michael S. Fischer. We were terminating
|
109
|
+
SSL connections that sent data before the handshake was complete.
|
110
|
+
08Jan08: Added an OpenBSD branch for extconf.rb, contributed by Guillaume
|
111
|
+
Sellier.
|
112
|
+
19Jan08: Added EM::Connection::get_sockname per request by Michael Fischer.
|
113
|
+
19Jan08: Supported IPv6 addresses.
|
114
|
+
30Apr08: Set the NODELAY option on sockets that we connect to other servers.
|
115
|
+
Omission noted by Roger Pack.
|
116
|
+
14May08: Generated a 0.12 release.
|
117
|
+
15May08: Supported EM#get_sockname for acceptors (TCP server sockets).
|
118
|
+
Requested by Roger Pack.
|
119
|
+
15May08; Accepted a patch from Dan Aquino that allows the interval of a
|
120
|
+
PeriodicTimer to be changed on the fly.
|
121
|
+
15Jun08: Supported nested calls to EM#run. Many people contributed ideas to
|
122
|
+
this, notably raggi and tmm1.
|
123
|
+
20Jul08: Accepted patch from tmm1 for EM#fork_reactor.
|
124
|
+
28Jul08: Added a Postgres3 implementation, written by FCianfrocca.
|
125
|
+
14Aug08: Added a patch by Mike Murphy to support basic auth in the http
|
126
|
+
client.
|
127
|
+
28Aug08: Added a patch by tmm1 to fix a longstanding problem with Java
|
128
|
+
data-sends.
|
129
|
+
13Sep08: Added LineText2#set_binary_mode, a back-compatibility alias.
|
130
|
+
13Sep08: Modified the load order of protocol libraries in eventmachine.rb
|
131
|
+
to permit a modification of HeaderAndContentProtocol.
|
132
|
+
13Sep08: Modified HeaderAndContent to use LineText2, which is less buggy
|
133
|
+
than LineAndTextProtocol. This change may be reversed if we can fix
|
134
|
+
the bugs in buftok.
|
135
|
+
13Sep08: Improved the password handling in the Postgres protocol handler.
|
136
|
+
15Sep08: Added attach/detach, contributed by Aman Gupta (tmm1) and Riham Aldakkak,
|
137
|
+
to support working with file descriptors not created in the reactor.
|
138
|
+
16Sep08: Added an optional version string to the HTTP client. This is a hack
|
139
|
+
that allows a client to specify a version 1.0 request, which
|
140
|
+
keeps the server from sending a chunked response. The right way to
|
141
|
+
solve this, of course, is to support chunked responses.
|
142
|
+
23Sep08: ChangeLog Summary for Merge of branches/raggi
|
143
|
+
Most notable work and patches by Aman Gupta, Roger Pack, and James Tucker.
|
144
|
+
Patches / Tickets also submitted by: Jeremy Evans, aanand, darix, mmmurf,
|
145
|
+
danielaquino, macournoyer.
|
146
|
+
- Moved docs into docs/ dir
|
147
|
+
- Major refactor of rakefile, added generic rakefile helpers in tasks
|
148
|
+
- Added example CPP build rakefile in tasks/cpp.rake
|
149
|
+
- Moved rake tests out to tasks/tests.rake
|
150
|
+
- Added svn ignores where appropriate
|
151
|
+
- Fixed jruby build on older java platforms
|
152
|
+
- Gem now builds from Rakefile rather than directly via extconf
|
153
|
+
- Gem unified for jruby, C++ and pure ruby.
|
154
|
+
- Correction for pure C++ build, removing ruby dependency
|
155
|
+
- Fix for CYGWIN builds on ipv6
|
156
|
+
- Major refactor for extconf.rb
|
157
|
+
- Working mingw builds
|
158
|
+
- extconf optionally uses pkg_config over manual configuration
|
159
|
+
- extconf builds for 1.9 on any system that has 1.9
|
160
|
+
- extconf no longer links pthread explicitly
|
161
|
+
- looks for kqueue on all *nix systems
|
162
|
+
- better error output on std::runtime_error, now says where it came from
|
163
|
+
- Fixed some tests on jruby
|
164
|
+
- Added test for general send_data flaw, required for a bugfix in jruby build
|
165
|
+
- Added timeout to epoll tests
|
166
|
+
- Added fixes for java reactor ruby api
|
167
|
+
- Small addition of some docs in httpclient.rb and httpcli2.rb
|
168
|
+
- Some refactor and fixes in smtpserver.rb
|
169
|
+
- Added parenthesis where possible to avoid excess ruby warnings
|
170
|
+
- Refactor of $eventmachine_library logic for accuracy and maintenance, jruby
|
171
|
+
- EM::start_server now supports unix sockets
|
172
|
+
- EM::connect now supports unix sockets
|
173
|
+
- EM::defer @threadqueue now handled more gracefully
|
174
|
+
- Added better messages on exceptions raised
|
175
|
+
- Fix edge case in timer fires
|
176
|
+
- Explicitly require buftok.rb
|
177
|
+
- Add protocols to autoload, rather than require them all immediately
|
178
|
+
- Fix a bug in pr_eventmachine for outbound_q
|
179
|
+
- Refactors to take some of the use of defer out of tests.
|
180
|
+
- Fixes in EM.defer under start/stop conditions. Reduced scope of threads.
|
181
|
+
23Sep08: Added patch from tmm1 to avoid popen errors on exit.
|
182
|
+
30Sep08: Added File.exists? checks in the args for start_tls, as suggested by
|
183
|
+
Brian Lopez (brianmario).
|
data/docs/DEFERRABLES
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
$Id$
|
2
|
+
|
3
|
+
[DOCUMENT UNDER CONSTRUCTION]
|
4
|
+
|
5
|
+
EventMachine (EM) adds two different formalisms for lightweight concurrency to the Ruby programmer's toolbox: spawned processes and deferrables. This note will show you how to use deferrables. For more information, see the separate document LIGHTWEIGHT_CONCURRENCY.
|
6
|
+
|
7
|
+
|
8
|
+
=== What are Deferrables?
|
9
|
+
|
10
|
+
EventMachine's Deferrable borrows heavily from the "deferred" object in Python's "Twisted" event-handling framework. Here's a minimal example that illustrates Deferrable:
|
11
|
+
|
12
|
+
require 'eventmachine'
|
13
|
+
|
14
|
+
class MyClass
|
15
|
+
include EM::Deferrable
|
16
|
+
|
17
|
+
def print_value x
|
18
|
+
puts "MyClass instance received #{x}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
EM.run {
|
23
|
+
df = MyClass.new
|
24
|
+
df.callback {|x|
|
25
|
+
df.print_value(x)
|
26
|
+
EM.stop
|
27
|
+
}
|
28
|
+
|
29
|
+
EM::Timer.new(2) {
|
30
|
+
df.set_deferred_status :succeeded, 100
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
This program will spin for two seconds, print out the string "MyClass instance received 100" and then exit. The Deferrable pattern relies on an unusual metaphor that may be unfamiliar to you, unless you've used Python's Twisted. You may need to read the following material through more than once before you get the idea.
|
36
|
+
|
37
|
+
EventMachine::Deferrable is simply a Ruby Module that you can include in your own classes. (There also is a class named EventMachine::DefaultDeferrable for when you want to create one without including it in code of your own.)
|
38
|
+
|
39
|
+
An object that includes EventMachine::Deferrable is like any other Ruby object: it can be created whenever you want, returned from your functions, or passed as an argument to other functions.
|
40
|
+
|
41
|
+
The Deferrable pattern allows you to specify any number of Ruby code blocks (callbacks or errbacks) that will be executed at some future time when the status of the Deferrable object changes.
|
42
|
+
|
43
|
+
How might that be useful? Well, imagine that you're implementing an HTTP server, but you need to make a call to some other server in order to fulfill a client request.
|
44
|
+
|
45
|
+
When you receive a request from one of your clients, you can create and return a Deferrable object. Some other section of your program can add a callback to the Deferrable that will cause the client's request to be fulfilled. Simultaneously, you initiate an event-driven or threaded client request to some different server. And then your EM program will continue to process other events and service other client requests.
|
46
|
+
|
47
|
+
When your client request to the other server completes some time later, you will call the #set_deferred_status method on the Deferrable object, passing either a success or failure status, and an arbitrary number of parameters (which might include the data you received from the other server).
|
48
|
+
|
49
|
+
At that point, the status of the Deferrable object becomes known, and its callback or errback methods are immediately executed. Callbacks and errbacks are code blocks that are attached to Deferrable objects at any time through the methods #callback and #errback.
|
50
|
+
|
51
|
+
The deep beauty of this pattern is that it decouples the disposition of one operation (such as a client request to an outboard server) from the subsequent operations that depend on that disposition (which may include responding to a different client or any other operation).
|
52
|
+
|
53
|
+
The code which invokes the deferred operation (that will eventually result in a success or failure status together with associated data) is completely separate from the code which depends on that status and data. This achieves one of the primary goals for which threading is typically used in sophisticated applications, with none of the nondeterminacy or debugging difficulties of threads.
|
54
|
+
|
55
|
+
As soon as the deferred status of a Deferrable becomes known by way of a call to #set_deferred_status, the Deferrable will IMMEDIATELY execute all of its callbacks or errbacks in the order in which they were added to the Deferrable.
|
56
|
+
|
57
|
+
Callbacks and errbacks can be added to a Deferrable object at any time, not just when the object is created. They can even be added after the status of the object has been determined! (In this case, they will be executed immediately when they are added.)
|
58
|
+
|
59
|
+
A call to Deferrable#set_deferred_status takes :succeeded or :failed as its first argument. (This determines whether the object will call its callbacks or its errbacks.) #set_deferred_status also takes zero or more additional parameters, that will in turn be passed as parameters to the callbacks or errbacks.
|
60
|
+
|
61
|
+
In general, you can only call #set_deferred_status ONCE on a Deferrable object. A call to #set_deferred_status will not return until all of the associated callbacks or errbacks have been called. If you add callbacks or errbacks AFTER making a call to #set_deferred_status, those additional callbacks or errbacks will execute IMMEDIATELY. Any given callback or errback will be executed AT MOST once.
|
62
|
+
|
63
|
+
It's possible to call #set_deferred_status AGAIN, during the execution a callback or errback. This makes it possible to change the parameters which will be sent to the callbacks or errbacks farther down the chain, enabling some extremely elegant use-cases. You can transform the data returned from a deferred operation in arbitrary ways as needed by subsequent users, without changing any of the code that generated the original data.
|
64
|
+
|
65
|
+
A call to #set_deferred_status will not return until all of the associated callbacks or errbacks have been called. If you add callbacks or errbacks AFTER making a call to #set_deferred_status, those additional callbacks or errbacks will execute IMMEDIATELY.
|
66
|
+
|
67
|
+
Let's look at some more sample code. It turns out that many of the internal protocol implementations in the EventMachine package rely on Deferrable. One of these is EM::Protocols::HttpClient.
|
68
|
+
|
69
|
+
To make an evented HTTP request, use the module function EM::Protocols::HttpClient#request, which returns a Deferrable object. Here's how:
|
70
|
+
|
71
|
+
require 'eventmachine'
|
72
|
+
|
73
|
+
EM.run {
|
74
|
+
df = EM::Protocols::HttpClient.request( :host=>"www.example.com", :request=>"/index.html" )
|
75
|
+
|
76
|
+
df.callback {|response|
|
77
|
+
puts "Succeeded: #{response[:content]}"
|
78
|
+
EM.stop
|
79
|
+
}
|
80
|
+
|
81
|
+
df.errback {|response|
|
82
|
+
puts "ERROR: #{response[:status]}"
|
83
|
+
EM.stop
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
(See the documentation of EventMachine::Protocols::HttpClient for information on the object returned by #request.)
|
88
|
+
|
89
|
+
In this code, we make a call to HttpClient#request, which immediately returns a Deferrable object. In the background, an HTTP client request is being made to www.example.com, although your code will continue to run concurrently.
|
90
|
+
|
91
|
+
At some future point, the HTTP client request will complete, and the code in EM::Protocols::HttpClient will process either a valid HTTP response (including returned content), or an error.
|
92
|
+
|
93
|
+
At that point, EM::Protocols::HttpClient will call EM::Deferrable#set_deferred_status on the Deferrable object that was returned to your program, as the return value from EM::Protocols::HttpClient.request. You don't have to do anything to make this happen. All you have to do is tell the Deferrable what to do in case of either success, failure, or both.
|
94
|
+
|
95
|
+
In our code sample, we set one callback and one errback. The former will be called if the HTTP call succeeds, and the latter if it fails. (For simplicity, we have both of them calling EM#stop to end the program, although real programs would be very unlikely to do this.)
|
96
|
+
|
97
|
+
Setting callbacks and errbacks is optional. They are handlers to defined events in the lifecycle of the Deferrable event. It's not an error if you fail to set either a callback, an errback, or both. But of course your program will then fail to receive those notifications.
|
98
|
+
|
99
|
+
If through some bug it turns out that #set_deferred_status is never called on a Deferrable object, then that object's callbacks or errbacks will NEVER be called. It's also possible to set a timeout on a Deferrable. If the timeout elapses before any other call to #set_deferred_status, the Deferrable object will behave as is you had called set_deferred_status(:failed) on it.
|
100
|
+
|
101
|
+
|
102
|
+
Now let's modify the example to illustrate some additional points:
|
103
|
+
|
104
|
+
require 'eventmachine'
|
105
|
+
|
106
|
+
EM.run {
|
107
|
+
df = EM::Protocols::HttpClient.request( :host=>"www.example.com", :request=>"/index.html" )
|
108
|
+
|
109
|
+
df.callback {|response|
|
110
|
+
df.set_deferred_status :succeeded, response[:content]
|
111
|
+
}
|
112
|
+
|
113
|
+
df.callback {|string|
|
114
|
+
puts "Succeeded: #{string}"
|
115
|
+
EM.stop
|
116
|
+
}
|
117
|
+
|
118
|
+
df.errback {|response|
|
119
|
+
puts "ERROR: #{response[:status]}"
|
120
|
+
EM.stop
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
Just for the sake of illustration, we've now set two callbacks instead of one. If the deferrable operation (the HTTP client-request) succeeds, then both of the callbacks will be executed in order.
|
126
|
+
|
127
|
+
But notice that we've also made our own call to #set_deferred_status in the first callback. This isn't required, because the HttpClient implementation already made a call to #set_deferred_status. (Otherwise, of course, the callback would not be executing.)
|
128
|
+
|
129
|
+
But we used #set_deferred_status in the first callback in order to change the parameters that will be sent to subsequent callbacks in the chain. In this way, you can construct powerful sequences of layered functionality. If you want, you can even change the status of the Deferrable from :succeeded to :failed, which would abort the chain of callback calls, and invoke the chain of errbacks instead.
|
130
|
+
|
131
|
+
Now of course it's somewhat trivial to define two callbacks in the same method, even with the parameter-changing effect we just described. It would be much more interesting to pass the Deferrable to some other function (for example, a function defined in another module or a different gem), that would in turn add callbacks and/or errbacks of its own. That would illustrate the true power of the Deferrable pattern: to isolate the HTTP client-request from other functions that use the data that it returns without caring where those data came from.
|
132
|
+
|
133
|
+
Remember that you can add a callback or an errback to a Deferrable at any point in time, regardless of whether the status of the deferred operation is known (more precisely, regardless of when #set_deferred_status is called on the object). Even hours or days later.
|
134
|
+
|
135
|
+
When you add a callback or errback to a Deferrable object on which #set_deferred_status has not yet been called, the callback/errback is queued up for future execution, inside the Deferrable object. When you add a callback or errback to a Deferrable on which #set_deferred_status has already been called, the callback/errback will be executed immediately. Your code doesn't have to worry about the ordering, and there are no timing issues, as there would be with a threaded approach.
|
136
|
+
|
137
|
+
For more information on Deferrables and their typical usage patterns, look in the EM unit tests. There are also quite a few sugarings (including EM::Deferrable#future) that make typical Deferrable usages syntactically easier to work with.
|
138
|
+
|