/** * */ package edu.washington.escience.myria.perfenforce; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; import java.io.StringWriter; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import org.apache.commons.io.IOUtils; import org.slf4j.LoggerFactory; import com.amazonaws.auth.AnonymousAWSCredentials; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.GetObjectRequest; import com.google.gson.Gson; import edu.washington.escience.myria.api.encoding.PerfEnforceQueryMetadataEncoding; import edu.washington.escience.myria.api.encoding.PerfEnforceTableEncoding; import edu.washington.escience.myria.parallel.Server; /** * The PerfEnforce Driver * */ public final class PerfEnforceDriver { protected static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(PerfEnforceDriver.class); /** The cluster sizes PerfEnforce considers. */ final public static List<Integer> configurations = Arrays.asList(4, 6, 8, 10, 12); /** The configuration path storing PerfEnforce helper files. */ public static Path configurationPath; /** The list of relations from the user. */ public static List<PerfEnforceTableEncoding> tableList; /** Metadata about the fact table. */ public static PerfEnforceTableEncoding factTableDesc; private final Server server; private String dataPreparationStatus; private boolean isDonePSLA; private PerfEnforceOnlineLearning perfenforceOnlineLearning; /** * Constructor for the PerfEnforceDriver * * @param server the instance of the server * @param instancePath the path for the Myria deployment */ public PerfEnforceDriver(final Server server, final String instancePath) { configurationPath = (Paths.get(instancePath, "perfenforce_files")); this.server = server; dataPreparationStatus = ""; isDonePSLA = false; } /** * Fetch necessary files from S3 * @throws PerfEnforceException throws an exception if there is an error fetching files from S3 */ public void fetchS3Files() throws PerfEnforceException { AmazonS3 s3Client = new AmazonS3Client(new AnonymousAWSCredentials()); String currentFile = ""; try { try (BufferedReader bufferedReader = new BufferedReader( new FileReader(configurationPath.resolve("filesToFetch.txt").toString()))) { while ((currentFile = bufferedReader.readLine()) != null) { Path filePath = configurationPath.resolve(currentFile); s3Client.getObject( new GetObjectRequest("perfenforce", currentFile), new File(filePath.toString())); } } } catch (Exception e) { throw new PerfEnforceException("Error while fetching files from S3"); } } /** * Prepares the PSLA given a list of tables * * @param tableList the tables from the user's dataset */ public void preparePSLA(List<PerfEnforceTableEncoding> tableList) throws Exception { isDonePSLA = false; PerfEnforceDriver.tableList = tableList; fetchS3Files(); PerfEnforceDataPreparation perfenforceDataPrepare = new PerfEnforceDataPreparation(server); dataPreparationStatus = "Ingesting Data"; for (PerfEnforceTableEncoding currentTable : tableList) { if (currentTable.type.equalsIgnoreCase("fact")) { perfenforceDataPrepare.ingestFact(currentTable); factTableDesc = currentTable; } else { perfenforceDataPrepare.ingestDimension(currentTable); } dataPreparationStatus = "Analyzing Data"; perfenforceDataPrepare.analyzeTable(currentTable); } dataPreparationStatus = "Collecting Statistics"; perfenforceDataPrepare.collectSelectivities(); Gson gson = new Gson(); String schemaDefinitionFile = gson.toJson(tableList); try (PrintWriter out = new PrintWriter( configurationPath .resolve("PSLAGeneration") .resolve("SchemaDefinition.json") .toString())) { out.print(schemaDefinitionFile); } dataPreparationStatus = "Generating Queries for PSLA"; PSLAManagerWrapper pslaManager = new PSLAManagerWrapper(); pslaManager.generateQueries(); perfenforceDataPrepare.collectFeaturesFromGeneratedQueries(); pslaManager.generatePSLA(); dataPreparationStatus = "Finished"; isDonePSLA = true; } /** * Returns the status of the PSLA generation process * @return the data preparation status */ public String getDataPreparationStatus() { return dataPreparationStatus; } /** * Return a boolean to determine whether the PSLA is finished generating * @return a boolean determining whether the PSLA is finished */ public boolean isDonePSLA() { return isDonePSLA; } /** * Returns the final PSLA * @return the generated PSLA * @throws PerfEnforceException if there is an error generating the PSLA */ public String getPSLA() throws PerfEnforceException { StringWriter output = new StringWriter(); try { Reader input = new FileReader( new File( configurationPath .resolve("PSLAGeneration") .resolve("FinalPSLA.json") .toString())); IOUtils.copy(input, output); } catch (IOException e) { throw new PerfEnforceException(); } return output.toString(); } /** * Sets the tier selected by the user * * @param tier the tier selected */ public void setTier(final int tier) { perfenforceOnlineLearning = new PerfEnforceOnlineLearning(server, tier); } /** * Finds the SLA for a given query * * @param querySQL the given query * @throws PerfEnforceException if there is an error computing the SLA for a query */ public void findSLA(String querySQL) throws PerfEnforceException { perfenforceOnlineLearning.findSLA(querySQL); perfenforceOnlineLearning.findBestConfigurationSize(); } /** * Records the runtime of a query * * @param queryRuntime the runtime of a query * @throws PerfEnforceException throws an exception if */ public void recordRealRuntime(final Double queryRuntime) throws PerfEnforceException { perfenforceOnlineLearning.recordRealRuntime(queryRuntime); } /** * Returns information about the current query, assuming the user recently requested the SLA * @return metadata about the current query */ public PerfEnforceQueryMetadataEncoding getCurrentQuery() { return perfenforceOnlineLearning.getCurrentQuery(); } /** * Returns the current cluster size * @return the current cluster size */ public int getClusterSize() { return perfenforceOnlineLearning.getClusterSize(); } }