/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE file at the root of the source * tree and available online at * * https://github.com/keeps/roda */ package org.roda.core.plugins.orchestrate; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.roda.core.RodaCoreFactory; import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.exceptions.JobAlreadyStartedException; import org.roda.core.data.exceptions.RequestNotValidException; import org.roda.core.data.v2.IsRODAObject; import org.roda.core.data.v2.LiteOptionalWithCause; import org.roda.core.data.v2.index.IndexResult; import org.roda.core.data.v2.index.IsIndexed; import org.roda.core.data.v2.index.filter.Filter; import org.roda.core.data.v2.index.sort.Sorter; import org.roda.core.data.v2.index.sublist.Sublist; import org.roda.core.data.v2.jobs.Job; import org.roda.core.index.IndexService; import org.roda.core.model.ModelService; import org.roda.core.plugins.Plugin; import org.roda.core.plugins.PluginException; import org.roda.core.plugins.PluginOrchestrator; import org.roda.core.plugins.orchestrate.akka.Messages.JobPartialUpdate; import org.roda.core.storage.StorageService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.util.concurrent.ThreadFactoryBuilder; /** * * @deprecated 20160323 hsilva: it's not safe to use this orchestrator in * production as it wasn't fully tested and it might have (most * certainly has) strange/not expected behavior */ public class EmbeddedPluginOrchestrator implements PluginOrchestrator { private static final int BLOCK_SIZE = 100; private static final Sorter SORTER = null; private static final int TIMEOUT = 1; private static final TimeUnit TIMEOUT_UNIT = TimeUnit.HOURS; private static final Logger LOGGER = LoggerFactory.getLogger(EmbeddedPluginOrchestrator.class); private final IndexService index; private final ModelService model; private final StorageService storage; private final ExecutorService executorService; public EmbeddedPluginOrchestrator() { index = RodaCoreFactory.getIndexService(); model = RodaCoreFactory.getModelService(); storage = RodaCoreFactory.getStorageService(); final ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("plugin-%d").setDaemon(true).build(); int threads = Runtime.getRuntime().availableProcessors() + 1; executorService = Executors.newFixedThreadPool(threads, threadFactory); LOGGER.debug("Running embedded plugin orchestrator on a {} thread pool", threads); } @Override public void setup() { // do nothing } @Override public void shutdown() { // do nothing } @Override public <T extends IsRODAObject, T1 extends IsIndexed> void runPluginFromIndex(Object context, Class<T1> classToActOn, Filter filter, Plugin<T> plugin) { try { IndexResult<T1> find; int offset = 0; do { // XXX block size could be recommended by plugin find = RodaCoreFactory.getIndexService().find(classToActOn, filter, SORTER, new Sublist(offset, BLOCK_SIZE), new ArrayList<>()); offset += find.getLimit(); // submitPlugin(find.getResults(), plugin); } while (find.getTotalCount() > find.getOffset() + find.getLimit()); finishedSubmit(); } catch (GenericException | RequestNotValidException e) { // TODO this exception handling should be reviewed LOGGER.error("Error running plugin from index", e); } } @SuppressWarnings("unused") private <T extends IsRODAObject> void submitPlugin(List<LiteOptionalWithCause> list, Plugin<T> plugin) { executorService.submit(new Runnable() { @Override public void run() { try { plugin.init(); plugin.execute(index, model, storage, list); plugin.shutdown(); } catch (PluginException e) { LOGGER.error("Plugin submission or execution failed"); } } }); } private boolean finishedSubmit() { executorService.shutdown(); try { return executorService.awaitTermination(TIMEOUT, TIMEOUT_UNIT); } catch (InterruptedException e) { LOGGER.error("Submission finish action failed"); return false; } } @Override public <T extends IsRODAObject> void runPlugin(Object context, Plugin<T> plugin) { } @Override public void executeJob(Job job, boolean async) throws JobAlreadyStartedException { // do nothing } @Override public void stopJob(Job job) { // do nothing } @Override public <T extends IsRODAObject> void updateJobInformation(Plugin<T> plugin, JobPluginInfo jobPluginInfo) { // do nothing } @Override public void cleanUnfinishedJobs() { // do nothing } @Override public <T extends IsRODAObject> void updateJob(Plugin<T> plugin, JobPartialUpdate partialUpdate) { // do nothing } @Override public <T extends IsRODAObject> void runPluginOnAllObjects(Object context, Plugin<T> plugin, Class<T> objectClass) { // do nothing } @Override public <T extends IsRODAObject> void runPluginOnObjects(Object context, Plugin<T> plugin, Class<T> objectClass, List<String> uuids) { // do nothing } @Override public void setJobContextInformation(String jobId, Object object) { // do nothing } @Override public void setJobInError(String jobId) { // do nothing } }