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