All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.bdeploy.bhive.op.ObjectConsistencyCheckOperation Maven / Gradle / Ivy

package io.bdeploy.bhive.op;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import io.bdeploy.bhive.BHive;
import io.bdeploy.bhive.audit.AuditParameterExtractor.AuditStrategy;
import io.bdeploy.bhive.audit.AuditParameterExtractor.AuditWith;
import io.bdeploy.bhive.model.Manifest;
import io.bdeploy.bhive.model.ObjectId;
import io.bdeploy.bhive.objects.MarkerDatabase;
import io.bdeploy.bhive.objects.view.ElementView;
import io.bdeploy.bhive.objects.view.ManifestRefView;
import io.bdeploy.bhive.objects.view.TreeView;
import io.bdeploy.bhive.objects.view.scanner.TreeVisitor;
import io.bdeploy.common.ActivityReporter.Activity;
import io.bdeploy.common.util.PathHelper;

/**
 * Checks for missing and corrupt objects. Missing objects will lead to an
 * exception, as they are required for full tree traversal. Corrupted objects
 * will be collected, and returned.
 */
public class ObjectConsistencyCheckOperation extends BHive.Operation> {

    @AuditWith(AuditStrategy.COLLECTION_PEEK)
    private final SortedSet roots = new TreeSet<>();
    private boolean dryRun = true;

    @Override
    public Set call() throws Exception {
        if (roots.isEmpty()) {
            SortedSet localManifests = execute(new ManifestListOperation());
            roots.addAll(localManifests);
        }

        Activity scanning = getActivityReporter().start("Scanning manifest trees...", roots.size());

        Path markerPath = Files.createTempDirectory("markers-");
        MarkerDatabase markerDb = new MarkerDatabase(markerPath, getActivityReporter());
        Set broken = new TreeSet<>();
        try {
            for (Manifest.Key key : roots) {
                List existingElements = new ArrayList<>();
                if (!execute(new ManifestExistsOperation().setManifest(key))) {
                    // does not even exist - happens if manifest consistency operation removed it.
                    continue;
                }

                TreeView state = execute(new ScanOperation().setManifest(key));

                if (state.getElementId() == null) {
                    // well, well - pretty damaged.
                    broken.add(state.getChildren().values().iterator().next());
                    continue;
                }

                state.visit(new TreeVisitor.Builder().onBlob(existingElements::add).onTree(existingElements::add)
                        .onManifestRef(existingElements::add).build());

                broken.addAll(checkElements(markerDb, existingElements));

                scanning.workAndCancelIfRequested(1);
            }
        } finally {
            scanning.done();
            PathHelper.deleteRecursive(markerPath);
        }

        return broken;
    }

    private Set checkElements(MarkerDatabase markerDb, List existingElements) {
        Set broken = new TreeSet<>();
        for (ElementView obj : existingElements) {
            if (markerDb.hasObject(obj.getElementId())) {
                continue;
            } else {
                // write the marker ourselves, the content never matches the checksum (intentionally).
                markerDb.addMarker(obj.getElementId());
            }

            if (!getObjectManager().checkObject(obj.getElementId(), !dryRun)) {
                broken.add(obj);
            }
            if (obj instanceof ManifestRefView) {
                ObjectId ref = ((ManifestRefView) obj).getReferenceId();
                if (!getObjectManager().checkObject(ref, !dryRun)) {
                    broken.add(obj);
                }
            }
        }
        return broken;
    }

    /**
     * Add a root {@link Manifest} to traverse and check objects of recursively.
     */
    public ObjectConsistencyCheckOperation addRoot(Manifest.Key key) {
        roots.add(key);
        return this;
    }

    public ObjectConsistencyCheckOperation setDryRun(boolean dry) {
        this.dryRun = dry;
        return this;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy