~ubuntu-branches/ubuntu/breezy/lurker/breezy

« back to all changes in this revision

Viewing changes to prune/prune.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Meurer
  • Date: 2004-09-26 16:27:51 UTC
  • Revision ID: james.westby@ubuntu.com-20040926162751-z1ohcjltv7ojtg6z
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Id: prune.cpp,v 1.13 2004/08/24 16:21:12 terpstra Exp $
 
2
 *  
 
3
 *  prune.cpp - Prune obsolete / stale cache files
 
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 _XOPEN_SOURCE 500
 
26
#define _FILE_OFFSET_BITS 64
 
27
 
 
28
#include <ConfigFile.h>
 
29
#include <esort.h>
 
30
 
 
31
#include <sys/types.h>
 
32
#include <sys/stat.h>
 
33
#include <sys/file.h>
 
34
 
 
35
#include <unistd.h>
 
36
#include <fcntl.h>
 
37
#include <utime.h>
 
38
 
 
39
#include <iostream>
 
40
 
 
41
#include <cstring>
 
42
#include <cerrno>
 
43
#include <ctime>
 
44
 
 
45
#include "PTable.h"
 
46
 
 
47
using namespace std;
 
48
 
 
49
void help(const char* name)
 
50
{
 
51
        cerr << "Lurker-prune (v" << VERSION << ") prunes the web-server cache.\n";
 
52
        cerr << "\n";
 
53
        cerr << "Usage: " << name << " -c <config-file> -d <docroot> [-m <d> -a <d> -p -v]\n";
 
54
        cerr << "\n";
 
55
        cerr << "\t-c <config-file> Use this config file for lurker settings\n";
 
56
        cerr << "\t-d <docroot>     The base directory of the lurker cache\n";
 
57
        cerr << "\t-m <days>        Keep cached files for at most this many days      [7]\n";
 
58
        cerr << "\t-a <days>        Kill cached files not accessed for this many days [1]\n";
 
59
        cerr << "\t-p               Purge everything even if it appears to not be expired\n";
 
60
        cerr << "\t-v               Verbose operation\n";
 
61
        cerr << "\n";
 
62
        cerr << "Prune obsolete or stale html/xml from the web-server accessible cache.\n";
 
63
        cerr << "This command should be run at regular intervals from cron for each site.\n";
 
64
        cerr << "\n";
 
65
}
 
66
 
 
67
int main(int argc, char** argv)
 
