Class: Moab::StorageObject

Inherits:
Object
  • Object
show all
Defined in:
lib/moab/storage_object.rb

Overview

Note:

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 digital object’s repository storage location and methods for

  • packaging a bag for ingest of a new object version to the repository

  • ingesting a bag

  • disseminating a bag containing a reconstructed object version

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object_id, object_dir, mkpath = false) ⇒ StorageObject

Returns a new instance of StorageObject.

Parameters:

  • object_id (String)

    The digital object identifier

  • object_dir (Pathname, String)

    The location of the object’s storage home directory



29
30
31
32
33
# File 'lib/moab/storage_object.rb', line 29

def initialize(object_id, object_dir, mkpath = false)
  @digital_object_id = object_id
  @object_pathname = Pathname.new(object_dir)
  initialize_storage if mkpath
end

Instance Attribute Details

#digital_object_idString

Returns The digital object ID (druid).

Returns:

  • (String)

    The digital object ID (druid)



19
20
21
# File 'lib/moab/storage_object.rb', line 19

def digital_object_id
  @digital_object_id
end

#object_pathnamePathname

Returns The location of the object’s storage home directory.

Returns:

  • (Pathname)

    The location of the object’s storage home directory



22
23
24
# File 'lib/moab/storage_object.rb', line 22

def object_pathname
  @object_pathname
end

#storage_rootPathname

Returns The location of the storage filesystem that contains (or will contain) the object.

Returns:

  • (Pathname)

    The location of the storage filesystem that contains (or will contain) the object



25
26
27
# File 'lib/moab/storage_object.rb', line 25

def storage_root
  @storage_root
end

Class Method Details

.version_dirname(version_id) ⇒ String

Returns The directory name of the version, relative to the digital object home directory (e.g v0002).

Parameters:

  • version_id (Integer)

    The version identifier of an object version

Returns:

  • (String)

    The directory name of the version, relative to the digital object home directory (e.g v0002)



122
123
124
# File 'lib/moab/storage_object.rb', line 122

def self.version_dirname(version_id)
  format("v%04d", version_id)
end

Instance Method Details

#current_versionStorageObjectVersion

Returns The most recent version in the storage object.

Returns:



155
156
157
# File 'lib/moab/storage_object.rb', line 155

def current_version
  storage_object_version(current_version_id)
end

#current_version_idInteger

Returns The identifier of the latest version of this object, or 0 if no versions exist.

Returns:

  • (Integer)

    The identifier of the latest version of this object, or 0 if no versions exist



150
151
152
# File 'lib/moab/storage_object.rb', line 150

def current_version_id
  @current_version_id ||= version_id_list.last || 0
end

#deposit_bag_pathnamePathname

Returns The absolute location of this object’s deposit bag.

Returns:

  • (Pathname)

    The absolute location of this object’s deposit bag



52
53
54
# File 'lib/moab/storage_object.rb', line 52

def deposit_bag_pathname
  deposit_home.join(StorageServices.deposit_branch(digital_object_id))
end

#deposit_homePathname

Returns The absolute location of the area in which bags are deposited.

Returns:

  • (Pathname)

    The absolute location of the area in which bags are deposited



47
48
49
# File 'lib/moab/storage_object.rb', line 47

def deposit_home
  storage_root.join(StorageServices.deposit_trunk)
end

#empty?Boolean

Returns true if there are no versions yet in this object.

Returns:

  • (Boolean)

    true if there are no versions yet in this object



144
145
146
# File 'lib/moab/storage_object.rb', line 144

def empty?
  version_id_list.empty?
end

#exist?Boolean

Returns true if the object’s storage directory exists.

Returns:

  • (Boolean)

    true if the object’s storage directory exists



36
37
38
# File 'lib/moab/storage_object.rb', line 36

def exist?
  @object_pathname.exist?
end

#find_object_version(version_id = nil) ⇒ StorageObjectVersion

Returns The representation of an existing version’s storage area.

Parameters:

  • version_id (Integer) (defaults to: nil)

    The existing version to return. If nil, return latest version

Returns:



172
173
174
175
176
177
178
179
180
181
182
# File 'lib/moab/storage_object.rb', line 172

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 "Version ID #{version_id} does not exist"
  end
