Merge branch 'master' of git.clinicalfuture.com:arvados
[arvados.git] / services / api / app / models / collection.rb
1 class Collection < ArvadosModel
2   include AssignUuid
3   include KindAndEtag
4   include CommonApiTemplate
5
6   api_accessible :user, extend: :common do |t|
7     t.add :data_size
8     t.add :files
9   end
10
11   def redundancy_status
12     if redundancy_confirmed_as.nil?
13       'unconfirmed'
14     elsif redundancy_confirmed_as < redundancy
15       'degraded'
16     else
17       if redundancy_confirmed_at.nil?
18         'unconfirmed'
19       elsif Time.now - redundancy_confirmed_at < 7.days
20         'OK'
21       else
22         'stale'
23       end
24     end
25   end
26
27   def assign_uuid
28     if self.manifest_text.nil? and self.uuid.nil?
29       super
30     elsif self.manifest_text and self.uuid
31       if self.uuid.gsub(/\+[^,]+/,'') == Digest::MD5.hexdigest(self.manifest_text)
32         true
33       else
34         errors.add :uuid, 'uuid does not match checksum of manifest_text'
35         false
36       end
37     elsif self.manifest_text
38       errors.add :uuid, 'checksum for manifest_text not supplied in uuid'
39       false
40     else
41       errors.add :manifest_text, 'manifest_text not supplied'
42       false
43     end
44   end
45
46   def data_size
47     inspect_manifest_text if @data_size.nil? or manifest_text_changed?
48     @data_size
49   end
50
51   def files
52     inspect_manifest_text if @files.nil? or manifest_text_changed?
53     @files
54   end
55
56   def inspect_manifest_text
57     if !manifest_text
58       @data_size = false
59       @files = []
60       return
61     end
62     @data_size = 0
63     @files = []
64     manifest_text.split("\n").each do |stream|
65       toks = stream.split(" ")
66
67       stream = toks[0].gsub /\\(\\|[0-7]{3})/ do |escape_sequence|
68         case $1
69         when '\\' '\\'
70         else $1.to_i(8).chr
71         end
72       end
73
74       toks[1..-1].each do |tok|
75         if (re = tok.match /^[0-9a-f]{32}/)
76           blocksize = nil
77           tok.split('+')[1..-1].each do |hint|
78             if !blocksize and hint.match /^\d+$/
79               blocksize = hint.to_i
80             end
81             if (re = hint.match /^GS(\d+)$/)
82               blocksize = re[1].to_i
83             end
84           end
85           @data_size = false if !blocksize
86           @data_size += blocksize if @data_size
87         else
88           if (re = tok.match /^(\d+):(\d+):(\S+)$/)
89             filename = re[3].gsub /\\(\\|[0-7]{3})/ do |escape_sequence|
90               case $1
91               when '\\' '\\'
92               else $1.to_i(8).chr
93               end
94             end
95             @files << [stream, filename, re[2].to_i]
96           end
97         end
98       end
99     end
100   end
101 end