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