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



33
34
35
36
37
# File 'lib/moab/storage_object.rb', line 33

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)



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

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



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

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



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

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)
  ("v%04d" % version_id)
end

Instance Method Details

#current_versionStorageObjectVersion

Returns The most recent version in the storage object.

Returns:



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

def current_version
  self.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



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

def current_version_id
  return @current_version_id unless @current_version_id.nil?
  list = self.version_id_list
  version_id = list.empty? ? 0 : list.last
  @current_version_id = version_id
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



56
57
58
# File 'lib/moab/storage_object.rb', line 56

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



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

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



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

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



40
41
42
# File 'lib/moab/storage_object.rb', line 40

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:



180
181
182
183
184
185
186
187
188
189
190
# File 'lib/moab/storage_object.rb', line 180

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



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

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.



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

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



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

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



218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/moab/storage_object.rb', line 218

def restore_object(recovery_path)
  timestamp = Time.now
  recovery_object = StorageObject.new(@digital_object_id, recovery_path, mkpath=false)
  recovery_object.versions.each do |recovery_version|
    version_id = recovery_version.version_id
    storage_version = self.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

#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:



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

def storage_filepath(catalog_filepath)
  storage_filepath = @object_pathname.join(catalog_filepath)
  raise FileNotFoundException, "#{catalog_filepath} missing from storage location #{storage_filepath}" 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:



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

def storage_object_version(version_id)
  if version_id
    StorageObjectVersion.new(self,version_id)
  else
    raise "Version ID not specified"
  end
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



170
171
172
173
174
175
# File 'lib/moab/storage_object.rb', line 170

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 verfication

Returns:



206
207
208
209
210
211
212
213
214
# File 'lib/moab/storage_object.rb', line 206

def verify_object_storage
  result = VerificationResult.new(digital_object_id)
  self.version_list.each do |version|
    result.subentities << version.verify_version_storage
  end
  result.subentities << current_version.verify_signature_catalog
  result.verified = result.subentities.all?{|entity| entity.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
140
# File 'lib/moab/storage_object.rb', line 130

def version_id_list
  list = Array.new
  return list unless @object_pathname.exist?
  @object_pathname.children.each do |dirname|
    vnum = dirname.basename.to_s
    if vnum.match /^v(\d+)$/
      list << vnum[1..-1].to_i
    end
  end
  list.sort
end

#version_listArray<StorageObjectVersion> Also known as: versions

Returns The list of all versions in this storage object.

Returns:



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

def version_list
  version_id_list.collect{|id| self.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



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

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