fastdfs-client 0.0.5 → 1.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 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