sdr-replication 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e99a0814e4383ec6287dec7df41825d786e65919
4
- data.tar.gz: 4890c2758dd820f22ce8aa9015621e1b33dec9ae
3
+ metadata.gz: 477696a5ac274697dfb1f337e562a859965695e8
4
+ data.tar.gz: ee4274bb597963bb1faec8783a0a41875abbd369
5
5
  SHA512:
6
- metadata.gz: deb3400e53fcbdf16cf8263ffe1deed70be83889633b4fecfa0de58e41a076e7f502de61d22f079b09ff6b81ddb29586bb6e898782f22e45010ecfd46d93828d
7
- data.tar.gz: a0533d23addcc264e7aeca97f985bdad1d70e8081230e09ab5337a03314b058374541b1587f47a5f89dd2f558115677190d49b320b892a77e7031bb15ac9c3ff
6
+ metadata.gz: 094e30cbc6e5e8c490e5560506a34b69cff7ab463cb4215e34d269b3f9abc9754fece858ac734a56448e1e4f0bd0332f6e7b0aee6d72e9d9436f5722afa6bfed
7
+ data.tar.gz: 1b1593dc47c1190a7bc1ea60b6f2bdb6635f21fc1170a7ef3cd18bb3be481d223b1b30435b72e327226ac33a81f63129a53405821cb4f7f04bbcc0c01ae64f54
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__),'../libdir')
2
+ require 'sdr_replication'
3
+
4
+ module Replication
5
+
6
+ class SdrObject < Moab::StorageObject
7
+
8
+ def initialize(druid)
9
+ @digital_object_id = druid
10
+ storage_object = StorageServices.find_storage_object(druid, include_deposit=true)
11
+ @object_pathname = storage_object.object_pathname
12
+ @storage_root = storage_object.storage_root
13
+ end
14
+
15
+
16
+ end
17
+
18
+ end
@@ -6,40 +6,139 @@ module Replication
6
6
  #
7
7
  # @note Copyright (c) 2014 by The Board of Trustees of the Leland Stanford Junior University.
8
8
  # All rights reserved. See {file:LICENSE.rdoc} for details.
9
- class SdrObjectVersion
9
+ class SdrObjectVersion < Moab::StorageObjectVersion
10
10
 
11
- # @return [Moab::StorageObjectVersion] Represents the object version's storage location
12
- attr_accessor :moab_object_version
11
+ def digital_object_id
12
+ storage_object.digital_object_id
13
+ end
13
14
 
14
- # @param [Moab::StorageObjectVersion] object_version Represents the object version's storage location
15
- # @return [SdrObjectVersion] Initialize a new SdrObjectVersion object
16
- def initialize(object_version)
17
- @moab_object_version = object_version
15
+ # @return [Moab::FileInventory] The moab version manifest for the version
16
+ def version_inventory
17
+ @version_inventory ||= file_inventory('version')
18
18
  end
19
19
 
20
- # @return [String] The digital object identifier (druid)
21
- def sdr_object_id
22
- @sdr_object_id ||= moab_object_version.storage_object.digital_object_id
20
+ # @return [Moab::FileInventory] The moab version manifest for the version
21
+ def version_additions
22
+ @version_additions ||= file_inventory('additions')
23
23
  end
24
24
 
25
- # @return [Integer] The digital object version number
26
- def sdr_version_id
27
- @sdr_version_id ||= moab_object_version.version_id
25
+ # @return [Hash] The contents of the versionMetadata file
26
+ def parse_version_metadata
27
+ metadata = Hash.new
28
+ pathname = find_filepath('metadata', 'versionMetadata.xml')
29
+ if pathname.exist?
30
+ doc = Nokogiri::XML(pathname.read)
31
+ nodeset = doc.xpath("/versionMetadata/version")
32
+ metadata[:version_id] = nodeset.last['versionId'].to_i unless nodeset.empty?
33
+ end
34
+ metadata
28
35
  end
29
36
 
