*much* nicer cache_clean program

This commit is contained in:
Andrew Tridgell 2002-03-28 06:37:27 +01:00
parent c2286aa2f6
commit c79ad6ff5d
4 changed files with 116 additions and 24 deletions

15
README
View File

@ -105,14 +105,15 @@ Cleaning the cache
ccache tends to quickly fill up the cache directory. You may find the
ccache_clean utility for removing old cache files. If called with no
arguments it will remove any cache files older than a week. You can
also pass a single argument specifying the number of days old files
need to be to be cleaned. For example:
arguments it will trim the cache to be less than 1 Gigabyte. You can
also pass a single argument specifying the size limit on the cache,
for example:
ccache_clean 2G
would clear the oldest files to bring the cache below 2G in size. You
can use 'M' for megabytes, 'G' for gigabytes or 'K' for kilobytes.
ccache_clean 3
will remove any files older than 3 days. You may wish to call
ccache_clean from a cron job to keep your disk space usage reasonable.
You may wish to call ccache_clean from a cron job to keep your disk
space usage reasonable.
How it works
------------

View File

@ -41,7 +41,9 @@ int copy_file(const char *src, const char *dest);
int create_dir(const char *dir);
void x_asprintf(char **ptr, const char *format, ...);
char *x_strdup(const char *s);
void traverse(const char *dir, void (*fn)(const char *));
void *x_realloc(void *ptr, size_t size);
void *x_malloc(size_t size);
void traverse(const char *dir, void (*fn)(const char *, struct stat *));
int execute(char **argv,
const char *path_stdout,

View File

@ -22,29 +22,72 @@
#include "ccache.h"
static time_t threshold;
#define BLOCK_SIZE 1024
char *cache_logfile = NULL;
static void clean_fn(const char *fname)
static struct files {
char *fname;
time_t mtime;
size_t size;
} **files;
static unsigned allocated;
static unsigned num_files;
static size_t total_size;
static size_t size_threshold = 1024*1024; /* 1G default */
static int files_compare(struct files *f1, struct files *f2)
{
struct stat st;
if (stat(fname, &st) != 0 || !S_ISREG(st.st_mode)) return;
return f2->mtime - f1->mtime;
}
if (st.st_mtime >= threshold) return;
/* this builds the list of files in the cache */
static void traverse_fn(const char *fname, struct stat *st)
{
if (!S_ISREG(st->st_mode)) return;
if (unlink(fname) != 0) {
cc_log("unlink %s - %s\n", fname, strerror(errno));
return;
if (num_files == allocated) {
allocated = 10000 + num_files*2;
files = x_realloc(files, sizeof(struct files *)*allocated);
}
cc_log("cleaned %s\n", fname);
files[num_files] = x_malloc(sizeof(struct files *));
files[num_files]->fname = x_strdup(fname);
files[num_files]->mtime = st->st_mtime;
/* we deliberately overestimate by up to 1 block */
files[num_files]->size = 1 + (st->st_size/BLOCK_SIZE);
total_size += files[num_files]->size;
num_files++;
}
static void sort_and_clean(void)
{
unsigned i;
if (num_files > 1) {
/* sort in ascending data order */
qsort(files, num_files, sizeof(struct files *), files_compare);
}
/* delete enough files to bring us below the threshold */
for (i=0;i<num_files && total_size >= size_threshold;i++) {
if (unlink(files[i]->fname) != 0) {
fprintf(stderr, "unlink %s - %s\n",
files[i]->fname, strerror(errno));
continue;
}
total_size -= files[i]->size;
}
printf("cleaned %d of %d files (cache is now %.1f MByte)\n",
i, num_files, total_size/1024.0);
}
int main(int argc, char *argv[])
{
char *cache_dir;
int num_days = 7;
cache_dir = getenv("CCACHE_DIR");
if (!cache_dir) {
x_asprintf(&cache_dir, "%s/.ccache", getenv("HOME"));
@ -59,13 +102,33 @@ int main(int argc, char *argv[])
exit(1);
}
/* work out what size cache they want */
if (argc > 1) {
num_days = atoi(argv[1]);
char *s = argv[1];
char m;
size_threshold = atoi(s);
m = s[strlen(s)-1];
switch (m) {
case 'G':
case 'g':
size_threshold *= 1024*1024;
break;
case 'M':
case 'm':
size_threshold *= 1024;
break;
case 'K':
case 'k':
size_threshold *= 1;
break;
}
}
threshold = time(NULL) - num_days*24*60*60;
/* build a list of files */
traverse(cache_dir, traverse_fn);
traverse(cache_dir, clean_fn);
/* clean the cache */
sort_and_clean();
return 0;
}

30
util.c
View File

@ -142,12 +142,38 @@ char *x_strdup(const char *s)
return ret;
}
/*
this is like malloc() but dies if the malloc fails
*/
void *x_malloc(size_t size)
{
void *ret;
ret = malloc(size);
if (!ret) {
fatal("out of memory in malloc\n");
}
return ret;
}
/*
this is like strdup() but dies if the malloc fails
*/
void *x_realloc(void *ptr, size_t size)
{
if (!ptr) return x_malloc(size);
ptr = realloc(ptr, size);
if (!ptr) {
fatal("out of memory in x_realloc");
}
return ptr;
}
/*
revsusive directory traversal - used for cleanup
fn() is called on all files/dirs in the tree
*/
void traverse(const char *dir, void (*fn)(const char *))
void traverse(const char *dir, void (*fn)(const char *, struct stat *))
{
DIR *d;
struct dirent *de;
@ -173,7 +199,7 @@ void traverse(const char *dir, void (*fn)(const char *))
traverse(fname, fn);
}
fn(fname);
fn(fname, &st);
free(fname);
}