end

#ingest_bag(bag_dir = deposit_bag_pathname) ⇒ void

This method returns an undefined value.

Returns Ingest a new object version contained in a bag into this objects storage area.

Examples:


Parameters:

  • bag_dir (Pathname, String) (defaults to: deposit_bag_pathname)

    The location of the bag to be ingested



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/moab/storage_object.rb', line 60

def ingest_bag(bag_dir = deposit_bag_pathname)
  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)
  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_storagevoid

This method returns an undefined value.

Returns Create the directory for the digital object home unless it already exists.



42
43
44
# File 'lib/moab/storage_object.rb', line 42

def initialize_storage
  @object_pathname.mkpath
end

#reconstruct_version(version_id, bag_dir) ⇒ void

This method returns an undefined value.

Returns Reconstruct an object version and package it in a bag for dissemination.

Examples:


Parameters:

  • version_id (Integer)

    The version identifier of the object version to be disseminated

  • bag_dir (Pathname, String)

    The location of the bag to be created



102
103
104
105
106
107
108
# File 'lib/moab/storage_object.rb', line 102

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) ⇒ Boolean

Returns Restore all recovered versions to online storage and verify results.

Parameters:

  • recovery_path (Pathname, String)

    The location of the recovered object versions

Returns:

  • (Boolean)

    Restore all recovered versions to online storage and verify results



207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/moab/storage_object.rb', line 207

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

#sizeInteger

Returns the size occupied on disk by the storage object, in bytes. this is the entire moab (all versions).

Returns:

  • (Integer)

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



222
223
224
225
226
227
228
# File 'lib/moab/storage_object.rb', line 222

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) ⇒ Pathname

Returns The absolute storage path of the file, including the object’s home directory.

Parameters:

  • catalog_filepath (String)

    The object-relative path of the file

Returns:

  • (Pathname)

    The absolute storage path of the file, including the object’s home directory

Raises:



112
113
114
115
116
117
# File 'lib/moab/storage_object.rb', line 112

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) ⇒ StorageObjectVersion

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

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

Parameters:

  • version_id (Integer)

    The version to return. OK if version does not exist

Returns:



189
190
191
192
# File 'lib/moab/storage_object.rb', line 189

def storage_object_version(version_id)
  raise "Version ID not specified" unless version_id
  StorageObjectVersion.new(self, version_id)
end

#validate_new_inventory(version_inventory) ⇒ Boolean

Returns Tests whether the new version number is one higher than the current version number.

Parameters:

  • version_inventory (FileInventory)

    The inventory of the object version to be ingested

Returns:

  • (Boolean)

    Tests whether the new version number is one higher than the current version number



162
163
164
165
166
167
# File 'lib/moab/storage_object.rb', line 162

def validate_new_inventory(version_inventory)
  if version_inventory.version_id != (current_version_id + 1)
    raise "version mismatch - current: #{current_version_id} new: #{version_inventory.version_id}"
  end
  true
end

#verify_object_storageVerificationResult

Return result of storage verification

Returns:



195
196
197
198
199
200
201
202
203
# File 'lib/moab/storage_object.rb', line 195

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_listArray<Integer>

Returns The list of all version ids for this object.

Returns:

  • (Array<Integer>)

    The list of all version ids for this object



127
128
129
130
131
132
133
134
135
# File 'lib/moab/storage_object.rb', line 127

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..-1].to_i if vnum =~ /^v(\d+)$/
  end
  list.sort
end

#version_listArray<StorageObjectVersion> Also known as: versions

Returns The list of all versions in this storage object.

Returns:



138
139
140
# File 'lib/moab/storage_object.rb', line 138

def version_list
  version_id_list.collect { |id| storage_object_version(id) }
end

#versionize_bag(bag_dir, current_version, new_version) ⇒ FileInventory

Returns The file inventory of the specified type for this version.

Parameters:

  • bag_dir (Pathname)

    The location of the bag to be ingested

  • current_version (StorageObjectVersion)

    The current latest version of the object

  • new_version (StorageObjectVersion)

    The version to be added

Returns:

  • (FileInventory)

    The file inventory of the specified type for this version



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/moab/storage_object.rb', line 83

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