]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Only create parent directories when needed to save stat() calls
authorJoel Rosdahl <joel@rosdahl.net>
Thu, 7 Oct 2010 19:50:29 +0000 (21:50 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 7 Oct 2010 19:50:29 +0000 (21:50 +0200)
ccache.c
ccache.h
lockfile.c
manifest.c
stats.c
util.c

index 43525c9b403a071a65687953d7d780f511da2b9b..e4b6239e32738b38aedbf9745180970a395bc24c 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -256,24 +256,12 @@ temp_dir()
        if (!path) {
                path = format("%s/tmp", cache_dir);
        }
-
-       /* make sure the temp dir exists */
-       if (create_dir(path) != 0) {
-               fprintf(stderr,
-                       "ccache: failed to create %s (%s)\n",
-                       path, strerror(errno));
-               exit(1);
-       }
        return path;
 }
 
 /*
  * Transform a name to a full path into the cache directory, creating needed
  * sublevels if needed. Caller frees.
- *
- * stat() calls can be expensive on the cache, so we both avoid checking a
- * single path multiple times, and also avoid stat()ing each level in a
- * many level cache.
  */
 static char *
 get_path_in_cache(const char *name, const char *suffix)
@@ -281,9 +269,7 @@ get_path_in_cache(const char *name, const char *suffix)
        int i;
        char *path;
        char *result;
-       struct stat st;
 
-       /* Form the entire path */
        path = x_strdup(cache_dir);
        for (i = 0; i < nlevels; ++i) {
                char *p = format("%s/%c", path, name[i]);
@@ -291,21 +277,6 @@ get_path_in_cache(const char *name, const char *suffix)
                path = p;
        }
 
-       /* First see if whole path exists, so can avoid directory one-by-one check */
-       if (!(stat(path, &st) == 0 && S_ISDIR(st.st_mode))) {
-               free(path);
-               path = x_strdup(cache_dir);
-               for (i = 0; i < nlevels; ++i) {
-                       char *p = format("%s/%c", path, name[i]);
-                       free(path);
-                       path = p;
-                       if (create_dir(path) != 0) {
-                               cc_log("Failed to create %s", path);
-                               failed();
-                       }
-               }
-       }
-
        result = format("%s/%s%s", path, name + nlevels, suffix);
        free(path);
        return result;
@@ -537,6 +508,7 @@ to_cache(struct args *args)
        size_t added_bytes = 0;
        unsigned added_files = 0;
 
+       create_parent_dirs(cached_obj);
        tmp_stdout = format("%s.tmp.stdout.%s", cached_obj, tmp_string());
        tmp_stderr = format("%s.tmp.stderr.%s", cached_obj, tmp_string());
        tmp_obj = format("%s.tmp.%s", cached_obj, tmp_string());
@@ -737,6 +709,15 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash)
                             temp_dir(), input_base, tmp_string(), i_extension);
        path_stderr = format("%s/tmp.cpp_stderr.%s", temp_dir(), tmp_string());
 
+       if (create_parent_dirs(path_stdout) != 0) {
+               char *parent = dirname(path_stdout);
+               fprintf(stderr,
+                       "ccache: failed to create %s (%s)\n",
+                       parent, strerror(errno));
+               free(parent);
+               exit(1);
+       }
+
        time_of_compilation = time(NULL);
 
        if (!direct_i_file) {
@@ -2154,14 +2135,6 @@ ccache_main(int argc, char *argv[])
 
        setup_uncached_err();
 
-       /* make sure the cache dir exists */
-       if (create_dir(cache_dir) != 0) {
-               fprintf(stderr,
-                       "ccache: failed to create %s (%s)\n",
-                       cache_dir, strerror(errno));
-               exit(1);
-       }
-
        ccache(argc, argv);
        return 1;
 }
index 8611429e5586e0a2c7e5d86691a76550d47a721d..c306ddfc7923551206e3debf831e13720b518e3f 100644 (file)
--- a/ccache.h
+++ b/ccache.h
@@ -127,7 +127,7 @@ char *dirname(const char *path);
 const char *get_extension(const char *path);
 char *remove_extension(const char *path);
 size_t file_size(struct stat *st);
-int safe_open(const char *fname);
+int safe_create_wronly(const char *fname);
 char *x_realpath(const char *path);
 char *gnu_getcwd(void);
 int create_empty_file(const char *fname);
index e62aac4be3d52d5e5a133b47e4dbf070070cc2c5..14b0cbb8daf04845c6915dd0afdd97fba14b507c 100644 (file)
@@ -51,6 +51,13 @@ lockfile_acquire(const char *path, unsigned staleness_limit)
                fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0666);
                if (fd == -1) {
                        cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno));
