/* * Copyright 2015 Alidays S.p.A. * * 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. */ package it.alidays.mapengine.core.map; import it.alidays.mapengine.core.database.DatabaseManager; import it.alidays.mapengine.enginedirectives.map.Map; import it.alidays.mapengine.enginedirectives.map.Retrieve; import it.alidays.mapengine.util.PerformanceUtils; import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayDeque; import java.util.LinkedHashMap; import java.util.Queue; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Mapper { private static final Logger logger = LoggerFactory.getLogger(Mapper.class); private final DatabaseManager databaseManager; private final AggregatorFactory aggregatorFactory; private final java.util.Map<String, RetrieveHandler> retrieveHandlerMap; private final ExecutorService executor; public Mapper(Map map, DatabaseManager databaseManager) throws MapperException { this.databaseManager = databaseManager; this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); try { this.aggregatorFactory = (AggregatorFactory)Class.forName(map.getAggregatorFactory()).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { throw new MapperException("Failed to istantiate the aggregator factory", e); } this.retrieveHandlerMap = new LinkedHashMap<>(); for (Retrieve retrieve : map.getRetrieves()) { try { AbstractRetrieve<?> abstractRetrieve = (AbstractRetrieve<?>)Class.forName(String.format("%s.%sRetrieve", map.getMapPackage(), retrieve.getId())).getConstructor(String.class).newInstance(retrieve.getId()); this.retrieveHandlerMap.put(retrieve.getId(), new RetrieveHandler(abstractRetrieve, retrieve.getContent())); logger.info("Added retrieve with id '{}'", retrieve.getId()); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException e) { throw new MapperException(String.format("Failed to istantiate the retrieve with id %s", retrieve.getId()), e); } } } public void shutdown() { this.executor.shutdownNow(); } public Object map(UUID vuid) throws MapperException { Object result = null; logger.info("Mapper started..."); PerformanceUtils.notifyStart(Mapper.class, "map", vuid); Aggregator aggregator = this.aggregatorFactory.make(); try (Connection connection = this.databaseManager.getConnection()) { // Esecuzione parallela query Queue<Future<RetrieveResult>> queryFutures = new ArrayDeque<>(); for (String id : this.retrieveHandlerMap.keySet()) { RetrieveTask task = new RetrieveTask(id, this.retrieveHandlerMap.get(id), connection, vuid); queryFutures.add(this.executor.submit(task)); } try { do { Future<RetrieveResult> queryFuture = queryFutures.poll(); RetrieveResult retrieveResult = queryFuture.get(); PerformanceUtils.notifyStart(Mapper.class, String.format("map(aggregate->%s)", retrieveResult.getId()), vuid); aggregator.notifyRetrieveResult(retrieveResult.getId(), retrieveResult.getResult()); PerformanceUtils.notifyEnd(Mapper.class, String.format("map(aggregate->%s)", retrieveResult.getId()), vuid, logger); } while (!queryFutures.isEmpty()); } catch (InterruptedException | ExecutionException | AggregatorException e) { throw new MapperException(e); } } catch (SQLException sqle) { throw new MapperException(sqle); } PerformanceUtils.notifyStart(Mapper.class, "map(getMapResult)", vuid); try { result = aggregator.getMapResult(); } catch (AggregatorException ae) { throw new MapperException(ae); } PerformanceUtils.notifyEnd(Mapper.class, "map(getMapResult)", vuid, logger); PerformanceUtils.notifyEnd(Mapper.class, "map", vuid, logger); logger.info("Mapper completed"); return result; } }