htcacheclean.c revision af91703d7657e52921bb36c44ff093b2d2077d0c
135c1278adef96d36fd421c536b1acc54a341cfbsf/* Licensed to the Apache Software Foundation (ASF) under one or more
135c1278adef96d36fd421c536b1acc54a341cfbsf * contributor license agreements. See the NOTICE file distributed with
135c1278adef96d36fd421c536b1acc54a341cfbsf * this work for additional information regarding copyright ownership.
135c1278adef96d36fd421c536b1acc54a341cfbsf * The ASF licenses this file to You under the Apache License, Version 2.0
135c1278adef96d36fd421c536b1acc54a341cfbsf * (the "License"); you may not use this file except in compliance with
135c1278adef96d36fd421c536b1acc54a341cfbsf * the License. You may obtain a copy of the License at
135c1278adef96d36fd421c536b1acc54a341cfbsf * Unless required by applicable law or agreed to in writing, software
135c1278adef96d36fd421c536b1acc54a341cfbsf * distributed under the License is distributed on an "AS IS" BASIS,
135c1278adef96d36fd421c536b1acc54a341cfbsf * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135c1278adef96d36fd421c536b1acc54a341cfbsf * See the License for the specific language governing permissions and
135c1278adef96d36fd421c536b1acc54a341cfbsf * limitations under the License.
135c1278adef96d36fd421c536b1acc54a341cfbsf * htcacheclean.c: simple program for cleaning of
135c1278adef96d36fd421c536b1acc54a341cfbsf * the disk cache of the Apache HTTP server
135c1278adef96d36fd421c536b1acc54a341cfbsf * Contributed by Andreas Steinmetz <ast domdv.de>
135c1278adef96d36fd421c536b1acc54a341cfbsf * 8 Oct 2004
135c1278adef96d36fd421c536b1acc54a341cfbsf/* define the following for debugging */
135c1278adef96d36fd421c536b1acc54a341cfbsf * Note: on Linux delays <= 2ms are busy waits without
135c1278adef96d36fd421c536b1acc54a341cfbsf * scheduling, so never use a delay <= 2ms below
135c1278adef96d36fd421c536b1acc54a341cfbsf#define DELETE_NICE 10 /* be nice after this amount of delete ops */
135c1278adef96d36fd421c536b1acc54a341cfbsf#define STAT_ATTEMPTS 10 /* maximum stat attempts for a file */
135c1278adef96d36fd421c536b1acc54a341cfbsf#define DIRINFO (APR_FINFO_MTIME|APR_FINFO_SIZE|APR_FINFO_TYPE|APR_FINFO_LINK)
135c1278adef96d36fd421c536b1acc54a341cfbsftypedef struct _direntry {
135c1278adef96d36fd421c536b1acc54a341cfbsf int type; /* type of file/fileset: TEMP, HEADER, DATA, HEADERDATA */
135c1278adef96d36fd421c536b1acc54a341cfbsftypedef struct _entry {
135c1278adef96d36fd421c536b1acc54a341cfbsf apr_time_t response_time; /* cache entry time of last response to client */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int delcount; /* file deletion count for nice mode */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int interrupted; /* flag: true if SIGINT or SIGTERM occurred */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int realclean; /* flag: true means user said apache is not running */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int verbose; /* flag: true means print statistics */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int benice; /* flag: true means nice mode is activated */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int dryrun; /* flag: true means dry run, don't actually delete
135c1278adef96d36fd421c536b1acc54a341cfbsf anything */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int deldirs; /* flag: true means directories should be deleted */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic int baselen; /* string length of the path to the proxy directory */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic apr_time_t now; /* start time of this processing run */
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic apr_off_t unsolicited; /* file size summary for deleted unsolicited
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic APR_RING_ENTRY(_entry) root; /* ENTRY ring anchor */
135c1278adef96d36fd421c536b1acc54a341cfbsf/* short program name as called */
135c1278adef96d36fd421c536b1acc54a341cfbsf/* what did we clean? */
135c1278adef96d36fd421c536b1acc54a341cfbsf * fake delete for debug purposes
135c1278adef96d36fd421c536b1acc54a341cfbsfstatic void fake_file_remove(char *pathname, apr_pool_t *p)
135c1278adef96d36fd421c536b1acc54a341cfbsf /* stat and printing to simulate some deletion system load and to
135c1278adef96d36fd421c536b1acc54a341cfbsf display what would actually have happened */
135c1278adef96d36fd421c536b1acc54a341cfbsf apr_file_printf(errfile, "would delete %s" APR_EOL_STR, pathname);
#ifdef DEBUG
static int called = 0;
if (!called) {
return APR_ENOMEM;
if (!verbose) {
if (unsolicited) {
(int)(s->entries));
char *nextpath;
apr_pool_t *p;
if (dryrun) {
apr_pool_destroy(p);
if (benice) {
delcount = 0;
char *nextpath;
apr_pool_t *p;
if (dryrun) {
apr_pool_destroy(p);
if (benice) {
delcount = 0;
apr_pool_t *p;
apr_hash_t *h;
apr_hash_index_t *i;
DIRENTRY *d, *t, *n;
ENTRY *e;
h = apr_hash_make(p);
skip = 0;
if (interrupted) {
if (!base++) {
if (!ext) {
if (interrupted) {
void *hvalue;
d = hvalue;
switch(d->type) {
case HEADERDATA:
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;
max = 0;
verbose = 0;
realclean = 0;
benice = 0;
deldirs = 0;
intelligent = 0;
if (argc) {
switch (opt) {
if (intelligent) {
if (dryrun) {
if (benice) {
if (deldirs) {
if (verbose) {
if (realclean) {
if (isdaemon) {
if (limit_found) {
char *end;
if (proxypath) {
if (pidfilename) {
int deleted = 0;
int error = 0;
if (isdaemon) {
if (intelligent) {
if (limit_found) {
if (verbose) {
if (verbose) {
if (verbose) {
o->ind++;
if (!proxypath) {
if (max <= 0) {
if (pidfilename) {
#ifndef DEBUG
if (isdaemon) {
if (pidfilename) {
if (pidfilename) {
delcount = 0;
unsolicited = 0;
dowork = 0;
switch (intelligent) {
if (isdaemon) {
delay = 0;