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