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

oracle.kv.impl.admin.SnapshotUtils Maven / Gradle / Ivy

Go to download

NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.

There is a newer version: 18.3.10
Show newest version
/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.impl.admin;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Logger;

import oracle.kv.impl.admin.Snapshot.SnapResult;
import oracle.kv.impl.admin.Snapshot.SnapResultSummary;
import oracle.kv.impl.admin.Snapshot.SnapshotOperation;
import oracle.kv.impl.topo.RepGroup;
import oracle.kv.impl.topo.RepGroupId;
import oracle.kv.impl.topo.RepGroupMap;
import oracle.kv.impl.topo.RepNodeId;
import oracle.kv.impl.topo.ResourceId;
import oracle.kv.impl.topo.StorageNodeId;
import oracle.kv.impl.topo.Topology;
import oracle.kv.impl.util.KVThreadFactory;

class SnapshotUtils {

    private Logger logger;
    private boolean verboseOutput;
    private PrintStream output;
    private SnapshotOperation sop;
    private ExecutorService threadPool;
    /**
     * Results handling
     */
    private List success;
    private List failure;
    private boolean allSucceeded = true;
    private boolean quorumSucceeded = true;

    SnapshotUtils (Logger logger) {
        this.logger = logger;
    }

    SnapshotUtils(boolean verboseOutput, PrintStream output) {
        this.verboseOutput = verboseOutput;
        this.output = output;
    }

    void resetOperation(SnapshotOperation newOp) {
        sop = newOp;
        allSucceeded = true;
        quorumSucceeded = true;
        success = null;
        failure = null;
    }

    ExecutorService createThreadPool() {
        if (threadPool == null) {
            threadPool = Executors.newCachedThreadPool
                (new KVThreadFactory("Snapshot", null));
        }
        return threadPool;
    }

    List> createFutureList() {
        return new ArrayList>();
    }

    /**
     * Walk the list of tasks aggregating results.  Because the SnapshotTask
     * will not throw an exception it should not be possible to get an
     * exception from the Future other than InterruptedException, but it needs
     * to be handled because of the Future.get() contract.
     */
    SnapResultSummary waitForResults(
        Topology topo, List> taskResults) {
        success = new ArrayList();
        failure = new ArrayList();
        List configSuccess = new ArrayList();
        List configFailure = new ArrayList();

        for (Future result : taskResults) {
            SnapResult snapResult = null;
            try {
                snapResult = result.get();
            } catch (InterruptedException e) {
                snapResult = new SnapResult(sop, false, null, e, "Interrupted");
            } catch (ExecutionException e) {
                snapResult = new SnapResult(sop, false, null, e, "Fail");
            }
            verbose("Task result (" + sop + "): " + snapResult);

            /* Update snapshot config results */
            if (snapResult.getService() instanceof StorageNodeId) {
                if (snapResult.getSucceeded()) {
                    configSuccess.add(snapResult);
                } else {
                    configFailure.add(snapResult);
                }
                continue;
            }

            if (snapResult.getSucceeded()) {
                success.add(snapResult);
            } else {
                allSucceeded = false;
                failure.add(snapResult);
            }
        }

        verbose("Operation " + sop + ", Successful nodes: " + success.size() +
                ", failed nodes: " + failure.size());

        /**
         * Perform additional analysis.
         */
        processResults(topo);
        return new SnapResultSummary(success, failure, allSucceeded,
            quorumSucceeded, configSuccess, configFailure);
    }

    void verbose(String msg) {
        if (verboseOutput) {
            message(msg);
        } else if (logger != null) {
            logger.fine(msg);
        }
    }

    private void message(String msg) {
        if (output != null) {
            output.println(msg);
        } else if (logger != null) {
            logger.info(msg);
        }
    }

    /**
     * Figure out if the operation was overall a success or failure based on
     * getting valid returns from enough nodes.  This isn't the most efficient
     * algorithm but it's simple.
     * o create a HashSet and populate it from the successes
     * o walk the topology and make sure that there is an entry in the set for
     * each RepGroup.
     * o note the failures.
     */
    private void processResults(Topology topo) {
        if (allSucceeded) {
            verbose("Operation " + sop + " succeeded for all nodes");
            quorumSucceeded = true;
            return;
        }

        Set repGroups = new HashSet();
        boolean adminOK = false;
        for (SnapResult res : success) {
            ResourceId rid = res.getService();
            if (rid != null) {
                if (rid instanceof RepNodeId) {
                    RepGroupId rgid =
                        new RepGroupId(((RepNodeId)rid).getGroupId());
                    repGroups.add(rgid);
                } else {
                    adminOK = true;
                }
            }
        }

        if (!adminOK) {
            quorumSucceeded = false;
        }
        RepGroupMap rgm = topo.getRepGroupMap();
        for (RepGroup rg : rgm.getAll()) {
            if (!repGroups.contains(rg.getResourceId())) {
                message("Operation " + sop + " did not succeed for shard " + rg);
                quorumSucceeded = false;
            } else {
                verbose("Operation " + sop + " succeeded for shard " + rg);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy