extern char *cache_dir;
extern unsigned lock_staleness_limit;
-static unsigned counter_updates[STATS_END];
+static struct counters *counter_updates;
/* default maximum cache size */
#ifndef DEFAULT_MAXSIZE
/* parse a stats file from a buffer - adding to the counters */
static void
-parse_stats(unsigned counters[STATS_END], char *buf)
+parse_stats(struct counters *counters, const char *buf)
{
- int i;
- char *p, *p2;
+ size_t i = 0;
+ const char *p;
+ char *p2;
+ long val;
p = buf;
- for (i = 0; i < STATS_END; i++) {
- counters[i] += strtol(p, &p2, 10);
- if (!p2 || p2 == p) break;
+ while (1) {
+ val = strtol(p, &p2, 10);
+ if (p2 == p) {
+ break;
+ }
+ if (counters->size < i + 1) {
+ counters_resize(counters, i + 1);
+ }
+ counters->data[i] += val;
+ i++;
p = p2;
}
}
/* write out a stats file */
-static void
-write_stats(const char *path, unsigned counters[STATS_END])
+void
+stats_write(const char *path, struct counters *counters)
{
- int i;
+ size_t i;
char *tmp_file;
FILE *f;
f = fopen(tmp_file, "wb");
if (!f) {
cc_log("Failed to open %s", tmp_file);
- return;
+ goto end;
}
- for (i = 0; i < STATS_END; i++) {
- if (fprintf(f, "%u\n", counters[i]) < 0) {
+ for (i = 0; i < counters->size; i++) {
+ if (fprintf(f, "%u\n", counters->data[i]) < 0) {
fatal("Failed to write to %s", tmp_file);
}
}
fclose(f);
x_rename(tmp_file, path);
+
+end:
+ free(tmp_file);
}
/* fill in some default stats values */
static void
-stats_default(unsigned counters[STATS_END])
+stats_default(struct counters *counters)
{
- counters[STATS_MAXSIZE] += DEFAULT_MAXSIZE / 16;
+ counters->data[STATS_MAXSIZE] += DEFAULT_MAXSIZE / 16;
+}
+
+static void
+init_counter_updates(void)
+{
+ if (!counter_updates) {
+ counter_updates = counters_init(STATS_END);
+ }
}
/*
void
stats_update_size(enum stats stat, size_t size, unsigned files)
{
+ init_counter_updates();
if (stat != STATS_NONE) {
- counter_updates[stat]++;
+ counter_updates->data[stat]++;
}
- counter_updates[STATS_NUMFILES] += files;
- counter_updates[STATS_TOTALSIZE] += size;
+ counter_updates->data[STATS_NUMFILES] += files;
+ counter_updates->data[STATS_TOTALSIZE] += size;
}
/* Read in the stats from one directory and add to the counters. */
-static void
-stats_read(const char *path, unsigned counters[STATS_END])
+void
+stats_read(const char *sfile, struct counters *counters)
{
- int fd;
-
- fd = open(path, O_RDONLY|O_BINARY);
- if (fd == -1) {
- stats_default(counters);
+ char *data = read_file(sfile);
+ if (data) {
+ parse_stats(counters, data);
} else {
- char buf[1024];
- int len = read(fd, buf, sizeof(buf)-1);
- if (len <= 0) {
- stats_default(counters);
- return;
- }
- buf[len] = 0;
- parse_stats(counters, buf);
- close(fd);
+ stats_default(counters);
}
+ free(data);
}
/*
void
stats_flush(void)
{
- unsigned counters[STATS_END];
+ struct counters *counters;
int need_cleanup = 0;
int should_flush = 0;
int i;
if (getenv("CCACHE_NOSTATS")) return;
+ init_counter_updates();
+
for (i = 0; i < STATS_END; ++i) {
- if (counter_updates[i] > 0) {
+ if (counter_updates->data[i] > 0) {
should_flush = 1;
break;
}
free(stats_dir);
}
- memset(counters, 0, sizeof(counters));
-
if (!lockfile_acquire(stats_file, lock_staleness_limit)) {
return;
}
+ counters = counters_init(STATS_END);
stats_read(stats_file, counters);
for (i = 0; i < STATS_END; ++i) {
- counters[i] += counter_updates[i];
+ counters->data[i] += counter_updates->data[i];
}
- write_stats(stats_file, counters);
+ stats_write(stats_file, counters);
lockfile_release(stats_file);
- if (counters[STATS_MAXFILES] != 0 &&
- counters[STATS_NUMFILES] > counters[STATS_MAXFILES]) {
+ if (counters->data[STATS_MAXFILES] != 0 &&
+ counters->data[STATS_NUMFILES] > counters->data[STATS_MAXFILES]) {
need_cleanup = 1;
}
- if (counters[STATS_MAXSIZE] != 0 &&
- counters[STATS_TOTALSIZE] > counters[STATS_MAXSIZE]) {
+ if (counters->data[STATS_MAXSIZE] != 0 &&
+ counters->data[STATS_TOTALSIZE] > counters->data[STATS_MAXSIZE]) {
need_cleanup = 1;
}
if (need_cleanup) {
char *p = dirname(stats_file);
- cleanup_dir(p, counters[STATS_MAXFILES], counters[STATS_MAXSIZE]);
+ cleanup_dir(p,
+ counters->data[STATS_MAXFILES],
+ counters->data[STATS_MAXSIZE]);
free(p);
}
}
stats_update_size(stat, 0, 0);
}
-/* Get the pending update a counter value. */
+/* Get the pending update of a counter value. */
unsigned
stats_get_pending(enum stats stat)
{
- return counter_updates[stat];
+ init_counter_updates();
+ return counter_updates->data[stat];
}
/* sum and display the total stats for all cache dirs */
stats_summary(void)
{
int dir, i;
- unsigned counters[STATS_END];
-
- memset(counters, 0, sizeof(counters));
+ struct counters *counters = counters_init(STATS_END);
/* add up the stats in each directory */
for (dir = -1; dir <= 0xF; dir++) {
/* oh what a nasty hack ... */
if (dir == -1) {
- counters[STATS_MAXSIZE] = 0;
+ counters->data[STATS_MAXSIZE] = 0;
}
-
}
printf("cache directory %s\n", cache_dir);
for (i = 0; stats_info[i].message; i++) {
enum stats stat = stats_info[i].stat;
- if (counters[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) {
+ if (counters->data[stat] == 0 && !(stats_info[i].flags & FLAG_ALWAYS)) {
continue;
}
printf("%s ", stats_info[i].message);
if (stats_info[i].fn) {
- stats_info[i].fn(counters[stat]);
+ stats_info[i].fn(counters->data[stat]);
printf("\n");
} else {
- printf("%8u\n", counters[stat]);
+ printf("%8u\n", counters->data[stat]);
}
}
+
+ counters_free(counters);
}
/* zero all the stats structures */
int dir;
unsigned i;
char *fname;
- unsigned counters[STATS_END];
fname = format("%s/stats", cache_dir);
unlink(fname);
free(fname);
for (dir = 0; dir <= 0xF; dir++) {
+ struct counters *counters = counters_init(STATS_END);
fname = format("%s/%1x/stats", cache_dir, dir);
- memset(counters, 0, sizeof(counters));
- if (!lockfile_acquire(fname, lock_staleness_limit)) {
- free(fname);
- continue;
- }
- stats_read(fname, counters);
- for (i = 0; stats_info[i].message; i++) {
- if (!(stats_info[i].flags & FLAG_NOZERO)) {
- counters[stats_info[i].stat] = 0;
+ if (lockfile_acquire(fname, lock_staleness_limit)) {
+ stats_read(fname, counters);
+ for (i = 0; stats_info[i].message; i++) {
+ if (!(stats_info[i].flags & FLAG_NOZERO)) {
+ counters->data[stats_info[i].stat] = 0;
+ }
}
+ stats_write(fname, counters);
+ lockfile_release(fname);
}
- write_stats(fname, counters);
- lockfile_release(fname);
+ counters_free(counters);
free(fname);
}
}
void
stats_get_limits(const char *dir, unsigned *maxfiles, unsigned *maxsize)
{
- unsigned counters[STATS_END];
+ struct counters *counters = counters_init(STATS_END);
char *sname = format("%s/stats", dir);
- memset(counters, 0, sizeof(counters));
stats_read(sname, counters);
+ *maxfiles = counters->data[STATS_MAXFILES];
+ *maxsize = counters->data[STATS_MAXSIZE];
free(sname);
- *maxfiles = counters[STATS_MAXFILES];
- *maxsize = counters[STATS_MAXSIZE];
+ counters_free(counters);
}
/* set the per directory limits */
stats_set_limits(long maxfiles, long maxsize)
{
int dir;
- unsigned counters[STATS_END];
if (maxfiles != -1) {
maxfiles /= 16;
cdir = format("%s/%1x", cache_dir, dir);
if (create_dir(cdir) != 0) {
+ free(cdir);
return 1;
}
fname = format("%s/stats", cdir);
free(cdir);
- if (!lockfile_acquire(fname, lock_staleness_limit)) {
- free(fname);
- continue;
- }
- memset(counters, 0, sizeof(counters));
- stats_read(fname, counters);
- if (maxfiles != -1) {
- counters[STATS_MAXFILES] = maxfiles;
- }
- if (maxsize != -1) {
- counters[STATS_MAXSIZE] = maxsize;
+ if (lockfile_acquire(fname, lock_staleness_limit)) {
+ struct counters *counters = counters_init(STATS_END);
+ stats_read(fname, counters);
+ if (maxfiles != -1) {
+ counters->data[STATS_MAXFILES] = maxfiles;
+ }
+ if (maxsize != -1) {
+ counters->data[STATS_MAXSIZE] = maxsize;
+ }
+ stats_write(fname, counters);
+ lockfile_release(fname);
+ counters_free(counters);
}
- write_stats(fname, counters);
- lockfile_release(fname);
free(fname);
}
void
stats_set_sizes(const char *dir, size_t num_files, size_t total_size)
{
- unsigned counters[STATS_END];
+ struct counters *counters = counters_init(STATS_END);
char *statsfile;
create_dir(dir);
statsfile = format("%s/stats", dir);
- memset(counters, 0, sizeof(counters));
-
- if (!lockfile_acquire(statsfile, lock_staleness_limit)) {
- free(statsfile);
- return;
+ if (lockfile_acquire(statsfile, lock_staleness_limit)) {
+ stats_read(statsfile, counters);
+ counters->data[STATS_NUMFILES] = num_files;
+ counters->data[STATS_TOTALSIZE] = total_size;
+ stats_write(statsfile, counters);
+ lockfile_release(statsfile);
}
- stats_read(statsfile, counters);
- counters[STATS_NUMFILES] = num_files;
- counters[STATS_TOTALSIZE] = total_size;
- write_stats(statsfile, counters);
- lockfile_release(statsfile);
free(statsfile);
+ counters_free(counters);
}