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:
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@1: import java.util.Date;
chris@3: import java.util.List;
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:
chris@1: /**
chris@1: * Loops through all messages and deletes them if their time
chris@1: * has come.
chris@1: */
chris@3: @Override
chris@3: public void run()
chris@1: {
chris@3: try
chris@3: {
chris@3: while(isRunning())
chris@3: {
chris@3: purgeDeleted();
chris@3: purgeOutdated();
chris@1:
chris@3: Thread.sleep(120000); // Sleep for two minutes
chris@3: }
chris@3: }
chris@3: catch(StorageBackendException ex)
chris@1: {
chris@3: ex.printStackTrace();
chris@3: }
chris@3: catch(InterruptedException ex)
chris@3: {
cli@16: Log.get().warning("Purger interrupted: " + ex);
chris@3: }
chris@3: }
chris@3:
chris@3: private void purgeDeleted()
chris@3: throws StorageBackendException
chris@3: {
chris@3: List groups = StorageManager.current().getGroups();
chris@3: for(Channel channel : groups)
chris@3: {
chris@3: if(!(channel instanceof Group))
chris@3: continue;
chris@3:
chris@3: Group group = (Group)channel;
chris@3: // Look for groups that are marked as deleted
chris@3: if(group.isDeleted())
chris@1: {
chris@3: List ids = StorageManager.current().getArticleNumbers(group.getInternalID());
chris@3: if(ids.size() == 0)
chris@3: {
chris@3: StorageManager.current().purgeGroup(group);
cli@16: Log.get().info("Group " + group.getName() + " purged.");
chris@3: }
chris@3:
chris@3: for(int n = 0; n < ids.size() && n < 10; n++)
chris@3: {
chris@3: Article art = StorageManager.current().getArticle(ids.get(n), group.getInternalID());
chris@3: StorageManager.current().delete(art.getMessageID());
cli@16: Log.get().info("Article " + art.getMessageID() + " purged.");
chris@3: }
chris@3: }
chris@3: }
chris@3: }
chris@3:
chris@3: private void purgeOutdated()
chris@3: throws InterruptedException, StorageBackendException
chris@3: {
chris@3: long articleMaximum =
chris@3: Config.inst().get("sonews.article.maxnum", Long.MAX_VALUE);
chris@3: long lifetime =
chris@3: Config.inst().get("sonews.article.lifetime", -1);
chris@3:
chris@3: if(lifetime > 0 || articleMaximum < Stats.getInstance().getNumberOfNews())
chris@3: {
cli@16: Log.get().info("Purging old messages...");
chris@3: String mid = StorageManager.current().getOldestArticle();
chris@3: if (mid == null) // No articles in the database
chris@3: {
chris@3: return;
chris@1: }
chris@1:
chris@3: Article art = StorageManager.current().getArticle(mid);
chris@3: long artDate = 0;
chris@3: String dateStr = art.getHeader(Headers.DATE)[0];
chris@3: try
chris@1: {
chris@3: artDate = Date.parse(dateStr) / 1000 / 60 / 60 / 24;
chris@3: }
chris@3: catch (IllegalArgumentException ex)
chris@3: {
cli@16: Log.get().warning("Could not parse date string: " + dateStr + " " + ex);
chris@3: }
chris@3:
chris@3: // Should we delete the message because of its age or because the
chris@3: // article maximum was reached?
chris@3: if (lifetime < 0 || artDate < (new Date().getTime() + lifetime))
chris@3: {
chris@3: StorageManager.current().delete(mid);
chris@3: System.out.println("Deleted: " + mid);
chris@1: }
chris@1: else
chris@1: {
chris@3: Thread.sleep(1000 * 60); // Wait 60 seconds
chris@3: return;
chris@3: }
chris@1: }
chris@3: else
chris@1: {
cli@16: Log.get().info("Lifetime purger is disabled");
chris@3: Thread.sleep(1000 * 60 * 30); // Wait 30 minutes
chris@1: }
chris@1: }
chris@1:
chris@1: }