/** * 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.common.monitor; import java.io.IOException; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayDeque; import java.util.Date; import java.util.EnumSet; import java.util.Optional; import org.roda.core.RodaCoreFactory; import org.roda.core.data.common.RodaConstants; import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.exceptions.RequestNotValidException; import org.roda.core.data.v2.index.filter.Filter; import org.roda.core.data.v2.index.filter.NotSimpleFilterParameter; import org.roda.core.data.v2.index.filter.SimpleFilterParameter; import org.roda.core.data.v2.ip.TransferredResource; import org.roda.core.index.IndexService; import org.roda.core.index.utils.SolrUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ReindexTransferredResourcesRunnable implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(ReindexTransferredResourcesRunnable.class); private Path basePath; private Optional<String> folderRelativePath; private IndexService index; public ReindexTransferredResourcesRunnable(IndexService index, Path basePath, Optional<String> folderRelativePath) { this.basePath = basePath; this.index = index; this.folderRelativePath = folderRelativePath; } @Override public void run() { long start = System.currentTimeMillis(); Date lastScanDate = new Date(); RodaCoreFactory.setTransferredResourcesScannerUpdateStatus(folderRelativePath, true); try { EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS); Path path; if (folderRelativePath.isPresent()) { path = basePath.resolve(Paths.get(folderRelativePath.get())); } else { path = basePath; } LOGGER.info("Start indexing transferred resources {}", path); Files.walkFileTree(path, opts, Integer.MAX_VALUE, new FileVisitor<Path>() { ArrayDeque<BasicFileAttributes> actualDirectoryAttributesStack = new ArrayDeque<>(); ArrayDeque<Long> fileSizeStack = new ArrayDeque<>(); @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { actualDirectoryAttributesStack.push(attrs); fileSizeStack.push(0L); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { try { long size = Files.size(file); long actualSize = fileSizeStack.pop(); fileSizeStack.push(actualSize + size); TransferredResource resource = TransferredResourcesScanner.createTransferredResource(file, attrs, size, basePath, lastScanDate); index.create(TransferredResource.class, resource); } catch (GenericException | RequestNotValidException e) { LOGGER.error("Error adding path to Transferred Resources index", e); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { if (!dir.equals(basePath)) { BasicFileAttributes actualDirectoryAttributes = actualDirectoryAttributesStack.pop(); long fileSize = fileSizeStack.pop(); TransferredResource resource = TransferredResourcesScanner.createTransferredResource(dir, actualDirectoryAttributes, fileSize, basePath, lastScanDate); if (!fileSizeStack.isEmpty()) { long actualSize = fileSizeStack.pop(); fileSizeStack.push(actualSize + fileSize); } try { index.create(TransferredResource.class, resource); } catch (GenericException | RequestNotValidException e) { LOGGER.error("Error adding path to Transferred Resources index", e); } } return FileVisitResult.CONTINUE; } }); index.commit(TransferredResource.class); Filter filter; String formattedDate = SolrUtils.getLastScanDate(lastScanDate); if (!folderRelativePath.isPresent()) { filter = new Filter( new NotSimpleFilterParameter(RodaConstants.TRANSFERRED_RESOURCE_LAST_SCAN_DATE, formattedDate)); } else { filter = new Filter( new SimpleFilterParameter(RodaConstants.TRANSFERRED_RESOURCE_ANCESTORS, folderRelativePath.get()), new NotSimpleFilterParameter(RodaConstants.TRANSFERRED_RESOURCE_LAST_SCAN_DATE, formattedDate)); } index.delete(TransferredResource.class, filter); index.commit(TransferredResource.class); LOGGER.info("End indexing Transferred Resources. Time elapsed: {} seconds", (System.currentTimeMillis() - start) / 1000); RodaCoreFactory.setTransferredResourcesScannerUpdateStatus(folderRelativePath, false); } catch (IOException | GenericException | RequestNotValidException | RuntimeException e) { LOGGER.error("Error reindexing Transferred Resources", e); } } }