comparison artifact-database/src/main/java/de/intevation/artifactdatabase/DatabaseCleaner.java @ 90:68285f7bc476

More javadoc. artifacts/trunk@846 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 26 Mar 2010 17:59:50 +0000
parents 8447467cef86
children 730ff077a58c
comparison
equal deleted inserted replaced
89:d348fe1fd822 90:68285f7bc476
13 13
14 import java.util.ArrayList; 14 import java.util.ArrayList;
15 import java.util.List; 15 import java.util.List;
16 16
17 /** 17 /**
18 * The database cleaner runs in background. It sleep for a configurable
19 * while and when it wakes up it removes outdated artifacts from the
20 * database. Outdated means that the the last access to the artifact
21 * is longer aga then the time to live of this artifact.<br>
22 * Before the artifact is finally removed from the system it is
23 * revived one last time an the #endOfLife() method of the artifact
24 * is called.<br>
25 * The artifact implementations may e.g. use this to remove some extrenal
26 * resources form the system.
27 *
18 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> 28 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
19 */ 29 */
20 public class DatabaseCleaner 30 public class DatabaseCleaner
21 extends Thread 31 extends Thread
22 { 32 {
33 /**
34 * Implementors of this interface are able to create a
35 * living artifact from a given byte array.
36 */
23 public interface ArtifactReviver { 37 public interface ArtifactReviver {
24 38
39 /**
40 * Called to revive an artifact from a given byte array.
41 * @param factoryName The name of the factory which
42 * created this artifact.
43 * @param bytes The bytes of the serialized artifact.
44 * @return The revived artfiact.
45 */
25 Artifact reviveArtifact(String factoryName, byte [] bytes); 46 Artifact reviveArtifact(String factoryName, byte [] bytes);
26 47
27 } // interface ArtifactReviver 48 } // interface ArtifactReviver
28 49
29 private static Logger logger = Logger.getLogger(DatabaseCleaner.class); 50 private static Logger logger = Logger.getLogger(DatabaseCleaner.class);
30 51
52 /**
53 * Number of artifacts to be loaded at once. Used to
54 * mitigate the problem of a massive denial of service
55 * if too many artifacts have died since last cleanup.
56 */
31 public static final int MAX_ROWS = 50; 57 public static final int MAX_ROWS = 50;
32 58
59 /**
60 * The SQL statement to select the outdated artifacts.
61 */
33 public static final String SQL_OUTDATED = 62 public static final String SQL_OUTDATED =
34 SQL.get("artifacts.outdated"); 63 SQL.get("artifacts.outdated");
35 64
65 /**
66 * The SQL statement to delete some artifacts from the database.
67 */
36 public static final String SQL_DELETE = 68 public static final String SQL_DELETE =
37 SQL.get("artifacts.delete"); 69 SQL.get("artifacts.delete");
38 70
71 /**
72 * XPath to figure out how long the cleaner should sleep between
73 * cleanups. This is stored in the global configuration.
74 */
39 public static final String SLEEP_XPATH = 75 public static final String SLEEP_XPATH =
40 "/artifact-database/cleaner/sleep-time/text()"; 76 "/artifact-database/cleaner/sleep-time/text()";
41 77
78 /**
79 * Default nap time between cleanups: 5 minutes.
80 */
42 public static final long SLEEP_DEFAULT = 81 public static final long SLEEP_DEFAULT =
43 5 * 60 * 1000L; // 5 minutes 82 5 * 60 * 1000L; // 5 minutes
44 83
84 /**
85 * The configured nap time.
86 */
45 protected long sleepTime; 87 protected long sleepTime;
46 88
89 /**
90 * Internal locking mechanism to prevent some race conditions.
91 */
47 protected Object sleepLock = new Object(); 92 protected Object sleepLock = new Object();
48 93
94 /**
95 * A reference to the global context.
96 */
49 protected Object context; 97 protected Object context;
50 98
99 /**
100 * A specialized Id filter which only delete some artifacts.
101 * This is used to prevent deletion of living artifacts.
102 */
51 protected Id.Filter filter; 103 protected Id.Filter filter;
52 104
105 /**
106 * The reviver used to bring the dead artifact on last
107 * time back to live to call endOfLife() on them.
108 */
53 protected ArtifactReviver reviver; 109 protected ArtifactReviver reviver;
54 110
111 /**
112 * Default constructor.
113 */
55 public DatabaseCleaner() { 114 public DatabaseCleaner() {
56 } 115 }
57 116
117 /**
118 * Constructor to create a cleaner with a given global context
119 * and an given reviver.
120 * @param context The global context of the artifact database
121 * @param reviver The reviver to awake artifact one last time.
122 */
58 public DatabaseCleaner(Object context, ArtifactReviver reviver) { 123 public DatabaseCleaner(Object context, ArtifactReviver reviver) {
59 setDaemon(true); 124 setDaemon(true);
60 sleepTime = getSleepTime(); 125 sleepTime = getSleepTime();
61 this.context = context; 126 this.context = context;
62 this.reviver = reviver; 127 this.reviver = reviver;
63 } 128 }
64 129
130 /**
131 * Sets the filter that prevents deletion of living artifacts.
132 * Living artifacts are artifacts which are currently active
133 * inside the artifact database. Deleting them in this state
134 * would create severe internal problems.
135 * @param filter
136 */
65 public void setFilter(Id.Filter filter) { 137 public void setFilter(Id.Filter filter) {
66 this.filter = filter; 138 this.filter = filter;
67 } 139 }
68 140
141 /**
142 * External hook to tell the cleaner to wake up before its
143 * regular nap time is over. This is the case when the artifact
144 * database finds an artifact which is already outdated.
145 */
69 public void wakeup() { 146 public void wakeup() {
70 synchronized (sleepLock) { 147 synchronized (sleepLock) {
71 sleepLock.notify(); 148 sleepLock.notify();
72 } 149 }
73 } 150 }
74 151
152 /**
153 * Fetches the sleep time from the global configuration.
154 * @return the time to sleep between database cleanups in ms.
155 */
75 protected static long getSleepTime() { 156 protected static long getSleepTime() {
76 String sleepTimeString = Config.getStringXPath(SLEEP_XPATH); 157 String sleepTimeString = Config.getStringXPath(SLEEP_XPATH);
77 158
78 if (sleepTimeString == null) { 159 if (sleepTimeString == null) {
79 return SLEEP_DEFAULT; 160 return SLEEP_DEFAULT;
200 } 281 }
201 282
202 logger.info("artifacts removed: " + removedArtifacts); 283 logger.info("artifacts removed: " + removedArtifacts);
203 } 284 }
204 285
286 /**
287 * The main code of the cleaner. It sleeps for the configured
288 * nap time, cleans up the database, sleeps again and so on.
289 */
290 @Override
205 public void run() { 291 public void run() {
206 logger.info("sleep time: " + sleepTime + "ms"); 292 logger.info("sleep time: " + sleepTime + "ms");
207 for (;;) { 293 for (;;) {
208 cleanup(); 294 cleanup();
209 long startTime = System.currentTimeMillis(); 295 long startTime = System.currentTimeMillis();
222 logger.debug("Cleaner slept " + (stopTime - startTime) + "ms"); 308 logger.debug("Cleaner slept " + (stopTime - startTime) + "ms");
223 } 309 }
224 } // for (;;) 310 } // for (;;)
225 } 311 }
226 } 312 }
227 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: 313 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org