em-ruby-sockets 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|