fastdfs-client 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83f837406bfbb7c59a4da740450c49232800e481
4
- data.tar.gz: 900430e39aeea9db93faf42c460394eeb9087277
3
+ metadata.gz: 84bd058d40b079c23d2cc236c651aa48a5a4e4f9
4
+ data.tar.gz: 21b8ffd285416638286d3181134790665ce17c44
5
5
  SHA512:
6
- metadata.gz: 106f6c4cc8406215c7fe22d4935e4b72538f8e7f70874c1f66e129eac483669f8d2d1493bb09f15b2a2d2389fa8e34ffdc21ba5b3944361b53c35836838f303d
7
- data.tar.gz: a12327a458920d7c1b4eccdf4828c1a7dc24d3ad0a7bd3d58d108b22fa7932d0cc050d1b0d3dc03b6a9bde3022dd33b349be9245383f18681f786ebc8ed06794
6
+ metadata.gz: de8034cd485d98fa4825ccb745e408f1e41052162c7bd86b75c25bcf08d7c5204cac57107ca3c2566770298f09d7fbc5ad8b0df0872f7bcfbfd8087e4ec525da
7
+ data.tar.gz: 3de188e4493f56da22ce8ffb66c4d6cf332536381c0ec38de294a3e2d1acbd7bc02fec557302c062e17e4c3abaec93f2ff58e3f04149f9bd01bdac76e697d770
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fastdfs-client (0.0.5)
4
+ fastdfs-client (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: http://gems.ruby-china.org/
data/README.md CHANGED
@@ -4,8 +4,7 @@ fastdfs client for ruby
4
4
 
5
5
  ### Install
6
6
 
7
- #Gemfile
8
- gem 'fastdfs-client', git: "git@github.com:huxinghai1988/fastdfs-client-ruby.git"
7
+ gem install 'fastdfs-client'
9
8
 
10
9
  ### Using
11
10
 
@@ -1,7 +1,7 @@
1
1
  require "fastdfs-client/extend_core"
2
2
  require 'fastdfs-client/socket'
3
+ require 'fastdfs-client/client_proxy'
3
4
  require 'fastdfs-client/cmd'
4
5
  require 'fastdfs-client/proto_common'
5
6
  require 'fastdfs-client/utils'
6
- require 'fastdfs-client/hook'
7
7
  require "fastdfs-client/tracker"
@@ -0,0 +1,32 @@
1
+ module Fastdfs
2
+ module Client
3
+
4
+ class ClientProxy
5
+ attr_accessor :data, :header, :content, :socket
6
+
7
+ def initialize(cmd, socket, content_len, header = [])
8
+ @cmd = cmd
9
+ socket.connection
10
+ @socket = socket
11
+ @header = ProtoCommon.header_bytes(cmd, content_len) + header
12
+ @content = []
13
+ end
14
+
15
+ def push_content
16
+ raise "argument not block!" unless block_given?
17
+ @content << yield
18
+ end
19
+
20
+ def dispose(&block)
21
+ @socket.write(@cmd, @header)
22
+ @content.each do |c|
23
+ @socket.write(@cmd, c)
24
+ end
25
+ @socket.receive &block
26
+ ensure
27
+ @socket.close
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -4,6 +4,9 @@ class Array
4
4
  self.each_with_index.inject(0){|s, item| s = s | (item[0] << (56 - (item[1] * 8))); s }
5
5
  end
6
6
 
7
+ def full_fill(val, len)
8
+ self.fill(val, self.length...len)
9
+ end
7
10
  end
8
11
 
9
12
  class Object
@@ -4,11 +4,6 @@ module Fastdfs
4
4
  module Client
5
5
 
6
6
  class Storage
7
- extend Hook
8
-
9
- before(:upload, :delete, :get_metadata, ){ @socket.connection }
10
- after(:upload, :delete, :get_metadata, ){ @socket.close }
11
-
12
7
  attr_accessor :host, :port, :group_name, :store_path, :socket, :options
13
8
 
14
9
  def initialize(host, port, store_path = nil, options = {})
@@ -22,23 +17,33 @@ module Fastdfs
22
17
  @store_path = store_path || 0
23
18
  end
24
19
 
25
- def upload(file)
26
- _upload(file)
20
+ def upload(file, options = {})
21
+ ext_name_bs = File.extname(file)[1..-1].bytes.full_fill(0, @extname_len)
22
+ size_byte = ([@store_path] + Utils.number_to_buffer(file.size)).full_fill(0, @size_len)
23
+ content_len = (@size_len + @extname_len + file.size)
24
+
25
+ client = ClientProxy.new(CMD::UPLOAD_FILE, @socket, content_len, size_byte + ext_name_bs)
26
+ client.push_content{ IO.read(file) }
27
+ client.dispose do |body|
28
+ group_name_max_len = ProtoCommon::GROUP_NAME_MAX_LEN
29
+
30
+ res = {group_name: body[0...group_name_max_len].strip, path: body[group_name_max_len..-1]}
31
+ _set_metadata(res[:path], res[:group_name], options) unless options.blank?
32
+ res
33
+ end
27
34
  end
28
35
 
29
36
  def delete(path, group_name = nil)
30
- cmd = CMD::DELETE_FILE
31
- path_bytes = header_path_bytes(cmd, path, group_name)
32
- @socket.write(cmd, path_bytes)
33
- @socket.receive{ true }
37
+ path_bytes = group_path_bytes(path, group_name).flatten
38
+ client = ClientProxy.new(CMD::DELETE_FILE, @socket, path_bytes.length, path_bytes)
39
+ client.dispose
34
40
  end
35
41
 
36
42
  def get_metadata(path, group_name = nil)
37
- cmd = CMD::GET_METADATA
38
- path_bytes = header_path_bytes(cmd, path, group_name)
39
- @socket.write(cmd, path_bytes)
40
- @socket.receive do |content|
41
- res = content.split(ProtoCommon::RECORD_SEPERATOR).map do |c|
43
+ path_bytes = group_path_bytes(path, group_name).flatten
44
+ client = ClientProxy.new(CMD::GET_METADATA, @socket, path_bytes.length, path_bytes)
45
+ client.dispose do |body|
46
+ res = body.split(ProtoCommon::RECORD_SEPERATOR).map do |c|
42
47
  c.split(ProtoCommon::FILE_SEPERATOR)
43
48
  end.flatten
44
49
  Utils.symbolize_keys(Hash[*res])
@@ -46,8 +51,6 @@ module Fastdfs
46
51
  end
47
52
 
48
53
  def set_metadata(path, group_name = nil, options = {}, flag = :cover)
49
- cmd = CMD::SET_METADATA
50
-
51
54
  unless options.is_a?(Hash)
52
55
  flag = options
53
56
  options = {}
@@ -57,28 +60,15 @@ module Fastdfs
57
60
  options = group_name
58
61
  group_name = nil
59
62
  end
60
- flag = convert_meta_flag(flag)
61
- group_bytes, path_bytes = group_path_bytes(path, group_name)
62
- meta_bytes = meta_to_bytes(options)
63
-
64
- size_bytes = Utils.number_to_buffer(path_bytes.length) + Utils.number_to_buffer(meta_bytes.length)
65
- size_bytes = (size_bytes).fill(0, size_bytes.length...16)
66
- total = size_bytes.length + flag.length + group_bytes.length + path_bytes.length + meta_bytes.length
67
- header_bytes = ProtoCommon.header_bytes(cmd, total)
68
- @socket.write(cmd, (header_bytes + size_bytes + flag.bytes + group_bytes + path_bytes))
69
- @socket.write(cmd, meta_bytes)
70
- @socket.receive
63
+ _set_metadata(path, group_name, options, flag)
71
64
  end
72
65
 
73
66
  def download(path, group_name = nil)
74
- cmd = CMD::DOWNLOAD_FILE
75
- group_bytes, path_bytes = group_path_bytes(path, group_name)
67
+ path_bytes = group_path_bytes(path, group_name).flatten
76
68
  download_bytes = Utils.number_to_buffer(0) + Utils.number_to_buffer(0)
77
-
78
- header_bytes = ProtoCommon.header_bytes(cmd, group_bytes.length + path_bytes.length + download_bytes.length)
79
-
80
- @socket.write(cmd, header_bytes + download_bytes + group_bytes + path_bytes)
81
- @socket.receive do |body|
69
+ data = download_bytes + path_bytes
70
+ client = ClientProxy.new(CMD::DOWNLOAD_FILE, @socket, data.length, data)
71
+ client.dispose do |body|
82
72
  create_tempfile(path, body) if body
83
73
  end
84
74
  end
@@ -86,7 +76,7 @@ module Fastdfs
86
76
  private
87
77
  def group_path_bytes(path, group_name = nil)
88
78
  group_name, path = extract_path!(path, group_name)
89
- group_bytes = group_name.bytes.fill(0, group_name.length...ProtoCommon::GROUP_NAME_MAX_LEN)
79
+ group_bytes = group_name.bytes.full_fill(0, ProtoCommon::GROUP_NAME_MAX_LEN)
90
80
  [group_bytes, path.bytes]
91
81
  end
92
82
 
@@ -105,24 +95,18 @@ module Fastdfs
105
95
  return group_name, path
106
96
  end
107
97
 
108
- def _upload(file)
109
- cmd = CMD::UPLOAD_FILE
110
-
111
- extname = File.extname(file)[1..-1]
112
- ext_name_bs = extname.bytes.fill(0, extname.length...@extname_len)
113
- hex_len_bytes = Utils.number_to_buffer(file.size)
114
- size_byte = [@store_path].concat(hex_len_bytes).fill(0, (hex_len_bytes.length+1)...@size_len)
98
+ def _set_metadata(path, group_name = nil, options = {}, flag = :cover)
99
+ flag = convert_meta_flag(flag)
100
+ group_bytes, path_bytes = group_path_bytes(path, group_name)
101
+ meta_bytes = meta_to_bytes(options)
115
102
 
116
- header = ProtoCommon.header_bytes(cmd, (size_byte.length + @extname_len + file.size))
117
- pkg = header + size_byte + ext_name_bs
103
+ size_bytes = Utils.number_to_buffer(path_bytes.length) + Utils.number_to_buffer(meta_bytes.length)
104
+ size_bytes = (size_bytes).full_fill(0, 16)
105
+ total = size_bytes.length + flag.length + group_bytes.length + path_bytes.length + meta_bytes.length
118
106
 
119
- @socket.write(cmd, pkg)
120
- @socket.write(cmd, IO.read(file))
121
- @socket.receive do |body|
122
- group_name_max_len = ProtoCommon::GROUP_NAME_MAX_LEN
123
-
124
- {group_name: body[0...group_name_max_len].strip, path: body[group_name_max_len..-1]}
125
- end
107
+ client = ClientProxy.new(CMD::SET_METADATA, @socket, total, (size_bytes + flag.bytes + group_bytes + path_bytes))
108
+ client.push_content{ meta_bytes }
109
+ client.dispose
126
110
  end
127
111
 
128
112
  def convert_meta_flag(flag)
@@ -4,10 +4,6 @@ module Fastdfs
4
4
  module Client
5
5
 
6
6
  class Tracker
7
- extend Hook
8
-
9
- before(:get_storage){ @socket.connection }
10
- after(:get_storage){ @socket.close }
11
7
 
12
8
  attr_accessor :socket, :cmd, :options
13
9
 
@@ -17,16 +13,15 @@ module Fastdfs
17
13
  end
18
14
 
19
15
  def get_storage
20
- header = ProtoCommon.header_bytes(@cmd, 0)
21
- @socket.write(@cmd, header)
22
- res = @socket.receive
23
- return res unless res[:status]
24
-
25
- storage_ip = @socket.content[ProtoCommon::IPADDR].strip
26
- storage_port = @socket.content[ProtoCommon::PORT].unpack("C*").to_pack_long
27
- store_path = @socket.content[ProtoCommon::TRACKER_BODY_LEN-1].unpack("C*")[0]
16
+ client = ClientProxy.new(@cmd, @socket, 0)
17
+ res = client.dispose do |body|
18
+ storage_ip = body[ProtoCommon::IPADDR].strip
19
+ storage_port = body[ProtoCommon::PORT].unpack("C*").to_pack_long
20
+ store_path = body[ProtoCommon::TRACKER_BODY_LEN-1].unpack("C*")[0]
28
21
 
29
- Storage.new(storage_ip, storage_port, store_path, options)
22
+ Storage.new(storage_ip, storage_port, store_path, options)
23
+ end
24
+ res[:status] ? res[:result] : res
30
25
  end
31
26
  end
32
27
 
@@ -1,5 +1,5 @@
1
1
  module Fastdfs
2
2
  module Client
3
- VERSION = '0.0.5'
3
+ VERSION = '1.0.0'
4
4
  end
5
5
  end
data/spec/storage_spec.rb CHANGED
@@ -8,47 +8,53 @@ describe Fastdfs::Client::Storage do
8
8
  let(:tracker){ FC::Tracker.new(host, port) }
9
9
  let(:storage){ tracker.get_storage }
10
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[:status]).to be_truthy
25
- # expect(res[:result]).to include(:group_name)
26
- # expect(res[:result]).to include(:path)
27
- # end
28
-
29
- # it "can delete file by group and path" do
30
- # res = storage.upload(TestConfig::FILE)[:result]
31
- # storage.delete(res[:path], res[:group_name])
32
- # end
33
-
34
- # it "can delete file raise exception" do
35
- # res = storage.upload(TestConfig::FILE)[:result]
36
- # result = FC::ProtoCommon.header_bytes(FC::CMD::RESP_CODE, 0, 22)
37
- # TCPSocket.any_instance.stub("recv").and_return(result.pack("C*"))
38
- # expect( storage.delete("fdsaf", res[:group_name])[:status] ).to be_falsey
39
- # end
40
-
41
- # it "can get metadata results" do
42
- # res = storage.get_metadata("#{TestConfig::GROUP_NAME}/#{TestConfig::FILE_NAME}")
43
- # expect(res[:result]).to eq(TestConfig::METADATA)
44
- # end
45
-
46
- # it "can set metadata" do
47
- # expect(storage.set_metadata(TestConfig::FILE_NAME, TestConfig::GROUP_NAME, TestConfig::METADATA)).to be_truthy
48
- # end
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 have access to the storage connection for 2 items" do
23
+ expect(storage.socket).to receive(:connection).at_most(2).times
24
+ expect(storage.socket).to receive(:close).at_most(2).times
25
+ storage.upload(TestConfig::FILE, {author: "kaka", width: "800"})
26
+ end
27
+
28
+ it "should the result attributes group_name and path" do
29
+ res = storage.upload(TestConfig::FILE)
30
+ expect(res[:status]).to be_truthy
31
+ expect(res[:result]).to include(:group_name)
32
+ expect(res[:result]).to include(:path)
33
+ end
34
+
35
+ it "can delete file by group and path" do
36
+ res = storage.upload(TestConfig::FILE)[:result]
37
+ storage.delete(res[:path], res[:group_name])
38
+ end
39
+
40
+ it "can delete file raise exception" do
41
+ res = storage.upload(TestConfig::FILE)[:result]
42
+ result = FC::ProtoCommon.header_bytes(FC::CMD::RESP_CODE, 0, 22)
43
+ TCPSocket.any_instance.stub("recv").and_return(result.pack("C*"))
44
+ expect( storage.delete("fdsaf", res[:group_name])[:status] ).to be_falsey
45
+ end
46
+
47
+ it "can get metadata results" do
48
+ res = storage.get_metadata("#{TestConfig::GROUP_NAME}/#{TestConfig::FILE_NAME}")
49
+ expect(res[:result]).to eq(TestConfig::METADATA)
50
+ end
51
+
52
+ it "can set metadata" do
53
+ expect(storage.set_metadata(TestConfig::FILE_NAME, TestConfig::GROUP_NAME, TestConfig::METADATA)).to be_truthy
54
+ end
49
55
 
