1 /*  $Id: list.cpp 1667 2009-10-30 18:09:31Z terpstra $
2  *
3  *  mindex.cpp - Cleanup after a mindex/ command
4  *
5  *  Copyright (C) 2002 - Wesley W. Terpstra
6  *
7  *  License: GPL
8  *
9  *  Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
10  *
11  *    This program is free software; you can redistribute it and/or modify
12  *    it under the terms of the GNU General Public License as published by
13  *    the Free Software Foundation; version 2.
14  *
15  *    This program is distributed in the hope that it will be useful,
16  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *    GNU General Public License for more details.
19  *
20  *    You should have received a copy of the GNU General Public License
21  *    along with this program; if not, write to the Free Software
22  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24 
25 #define _FILE_OFFSET_BITS 64
26 
27 #include "PTable.h"
28 #include <Keys.h>
29 
30 #include <iostream>
31 
32 using namespace std;
33 
test_list(KSI ks)34 bool PTable::test_list(KSI ks)
35 {
36 	const string::size_type skip = sizeof("list"); // null is /
37 
38 	/* We need to work around list-ids which contain a '.'
39 	 * For legacy reasons there may be URLs with only a single '.'
40 	 * We cannot support legacy URLs AND list-ids with '.', but that's ok.
41 	 * Compromise: Strip last two '.'s -- or only last '.' if not two.
42 	 */
43 	string::size_type o = ks->first.rfind('.');
44 	if (o != string::npos && o > skip)
45 	{
46 		string::size_type tmp = ks->first.rfind('.', o-1);
47 		if (tmp != string::npos && tmp >= skip) o = tmp;
48 	}
49 
50 	return	o != string::npos && o >= skip &&
51 		cfg.lists.find(string(ks->first, skip, o-skip)) != cfg.lists.end();
52 }
53 
calc_list(KSI ks)54 void PTable::calc_list(KSI ks)
55 {
56 	/* List entries are invalidated by any new message to the list
57 	 *
58 	 * ... but list includes:
59 	 *   list info (from config file)
60 	 *
61 	 * Policy:
62 	 *   kill if older than newest message to list
63 	 *   kill if older than a fixed time
64 	 *   kill if no recent accesses
65 	 */
66 
67 	if (!test_list(ks))
68 	{
69 		if (verbose)
70 			cout << ks->first << ": not a lurker file." << endl;
71 		return;
72 	}
73 
74 	if (ks->second.mtime <= cfg.modified)
75 	{	// die - it's older than the config file
76 		ks->second.kill = true;
77 		if (verbose)
78 			cout << ks->first << ": older than config file." << endl;
79 		return;
80 	}
81 
82 	// Don't let the page get too old; it is time dependent
83 	if (now - ks->second.mtime >= accessedLimit)
84 	{
85 		ks->second.kill = true;
86 		if (verbose)
87 			cout << ks->first << ": expired due to maximum age." << endl;
88 		return;
89 	}
90 
91 	if (now - ks->second.atime >= accessedLimit)
92 	{
93 		ks->second.kill = true;
94 		if (verbose)
95 			cout << ks->first << ": expired due to no access." << endl;
96 		return;
97 	}
98 
99 	string query(ks->first, 5, string::npos);
100 	string::size_type at = query.rfind('.');
101 
102 	/* Same work-around as test_list */
103 	if (at != string::npos && at > 0)
104 	{
105 		string::size_type tmp = ks->first.rfind('.', at-1);
106 		if (tmp != string::npos) at = tmp;
107 	}
108 
109 	string listn(query, 0, at);
110 	if (lists.find(listn) == lists.end())
111 	{	// this list has not changed if not pulled
112 		if (verbose)
113 			cout << ks->first << ": not a modified list." << endl;
114 		return;
115 	}
116 
117 	MessageIds& list = lists[listn];
118 	if (list.empty())
119 	{
120 		if (verbose)
121 			cout << ks->first << ": empty list." << endl;
122 		return;
123 	}
124 
125 	// Any new message (even in the past) will affect this page
126 	MessageIds::iterator id;
127 	for (id = list.begin(); id != list.end(); ++id)
128 	{
129 		Summaries::const_iterator s;
130 		if ((s = summaries.find(*id)) != summaries.end() &&
131 		    s->second.changed)
132 		{
133 			ks->second.kill = true;
134 			if (verbose)
135 				cout << ks->first << ": " << id->serialize() << " is new." << endl;
136 			return;
137 		}
138 	}
139 
140 	if (verbose)
141 		cout << ks->first << ": nothing newer than page." << endl;
142 }
143