htcacheclean.c revision 717473b4288c54ef043f016a4ee801aba477303e
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/* Licensed to the Apache Software Foundation (ASF) under one or more
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * contributor license agreements. See the NOTICE file distributed with
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * this work for additional information regarding copyright ownership.
8b50db41286ddbfeb78954b0facf7fcad7c9a9ccrbowen * The ASF licenses this file to You under the Apache License, Version 2.0
acc36ab93565d2880447d535da6ca6e5feac7a70nd * (the "License"); you may not use this file except in compliance with
acc36ab93565d2880447d535da6ca6e5feac7a70nd * the License. You may obtain a copy of the License at
031b91a62d25106ae69d4693475c79618dd5e884fielding * Unless required by applicable law or agreed to in writing, software
031b91a62d25106ae69d4693475c79618dd5e884fielding * distributed under the License is distributed on an "AS IS" BASIS,
031b91a62d25106ae69d4693475c79618dd5e884fielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
acc36ab93565d2880447d535da6ca6e5feac7a70nd * See the License for the specific language governing permissions and
acc36ab93565d2880447d535da6ca6e5feac7a70nd * limitations under the License.
acc36ab93565d2880447d535da6ca6e5feac7a70nd * htcacheclean.c: simple program for cleaning of
acc36ab93565d2880447d535da6ca6e5feac7a70nd * the disk cache of the Apache HTTP server
acc36ab93565d2880447d535da6ca6e5feac7a70nd * Contributed by Andreas Steinmetz <ast domdv.de>
acc36ab93565d2880447d535da6ca6e5feac7a70nd * 8 Oct 2004
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd/* define the following for debugging */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * Note: on Linux delays <= 2ms are busy waits without
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd * scheduling, so never use a delay <= 2ms below
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#define DELETE_NICE 10 /* be nice after this amount of delete ops */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#define STAT_ATTEMPTS 10 /* maximum stat attempts for a file */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd#define DIRINFO (APR_FINFO_MTIME|APR_FINFO_SIZE|APR_FINFO_TYPE|APR_FINFO_LINK)
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndtypedef struct _direntry {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd int type; /* type of file/fileset: TEMP, HEADER, DATA, HEADERDATA */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndtypedef struct _entry {
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd apr_time_t response_time; /* cache entry time of last response to client */
5718d2b6ea423b4eb2d45f64bbc4c8eb61e0400fndstatic int delcount; /* file deletion count for nice mode */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int interrupted; /* flag: true if SIGINT or SIGTERM occurred */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int realclean; /* flag: true means user said apache is not running */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int verbose; /* flag: true means print statistics */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int benice; /* flag: true means nice mode is activated */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int dryrun; /* flag: true means dry run, don't actually delete
d78d735dbf7c5ce5ae545eecd8ee2c052224db77nd anything */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int deldirs; /* flag: true means directories should be deleted */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int listurls; /* flag: true means list cached urls */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int listextended;/* flag: true means list cached urls */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic int baselen; /* string length of the path to the proxy directory */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic apr_time_t now; /* start time of this processing run */
d78d735dbf7c5ce5ae545eecd8ee2c052224db77ndstatic apr_off_t unsolicited; /* file size summary for deleted unsolicited
struct stats {
#ifdef DEBUG
#ifdef DEBUG
static int called = 0;
if (!called) {
return APR_ENOMEM;
if (!verbose) {
if (unsolicited) {
s->inodes);
return val;
apr_pool_t *p;
const char *vary;
while (end) {
*end = 0;
(*nodes)--;
(*nodes)--;
apr_pool_destroy(p);
if (benice) {
delcount = 0;
char *nextpath;
apr_pool_t *p;
if (dryrun) {
(*nodes)--;
(*nodes)--;
apr_pool_destroy(p);
if (benice) {
delcount = 0;
char *nextpath;
apr_pool_t *p;
if (dryrun) {
(*nodes)--;
(*nodes)--;
if (dryrun) {
(*nodes)--;
(*nodes)--;
apr_pool_destroy(p);
if (benice) {
delcount = 0;
apr_pool_t *p;
char *url;
== APR_SUCCESS) {
== APR_SUCCESS) {
== APR_SUCCESS) {
if (listextended) {
!= apr_stat(
&dinfo,
path,
NULL),
url,
: 0, round),
!= apr_stat(
&dinfo,
path,
NULL),
url);
if (interrupted) {
apr_pool_destroy(p);
if (benice) {
if (interrupted) {
apr_pool_t *p;
apr_hash_t *h;
apr_hash_index_t *i;
DIRENTRY *d, *t, *n;
ENTRY *e;
h = apr_hash_make(p);
(*nodes)++;
if (interrupted) {
if (!base++) {
if (!ext) {
if (interrupted) {
void *hvalue;
d = hvalue;
switch(d->type) {
case HEADERDATA:
nodes, p);
nodes, p);
case HEADER:
case DATA:
case TEMP:
if (interrupted) {
apr_pool_destroy(p);
if (benice) {
if (interrupted) {
struct stats s;
s.sum = 0;
s.entries = 0;
s.dfuture = 0;
s.dexpired = 0;
s.dfresh = 0;
s.entries++;
s.entries--;
s.dfuture++;
if (!interrupted) {
if (interrupted) {
s.entries--;
s.dexpired++;
if (!interrupted) {
if (interrupted) {
oldest = e;
s.entries--;
s.dfresh++;
if (!interrupted) {
return rv;
return rv;
== APR_SUCCESS) {
return rv;
const char *rest)
return rv;
== APR_SUCCESS) {
: restlen));
if (files) {
if (!dryrun) {
const char *remove;
if (found) {
return APR_SUCCESS;
return rv;
tmp[k] = 0;
if (error) {
option));
if (errfile) {
apr_getopt_t *o;
char opt;
const char *arg;
interrupted = 0;
repeat = 0;
isdaemon = 0;
dryrun = 0;
limit_found = 0;
inodes_found = 0;
max = 0;
inodes = 0;
round = 0;
verbose = 0;
realclean = 0;
benice = 0;
deldirs = 0;
intelligent = 0;
if (argc) {
char *end;
switch (opt) {
if (intelligent) {
if (dryrun) {
if (benice) {
if (deldirs) {
if (verbose) {
if (realclean) {
if (isdaemon) {
if (limit_found) {
if (inodes_found) {
if (listurls) {
if (listurls) {
if (proxypath) {
if (pidfilename) {
if (round) {
if (*end) {
else if (round < 0) {
int deleted = 0;
int error = 0;
if (isdaemon) {
if (intelligent) {
if (limit_found) {
if (verbose) {
if (verbose) {
if (verbose) {
o->ind++;
if (!proxypath) {
if (pidfilename) {
if (listurls) {
return (interrupted != 0);
#ifndef DEBUG
if (isdaemon) {
if (pidfilename) {
if (pidfilename) {
delcount = 0;
unsolicited = 0;
dowork = 0;
switch (intelligent) {
if (isdaemon) {
delay = 0;