org.sosy_lab.cpachecker.pcc.strategy.parallel.interleaved.PartialReachedSetIOCheckingOnlyInterleavedCMCStrategy.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.pcc.strategy.parallel.interleaved.PartialReachedSetIOCheckingOnlyInterleavedCMCStrategy.java

Source

/*
 *  CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2015  Dirk Beyer
 *  All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 *  CPAchecker web page:
 *    http://cpachecker.sosy-lab.org
 */
package org.sosy_lab.cpachecker.pcc.strategy.parallel.interleaved;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.zip.ZipInputStream;

import org.sosy_lab.common.Pair;
import org.sosy_lab.common.ShutdownNotifier;
import org.sosy_lab.common.Triple;
import org.sosy_lab.common.configuration.Configuration;
import org.sosy_lab.common.configuration.InvalidConfigurationException;
import org.sosy_lab.common.log.LogManager;
import org.sosy_lab.cpachecker.cfa.CFA;
import org.sosy_lab.cpachecker.core.interfaces.AbstractState;
import org.sosy_lab.cpachecker.core.interfaces.ConfigurableProgramAnalysis;
import org.sosy_lab.cpachecker.core.reachedset.HistoryForwardingReachedSet;
import org.sosy_lab.cpachecker.core.reachedset.ReachedSet;
import org.sosy_lab.cpachecker.core.reachedset.ReachedSetFactory;
import org.sosy_lab.cpachecker.core.reachedset.UnmodifiableReachedSet;
import org.sosy_lab.cpachecker.cpa.PropertyChecker.PropertyCheckerCPA;
import org.sosy_lab.cpachecker.cpa.arg.ARGState;
import org.sosy_lab.cpachecker.cpa.predicate.PredicateCPA;
import org.sosy_lab.cpachecker.exceptions.CPAException;
import org.sosy_lab.cpachecker.pcc.strategy.AbstractStrategy;
import org.sosy_lab.cpachecker.pcc.strategy.partitioning.CMCPartitionChecker;
import org.sosy_lab.cpachecker.pcc.strategy.partitioning.CMCPartitioningIOHelper;
import org.sosy_lab.cpachecker.pcc.strategy.util.cmc.AssumptionAutomatonGenerator;
import org.sosy_lab.cpachecker.pcc.strategy.util.cmc.PartialCPABuilder;
import org.sosy_lab.cpachecker.util.CPAs;
import org.sosy_lab.cpachecker.util.globalinfo.GlobalInfo;

import com.google.common.collect.Sets;

// FIXME unsound strategy
public class PartialReachedSetIOCheckingOnlyInterleavedCMCStrategy extends AbstractStrategy {

    private final Configuration config;
    private final ShutdownNotifier shutdown;
    private final PartialCPABuilder cpaBuilder;
    private final AssumptionAutomatonGenerator automatonWriter;
    private int numProofs;

    public PartialReachedSetIOCheckingOnlyInterleavedCMCStrategy(final Configuration pConfig,
            final LogManager pLogger, final ShutdownNotifier pShutdownNotifier, final CFA pCFA)
            throws InvalidConfigurationException {
        super(pConfig, pLogger);
        cpaBuilder = new PartialCPABuilder(pConfig, pLogger, pShutdownNotifier, pCFA);
        automatonWriter = new AssumptionAutomatonGenerator(pConfig, pLogger);
        config = pConfig;
        logger = pLogger;
        shutdown = pShutdownNotifier;
    }

    @Override
    public void constructInternalProofRepresentation(UnmodifiableReachedSet pReached)
            throws InvalidConfigurationException, InterruptedException {
        throw new InvalidConfigurationException(
                "Interleaved proof reading and checking strategies do not  support internal PCC with result check algorithm");
    }