+                       if (errno == ENOENT) {
+                               /* Directory doesn't exist? */
+                               if (create_parent_dirs(lockfile) == 0) {
+                                       /* OK. Retry. */
+                                       continue;
+                               }
+                       }
                        if (errno != EEXIST) {
                                /* Directory doesn't exist or isn't writable? */
                                goto out;
@@ -99,6 +106,13 @@ lockfile_acquire(const char *path, unsigned staleness_limit)
                        goto out;
                }
                cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(errno));
+               if (errno == ENOENT) {
+                       /* Directory doesn't exist? */
+                       if (create_parent_dirs(lockfile) == 0) {
+                               /* OK. Retry. */
+                               continue;
+                       }
+               }
                if (errno != EEXIST) {
                        /* Directory doesn't exist or isn't writable? */
                        goto out;
index bb809ba5736d292cdad9a5825708169b4970b4e8..1e2c53041d371a4351a14a329ce11badc9e5264d 100644 (file)
@@ -580,7 +580,6 @@ manifest_put(const char *manifest_path, struct file_hash *object_hash,
        int ret = 0;
        int fd1;
        int fd2;
-       struct stat st;
        gzFile f1 = NULL;
        gzFile f2 = NULL;
        struct manifest *mf = NULL;
@@ -592,17 +591,8 @@ manifest_put(const char *manifest_path, struct file_hash *object_hash,
         * not a big deal, and it's also very unlikely.
         */
 
-       fd1 = safe_open(manifest_path);
+       fd1 = open(manifest_path, O_RDONLY | O_BINARY);
        if (fd1 == -1) {
-               cc_log("Failed to open manifest file");
-               goto out;
-       }
-       if (fstat(fd1, &st) != 0) {
-               cc_log("Failed to stat manifest file");
-               close(fd1);
-               goto out;
-       }
-       if (st.st_size == 0) {
                /* New file. */
                mf = create_empty_manifest();
        } else {
@@ -646,7 +636,7 @@ manifest_put(const char *manifest_path, struct file_hash *object_hash,
        }
 
        tmp_file = format("%s.tmp.%s", manifest_path, tmp_string());
-       fd2 = safe_open(tmp_file);
+       fd2 = safe_create_wronly(tmp_file);
        if (fd2 == -1) {
                cc_log("Failed to open %s", tmp_file);
                goto out;
diff --git a/stats.c b/stats.c
index ac6d1008c5536c468106d808378e85a0cefe8c76..c98b25b9a0e0d1c407cbfbc15eab14d501f65acd 100644 (file)
--- a/stats.c
+++ b/stats.c
@@ -128,6 +128,11 @@ stats_write(const char *path, struct counters *counters)
 
        tmp_file = format("%s.tmp.%s", path, tmp_string());
        f = fopen(tmp_file, "wb");
+       if (!f && errno == ENOENT) {
+               if (create_parent_dirs(path) == 0) {
+                       f = fopen(tmp_file, "wb");
+               }
+       }
        if (!f) {
                cc_log("Failed to open %s", tmp_file);
                goto end;
@@ -221,7 +226,6 @@ stats_flush(void)
                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);
        }
 
@@ -382,19 +386,11 @@ stats_set_limits(long maxfiles, long maxsize)
                maxsize /= 16;
        }
 
-       if (create_dir(cache_dir) != 0) {
-               return 1;
-       }
-
        /* set the limits in each directory */
        for (dir = 0; dir <= 0xF; dir++) {
                char *fname, *cdir;
 
                cdir = format("%s/%1x", cache_dir, dir);
-               if (create_dir(cdir) != 0) {
-                       free(cdir);
-                       return 1;
-               }
                fname = format("%s/stats", cdir);
                free(cdir);
 
@@ -424,7 +420,6 @@ stats_set_sizes(const char *dir, size_t num_files, size_t total_size)
        struct counters *counters = counters_init(STATS_END);
        char *statsfile;
 
-       create_dir(dir);
        statsfile = format("%s/stats", dir);
 
        if (lockfile_acquire(statsfile, lock_staleness_limit)) {
diff --git a/util.c b/util.c
index 5a5b7dc86d34377721033580e066b34d1a53592d..ce36f07c40700026a6460eba109b1c9b0f652b57 100644 (file)
--- a/util.c
+++ b/util.c
@@ -770,15 +770,20 @@ file_size(struct stat *st)
 #endif
 }
 
-/* a safe open/create for read-write */
+/*
+ * Create a file for writing. Creates parent directories if they don't exist.
+ */
 int
-safe_open(const char *fname)
+safe_create_wronly(const char *fname)
 {
-       int fd = open(fname, O_RDWR|O_BINARY);
+       int fd = open(fname, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0666);
        if (fd == -1 && errno == ENOENT) {
-               fd = open(fname, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0666);
-               if (fd == -1 && errno == EEXIST) {
-                       fd = open(fname, O_RDWR|O_BINARY);
+               /*
+                * Only make sure parent directories exist when have failed to open the
+                * file -- this saves stat() calls.
+                */
+               if (create_parent_dirs(fname) == 0) {
+                       fd = open(fname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0666);
                }
        }
        return fd;