68
{
 
69
        int c;
 
70
        
 
71
        const char* config  = 0;
 
72
        const char* docroot = 0;
 
73
        bool        verbose = false;
 
74
        bool        purge = false;
 
75
        time_t      modifyTime = 60*60*24*7;
 
76
        time_t      accessTime = 60*60*24*1;
 
77
        
 
78
        srandom(time(0));
 
79
        
 
80
        while ((c = getopt(argc, (char*const*)argv, "c:d:m:a:vp?")) != -1)
 
81
        {
 
82
                switch ((char)c)
 
83
                {
 
84
                case 'c':
 
85
                        config = optarg;
 
86
                        break;
 
87
                case 'd':
 
88
                        docroot = optarg;
 
89
                        break;
 
90
                case 'm':
 
91
                        modifyTime = atol(optarg)*60*60*24;
 
92
                        if (!modifyTime)
 
93
                        {
 
94
                                help(argv[0]);
 
95
                                return 1;
 
96
                        }
 
97
                        break;
 
98
                case 'a':
 
99
                        accessTime = atol(optarg)*60*60*24;
 
100
                        if (!accessTime)
 
101
                        {
 
102
                                help(argv[0]);
 
103
                                return 1;
 
104
                        }
 
105
                        break;
 
106
                case 'p':
 
107
                        purge = true;
 
108
                        break;
 
109
                case 'v':
 
110
                        verbose = true;
 
111
                        break;
 
112
                default:
 
113
                        help(argv[0]);
 
114
                        return 1;
 
115
                }
 
116
        }
 
117
        
 
118
        if (!config || !docroot || optind < argc)
 
119
        {
 
120
                help(argv[0]);
 
121
                return 1;
 
122
        }
 
123
        
 
124
        Config cfg;
 
125
        if (cfg.load(config) != 0)
 
126
        {
 
127
                cerr << cfg.getError() << flush;
 
128
                return 1;
 
129
        }
 
130
        
 
131
        string docfile = string(docroot) + "/lurker.docroot";
 
132
        int fd = open(docfile.c_str(), O_RDWR | O_CREAT, 0666);
 
133
        if (fd == -1)
 
134
        {
 
135
                cerr << "open()ing " << docfile << ": " << strerror(errno) << endl;
 
136
                return 1;
 
137
        }
 
138
        
 
139
        struct stat dbuf;
 
140
        if (fstat(fd, &dbuf) < 0)
 
141
        {
 
142
                cerr << "stat()ing " << docfile << ": " << strerror(errno) << endl;
 
143
                return 1;
 
144
        }
 
145
        
 
146
        enum LockState { GOT, FAIL, USED } state = GOT;
 
147
        
 
148
#ifdef  LOCK_EX
 
149
        if (flock(fd, LOCK_EX|LOCK_NB) != 0)
 
150
        {
 
151
                if (errno == EWOULDBLOCK)
 
152
                        state = USED;
 
153
                else    state = FAIL;
 
154
        }
 
155
#else
 
156
#ifdef F_SETLK
 
157
        struct flock lock;
 
158
        memset(&lock, 0, sizeof(lock));
 
159
        lock.l_type = F_WRLCK;
 
160
        lock.l_whence = SEEK_SET;
 
161
        if (fcntl(fd, F_SETLK, &lock) != 0)
 
162
        {
 
163
                if (errno == EACCES || errno == EAGAIN)
 
164
                        state = USED;
 
165
                else    state = FAIL;
 
166
        }
 
167
#endif
 
168
#endif
 
169
        
 
170
        if (state == USED)
 
171
        {
 
172
                if (verbose) cout << "Already pruning this docroot" << endl;
 
173
                return 0;
 
174
        }
 
175
        
 
176
        if (state == FAIL)
 
177
        {
 
178
                cerr << "Locking " << docfile << " failed: " << strerror(errno) << endl;
 
179
                return 1;
 
180
        }
 
181
        
 
182
        std::auto_ptr<ESort::Reader> db(ESort::Reader::opendb(cfg.dbdir + "/db"));
 
183
        if (!db.get())
 
184
        {
 
185
                cerr << "Opening database: " << strerror(errno) << endl;
 
186
                return 1;
 
187
        }
 
188
        
 
189
        time_t beginfix = time(0);
 
190
        
 
191
        if (chdir(docroot) != 0)
 
192
        {
 
193
                cerr << "chdir: " << docroot << ": " << strerror(errno) << endl;
 
194
                return 1;
 
195
        }
 
196
        
 
197
        PTable ptable(cfg, db.get(), dbuf.st_mtime, purge, verbose, modifyTime, accessTime);
 
198
        string ok;
 
199
        
 
200
        if ((ok = ptable.load()) != "")
 
201
        {
 
202
                cerr << "load: " << ok << endl;
 
203
                return 1;
 
204
        }
 
205
        
 
206
        if ((ok = ptable.calc()) != "")
 
207
        {
 
208
                cerr << "calc: " << ok << endl;
 
209
                return 1;
 
210
        }
 
211
        
 
212
        if ((ok = ptable.kill()) != "")
 
213
        {
 
214
                cerr << "kill: " << ok << endl;
 
215
                return 1;
 
216
        }
 
217
        
 
218
        // set the mtime stamp to beginfix
 
219
        struct utimbuf touch;
 
220
        touch.actime = touch.modtime = beginfix;
 
221
        if (utime("lurker.docroot", &touch) < 0)
 
222
        {
 
223
                cerr << "touching " << docfile << ": " << strerror(errno) << endl;
 
224
                return 1;
 
225
        }
 
226
        
 
227
        return 0;
 
228
}