diff options
author | Eric Wong <normalperson@yhbt.net> | 2008-10-11 23:04:36 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2008-10-12 05:27:33 -0700 |
commit | e018b35b0d99d24e1f3779fd51c07154b370eca9 (patch) | |
tree | 236e61c9c8e69317079e8c2796f6aa5c875bc763 | |
parent | 4111d84ad5b72f871d35f76a47765c138a201611 (diff) | |
download | mpd-e018b35b0d99d24e1f3779fd51c07154b370eca9.tar.gz mpd-e018b35b0d99d24e1f3779fd51c07154b370eca9.tar.xz mpd-e018b35b0d99d24e1f3779fd51c07154b370eca9.zip |
dirvec: use dirvec_for_each where it makes sense
This way we can introduce locking to allow safe traversals from
the main thread while we're updating.
-rw-r--r-- | src/directory.c | 60 | ||||
-rw-r--r-- | src/directory_print.c | 22 | ||||
-rw-r--r-- | src/update.c | 35 |
3 files changed, 65 insertions, 52 deletions
diff --git a/src/directory.c b/src/directory.c index e66349e02..6a0bd18fd 100644 --- a/src/directory.c +++ b/src/directory.c @@ -50,18 +50,17 @@ void directory_free(struct directory *dir) free(dir); } -void directory_prune_empty(struct directory *dir) +static int dir_pruner(struct directory *dir, void *_dv) { - int i; - struct dirvec *dv = &dir->children; + directory_prune_empty(dir); + if (directory_is_empty(dir)) + dirvec_delete((struct dirvec *)_dv, dir); + return 0; +} - for (i = dv->nr; --i >= 0; ) { - directory_prune_empty(dv->base[i]); - if (directory_is_empty(dv->base[i])) - dirvec_delete(dv, dv->base[i]); - } - if (!dv->nr) - dirvec_destroy(dv); +void directory_prune_empty(struct directory *dir) +{ + dirvec_for_each(&dir->children, dir_pruner, &dir->children); } struct directory * @@ -97,27 +96,38 @@ directory_get_subdir(struct directory *dir, const char *name) return found; } -void directory_sort(struct directory *dir) +static int directory_sort_x(struct directory *dir, mpd_unused void *arg) { - int i; - struct dirvec *dv = &dir->children; + directory_sort(dir); + return 0; +} - dirvec_sort(dv); +void directory_sort(struct directory *dir) +{ + dirvec_sort(&dir->children); + dirvec_for_each(&dir->children, directory_sort_x, NULL); songvec_sort(&dir->songs); +} + +struct dirwalk_arg { + int (*each_song) (struct mpd_song *, void *); + int (*each_dir) (struct directory *, void *); + void *data; +}; - for (i = dv->nr; --i >= 0; ) - directory_sort(dv->base[i]); +static int dirwalk_x(struct directory *dir, void *_arg) +{ + struct dirwalk_arg *arg = _arg; + + return directory_walk(dir, arg->each_song, arg->each_dir, arg->data); } -int -directory_walk(struct directory *dir, +int directory_walk(struct directory *dir, int (*forEachSong) (struct mpd_song *, void *), int (*forEachDir) (struct directory *, void *), void *data) { - struct dirvec *dv = &dir->children; int err = 0; - size_t j; if (forEachDir && (err = forEachDir(dir, data)) < 0) return err; @@ -128,9 +138,13 @@ directory_walk(struct directory *dir, return err; } - for (j = 0; err >= 0 && j < dv->nr; ++j) - err = directory_walk(dv->base[j], forEachSong, - forEachDir, data); + if (forEachDir) { + struct dirwalk_arg dw_arg; + dw_arg.each_song = forEachSong; + dw_arg.each_dir = forEachDir; + dw_arg.data = data; + err = dirvec_for_each(&dir->children, dirwalk_x, &dw_arg); + } return err; } diff --git a/src/directory_print.c b/src/directory_print.c index 1c30f1608..d7b42ec59 100644 --- a/src/directory_print.c +++ b/src/directory_print.c @@ -23,25 +23,23 @@ #include "songvec.h" #include "myfprintf.h" -static int dirvec_print(int fd, const struct dirvec *dv) +static int directory_print_info(struct directory *dir, int fd) { - size_t i; - - for (i = 0; i < dv->nr; ++i) { - if (fdprintf(fd, DIRECTORY_DIR "%s\n", - directory_get_path(dv->base[i])) < 0) - return -1; - } + return fdprintf(fd, DIRECTORY_DIR "%s\n", directory_get_path(dir)); +} - return 0; +static int directory_print_info_x(struct directory *dir, void *data) +{ + return directory_print_info(dir, (int)(size_t)data); } int directory_print(int fd, const struct directory *dir) { - if (dirvec_print(fd, &dir->children) < 0) + void *arg = (void *)(size_t)fd; + + if (dirvec_for_each(&dir->children, directory_print_info_x, arg) < 0) return -1; - if (songvec_for_each(&dir->songs, song_print_info_x, - (void *)(size_t)fd) < 0) + if (songvec_for_each(&dir->songs, song_print_info_x, arg) < 0) return -1; return 0; } diff --git a/src/update.c b/src/update.c index 35605ee51..99a58a06e 100644 --- a/src/update.c +++ b/src/update.c @@ -91,15 +91,12 @@ static int delete_each_song(struct mpd_song *song, mpd_unused void *data) * Recursively remove all sub directories and songs from a directory, * leaving an empty directory. */ -static void clear_directory(struct directory *dir) +static int clear_directory(struct directory *dir, mpd_unused void *arg) { - int i; - - for (i = dir->children.nr; --i >= 0;) - clear_directory(dir->children.base[i]); + dirvec_for_each(&dir->children, clear_directory, NULL); dirvec_clear(&dir->children); - songvec_for_each(&dir->songs, delete_each_song, dir); + return 0; } /** @@ -109,7 +106,7 @@ static void delete_directory(struct directory *dir) { assert(dir->parent != NULL); - clear_directory(dir); + clear_directory(dir, NULL); dirvec_delete(&dir->parent->children, dir); directory_free(dir); } @@ -149,23 +146,27 @@ static void delete_path(const char *path) } } -static void -removeDeletedFromDirectory(char *path_max_tmp, struct directory *dir) +/* passed to dirvec_for_each */ +static int delete_directory_if_removed(struct directory *dir, void *_data) { - int i; - struct dirvec *dv = &dir->children; - struct delete_data data; + if (!isDir(dir->path)) { + struct delete_data *data = _data; - for (i = dv->nr; --i >= 0; ) { - if (isDir(dv->base[i]->path)) - continue; - LOG("removing directory: %s\n", dv->base[i]->path); - dirvec_delete(dv, dv->base[i]); + LOG("removing directory: %s\n", directory_get_path(dir)); + dirvec_delete(&data->dir->children, dir); modified = 1; } + return 0; +} + +static void +removeDeletedFromDirectory(char *path_max_tmp, struct directory *dir) +{ + struct delete_data data; data.dir = dir; data.tmp = path_max_tmp; + dirvec_for_each(&dir->children, delete_directory_if_removed, &data); songvec_for_each(&dir->songs, delete_song_if_removed, &data); } |