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 ⇒ Boolean
Return true if the manifest inventory matches the actual files.
- #verify_signature_catalog ⇒ Object
-
#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.
35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/moab/storage_object_version.rb', line 35 def initialize(storage_object, version_id) if version_id.is_a?(Integer) @version_id = version_id elsif version_id.is_a?(String) and version_id.match /^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 = Hash.new end |
Instance Attribute Details
#inventory_cache ⇒ Hash<FileInventory>
Returns Cached copies of versionInventory, versionAdditions, or manifestInventory.
31 32 33 |
# File 'lib/moab/storage_object_version.rb', line 31 def inventory_cache @inventory_cache end |
#storage_object ⇒ Pathname
Returns The location of the object’s home directory.
28 29 30 |
# File 'lib/moab/storage_object_version.rb', line 28 def storage_object @storage_object end |
#version_id ⇒ Integer
Returns The ordinal version number.
19 20 21 |
# File 'lib/moab/storage_object_version.rb', line 19 def version_id @version_id end |
#version_name ⇒ String
Returns The “v0001” directory name derived from the version id.
22 23 24 |
# File 'lib/moab/storage_object_version.rb', line 22 def version_name @version_name end |
#version_pathname ⇒ Pathname
Returns The location of the version inside the home directory.
25 26 27 |
# File 'lib/moab/storage_object_version.rb', line 25 def version_pathname @version_pathname end |
Instance Method Details
#composite_key ⇒ String
Returns The unique identifier concatenating digital object id with version id.
50 51 52 |
# File 'lib/moab/storage_object_version.rb', line 50 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 329 |
# File 'lib/moab/storage_object_version.rb', line 322 def deactivate() if @version_pathname.exist? = @version_pathname.parent.join(.utc.iso8601.gsub(/[-:]/,'')) .mkpath demote_pathame = .join(@version_pathname.basename) @version_pathname.rename(demote_pathame) end end |
#exist? ⇒ Boolean
Returns true if the object version directory exists.
55 56 57 |
# File 'lib/moab/storage_object_version.rb', line 55 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.
99 100 101 102 103 104 105 |
# File 'lib/moab/storage_object_version.rb', line 99 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.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/moab/storage_object_version.rb', line 111 def file_inventory(type) if version_id > 0 return @inventory_cache[type] if @inventory_cache.has_key?(type) @inventory_cache[type] = FileInventory.read_xml_file(@version_pathname.join('manifests'), type) else groups = ['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.
93 94 95 |
# File 'lib/moab/storage_object_version.rb', line 93 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.
73 74 75 76 77 78 79 80 |
# File 'lib/moab/storage_object_version.rb', line 73 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? raise FileNotFoundException, "manifest file #{file_id} not found for #{@storage_object.digital_object_id} - #{@version_id}" if file_category == 'manifest' 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.
85 86 87 88 |
# File 'lib/moab/storage_object_version.rb', line 85 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.
62 63 64 65 66 67 68 |
# File 'lib/moab/storage_object_version.rb', line 62 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.
192 193 194 195 |
# File 'lib/moab/storage_object_version.rb', line 192 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.
199 200 201 202 203 204 205 206 |
# File 'lib/moab/storage_object_version.rb', line 199 def generate_manifest_inventory manifest_inventory = FileInventory.new( :type=>'manifests', :digital_object_id=>@storage_object.digital_object_id, :version_id=>@version_id) manifest_inventory.groups << FileGroup.new(:group_id=>'manifests').group_from_directory(@version_pathname.join('manifests'), recursive=false) manifest_inventory.write_xml_file(@version_pathname.join('manifests')) end |
#ingest_bag_data(bag_dir) ⇒ void
This method returns an undefined value.
Returns Create the version subdirectory and move files into it.
139 140 141 142 143 144 145 146 |
# File 'lib/moab/storage_object_version.rb', line 139 def ingest_bag_data(bag_dir) raise "Version already exists: #{@version_pathname.to_s}" 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.
153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/moab/storage_object_version.rb', line 153 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.
170 171 172 173 174 175 176 |
# File 'lib/moab/storage_object_version.rb', line 170 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.
128 129 130 131 132 133 134 |
# File 'lib/moab/storage_object_version.rb', line 128 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.
183 184 185 186 |
# File 'lib/moab/storage_object_version.rb', line 183 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 ⇒ Boolean
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 = self.file_inventory('manifests') result.subentities << VerificationResult.verify_value('composite_key',self.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?{|entity| entity.verified} result end |
#verify_signature_catalog ⇒ Object
241 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 |
# File 'lib/moab/storage_object_version.rb', line 241 def verify_signature_catalog result = VerificationResult.new("signature_catalog") signature_catalog =self.signature_catalog result.subentities << VerificationResult.verify_value('signature_key',self.composite_key,signature_catalog.composite_key) found = 0 missing = Array.new object_pathname = self.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?{|entity| entity.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 = self.file_inventory('additions') result.subentities << VerificationResult.verify_value('composite_key',self.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?{|entity| entity.verified} result end |
#verify_version_inventory ⇒ Boolean
Returns true if files & signatures listed in version inventory can all be found.
269 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 269 def verify_version_inventory result = VerificationResult.new("version_inventory") version_inventory = self.file_inventory('version') result.subentities << VerificationResult.verify_value('inventory_key',self.composite_key,version_inventory.composite_key) signature_catalog =self.signature_catalog result.subentities << VerificationResult.verify_value('signature_key',self.composite_key,signature_catalog.composite_key) found = 0 missing = Array.new 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?{|entity| entity.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(self.composite_key) result.subentities << self.verify_manifest_inventory result.subentities << self.verify_version_inventory result.subentities << self.verify_version_additions result.verified = result.subentities.all?{|entity| entity.verified} result end |