org/sonews/util/Purger.java
author cli
Sun, 09 May 2010 12:38:46 +0200
changeset 30 146b3275b792
parent 16 5a4a41cfc0a3
permissions -rw-r--r--
The StorageBackendException is catched two times so that the user see the "500 internal server error" only at the second catch (probably fixes #5).
     1 /*
     2  *   SONEWS News Server
     3  *   see AUTHORS for the list of contributors
     4  *
     5  *   This program is free software: you can redistribute it and/or modify
     6  *   it under the terms of the GNU General Public License as published by
     7  *   the Free Software Foundation, either version 3 of the License, or
     8  *   (at your option) any later version.
     9  *
    10  *   This program is distributed in the hope that it will be useful,
    11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *   GNU General Public License for more details.
    14  *
    15  *   You should have received a copy of the GNU General Public License
    16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 
    19 package org.sonews.util;
    20 
    21 import org.sonews.daemon.AbstractDaemon;
    22 import org.sonews.config.Config;
    23 import org.sonews.storage.Article;
    24 import org.sonews.storage.Headers;
    25 import java.util.Date;
    26 import java.util.List;
    27 import org.sonews.storage.Channel;
    28 import org.sonews.storage.Group;
    29 import org.sonews.storage.StorageBackendException;
    30 import org.sonews.storage.StorageManager;
    31 
    32 /**
    33  * The purger is started in configurable intervals to search
    34  * for messages that can be purged. A message must be deleted if its lifetime
    35  * has exceeded, if it was marked as deleted or if the maximum number of
    36  * articles in the database is reached.
    37  * @author Christian Lins
    38  * @since sonews/0.5.0
    39  */
    40 public class Purger extends AbstractDaemon
    41 {
    42 
    43   /**
    44    * Loops through all messages and deletes them if their time
    45    * has come.
    46    */
    47   @Override
    48   public void run()
    49   {
    50     try
    51     {
    52       while(isRunning())
    53       {
    54         purgeDeleted();
    55         purgeOutdated();
    56 
    57         Thread.sleep(120000); // Sleep for two minutes
    58       }
    59     }
    60     catch(StorageBackendException ex)
    61     {
    62       ex.printStackTrace();
    63     }
    64     catch(InterruptedException ex)
    65     {
    66       Log.get().warning("Purger interrupted: " + ex);
    67     }
    68   }
    69 
    70   private void purgeDeleted()
    71     throws StorageBackendException
    72   {
    73     List<Channel> groups = StorageManager.current().getGroups();
    74     for(Channel channel : groups)
    75     {
    76       if(!(channel instanceof Group))
    77         continue;
    78       
    79       Group group = (Group)channel;
    80       // Look for groups that are marked as deleted
    81       if(group.isDeleted())
    82       {
    83         List<Long> ids = StorageManager.current().getArticleNumbers(group.getInternalID());
    84         if(ids.size() == 0)
    85         {
    86           StorageManager.current().purgeGroup(group);
    87           Log.get().info("Group " + group.getName() + " purged.");
    88         }
    89 
    90         for(int n = 0; n < ids.size() && n < 10; n++)
    91         {
    92           Article art = StorageManager.current().getArticle(ids.get(n), group.getInternalID());
    93           StorageManager.current().delete(art.getMessageID());
    94           Log.get().info("Article " + art.getMessageID() + " purged.");
    95         }
    96       }
    97     }
    98   }
    99 
   100   private void purgeOutdated()
   101     throws InterruptedException, StorageBackendException
   102   {
   103     long articleMaximum =
   104       Config.inst().get("sonews.article.maxnum", Long.MAX_VALUE);
   105     long lifetime =
   106       Config.inst().get("sonews.article.lifetime", -1);
   107 
   108     if(lifetime > 0 || articleMaximum < Stats.getInstance().getNumberOfNews())
   109     {
   110       Log.get().info("Purging old messages...");
   111       String mid = StorageManager.current().getOldestArticle();
   112       if (mid == null) // No articles in the database
   113       {
   114         return;
   115       }
   116 
   117       Article art = StorageManager.current().getArticle(mid);
   118       long artDate = 0;
   119       String dateStr = art.getHeader(Headers.DATE)[0];
   120       try
   121       {
   122         artDate = Date.parse(dateStr) / 1000 / 60 / 60 / 24;
   123       }
   124       catch (IllegalArgumentException ex)
   125       {
   126         Log.get().warning("Could not parse date string: " + dateStr + " " + ex);
   127       }
   128 
   129       // Should we delete the message because of its age or because the
   130       // article maximum was reached?
   131       if (lifetime < 0 || artDate < (new Date().getTime() + lifetime))
   132       {
   133         StorageManager.current().delete(mid);
   134         System.out.println("Deleted: " + mid);
   135       }
   136       else
   137       {
   138         Thread.sleep(1000 * 60); // Wait 60 seconds
   139         return;
   140       }
   141     }
   142     else
   143     {
   144       Log.get().info("Lifetime purger is disabled");
   145       Thread.sleep(1000 * 60 * 30); // Wait 30 minutes
   146     }
   147   }
   148 
   149 }