Merge branch '1943-client-sdk-config-files'
[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       self.uuid.gsub! /\+.*/, ''
32       if self.uuid == Digest::MD5.hexdigest(self.manifest_text)
33         self.uuid.gsub! /$/, '+' + self.manifest_text.length.to_s
34         true
35       else
36         errors.add :uuid, 'uuid does not match checksum of manifest_text'
37         false
38       end
39     elsif self.manifest_text
40       errors.add :uuid, 'checksum for manifest_text not supplied in uuid'
41       false
42     else
43       errors.add :manifest_text, 'manifest_text not supplied'
44       false
45     end
46   end
47
48   def data_size
49     inspect_manifest_text if @data_size.nil? or manifest_text_changed?
50     @data_size
51   end
52
53   def files
54     inspect_manifest_text if @files.nil? or manifest_text_changed?
55     @files
56   end
57
58   def inspect_manifest_text
59     if !manifest_text
60       @data_size = false
61       @files = []
62       return
63     end
64     @data_size = 0
65     @files = []
66     manifest_text.split("\n").each do |stream|
67       toks = stream.split(" ")
68
69       stream = toks[0].gsub /\\(\\|[0-7]{3})/ do |escape_sequence|
70         case $1
71         when '\\' '\\'
72         else $1.to_i(8).chr
73         end
74       end
75
76       toks[1..-1].each do |tok|
77         if (re = tok.match /^[0-9a-f]{32}/)
78           blocksize = nil
79           tok.split('+')[1..-1].each do |hint|
80             if !blocksize and hint.match /^\d+$/
81               blocksize = hint.to_i
82             end
83             if (re = hint.match /^GS(\d+)$/)
84               blocksize = re[1].to_i
85             end
86           end
87           @data_size = false if !blocksize
88           @data_size += blocksize if @data_size
89         else
90           if (re = tok.match /^(\d+):(\d+):(\S+)$/)
91             filename = re[3].gsub /\\(\\|[0-7]{3})/ do |escape_sequence|
92               case $1
93               when '\\' '\\'
94               else $1.to_i(8).chr
95               end
96             end
97             @files << [stream, filename, re[2].to_i]
98           end
99         end
100       end
101     end
102   end
103 end