src/org/sonews/util/Purger.java
author cli
Tue, 07 Jun 2011 09:23:34 +0200
changeset 43 7d0e65712a95
parent 37 74139325d305
child 48 b78e77619152
permissions -rwxr-xr-x
Adapt config sample to use hsqldb
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
cli@36
    21
import java.util.Date;
cli@36
    22
import java.util.List;
chris@3
    23
import org.sonews.daemon.AbstractDaemon;
chris@3
    24
import org.sonews.config.Config;
chris@3
    25
import org.sonews.storage.Article;
chris@3
    26
import org.sonews.storage.Headers;
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
cli@37
    43
	/**
cli@37
    44
	 * Loops through all messages and deletes them if their time
cli@37
    45
	 * has come.
cli@37
    46
	 */
cli@37
    47
	@Override
cli@37
    48
	public void run()
cli@37
    49
	{
cli@37
    50
		try {
cli@37
    51
			while (isRunning()) {
cli@37
    52
				purgeDeleted();
cli@37
    53
				purgeOutdated();
chris@1
    54
cli@37
    55
				Thread.sleep(120000); // Sleep for two minutes
cli@37
    56
			}
cli@37
    57
		} catch (StorageBackendException ex) {
cli@37
    58
			ex.printStackTrace();
cli@37
    59
		} catch (InterruptedException ex) {
cli@37
    60
			Log.get().warning("Purger interrupted: " + ex);
cli@37
    61
		}
cli@37
    62
	}
chris@3
    63
cli@37
    64
	private void purgeDeleted()
cli@37
    65
		throws StorageBackendException
cli@37
    66
	{
cli@37
    67
		List<Channel> groups = StorageManager.current().getGroups();
cli@37
    68
		for (Channel channel : groups) {
cli@37
    69
			if (!(channel instanceof Group)) {
cli@37
    70
				continue;
cli@37
    71
			}
chris@3
    72
cli@37
    73
			Group group = (Group) channel;
cli@37
    74
			// Look for groups that are marked as deleted
cli@37
    75
			if (group.isDeleted()) {
cli@37
    76
				List<Long> ids = StorageManager.current().getArticleNumbers(group.getInternalID());
cli@37
    77
				if (ids.size() == 0) {
cli@37
    78
					StorageManager.current().purgeGroup(group);
cli@37
    79
					Log.get().info("Group " + group.getName() + " purged.");
cli@37
    80
				}
chris@3
    81
cli@37
    82
				for (int n = 0; n < ids.size() && n < 10; n++) {
cli@37
    83
					Article art = StorageManager.current().getArticle(ids.get(n), group.getInternalID());
cli@37
    84
					StorageManager.current().delete(art.getMessageID());
cli@37
    85
					Log.get().info("Article " + art.getMessageID() + " purged.");
cli@37
    86
				}
cli@37
    87
			}
cli@37
    88
		}
cli@37
    89
	}
chris@3
    90
cli@37
    91
	private void purgeOutdated()
cli@37
    92
		throws InterruptedException, StorageBackendException
cli@37
    93
	{
cli@37
    94
		long articleMaximum =
cli@37
    95
			Config.inst().get("sonews.article.maxnum", Long.MAX_VALUE);
cli@37
    96
		long lifetime =
cli@37
    97
			Config.inst().get("sonews.article.lifetime", -1);
chris@1
    98
cli@37
    99
		if (lifetime > 0 || articleMaximum < Stats.getInstance().getNumberOfNews()) {
cli@37
   100
			Log.get().info("Purging old messages...");
cli@37
   101
			String mid = StorageManager.current().getOldestArticle();
cli@37
   102
			if (mid == null) // No articles in the database
cli@37
   103
			{
cli@37
   104
				return;
cli@37
   105
			}
chris@3
   106
cli@37
   107
			Article art = StorageManager.current().getArticle(mid);
cli@37
   108
			long artDate = 0;
cli@37
   109
			String dateStr = art.getHeader(Headers.DATE)[0];
cli@37
   110
			try {
cli@37
   111
				artDate = Date.parse(dateStr) / 1000 / 60 / 60 / 24;
cli@37
   112
			} catch (IllegalArgumentException ex) {
cli@37
   113
				Log.get().warning("Could not parse date string: " + dateStr + " " + ex);
cli@37
   114
			}
chris@1
   115
cli@37
   116
			// Should we delete the message because of its age or because the
cli@37
   117
			// article maximum was reached?
cli@37
   118
			if (lifetime < 0 || artDate < (new Date().getTime() + lifetime)) {
cli@37
   119
				StorageManager.current().delete(mid);
cli@37
   120
				System.out.println("Deleted: " + mid);
cli@37
   121
			} else {
cli@37
   122
				Thread.sleep(1000 * 60); // Wait 60 seconds
cli@37
   123
				return;
cli@37
   124
			}
cli@37
   125
		} else {
cli@37
   126
			Log.get().info("Lifetime purger is disabled");
cli@37
   127
			Thread.sleep(1000 * 60 * 30); // Wait 30 minutes
cli@37
   128
		}
cli@37
   129
	}
chris@1
   130
}