fastdfs-client 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +38 -0
- data/README.md +21 -0
- data/fastdfs-client.gemspec +23 -0
- data/lib/fastdfs-client.rb +7 -0
- data/lib/fastdfs-client/cmd.rb +12 -0
- data/lib/fastdfs-client/extend_core.rb +14 -0
- data/lib/fastdfs-client/hook.rb +41 -0
- data/lib/fastdfs-client/proto_common.rb +24 -0
- data/lib/fastdfs-client/socket.rb +69 -0
- data/lib/fastdfs-client/storage.rb +71 -0
- data/lib/fastdfs-client/tracker.rb +35 -0
- data/lib/fastdfs-client/utils.rb +13 -0
- data/lib/fastdfs-client/version.rb +5 -0
- data/spec/mock_tcp_socket.rb +74 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/storage_spec.rb +40 -0
- data/spec/test_config.rb +12 -0
- data/spec/tracker_spec.rb +38 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 711de59fe7605cadbe4820f3f852e79860e5c1ab
|
4
|
+
data.tar.gz: cd68e14f5f1932d19045e5c3c31fa77e91d75472
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 673c80215e1b30fea0aae0f2b3b2471d6641027491f548365213915762cb092f8fec7d6643bbf3c7fc22501e534eb730f22e495e08253de45a4fda92cbe88374
|
7
|
+
data.tar.gz: 310349702c4c17c9316cae1a165c9f305a88f34445023a5f75139d26741a9642bdddcb5ca3176407211ec7e2f1c41c9cb7a83b384f838077dcd55b385be76a58
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
fastdfs-client (0.0.2)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://gems.ruby-china.org/
|
8
|
+
specs:
|
9
|
+
columnize (0.9.0)
|
10
|
+
debugger (1.6.8)
|
11
|
+
columnize (>= 0.3.1)
|
12
|
+
debugger-linecache (~> 1.2.0)
|
13
|
+
debugger-ruby_core_source (~> 1.3.5)
|
14
|
+
debugger-linecache (1.2.0)
|
15
|
+
debugger-ruby_core_source (1.3.8)
|
16
|
+
diff-lcs (1.2.5)
|
17
|
+
rspec (3.4.0)
|
18
|
+
rspec-core (~> 3.4.0)
|
19
|
+
rspec-expectations (~> 3.4.0)
|
20
|
+
rspec-mocks (~> 3.4.0)
|
21
|
+
rspec-core (3.4.4)
|
22
|
+
rspec-support (~> 3.4.0)
|
23
|
+
rspec-expectations (3.4.0)
|
24
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
25
|
+
rspec-support (~> 3.4.0)
|
26
|
+
rspec-mocks (3.4.1)
|
27
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
28
|
+
rspec-support (~> 3.4.0)
|
29
|
+
rspec-support (3.4.1)
|
30
|
+
|
31
|
+
PLATFORMS
|
32
|
+
ruby
|
33
|
+
|
34
|
+
DEPENDENCIES
|
35
|
+
bundler (~> 1.3)
|
36
|
+
debugger
|
37
|
+
fastdfs-client!
|
38
|
+
rspec
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# fastdfs-client-ruby
|
2
|
+
|
3
|
+
fastdfs client for ruby
|
4
|
+
|
5
|
+
### Install
|
6
|
+
|
7
|
+
#Gemfile
|
8
|
+
gem 'fastdfs-client', git: "git@github.com:huxinghai1988/fastdfs-client-ruby.git"
|
9
|
+
|
10
|
+
### Using
|
11
|
+
|
12
|
+
```RUBY
|
13
|
+
tracker = new Fastdfs::Client::Tracker("192.168.1.1", "22122")
|
14
|
+
|
15
|
+
@storage = tracker.get_storage
|
16
|
+
|
17
|
+
@storage.upload(@file)
|
18
|
+
|
19
|
+
#group_name + path
|
20
|
+
@storage.delete(path)
|
21
|
+
```
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'fastdfs-client/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "fastdfs-client"
|
9
|
+
spec.version = Fastdfs::Client::VERSION
|
10
|
+
spec.authors = ["Ka Ka"]
|
11
|
+
spec.email = ["huxinghai1988@gmail.com"]
|
12
|
+
spec.description = "fastdfs upload file client for ruby"
|
13
|
+
spec.summary = "fastdfs upload file client for ruby"
|
14
|
+
spec.homepage = "https://github.com/huxinghai1988/fastdfs-client-ruby.git"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Hook
|
2
|
+
def before(*meth_names, &callback)
|
3
|
+
meth_names.each{|meth_name| add_hook :before, meth_name, &callback }
|
4
|
+
end
|
5
|
+
|
6
|
+
def after(*meth_names, &callback)
|
7
|
+
meth_names.each{|meth_name| add_hook :after, meth_name, &callback }
|
8
|
+
end
|
9
|
+
|
10
|
+
def hooks
|
11
|
+
@hooks ||= Hash.new do |hash, method_name|
|
12
|
+
hash[method_name] = { before: [], after: [], hijacked: false }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_hook(where, meth_name, &callback)
|
17
|
+
hooks[meth_name][where] << callback
|
18
|
+
ensure_hijacked meth_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_added(meth_name)
|
22
|
+
ensure_hijacked meth_name if hooks.has_key? meth_name
|
23
|
+
end
|
24
|
+
|
25
|
+
def ensure_hijacked(meth_name)
|
26
|
+
return if hooks[meth_name][:hijacked] || !instance_methods.include?(meth_name)
|
27
|
+
meth = instance_method meth_name
|
28
|
+
_hooks = hooks
|
29
|
+
_hooks[meth_name][:hijacked] = true
|
30
|
+
define_method meth_name do |*args, &block|
|
31
|
+
_hooks[meth_name][:before].each do |callback|
|
32
|
+
self.instance_exec(&callback)
|
33
|
+
end
|
34
|
+
return_value = meth.bind(self).call *args, &block
|
35
|
+
_hooks[meth_name][:after].each do |callback|
|
36
|
+
self.instance_exec(&callback)
|
37
|
+
end
|
38
|
+
return_value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Fastdfs
|
2
|
+
module Client
|
3
|
+
|
4
|
+
module ProtoCommon
|
5
|
+
TRACKER_BODY_LEN = 40
|
6
|
+
|
7
|
+
IPADDR = 16...31
|
8
|
+
PORT = 31...-1
|
9
|
+
SIZE_LEN = 9
|
10
|
+
HEAD_LEN = 10
|
11
|
+
EXTNAME_LEN = 6
|
12
|
+
GROUP_NAME_MAX_LEN = 16
|
13
|
+
|
14
|
+
def self.header_bytes(cmd, hex_long, erron=0)
|
15
|
+
hex_bytes = Utils.number_to_Buffer(hex_long)
|
16
|
+
header = hex_bytes.fill(0, hex_bytes.length...HEAD_LEN)
|
17
|
+
header[8] = cmd
|
18
|
+
header[9] = erron
|
19
|
+
header
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'timeout'
|
3
|
+
require 'fastdfs-client/cmd'
|
4
|
+
|
5
|
+
|
6
|
+
module Fastdfs
|
7
|
+
module Client
|
8
|
+
|
9
|
+
class Socket
|
10
|
+
attr_accessor :header, :content, :header_len, :cmd, :socket, :host, :port
|
11
|
+
|
12
|
+
def initialize(host, port, options = {})
|
13
|
+
@host = host
|
14
|
+
@port = port
|
15
|
+
connection
|
16
|
+
@header_len = ProtoCommon::HEAD_LEN
|
17
|
+
@options = options || {}
|
18
|
+
@connection_timeout = @options[:connection_timeout] || 3
|
19
|
+
@recv_timeout = @options[:recv_timeout] || 3
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(*args)
|
23
|
+
@cmd = args.shift
|
24
|
+
pkg = args.shift
|
25
|
+
pkg = pkg.pack("C*") if pkg.is_a?(Array)
|
26
|
+
@socket.write pkg
|
27
|
+
end
|
28
|
+
|
29
|
+
def close
|
30
|
+
@socket.close if connected
|
31
|
+
end
|
32
|
+
|
33
|
+
def connection
|
34
|
+
if @socket.nil? || !connected
|
35
|
+
Timeout.timeout(@connection_timeout) do
|
36
|
+
@socket = TCPSocket.new(@host, @port)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def connected
|
42
|
+
!@socket.closed?
|
43
|
+
end
|
44
|
+
|
45
|
+
def receive
|
46
|
+
@content = nil
|
47
|
+
Timeout.timeout(@recv_timeout) do
|
48
|
+
@header = @socket.recv(@header_len).unpack("C*")
|
49
|
+
end
|
50
|
+
res_header = parseHeader
|
51
|
+
if res_header[:body_length] > 0
|
52
|
+
Timeout.timeout(@recv_timeout) do
|
53
|
+
@content = @socket.recv(@header.to_pack_long)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
yield @content if block_given?
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def parseHeader
|
61
|
+
raise "recv package size #{@header} != #{@header_len}, cmd: #{@cmd}" unless @header.length == @header_len
|
62
|
+
raise "recv cmd: #{@header[8]} is not correct, expect cmd: #{CMD::RESP_CODE}, cmd: #{@cmd}" unless @header[8] == CMD::RESP_CODE
|
63
|
+
raise "recv erron #{@header[9]} 0 is correct, cmd: #{@cmd}" unless @header[9] == 0
|
64
|
+
{status: true, body_length: @header[0...8].to_pack_long}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Fastdfs
|
4
|
+
module Client
|
5
|
+
|
6
|
+
class Storage
|
7
|
+
extend Hook
|
8
|
+
|
9
|
+
before(:upload, :delete){ @socket.connection }
|
10
|
+
after(:upload, :delete){ @socket.close }
|
11
|
+
|
12
|
+
attr_accessor :host, :port, :group_name, :store_path, :socket, :options
|
13
|
+
|
14
|
+
def initialize(host, port, store_path = nil, options = {})
|
15
|
+
@host = host
|
16
|
+
@port = port
|
17
|
+
@options = options || {}
|
18
|
+
@options = store_path if store_path.is_a?(Hash)
|
19
|
+
@socket = Socket.new(host, port, @options[:socket])
|
20
|
+
@extname_len = ProtoCommon::EXTNAME_LEN
|
21
|
+
@size_len = ProtoCommon::SIZE_LEN
|
22
|
+
@store_path = store_path || 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def upload(file)
|
26
|
+
_upload(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(path, group_name = nil)
|
30
|
+
cmd = CMD::DELETE_FILE
|
31
|
+
raise "path arguments is empty!" if path.blank?
|
32
|
+
if group_name.blank?
|
33
|
+
group_name = /^\/?(\w+)/.match(path)[1]
|
34
|
+
path = path.gsub("/#{group_name}")
|
35
|
+
end
|
36
|
+
raise "group_name arguments is empty!" if group_name.blank?
|
37
|
+
group_bytes = group_name.bytes.fill(0, group_name.length...ProtoCommon::GROUP_NAME_MAX_LEN)
|
38
|
+
path_length = (group_bytes.length + path.bytes.length)
|
39
|
+
|
40
|
+
@socket.write(cmd, (ProtoCommon.header_bytes(cmd, path_length) + group_bytes + path.bytes))
|
41
|
+
@socket.receive
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def _upload(file)
|
46
|
+
cmd = CMD::UPLOAD_FILE
|
47
|
+
|
48
|
+
extname = File.extname(file)[1..-1]
|
49
|
+
ext_name_bs = extname.bytes.fill(0, extname.length...@extname_len)
|
50
|
+
hex_len_bytes = Utils.number_to_Buffer(file.size)
|
51
|
+
size_byte = [@store_path].concat(hex_len_bytes).fill(0, (hex_len_bytes.length+1)...@size_len)
|
52
|
+
|
53
|
+
header = ProtoCommon.header_bytes(cmd, (size_byte.length + @extname_len + file.size))
|
54
|
+
pkg = header + size_byte + ext_name_bs
|
55
|
+
|
56
|
+
@socket.write(cmd, pkg)
|
57
|
+
@socket.write(cmd, IO.read(file))
|
58
|
+
@socket.receive do |body|
|
59
|
+
group_name_max_len = ProtoCommon::GROUP_NAME_MAX_LEN
|
60
|
+
|
61
|
+
{
|
62
|
+
group_name: body[0...group_name_max_len].strip,
|
63
|
+
path: body[group_name_max_len..-1]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fastdfs-client/storage'
|
2
|
+
|
3
|
+
module Fastdfs
|
4
|
+
module Client
|
5
|
+
|
6
|
+
class Tracker
|
7
|
+
extend Hook
|
8
|
+
|
9
|
+
before(:get_storage){ @socket.connection }
|
10
|
+
after(:get_storage){ @socket.close }
|
11
|
+
|
12
|
+
attr_accessor :socket, :cmd, :options
|
13
|
+
|
14
|
+
def initialize(host, port, options = {})
|
15
|
+
@socket = Socket.new(host, port, options[:socket])
|
16
|
+
@cmd = CMD::STORE_WITHOUT_GROUP_ONE
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_storage
|
20
|
+
header = ProtoCommon.header_bytes(@cmd, 0)
|
21
|
+
@socket.write(@cmd, header)
|
22
|
+
@socket.receive do |body|
|
23
|
+
storage_ip = body[ProtoCommon::IPADDR].strip
|
24
|
+
storage_port = body[ProtoCommon::PORT].unpack("C*").to_pack_long
|
25
|
+
store_path = body[ProtoCommon::TRACKER_BODY_LEN-1].unpack("C*")[0]
|
26
|
+
|
27
|
+
Storage.new(storage_ip, storage_port, store_path, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Utils
|
2
|
+
|
3
|
+
def self.number_to_Buffer(num)
|
4
|
+
8.times.map{|i| (num >> (56 - 8 * i)) & 255}
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.array_merge(arr1, arr2)
|
8
|
+
raise "argument must be array" unless arr1.is_a?(Array) || arr2.is_a?(Array)
|
9
|
+
arr2.each_with_index.map{|v, i| arr1[i] = v }
|
10
|
+
arr1
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
class TCPSocket
|
3
|
+
include Fastdfs::Client
|
4
|
+
|
5
|
+
attr_accessor :host, :port, :cmd, :recv_offset, :connect_state
|
6
|
+
|
7
|
+
def initialize(host, port)
|
8
|
+
@host = host
|
9
|
+
@port = port
|
10
|
+
@recv_offset = 0
|
11
|
+
@connect_state = true
|
12
|
+
@cmd = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def write(*args)
|
16
|
+
pkg = args[0].unpack("C*")
|
17
|
+
@cmd ||= pkg[8]
|
18
|
+
end
|
19
|
+
|
20
|
+
def recv(len)
|
21
|
+
recv_data = recv_config[@cmd.to_s] || {}
|
22
|
+
data = recv_data.key?(:recv_bytes) ? recv_data[:recv_bytes].call(len) : nil
|
23
|
+
@recv_offset = len
|
24
|
+
data
|
25
|
+
end
|
26
|
+
|
27
|
+
def close
|
28
|
+
@recv_offset = 0
|
29
|
+
@connect_state = false
|
30
|
+
@cmd = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def closed?
|
34
|
+
@connect_state
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def recv_config
|
40
|
+
{
|
41
|
+
"101" => {
|
42
|
+
recv_bytes: lambda do |len|
|
43
|
+
header = ProtoCommon.header_bytes(CMD::RESP_CODE, 0)
|
44
|
+
header[7] = ProtoCommon::TRACKER_BODY_LEN
|
45
|
+
|
46
|
+
group_name = Utils.array_merge([].fill(0, 0...16), TestConfig::GROUP_NAME.bytes)
|
47
|
+
ip = Utils.array_merge([].fill(0, 0...15), TestConfig::STORAGE_IP.bytes)
|
48
|
+
port = Utils.number_to_Buffer(TestConfig::STORAGE_PORT.to_i)
|
49
|
+
store_path = Array(TestConfig::STORE_PATH)
|
50
|
+
|
51
|
+
(header+group_name+ip+port+store_path)[@recv_offset...@recv_offset+len].pack("C*")
|
52
|
+
end
|
53
|
+
},
|
54
|
+
"11" => {
|
55
|
+
recv_bytes: lambda do |len|
|
56
|
+
header = ProtoCommon.header_bytes(CMD::RESP_CODE, 0)
|
57
|
+
group_name = Utils.array_merge([].fill(0, 0...16), TestConfig::GROUP_NAME.bytes)
|
58
|
+
file_name = TestConfig::FILE_NAME.bytes
|
59
|
+
res = (group_name + file_name)
|
60
|
+
header[7] = (header + res).length
|
61
|
+
res = (header + res)
|
62
|
+
|
63
|
+
res[@recv_offset...@recv_offset+len].pack("C*")
|
64
|
+
end
|
65
|
+
},
|
66
|
+
"12" => {
|
67
|
+
recv_bytes: lambda do |len|
|
68
|
+
header = ProtoCommon.header_bytes(CMD::RESP_CODE, 0)
|
69
|
+
header.pack("C*")
|
70
|
+
end
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'debugger'
|
2
|
+
require 'rspec'
|
3
|
+
require 'rspec/core'
|
4
|
+
require 'rspec/mocks'
|
5
|
+
require File.expand_path('../../lib/fastdfs-client', __FILE__)
|
6
|
+
require File.expand_path('../test_config', __FILE__)
|
7
|
+
require File.expand_path('../mock_tcp_socket', __FILE__)
|
8
|
+
|
9
|
+
FC = Fastdfs::Client
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.mock_with :rspec do |c|
|
13
|
+
c.syntax = [:should, :expect]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fastdfs::Client::Storage do
|
4
|
+
|
5
|
+
let(:host){ "192.168.9.16" }
|
6
|
+
let(:port){ "22122" }
|
7
|
+
|
8
|
+
let(:tracker){ FC::Tracker.new(host, port) }
|
9
|
+
let(:storage){ tracker.get_storage }
|
10
|
+
|
11
|
+
it "initialize the server" do
|
12
|
+
expect(FC::Socket).to receive(:new).with(host, port, nil)
|
13
|
+
FC::Storage.new(host, port)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have access to the storage connection" do
|
17
|
+
expect(storage.socket).to receive(:connection)
|
18
|
+
expect(storage.socket).to receive(:close)
|
19
|
+
storage.upload(TestConfig::FILE)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should the result attributes group_name and path" do
|
23
|
+
res = storage.upload(TestConfig::FILE)
|
24
|
+
expect(res).to include(:group_name)
|
25
|
+
expect(res).to include(:path)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can delete file by group and path" do
|
29
|
+
res = storage.upload(TestConfig::FILE)
|
30
|
+
storage.delete(res[:path], res[:group_name])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can delete file raise exception" do
|
34
|
+
res = storage.upload(TestConfig::FILE)
|
35
|
+
result = FC::ProtoCommon.header_bytes(FC::CMD::RESP_CODE, 0, 22)
|
36
|
+
TCPSocket.any_instance.stub("recv").and_return(result.pack("C*"))
|
37
|
+
expect{ storage.delete("fdsaf", res[:group_name]) }.to raise_error(RuntimeError)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/spec/test_config.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module TestConfig
|
2
|
+
STORAGE_IP = "192.168.8.23"
|
3
|
+
STORAGE_PORT = "23000"
|
4
|
+
STORE_PATH = 0
|
5
|
+
GROUP_NAME = "group1"
|
6
|
+
FILE_NAME = "M00/04/47/wKgIF1cHcQyAeAF7AAACVHeY6n8267.png"
|
7
|
+
|
8
|
+
FILE = Tempfile.new("test.jpg")
|
9
|
+
FILE.write("testtest")
|
10
|
+
FILE.close
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fastdfs::Client::Tracker do
|
4
|
+
|
5
|
+
let(:host){ "192.168.9.16" }
|
6
|
+
let(:port){ "22122" }
|
7
|
+
|
8
|
+
let(:tracker){ FC::Tracker.new(host, port) }
|
9
|
+
|
10
|
+
it "initialize the server" do
|
11
|
+
expect(FC::Socket).to receive(:new).with(host, port, nil)
|
12
|
+
FC::Tracker.new(host, port)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have access to the storage connection" do
|
16
|
+
expect(tracker.socket).to receive(:connection)
|
17
|
+
expect(tracker.socket).to receive(:close)
|
18
|
+
tracker.get_storage
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have access to the storage class" do
|
22
|
+
expect(tracker.get_storage.class).to eq(FC::Storage)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "verify the server address and port" do
|
26
|
+
expect(tracker.get_storage.host).to eq(TestConfig::STORAGE_IP)
|
27
|
+
#[0, 0, 0, 0, 0, 89, 216, 0]
|
28
|
+
expect(tracker.get_storage.port.to_s).to eq(TestConfig::STORAGE_PORT)
|
29
|
+
expect(tracker.get_storage.store_path).to eq(TestConfig::STORE_PATH)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "run server flow" do
|
33
|
+
# storage = tracker.get_storage
|
34
|
+
# puts "#{storage.host}, #{storage.port}"
|
35
|
+
# results = storage.upload(File.open("/Users/huxinghai/Documents/shark/app/assets/images/page.png"))
|
36
|
+
# puts storage.delete(results[:path], results[:group_name])
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fastdfs-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ka Ka
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
description: fastdfs upload file client for ruby
|
28
|
+
email:
|
29
|
+
- huxinghai1988@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- Gemfile
|
35
|
+
- Gemfile.lock
|
36
|
+
- README.md
|
37
|
+
- fastdfs-client.gemspec
|
38
|
+
- lib/fastdfs-client.rb
|
39
|
+
- lib/fastdfs-client/cmd.rb
|
40
|
+
- lib/fastdfs-client/extend_core.rb
|
41
|
+
- lib/fastdfs-client/hook.rb
|
42
|
+
- lib/fastdfs-client/proto_common.rb
|
43
|
+
- lib/fastdfs-client/socket.rb
|
44
|
+
- lib/fastdfs-client/storage.rb
|
45
|
+
- lib/fastdfs-client/tracker.rb
|
46
|
+
- lib/fastdfs-client/utils.rb
|
47
|
+
- lib/fastdfs-client/version.rb
|
48
|
+
- spec/mock_tcp_socket.rb
|
49
|
+
- spec/spec_helper.rb
|
50
|
+
- spec/storage_spec.rb
|
51
|
+
- spec/test_config.rb
|
52
|
+
- spec/tracker_spec.rb
|
53
|
+
homepage: https://github.com/huxinghai1988/fastdfs-client-ruby.git
|
54
|
+
licenses:
|
55
|
+
- MIT
|
56
|
+
metadata: {}
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.2.2
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: fastdfs upload file client for ruby
|
77
|
+
test_files:
|
78
|
+
- spec/mock_tcp_socket.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
- spec/storage_spec.rb
|
81
|
+
- spec/test_config.rb
|
82
|
+
- spec/tracker_spec.rb
|
83
|
+
has_rdoc:
|