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
Class Method Summary collapse
Instance Method Summary collapse
- #before_destroy ⇒ Object
-
#clean_up_duplicate_content ⇒ Object
In the special case of an identical sequence existing, we can safely delete all related sequences and then destroy the file content object without the (far slower) orphan checking process.
- #guarantee_path ⇒ 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 ⇒ 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_information) ⇒ Object
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/nearline/archived_file.rb', line 15 def self.create_for(file_information) # The path doesn't actually exist and fails a File.lstat return nil if file_information.path_hash.nil? # We need to create a record for a link, directory or file archived_file = ArchivedFile.new( file_information.archived_file_parameters ) begin # Find a new link if(file_information.ftype == "link") archived_file.ftype_data = file_information.link_target archived_file.save! file_information.manifest.archived_files << archived_file return archived_file end # Find a new directory if (file_information.ftype=="directory") archived_file.save! file_information.manifest.archived_files << archived_file 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 = archived_file.persist(file_information.manifest) unless archived_file.nil? || archived_file.frozen? archived_file.save! file_information.manifest.archived_files << archived_file end return archived_file # TODO: block devices, ...? rescue msg = "#{file_information.file_path} failed to persist" puts msg file_information.manifest.add_log(msg) return nil end end |
Instance Method Details
#before_destroy ⇒ Object
110 111 112 |
# File 'lib/nearline/archived_file.rb', line 110 def before_destroy self.file_content.orphan_check if !self.file_content.nil? end |
#clean_up_duplicate_content ⇒ Object
In the special case of an identical sequence existing, we can safely delete all related sequences and then destroy the file content object without the (far slower) orphan checking process
191 192 193 194 |
# File 'lib/nearline/archived_file.rb', line 191 def clean_up_duplicate_content Sequence.delete_all "file_content_id = #{self.file_content.id}" self.file_content.destroy end |
#guarantee_path ⇒ Object
85 86 87 88 89 90 |
# File 'lib/nearline/archived_file.rb', line 85 def guarantee_path target_path = File.dirname(option_override(:path)) if (!File.exist? target_path) FileUtils.mkdir_p target_path end end |
#option_override(key) ⇒ Object
92 93 94 95 96 97 |
# File 'lib/nearline/archived_file.rb', line 92 def option_override(key) if (@options.has_key?(key)) return @options[key] end return self.send(key.to_s) end |
#orphan_check ⇒ Object
114 115 116 117 118 |
# File 'lib/nearline/archived_file.rb', line 114 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.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/nearline/archived_file.rb', line 127 def persist(manifest) seq = nil begin seq = read_file rescue error = "Got error '#{$!}' on path: #{self.path}" manifest.add_log error self.orphan_check return nil end size_check(seq.file_size, manifest) # Do we have a unique sequence? key = seq.fingerprint 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 ⇒ Object
150 151 152 153 154 155 156 157 158 |
# File 'lib/nearline/archived_file.rb', line 150 def read_file File.open(self.path, "rb") do |io| seq = FileSequencer.new(io, self.file_content) while (!io.eof) seq.persist_segment end return seq end end |
#replace_content(key) ⇒ Object
196 197 198 199 |
# File 'lib/nearline/archived_file.rb', line 196 def replace_content(key) self.file_content = FileContent.find_by_fingerprint(key) self.save! end |
#restore(*args) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/nearline/archived_file.rb', line 59 def restore(*args) @options = args. if (self.ftype == "link") guarantee_path File.symlink(self.ftype_data, option_override(:path)) # do not restore_metadata on a link return end if (self.ftype == "directory") FileUtils.mkdir_p option_override(:path) return end # ftype == "file" guarantee_path f = File.open(option_override(:path), "wb") self.file_content.restore_to(f) f.close return end |
#restore_metadata ⇒ Object
99 100 101 102 103 104 105 106 107 108 |
# File 'lib/nearline/archived_file.rb', line 99 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
160 161 162 163 164 165 166 167 |
# File 'lib/nearline/archived_file.rb', line 160 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}" self.file_content.file_size = file_size end end |
#unique_sequence_processed?(key, manifest) ⇒ Boolean
177 178 179 180 181 182 183 184 185 |
# File 'lib/nearline/archived_file.rb', line 177 def unique_sequence_processed?(key,manifest) if self.file_content.unique_fingerprint?(key) self.file_content.fingerprint = key self.save! verify_content(manifest) return true end false end |
#verify_content(manifest) ⇒ Object
169 170 171 172 173 174 175 |
# File 'lib/nearline/archived_file.rb', line 169 def verify_content(manifest) unless (self.file_content.verified?) manifest.add_log "file dropped on failed verification on path: #{self.path}" self.file_content.orphan_check self.destroy end end |