    @Override
    public boolean checkCertificate(ReachedSet pReachedSet) throws CPAException, InterruptedException {
        pReachedSet.popFromWaitlist();
        if (numProofs <= 0) {
            logger.log(Level.SEVERE, "No proofs provided.");
            return false;
        }

        try {

            PropertyCheckerCPA[] cpas = new PropertyCheckerCPA[numProofs];
            CMCPartitioningIOHelper[] ioHelpers = new CMCPartitioningIOHelper[numProofs];
            AbstractState[] roots = new AbstractState[numProofs];
            AtomicBoolean checkResult = new AtomicBoolean(true);
            // we may use one semaphore only because we check and read proof parts sequentially
            Semaphore partitionsAvailable = new Semaphore(0);
            Semaphore automatonAvailable = new Semaphore(1);

            Thread readingThread = new Thread(new ProofPartReader(automatonAvailable, partitionsAvailable,
                    checkResult, ioHelpers, cpas, roots, new ReachedSetFactory(config, logger)));
            try {
                readingThread.start();

                Pair<ARGState, List<ARGState>> checkingResult;

                CMCPartitionChecker checker;

                for (int i = 0; checkResult.get() && i < numProofs;) {
                    shutdown.shutdownIfNecessary();

                    partitionsAvailable.acquire();

                    if (!checkResult.get()) {
                        return false;
                    }

                    // partitioning checker
                    checker = new CMCPartitionChecker(cpas[i], checkResult, shutdown, logger, roots[i]);

                    // initial state coverage checked by checker
                    // assume that root is first state in first partition
                    for (int j = 0; j < ioHelpers[i].getNumPartitions() && checkResult.get(); j++) {
                        shutdown.shutdownIfNecessary();
                        partitionsAvailable.acquire();

                        if (!checkResult.get()) {
                            return false;
                        }

                        checker.checkPartition(ioHelpers[i].getPartition(j).getFirst(),
                                ioHelpers[i].getPartition(j).getSecond(), ioHelpers[i].getEdgesForPartition(j),
                                ioHelpers[i].getSavedReachedSetSize());
                    }

                    // check if all external nodes are checked in different partition
                    if (!checker.checkCoverageOfExternalsAndInitialState()) {
                        logger.log(Level.SEVERE,
                                "Elements which should be checked in different partition are not checked or initial state not covered");
                        return false;
                    }

                    // inspect safety
                    if (!cpas[i].getPropChecker().satisfiesProperty(checker.getInspectedStates())) {
                        logger.log(Level.SEVERE, "Property violation in certificate found.");
                        return false;
                    }

                    checkingResult = checker.getAutomatonReconstructionInfo();

                    i++;
                    if (i < numProofs) {
                        // write assumption automaton for next round
                        automatonWriter.writeAutomaton(checkingResult.getFirst(), checkingResult.getSecond());
                        automatonAvailable.release();
                    } else {
                        if (!checkingResult.getSecond().isEmpty()) {
                            return false;
                        }
                    }
                }
                return checkResult.get();
            } finally {
                checkResult.set(false);
                readingThread.interrupt();
            }
        } catch (InvalidConfigurationException e) {
            logger.log(Level.SEVERE, "Cannot set up infrastructure for proof checking.");
            return false;
        }
    }

    @Override
    protected void writeProofToStream(ObjectOutputStream pOut, UnmodifiableReachedSet pReached)
            throws IOException, InvalidConfigurationException, InterruptedException {
        if (!(pReached instanceof HistoryForwardingReachedSet)) {
            throw new InvalidConfigurationException(
                    "Reached sets used by restart algorithm are not memorized. Please enable option analysis.memorizeReachedAfterRestart");
        }

        List<ReachedSet> partialReachedSets = ((HistoryForwardingReachedSet) pReached)
                .getAllReachedSetsUsedAsDelegates();

        if (partialReachedSets == null || partialReachedSets.isEmpty()) {
            logger.log(Level.SEVERE, "No proof parts available. Proof cannot be generated.");
            return;
        }

        List<ConfigurableProgramAnalysis> cpas = ((HistoryForwardingReachedSet) pReached).getCPAs();

        if (partialReachedSets.size() != cpas.size()) {
            logger.log(Level.SEVERE, "Analysis inconsistent. Proof cannot be generated.");
            return;
        }

        logger.log(Level.FINEST, "Write number of proof parts to proof");
        pOut.writeInt(partialReachedSets.size());

        CMCPartitioningIOHelper ioHelper;
        Set<ARGState> unexplored;
        try {
            ReachedSet reached;
            for (int i = 0; i < partialReachedSets.size(); i++) {
                GlobalInfo.getInstance().setUpInfoFromCPA(cpas.get(i));
                reached = partialReachedSets.get(i);

                unexplored = Sets.newHashSetWithExpectedSize(reached.getWaitlist().size());
                for (AbstractState toExplore : reached.getWaitlist()) {
                    unexplored.add((ARGState) toExplore);
                }

                ioHelper = new CMCPartitioningIOHelper(config, logger, shutdown,
                        automatonWriter.getAllAncestorsFor(unexplored), unexplored,
                        (ARGState) reached.getFirstState());
                ioHelper.writeProof(pOut, reached);
            }
        } catch (ClassCastException e) {
            logger.log(Level.SEVERE, "Stop writing proof. Not all analysis use ARG CPA as top level CPA");
        }
    }

