1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.workingfilerepository.impl;
23
24 import org.opencastproject.workingfilerepository.api.WorkingFileRepository;
25
26 import org.quartz.Job;
27 import org.quartz.JobDetail;
28 import org.quartz.JobExecutionContext;
29 import org.quartz.JobExecutionException;
30 import org.quartz.Trigger;
31 import org.quartz.TriggerUtils;
32 import org.quartz.impl.StdSchedulerFactory;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import java.io.IOException;
37 import java.util.Date;
38 import java.util.List;
39
40
41 public class WorkingFileRepositoryCleaner {
42 private static final Logger logger = LoggerFactory.getLogger(WorkingFileRepositoryCleaner.class);
43
44 private static final String JOB_NAME = "working-file-repository-cleaner-job";
45 private static final String JOB_GROUP = "working-file-repository-cleaner-job-group";
46 private static final String TRIGGER_NAME = "working-file-repository-cleaner-trigger";
47 private static final String TRIGGER_GROUP = "working-file-repository-cleaner-trigger-group";
48 private static final String JOB_PARAM_PARENT = "parent";
49
50 private final org.quartz.Scheduler quartz;
51
52 private final WorkingFileRepository workingFileRepository;
53 private final int maxAge;
54 private int schedulerPeriod;
55 private List<String> collectionIds;
56
57 protected WorkingFileRepositoryCleaner(WorkingFileRepository workingFileRepository, int schedulerPeriod, int maxAge,
58 List<String> collectionIds) {
59 this.workingFileRepository = workingFileRepository;
60 this.maxAge = maxAge;
61 this.schedulerPeriod = schedulerPeriod;
62 this.collectionIds = collectionIds;
63
64 if (maxAge <= 0) {
65 logger.debug("No scheduler initialized due to invalid max age setting ({})", schedulerPeriod);
66 quartz = null;
67 return;
68 }
69
70
71 if (schedulerPeriod <= 0) {
72 logger.debug("No scheduler initialized due to invalid scheduling period ({})", schedulerPeriod);
73 quartz = null;
74 return;
75 }
76
77 if (collectionIds == null || collectionIds.size() == 0) {
78 logger.debug("No scheduler initialized due to invalid working file collection ({})", collectionIds);
79 quartz = null;
80 return;
81 }
82
83 try {
84 quartz = new StdSchedulerFactory().getScheduler();
85 quartz.start();
86
87 final JobDetail job = new JobDetail(JOB_NAME, JOB_GROUP, Runner.class);
88 job.setDurability(false);
89 job.setVolatility(true);
90 job.getJobDataMap().put(JOB_PARAM_PARENT, this);
91 quartz.addJob(job, true);
92 } catch (org.quartz.SchedulerException e) {
93 throw new RuntimeException(e);
94 }
95 }
96
97
98
99
100 public void schedule() {
101 if (quartz == null || schedulerPeriod <= 0) {
102 logger.warn("Cancel scheduling of workspace cleaner due to invalid scheduling period");
103 return;
104 }
105 logger.debug("Scheduling workspace cleaner to run every {} seconds.", schedulerPeriod);
106 try {
107 final Trigger trigger = TriggerUtils.makeSecondlyTrigger(schedulerPeriod);
108 trigger.setStartTime(new Date());
109 trigger.setName(TRIGGER_NAME);
110 trigger.setGroup(TRIGGER_GROUP);
111 trigger.setJobName(JOB_NAME);
112 trigger.setJobGroup(JOB_GROUP);
113 if (quartz.getTriggersOfJob(JOB_NAME, JOB_GROUP).length == 0) {
114 quartz.scheduleJob(trigger);
115 } else {
116 quartz.rescheduleJob(TRIGGER_NAME, TRIGGER_GROUP, trigger);
117 }
118 } catch (Exception e) {
119 logger.error("Error scheduling Quartz job", e);
120 }
121 }
122
123
124 public void shutdown() {
125 try {
126 quartz.shutdown();
127 } catch (org.quartz.SchedulerException ignore) {
128 }
129 }
130
131
132 @Override
133 protected void finalize() throws Throwable {
134 super.finalize();
135 shutdown();
136 }
137
138
139 private void cleanup() {
140 for (String collectionId : collectionIds) {
141 try {
142 workingFileRepository.cleanupOldFilesFromCollection(collectionId, maxAge);
143 } catch (IOException e) {
144 logger.error("Cleaning of collection with id:{} failed", collectionId);
145 }
146 }
147 try {
148 workingFileRepository.cleanupOldFilesFromMediaPackage(maxAge);
149 } catch (IOException e) {
150 logger.error("Cleaning of mediapackages failed");
151 }
152 }
153
154
155
156
157 public static class Runner implements Job {
158
159 @Override
160 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
161 logger.debug("Start working file repository cleaner");
162 try {
163 execute((WorkingFileRepositoryCleaner) jobExecutionContext.getJobDetail().getJobDataMap().get(JOB_PARAM_PARENT));
164 } catch (Exception e) {
165 throw new JobExecutionException("An error occurred while cleaning working file repository", e);
166 }
167 logger.debug("Finished working file repository cleaner");
168 }
169
170 private void execute(WorkingFileRepositoryCleaner workingFileRepositoryCleaner) {
171 workingFileRepositoryCleaner.cleanup();
172 }
173 }
174 }