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