All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hp.autonomy.searchcomponents.hod.databases.ForkJoinResourceMapper Maven / Gradle / Ivy

/*
 * Copyright 2015 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.searchcomponents.hod.databases;

import com.hp.autonomy.hod.client.api.authentication.TokenType;
import com.hp.autonomy.hod.client.api.resource.Resource;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.hod.client.token.TokenProxy;
import com.hp.autonomy.searchcomponents.hod.fields.IndexFieldsService;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * ResourceMapper that uses a {@link ForkJoinPool} to perform mapping in parallel. If using the internal ForkJoinPool,
 * the {@link #destroy} method should be called when the ResourceMapper is finished with.
 */
@Slf4j
public class ForkJoinResourceMapper extends AbstractResourceMapper {
    private final ForkJoinPool forkJoinPool;

    /**
     * Constructs a new ForkJoinResourceMapper with the given IndexFieldsService. The {@link #destroy} method should be
     * called when using this constructor when the ForkJoinResourceMapper is finished with.
     * @param indexFieldsService The IndexFieldsService to use
     */
    public ForkJoinResourceMapper(final IndexFieldsService indexFieldsService) {
        this(indexFieldsService, new ForkJoinPool());
    }

    /**
     * Constructs a new ForkJoinResourceMapper with the given IndexFieldsService and ForkJoinPool.
     * @param indexFieldsService The IndexFieldsService to use
     * @param forkJoinPool The ForkJoinPool to use
     */
    public ForkJoinResourceMapper(final IndexFieldsService indexFieldsService, final ForkJoinPool forkJoinPool) {
        super(indexFieldsService);

        this.forkJoinPool = forkJoinPool;
    }

    /**
     * Shuts down the ForkJoinPool.
     */
    public void destroy() {
        forkJoinPool.shutdown();
    }

    @Override
    public Set map(final TokenProxy tokenProxy, final Set resources, final String domain) throws HodErrorException {
        final DatabaseTask privateTask = new DatabaseTask(tokenProxy, new ArrayList<>(resources), domain);

        forkJoinPool.submit(privateTask);

        try {
            return privateTask.get();
        } catch (final InterruptedException e) {
            // preserve interrupted status
            Thread.currentThread().interrupt();
            // anything we return may be incomplete
            throw new IllegalStateException("Interrupted while waiting for parametric fields", e);
        } catch (final ExecutionException e) {
            Throwable currentException = e;

            // look for HodErrorException in the cause chain so we can throw it
            while (currentException != null && currentException != currentException.getCause()) {
                if (currentException instanceof HodErrorException) {
                    throw (HodErrorException) currentException;
                }

                currentException = currentException.getCause();
            }

            throw new IllegalStateException("Error occurred executing task", e);
        }
    }

    private class DatabaseTask extends RecursiveTask> {

        private static final long serialVersionUID = -8514152774998360171L;
        private final TokenProxy tokenProxy;
        private final List inputResources;
        private final String domain;

        private DatabaseTask(final TokenProxy tokenProxy, final List inputResources, final String domain) {
            this.tokenProxy = tokenProxy;
            this.inputResources = inputResources;
            this.domain = domain;
        }

        @Override
        protected Set compute() {
            if (inputResources.isEmpty()) {
                return Collections.emptySet();
            }
            else if(inputResources.size() == 1) {

                final Database database;

                try {
                    database = databaseForResource(tokenProxy, inputResources.get(0), domain);
                } catch (final HodErrorException e) {
                    completeExceptionally(e);
                    // this value is irrelevant as completeExceptionally will throw a RuntimeException
                    return null;
                }

                return Collections.singleton(database);
            }
            else {
                final int middle = (inputResources.size() / 2); // truncation is OK

                final DatabaseTask left =  new DatabaseTask(tokenProxy, inputResources.subList(0, middle), domain);
                left.fork();

                final DatabaseTask right = new DatabaseTask(tokenProxy, inputResources.subList(middle, inputResources.size()), domain);
                right.fork();

                final Set result = new HashSet<>();
                result.addAll(left.join());
                result.addAll(right.join());

                return result;
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy