package uk.ac.imperial.lsds.seepmaster.query; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.imperial.lsds.seep.api.QueryExecutionMode; import uk.ac.imperial.lsds.seep.api.QueryType; import uk.ac.imperial.lsds.seep.api.operator.SeepLogicalQuery; import uk.ac.imperial.lsds.seep.comm.Comm; import uk.ac.imperial.lsds.seep.errors.NotImplementedException; import uk.ac.imperial.lsds.seep.infrastructure.ControlEndPoint; import uk.ac.imperial.lsds.seep.infrastructure.SeepEndPoint; import uk.ac.imperial.lsds.seep.scheduler.ScheduleDescription; import uk.ac.imperial.lsds.seep.util.Utils; import uk.ac.imperial.lsds.seepmaster.LifecycleManager; import uk.ac.imperial.lsds.seepmaster.MasterConfig; import uk.ac.imperial.lsds.seepmaster.infrastructure.master.InfrastructureManager; public class GenericQueryManager implements QueryManager { final private Logger LOG = LoggerFactory.getLogger(GenericQueryManager.class); private MasterConfig mc; // Singleton instance made available to client (Master) private static GenericQueryManager gqm; // The actual QueryManager backend private QueryManager qm; private InfrastructureManager inf; private Map<Integer, ControlEndPoint> opToEndpointMapping; private Comm comm; private LifecycleManager lifeManager; public static GenericQueryManager getInstance(InfrastructureManager inf, Map<Integer, ControlEndPoint> mapOpToEndPoint, Comm comm, LifecycleManager lifeManager, MasterConfig mc){ if(gqm == null){ gqm = new GenericQueryManager(inf, mapOpToEndPoint, comm, lifeManager, mc); } return gqm; } private GenericQueryManager(InfrastructureManager inf, Map<Integer, ControlEndPoint> mapOpToEndPoint, Comm comm, LifecycleManager lifeManager, MasterConfig mc){ this.inf = inf; this.opToEndpointMapping = mapOpToEndPoint; this.comm = comm; this.lifeManager = lifeManager; this.mc = mc; } @Override public boolean loadQueryFromParameter(short queryType, SeepLogicalQuery slq, String pathToQueryJar, String definitionClassName, String[] queryArgs, String composeMethodName) { // Check whether the action is valid, but GenericQueryManager does not change Lifecycle boolean allowed = lifeManager.canTransitTo(LifecycleManager.AppStatus.QUERY_SUBMITTED); if(!allowed){ LOG.error("Attempt to violate application lifecycle"); return false; } LOG.debug("Logical query loaded: {}", slq.toString()); // This is the only operation fully handled by QueryManager // After checking queryExecutionMode it creates an appropriate queryManager and // delegates all operations to that one QueryExecutionMode qem = slq.getQueryExecutionMode(); qm = this.getQueryManagerForExecutionMode(qem, queryType); boolean success = qm.loadQueryFromParameter(queryType, slq, pathToQueryJar, definitionClassName, queryArgs, composeMethodName); return success; } @Override public boolean loadQueryFromFile(short queryType, String pathToQueryJar, String definitionClassName, String[] queryArgs, String composeMethodName) { // Check whether the action is valid, but GenericQueryManager does not change Lifecycle boolean allowed = lifeManager.canTransitTo(LifecycleManager.AppStatus.QUERY_SUBMITTED); if(!allowed){ LOG.error("Attempt to violate application lifecycle"); return false; } // TODO: do something with the type at this point if(queryType == QueryType.SEEPLOGICALQUERY.ofType()) { // get logical query SeepLogicalQuery slq = Utils.executeComposeFromQuery(pathToQueryJar, definitionClassName, queryArgs, composeMethodName); if (slq == null) { LOG.error("Failed to load class " + definitionClassName + " from file " + pathToQueryJar); return false; } return this.loadQueryFromParameter(queryType, slq, pathToQueryJar, definitionClassName, queryArgs, composeMethodName); } else if (queryType == QueryType.SCHEDULE.ofType()) { ScheduleDescription schedule = Utils.executeComposeFromQuery(pathToQueryJar, definitionClassName, queryArgs, composeMethodName); if (schedule == null) { LOG.error("Failed to load class " + definitionClassName + " from file " + pathToQueryJar); return false; } // Otherwise create the scheduleQueryManager QueryExecutionMode qem = QueryExecutionMode.ALL_SCHEDULED; qm = this.getQueryManagerForExecutionMode(qem, queryType); // and load the scheduleDescription directly ((ScheduledQueryManager)qm).loadSchedule(schedule, pathToQueryJar, definitionClassName, queryArgs, composeMethodName); return true; } LOG.error("Unrecognized Query type or non implemented"); return false; } private QueryManager getQueryManagerForExecutionMode(QueryExecutionMode qem, short queryType) { QueryManager qm = null; switch (qem){ case ALL_MATERIALIZED: LOG.info("Creating MaterializedQueryManager..."); qm = MaterializedQueryManager.getInstance(inf, opToEndpointMapping, comm, lifeManager, mc); LOG.info("Creating MaterializedQueryManager...OK"); break; case ALL_SCHEDULED: LOG.info("Creating ScheduledQueryManager..."); qm = ScheduledQueryManager.getInstance(inf, comm, lifeManager, mc, queryType); LOG.info("Creating ScheduledQueryManager...OK"); break; case AUTOMATIC_HYBRID: throw new NotImplementedException("Not implemented (?)"); default: LOG.error("Execution Mode not supported !"); throw new NotImplementedException("Most likely lacks implementation (?)"); } return qm; } @Override public boolean deployQueryToNodes() { return this.qm.deployQueryToNodes(); } @Override public boolean startQuery() { return this.qm.startQuery(); } @Override public boolean stopQuery() { return this.qm.stopQuery(); } public QueryManager getQueryManager() { return qm; } }