| CODENOTIFIER | HelpYou are not signed inSign in |
Project: rev
Revision: 246
Author: tarcieri
Date: 18 Aug 2008 17:30:06
Changes:Nuke contents of trunk
Files:| ... | ...@@ -1,166 +0,0 @@ | |
| 1 | = Rev | |
| 2 | ||
| 3 | Rev is an event library for Ruby, built on the libev event library which | |
| 4 | provides a cross-platform interface to high performance system calls . This | |
| 5 | includes the epoll system call for Linux, the kqueue system call for BSDs and | |
| 6 | OS X, and the completion ports interface for Solaris. | |
| 7 | ||
| 8 | Rev also binds asynchronous wrappers to Ruby's core socket classes so you can | |
| 9 | use them in conjunction with Rev to build asynchronous event-driven | |
| 10 | applications. | |
| 11 | ||
| 12 | You can include Rev in your programs with: | |
| 13 | ||
| 14 | require 'rubygems' | |
| 15 | require 'rev' | |
| 16 | ||
| 17 | For more information, consult the RubyForge page: | |
| 18 | ||
| 19 | http://rev.rubyforge.org | |
| 20 | ||
| 21 | http://rubyforge.org/projects/rev | |
| 22 | ||
| 23 | Questions? Sign up for the mailing list at: | |
| 24 | ||
| 25 | http://rubyforge.org/mailman/listinfo/rev-talk | |
| 26 | ||
| 27 | The latest development code is available at: | |
| 28 | ||
| 29 | http://rev.rubyforge.org/svn/trunk | |
| 30 | ||
| 31 | == Anatomy | |
| 32 | ||
| 33 | Rev builds on two core classes which bind to the libev API: | |
| 34 | ||
| 35 | * Rev::Loop - This class represents an event loop which uses underlying high | |
| 36 | performance system calls to wait for events. | |
| 37 | ||
| 38 | * Rev::Watcher - This is the base class for event observers. Once you attach | |
| 39 | an event observer to a loop and start running it, you will begin receiving | |
| 40 | callbacks to particlar methods when events occur. | |
| 41 | ||
| 42 | == Watchers | |
| 43 | ||
| 44 | There are presently two types of watchers: | |
| 45 | ||
| 46 | * Rev::IOWatcher - This class waits for an IO object to become readable, | |
| 47 | writable, or both. | |
| 48 | ||
| 49 | * Rev::TimerWatcher - This class waits for a specified duration then fires | |
| 50 | an event. You can also configure it to fire an event at specified intervals. | |
| 51 | ||
| 52 | == Using Watchers | |
| 53 | ||
| 54 | Watchers have five important methods: | |
| 55 | ||
| 56 | * attach(loop) - This binds a watcher to the specified event loop. If the | |
| 57 | watcher is already bound to a loop it will be detached first, then attached | |
| 58 | to the new one. | |
| 59 | ||
| 60 | * detach - This completely unbinds a watcher from an event loop. | |
| 61 | ||
| 62 | * disable - This stops the watcher from receiving events but does not unbind | |
| 63 | it from the loop. If you are trying to toggle a watcher on and off, it's | |
| 64 | best to use this method (and enable) as it performs better than completely | |
| 65 | removing the watcher from the event loop. | |
| 66 | ||
| 67 | * enable - This re-enables a watcher which has been disabled in the past. | |
| 68 | The watcher must still be bound to an event loop. | |
| 69 | ||
| 70 | * evloop - This returns the Rev::Loop object which the watcher is currently | |
| 71 | bound to. | |
| 72 | ||
| 73 | == Asynchronous Wrappers | |
| 74 | ||
| 75 | Several classes which provide asynchronous event-driven wrappers for Ruby's | |
| 76 | core socket classes are also provided. Among these are: | |
| 77 | ||
| 78 | * Rev::TCPSocket - A buffered wrapper to core Ruby's Socket class for use with | |
| 79 | TCP sockets. You can asynchronously create outgoing TCP connections using | |
| 80 | its Rev::TCPSocket.connect method. Rev::TCPSocket provides write buffering | |
| 81 | to ensure that writing never blocks, and has asynchronous callbacks for | |
| 82 | several events, including when the connection is opened (or failed), when | |
| 83 | data is received, when the write buffer has been written out completely, | |
| 84 | and when the connection closes. | |
| 85 | ||
| 86 | * Rev::TCPServer - A wrapper for TCPServer which creates new instances of | |
| 87 | Rev::TCPSocket (or any subclass you wish to provide) whenever an incoming | |
| 88 | connection is received. | |
| 89 | ||
| 90 | * Rev::HttpClient - An HTTP/1.1 client with support for chunked encoding | |
| 91 | and streaming response processing through asynchronous callbacks. | |
| 92 | ||
| 93 | == Example Program | |
| 94 | ||
| 95 | Below is an example of how to write an echo server: | |
| 96 | ||
| 97 | require 'rev' | |
| 98 | HOST = 'localhost' | |
| 99 | PORT = 4321 | |
| 100 | ||
| 101 | class EchoServerConnection < Rev::TCPSocket | |
| 102 | def on_connect | |
| 103 | puts "#{remote_addr}:#{remote_port} connected" | |
| 104 | end | |
| 105 | ||
| 106 | def on_close | |
| 107 | puts "#{remote_addr}:#{remote_port} disconnected" | |
| 108 | end | |
| 109 | ||
| 110 | def on_read(data) | |
| 111 | write data | |
| 112 | end | |
| 113 | end | |
| 114 | ||
| 115 | server = Rev::TCPServer.new(HOST, PORT, EchoServerConnection) | |
| 116 | server.attach(Rev::Loop.default) | |
| 117 | ||
| 118 | puts "Echo server listening on #{HOST}:#{PORT}" | |
| 119 | Rev::Loop.default.run | |
| 120 | ||
| 121 | Here a new observer type (EchoServerConnection) is made by subclassing an | |
| 122 | existing one and adding new implementations to existing event handlers. | |
| 123 | ||
| 124 | A new event loop is created, and a new Rev::TCPServer (whose base class is | |
| 125 | Rev::Watcher) is created and attached to the event loop. | |
| 126 | ||
| 127 | Once this is done, the event loop is started with event_loop.run. This method | |
| 128 | will block until there are no active watchers for the loop or the loop is | |
| 129 | stopped explicitly with event_loop.stop. | |
| 130 | ||
| 131 | == Defining Callbacks at Runtime | |
| 132 | ||
| 133 | It's often tedious to subclass in order to just change one callback. Rev | |
| 134 | gives you the ability to change event callbacks on the fly (provided you | |
| 135 | haven't overridden them in a subclass). This is especially useful for small | |
| 136 | one off programs or just experimenting with the API. | |
| 137 | ||
| 138 | Any callback (methods prefixed with on_*) can be set on the fly by passing it | |
| 139 | a block. (NOTE: Ruby 1.9/1.8.7 only) | |
| 140 | ||
| 141 | Below is an example of using this syntax. It implements an echo server | |
| 142 | identical to the one above: | |
| 143 | ||
| 144 | HOST = '127.0.0.1' | |
| 145 | PORT = 4321 | |
| 146 | ||
| 147 | server = Rev::TCPServer.new(HOST, PORT) do |c| | |
| 148 | c.on_connect { puts "#{remote_addr}:#{remote_port} connected" } | |
| 149 | c.on_close { puts "#{remote_addr}:#{remote_port} disconnected" } | |
| 150 | c.on_read { |data| write data } | |
| 151 | end | |
| 152 | ||
| 153 | server.attach(Rev::Loop.default) | |
| 154 | ||
| 155 | puts "Echo server listening on #{HOST}:#{PORT}" | |
| 156 | Rev::Loop.default.run | |
| 157 | ||
| 158 | As you can see, it provides a more concise (albeint slightly slower) | |
| 159 | expression of the same server as above, without the need to subclass. | |
| 160 | ||
| 161 | Rev::TCPServer will automatically yield new connections if a block is | |
| 162 | given. In this case the "c" variable being passed to the block is | |
| 163 | a new instance of Rev::TCPSocket representing the newly created connection. | |
| 164 | ||
| 165 | The above example sets the on_connect, on_close, and on_read callbacks each | |
| 166 | time a new connection is created. |
| ... | ...@@ -1,27 +0,0 @@ | |
| 1 | require 'rubygems' | |
| 2 | ||
| 3 | GEMSPEC = Gem::Specification.new do |s| | |
| 4 | s.name = "rev" | |
| 5 | s.version = "0.2.3" | |
| 6 | s.authors = "Tony Arcieri" | |
| 7 | s.email = "tony@medioh.com" | |
| 8 | s.date = "2008-5-31" | |
| 9 | s.summary = "Rev is a Ruby binding to the libev high performance event library" | |
| 10 | s.platform = Gem::Platform::RUBY | |
| 11 | s.required_ruby_version = '>= 1.8.6' | |
| 12 | ||
| 13 | # Gem contents | |
| 14 | s.files = Dir.glob("{lib,ext,examples}/**/*") + ['Rakefile', 'rev.gemspec'] | |
| 15 | ||
| 16 | # RubyForge info | |
| 17 | s.homepage = "http://rev.rubyforge.org" | |
| 18 | s.rubyforge_project = "rev" | |
| 19 | ||
| 20 | # RDoc settings | |
| 21 | s.has_rdoc = true | |
| 22 | s.rdoc_options = %w(--title Rev --main README --line-numbers) | |
| 23 | s.extra_rdoc_files = ["LICENSE", "README", "CHANGES"] | |
| 24 | ||
| 25 | # Extensions | |
| 26 | s.extensions = FileList["ext/**/extconf.rb"].to_a | |
| 27 | end |
| ... | ...@@ -1,58 +0,0 @@ | |
| 1 | Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>. | |
| 2 | You can redistribute it and/or modify it under either the terms of the GPL | |
| 3 | (see COPYING.txt file), or the conditions below: | |
| 4 | ||
| 5 | 1. You may make and give away verbatim copies of the source form of the | |
| 6 | software without restriction, provided that you duplicate all of the | |
| 7 | original copyright notices and associated disclaimers. | |
| 8 | ||
| 9 | 2. You may modify your copy of the software in any way, provided that | |
| 10 | you do at least ONE of the following: | |
| 11 | ||
| 12 | a) place your modifications in the Public Domain or otherwise | |
| 13 | make them Freely Available, such as by posting said | |
| 14 | modifications to Usenet or an equivalent medium, or by allowing | |
| 15 | the author to include your modifications in the software. | |
| 16 | ||
| 17 | b) use the modified software only within your corporation or | |
| 18 | organization. | |
| 19 | ||
| 20 | c) rename any non-standard executables so the names do not conflict | |
| 21 | with standard executables, which must also be provided. | |
| 22 | ||
| 23 | d) make other distribution arrangements with the author. | |
| 24 | ||
| 25 | 3. You may distribute the software in object code or executable | |
| 26 | form, provided that you do at least ONE of the following: | |
| 27 | ||
| 28 | a) distribute the executables and library files of the software, | |
| 29 | together with instructions (in the manual page or equivalent) | |
| 30 | on where to get the original distribution. | |
| 31 | ||
| 32 | b) accompany the distribution with the machine-readable source of | |
| 33 | the software. | |
| 34 | ||
| 35 | c) give non-standard executables non-standard names, with | |
| 36 | instructions on where to get the original software distribution. | |
| 37 | ||
| 38 | d) make other distribution arrangements with the author. | |
| 39 | ||
| 40 | 4. You may modify and include the part of the software into any other | |
| 41 | software (possibly commercial). But some files in the distribution | |
| 42 | are not written by the author, so that they are not under this terms. | |
| 43 | ||
| 44 | They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some | |
| 45 | files under the ./missing directory. See each file for the copying | |
| 46 | condition. | |
| 47 | ||
| 48 | 5. The scripts and library files supplied as input to or produced as | |
| 49 | output from the software do not automatically fall under the | |
| 50 | copyright of the software, but belong to whomever generated them, | |
| 51 | and may be sold commercially, and may be aggregated with this | |
| 52 | software. | |
| 53 | ||
| 54 | 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR | |
| 55 | IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
| 56 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 57 | PURPOSE. | |
| 58 |
| ... | ...@@ -1,80 +0,0 @@ | |
| 1 | require 'rake' | |
| 2 | require 'rake/clean' | |
| 3 | require 'rake/rdoctask' | |
| 4 | require 'rake/gempackagetask' | |
| 5 | require 'fileutils' | |
| 6 | include FileUtils | |
| 7 | ||
| 8 | # Load Rev Gemspec | |
| 9 | load 'rev.gemspec' | |
| 10 | ||
| 11 | # Default Rake task is compile | |
| 12 | task :default => :compile | |
| 13 | ||
| 14 | # RDoc | |
| 15 | Rake::RDocTask.new(:rdoc) do |task| | |
| 16 | task.rdoc_dir = 'doc' | |
| 17 | task.title = 'Rev' | |
| 18 | task.options = %w(--title Revactor --main README --line-numbers) | |
| 19 | task.rdoc_files.include(['ext/rev/*.c', 'lib/**/*.rb']) | |
| 20 | task.rdoc_files.include(['README', 'LICENSE']) | |
| 21 | end | |
| 22 | ||
| 23 | # Rebuild parser Ragel | |
| 24 | task :ragel do | |
| 25 | Dir.chdir "ext/http11_client" do | |
| 26 | target = "http11_parser.c" | |
| 27 | File.unlink target if File.exist? target | |
| 28 | sh "ragel http11_parser.rl | rlgen-cd -G2 -o #{target}" | |
| 29 | raise "Failed to build C source" unless File.exist? target | |
| 30 | end | |
| 31 | end | |
| 32 | ||
| 33 | # Gem | |
| 34 | Rake::GemPackageTask.new(GEMSPEC) do |pkg| | |
| 35 | pkg.need_tar = true | |
| 36 | end | |
| 37 | ||
| 38 | def make(makedir) | |
| 39 | Dir.chdir(makedir) { sh 'make' } | |
| 40 | end | |
| 41 | ||
| 42 | def extconf(dir) | |
| 43 | Dir.chdir(dir) { ruby "extconf.rb" } | |
| 44 | end | |
| 45 | ||
| 46 | def setup_extension(dir, extension) | |
| 47 | ext = "ext/#{dir}" | |
| 48 | ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}" | |
| 49 | ext_files = FileList[ | |
| 50 | "#{ext}/*.c", | |
| 51 | "#{ext}/*.h", | |
| 52 | "#{ext}/extconf.rb", | |
| 53 | "#{ext}/Makefile", | |
| 54 | "lib" | |
| 55 | ] | |
| 56 | ||
| 57 | task "lib" do | |
| 58 | directory "lib" | |
| 59 | end | |
| 60 | ||
| 61 | desc "Builds just the #{extension} extension" | |
| 62 | task extension.to_sym => ["#{ext}/Makefile", ext_so ] | |
| 63 | ||
| 64 | file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do | |
| 65 | extconf "#{ext}" | |
| 66 | end | |
| 67 | ||
| 68 | file ext_so => ext_files do | |
| 69 | make "#{ext}" | |
| 70 | cp ext_so, "lib" | |
| 71 | end | |
| 72 | end | |
| 73 | ||
| 74 | setup_extension("rev", "rev_ext") | |
| 75 | setup_extension("http11_client", "http11_client") | |
| 76 | ||
| 77 | task :compile => [:rev_ext, :http11_client] | |
| 78 | ||
| 79 | CLEAN.include ['build/*', '**/*.o', '**/*.so', '**/*.a', '**/*.log', 'pkg'] | |
| 80 | CLEAN.include ['ext/rev/Makefile', 'lib/rev_ext.*', 'lib/http11_client.*'] |
| ... | ...@@ -1,128 +0,0 @@ | |
| 1 | 0.2.2: | |
| 2 | ||
| 3 | * Correct a pointer arithmetic error in the buffering code that could result | |
| 4 | in data corruption. | |
| 5 | ||
| 6 | * Upgrade to libev 3.41 | |
| 7 | ||
| 8 | * Relax HTTP/1.1 reponse parser to allow the "reason" portion of the response | |
| 9 | header to be omitted | |
| 10 | ||
| 11 | 0.2.1: | |
| 12 | ||
| 13 | * Upgrade to libev 3.31 | |
| 14 | ||
| 15 | * Rev::Loop#run_once and Rev::Loop#run_nonblock now return the number of events | |
| 16 | received when they were running | |
| 17 | ||
| 18 | * Remove inheritence relationship between Rev::IO and Rev::IOWatcher | |
| 19 | ||
| 20 | * Loosen HTTP/1.1 response parser to accept a common malformation in HTTP/1.1 | |
| 21 | chunk headers | |
| 22 | ||
| 23 | * Add underscore prefix to instance variables to avoid conflicts in subclasses | |
| 24 | ||
| 25 | * Remove Rev::SSLServer until it can be made more useful | |
| 26 | ||
| 27 | 0.2.0: | |
| 28 | ||
| 29 | * Initial Ruby 1.8.6 support | |
| 30 | ||
| 31 | * Omit Rev::LIBEV_VERSION constant | |
| 32 | ||
| 33 | * Catch Errno::ECONNRESET when writing to sockets | |
| 34 | ||
| 35 | * SSL support via Rev::SSL, with a small C extension subclassing Ruby's | |
| 36 | OpenSSL::SSL::SSLSocket allowing for non-blocking SSL handshakes | |
| 37 | ||
| 38 | * Initial Rev::Utils implementation with #ncpus and methods to query and | |
| 39 | change the maximum number of file descriptors for the current process. | |
| 40 | ||
| 41 | * Initial Rev::AsyncWatcher implementation for cross-thread signaling | |
| 42 | ||
| 43 | * Handle unspecified Content-Length when encoding is identity in HttpClient | |
| 44 | ||
| 45 | * Fix bug in HttpClient processing zero Content-Length | |
| 46 | ||
| 47 | * Get rid of method_missing stuff in Rev::HttpClient | |
| 48 | ||
| 49 | * Have Rev::HttpClient close the connection on error | |
| 50 | ||
| 51 | * Allow Rev::TCPSocket#on_connect to be private when accepting connections | |
| 52 | from a Rev::TCPServer | |
| 53 | ||
| 54 | 0.1.4: | |
| 55 | ||
| 56 | * Calibrate Rev::TimerWatchers against ev_time() and ev_now() when the watcher | |
| 57 | is attached to the loop to ensure that the timeout interval is correct. | |
| 58 | ||
| 59 | * Add check to ensure that a Rev::Loop cannot be run from within a callback | |
| 60 | ||
| 61 | * Store Rev::Loop.default in a Thread-specific instance variable | |
| 62 | ||
| 63 | * Upgrade libev to 0.3.0 | |
| 64 | ||
| 65 | * Rename BufferedIO to IO | |
| 66 | ||
| 67 | * Fixed bug in BufferedIO#write_output_buffer causing it to spin endlessly on | |
| 68 | an empty buffer. | |
| 69 | ||
| 70 | * Added has_active_watchers? to Rev::Loop to check for active watchers | |
| 71 | ||
| 72 | 0.1.3: | |
| 73 | ||
| 74 | * Fixed bug in Rev::Buffer read_from and write_to: now rb_sys_fail on failed | |
| 75 | reads/writes. | |
| 76 | ||
| 77 | * Change Rev::Buffer memory pools to purge on a periodic interval, rather than | |
| 78 | whenever the GC marks the object. | |
| 79 | ||
| 80 | * Fix bug in tracking the active watcher count. Factor shared watcher behavior | |
| 81 | from rev_watcher.h to rev_watcher.c. | |
| 82 | ||
| 83 | 0.1.2: | |
| 84 | ||
| 85 | * Commit initial specs | |
| 86 | ||
| 87 | * Improve RDoc for the library | |
| 88 | ||
| 89 | * Eliminate "zero copy" writes as they bypass the event loop | |
| 90 | ||
| 91 | * Added Rev::Buffer C extension to provide high speed buffered writes | |
| 92 | ||
| 93 | * Implement Rev::TCPSocket#peeraddr to improve compatibility with Ruby sockets | |
| 94 | ||
| 95 | * Added Rev::Listener.close for clean shutdown of a listener | |
| 96 | ||
| 97 | * Rev::Loop.default used to call ev_loop_default() (in C). However, this | |
| 98 | registers signal handlers which conflict with Ruby's own. Now the behavior | |
| 99 | has been changed to return a thread-local singleton of Rev::Loop. | |
| 100 | ||
| 101 | * Creating a new Rev::TCPListener will disable reverse lookups in BasicSocket | |
| 102 | ||
| 103 | * Made backlog for Rev::TCPListener user-definable | |
| 104 | ||
| 105 | * Rev::TCPSocket now implements an on_resolve_failed callback for failed DNS | |
| 106 | resolution. By default it's aliased to on_connect_failed. | |
| 107 | ||
| 108 | * Changed event_callbacks to use instance_exec rather than passing the | |
| 109 | watcher object as an argument. Documented use of defining an event | |
| 110 | callback as a block | |
| 111 | ||
| 112 | * Subsecond precision for Rev::TimerWatchers | |
| 113 | ||
| 114 | 0.1.1: | |
| 115 | ||
| 116 | * Added Rev::HttpClient, an asynchronous HTTP/1.1 client written on top of | |
| 117 | the Rev::TCPSocket class | |
| 118 | ||
| 119 | * Imported HTTP response parser from the RFuzz project | |
| 120 | ||
| 121 | * Added exception handling for Errno::ECONNRESET and Errno::EAGAIN | |
| 122 | ||
| 123 | * Fixed bugs in buffered writer which resulted in exceptions if all data | |
| 124 | couldn't be written with a nonblocking write. | |
| 125 | ||
| 126 | 0.1.0: | |
| 127 | ||
| 128 | * Initial public release |
| ... | ...@@ -1,5 +0,0 @@ | |
| 1 | how to run it from an svn copy: | |
| 2 | run | |
| 3 | rake # same as rake default | |
| 4 | and then | |
| 5 | require 'rev' from the lib directory should work |