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


31
32
33
34
35
# 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

Instance Attribute Details

#digital_object_idString

Returns The digital object ID (druid).

Returns:

  • (String)

    The digital object ID (druid)


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

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


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

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


27
28
29
# File 'lib/moab/storage_object.rb', line 27

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)


125
126
127
# File 'lib/moab/storage_object.rb', line 125

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:


159
160
161
# File 'lib/moab/storage_object.rb', line 159

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


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

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


54
55
56
# File 'lib/moab/storage_object.rb', line 54

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


49
50
51
# File 'lib/moab/storage_object.rb', line 49

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


148
149
150
# File 'lib/moab/storage_object.rb', line 148

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


38
39
40
# File 'lib/moab/storage_object.rb', line 38

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:


177
178
179
180
181
182
183
184
185
186
187
# File 'lib/moab/storage_object.rb', line 177

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)

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


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

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_storage

This method returns an undefined value.

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


44
45
46
# File 'lib/moab/storage_object.rb', line 44

def initialize_storage
  @object_pathname.mkpath
end

#reconstruct_version(version_id, bag_dir)

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


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

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


213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/moab/storage_object.rb', line 213

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).


228
229
230
231
232
233
234
# File 'lib/moab/storage_object.rb', line 228

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:


114
115
116
117
118
119
120
# File 'lib/moab/storage_object.rb', line 114

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:

Raises:


194
195
196
197
198
# File 'lib/moab/storage_object.rb', line 194

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


166
167
168
169
170
171
172
# File 'lib/moab/storage_object.rb', line 166

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_storageVerificationResult

Return result of storage verification

Returns:


201
202
203
204
205
206
207
208
209
# File 'lib/moab/storage_object.rb', line 201

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


130
131
132
133
134
135
136
137
138
139
# File 'lib/moab/storage_object.rb', line 130

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:


142
143
144
# File 'lib/moab/storage_object.rb', line 142

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


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

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