bigfile: make parse_info public and require arg
[ruby-mogilefs-client.git] / lib / mogilefs / bigfile.rb
blob1f9d0ba00ba368916bbdea7f0b5870e316c5fcfc
1 # -*- encoding: binary -*-
2 require 'uri'
3 require 'mogilefs/util'
4 require 'mogilefs/network'
6 # Used for reading deprecated "bigfile" objects generated by the deprecated
7 # mogtool(1) utility.  Not recommended for new projects.
9 module MogileFS::Bigfile
10   # VALID_TYPES = %w(file tarball partition).map { |x| x.freeze }.freeze
11   include MogileFS::Network
13   # returns a big_info hash if successful
14   def bigfile_stat(key)
15     bigfile_parse_info(get_file_data(key))
16   end
18   # returns total bytes written and the big_info hash if successful, raises an
19   # exception if not.  wr_io is expected to be an IO-like object capable of
20   # receiving the write method.
21   def bigfile_write(key, wr_io, opts = { :verify => false })
22     info = bigfile_stat(key)
23     total = 0
25     # we only decode raw zlib deflated streams that mogtool (unfortunately)
26     # generates.  tarballs and gzip(1) are up to to the application to decrypt.
27     if info[:compressed] || opts[:verify]
28       wr_io = MogileFS::Bigfile::Filter.new(wr_io, info, opts)
29     end
31     info[:parts].each_with_index do |part,part_nr|
32       next if part_nr == 0 # info[:parts][0] is always empty
33       uris = verify_uris(part[:paths].map { |path| URI.parse(path) })
34       if uris.empty?
35         # part[:paths] may not be valid anymore due to rebalancing, however we
36         # can get_keys on key,<part_nr> and retry paths if all paths fail
37         part[:paths] = get_paths("#{key.gsub(/^big_info:/, '')},#{part_nr}")
38         uris = verify_uris(part[:paths].map { |path| URI.parse(path) })
39         raise MogileFS::Backend::NoDevices if uris.empty?
40       end
42       sock = http_read_sock(uris[0])
43       w = copy_stream(sock, wr_io)
45       wr_io.respond_to?(:md5_check!) and wr_io.md5_check!(part[:md5])
46       total += w
47     end
48     wr_io.flush
49     total += wr_io.flushed_bytes if wr_io.respond_to?(:flushed_bytes)
51     [ total, info ]
52   end
54   ##
55   # parses the contents of a _big_info: string or IO object
56   def bigfile_parse_info(info) # :nodoc:
57     rv = { :parts => [] }
58     info.each_line do |line|
59       line.chomp!
60       case line
61       when /^(des|type|filename)\s+(.+)$/
62         rv[$1.to_sym] = $2
63       when /^compressed\s+([01])$/
64         rv[:compressed] = ($1 == '1')
65       when /^(chunks|size)\s+(\d+)$/
66         rv[$1.to_sym] = $2.to_i
67       when /^part\s+(\d+)\s+bytes=(\d+)\s+md5=(.+)\s+paths:\s+(.+)$/
68         rv[:parts][$1.to_i] = {
69           :bytes => $2.to_i,
70           :md5 => $3.downcase,
71           :paths => $4.split(/\s*,\s*/),
72         }
73       end
74     end
76     rv
77   end
78 end
79 require "mogilefs/bigfile/filter"
81 __END__
82 # Copied from mogtool:
83 # http://code.sixapart.com/svn/mogilefs/utils/mogtool, r1221
85 # this is a temporary file that we delete when we're doing recording all chunks
87 _big_pre:<key>
89     starttime=UNIXTIMESTAMP
91 # when done, we write the _info file and delete the _pre.
93 _big_info:<key>
95     des Cow's ljdb backup as of 2004-11-17
96     type  { partition, file, tarball }
97     compressed {0, 1}
98     filename  ljbinlog.305.gz
99     partblocks  234324324324
102     part 1 <bytes> <md5hex>
103     part 2 <bytes> <md5hex>
104     part 3 <bytes> <md5hex>
105     part 4 <bytes> <md5hex>
106     part 5 <bytes> <md5hex>
108 _big:<key>,<n>
109 _big:<key>,<n>
110 _big:<key>,<n>
113 Receipt format:
115 BEGIN MOGTOOL RECIEPT
116 type partition
117 des Foo
118 compressed foo
120 part 1 bytes=23423432 md5=2349823948239423984 paths: http://dev5/2/23/23/.fid, http://dev6/23/423/4/324.fid
121 part 1 bytes=23423432 md5=2349823948239423984 paths: http://dev5/2/23/23/.fid, http://dev6/23/423/4/324.fid
122 part 1 bytes=23423432 md5=2349823948239423984 paths: http://dev5/2/23/23/.fid, http://dev6/23/423/4/324.fid
123 part 1 bytes=23423432 md5=2349823948239423984 paths: http://dev5/2/23/23/.fid, http://dev6/23/423/4/324.fid
126 END RECIEPT