Class: EventMachine::FileStreamer
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
self,
Deferrable
|
|
Inherits: | Object |
Defined in: | lib/em/streamer.rb |
Overview
Streams a file over a given connection. Streaming begins once the object is instantiated. Typically FileStreamer instances are not reused.
Streaming uses buffering for files larger than 16K and uses so-called fast file reader (a C++ extension) if available (it is part of eventmachine gem itself).
Constant Summary
-
BackpressureLevel =
Wait until next tick to send more data when 50k is still in the outgoing buffer
50000
-
ChunkSize =
Send 16k chunks at a time
16384
-
MappingThreshold =
Use mapped streamer for files bigger than 16k
16384
Deferrable
- Included
Class Method Summary
Instance Method Summary
-
#stream_one_chunk
Internal use only
Internal use only
Used internally to stream one chunk at a time over multiple reactor ticks.
-
#ensure_mapping_extension_is_present
private
Internal use only
Internal use only
We use an outboard extension class to get memory-mapped files.
- #stream_with_mapping(filename) private Internal use only Internal use only
- #stream_without_mapping(filename) private Internal use only Internal use only
Deferrable
- Included
#callback | Specify a block to be executed if and when the |
#cancel_callback | Cancels an outstanding callback to &block if any. |
#cancel_errback | Cancels an outstanding errback to &block if any. |
#cancel_timeout | Cancels an outstanding timeout if any. |
#errback | Specify a block to be executed if and when the |
#fail | Sugar for set_deferred_status(:failed, ...). |
#set_deferred_failure | Alias for Deferrable#fail. |
#set_deferred_status | Sets the "disposition" (status) of the |
#set_deferred_success | Alias for Deferrable#succeed. |
#succeed | Sugar for set_deferred_status(:succeeded, ...). |
#timeout | Setting a timeout on a |
Constructor Details
.new(connection, filename, args = {}) ⇒ FileStreamer
# File 'lib/em/streamer.rb', line 36
def initialize connection, filename, args = {} @connection = connection @http_chunks = args[:http_chunks] if File.exist?(filename) @size = File.size(filename) if @size <= MappingThreshold stream_without_mapping filename else stream_with_mapping filename end else fail "file not found" end end
Instance Method Details
#ensure_mapping_extension_is_present (private)
We use an outboard extension class to get memory-mapped files. It's outboard to avoid polluting the core distro, but that means there's a "hidden" dependency on it. The first time we get here in any run, try to load up the dependency extension. User code will see a LoadError if it's not available, but code that doesn't require mapped files will work fine without it. This is a somewhat difficult compromise between usability and proper modularization.
# File 'lib/em/streamer.rb', line 112
def ensure_mapping_extension_is_present @@fastfilereader ||= (require 'fastfilereaderext') end
#stream_one_chunk
Used internally to stream one chunk at a time over multiple reactor ticks
# File 'lib/em/streamer.rb', line 77
def stream_one_chunk loop { if @position < @size if @connection.get_outbound_data_size > BackpressureLevel EventMachine::next_tick {stream_one_chunk} break else len = @size - @position len = ChunkSize if (len > ChunkSize) @connection.send_data( "#{len.to_s(16)}\r\n" ) if @http_chunks @connection.send_data( @mapping.get_chunk( @position, len )) @connection.send_data("\r\n") if @http_chunks @position += len end else @connection.send_data "0\r\n\r\n" if @http_chunks @mapping.close succeed break end } end
#stream_with_mapping(filename) (private)
# File 'lib/em/streamer.rb', line 66
def stream_with_mapping filename ensure_mapping_extension_is_present @position = 0 @mapping = EventMachine::FastFileReader::Mapper.new filename stream_one_chunk end
#stream_without_mapping(filename) (private)
# File 'lib/em/streamer.rb', line 53
def stream_without_mapping filename if @http_chunks @connection.send_data "#{@size.to_s(16)}\r\n" @connection.send_file_data filename @connection.send_data "\r\n0\r\n\r\n" else @connection.send_file_data filename end succeed end