class Moab::StorageObject

A class to represent a digital object’s repository storage location and methods for

Data Model

@note Copyright © 2012 by The Board of Trustees of the Leland Stanford Junior University.

All rights reserved.  See {file:LICENSE.rdoc} for details.

Attributes

digital_object_id[RW]

@return [String] The digital object ID (druid)

object_pathname[RW]

@return [Pathname] The location of the object’s storage home directory

storage_root[RW]

@return [Pathname] The location of the storage filesystem that contains (or will contain) the object

Public Class Methods

new(object_id, object_dir, mkpath = false) click to toggle source

@param object_id [String] The digital object identifier @param object_dir [Pathname,String] The location of the object’s storage home directory

# File lib/moab/storage_object.rb, line 31
def initialize(object_id, object_dir, mkpath = false)
  @digital_object_id = object_id
  @object_pathname = Pathname.new(object_dir)
  initialize_storage if mkpath
end
version_dirname(version_id) click to toggle source

@api external @param version_id [Integer] The version identifier of an object version @return [String] The directory name of the version, relative to the digital object home directory (e.g v0002)

# File lib/moab/storage_object.rb, line 126
def self.version_dirname(version_id)
  format('v%04d', version_id)
end

Public Instance Methods

current_version() click to toggle source

@return [StorageObjectVersion] The most recent version in the storage object

# File lib/moab/storage_object.rb, line 160
def current_version
  storage_object_version(current_version_id)
end
current_version_id() click to toggle source

@api external @return [Integer] The identifier of the latest version of this object, or 0 if no versions exist

# File lib/moab/storage_object.rb, line 155
def current_version_id
  @current_version_id ||= version_id_list.last || 0
end
deposit_bag_pathname() click to toggle source

@return [Pathname] The absolute location of this object’s deposit bag

# File lib/moab/storage_object.rb, line 54
def deposit_bag_pathname
  deposit_home.join(StorageServices.deposit_branch(digital_object_id))
end
deposit_home() click to toggle source

@return [Pathname] The absolute location of the area in which bags are deposited

# File lib/moab/storage_object.rb, line 49
def deposit_home
  storage_root.join(StorageServices.deposit_trunk)
end
empty?() click to toggle source

@return [Boolean] true if there are no versions yet in this object

# File lib/moab/storage_object.rb, line 149
def empty?
  version_id_list.empty?
end
exist?() click to toggle source

@return [Boolean] true if the object’s storage directory exists

# File lib/moab/storage_object.rb, line 38
def exist?
  @object_pathname.exist?
end
find_object_version(version_id = nil) click to toggle source

@api external @param version_id [Integer] The existing version to return. If nil, return latest version @return [StorageObjectVersion] The representation of an existing version’s storage area

# File lib/moab/storage_object.rb, line 178
def find_object_version(version_id = nil)
  current = current_version_id
  case version_id
  when nil
    StorageObjectVersion.new(self, current)
  when 1..current
    StorageObjectVersion.new(self, version_id)
  else
    raise(MoabRuntimeError, "Version ID #{version_id} does not exist")
  end
end
ingest_bag(bag_dir = deposit_bag_pathname, use_links: true) click to toggle source

@api external @param bag_dir [Pathname,String] The location of the bag to be ingested @param use_links [Boolean] If true, use hard links; if false, make copies @return [void] Ingest a new object version contained in a bag into this objects storage area @example {include:file:spec/features/storage/ingest_spec.rb}

# File lib/moab/storage_object.rb, line 63
def ingest_bag(bag_dir = deposit_bag_pathname, use_links: true)
  bag_dir = Pathname(bag_dir)
  current_version = StorageObjectVersion.new(self, current_version_id)
  current_inventory = current_version.file_inventory('version')
  new_version = StorageObjectVersion.new(self, current_version_id + 1)
  if FileInventory.xml_pathname_exist?(bag_dir, 'version')
    new_inventory = FileInventory.read_xml_file(bag_dir, 'version')
  elsif current_version.version_id == 0
    new_inventory = versionize_bag(bag_dir, current_version, new_version)
  end
  validate_new_inventory(new_inventory)
  new_version.ingest_bag_data(bag_dir, use_links: use_links)
  new_version.update_catalog(current_version.signature_catalog, new_inventory)
  new_version.generate_differences_report(current_inventory, new_inventory)
  new_version.generate_manifest_inventory
  new_version
end
initialize_storage() click to toggle source

@api external @return [void] Create the directory for the digital object home unless it already exists

# File lib/moab/storage_object.rb, line 44
def initialize_storage
  @object_pathname.mkpath
end
reconstruct_version(version_id, bag_dir) click to toggle source

@api external @param version_id [Integer] The version identifier of the object version to be disseminated @param bag_dir [Pathname,String] The location of the bag to be created @return [void] Reconstruct an object version and package it in a bag for dissemination @example {include:file:spec/features/storage/reconstruct_spec.rb}