50
56
  it "download the file to the local" do
51
- res = storage.download("M00/04/46/wKgIF1b7XLWAI2Q6AAACVHeY6n8655.png", "group1")
57
+ res = storage.download(TestConfig::FILE_NAME, TestConfig::GROUP_NAME)
52
58
  expect(res[:status]).to be_truthy
53
59
  expect(res[:result]).to be_an_instance_of(Tempfile)
54
60
  expect(IO.read(res[:result])).to eq(IO.read(TestConfig::FILE))
data/spec/tracker_spec.rb CHANGED
@@ -30,10 +30,10 @@ describe Fastdfs::Client::Tracker do
30
30
  end
31
31
 
32
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 results
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 results
37
37
  # puts storage.delete(results[:path], results[:group_name])
38
38
  end
39
39
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastdfs-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ka Ka
@@ -37,9 +37,9 @@ files:
37
37
  - README.md
38
38
  - fastdfs-client.gemspec
39
39
  - lib/fastdfs-client.rb
40
+ - lib/fastdfs-client/client_proxy.rb
40
41
  - lib/fastdfs-client/cmd.rb
41
42
  - lib/fastdfs-client/extend_core.rb
42
- - lib/fastdfs-client/hook.rb
43
43
  - lib/fastdfs-client/proto_common.rb
44
44
  - lib/fastdfs-client/socket.rb
45
45
  - lib/fastdfs-client/storage.rb
@@ -1,44 +0,0 @@
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
- begin
35
- return_value = meth.bind(self).call *args, &block
36
- ensure
37
- _hooks[meth_name][:after].each do |callback|
38
- self.instance_exec(&callback)
39
- end
40
- end
41
- return_value
42
- end
43
- end
44
- end