    @Override
    protected void readProofFromStream(ObjectInputStream pIn)
            throws ClassNotFoundException, InvalidConfigurationException, IOException {
        numProofs = pIn.readInt();
        // remaining proof parts are read interleaved, no further reading required
    }

    private class ProofPartReader implements Runnable {

        private final AtomicBoolean checkResult;
        private final Semaphore mainSemaphore, startReading;
        private final CMCPartitioningIOHelper[] ioHelperPerProofPart;
        private final PropertyCheckerCPA[] cpas;
        private final AbstractState[] roots;
        private final ReachedSetFactory factory;

        public ProofPartReader(final Semaphore pReadNext, Semaphore pPartitionsAvailable,
                final AtomicBoolean pCheckResult, final CMCPartitioningIOHelper[] pIoHelpers,
                final PropertyCheckerCPA[] pCpas, final AbstractState[] pRoots, final ReachedSetFactory pFactory) {
            startReading = pReadNext;
            checkResult = pCheckResult;
            mainSemaphore = pPartitionsAvailable;
            ioHelperPerProofPart = pIoHelpers;
            cpas = pCpas;
            roots = pRoots;
            factory = pFactory;
        }

        @Override
        public void run() {
            Triple<InputStream, ZipInputStream, ObjectInputStream> streams = null;
            try {
                streams = openProofStream();
                ObjectInputStream o = streams.getThird();
                o.readInt();

                CMCPartitioningIOHelper ioHelper;
                ConfigurableProgramAnalysis cpa;

                boolean mustReadAndCheckSequentially;

                for (int i = 0; i < numProofs && checkResult.get(); i++) {
                    startReading.acquire();
                    ioHelper = new CMCPartitioningIOHelper(config, logger, shutdown);
                    // save helper for proof checking
                    ioHelperPerProofPart[i] = ioHelper;
                    // create config for reading and save for later checking
                    cpa = cpaBuilder.buildPartialCPA(i, factory);
                    if (!(cpa instanceof PropertyCheckerCPA)) {
                        logger.log(Level.SEVERE,
                                "Conflicting configuration: Partial proofs must be checked with CPA based strategy but toplevel CPA is not a PropertyCheckerCPA as needed");
                        abortPreparation();
                        break;
                    }
                    cpas[i] = (PropertyCheckerCPA) cpa;
                    GlobalInfo.getInstance().setUpInfoFromCPA(cpas[i]);

                    mustReadAndCheckSequentially = CPAs.retrieveCPA(cpa, PredicateCPA.class) != null;

                    ioHelper.readMetadata(o, true);
                    roots[i] = ioHelper.getRoot();

                    if (roots[i] == null) {
                        logger.log(Level.SEVERE, "Root node not well specified in proof.");
                        abortPreparation();
                        break;
                    }

                    // release for set up checking of particular, partial proof
                    if (!mustReadAndCheckSequentially) {
                        mainSemaphore.release();
                    }

                    for (int j = 0; j < ioHelper.getNumPartitions() && checkResult.get(); j++) {
                        ioHelper.readPartition(o, stats);

                        if (shutdown.shouldShutdown()) {
                            abortPreparation();
                            break;
                        }

                        // release to check partition
                        if (!mustReadAndCheckSequentially) {
                            mainSemaphore.release();
                        }
                    }
                    if (mustReadAndCheckSequentially) {
                        mainSemaphore.release(ioHelper.getNumPartitions() + 1);
                    }
                }
            } catch (IOException | ClassNotFoundException e) {
                logger.logUserException(Level.SEVERE, e, "Partition reading failed. Stop checking");
                abortPreparation();
            } catch (InterruptedException exp) {
                if (checkResult.get()) {
                    logger.log(Level.SEVERE, "Unexpected interrupt. Stop checking.");
                    abortPreparation();
                }
            } catch (Exception e2) {
                logger.logException(Level.SEVERE, e2, "Unexpected failure during proof reading");
                abortPreparation();
            } finally {
                if (streams != null) {
                    try {
                        streams.getThird().close();
                        streams.getSecond().close();
                        streams.getFirst().close();
                    } catch (IOException e) {
                    }
                }
            }
        }

        private void abortPreparation() {
            checkResult.set(false);
            mainSemaphore.release(2);
        }

    }

}