/**
* 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.plugins.reindex;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.common.RodaConstants.PreservationEventType;
import org.roda.core.data.exceptions.NotFoundException;
import org.roda.core.data.exceptions.RODAException;
import org.roda.core.data.v2.IsRODAObject;
import org.roda.core.data.v2.LiteOptionalWithCause;
import org.roda.core.data.v2.Void;
import org.roda.core.data.v2.index.select.SelectedItemsAll;
import org.roda.core.data.v2.index.select.SelectedItemsNone;
import org.roda.core.data.v2.ip.TransferredResource;
import org.roda.core.data.v2.ip.metadata.IndexedPreservationAgent;
import org.roda.core.data.v2.jobs.Job;
import org.roda.core.data.v2.jobs.PluginType;
import org.roda.core.data.v2.jobs.Report;
import org.roda.core.data.v2.jobs.Report.PluginState;
import org.roda.core.data.v2.log.LogEntry;
import org.roda.core.data.v2.user.RODAMember;
import org.roda.core.index.IndexService;
import org.roda.core.model.ModelService;
import org.roda.core.plugins.AbstractPlugin;
import org.roda.core.plugins.Plugin;
import org.roda.core.plugins.PluginException;
import org.roda.core.plugins.RODAProcessingLogic;
import org.roda.core.plugins.orchestrate.SimpleJobPluginInfo;
import org.roda.core.plugins.plugins.PluginHelper;
import org.roda.core.storage.StorageService;
import org.roda.core.util.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ReindexAllRodaEntitiesPlugin extends AbstractPlugin<Void> {
private static final Logger LOGGER = LoggerFactory.getLogger(ReindexAllRodaEntitiesPlugin.class);
@Override
public void init() throws PluginException {
// do nothing
}
@Override
public void shutdown() {
// do nothing
}
@Override
public String getName() {
return "Rebuild all indexes";
}
@Override
public String getDescription() {
return "Clears all indexes and recreates them from actual physical data that exists on the storage. This task aims to fix inconsistencies between what "
+ "is shown in the graphical user interface of the repository and what is actually kept at the storage layer. Such inconsistencies may occur for "
+ "various reasons, e.g. index corruption, ungraceful shutdown of the repository, etc.";
}
@Override
public String getVersionImpl() {
return "1.0";
}
@Override
public Report execute(IndexService index, ModelService model, StorageService storage,
List<LiteOptionalWithCause> list) throws PluginException {
final List<Class<? extends IsRODAObject>> classes = PluginHelper.getReindexObjectClasses();
classes.remove(Job.class);
return PluginHelper.processVoids(this, new RODAProcessingLogic<Void>() {
@Override
public void process(IndexService index, ModelService model, StorageService storage, Report report, Job cachedJob,
SimpleJobPluginInfo jobPluginInfo, Plugin<Void> plugin) {
reindexAll(model, report, jobPluginInfo, cachedJob, classes);
}
}, index, model, storage, classes.size());
}
private void reindexAll(ModelService model, Report pluginReport, SimpleJobPluginInfo jobPluginInfo, Job job,
List<Class<? extends IsRODAObject>> classes) {
for (Class<? extends IsRODAObject> reindexClass : classes) {
Report reportItem = reindexRODAObject(model, reindexClass, jobPluginInfo);
if (reportItem != null) {
pluginReport.addReport(reportItem);
PluginHelper.updatePartialJobReport(this, model, reportItem, true, job);
}
}
pluginReport.setPluginState(PluginState.SUCCESS);
}
private Report reindexRODAObject(ModelService model, Class<? extends IsRODAObject> reindexClass,
SimpleJobPluginInfo jobPluginInfo) {
LOGGER.debug("Creating job to reindexing all {}", reindexClass.getSimpleName());
Report report = null;
if (model.hasObjects(reindexClass)) {
String jobId = IdUtils.createUUID();
String jobName = ReindexRodaEntityPlugin.class.getSimpleName() + " (" + reindexClass.getSimpleName() + ")";
report = PluginHelper.initPluginReportItem(this, jobId, Job.class);
try {
String username = PluginHelper.getJobUsername(this, model);
Job job = initReindexJob(reindexClass, jobId, jobName, username);
PluginHelper.createAndExecuteJob(job);
jobPluginInfo.incrementObjectsProcessedWithSuccess();
report.setPluginState(PluginState.SUCCESS).setPluginDetails(jobName + " ran successfully");
} catch (RODAException e) {
LOGGER.error("Error creating job to reindex all {}", reindexClass.getSimpleName(), e);
jobPluginInfo.incrementObjectsProcessedWithFailure();
report.setPluginState(PluginState.FAILURE).setPluginDetails(jobName + " did not run successfully");
}
} else {
jobPluginInfo.incrementObjectsProcessedWithSuccess();
}
return report;
}
private <T extends IsRODAObject> Job initReindexJob(Class<T> reindexClass, String jobId, String jobName,
String username) throws NotFoundException {
Job job = new Job();
job.setId(jobId);
job.setName(jobName);
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_CLEAR_INDEXES, "true");
job.setPluginParameters(pluginParameters);
job.setPluginType(PluginType.MISC);
job.setUsername(username);
job.setPlugin(PluginHelper.getReindexPluginName(reindexClass));
if (TransferredResource.class.equals(reindexClass) || LogEntry.class.equals(reindexClass)
|| RODAMember.class.equals(reindexClass) || IndexedPreservationAgent.class.equals(reindexClass)) {
job.setSourceObjects(SelectedItemsNone.create());
} else {
job.setSourceObjects(SelectedItemsAll.create(reindexClass));
}
return job;
}
@Override
public Report beforeAllExecute(IndexService index, ModelService model, StorageService storage)
throws PluginException {
// Do not need to clear indexes, single jobs already does it by default
return new Report();
}
@Override
public Report afterAllExecute(IndexService index, ModelService model, StorageService storage) throws PluginException {
// Do not need to optimize indexes, single jobs already does it by default
return new Report();
}
@Override
public Plugin<Void> cloneMe() {
return new ReindexAllRodaEntitiesPlugin();
}
@Override
public PluginType getType() {
return PluginType.MISC;
}
@Override
public boolean areParameterValuesValid() {
return true;
}
@Override
public PreservationEventType getPreservationEventType() {
return PreservationEventType.NONE;
}
@Override
public String getPreservationEventDescription() {
return "Reindex Roda entity";
}
@Override
public String getPreservationEventSuccessMessage() {
return "All entities were reindexed with success";
}
@Override
public String getPreservationEventFailureMessage() {
return "An error occured while reindexing all entities";
}
@Override
public List<String> getCategories() {
return Arrays.asList(RodaConstants.PLUGIN_CATEGORY_REINDEX);
}
@Override
public List<Class<Void>> getObjectClasses() {
return Arrays.asList(Void.class);
}
}