chiark / gitweb /
manager: introduce unit path cache to minimize disk accesses
authorLennart Poettering <lennart@poettering.net>
Sat, 10 Jul 2010 22:52:00 +0000 (00:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 10 Jul 2010 22:52:00 +0000 (00:52 +0200)
src/load-dropin.c
src/load-fragment.c
src/manager.c
src/manager.h

index bdf3dd2..9ba1201 100644 (file)
@@ -84,7 +84,11 @@ int unit_load_dropin(Unit *u) {
                         if (asprintf(&path, "%s/%s.wants", *p, t) < 0)
                                 return -ENOMEM;
 
-                        r = iterate_dir(u, path);
+                        if (u->meta.manager->unit_path_cache &&
+                            !set_get(u->meta.manager->unit_path_cache, path))
+                                r = 0;
+                        else
+                                r = iterate_dir(u, path);
                         free(path);
 
                         if (r < 0)
@@ -103,7 +107,11 @@ int unit_load_dropin(Unit *u) {
                                 if (r < 0)
                                         return -ENOMEM;
 
-                                r = iterate_dir(u, path);
+                                if (u->meta.manager->unit_path_cache &&
+                                    !set_get(u->meta.manager->unit_path_cache, path))
+                                        r = 0;
+                                else
+                                        r = iterate_dir(u, path);
                                 free(path);
 
                                 if (r < 0)
index 6a71d42..394aa02 100644 (file)
@@ -1690,7 +1690,13 @@ static int load_from_path(Unit *u, const char *path) {
                                 goto finish;
                         }
 
-                        if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
+                        if (u->meta.manager->unit_path_cache &&
+                            !set_get(u->meta.manager->unit_path_cache, filename))
+                                r = -ENOENT;
+                        else
+                                r = open_follow(&filename, &f, symlink_names, &id);
+
+                        if (r < 0) {
                                 char *sn;
 
                                 free(filename);
index a7e24eb..5125db2 100644 (file)
@@ -36,6 +36,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <dirent.h>
 
 #include "manager.h"
 #include "hashmap.h"
@@ -478,11 +479,71 @@ int manager_coldplug(Manager *m) {
         return r;
 }
 
+static void manager_build_unit_path_cache(Manager *m) {
+        char **i;
+        DIR *d = NULL;
+        int r;
+
+        assert(m);
+
+        set_free_free(m->unit_path_cache);
+
+        if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) {
+                log_error("Failed to allocate unit path cache.");
+                return;
+        }
+
+        /* This simply builds a list of files we know exist, so that
+         * we don't always have to go to disk */
+
+        STRV_FOREACH(i, m->lookup_paths.unit_path) {
+                struct dirent *de;
+
+                if (!(d = opendir(*i))) {
+                        log_error("Failed to open directory: %m");
+                        continue;
+                }
+
+                while ((de = readdir(d))) {
+                        char *p;
+
+                        if (ignore_file(de->d_name))
+                                continue;
+
+                        if (asprintf(&p, "%s/%s", streq(*i, "/") ? "" : *i, de->d_name) < 0) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
+                        if ((r = set_put(m->unit_path_cache, p)) < 0) {
+                                free(p);
+                                goto fail;
+                        }
+                }
+
+                closedir(d);
+                d = NULL;
+        }
+
+        return;
+
+fail:
+        log_error("Failed to build unit path cache: %s", strerror(-r));
+
+        set_free_free(m->unit_path_cache);
+        m->unit_path_cache = NULL;
+
+        if (d)
+                closedir(d);
+}
+
 int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         int r, q;
 
         assert(m);
 
+        manager_build_unit_path_cache(m);
+
         /* First, enumerate what we can from all config files */
         r = manager_enumerate(m);
 
@@ -1993,6 +2054,10 @@ int manager_loop(Manager *m) {
         assert(m);
         m->exit_code = MANAGER_RUNNING;
 
+        /* Release the path cache */
+        set_free_free(m->unit_path_cache);
+        m->unit_path_cache = NULL;
+
         /* There might still be some zombies hanging around from
          * before we were exec()'ed. Leat's reap them */
         if ((r = manager_dispatch_sigchld(m)) < 0)
index f3bf96e..0eceab9 100644 (file)
@@ -134,6 +134,7 @@ struct Manager {
         unsigned n_snapshots;
 
         LookupPaths lookup_paths;
+        Set *unit_path_cache;
 
         char **environment;