diff lib/swig/swigwin-2.0.11/CCache/cleanup.c @ 1899:b3009adc0e2f

Adding swig, gitignore, hgignore
author Nomad
date Mon, 21 Oct 2013 10:42:27 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/swig/swigwin-2.0.11/CCache/cleanup.c	Mon Oct 21 10:42:27 2013 +0200
@@ -0,0 +1,213 @@
+/*
+   Copyright (C) Andrew Tridgell 2002
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+  functions to cleanup the cache directory when it gets too large 
+ */
+
+#include "ccache.h"
+
+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 total_files;
+static size_t size_threshold;
+static size_t files_threshold;
+
+/* file comparison function to try to delete the oldest files first */
+static int files_compare(struct files **f1, struct files **f2)
+{
+	if ((*f2)->mtime == (*f1)->mtime) {
+		return strcmp((*f2)->fname, (*f1)->fname);
+	}
+	if ((*f2)->mtime > (*f1)->mtime) {
+		return -1;
+	}
+	return 1;
+}
+
+/* this builds the list of files in the cache */
+static void traverse_fn(const char *fname, struct stat *st)
+{
+	char *p;
+
+	if (!S_ISREG(st->st_mode)) return;
+
+	p = str_basename(fname);
+	if (strcmp(p, "stats") == 0) {
+		free(p);
+		return;
+	}
+	free(p);
+
+	if (num_files == allocated) {
+		allocated = 10000 + num_files*2;
+		files = (struct files **)x_realloc(files, 
+						   sizeof(struct files *)*allocated);
+	}
+
+	files[num_files] = (struct files *)x_malloc(sizeof(struct files));
+	files[num_files]->fname = x_strdup(fname);
+	files[num_files]->mtime = st->st_mtime;
+	files[num_files]->size = file_size(st) / 1024;
+	total_size += files[num_files]->size;
+	num_files++;
+}
+
+/* sort the files we've found and delete the oldest ones until we are
+   below the thresholds */
+static void sort_and_clean(size_t minfiles)
+{
+	unsigned i;
+	size_t adjusted_minfiles = minfiles;
+
+	if (num_files > 1) {
+		/* sort in ascending data order */
+		qsort(files, num_files, sizeof(struct files *), 
+		      (COMPAR_FN_T)files_compare);
+	}
+	/* ensure newly cached files (minfiles) are kept - instead of matching
+	   the filenames of those newly cached, a faster and simpler approach
+	   assumes these are the most recent in the cache and if any other
+	   cached files have an identical time stamp, they will also be kept -
+	   this approach would not be needed if the cleanup was done at exit. */
+	if (minfiles != 0 && minfiles < num_files) {
+		unsigned minfiles_index = num_files - minfiles;
+		time_t minfiles_time = files[minfiles_index]->mtime;
+		for (i=1; i<=minfiles_index; i++) {
+			if (files[minfiles_index-i]->mtime == minfiles_time)
+				adjusted_minfiles++;
+			else
+				break;
+		}
+	}
+	
+	/* delete enough files to bring us below the threshold */
+	for (i=0;i<num_files; i++) {
+		if ((size_threshold==0 || total_size < size_threshold) &&
+		    (files_threshold==0 || (num_files-i) < files_threshold)) break;
+
+		if (adjusted_minfiles != 0 && num_files-i <= adjusted_minfiles)
+			break;
+
+		if (unlink(files[i]->fname) != 0 && errno != ENOENT) {
+			fprintf(stderr, "unlink %s - %s\n", 
+				files[i]->fname, strerror(errno));
+			continue;
+		}
+		
+		total_size -= files[i]->size;
+	}	
+
+	total_files = num_files - i;
+}
+
+/* cleanup in one cache subdir */
+void cleanup_dir(const char *dir, size_t maxfiles, size_t maxsize, size_t minfiles)
+{
+	unsigned i;
+
+	size_threshold = maxsize * LIMIT_MULTIPLE;
+	files_threshold = maxfiles * LIMIT_MULTIPLE;
+
+	num_files = 0;
+	total_size = 0;
+
+	/* build a list of files */
+	traverse(dir, traverse_fn);
+
+	/* clean the cache */
+	sort_and_clean(minfiles);
+
+	stats_set_sizes(dir, total_files, total_size);
+
+	/* free it up */
+	for (i=0;i<num_files;i++) {
+		free(files[i]->fname);
+		free(files[i]);
+		files[i] = NULL;
+	}
+	if (files) free(files);
+	allocated = 0;
+	files = NULL;
+
+	num_files = 0;
+	total_size = 0;
+}
+
+/* cleanup in all cache subdirs */
+void cleanup_all(const char *dir)
+{
+	unsigned counters[STATS_END];
+	char *dname, *sfile;
+	int i;
+	
+	for (i=0;i<=0xF;i++) {
+		x_asprintf(&dname, "%s/%1x", dir, i);
+		x_asprintf(&sfile, "%s/%1x/stats", dir, i);
+
+		memset(counters, 0, sizeof(counters));
+		stats_read(sfile, counters);
+
+		cleanup_dir(dname, 
+			    counters[STATS_MAXFILES], 
+			    counters[STATS_MAXSIZE],
+			    0);
+		free(dname);
+		free(sfile);
+	}
+}
+
+
+/* traverse function for wiping files */
+static void wipe_fn(const char *fname, struct stat *st)
+{
+	char *p;
+
+	if (!S_ISREG(st->st_mode)) return;
+
+	p = str_basename(fname);
+	if (strcmp(p, "stats") == 0) {
+		free(p);
+		return;
+	}
+	free(p);
+
+	unlink(fname);
+}
+
+
+/* wipe all cached files in all subdirs */
+void wipe_all(const char *dir)
+{
+	char *dname;
+	int i;
+	
+	for (i=0;i<=0xF;i++) {
+		x_asprintf(&dname, "%s/%1x", dir, i);
+		traverse(dir, wipe_fn);
+		free(dname);
+	}
+
+	/* and fix the counters */
+	cleanup_all(dir);
+}