diff --git a/lib/syskit/log/datastore/repair.rb b/lib/syskit/log/datastore/repair.rb index e7cc730..b41a1ca 100644 --- a/lib/syskit/log/datastore/repair.rb +++ b/lib/syskit/log/datastore/repair.rb @@ -1,8 +1,13 @@ +# frozen_string_literal: true + module Syskit::Log class Datastore module Repair # rubocop:disable Style/Documentation # Detect problems and perform repair steps on the given dataset - def self.repair_dataset(datastore, dataset, dry_run: true) + def self.repair_dataset( + datastore, dataset, + dry_run: true, reporter: Pocolog::CLI::NullReporter.new + ) if dry_run ops = find_all_repair_ops(datastore, dataset) if ops.empty? @@ -15,16 +20,22 @@ def self.repair_dataset(datastore, dataset, dry_run: true) return unless (op = find_repair_op(datastore, dataset)) puts op - (dataset = op.apply) unless dry_run + (dataset = op.apply(reporter)) unless dry_run end end end + # @api private + # + # Return the operations that should be applied to this dataset def self.find_all_repair_ops(datastore, dataset) OPERATIONS.map { |op_class| op_class.detect(datastore, dataset) } .compact end + # @api private + # + # Return the first operation that should be applied to this dataset def self.find_repair_op(datastore, dataset) OPERATIONS.each do |op_class| if (op = op_class.detect(datastore, dataset)) @@ -34,6 +45,8 @@ def self.find_repair_op(datastore, dataset) nil end + # @api private + # # Migration of roby-events.log to roby-events.0.log class MigrateRobyLogName def self.detect(datastore, dataset) @@ -55,7 +68,7 @@ def to_s "changing the dataset identity" end - def apply + def apply(_reporter) @datastore.updating_digest(@dataset) do identity = @dataset.read_dataset_identity_from_metadata_file roby_log = identity.find do |e| @@ -70,6 +83,8 @@ def apply end end + # @api private + # # roby-events.?.log were at some point not added to the identity metadata class AddRobyLogsToIdentity def self.detect(datastore, dataset) @@ -102,7 +117,7 @@ def to_s " #{missing_paths.map(&:to_s).join("\n ")}" end - def apply + def apply(_reporter) @datastore.updating_digest(@dataset) do missing_paths = self.class.roby_log_paths(@dataset) identity = @dataset.read_dataset_identity_from_metadata_file @@ -114,10 +129,64 @@ def apply end end + # @api private + # + # Builds the cache folder for the given dataset + class CacheRebuild + def self.detect(datastore, dataset) + return if datastore.cache_path_of(dataset.digest).exist? + + new(datastore, dataset) + end + + def initialize(datastore, dataset) + @datastore = datastore + @dataset = dataset + end + + def to_s + "#{@dataset.digest}: rebuild cache" + end + + def apply(reporter) + Syskit::Log::Datastore.index_build( + @datastore, @dataset, reporter: reporter + ) + @dataset + end + end + + # @api private + # + # Calculate the timestamp and save it in the dataset + class ComputeTimestamp + def self.detect(_datastore, dataset) + new(dataset) unless dataset.metadata["timestamp"] + end + + def initialize(dataset) + @dataset = dataset + end + + def to_s + "#{@dataset.digest}: save the timestamp metadata "\ + "#{@dataset.timestamp}" + end + + def apply(_reporter) + # This computes & saves the timestamp in the metadata + @dataset.timestamp + @dataset.metadata_write_to_file + @dataset + end + end + OPERATIONS = [ MigrateRobyLogName, AddRobyLogsToIdentity, + # Must be after everything that repairs the identity + CacheRebuild, ComputeTimestamp ].freeze end diff --git a/test/cli/datastore_test.rb b/test/cli/datastore_test.rb index 1dde90d..38206c1 100644 --- a/test/cli/datastore_test.rb +++ b/test/cli/datastore_test.rb @@ -710,6 +710,14 @@ def expected_dataset(digest) ds.metadata_fetch("timestamp") end + it "re-creates the cache if it is missing" do + d = "8bed98f3ce3ff08487675280844b51d9e3c564313bb8ded1854c7a70255da5a8" + refute @datastore.cache_path_of(d).exist? + + run_repair d + assert @datastore.cache_path_of(d).exist? + end + def run_repair(digest) call_cli("repair", "--store", @store_path, digest) end