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