fastdfs-client 1.4.4 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/README.md +38 -15
- data/fastdfs-client.gemspec +7 -1
- data/lib/fastdfs-client.rb +3 -2
- data/lib/fastdfs-client/client_proxy.rb +23 -13
- data/lib/fastdfs-client/delegation.rb +24 -0
- data/lib/fastdfs-client/socket.rb +14 -9
- data/lib/fastdfs-client/storage.rb +13 -9
- data/lib/fastdfs-client/tracker.rb +61 -9
- data/lib/fastdfs-client/version.rb +6 -1
- data/spec/delegation_spec.rb +56 -0
- data/spec/mock_tcp_socket.rb +32 -21
- data/spec/spec_helper.rb +10 -2
- data/spec/storage_spec.rb +6 -7
- data/spec/test_config.rb +2 -1
- data/spec/tracker_spec.rb +56 -21
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba4443192b50ffc2e07f6173e31d58ec42b33531
|
4
|
+
data.tar.gz: 53f3b35f8742cbfebfdd1092938f53714ef834c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03f0b6d523e8596f9c455fea0517897201b23755d7ab7ab871e0c98328820db4366f72fc73e3a732047496421f6f7bd89ef45317109846451289a7292532bed1
|
7
|
+
data.tar.gz: 0eb796a19af1869c3b17785f16474ef521139fa35018f348cb6f7a3c0d5a07484899a2ee03dd53d4b64566356b6645f3e210cdc55ec5a0a29c6c52e76eeedf20
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -17,26 +17,49 @@ fastdfs client for ruby
|
|
17
17
|
#
|
18
18
|
|
19
19
|
|
20
|
-
tracker = Fastdfs::Client::Tracker.new("192.168.1.1", "22122")
|
20
|
+
tracker = Fastdfs::Client::Tracker.new(trackers: {host: "192.168.1.1", port: "22122"})
|
21
|
+
|
22
|
+
# multiple trackers server
|
23
|
+
# trackers: [
|
24
|
+
# {host: "192.168.1.1", port: "22122"},
|
25
|
+
# {host: "192.168.1.2", port: "22122"}
|
26
|
+
# ]
|
27
|
+
|
28
|
+
# socket connection KEEPALIVE
|
29
|
+
tracker.pipeline do |s|
|
30
|
+
files.each do |file|
|
31
|
+
s.upload(s)
|
32
|
+
end
|
33
|
+
end
|
21
34
|
|
22
|
-
@
|
35
|
+
# @file class includes [File, Tempfile, ActionDispatch::Http::UploadedFile]
|
36
|
+
@tracker.upload(@file)
|
37
|
+
#result: {group_name: "group1", path: "m1/xfsd/fds.jpg"}
|
23
38
|
|
24
|
-
|
39
|
+
@tracker.delete(path, group_name)
|
25
40
|
|
26
|
-
|
27
|
-
|
28
|
-
#result: {group_name: "group1", path: "m1/xfsd/fds.jpg"}
|
41
|
+
# flag params [cover, merge]
|
42
|
+
@tracker.set_metadata(path, group_name, {author: "kaka", width: "300"}, flag)
|
29
43
|
|
30
|
-
|
44
|
+
@tracker.get_metadata(path, group_name)
|
45
|
+
#result: {author: "kaka", width: "300"}
|
31
46
|
|
32
|
-
|
33
|
-
|
47
|
+
@tracker.download(path, group_name)
|
48
|
+
#result: #<Tempfile:/var/folders/m7/bt2j0rk54x555t44dpn4b7bm0000gn/T/test.jpg20160416-43738-1560vq3>
|
34
49
|
|
35
|
-
@storage.get_metadata(path, group_name)
|
36
|
-
#result: {author: "kaka", width: "300"}
|
37
50
|
|
38
|
-
|
39
|
-
|
40
|
-
|
51
|
+
# Make compatible 1.x version
|
52
|
+
|
53
|
+
@storage = tracker.get_storage
|
54
|
+
|
55
|
+
@storage.upload ...
|
56
|
+
@storage.delete ...
|
57
|
+
@storage.set_metadata ...
|
58
|
+
@storage.get_metadata ...
|
59
|
+
@storage.download ...
|
60
|
+
|
61
|
+
```
|
62
|
+
|
63
|
+
### License
|
41
64
|
|
42
|
-
|
65
|
+
[MIT License](https://opensource.org/licenses/MIT)
|
data/fastdfs-client.gemspec
CHANGED
@@ -21,6 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.add_development_dependency "bundler", "~> 1.6"
|
23
23
|
spec.add_development_dependency "rspec", "~> 3.4"
|
24
|
-
spec.add_development_dependency "debugger", "~> 1.6"
|
25
24
|
|
25
|
+
if RUBY_VERSION.start_with?('2.2')
|
26
|
+
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
27
|
+
spec.add_development_dependency "byebug", "~> 9.1.0"
|
28
|
+
else
|
29
|
+
# Call 'debugger' anywhere in the code to stop execution and get a debugger console
|
30
|
+
spec.add_development_dependency "debugger", "~> 1.6"
|
31
|
+
end
|
26
32
|
end
|
data/lib/fastdfs-client.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require 'fastdfs-client/version'
|
1
2
|
require "fastdfs-client/extend_core"
|
3
|
+
require 'fastdfs-client/delegation'
|
2
4
|
require 'fastdfs-client/socket'
|
3
5
|
require 'fastdfs-client/client_proxy'
|
4
6
|
require 'fastdfs-client/cmd'
|
5
7
|
require 'fastdfs-client/proto_common'
|
6
8
|
require 'fastdfs-client/utils'
|
7
|
-
require "fastdfs-client/tracker"
|
8
|
-
|
9
|
+
require "fastdfs-client/tracker"
|
@@ -6,34 +6,44 @@ module Fastdfs
|
|
6
6
|
class ClientProxy
|
7
7
|
include MonitorMixin
|
8
8
|
|
9
|
-
attr_accessor :host, :port, :socket
|
9
|
+
attr_accessor :host, :port, :socket, :alive
|
10
10
|
|
11
11
|
def initialize(host, port, options = {})
|
12
12
|
super()
|
13
13
|
options ||= {}
|
14
|
-
@host = host
|
15
|
-
@
|
14
|
+
@host, @port = host, port
|
15
|
+
@alive = options.delete(:alive) || false
|
16
16
|
|
17
|
-
@socket = Socket.new(host, port, options
|
17
|
+
@socket = Socket.new(host, port, options)
|
18
18
|
end
|
19
19
|
|
20
20
|
def dispose(cmd, header = [], content = [], &block)
|
21
21
|
synchronize do
|
22
22
|
@socket.connection do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@socket.write(cmd,
|
23
|
+
begin
|
24
|
+
contents = Array(content)
|
25
|
+
body_len = contents.map{|c| c.bytes.size }.inject(header.length){|sum, x| sum + x }
|
26
|
+
full_header = ProtoCommon.header_bytes(cmd, body_len).concat(header)
|
27
|
+
@socket.socket.reload_data if Fastdfs::Client.mock_test && @socket.socket.respond_to?(:reload_data)
|
28
|
+
@socket.write(cmd, full_header)
|
29
|
+
contents.each do |c|
|
30
|
+
@socket.write(cmd, c)
|
31
|
+
end
|
32
|
+
@socket.receive &block
|
33
|
+
rescue Exception => e
|
34
|
+
close
|
35
|
+
@socket.response_obj.update(status: false, err_msg: e.message)
|
29
36
|
end
|
30
|
-
|
31
|
-
end
|
37
|
+
|
38
|
+
end
|
32
39
|
end
|
33
40
|
ensure
|
41
|
+
close unless @alive
|
42
|
+
end
|
43
|
+
|
44
|
+
def close
|
34
45
|
@socket.close
|
35
46
|
end
|
36
47
|
end
|
37
|
-
|
38
48
|
end
|
39
49
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Fastdfs
|
2
|
+
module Client
|
3
|
+
|
4
|
+
module Delegation
|
5
|
+
module ClassMethods
|
6
|
+
|
7
|
+
def delegate(*methods, to:)
|
8
|
+
methods.each do |m|
|
9
|
+
class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
10
|
+
def #{m}(*args, &block)
|
11
|
+
#{to}.#{m}(*args, &block)
|
12
|
+
end
|
13
|
+
EVAL
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.included(receiver)
|
19
|
+
receiver.extend ClassMethods
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -9,12 +9,12 @@ module Fastdfs
|
|
9
9
|
class Socket
|
10
10
|
attr_accessor :socket, :host, :port
|
11
11
|
|
12
|
-
def initialize(host, port, options
|
12
|
+
def initialize(host, port, options)
|
13
13
|
@host, @port = host, port
|
14
14
|
@header_len = ProtoCommon::HEAD_LEN
|
15
15
|
@options = options || {}
|
16
|
-
@connection_timeout = @options[:connection_timeout]
|
17
|
-
@recv_timeout = @options[:recv_timeout]
|
16
|
+
@connection_timeout = @options[:connection_timeout]
|
17
|
+
@recv_timeout = @options[:recv_timeout]
|
18
18
|
end
|
19
19
|
|
20
20
|
def write(*args)
|
@@ -39,7 +39,7 @@ module Fastdfs
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def connected
|
42
|
-
!@socket.closed?
|
42
|
+
@socket.nil? ? false : !@socket.closed?
|
43
43
|
end
|
44
44
|
|
45
45
|
def receive(&block)
|
@@ -55,13 +55,18 @@ module Fastdfs
|
|
55
55
|
res_header
|
56
56
|
end
|
57
57
|
|
58
|
+
def response_obj
|
59
|
+
Hash[status: true, err_msg: nil, result: nil]
|
60
|
+
end
|
61
|
+
|
58
62
|
private
|
59
63
|
def parseHeader
|
60
|
-
|
61
|
-
err_msg = "recv package size #{@header} is not equal #{@header_len}, cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header.length == @header_len || err_msg
|
62
|
-
err_msg = "recv cmd: #{@header[8]} is not correct, expect recv code: #{CMD::RESP_CODE}, cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header[8] == CMD::RESP_CODE || err_msg
|
63
|
-
err_msg = "recv erron #{@header[9]}, 0 is correct cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header[9] == 0 || err_msg
|
64
|
-
|
64
|
+
obj = response_obj
|
65
|
+
obj[:err_msg] = "recv package size #{@header} is not equal #{@header_len}, cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header.length == @header_len || obj[:err_msg]
|
66
|
+
obj[:err_msg] = "recv cmd: #{@header[8]} is not correct, expect recv code: #{CMD::RESP_CODE}, cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header[8] == CMD::RESP_CODE || obj[:err_msg]
|
67
|
+
obj[:err_msg] = "recv erron #{@header[9]}, 0 is correct cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header[9] == 0 || obj[:err_msg]
|
68
|
+
obj[:status] = obj[:err_msg].nil?
|
69
|
+
obj
|
65
70
|
end
|
66
71
|
|
67
72
|
def timeout_recv
|
@@ -4,25 +4,29 @@ module Fastdfs
|
|
4
4
|
module Client
|
5
5
|
|
6
6
|
class Storage
|
7
|
-
attr_accessor :proxy, :
|
7
|
+
attr_accessor :proxy, :socket, :store_path
|
8
8
|
|
9
9
|
def initialize(host, port, store_path = nil, options = {})
|
10
|
-
@
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
@store_path = 0
|
11
|
+
options = if store_path.is_a?(Hash)
|
12
|
+
store_path
|
13
|
+
else
|
14
|
+
@store_path = store_path
|
15
|
+
options
|
16
|
+
end
|
17
|
+
|
18
|
+
@proxy = ClientProxy.new(host, port, options)
|
14
19
|
@socket = @proxy.socket
|
15
|
-
@store_path = store_path || 0
|
16
20
|
end
|
17
21
|
|
18
22
|
def upload(_file, options = {})
|
19
23
|
file, ext_name_bytes = convert_file_info(_file)
|
20
24
|
size_byte = [@store_path].concat(file.size.to_eight_buffer).full_fill(0, file_size_len)
|
21
|
-
content_len = file_size_len + extname_len + file.size
|
22
25
|
|
23
|
-
|
26
|
+
byte = size_byte + ext_name_bytes
|
27
|
+
|
28
|
+
@proxy.dispose(CMD::UPLOAD_FILE, byte , IO.read(file)) do |body|
|
24
29
|
group_name_max_len = ProtoCommon::GROUP_NAME_MAX_LEN
|
25
|
-
|
26
30
|
res = {group_name: body[0...group_name_max_len].strip, path: body[group_name_max_len..-1]}
|
27
31
|
_set_metadata(res[:path], res[:group_name], options) unless options.blank?
|
28
32
|
res
|
@@ -5,23 +5,75 @@ module Fastdfs
|
|
5
5
|
|
6
6
|
class Tracker
|
7
7
|
|
8
|
-
|
8
|
+
include Delegation
|
9
|
+
|
10
|
+
attr_accessor :options
|
11
|
+
|
12
|
+
delegate :upload, :delete, :get_metadata, :set_metadata, :download, to: :get_storage
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@options = default_options_merge(options)
|
16
|
+
@proxies = @options[:trackers].map do |tracker|
|
17
|
+
opt = tracker.fs_symbolize_keys
|
18
|
+
ClientProxy.new(opt[:host], opt[:port], extract_proxy_options.merge(alive: true))
|
19
|
+
end
|
9
20
|
|
10
|
-
def initialize(host, port, options = {})
|
11
|
-
@options = options
|
12
|
-
@proxy = ClientProxy.new(host, port, @options[:socket])
|
13
|
-
@socket = @proxy.socket
|
14
21
|
end
|
15
22
|
|
16
|
-
def get_storage
|
17
|
-
res =
|
23
|
+
def get_storage(alive = false)
|
24
|
+
res = proxy.dispose(CMD::STORE_WITHOUT_GROUP_ONE) do |body|
|
18
25
|
storage_ip = body[ProtoCommon::IPADDR].strip
|
19
26
|
storage_port = body[ProtoCommon::PORT].unpack("C*").to_pack_long
|
20
27
|
store_path = body[ProtoCommon::TRACKER_BODY_LEN-1].unpack("C*")[0]
|
21
28
|
|
22
|
-
Storage.new(storage_ip, storage_port, store_path,
|
29
|
+
Storage.new(storage_ip, storage_port, store_path, extract_proxy_options.merge(alive: alive))
|
23
30
|
end
|
24
|
-
res[:
|
31
|
+
raise res[:err_msg] unless res[:status]
|
32
|
+
res[:result]
|
33
|
+
end
|
34
|
+
|
35
|
+
def pipeline
|
36
|
+
storage = get_storage(true)
|
37
|
+
yield storage
|
38
|
+
storage
|
39
|
+
ensure
|
40
|
+
storage.proxy.close
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def default_options_merge(options = {})
|
45
|
+
opts = default_options.merge(options)
|
46
|
+
tracker = {host: opts.delete(:host), port: opts.delete(:port)}
|
47
|
+
if !tracker[:host].nil?
|
48
|
+
opts[:trackers] = [tracker]
|
49
|
+
elsif opts[:trackers].is_a?(Hash)
|
50
|
+
opts[:trackers] = [opts[:trackers]]
|
51
|
+
end
|
52
|
+
opts
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_options
|
56
|
+
{
|
57
|
+
host: nil,
|
58
|
+
port: nil,
|
59
|
+
trackers: [
|
60
|
+
{host: "127.0.0.1", port: "22122"}
|
61
|
+
],
|
62
|
+
connection_timeout: 3,
|
63
|
+
recv_timeout: 20
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def extract_proxy_options
|
68
|
+
keys = [:connection_timeout, :recv_timeout]
|
69
|
+
@options.select{|key| keys.include?(key) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def proxy
|
73
|
+
@proxy_index ||= -1
|
74
|
+
@proxy_index += 1
|
75
|
+
@proxy_index = 0 if @proxy_index >= @proxies.length
|
76
|
+
@proxies[@proxy_index]
|
25
77
|
end
|
26
78
|
end
|
27
79
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
BLOG_URI = "http://168ta.com"
|
4
|
+
|
5
|
+
class Profile
|
6
|
+
|
7
|
+
def messages(limit, offset); [limit, offset] end
|
8
|
+
|
9
|
+
def blog; BLOG_URI end
|
10
|
+
|
11
|
+
def change_email; yield end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
class User
|
16
|
+
include Fastdfs::Client::Delegation
|
17
|
+
|
18
|
+
delegate :messages, :blog, :change_email, to: :profile
|
19
|
+
|
20
|
+
def profile
|
21
|
+
Profile.new
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Fastdfs::Client::Delegation do
|
26
|
+
|
27
|
+
let(:user){ User.new }
|
28
|
+
|
29
|
+
it "user should be three methods" do
|
30
|
+
expect(user.respond_to?(:messages)).to be_truthy
|
31
|
+
expect(user.respond_to?(:blog)).to be_truthy
|
32
|
+
expect(user.respond_to?(:change_email)).to be_truthy
|
33
|
+
expect(user.respond_to?(:title)).to be_falsey
|
34
|
+
end
|
35
|
+
|
36
|
+
it "user method receive argments" do
|
37
|
+
expect(user.messages(25, 0)).to eq([25, 0])
|
38
|
+
expect(user.blog).to eq(BLOG_URI)
|
39
|
+
expect(user.change_email{ "hello" }).to eq("hello")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "argments of the execption" do
|
43
|
+
begin
|
44
|
+
user.messages(25)
|
45
|
+
rescue Exception => e
|
46
|
+
expect(e).to be_a_kind_of(ArgumentError)
|
47
|
+
end
|
48
|
+
|
49
|
+
begin
|
50
|
+
user.change_email
|
51
|
+
rescue Exception => e
|
52
|
+
expect(e).to be_a_kind_of(LocalJumpError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/spec/mock_tcp_socket.rb
CHANGED
@@ -5,18 +5,17 @@ class MockTCPSocket
|
|
5
5
|
attr_accessor :host, :port, :cmd, :recv_offset, :connect_state
|
6
6
|
|
7
7
|
def initialize(host, port)
|
8
|
-
@host = host
|
9
|
-
|
10
|
-
@recv_offset = 0
|
11
|
-
@connect_state = true
|
12
|
-
@cmd = nil
|
13
|
-
@content = []
|
14
|
-
@header = []
|
8
|
+
@host, @port = host, port
|
9
|
+
reload_data
|
15
10
|
end
|
16
11
|
|
17
12
|
def connection
|
18
|
-
|
19
|
-
|
13
|
+
reload_data
|
14
|
+
end
|
15
|
+
|
16
|
+
def reload_data
|
17
|
+
init_options
|
18
|
+
init_data
|
20
19
|
end
|
21
20
|
|
22
21
|
def write(*args)
|
@@ -51,69 +50,81 @@ class MockTCPSocket
|
|
51
50
|
end
|
52
51
|
|
53
52
|
def close
|
54
|
-
|
53
|
+
init_options
|
55
54
|
@connect_state = false
|
56
|
-
@cmd = nil
|
57
55
|
end
|
58
56
|
|
59
57
|
def closed?
|
60
|
-
|
58
|
+
!@connect_state
|
61
59
|
end
|
62
60
|
|
63
61
|
private
|
64
62
|
def gate_tracker(len)
|
65
|
-
header =
|
63
|
+
header = init_header_bytes
|
66
64
|
header[7] = ProtoCommon::TRACKER_BODY_LEN
|
67
65
|
|
68
66
|
group_name = Utils.array_merge([].fill(0, 0...16), TestConfig::GROUP_NAME.bytes)
|
69
67
|
ip = Utils.array_merge([].fill(0, 0...15), TestConfig::STORAGE_IP.bytes)
|
70
68
|
port = TestConfig::STORAGE_PORT.to_i.to_eight_buffer
|
71
69
|
store_path = Array(TestConfig::STORE_PATH)
|
72
|
-
|
73
70
|
(header+group_name+ip+port+store_path)[@recv_offset...@recv_offset+len].pack("C*")
|
74
71
|
end
|
75
72
|
|
76
73
|
def upload_file(len)
|
77
|
-
header =
|
74
|
+
header = init_header_bytes
|
78
75
|
group_name = Utils.array_merge([].fill(0, 0...16), TestConfig::GROUP_NAME.bytes)
|
79
76
|
path = path_replace_extname
|
80
77
|
file_path_bytes = path.bytes
|
81
78
|
res = (group_name + file_path_bytes)
|
82
79
|
header[7] = (header + res).length
|
83
|
-
res = (header + res)
|
84
80
|
|
81
|
+
res = (header + res)
|
85
82
|
res[@recv_offset...@recv_offset+len].pack("C*")
|
86
83
|
end
|
87
84
|
|
88
85
|
def delete_file(len)
|
89
|
-
header =
|
86
|
+
header = init_header_bytes
|
90
87
|
header.pack("C*")
|
91
88
|
end
|
92
89
|
|
93
90
|
def get_metadata(len)
|
94
|
-
header =
|
91
|
+
header = init_header_bytes
|
95
92
|
body = TestConfig::METADATA.map{|a| a.join(ProtoCommon::FILE_SEPERATOR)}.join(ProtoCommon::RECORD_SEPERATOR).bytes
|
96
93
|
header[7] = body.length
|
97
94
|
(header + body)[@recv_offset...@recv_offset+len].pack("C*")
|
98
95
|
end
|
99
96
|
|
100
97
|
def set_metadata(len)
|
101
|
-
header =
|
98
|
+
header = init_header_bytes
|
102
99
|
header.pack("C*")
|
103
100
|
end
|
104
101
|
|
105
102
|
def download_file(len)
|
106
|
-
header =
|
103
|
+
header = init_header_bytes
|
107
104
|
body = IO.read(TestConfig::FILE).bytes
|
108
105
|
header[7] = body.length
|
109
106
|
(header + body)[@recv_offset...@recv_offset+len].pack("C*")
|
110
107
|
end
|
111
108
|
|
112
|
-
|
109
|
+
def init_options
|
110
|
+
@recv_offset = 0
|
111
|
+
@connect_state = true
|
112
|
+
@cmd = nil
|
113
|
+
end
|
114
|
+
|
115
|
+
def init_data
|
116
|
+
@content = []
|
117
|
+
@header = []
|
118
|
+
end
|
119
|
+
|
113
120
|
def path_replace_extname
|
114
121
|
path = TestConfig::FILE_PATH
|
115
122
|
extname = File.extname(path)
|
116
123
|
path.gsub!(extname, ".#{@header[19..-1].reject{|i| i.zero? }.pack('C*')}")
|
117
124
|
path
|
118
125
|
end
|
126
|
+
|
127
|
+
def init_header_bytes
|
128
|
+
ProtoCommon.header_bytes(CMD::RESP_CODE, 0)
|
129
|
+
end
|
119
130
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
if RUBY_VERSION.start_with?('2')
|
2
|
+
require 'byebug'
|
3
|
+
else
|
4
|
+
require 'debugger'
|
5
|
+
end
|
2
6
|
require 'rspec'
|
3
7
|
require 'rspec/core'
|
4
8
|
require 'rspec/mocks'
|
@@ -7,6 +11,10 @@ require File.expand_path('../../lib/fastdfs-client', __FILE__)
|
|
7
11
|
require File.expand_path('../test_config', __FILE__)
|
8
12
|
require File.expand_path('../mock_tcp_socket', __FILE__)
|
9
13
|
|
14
|
+
Fastdfs::Client.class_eval do
|
15
|
+
def self.mock_test; true end
|
16
|
+
end
|
17
|
+
|
10
18
|
FC = Fastdfs::Client
|
11
19
|
|
12
20
|
RSpec.configure do |config|
|
@@ -14,7 +22,7 @@ RSpec.configure do |config|
|
|
14
22
|
TCPSocket.stub(:new) do |h, p|
|
15
23
|
MockTCPSocket.new(h, p)
|
16
24
|
end
|
17
|
-
end
|
25
|
+
end
|
18
26
|
config.mock_with :rspec do |c|
|
19
27
|
c.syntax = [:should, :expect]
|
20
28
|
end
|
data/spec/storage_spec.rb
CHANGED
@@ -2,21 +2,20 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Fastdfs::Client::Storage do
|
4
4
|
|
5
|
-
let(:
|
6
|
-
let(:
|
5
|
+
let(:server){ {host: "192.168.1.168", port: "22122"} }
|
6
|
+
let(:tracker){ FC::Tracker.new(trackers: server) }
|
7
7
|
|
8
|
-
let(:tracker){ FC::Tracker.new(host, port) }
|
9
8
|
let(:storage){ tracker.get_storage }
|
10
9
|
let(:tempfile) do
|
11
|
-
file = Tempfile.new([
|
10
|
+
file = Tempfile.new(["/tmp", "1.txt"])
|
12
11
|
file.write("testtest")
|
13
12
|
file.close
|
14
13
|
file
|
15
14
|
end
|
16
15
|
|
17
16
|
it "initialize the server" do
|
18
|
-
expect(FC::Socket).to receive(:new).with(host, port,
|
19
|
-
FC::Storage.new(host, port)
|
17
|
+
expect(FC::Socket).to receive(:new).with(server[:host], server[:port], {})
|
18
|
+
FC::Storage.new(server[:host], server[:port])
|
20
19
|
end
|
21
20
|
|
22
21
|
it "should have access to the storage connection" do
|
@@ -79,7 +78,7 @@ describe Fastdfs::Client::Storage do
|
|
79
78
|
expect(storage.set_metadata(TestConfig::FILE_PATH, TestConfig::GROUP_NAME, TestConfig::METADATA)).to be_truthy
|
80
79
|
end
|
81
80
|
|
82
|
-
it "download the file to the local" do
|
81
|
+
it "download the file to the local" do
|
83
82
|
res = storage.download(TestConfig::FILE_PATH, TestConfig::GROUP_NAME)
|
84
83
|
expect(res[:status]).to be_truthy
|
85
84
|
expect(res[:result]).to be_an_instance_of(Tempfile)
|
data/spec/test_config.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module TestConfig
|
2
|
-
STORAGE_IP = "192.168.
|
2
|
+
STORAGE_IP = "192.168.1.168"
|
3
3
|
STORAGE_PORT = "23000"
|
4
4
|
STORE_PATH = 0
|
5
5
|
GROUP_NAME = "group1"
|
6
6
|
FILE_PATH = "M00/04/47/wKgIF1cHcQyAeAF7AAACVHeY6n8267.png"
|
7
|
+
SOCKET_DEFAULT_OPTION = {connection_timeout: 3, recv_timeout: 20}
|
7
8
|
|
8
9
|
METADATA = {
|
9
10
|
width: "800",
|
data/spec/tracker_spec.rb
CHANGED
@@ -1,21 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Fastdfs::Client::Tracker do
|
4
|
-
|
5
|
-
let(:
|
6
|
-
let(:port){ "22122" }
|
7
|
-
|
8
|
-
let(:tracker){ FC::Tracker.new(host, port) }
|
4
|
+
let(:server){ {host: "192.168.1.168", port: "22122"} }
|
5
|
+
let(:tracker){ FC::Tracker.new(trackers: server) }
|
9
6
|
|
10
7
|
it "initialize the server" do
|
11
|
-
expect(FC::Socket).to receive(:new).with(host, port,
|
12
|
-
FC::Tracker.new(
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should have access to the storage connection" do
|
16
|
-
expect(tracker.socket).to receive(:connection).and_return({})
|
17
|
-
expect(tracker.socket).to receive(:close)
|
18
|
-
tracker.get_storage
|
8
|
+
expect(FC::Socket).to receive(:new).with(server[:host], server[:port], TestConfig::SOCKET_DEFAULT_OPTION)
|
9
|
+
FC::Tracker.new(trackers: server)
|
19
10
|
end
|
20
11
|
|
21
12
|
it "should have access to the storage class" do
|
@@ -23,17 +14,20 @@ describe Fastdfs::Client::Tracker do
|
|
23
14
|
end
|
24
15
|
|
25
16
|
it "verify the server address and port" do
|
26
|
-
|
17
|
+
storage = tracker.get_storage
|
18
|
+
expect(storage.proxy.host).to eq(TestConfig::STORAGE_IP)
|
27
19
|
|
28
|
-
expect(
|
29
|
-
expect(
|
20
|
+
expect(storage.proxy.port.to_s).to eq(TestConfig::STORAGE_PORT)
|
21
|
+
expect(storage.store_path).to eq(TestConfig::STORE_PATH)
|
30
22
|
end
|
31
23
|
|
32
24
|
it "get to the server failed" do
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
25
|
+
if tracker.get_storage.socket.is_a?(MockTCPSocket)
|
26
|
+
result = FC::ProtoCommon.header_bytes(FC::CMD::RESP_CODE, 0, 22)
|
27
|
+
MockTCPSocket.any_instance.stub("recv").and_return(result.pack("C*"))
|
28
|
+
expect(tracker.get_storage).to be_a_kind_of(Hash)
|
29
|
+
expect(tracker.get_storage[:status]).to be_falsey
|
30
|
+
end
|
37
31
|
end
|
38
32
|
|
39
33
|
it "multi thread upload" do
|
@@ -48,7 +42,48 @@ describe Fastdfs::Client::Tracker do
|
|
48
42
|
end
|
49
43
|
end
|
50
44
|
|
51
|
-
items.map
|
45
|
+
items.map(&:join)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be storage methods" do
|
49
|
+
expect(tracker.respond_to?(:upload)).to be_truthy
|
50
|
+
expect(tracker.respond_to?(:delete)).to be_truthy
|
51
|
+
expect(tracker.respond_to?(:get_metadata)).to be_truthy
|
52
|
+
expect(tracker.respond_to?(:set_metadata)).to be_truthy
|
53
|
+
expect(tracker.respond_to?(:download)).to be_truthy
|
54
|
+
end
|
55
|
+
|
56
|
+
it "storage socket keepalive request" do
|
57
|
+
storage = tracker.pipeline do |storage|
|
58
|
+
res = storage.upload(File.open(File.expand_path("../page.png", __FILE__)))[:result]
|
59
|
+
expect(storage.socket.connected).to be_truthy
|
60
|
+
|
61
|
+
tmp = storage.set_metadata(res[:path], res[:group_name], TestConfig::METADATA)
|
62
|
+
expect(tmp[:status]).to be_truthy
|
63
|
+
expect(storage.socket.connected).to be_truthy
|
64
|
+
|
65
|
+
tmp = storage.get_metadata(res[:path], res[:group_name])
|
66
|
+
expect(tmp[:status]).to be_truthy
|
67
|
+
expect(storage.socket.connected).to be_truthy
|
68
|
+
|
69
|
+
tmp = storage.download(res[:path], res[:group_name])
|
70
|
+
expect(tmp[:status]).to be_truthy
|
71
|
+
expect(storage.socket.connected).to be_truthy
|
72
|
+
end
|
73
|
+
expect(storage.socket.connected).to be_falsey
|
52
74
|
end
|
53
75
|
|
76
|
+
it "multiple trackers server proxy" do
|
77
|
+
trackers = [server]
|
78
|
+
two_server = {host: "192.168.1.169", port: "22122"}
|
79
|
+
trackers << two_server
|
80
|
+
ts = FC::Tracker.new(trackers: trackers)
|
81
|
+
|
82
|
+
1.upto(6).each do |i|
|
83
|
+
proxy = ts.send(:proxy)
|
84
|
+
res = i % 2 == 0 ? two_server : server
|
85
|
+
expect({host: proxy.host, port: proxy.port}).to eq(res)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
54
89
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastdfs-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ka Ka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,19 +39,19 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.4'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: byebug
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 9.1.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 9.1.0
|
55
55
|
description: fastdfs upload file client for ruby
|
56
56
|
email:
|
57
57
|
- huxinghai1988@gmail.com
|
@@ -67,6 +67,7 @@ files:
|
|
67
67
|
- lib/fastdfs-client.rb
|
68
68
|
- lib/fastdfs-client/client_proxy.rb
|
69
69
|
- lib/fastdfs-client/cmd.rb
|
70
|
+
- lib/fastdfs-client/delegation.rb
|
70
71
|
- lib/fastdfs-client/extend_core.rb
|
71
72
|
- lib/fastdfs-client/proto_common.rb
|
72
73
|
- lib/fastdfs-client/socket.rb
|
@@ -75,6 +76,7 @@ files:
|
|
75
76
|
- lib/fastdfs-client/utils.rb
|
76
77
|
- lib/fastdfs-client/version.rb
|
77
78
|
- spec/.DS_Store
|
79
|
+
- spec/delegation_spec.rb
|
78
80
|
- spec/mock_tcp_socket.rb
|
79
81
|
- spec/page.png
|
80
82
|
- spec/spec_helper.rb
|
@@ -102,12 +104,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
104
|
version: '0'
|
103
105
|
requirements: []
|
104
106
|
rubyforge_project:
|
105
|
-
rubygems_version: 2.
|
107
|
+
rubygems_version: 2.4.6
|
106
108
|
signing_key:
|
107
109
|
specification_version: 4
|
108
110
|
summary: fastdfs upload file client for ruby
|
109
111
|
test_files:
|
110
112
|
- spec/.DS_Store
|
113
|
+
- spec/delegation_spec.rb
|
111
114
|
- spec/mock_tcp_socket.rb
|
112
115
|
- spec/page.png
|
113
116
|
- spec/spec_helper.rb
|
@@ -115,4 +118,3 @@ test_files:
|
|
115
118
|
- spec/test_config.rb
|
116
119
|
- spec/tracker_spec.rb
|
117
120
|
- spec/upload.rb
|
118
|
-
has_rdoc:
|