# File lib/moab/storage_object.rb, line 105
def reconstruct_version(version_id, bag_dir)
  storage_version = StorageObjectVersion.new(self, version_id)
  version_inventory = storage_version.file_inventory('version')
  signature_catalog = storage_version.signature_catalog
  bagger = Bagger.new(version_inventory, signature_catalog, bag_dir)
  bagger.fill_bag(:reconstructor, @object_pathname)
end
restore_object(recovery_path) click to toggle source

@param recovery_path [Pathname, String] The location of the recovered object versions @return [Boolean] Restore all recovered versions to online storage and verify results

# File lib/moab/storage_object.rb, line 214
def restore_object(recovery_path)
  timestamp = Time.now
  recovery_object = StorageObject.new(@digital_object_id, recovery_path, false)
  recovery_object.versions.each do |recovery_version|
    version_id = recovery_version.version_id
    storage_version = storage_object_version(version_id)
    # rename/save the original
    storage_version.deactivate(timestamp)
    # copy the recovered version into place
    FileUtils.cp_r(recovery_version.version_pathname.to_s, storage_version.version_pathname.to_s)
  end
  self
end
size() click to toggle source

@return [Integer] the size occupied on disk by the storage object, in bytes. this is the entire moab (all versions).

# File lib/moab/storage_object.rb, line 229
def size
  size = 0
  Find.find(object_pathname) do |path|
    size += FileTest.size(path) unless FileTest.directory?(path)
  end
  size
end
storage_filepath(catalog_filepath) click to toggle source

@param [String] catalog_filepath The object-relative path of the file @return [Pathname] The absolute storage path of the file, including the object’s home directory

# File lib/moab/storage_object.rb, line 115
def storage_filepath(catalog_filepath)
  storage_filepath = @object_pathname.join(catalog_filepath)
  errmsg = "#{catalog_filepath} missing from storage location #{storage_filepath}"
  raise FileNotFoundException, errmsg unless storage_filepath.exist?

  storage_filepath
end
storage_object_version(version_id) click to toggle source

@api external @param version_id [Integer] The version to return. OK if version does not exist @return [StorageObjectVersion] The representation of a specified version.

  • Version 0 is a special case used to generate empty manifests

  • Current version + 1 is used for creation of a new version

# File lib/moab/storage_object.rb, line 195
def storage_object_version(version_id)
  raise(MoabRuntimeError, 'Version ID not specified') unless version_id

  StorageObjectVersion.new(self, version_id)
end
validate_new_inventory(version_inventory) click to toggle source

@api internal @param version_inventory [FileInventory] The inventory of the object version to be ingested @return [Boolean] Tests whether the new version number is one higher than the current version number

# File lib/moab/storage_object.rb, line 167
def validate_new_inventory(version_inventory)
  if version_inventory.version_id != (current_version_id + 1)
    raise(MoabRuntimeError, "version mismatch - current: #{current_version_id} new: #{version_inventory.version_id}")
  end

  true
end
verify_object_storage() click to toggle source

@return [VerificationResult] Return result of storage verification

# File lib/moab/storage_object.rb, line 202
def verify_object_storage
  result = VerificationResult.new(digital_object_id)
  version_list.each do |version|
    result.subentities << version.verify_version_storage
  end
  result.subentities << current_version.verify_signature_catalog
  result.verified = result.subentities.all?(&:verified)
  result
end
version_id_list() click to toggle source

@return [Array<Integer>] The list of all version ids for this object

# File lib/moab/storage_object.rb, line 131
def version_id_list
  list = []
  return list unless @object_pathname.exist?

  @object_pathname.children.each do |dirname|
    vnum = dirname.basename.to_s
    list << vnum[1..].to_i if vnum =~ /^v(\d+)$/
  end
  list.sort
end
version_list() click to toggle source

@return [Array<StorageObjectVersion>] The list of all versions in this storage object

# File lib/moab/storage_object.rb, line 143
def version_list
  version_id_list.collect { |id| storage_object_version(id) }
end
Also aliased as: versions
versionize_bag(bag_dir, current_version, new_version) click to toggle source

@api internal @param bag_dir [Pathname] The location of the bag to be ingested @param current_version The current latest version of the object @param new_version [StorageObjectVersion] The version to be added @return [FileInventory] The file inventory of the specified type for this version

# File lib/moab/storage_object.rb, line 86
def versionize_bag(bag_dir, current_version, new_version)
  new_inventory = FileInventory.new(
    type: 'version',
    digital_object_id: @digital_object_id,
    version_id: new_version.version_id,
    inventory_datetime: Time.now
  )
  new_inventory.inventory_from_bagit_bag(bag_dir)
  new_inventory.write_xml_file(bag_dir)
  version_additions = current_version.signature_catalog.version_additions(new_inventory)
  version_additions.write_xml_file(bag_dir)
  new_inventory
end
versions()
Alias for: version_list