Class: Nearline::Models::ArchivedFile
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Nearline::Models::ArchivedFile
- Defined in:
- lib/nearline/archived_file.rb
Overview
Represents file metadata and possible related FileContent for a single file on a single system
Defined Under Namespace
Classes: FileInformation
Class Method Summary collapse
Instance Method Summary collapse
- #before_destroy ⇒ Object
- #clean_up_duplicate_content ⇒ Object
- #option_override(key) ⇒ Object
- #orphan_check ⇒ Object
-
#persist(manifest) ⇒ Object
Actually persist the file to the repository It has already been determined that a new ArchivedFile record is necessary and the file requires persisting.
- #read_file_counting_bytes(whole_file_hash) ⇒ Object
- #replace_content(key) ⇒ Object
- #restore(*args) ⇒ Object
- #restore_metadata ⇒ Object
- #size_check(file_size, manifest) ⇒ Object
- #unique_sequence_processed?(key, manifest) ⇒ Boolean
- #verify_content(manifest) ⇒ Object
Class Method Details
.create_for(file_path, manifest) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/nearline/archived_file.rb', line 12 def self.create_for(file_path, manifest) file_information = FileInformation.new(file_path, manifest) # The path doesn't actually exist and fails a File.stat return nil if file_information.path_hash.nil? # If we find an exising entry, use it hit = self.find_by_path_hash(file_information.path_hash) return hit unless hit.nil? # We need to create a record for either a directory or file archived_file = ArchivedFile.new( file_information.archived_file_parameters ) # Find a new directory if (file_information.is_directory) archived_file.save! return archived_file end # Find a new file that needs persisted archived_file.file_content.file_size = [file_information.stat.size].pack('Q').unpack('L').first # HACK for Windows archived_file.persist(manifest) archived_file.save! archived_file # TODO: Symbolic links, block devices, ...? end |
Instance Method Details
#before_destroy ⇒ Object
133 134 135 |
# File 'lib/nearline/archived_file.rb', line 133 def before_destroy self.file_content.orphan_check if !self.file_content.nil? end |
#clean_up_duplicate_content ⇒ Object
213 214 215 216 |
# File 'lib/nearline/archived_file.rb', line 213 def clean_up_duplicate_content Sequence.delete_all("file_content_id=#{self.file_content.id}") self.file_content.orphan_check end |
#option_override(key) ⇒ Object
115 116 117 118 119 120 |
# File 'lib/nearline/archived_file.rb', line 115 def option_override(key) if (@options.has_key?(key)) return @options[key] end return self.send(key.to_s) end |
#orphan_check ⇒ Object
137 138 139 140 141 |
# File 'lib/nearline/archived_file.rb', line 137 def orphan_check if self.manifests.size == 1 self.destroy end end |
#persist(manifest) ⇒ Object
Actually persist the file to the repository It has already been determined that a new ArchivedFile record is necessary and the file requires persisting
But, the content may be identical to something else, and we won’t know that until we complete the process and have to clean up our mess.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/nearline/archived_file.rb', line 150 def persist(manifest) whole_file_hash = Digest::SHA1.new file_size = 0 begin file_size = read_file_counting_bytes(whole_file_hash) rescue manifest.add_log "Got error '#{$!}' on path: #{self.path}" self.orphan_check return nil end size_check(file_size, manifest) # Do we have a unique sequence? key = whole_file_hash.hexdigest return self if unique_sequence_processed?(key, manifest) # Handle the case where the sequence is not unique... clean_up_duplicate_content replace_content(key) self end |
#read_file_counting_bytes(whole_file_hash) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/nearline/archived_file.rb', line 173 def read_file_counting_bytes(whole_file_hash) sequencer = FileSequencer.new(self.file_content) file_size = 0 buffer = "" File.open(self.path, "rb") do |io| while (!io.eof) do io.read(Block::MAX_SIZE, buffer) file_size += buffer.size whole_file_hash.update(buffer) sequencer.preserve_content(buffer) end end return file_size end |
#replace_content(key) ⇒ Object
218 219 220 221 |
# File 'lib/nearline/archived_file.rb', line 218 def replace_content(key) self.file_content = FileContent.find_by_fingerprint(key) self.save! end |
#restore(*args) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/nearline/archived_file.rb', line 97 def restore(*args) @options = args. if (self.is_directory) FileUtils.mkdir_p option_override(:path) return end target_path = File.dirname(option_override(:path)) if (!File.exist? target_path) FileUtils.mkdir_p target_path end f = File.open(option_override(:path), "wb") self.file_content.restore_to(f) f.close return end |
#restore_metadata ⇒ Object
122 123 124 125 126 127 128 129 130 131 |
# File 'lib/nearline/archived_file.rb', line 122 def path = option_override(:path) mtime = option_override(:mtime) uid = option_override(:uid) gid = option_override(:gid) mode = option_override(:mode) File.utime(0,Time.at(mtime),path) File.chown(uid, gid, path) File.chmod(mode, path) end |
#size_check(file_size, manifest) ⇒ Object
188 189 190 191 192 193 194 |
# File 'lib/nearline/archived_file.rb', line 188 def size_check(file_size, manifest) if file_size != self.file_content.file_size manifest.add_log "recorded file length #{file_size} " + "does not match #{self.file_content.file_size} " + "reported by the file system on path: #{self.path}" end end |
#unique_sequence_processed?(key, manifest) ⇒ Boolean
202 203 204 205 206 207 208 209 210 211 |
# File 'lib/nearline/archived_file.rb', line 202 def unique_sequence_processed?(key,manifest) if self.file_content.unique_fingerprint?(key) self.file_content.fingerprint = key self.file_content.save! self.save! verify_content(manifest) return true end false end |
#verify_content(manifest) ⇒ Object
196 197 198 199 200 |
# File 'lib/nearline/archived_file.rb', line 196 def verify_content(manifest) unless (self.file_content.verified?) manifest.add_log "failed verification on path: #{self.path}" end end |