em-ruby-sockets 0.0.1 → 0.0.2
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/lib/em-ruby-sockets/file_streamer.rb +127 -0
- data/lib/em-ruby-sockets/version.rb +1 -1
- metadata +3 -2
@@ -0,0 +1,127 @@
|
|
1
|
+
module EventMachine::RubySockets
|
2
|
+
|
3
|
+
# Streams a file over a given TCP connection.
|
4
|
+
# It makes use of the fastfilereaderext.so Ruby extension.
|
5
|
+
#
|
6
|
+
# class MyFileStreamer < EM::RubySockets::TcpClient
|
7
|
+
# def post_init
|
8
|
+
# streamer = EM::RubySockets::FileStreamer.new(self, "/tmp/bigfile.tar.gz")
|
9
|
+
# streamer.callback {
|
10
|
+
# # file was sent successfully
|
11
|
+
# disconnect
|
12
|
+
# }
|
13
|
+
# streamer.errback {
|
14
|
+
# # file could not be sent
|
15
|
+
# disconnect
|
16
|
+
# }
|
17
|
+
# streamer.run
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
class FileStreamer
|
22
|
+
# Wait until next tick to send more data when 50k is still in the outgoing buffer.
|
23
|
+
BackpressureLevel = 50000
|
24
|
+
# Send 16k chunks at a time.
|
25
|
+
ChunkSize = 16384
|
26
|
+
|
27
|
+
# Parameters:
|
28
|
+
#
|
29
|
+
# - [connection] An EventMachine::RubySockets::TcpClient, EventMachine::RubySockets::TcpServer, EventMachine::RubySockets::TlsClient or EventMachine::RubySockets::TlsServer.
|
30
|
+
# - [filename] File path.
|
31
|
+
# - [args] A Hash with options.
|
32
|
+
#
|
33
|
+
# Valid options for _args_:
|
34
|
+
#
|
35
|
+
# - [http_chunks] Use HTTP 1.1 chunked-encoding.
|
36
|
+
#
|
37
|
+
def initialize connection, filename, args = {}
|
38
|
+
@connection = connection
|
39
|
+
@filename = filename
|
40
|
+
@http_chunks = args[:http_chunks]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set the success callback to be executed upon file transfer completion.
|
44
|
+
def callback &block
|
45
|
+
@on_success_block = block
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set the error callback (errback) to be executed if file transfer fails. The errback
|
49
|
+
# is called by passing a single argument which can be _:invalid_file_ or _:disconnected_.
|
50
|
+
def errback &block
|
51
|
+
@on_error_block = block
|
52
|
+
end
|
53
|
+
|
54
|
+
# Start sending the file. This method must be called after setting both the callback and
|
55
|
+
# errback blocks.
|
56
|
+
def run
|
57
|
+
unless ::File.readable?(@filename) and ::File.file?(@filename)
|
58
|
+
do_error :invalid_file
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
@size = ::File.size(@filename)
|
63
|
+
stream_with_mapping
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns a Float value indicating the file percentage trasferred at this moment.
|
68
|
+
def percentage_sent
|
69
|
+
@mapping ? (@position.to_f / @size)*100 : 0.0
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def do_success
|
76
|
+
@on_success_block && @on_success_block.call
|
77
|
+
end
|
78
|
+
|
79
|
+
def do_error cause
|
80
|
+
@on_error_block && @on_error_block.call(cause)
|
81
|
+
end
|
82
|
+
|
83
|
+
def stream_with_mapping
|
84
|
+
ensure_mapping_extension_is_present
|
85
|
+
|
86
|
+
@position = 0
|
87
|
+
@mapping = ::EM::FastFileReader::Mapper.new @filename
|
88
|
+
stream_one_chunk
|
89
|
+
end
|
90
|
+
|
91
|
+
# Used internally to stream one chunk at a time over multiple reactor ticks.
|
92
|
+
def stream_one_chunk
|
93
|
+
loop do
|
94
|
+
if @connection.error?
|
95
|
+
@mapping.close
|
96
|
+
do_error :disconnected
|
97
|
+
break
|
98
|
+
|
99
|
+
elsif @position < @size
|
100
|
+
if @connection.get_outbound_data_size > BackpressureLevel
|
101
|
+
::EM.next_tick { stream_one_chunk }
|
102
|
+
break
|
103
|
+
else
|
104
|
+
len = @size - @position
|
105
|
+
len = ChunkSize if (len > ChunkSize)
|
106
|
+
|
107
|
+
@connection.send_data "#{len.to_s(16)}\r\n" if @http_chunks
|
108
|
+
@connection.send_data @mapping.get_chunk(@position, len)
|
109
|
+
@connection.send_data "\r\n" if @http_chunks
|
110
|
+
|
111
|
+
@position += len
|
112
|
+
end
|
113
|
+
else
|
114
|
+
@connection.send_data "0\r\n\r\n" if @http_chunks
|
115
|
+
@mapping.close
|
116
|
+
do_success
|
117
|
+
break
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def ensure_mapping_extension_is_present
|
123
|
+
@@fastfilereader ||= (require "fastfilereaderext")
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "I\xC3\xB1aki Baz Castillo"
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/em-ruby-sockets/errors.rb
|
62
62
|
- lib/em-ruby-sockets/tcp_connection.rb
|
63
63
|
- lib/em-ruby-sockets/tcp_client.rb
|
64
|
+
- lib/em-ruby-sockets/file_streamer.rb
|
64
65
|
has_rdoc: true
|
65
66
|
homepage: https://github.com/ibc/em-ruby-sockets
|
66
67
|
licenses: []
|