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: }