Class: Dor::DigitalStacksService

Inherits:
Object
  • Object
show all
Defined in:
lib/dor/services/digital_stacks_service.rb

Class Method Summary collapse

Class Method Details

.copy_file(workspace_pathname, stacks_pathname, moab_signature) ⇒ Boolean

Copy a file to stacks, but only if it does not yet exist with the expected signature

Parameters:

  • workspace_pathname (Pathname)

    The location of the file in the DOR workspace

  • stacks_pathname (Pathname)

    The location of the file in the stacks

  • moab_signature (Moab::FileSignature)

    The fixity values of the file

Returns:

  • (Boolean)

    true if file copied, false otherwise


103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/dor/services/digital_stacks_service.rb', line 103

def self.copy_file(workspace_pathname, stacks_pathname, moab_signature)
  if stacks_pathname.exist?
    file_signature = Moab::FileSignature.new.signature_from_file(stacks_pathname)
    stacks_pathname.delete if (file_signature != moab_signature)
  end
  unless stacks_pathname.exist?
    stacks_pathname.parent.mkpath
    FileUtils.cp workspace_pathname.to_s, stacks_pathname.to_s
    return true
  end
  return false
end

.delete_file(file_pathname, moab_signature) ⇒ Boolean

Delete a file, but only if it exists and matches the expected signature

Parameters:

  • file_pathname (Pathname)

    The location of the file to be deleted

  • moab_signature (Moab::FileSignature)

    The fixity values of the file

Returns:

  • (Boolean)

    true if file deleted, false otherwise


26
27
28
29
30
31
32
33
34
35
# File 'lib/dor/services/digital_stacks_service.rb', line 26

def self.delete_file(file_pathname, moab_signature)
  if file_pathname.exist? and (file_pathname.size == moab_signature.size)
    file_signature = Moab::FileSignature.new.signature_from_file(file_pathname)
    if (file_signature == moab_signature)
      file_pathname.delete
      return true
    end
  end
  return false
end

.prune_purl_dir(id) ⇒ Object


136
137
138
139
# File 'lib/dor/services/digital_stacks_service.rb', line 136

def self.prune_purl_dir(id)
  druid = DruidTools::PurlDruid.new(id, Dor::Config.stacks.local_document_cache_root)
  druid.prune!
end

.prune_stacks_dir(id) ⇒ Object

Assumes the digital stacks storage root is mounted to the local file system TODO since this is delegating to the Druid, this method may not be necessary


131
132
133
134
# File 'lib/dor/services/digital_stacks_service.rb', line 131

def self.prune_stacks_dir(id)
  stacks_druid_tree = DruidTools::StacksDruid.new(id, Config.stacks.local_stacks_root)
  stacks_druid_tree.prune!
end

.remove_from_stacks(stacks_object_pathname, content_diff) ⇒ Object

Delete files from stacks that have change type 'deleted', 'copydeleted', or 'modified'

Parameters:

  • stacks_object_pathname (Pathname)

    the stacks location of the digital object

  • content_diff (Moab::FileGroupDifference)

    the content file version differences report


11
12
13
14
15
16
17
18
19
20
# File 'lib/dor/services/digital_stacks_service.rb', line 11

def self.remove_from_stacks(stacks_object_pathname, content_diff)
  [:deleted, :copydeleted, :modified].each do |change_type|
    subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset}
    subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
      moab_signature = moab_file.signatures.first # {Moab::FileSignature}
      file_pathname = stacks_object_pathname.join(moab_file.basis_path)
      self.delete_file(file_pathname, moab_signature)
    end
  end
end

.rename_file(old_pathname, new_pathname, moab_signature) ⇒ Boolean

Rename a file, but only if it exists and has the expected signature

Parameters:

  • old_pathname (Pathname)

    The original location/name of the file being renamed

  • new_pathname (Pathname)

    The new location/name of the file

  • moab_signature (Moab::FileSignature)

    The fixity values of the file

Returns:

  • (Boolean)

    true if file renamed, false otherwise


67
68
69
70
71
72
73
74
75
76
77
# File 'lib/dor/services/digital_stacks_service.rb', line 67

def self.rename_file(old_pathname, new_pathname, moab_signature)
  if old_pathname.exist? and (old_pathname.size == moab_signature.size)
    file_signature = Moab::FileSignature.new.signature_from_file(old_pathname)
    if (file_signature == moab_signature)
      new_pathname.parent.mkpath
      old_pathname.rename(new_pathname)
      return true
    end
  end
  return false
end

.rename_in_stacks(stacks_object_pathname, content_diff) ⇒ Object

Rename files from stacks that have change type 'renamed' using an intermediate temp filename. The 2-step renaming allows chained or cyclic renames to occur without file collisions.

Parameters:

  • stacks_object_pathname (Pathname)

    the stacks location of the digital object

  • content_diff (Moab::FileGroupDifference)

    the content file version differences report


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/dor/services/digital_stacks_service.rb', line 41

def self.rename_in_stacks(stacks_object_pathname, content_diff)
  subset = content_diff.subset(:renamed) # {Moab::FileGroupDifferenceSubset

  # 1st Pass - rename files from original name to checksum-based name
  subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
    moab_signature = moab_file.signatures.first # {Moab::FileSignature}
    original_pathname = stacks_object_pathname.join(moab_file.basis_path)
    temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
    self.rename_file(original_pathname, temp_pathname, moab_signature)
  end

  # 2nd Pass - rename files from checksum-based name to new name
  subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
    moab_signature = moab_file.signatures.first # {Moab::FileSignature}
    temp_pathname = stacks_object_pathname.join(moab_signature.checksums.values.last)
    new_pathname = stacks_object_pathname.join(moab_file.other_path)
    self.rename_file(temp_pathname, new_pathname, moab_signature)
  end

end

.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, content_diff) ⇒ Object

Add files to stacks that have change type 'added', 'copyadded' or 'modified'.

Parameters:

  • workspace_content_pathname (Pathname)

    The dor workspace location of the digital object's content fies

  • stacks_object_pathname (Pathname)

    the stacks location of the digital object's shelved files

  • content_diff (Moab::FileGroupDifference)

    the content file version differences report


83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/dor/services/digital_stacks_service.rb', line 83

def self.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, content_diff)
  return false if workspace_content_pathname.nil?
  [:added, :copyadded, :modified,].each do |change_type|
    subset = content_diff.subset(change_type) # {Moab::FileGroupDifferenceSubset
    subset.files.each do |moab_file| # {Moab::FileInstanceDifference}
      moab_signature = moab_file.signatures.last # {Moab::FileSignature}
      filename = (change_type == :modified) ? moab_file.basis_path : moab_file.other_path
      workspace_pathname = workspace_content_pathname.join(filename)
      stacks_pathname = stacks_object_pathname.join(filename)
      self.copy_file(workspace_pathname, stacks_pathname, moab_signature)
    end
  end
  true
end

.transfer_to_document_store(id, content, filename) ⇒ void

This method returns an undefined value.

Create a file inside the content directory under the stacks.local_document_cache_root

Parameters:

  • id (String)

    The druid identifier for the object

  • content (String)

    The contents of the file to be created

  • filename (String)

    The name of the file to be created


123
124
125
126
127
# File 'lib/dor/services/digital_stacks_service.rb', line 123

def self.transfer_to_document_store(id, content, filename)
  druid = DruidTools::PurlDruid.new id, Config.stacks.local_document_cache_root
  druid.content_dir # create the druid tree if it doesn't exist yet
  File.open(File.join(druid.content_dir, filename), 'w') { |f| f.write content }
end