/** * This file is part of General Entity Annotator Benchmark. * * General Entity Annotator Benchmark is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * General Entity Annotator Benchmark is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with General Entity Annotator Benchmark. If not, see <http://www.gnu.org/licenses/>. */ package org.aksw.gerbil.database; import java.util.ArrayList; import java.util.List; import org.aksw.gerbil.datatypes.ErrorTypes; import org.aksw.gerbil.datatypes.ExperimentTaskResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Abstract class implementing the general behavior of an {@link ExperimentDAO}. * Note that it is strongly recommended to extend this class instead of * implementing the {@link ExperimentDAO} class directly since this class * already takes care of the synchronization problem of the * {@link ExperimentDAO#connectCachedResultOrCreateTask(String, String, String, String, String)} method. * * @author m.roeder * */ public abstract class AbstractExperimentDAO implements ExperimentDAO { private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentDAOImpl.class); /** * Sentinel value used to indicate that an experiment task with the given * preferences couldn't be found. */ protected static final int EXPERIMENT_TASK_NOT_CACHED = -1; protected long resultDurability; protected boolean initialized = false; public AbstractExperimentDAO() { } public AbstractExperimentDAO(long resultDurability) { setResultDurability(resultDurability); } /** * The {@link AbstractExperimentDAO} class makes sure that an instance is * initialized only once even if this method is called multiple times. */ @Override public void initialize() { if (!initialized) { /* * We only have to set back the status of experiments that were * running while the server has been stopped. */ setRunningExperimentsToError(); } } /** * Searches the database for experiment tasks that have been started but not * ended yet (their status equals {@link #TASK_STARTED_BUT_NOT_FINISHED_YET} ) and set their status to * {@link ErrorTypes#SERVER_STOPPED_WHILE_PROCESSING}. This method should * only be called directly after the initialization of the database. It * makes sure that "old" experiment tasks which have been started but never * finished are set to an error state and can't be used inside the caching * mechanism. */ protected abstract void setRunningExperimentsToError(); @Override public void setResultDurability(long resultDurability) { this.resultDurability = resultDurability; } public long getResultDurability() { return resultDurability; } @Override public synchronized int connectCachedResultOrCreateTask(String annotatorName, String datasetName, String experimentType, String matching, String experimentId) { int experimentTaskId = EXPERIMENT_TASK_NOT_CACHED; if (resultDurability > 0) { experimentTaskId = getCachedExperimentTaskId(annotatorName, datasetName, experimentType, matching); } else { LOGGER.warn("The durability of results is <= 0. I won't be able to cache results."); } if (experimentTaskId == EXPERIMENT_TASK_NOT_CACHED) { return createTask(annotatorName, datasetName, experimentType, matching, experimentId); } else { LOGGER.debug("Could reuse cached task (id={}).", experimentTaskId); connectExistingTaskWithExperiment(experimentTaskId, experimentId); return CACHED_EXPERIMENT_TASK_CAN_BE_USED; } } /** * The method checks whether there exists an experiment task with the given * preferences inside the database. If such a task exists, if it is not to * old regarding the durability of experiment task results and if its state * is not an error code, its experiment task id is returned. Otherwise {@link #EXPERIMENT_TASK_NOT_CACHED} is * returned. * * <b>NOTE:</b> this method MUST be synchronized since it should only be * called by a single thread at once. * * @param annotatorName * the name with which the annotator can be identified * @param datasetName * the name of the dataset * @param experimentType * the name of the experiment type * @param matching * the name of the matching used * @return The id of the experiment task or {@value #EXPERIMENT_TASK_NOT_CACHED} if such an experiment task * couldn't be found. */ protected abstract int getCachedExperimentTaskId(String annotatorName, String datasetName, String experimentType, String matching); /** * This method connects an already existing experiment task with an * experiment. * * @param experimentTaskId * the id of the experiment task * @param experimentId * the id of the experiment */ protected abstract void connectExistingTaskWithExperiment(int experimentTaskId, String experimentId); @Deprecated @Override public List<ExperimentTaskResult> getLatestResultsOfExperiments(String experimentType, String matching) { List<String[]> experimentTasks = getAnnotatorDatasetCombinations(experimentType, matching); List<ExperimentTaskResult> results = new ArrayList<ExperimentTaskResult>(experimentTasks.size()); ExperimentTaskResult result; for (String combination[] : experimentTasks) { result = getLatestExperimentTaskResult(experimentType, matching, combination[0], combination[1]); if (result != null) { results.add(result); } } return results; } /** * This method returns a list of annotator dataset combinations for the given experimentType and matching that exist * inside the database. The first element of every array contains the name of an annotator and the second element is * the name of a dataset. * * @param experimentType * the name of the experiment type * @param matching * the name of the matching used * @return a list of annotator dataset combinations */ @Deprecated protected abstract List<String[]> getAnnotatorDatasetCombinations(String experimentType, String matching); /** * Returns the result of the most recent finished experiment task with the given experiment type, matchin, annotator * and dataset. * * @param annotatorName * the name with which the annotator can be identified * @param datasetName * the name of the dataset * @param experimentType * the name of the experiment type * @param matching * the name of the matching used * @return the result of the most recent experiment task or null if no such task exists */ @Deprecated protected abstract ExperimentTaskResult getLatestExperimentTaskResult(String experimentType, String matching, String annotatorName, String datasetName); }