static int create_dir(const char *path, const char **dir_files) { int res; int i; rmdir(path); res = mkdir(path, 0755); if (res == -1) { PERROR("mkdir"); return -1; } res = check_type(path, S_IFDIR); if (res == -1) return -1; res = check_mode(path, 0755); if (res == -1) return -1; for (i = 0; dir_files[i]; i++) { char fpath[1024]; sprintf(fpath, "%s/%s", path, dir_files[i]); res = create_file(fpath, "", 0); if (res == -1) { cleanup_dir(path, dir_files, 1); return -1; } } res = check_dir_contents(path, dir_files); if (res == -1) { cleanup_dir(path, dir_files, 1); return -1; } return 0; }
/* update the stats counter for this compile */ static void stats_update_size(enum stats stat, size_t size, size_t numfiles) { int fd; unsigned counters[STATS_END]; int need_cleanup = 0; if (getenv("CCACHE_NOSTATS")) return; if (!stats_file) { if (!cache_dir) return; x_asprintf(&stats_file, "%s/stats", cache_dir); } /* open safely to try to prevent symlink races */ fd = safe_open(stats_file); /* still can't get it? don't bother ... */ if (fd == -1) return; memset(counters, 0, sizeof(counters)); if (lock_fd(fd) != 0) { close(fd); return; } /* read in the old stats */ stats_read_fd(fd, counters); /* update them */ counters[stat]++; /* on a cache miss we up the file count and size */ if (stat == STATS_TOCACHE) { counters[STATS_NUMFILES] += numfiles; counters[STATS_TOTALSIZE] += size; } /* and write them out */ write_stats(fd, counters); close(fd); /* we might need to cleanup if the cache has now got too big */ if (counters[STATS_MAXFILES] != 0 && counters[STATS_NUMFILES] > counters[STATS_MAXFILES]) { need_cleanup = 1; } if (counters[STATS_MAXSIZE] != 0 && counters[STATS_TOTALSIZE] > counters[STATS_MAXSIZE]) { need_cleanup = 1; } if (need_cleanup) { char *p = dirname(stats_file); cleanup_dir(p, counters[STATS_MAXFILES], counters[STATS_MAXSIZE], numfiles); free(p); } }
static int test_rename_dir(void) { int err = 0; int res; start_test("rename dir"); res = create_dir(testdir, testdir_files); if (res == -1) return -1; rmdir(testdir2); res = rename(testdir, testdir2); if (res == -1) { PERROR("rename"); cleanup_dir(testdir, testdir_files, 1); return -1; } res = check_nonexist(testdir); if (res == -1) { cleanup_dir(testdir, testdir_files, 1); return -1; } res = check_type(testdir2, S_IFDIR); if (res == -1) { cleanup_dir(testdir2, testdir_files, 1); return -1; } err += check_mode(testdir2, 0755); err += check_dir_contents(testdir2, testdir_files); err += cleanup_dir(testdir2, testdir_files, 0); res = rmdir(testdir2); if (res == -1) { PERROR("rmdir"); return -1; } res = check_nonexist(testdir2); if (res == -1) return -1; if (err) return -1; success(); return 0; }
/* cleanup in all cache subdirs */ void cleanup_all(struct conf *conf) { char *dname; int i; for (i = 0; i <= 0xF; i++) { dname = format("%s/%1x", conf->cache_dir, i); cleanup_dir(conf, dname); free(dname); } }
/* cleanup in all cache subdirs */ void cleanup_all(const char *dir) { unsigned maxfiles, maxsize; char *dname; int i; for (i = 0; i <= 0xF; i++) { dname = format("%s/%1x", dir, i); stats_get_limits(dname, &maxfiles, &maxsize); cleanup_dir(dname, maxfiles, maxsize); free(dname); } }
/* 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]); free(dname); free(sfile); } }
/* * Write counter updates in counter_updates to disk. */ void stats_flush(void) { struct counters *counters; bool need_cleanup = false; bool should_flush = false; int i; assert(conf); if (!conf->stats) { return; } if (!counter_updates) { return; } for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[i] > 0) { should_flush = true; break; } } if (!should_flush) { return; } if (!stats_file) { char *stats_dir; /* * A NULL stats_file means that we didn't get past calculate_object_hash(), * so we just choose one of stats files in the 16 subdirectories. */ stats_dir = format("%s/%x", conf->cache_dir, hash_from_int(getpid()) % 16); stats_file = format("%s/stats", stats_dir); free(stats_dir); } 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->data[i] += counter_updates->data[i]; } stats_write(stats_file, counters); lockfile_release(stats_file); if (!str_eq(conf->log_file, "")) { for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[stats_info[i].stat] != 0 && !(stats_info[i].flags & FLAG_NOZERO)) { cc_log("Result: %s", stats_info[i].message); } } } if (conf->max_files != 0 && counters->data[STATS_NUMFILES] > conf->max_files / 16) { need_cleanup = true; } if (conf->max_size != 0 && counters->data[STATS_TOTALSIZE] > conf->max_size / 1024 / 16) { need_cleanup = true; } if (need_cleanup) { char *p = dirname(stats_file); cleanup_dir(conf, p); free(p); } counters_free(counters); }
/* * Write counter updates in counter_updates to disk. */ void stats_flush(void) { struct counters *counters; bool need_cleanup = false; bool should_flush = false; int i; extern char *cache_logfile; if (getenv("CCACHE_NOSTATS")) return; init_counter_updates(); for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[i] > 0) { should_flush = true; break; } } if (!should_flush) return; if (!stats_file) { char *stats_dir; /* * A NULL stats_file means that we didn't get past calculate_object_hash(), * so we just choose one of stats files in the 16 subdirectories. */ if (!cache_dir) return; stats_dir = format("%s/%x", cache_dir, hash_from_int(getpid()) % 16); stats_file = format("%s/stats", stats_dir); create_dir(stats_dir); free(stats_dir); } 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->data[i] += counter_updates->data[i]; } stats_write(stats_file, counters); lockfile_release(stats_file); if (cache_logfile) { for (i = 0; i < STATS_END; ++i) { if (counter_updates->data[stats_info[i].stat] != 0 && !(stats_info[i].flags & FLAG_NOZERO)) { cc_log("Result: %s", stats_info[i].message); } } } if (counters->data[STATS_MAXFILES] != 0 && counters->data[STATS_NUMFILES] > counters->data[STATS_MAXFILES]) { need_cleanup = true; } if (counters->data[STATS_MAXSIZE] != 0 && counters->data[STATS_TOTALSIZE] > counters->data[STATS_MAXSIZE]) { need_cleanup = true; } if (need_cleanup) { char *p = dirname(stats_file); cleanup_dir(p, counters->data[STATS_MAXFILES], counters->data[STATS_MAXSIZE]); free(p); } }
int main(int argc, char **argv) { int ret; char tmppath[] = "/tmp/lttng-rotate-XXXXXX"; char *session_name, *path, *ext_program; int delay, nr; if (argc != 5) { usage(argv[0]); ret = -1; goto end; } session_name = argv[1]; delay = atoi(argv[2]); nr = atoi(argv[3]); ext_program = argv[4]; if (delay < 0) { fprintf(stderr, "delay-sec must be a positive values\n"); ret = -1; goto end; } if (signal(SIGINT, sighandler) == SIG_ERR) { perror("signal handler"); goto end; } path = mkdtemp(tmppath); if (!path) { fprintf(stderr, "Failed to create temporary path\n"); } printf("Output directory: %s\n", path); ret = setup_session(session_name, path); if (ret) { goto end_cleanup_dir; } if (nr > 0) { unsigned int sleep_time; int i; for (i = 0; i < nr; i++) { ret = rotate_session(session_name, ext_program); if (ret) { goto end_cleanup; } sleep_time = delay; while (sleep_time > 0) { sleep_time = sleep(sleep_time); } } } else { for(;;) { if (quit) { break; } ret = rotate_session(session_name, ext_program); if (ret) { goto end_cleanup; } sleep(delay); } } end_cleanup: ret = cleanup_session(session_name); if (ret) { goto end; } end_cleanup_dir: ret = cleanup_dir(path); end: return ret; }