diff -r 5a4a41cfc0a3 -r ed84c8bdd87b src/org/sonews/util/Purger.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/sonews/util/Purger.java Sun Aug 29 17:28:58 2010 +0200 @@ -0,0 +1,149 @@ +/* + * SONEWS News Server + * see AUTHORS for the list of contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sonews.util; + +import org.sonews.daemon.AbstractDaemon; +import org.sonews.config.Config; +import org.sonews.storage.Article; +import org.sonews.storage.Headers; +import java.util.Date; +import java.util.List; +import org.sonews.storage.Channel; +import org.sonews.storage.Group; +import org.sonews.storage.StorageBackendException; +import org.sonews.storage.StorageManager; + +/** + * The purger is started in configurable intervals to search + * for messages that can be purged. A message must be deleted if its lifetime + * has exceeded, if it was marked as deleted or if the maximum number of + * articles in the database is reached. + * @author Christian Lins + * @since sonews/0.5.0 + */ +public class Purger extends AbstractDaemon +{ + + /** + * Loops through all messages and deletes them if their time + * has come. + */ + @Override + public void run() + { + try + { + while(isRunning()) + { + purgeDeleted(); + purgeOutdated(); + + Thread.sleep(120000); // Sleep for two minutes + } + } + catch(StorageBackendException ex) + { + ex.printStackTrace(); + } + catch(InterruptedException ex) + { + Log.get().warning("Purger interrupted: " + ex); + } + } + + private void purgeDeleted() + throws StorageBackendException + { + List groups = StorageManager.current().getGroups(); + for(Channel channel : groups) + { + if(!(channel instanceof Group)) + continue; + + Group group = (Group)channel; + // Look for groups that are marked as deleted + if(group.isDeleted()) + { + List ids = StorageManager.current().getArticleNumbers(group.getInternalID()); + if(ids.size() == 0) + { + StorageManager.current().purgeGroup(group); + Log.get().info("Group " + group.getName() + " purged."); + } + + for(int n = 0; n < ids.size() && n < 10; n++) + { + Article art = StorageManager.current().getArticle(ids.get(n), group.getInternalID()); + StorageManager.current().delete(art.getMessageID()); + Log.get().info("Article " + art.getMessageID() + " purged."); + } + } + } + } + + private void purgeOutdated() + throws InterruptedException, StorageBackendException + { + long articleMaximum = + Config.inst().get("sonews.article.maxnum", Long.MAX_VALUE); + long lifetime = + Config.inst().get("sonews.article.lifetime", -1); + + if(lifetime > 0 || articleMaximum < Stats.getInstance().getNumberOfNews()) + { + Log.get().info("Purging old messages..."); + String mid = StorageManager.current().getOldestArticle(); + if (mid == null) // No articles in the database + { + return; + } + + Article art = StorageManager.current().getArticle(mid); + long artDate = 0; + String dateStr = art.getHeader(Headers.DATE)[0]; + try + { + artDate = Date.parse(dateStr) / 1000 / 60 / 60 / 24; + } + catch (IllegalArgumentException ex) + { + Log.get().warning("Could not parse date string: " + dateStr + " " + ex); + } + + // Should we delete the message because of its age or because the + // article maximum was reached? + if (lifetime < 0 || artDate < (new Date().getTime() + lifetime)) + { + StorageManager.current().delete(mid); + System.out.println("Deleted: " + mid); + } + else + { + Thread.sleep(1000 * 60); // Wait 60 seconds + return; + } + } + else + { + Log.get().info("Lifetime purger is disabled"); + Thread.sleep(1000 * 60 * 30); // Wait 30 minutes + } + } + +}