f625cf2197e2ea1dcd189a5e3a0f1b9c272c8bae
[mediacube.git] /
1 package hu.user.mediacube.integration.safedelete;
2
3 import hu.user.mediacube.integration.safedelete.services.ArchiveStatusService;
4 import hu.user.mediacube.integration.safedelete.services.StatusFileService;
5 import hu.user.mediacube.integration.safedelete.verifier.MediaCubeDatabaseService;
6 import hu.user.mediacube.integration.safedelete.verifier.TSMService;
7 import lombok.extern.log4j.Log4j2;
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.stereotype.Component;
10
11 import java.io.IOException;
12 import java.nio.file.DirectoryStream;
13 import java.nio.file.Files;
14 import java.nio.file.Path;
15 import java.nio.file.Paths;
16 import java.time.Duration;
17 import java.time.Instant;
18 import java.time.LocalDate;
19 import java.time.format.DateTimeFormatter;
20 import java.util.Set;
21 import java.util.TimeZone;
22
23 @Component
24 @Log4j2
25 public class SafeDeleteCommand {
26     @Autowired
27     private SafeDeleteProperties safeDeleteProperties;
28
29     @Autowired
30     private MediaCubeDatabaseService mediaCubeDatabaseService;
31
32     @Autowired
33     private TSMService tsmService;
34
35     @Autowired
36     private ArchiveStatusService archivestatusService;
37
38     @Autowired
39     private StatusFileService statusFileService;
40
41     private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(TimeZone.getDefault().toZoneId());
42
43     public void processDirectory(String directory, boolean forceDeleteArchived) throws IOException {
44         archivestatusService.logHeader();
45         final Instant start = Instant.now();
46         log.info("Check directory: {}", directory);
47         log.info("Delete already archived: {}", forceDeleteArchived);
48         Path inputPath = Paths.get(directory);
49
50         Set<String> fileNamesWithKillDates = statusFileService.loadFileNamesWithKillDates(inputPath);
51
52         try (DirectoryStream<Path> stream = Files.newDirectoryStream(inputPath, FileOperations.filterOnlyFiles())) {
53             for (Path filePath : stream) {
54                 ArchiveFileStatus status = archivestatusService.createStatus(filePath);
55
56                 try {
57                     process(filePath, status, fileNamesWithKillDates, forceDeleteArchived);
58                 } catch (Exception e) {
59                     log.error(e.getMessage());
60                     FileOperations.silentRename(filePath, FileOperations.ERROR_FILENAME_PREFIX + formatter.format(LocalDate.now()));
61                 } finally {
62                     archivestatusService.logStatus(status);
63                 }
64
65                 if (safeDeleteProperties.getMaxExecutionHours() > -1
66                         && safeDeleteProperties.getMaxExecutionHours() <= Duration.between(start, Instant.now()).toHours()
67                 ) {
68                     log.info("Reached maximum enabled execution duration {} hours(s)", safeDeleteProperties.getMaxExecutionHours());
69                     break;
70                 }
71             }
72         }
73     }
74
75     private void process(Path filePath, ArchiveFileStatus status, Set<String> fileNamesWithKillDates, boolean forceDeleteArchived) throws Exception {
76         boolean canDelete = fileNamesWithKillDates.contains(status.getFileName());
77         if (canDelete) {
78             if (status.getFileSize() == 0) {
79                 processEmptyInputFile(filePath, status, forceDeleteArchived);
80             } else {
81                 processInputFile(filePath, status, forceDeleteArchived);
82             }
83         } else {
84             log.info("File {} not processed yet by archive system, .killdate status file is missing", filePath.toString());
85         }
86     }
87
88     private void processEmptyInputFile(Path source, ArchiveFileStatus status, boolean forceDeleteArchived) throws Exception {
89         status.setMetadataOnly(true);
90         status.setCanDelete(true);
91         if (forceDeleteArchived) {
92             deleteArchivedFileAndStatusFiles(source, status);
93         }
94     }
95
96     private void processInputFile(Path source, ArchiveFileStatus status, boolean forceDeleteArchived) throws Exception {
97         log.info("Check MediaCube metadata for {}", source);
98         mediaCubeDatabaseService.verify(source, status);
99         log.info("Check TSM file for {}", source);
100         tsmService.verify(source, status);
101         status.setCanDelete(status.isFileSizeEquals() && status.isHashEquals());
102         if (forceDeleteArchived && status.isCanDelete()) {
103             deleteArchivedFileAndStatusFiles(source, status);
104         }
105     }
106
107     private void deleteArchivedFileAndStatusFiles(Path source, ArchiveFileStatus status) throws IOException {
108         String fileName = source.getFileName().toString();
109         Path statusPath = FileOperations.getStatusPath(source);
110         status.setStatusCleanupSuccess(statusFileService.cleanupStatusFiles(statusPath, fileName));
111         status.setDeleteSuccess(FileOperations.silentDelete(source));
112     }
113 }
114