lib/fastdfs-client/storage.rb in fastdfs-client-0.0.3 vs lib/fastdfs-client/storage.rb in fastdfs-client-0.0.5
- old
+ new
@@ -4,12 +4,12 @@
module Client
class Storage
extend Hook
- before(:upload, :delete){ @socket.connection }
- after(:upload, :delete){ @socket.close }
+ before(:upload, :delete, :get_metadata, ){ @socket.connection }
+ after(:upload, :delete, :get_metadata, ){ @socket.close }
attr_accessor :host, :port, :group_name, :store_path, :socket, :options
def initialize(host, port, store_path = nil, options = {})
@host = host
@@ -26,44 +26,129 @@
_upload(file)
end
def delete(path, group_name = nil)
cmd = CMD::DELETE_FILE
+ path_bytes = header_path_bytes(cmd, path, group_name)
+ @socket.write(cmd, path_bytes)
+ @socket.receive{ true }
+ end
+
+ def get_metadata(path, group_name = nil)
+ cmd = CMD::GET_METADATA
+ path_bytes = header_path_bytes(cmd, path, group_name)
+ @socket.write(cmd, path_bytes)
+ @socket.receive do |content|
+ res = content.split(ProtoCommon::RECORD_SEPERATOR).map do |c|
+ c.split(ProtoCommon::FILE_SEPERATOR)
+ end.flatten
+ Utils.symbolize_keys(Hash[*res])
+ end
+ end
+
+ def set_metadata(path, group_name = nil, options = {}, flag = :cover)
+ cmd = CMD::SET_METADATA
+
+ unless options.is_a?(Hash)
+ flag = options
+ options = {}
+ end
+
+ if group_name.is_a?(Hash)
+ options = group_name
+ group_name = nil
+ end
+ flag = convert_meta_flag(flag)
+ group_bytes, path_bytes = group_path_bytes(path, group_name)
+ meta_bytes = meta_to_bytes(options)
+
+ size_bytes = Utils.number_to_buffer(path_bytes.length) + Utils.number_to_buffer(meta_bytes.length)
+ size_bytes = (size_bytes).fill(0, size_bytes.length...16)
+ total = size_bytes.length + flag.length + group_bytes.length + path_bytes.length + meta_bytes.length
+ header_bytes = ProtoCommon.header_bytes(cmd, total)
+ @socket.write(cmd, (header_bytes + size_bytes + flag.bytes + group_bytes + path_bytes))
+ @socket.write(cmd, meta_bytes)
+ @socket.receive
+ end
+
+ def download(path, group_name = nil)
+ cmd = CMD::DOWNLOAD_FILE
+ group_bytes, path_bytes = group_path_bytes(path, group_name)
+ download_bytes = Utils.number_to_buffer(0) + Utils.number_to_buffer(0)
+
+ header_bytes = ProtoCommon.header_bytes(cmd, group_bytes.length + path_bytes.length + download_bytes.length)
+
+ @socket.write(cmd, header_bytes + download_bytes + group_bytes + path_bytes)
+ @socket.receive do |body|
+ create_tempfile(path, body) if body
+ end
+ end
+
+ private
+ def group_path_bytes(path, group_name = nil)
+ group_name, path = extract_path!(path, group_name)
+ group_bytes = group_name.bytes.fill(0, group_name.length...ProtoCommon::GROUP_NAME_MAX_LEN)
+ [group_bytes, path.bytes]
+ end
+
+ def header_path_bytes(cmd, path, group_name = nil)
+ path_bytes = group_path_bytes(path, group_name).flatten
+ return (ProtoCommon.header_bytes(cmd, path_bytes.length) + path_bytes)
+ end
+
+ def extract_path!(path, group_name = nil)
raise "path arguments is empty!" if path.blank?
if group_name.blank?
group_name = /^\/?(\w+)/.match(path)[1]
path = path.gsub(Regexp.new("/?#{group_name}/?"), "")
end
raise "group_name arguments is empty!" if group_name.blank?
- group_bytes = group_name.bytes.fill(0, group_name.length...ProtoCommon::GROUP_NAME_MAX_LEN)
- path_length = (group_bytes.length + path.bytes.length)
-
- @socket.write(cmd, (ProtoCommon.header_bytes(cmd, path_length) + group_bytes + path.bytes))
- @socket.receive{ true }
+ return group_name, path
end
- private
def _upload(file)
cmd = CMD::UPLOAD_FILE
extname = File.extname(file)[1..-1]
ext_name_bs = extname.bytes.fill(0, extname.length...@extname_len)
- hex_len_bytes = Utils.number_to_Buffer(file.size)
+ hex_len_bytes = Utils.number_to_buffer(file.size)
size_byte = [@store_path].concat(hex_len_bytes).fill(0, (hex_len_bytes.length+1)...@size_len)
header = ProtoCommon.header_bytes(cmd, (size_byte.length + @extname_len + file.size))
pkg = header + size_byte + ext_name_bs
@socket.write(cmd, pkg)
@socket.write(cmd, IO.read(file))
@socket.receive do |body|
group_name_max_len = ProtoCommon::GROUP_NAME_MAX_LEN
- {
- group_name: body[0...group_name_max_len].strip,
- path: body[group_name_max_len..-1]
- }
+ {group_name: body[0...group_name_max_len].strip, path: body[group_name_max_len..-1]}
end
+ end
+
+ def convert_meta_flag(flag)
+ data = {
+ cover: ProtoCommon::SET_METADATA_FLAG_OVERWRITE,
+ merge: ProtoCommon::SET_METADATA_FLAG_MERGE
+ }
+ flag = :cover if flag.blank?
+ data[flag.to_sym]
+ end
+
+ def meta_to_bytes(options = {})
+ meta_bytes = options.map do |a|
+ a.join(ProtoCommon::FILE_SEPERATOR)
+ end.join(ProtoCommon::RECORD_SEPERATOR).bytes
+ meta_bytes << 0 if meta_bytes.blank?
+ meta_bytes
+ end
+
+ def create_tempfile(path, body)
+ tmp = Tempfile.new(path.gsub(/\//, "_"))
+ tmp.binmode
+ tmp.write(body)
+ tmp.close
+ tmp
end
end
end
\ No newline at end of file