/**************************************************************************/
/* Implementation of a simple deadlock analysis system */
/* Copyright (C) 2012. Michael Lienhardt and Carlo Garzia */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; version 2 of the License. */
/* */
/* This program is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
/* General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA */
/* 02110-1301 USA */
/* */
/**************************************************************************/
package deadlock.analyser;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.PrintStream;
import abs.frontend.ast.Model;
import abs.frontend.ast.InterfaceDecl;
import abs.frontend.ast.ClassDecl;
import deadlock.analyser.factory.*;
import com.gzoumix.semisolver.term.*;
import deadlock.analyser.generation.*;
import deadlock.analyser.inference.ContractInference;
import deadlock.analyser.detection.*;
import com.gzoumix.semisolver.constraint.*;
import com.gzoumix.semisolver.substitution.*;
public class Analyser {
private static int FixPoint1_0 = 1;
private static int FixPoint2_0 = 2;
public void deadlockAnalysis(Model m, boolean verbose, int nbIteration, int fixPointVersion, PrintStream out) {
Variable.varCounter =0;
Long totalTimeInMs = 0L;
Long nanoTime = System.nanoTime();
DeadlockPreanalysis p = new DeadlockPreanalysis(m);
p.analyzeModel();
Long ellapsedTime = (System.nanoTime() - nanoTime) / 1000000L;
totalTimeInMs += ellapsedTime;
if(p.isDeadlockFree()){
out.println("### LOCK INFORMATION RESULTED BY THE ANALYSIS ###\n");
out.println("Possible Deadlock in Main: false");
out.println("Current Version: no solver was used");
out.println("Note: necessary conditions for deadlocks were not present");
out.println();
out.println("Analysis Duration: " + totalTimeInMs + "ms");
return;
}
/* 0, Create the initial data */
Factory df = new Factory(verbose);
AnalyserLog log = new AnalyserLog();
if(verbose) { log.verbose(); }
ContractInference ci = new ContractInference(log, df, m);
ci.computeMapInterfaceToClass();
ci.computeEnvironment();
/* 1. Generate contracts */
log.logDebug("Analyzing dependencies to look for deadlocks...");
nanoTime = System.nanoTime();
ellapsedTime = (System.nanoTime() - nanoTime) / 1000000L;
totalTimeInMs += ellapsedTime;
ResultInference InferenceOutput = ci.typeInference();
Map<String, MethodContract> methodMap = InferenceOutput.getMethods();
Constraint c = InferenceOutput.getConstraint();
log.logDebug("###############################################################\n");
log.logDebug("Contract and Constraint generation finished...");
log.logDebug("Ellapsed time: " + ellapsedTime + "ms");
log.logDebug(" Initial constraint:\n -------------------");
log.logDebug(InferenceOutput.getConstraint().toString() + "\n");
log.logDebug(" Initial contracts:\n -----------------");
for(Map.Entry<String, MethodContract> entry : methodMap.entrySet()){
log.logDebug(" \"" + entry.getKey() + "\": " + ((entry.getValue() != null) ? (entry.getValue().toString()) : ("null")));
}
log.logDebug(" \"main\": " + ((InferenceOutput.getMainContractPresent() != null) ? ("< " + InferenceOutput.getMainContractPresent() + ", " + InferenceOutput.getMainContractFuture() + ">") : ("null")));
log.logDebug("###############################################################\n");
log.logDebug("Solving constraint...");
// 1.2. Solve the constraint and check for errors
nanoTime = System.nanoTime();
c.solve();
ellapsedTime = (System.nanoTime() - nanoTime) / 1000000L;
totalTimeInMs += ellapsedTime;
if(!c.getErrors().isEmpty()) {
log.logDebug("Generation of Contract failed: constraint not satisfiable");
log.logDebug("###############################################################\n");
} else {
log.logDebug("Constraint solving completed");
log.logDebug("Ellapsed time: " + ellapsedTime + "ms");
log.logDebug("###############################################################\n");
}
ArrayList<GenerationError> errors = new ArrayList<GenerationError>(c.getErrors().size());
for(SolvingError err : c.getErrors()) {
if(err instanceof SolvingErrorLoop) { errors.add(new ErrorLoop((SolvingErrorLoop)err)); }
else { errors.add(new ErrorUnif((SolvingErrorUnif)err)); }
}
out.println();
if(!errors.isEmpty()) {
out.println("### Analysis failed due to some errors ###");
out.println();
int i = 1;
for(GenerationError err : errors){
out.println(i++ + ":");
out.println(err.getHelpMessage());
out.println();
}
return;
}
// 1.3. apply it to the contracts
nanoTime = System.nanoTime();
Substitution s = c.getSubstitution();
for(String k : methodMap.keySet()){
MethodContract mc = (MethodContract)s.apply(methodMap.get(k));
//mc.clean();
if(methodMap.get(k) != null) methodMap.put(k, mc);
}
ellapsedTime = (System.nanoTime() - nanoTime) / 1000000L;
totalTimeInMs += ellapsedTime;
if(verbose) {
out.println("###############################################################\n");
out.println("Substitution completed");
out.println("Ellapsed time: " + ellapsedTime + "ms");
out.println("###############################################################\n");
out.println("Contract and Constraint computation finished...");
out.println(" Constraint:\n -----------");
out.println(c.toString() + "\n");
out.println(" Substitution:\n -------------");
out.println(s.toString() + "\n");
out.println(" Contracts:\n ---------");
for(Map.Entry<String, MethodContract> entry : methodMap.entrySet()){
out.println(" \"" + entry.getKey() + "\": " + entry.getValue());
}
out.println("###############################################################\n");
out.println("Initiating contract analysis");
}
/* 2. Analyze the contract */
//if(verbose) out.println("Creating CCT...");
//nanoTime = System.nanoTime();
// Map<String, Term> cct = new HashMap<String, Term>();
// for(String k : methodMap.keySet()){
// if(methodMap.get(k) != null){
// cct.put(k, methodMap.get(k));
// }
// }
if(verbose) out.println("Applying substitution to Main Contract...");
//cct.put("Main.main", s.apply(InferenceOutput.getMainContractPresent()));
MainMethodContract mmc = new MainMethodContract((Contract)s.apply(InferenceOutput.getMainContractPresent()), (Contract)s.apply(InferenceOutput.getMainContractFuture()));
// List<Contract> mainContracts = new LinkedList<Contract>();
// mainContracts.add(InferenceOutput.getMainContractPresent());
// mainContracts.add(InferenceOutput.getMainContractFuture());
// cct.put("Main.main", s.apply(df.newContractSequence(mainContracts)));
ellapsedTime = (System.nanoTime() - nanoTime)/1000000L;
totalTimeInMs += ellapsedTime;
//
if(verbose) {
out.println("CCT creation completed");
out.println("Ellapsed time: " + ellapsedTime + "ms");
out.println("*****CONTRACTS*******");
Term contract;
for(String k : methodMap.keySet()){
contract = methodMap.get(k);
out.println(" \"" + k + "\": " + ((contract != null) ? (contract.toString()) : ("null")));
}
out.println(" \"MAIN.main\": " + mmc.toString());
out.println("*****END CONTRACTS*******");
}
//
if(verbose){
out.println("###############################################################\n");
out.println("Computing Dependencies...");
}
nanoTime = System.nanoTime();
DASolver solver = (fixPointVersion == FixPoint2_0)? new FixPointSolver2(df, methodMap, mmc):new FixPointSolver1(df, methodMap, mmc, nbIteration);
solver.computeSolution();
ellapsedTime = (System.nanoTime() - nanoTime) / 1000000L;
totalTimeInMs += ellapsedTime;
if(verbose) {
out.println("Dependency analysis completed");
out.println("Ellapsed time: " + ellapsedTime + "ms");
}
out.println("### LOCK INFORMATION RESULTED BY THE ANALYSIS ###\n");
out.println("Possible Deadlock in Main: " + solver.isDeadlockMain());
out.println("Current Version: " + solver.getName() );
if(solver.isDeadlockMain()){
out.println("Deadlock details: ");
solver.printDeadlockDetails(out);
}
if(fixPointVersion == FixPoint1_0){
out.println("Saturation: " + ((FixPointSolver1)solver).isSatured());
out.println("Possible Livelock in Main: " + ((FixPointSolver1)solver).isLivelockMain());
}
out.println("Analysis Duration: " + totalTimeInMs + "ms");
}
}