Class: Moab::StorageObjectVersion
- Inherits:
-
Object
- Object
- Moab::StorageObjectVersion
- Defined in:
- lib/moab/storage_object_version.rb
Overview
Copyright © 2012 by The Board of Trustees of the Leland Stanford Junior University. All rights reserved. See LICENSE for details.
A class to represent a version subdirectory within an object’s home directory in preservation storage
Data Model
-
StorageRepository = represents a digital object repository storage node
-
StorageServices = supports application layer access to the repository’s objects, data, and metadata
-
StorageObject = represents a digital object’s repository storage location and ingest/dissemination methods
-
StorageObjectVersion [1..*] = represents a version subdirectory within an object’s home directory
-
Bagger [1] = utility for creating bagit packages for ingest or dissemination
-
-
-
Instance Attribute Summary collapse
-
#inventory_cache ⇒ Hash<FileInventory>
Cached copies of versionInventory, versionAdditions, or manifestInventory.
-
#storage_object ⇒ Pathname
The location of the object’s home directory.
-
#version_id ⇒ Integer
The ordinal version number.
-
#version_name ⇒ String
The “v0001” directory name derived from the version id.
-
#version_pathname ⇒ Pathname
The location of the version inside the home directory.
Instance Method Summary collapse
-
#composite_key ⇒ String
The unique identifier concatenating digital object id with version id.
-
#deactivate(timestamp) ⇒ null
Deactivate this object version by moving it to another directory.
-
#exist? ⇒ Boolean
True if the object version directory exists.
-
#file_category_pathname(file_category) ⇒ Pathname
Pathname object containing this version’s storage home for the specified file category.
-
#file_inventory(type) ⇒ FileInventory
The file inventory of the specified type for this version.
-
#file_pathname(file_category, file_id) ⇒ Pathname
Pathname object containing this version’s storage path for the specified file.
-
#find_filepath(file_category, file_id) ⇒ Pathname
Pathname object containing the full path for the specified file.
-
#find_filepath_using_signature(_file_category, file_signature) ⇒ Pathname
Pathname object containing the full path for the specified file.
-
#find_signature(file_category, file_id) ⇒ FileSignature
Signature of the specified file.
-
#generate_differences_report(old_inventory, new_inventory) ⇒ void
Generate a file inventory differences report and save to disk.
-
#generate_manifest_inventory ⇒ void
Examine the version’s directory and create/serialize a FileInventory containing the manifest files.
-
#ingest_bag_data(bag_dir) ⇒ void
Create the version subdirectory and move files into it.
-
#ingest_dir(source_dir, target_dir, use_links = true) ⇒ void
Recursively link or copy the source directory contents to the target directory.
-
#ingest_file(source_file, target_dir, use_links = true) ⇒ void
Link or copy the specified file from source location to the version directory.
-
#initialize(storage_object, version_id) ⇒ StorageObjectVersion
constructor
A new instance of StorageObjectVersion.
-
#signature_catalog ⇒ SignatureCatalog
The signature catalog of the digital object as of this version.
-
#update_catalog(signature_catalog, new_inventory) ⇒ void
Updates the catalog to include newly added files, then saves it to disk.
-
#verify_manifest_inventory ⇒ VerificationResult
Return true if the manifest inventory matches the actual files.
- #verify_signature_catalog ⇒ VerificationResult
-
#verify_version_additions ⇒ Boolean
Returns true if files in data folder match files listed in version addtions inventory.
-
#verify_version_inventory ⇒ Boolean
True if files & signatures listed in version inventory can all be found.
-
#verify_version_storage ⇒ VerificationResult
Return result of testing correctness of version manifests.
Constructor Details
#initialize(storage_object, version_id) ⇒ StorageObjectVersion
Returns a new instance of StorageObjectVersion.
30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/moab/storage_object_version.rb', line 30 def initialize(storage_object, version_id) if version_id.is_a?(Integer) @version_id = version_id elsif version_id.is_a?(String) && version_id =~ /^v(\d+)$/ @version_id = version_id.sub(/^v/, '').to_i else raise "version_id (#{version_id}) is not in a recognized format" end @version_name = StorageObject.version_dirname(@version_id) @version_pathname = storage_object.object_pathname.join(@version_name) @storage_object = storage_object @inventory_cache = {} end |
Instance Attribute Details
#inventory_cache ⇒ Hash<FileInventory>
Returns Cached copies of versionInventory, versionAdditions, or manifestInventory.
26 27 28 |
# File 'lib/moab/storage_object_version.rb', line 26 def inventory_cache @inventory_cache end |
#storage_object ⇒ Pathname
Returns The location of the object’s home directory.
23 24 25 |
# File 'lib/moab/storage_object_version.rb', line 23 def storage_object @storage_object end |
#version_id ⇒ Integer
Returns The ordinal version number.
14 15 16 |
# File 'lib/moab/storage_object_version.rb', line 14 def version_id @version_id end |
#version_name ⇒ String
Returns The “v0001” directory name derived from the version id.
17 18 19 |
# File 'lib/moab/storage_object_version.rb', line 17 def version_name @version_name end |
#version_pathname ⇒ Pathname
Returns The location of the version inside the home directory.
20 21 22 |
# File 'lib/moab/storage_object_version.rb', line 20 def version_pathname @version_pathname end |
Instance Method Details
#composite_key ⇒ String
Returns The unique identifier concatenating digital object id with version id.
45 46 47 |
# File 'lib/moab/storage_object_version.rb', line 45 def composite_key @storage_object.digital_object_id + '-' + StorageObject.version_dirname(@version_id) end |
#deactivate(timestamp) ⇒ null
Returns Deactivate this object version by moving it to another directory. (Used by restore operation).
322 323 324 325 326 327 328 |
# File 'lib/moab/storage_object_version.rb', line 322 def deactivate() return unless @version_pathname.exist? = @version_pathname.parent.join(.utc.iso8601.gsub(/[-:]/, '')) .mkpath demote_pathame = .join(@version_pathname.basename) @version_pathname.rename(demote_pathame) end |
#exist? ⇒ Boolean
Returns true if the object version directory exists.
50 51 52 |
# File 'lib/moab/storage_object_version.rb', line 50 def exist? @version_pathname.exist? end |
#file_category_pathname(file_category) ⇒ Pathname
Returns Pathname object containing this version’s storage home for the specified file category.
97 98 99 100 101 102 103 |
# File 'lib/moab/storage_object_version.rb', line 97 def file_category_pathname(file_category) if file_category =~ /manifest/ @version_pathname.join('manifests') else @version_pathname.join('data', file_category) end end |
#file_inventory(type) ⇒ FileInventory
Returns The file inventory of the specified type for this version.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/moab/storage_object_version.rb', line 109 def file_inventory(type) if version_id > 0 return @inventory_cache[type] if @inventory_cache.key?(type) @inventory_cache[type] = FileInventory.read_xml_file(@version_pathname.join('manifests'), type) else groups = %w[content metadata].collect { |id| FileGroup.new(:group_id => id) } FileInventory.new( :type => 'version', :digital_object_id => @storage_object.digital_object_id, :version_id => @version_id, :groups => groups ) end end |
#file_pathname(file_category, file_id) ⇒ Pathname
Returns Pathname object containing this version’s storage path for the specified file.
91 92 93 |
# File 'lib/moab/storage_object_version.rb', line 91 def file_pathname(file_category, file_id) file_category_pathname(file_category).join(file_id) end |
#find_filepath(file_category, file_id) ⇒ Pathname
Returns Pathname object containing the full path for the specified file.
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/moab/storage_object_version.rb', line 68 def find_filepath(file_category, file_id) this_version_filepath = file_pathname(file_category, file_id) return this_version_filepath if this_version_filepath.exist? if file_category == 'manifest' msg = "manifest file #{file_id} not found for #{@storage_object.digital_object_id} - #{@version_id}" raise FileNotFoundException, msg end file_signature = file_inventory('version').file_signature(file_category, file_id) catalog_filepath = signature_catalog.catalog_filepath(file_signature) @storage_object.storage_filepath(catalog_filepath) end |
#find_filepath_using_signature(_file_category, file_signature) ⇒ Pathname
Returns Pathname object containing the full path for the specified file.
83 84 85 86 |
# File 'lib/moab/storage_object_version.rb', line 83 def find_filepath_using_signature(_file_category, file_signature) catalog_filepath = signature_catalog.catalog_filepath(file_signature) @storage_object.storage_filepath(catalog_filepath) end |
#find_signature(file_category, file_id) ⇒ FileSignature
Returns signature of the specified file.
57 58 59 60 61 62 63 |
# File 'lib/moab/storage_object_version.rb', line 57 def find_signature(file_category, file_id) if file_category =~ /manifest/ file_inventory('manifests').file_signature('manifests', file_id) else file_inventory('version').file_signature(file_category, file_id) end end |
#generate_differences_report(old_inventory, new_inventory) ⇒ void
This method returns an undefined value.
Returns generate a file inventory differences report and save to disk.
190 191 192 193 |
# File 'lib/moab/storage_object_version.rb', line 190 def generate_differences_report(old_inventory, new_inventory) differences = FileInventoryDifference.new.compare(old_inventory, new_inventory) differences.write_xml_file(@version_pathname.join('manifests')) end |
#generate_manifest_inventory ⇒ void
This method returns an undefined value.
Returns examine the version’s directory and create/serialize a FileInventory containing the manifest files.
197 198 199 200 201 202 203 204 205 206 |
# File 'lib/moab/storage_object_version.rb', line 197 def generate_manifest_inventory manifest_inventory = FileInventory.new( :type => 'manifests', :digital_object_id => @storage_object.digital_object_id, :version_id => @version_id ) pathname = @version_pathname.join('manifests') manifest_inventory.groups << FileGroup.new(:group_id => 'manifests').group_from_directory(pathname, false) manifest_inventory.write_xml_file(pathname) end |
#ingest_bag_data(bag_dir) ⇒ void
This method returns an undefined value.
Returns Create the version subdirectory and move files into it.
137 138 139 140 141 142 143 144 |
# File 'lib/moab/storage_object_version.rb', line 137 def ingest_bag_data(bag_dir) raise "Version already exists: #{@version_pathname}" if @version_pathname.exist? @version_pathname.join('manifests').mkpath bag_dir = Pathname(bag_dir) ingest_dir(bag_dir.join('data'), @version_pathname.join('data')) ingest_file(bag_dir.join(FileInventory.xml_filename('version')), @version_pathname.join('manifests')) ingest_file(bag_dir.join(FileInventory.xml_filename('additions')), @version_pathname.join('manifests')) end |
#ingest_dir(source_dir, target_dir, use_links = true) ⇒ void
This method returns an undefined value.
Returns recursively link or copy the source directory contents to the target directory.
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/moab/storage_object_version.rb', line 151 def ingest_dir(source_dir, target_dir, use_links = true) raise "cannot copy - target already exists: #{target_dir.}" if target_dir.exist? target_dir.mkpath source_dir.children.each do |child| if child.directory? ingest_dir(child, target_dir.join(child.basename), use_links) else ingest_file(child, target_dir, use_links) end end end |
#ingest_file(source_file, target_dir, use_links = true) ⇒ void
This method returns an undefined value.
Returns link or copy the specified file from source location to the version directory.
168 169 170 171 172 173 174 |
# File 'lib/moab/storage_object_version.rb', line 168 def ingest_file(source_file, target_dir, use_links = true) if use_links FileUtils.link(source_file.to_s, target_dir.to_s) #, :force => true) else FileUtils.copy(source_file.to_s, target_dir.to_s) end end |
#signature_catalog ⇒ SignatureCatalog
Returns The signature catalog of the digital object as of this version.
126 127 128 129 130 131 132 |
# File 'lib/moab/storage_object_version.rb', line 126 def signature_catalog if version_id > 0 SignatureCatalog.read_xml_file(@version_pathname.join('manifests')) else SignatureCatalog.new(:digital_object_id => @storage_object.digital_object_id) end end |
#update_catalog(signature_catalog, new_inventory) ⇒ void
This method returns an undefined value.
Returns Updates the catalog to include newly added files, then saves it to disk.
181 182 183 184 |
# File 'lib/moab/storage_object_version.rb', line 181 def update_catalog(signature_catalog, new_inventory) signature_catalog.update(new_inventory, @version_pathname.join('data')) signature_catalog.write_xml_file(@version_pathname.join('manifests')) end |
#verify_manifest_inventory ⇒ VerificationResult
Return true if the manifest inventory matches the actual files
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/moab/storage_object_version.rb', line 219 def verify_manifest_inventory # read/parse manifestInventory.xml result = VerificationResult.new("manifest_inventory") manifest_inventory = file_inventory('manifests') result.subentities << VerificationResult.verify_value('composite_key', composite_key, manifest_inventory.composite_key) result.subentities << VerificationResult.verify_truth('manifests_group', !manifest_inventory.group_empty?('manifests')) # measure the manifest signatures of the files in the directory (excluding manifestInventory.xml) directory_inventory = FileInventory.new.inventory_from_directory(@version_pathname.join('manifests'), 'manifests') directory_inventory.digital_object_id = storage_object.digital_object_id directory_group = directory_inventory.group('manifests') directory_group.remove_file_having_path("manifestInventory.xml") # compare the measured signatures against the values in manifestInventory.xml diff = FileInventoryDifference.new diff.compare(manifest_inventory, directory_inventory) compare_result = VerificationResult.new('file_differences') compare_result.verified = (diff.difference_count == 0) compare_result.details = diff.differences_detail result.subentities << compare_result result.verified = result.subentities.all?(&:verified) result end |
#verify_signature_catalog ⇒ VerificationResult
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/moab/storage_object_version.rb', line 242 def verify_signature_catalog result = VerificationResult.new("signature_catalog") signature_catalog = self.signature_catalog result.subentities << VerificationResult.verify_value('signature_key', composite_key, signature_catalog.composite_key) found = 0 missing = [] object_pathname = storage_object.object_pathname signature_catalog.entries.each do |catalog_entry| storage_location = object_pathname.join(catalog_entry.storage_path) if storage_location.exist? found += 1 else missing << storage_location.to_s end end file_result = VerificationResult.new("storage_location") file_result.verified = (found == signature_catalog.file_count) file_result.details = { 'expected' => signature_catalog.file_count, 'found' => found } file_result.details['missing'] = missing unless missing.empty? result.subentities << file_result result.verified = result.subentities.all?(&:verified) result end |
#verify_version_additions ⇒ Boolean
Returns true if files in data folder match files listed in version addtions inventory
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/moab/storage_object_version.rb', line 304 def verify_version_additions result = VerificationResult.new("version_additions") version_additions = file_inventory('additions') result.subentities << VerificationResult.verify_value('composite_key', composite_key, version_additions.composite_key) data_directory = @version_pathname.join('data') directory_inventory = FileInventory.new(:type => 'directory').inventory_from_directory(data_directory) diff = FileInventoryDifference.new diff.compare(version_additions, directory_inventory) compare_result = VerificationResult.new('file_differences') compare_result.verified = (diff.difference_count == 0) compare_result.details = diff.differences_detail result.subentities << compare_result result.verified = result.subentities.all?(&:verified) result end |
#verify_version_inventory ⇒ Boolean
Returns true if files & signatures listed in version inventory can all be found.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/moab/storage_object_version.rb', line 270 def verify_version_inventory result = VerificationResult.new("version_inventory") version_inventory = file_inventory('version') result.subentities << VerificationResult.verify_value('inventory_key', composite_key, version_inventory.composite_key) signature_catalog = self.signature_catalog result.subentities << VerificationResult.verify_value('signature_key', composite_key, signature_catalog.composite_key) found = 0 missing = [] version_inventory.groups.each do |group| group.files.each do |file| file.instances.each do |instance| relative_path = File.join(group.group_id, instance.path) catalog_entry = signature_catalog.signature_hash[file.signature] if !catalog_entry.nil? found += 1 else missing << relative_path.to_s end end end end file_result = VerificationResult.new("catalog_entry") file_result.verified = (found == version_inventory.file_count) file_result.details = { 'expected' => version_inventory.file_count, 'found' => found } file_result.details['missing'] = missing unless missing.empty? result.subentities << file_result result.verified = result.subentities.all?(&:verified) result end |
#verify_version_storage ⇒ VerificationResult
Return result of testing correctness of version manifests
209 210 211 212 213 214 215 216 |
# File 'lib/moab/storage_object_version.rb', line 209 def verify_version_storage result = VerificationResult.new(composite_key) result.subentities << verify_manifest_inventory result.subentities << verify_version_inventory result.subentities << verify_version_additions result.verified = result.subentities.all?(&:verified) result end |