30
- # @return [Moab::FileInventory] The moab version manifest for the version
31
- def version_inventory
32
- @version_inventory ||= moab_object_version.file_inventory('version')
37
+ # @return [Hash] The contents of the identityMetadata file
38
+ def parse_identity_metadata
39
+ metadata = Hash.new
40
+ pathname = find_filepath('metadata', 'identityMetadata.xml')
41
+ if pathname.exist?
42
+ doc = Nokogiri::XML(pathname.read)
43
+ nodeset = doc.xpath("/identityMetadata/objectType")
44
+ metadata[:object_type] = nodeset.first.text unless nodeset.empty?
45
+ nodeset = doc.xpath("/identityMetadata/objectLabel")
46
+ metadata[:object_label] = nodeset.first.text unless nodeset.empty?
47
+ end
48
+ metadata
33
49
  end
34
50
 
35
- # @return [Moab::FileInventory] The moab version manifest for the version
36
- def version_additions
37
- @version_additions ||= moab_object_version.file_inventory('additions')
51
+ # @return [Hash] The contents of the relationshipMetadata file
52
+ def parse_relationship_metadata
53
+ metadata = Hash.new
54
+ pathname = find_filepath('metadata', 'relationshipMetadata.xml')
55
+ if pathname.exist?
56
+ doc = Nokogiri::XML(pathname.read)
57
+ nodeset = doc.xpath("//hydra:isGovernedBy", 'hydra' => 'http://projecthydra.org/ns/relations#')
58
+ unless nodeset.empty?
59
+ apo_id = nodeset.first.attribute_with_ns('resource', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
60
+ if apo_id
61
+ metadata[:governed_by] = apo_id.text.split('/')[-1]
62
+ end
63
+ end
64
+ end
65
+ metadata
66
+ end
67
+
68
+ def update_object_data
69
+
70
+ identity_metadata = parse_identity_metadata
71
+ relationship_metadata = parse_relationship_metadata
72
+
73
+ digital_object_data = {
74
+ :digital_object_id => digital_object_id,
75
+ :home_repository => 'sdr'
76
+ }
77
+
78
+ sdr_object_data = {
79
+ :sdr_object_id => digital_object_id,
80
+ :object_type => identity_metadata[:object_type],
81
+ :object_label => identity_metadata[:object_label],
82
+ :governing_object => relationship_metadata[:governed_by],
83
+ :latest_version => storage_object.current_version_id
84
+ }
85
+
86
+ if version_id == 1
87
+ ArchiveCatalog.find_or_create_item(:digital_objects,digital_object_data)
88
+ ArchiveCatalog.find_or_create_item(:sdr_objects,sdr_object_data)
89
+ else
90
+ ArchiveCatalog.update_item(:sdr_objects, digital_object_id, sdr_object_data)
91
+ end
92
+
93
+ end
94
+
95
+ def update_version_data
96
+
97
+ sdr_object_version_data = {
98
+ :sdr_object_id => digital_object_id,
99
+ :sdr_version_id => version_id,
100
+ :replica_id => composite_key,
101
+ :ingest_date => version_inventory.inventory_datetime
102
+ }
103
+ ArchiveCatalog.find_or_create_item(:sdr_object_versions, sdr_object_version_data)
104
+
105
+
106
+ content = version_inventory.group('content')
107
+ metadata = version_inventory.group('metadata')
108
+ sdr_version_full = {
109
+ :sdr_object_id => digital_object_id,
110
+ :sdr_version_id => version_id,
111
+ :inventory_type => 'full',
112
+ :content_files => content.file_count,
113
+ :content_bytes => content.byte_count,
114
+ :content_blocks => content.block_count,
115
+ :metadata_files => metadata.file_count,
116
+ :metadata_bytes => metadata.byte_count,
117
+ :metadata_blocks => metadata.block_count
118
+ }
119
+ ArchiveCatalog.find_or_create_item(:sdr_version_stats, sdr_version_full)
120
+
121
+ content = version_additions.group('content')
122
+ metadata = version_additions.group('metadata')
123
+ sdr_version_delta = {
124
+ :sdr_object_id => digital_object_id,
125
+ :sdr_version_id => version_id,
126
+ :inventory_type => 'delta',
127
+ :content_files => content.file_count,
128
+ :content_bytes => content.byte_count,
129
+ :content_blocks => content.block_count,
130
+ :metadata_files => metadata.file_count,
131
+ :metadata_bytes => metadata.byte_count,
132
+ :metadata_blocks => metadata.block_count
133
+ }
134
+ ArchiveCatalog.find_or_create_item(:sdr_version_stats, sdr_version_delta)
135
+
38
136
  end
39
137
 
138
+
40
139
  # @return [String] The unique identifier for the digital object replica
41
140
  def replica_id
42
- @replica_id ||= "#{sdr_object_id.split(':').last}-#{moab_object_version.version_name}"
141
+ @replica_id ||= "#{storage_object.digital_object_id.split(':').last}-#{version_name}"
43
142
  end
44
143
 
45
144
  # @return [Replica] The Replica of the object version that is archived to tape, etc
@@ -52,7 +151,7 @@ module Replication
52
151
  bag_dir = replica.replica_pathname
53
152
  bag = BagitBag.create_bag(bag_dir)
54
153
  bag.bag_checksum_types = [:sha256]
55
- bag.add_payload_tarfile("#{replica_id}.tar",moab_object_version.version_pathname, moab_object_version.storage_object.object_pathname.parent)
154
+ bag.add_payload_tarfile("#{replica_id}.tar",version_pathname, storage_object.object_pathname.parent)
56
155
  bag.write_bag_info_txt
57
156
  bag.write_manifest_checksums('tagmanifest', bag.generate_tagfile_checksums)
58
157
  bag
@@ -20,6 +20,7 @@ require 'replication/file_fixity'
20
20
  require 'replication/fixity'
21
21
  require 'replication/operating_system'
22
22
  require 'replication/replica'
23
+ require 'replication/sdr_object'
23
24
  require 'replication/sdr_object_version'
24
25
  require 'replication/tarfile'
25
26
  include Replication
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdr-replication
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Anderson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-24 00:00:00.000000000 Z
11
+ date: 2014-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json_pure
@@ -26,6 +26,20 @@ dependencies:
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: moab-versioning
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: systemu
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
@@ -39,7 +53,7 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: systemu
56
+ name: rest-client
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -53,13 +67,13 @@ dependencies:
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: rest-client
70
+ name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
60
74
  - !ruby/object:Gem::Version
61
75
  version: '0'
62
- type: :runtime
76
+ type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
@@ -161,13 +175,11 @@ files:
161
175
  - lib/libdir.rb
162
176
  - lib/replication/archive_catalog.rb
163
177
  - lib/replication/bagit_bag.rb
164
- - lib/replication/command_consumer.rb
165
- - lib/replication/command_producer.rb
166
- - lib/replication/dpn_check_rep.rb
167
178
  - lib/replication/file_fixity.rb
168
179
  - lib/replication/fixity.rb
169
180
  - lib/replication/operating_system.rb
170
181
  - lib/replication/replica.rb
182
+ - lib/replication/sdr_object.rb
171
183
  - lib/replication/sdr_object_version.rb
172
184
  - lib/replication/tarfile.rb
173
185
  - lib/sdr_replication.rb
@@ -190,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
202
  version: 2.2.1
191
203
  requirements: []
192
204
  rubyforge_project:
193
- rubygems_version: 2.2.1
205
+ rubygems_version: 2.3.0
194
206
  signing_key:
195
207
  specification_version: 4
196
208
  summary: Core methods for support of SDR Preservation Core replication
@@ -1,55 +0,0 @@
1
- require "rubygems"
2
- require "amqp"
3
- require "amqp/extensions/rabbitmq"
4
- require "yaml"
5
-
6
- EventMachine.run do
7
-
8
-
9
- connection_params = {
10
- :host => "127.0.0.1",
11
- :port => 5672,
12
- :user => "guest",
13
- :pass => "guest",
14
- :vhost => "/",
15
- :ssl => false,
16
- :frame_max => 131072
17
- }
18
-
19
- connection = AMQP.connect(connection_params)
20
- channel = AMQP::Channel.new(connection, :auto_recovery => true)
21
-
22
-
23
- channel.prefetch(1)
24
-
25
- # Acknowledgements are good for letting the server know
26
- # that the task is finished. If the consumer doesn't send
27
- # the acknowledgement, then the task is considered to be unfinished
28
- # and will be requeued when consumer closes AMQP connection (because of a crash, for example).
29
-
30
- channel.queue("sdr.replication.notification", :durable => true, :auto_delete => false).subscribe(:ack => true) do |metadata, payload|
31
- case metadata.type
32
- when "sdr_replication_notification"
33
- data = YAML.load(payload)
34
- puts "sdr_replication_notification request with #{data.inspect}"
35
-
36
- message = "'" + payload + "'"
37
- header = "'" + metadata.attributes.to_yaml + "'"
38
-
39
-
40
- (pid = fork) ? Process.detach(pid) : exec("./dpn_check_rep.rb #{message} #{header}")
41
- #shellout = "./dpn_check_rep.rb '#{data[:name]}' #{data[:size]}"
42
- #puts "dpn_check_rep.rb Executing #{shellout}"; system(shellout)
43
- puts "Call to SDR DPN replication request done"
44
- puts
45
-
46
- when "dpn_replication_notification"
47
- else
48
- puts "[commands] Unknown command: #{metadata.type}"
49
- end
50
-
51
- # message is processed, acknowledge it so that broker discards it
52
- metadata.ack
53
- end
54
- Signal.trap("INT") { connection.close { EventMachine.stop } }
55
- end
@@ -1,105 +0,0 @@
1
- require "amqp"
2
- require "amqp/extensions/rabbitmq"
3
- require "yaml"
4
- require "json"
5
- require "securerandom"
6
- require "time"
7
-
8
-
9
- connection_params = {
10
- :host => "127.0.0.1",
11
- :port => 5672,
12
- :user => "guest",
13
- :pass => "guest",
14
- :vhost => "/",
15
- :ssl => false,
16
- :frame_max => 131072
17
- }
18
-
19
- #usually send one message only, rely on message broker to recover
20
- doit = 1
21
-
22
- EventMachine.run do
23
- sleep(0.5)
24
-
25
- connection = AMQP.connect(connection_params)
26
- channel = AMQP::Channel.new(connection)
27
-
28
-
29
- # publish new commands every 2 seconds, count + one times
30
- count = 0
31
- EventMachine.add_periodic_timer(2.0) do
32
- count += 1
33
- if count >= doit then
34
- EM.stop_event_loop
35
- end
36
- puts "count = #{count}"
37
- puts "Messaging that sdr has content for replication, parameters are name and size."
38
- payload = { :name => "12345.tar", :size => 4096 }.to_yaml
39
-
40
- correlation_id = SecureRandom.random_number(10000)
41
- utctime = Time.now.utc
42
- ttl = 20 #time for transaction to live
43
-
44
- channel.default_exchange.publish(payload,
45
- :arguments => { "x-message-ttl" => 10 },
46
- :type => "sdr_replication_notification",
47
- :routing_key => "sdr.replication.notification",
48
- :reply_to => "dpn.replication.reply",
49
- :correlation_id => correlation_id,
50
- :timestamp => utctime.to_i
51
- )
52
-
53
- end
54
-
55
- puts "Sending notification message"
56
- Signal.trap("INT") { connection.close { EventMachine.stop } }
57
- end
58
-
59
-
60
-
61
- exit
62
-
63
- #listen for response to previous message
64
- EventMachine.run do
65
- sleep(0.5)
66
-
67
- connection = AMQP.connect(connection_params)
68
- channel = AMQP::Channel.new(connection, :auto_recovery => true)
69
- channel.prefetch(1)
70
-
71
- count = 0
72
- EventMachine.add_periodic_timer(10.0) do
73
- count += 1
74
- puts "waiting....."
75
- if count > doit+1 then
76
- EM.stop_event_loop
77
- end
78
- end
79
-
80
- channel.queue("dpn.replication.notification", :durable => true, :auto_delete => false).subscribe(:ack => true) do |metadata, payload|
81
- case metadata.type
82
- when "dpn_replication_ack"
83
- message = YAML.load(payload)
84
- if message[:message] == "dpn_available_reply" && message[:acknak] == 'ack' then
85
- puts "[sdr dpn says to go ahead and replicate content to temp area."
86
- # (pid = fork) ? Process.detach(pid) : exec("start_replication_workflow.rb
87
- puts "Start workflow to copy content to sdr dpn for replication. "
88
- else
89
- puts "no replication possible, DPN say's no!"
90
- # (pid = fork) ? Process.detach(pid) : exec("replication_denied_workflow.rb
91
- end
92
-
93
- when "dpn_replication_notification"
94
- puts "DPN wants to replicate"
95
- else
96
- puts "[commands] Unknown command: #{metadata.type}"
97
- end
98
-
99
- # message is processed, acknowledge it so that broker discards it
100
- metadata.ack
101
- end
102
- puts "Waiting for 'ack' notification message"
103
- Signal.trap("INT") { connection.close { EventMachine.stop } }
104
-
105
- end
@@ -1,83 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
- $: << "./"
4
- require 'securerandom'
5
- require "rubygems"
6
- require 'time'
7
- require 'date'
8
- require "eventmachine"
9
- require "amqp"
10
- require "amqp/extensions/rabbitmq"
11
- require "yaml"
12
-
13
-
14
- connection_params = {
15
- :host => "127.0.0.1",
16
- :port => 5672,
17
- :user => "guest",
18
- :pass => "guest",
19
- :vhost => "/",
20
- :ssl => false,
21
- :frame_max => 131072
22
- }
23
-
24
- #arguments passed are json strings. payload, header.
25
- puts "*************************************"
26
- puts "In dpn_check_rep.rb"
27
- if ARGV.length != 2 then
28
- exit 5001 #should not get here, but this is an error condition
29
- end
30
-
31
- message = YAML.load(ARGV[0])
32
- header = YAML.load(ARGV[1])
33
-
34
- if header[:type] != "sdr_replication_notification" then
35
- exit 5002 #bad message type
36
- end
37
-
38
- puts "sdr_replication_notification message #{message.inspect}"
39
- puts "sdr_replication_notification header #{header.inspect}"
40
-
41
- puts "checking to see if DPN can replicate content from SDR"
42
-
43
- #
44
- #Do checking!
45
- #
46
-
47
- sleep 4.5 #simulate checking
48
-
49
-
50
- exit
51
-
52
- EventMachine.run do
53
- sleep(0.5)
54
- connection = AMQP.connect(connection_params)
55
- channel = AMQP::Channel.new(connection)
56
-
57
- count = 0
58
- EventMachine.add_periodic_timer(2.0) do
59
- count += 1
60
- if count > 2 then
61
- EM.stop_event_loop
62
- end
63
- end
64
-
65
- EM.add_timer(1.0) do
66
- puts "Working: #{Time.now}"
67
- STDOUT.flush
68
- end
69
-
70
- puts "Acking that content can be replicated"
71
- payload = { :message => "dpn_available_reply", :acknak => 'ack' }.to_yaml
72
-
73
- channel.default_exchange.publish(payload,
74
- :type => "dpn_replication_ack",
75
- :routing_key => header[:reply_to],
76
- :reply_to => "dpn.err.notification",
77
- :correlation_id => header[:correlation_id],
78
- :timestamp => header[:timestamp])
79
-
80
- puts "Sending ack notification message"
81
- Signal.trap("INT") { connection.close { EventMachine.stop } }
82
-
83
- end