Commit 817a033f authored by Max Kellermann's avatar Max Kellermann

update: replaced update_return with global "modified" flag

There is only once update thread at a time. Make the "modified" flag global and remove the return values of most functions. Propagating an error is only useful for updateDirectory(), since updateInDirectory() will delete failed subdirectories.
parent b8115f2a
...@@ -30,18 +30,14 @@ ...@@ -30,18 +30,14 @@
#include "condition.h" #include "condition.h"
#include "update.h" #include "update.h"
enum update_return {
UPDATE_RETURN_ERROR = -1,
UPDATE_RETURN_NOUPDATE = 0,
UPDATE_RETURN_UPDATED = 1
};
static enum update_progress { static enum update_progress {
UPDATE_PROGRESS_IDLE = 0, UPDATE_PROGRESS_IDLE = 0,
UPDATE_PROGRESS_RUNNING = 1, UPDATE_PROGRESS_RUNNING = 1,
UPDATE_PROGRESS_DONE = 2 UPDATE_PROGRESS_DONE = 2
} progress; } progress;
static bool modified;
/* make this dynamic?, or maybe this is big enough... */ /* make this dynamic?, or maybe this is big enough... */
static char *update_paths[32]; static char *update_paths[32];
static size_t update_paths_nr; static size_t update_paths_nr;
...@@ -130,7 +126,6 @@ delete_directory(struct directory *directory) ...@@ -130,7 +126,6 @@ delete_directory(struct directory *directory)
struct delete_data { struct delete_data {
char *tmp; char *tmp;
struct directory *dir; struct directory *dir;
enum update_return ret;
}; };
/* passed to songvec_for_each */ /* passed to songvec_for_each */
...@@ -144,32 +139,31 @@ delete_song_if_removed(struct song *song, void *_data) ...@@ -144,32 +139,31 @@ delete_song_if_removed(struct song *song, void *_data)
if (!isFile(data->tmp, NULL)) { if (!isFile(data->tmp, NULL)) {
delete_song(data->dir, song); delete_song(data->dir, song);
data->ret = UPDATE_RETURN_UPDATED; modified = true;
} }
return 0; return 0;
} }
static enum update_return static void
delete_path(const char *path) delete_path(const char *path)
{ {
struct directory *directory = db_get_directory(path); struct directory *directory = db_get_directory(path);
struct song *song = db_get_song(path); struct song *song = db_get_song(path);
if (directory != NULL) if (directory != NULL) {
delete_directory(directory); delete_directory(directory);
modified = true;
}
if (song != NULL) if (song != NULL) {
delete_song(song->parent, song); delete_song(song->parent, song);
modified = true;
return directory == NULL && song == NULL }
? UPDATE_RETURN_NOUPDATE
: UPDATE_RETURN_UPDATED;
} }
static enum update_return static void
removeDeletedFromDirectory(char *path_max_tmp, struct directory *directory) removeDeletedFromDirectory(char *path_max_tmp, struct directory *directory)
{ {
enum update_return ret = UPDATE_RETURN_NOUPDATE;
int i; int i;
struct dirvec *dv = &directory->children; struct dirvec *dv = &directory->children;
struct delete_data data; struct delete_data data;
...@@ -179,15 +173,12 @@ removeDeletedFromDirectory(char *path_max_tmp, struct directory *directory) ...@@ -179,15 +173,12 @@ removeDeletedFromDirectory(char *path_max_tmp, struct directory *directory)
continue; continue;
LOG("removing directory: %s\n", dv->base[i]->path); LOG("removing directory: %s\n", dv->base[i]->path);
dirvec_delete(dv, dv->base[i]); dirvec_delete(dv, dv->base[i]);
ret = UPDATE_RETURN_UPDATED; modified = true;
} }
data.dir = directory; data.dir = directory;
data.tmp = path_max_tmp; data.tmp = path_max_tmp;
data.ret = ret;
songvec_for_each(&directory->songs, delete_song_if_removed, &data); songvec_for_each(&directory->songs, delete_song_if_removed, &data);
return data.ret;
} }
static const char *opendir_path(char *path_max_tmp, const char *dirname) static const char *opendir_path(char *path_max_tmp, const char *dirname)
...@@ -227,10 +218,10 @@ inodeFoundInParent(struct directory *parent, ino_t inode, dev_t device) ...@@ -227,10 +218,10 @@ inodeFoundInParent(struct directory *parent, ino_t inode, dev_t device)
return 0; return 0;
} }
static enum update_return static bool
updateDirectory(struct directory *directory, const struct stat *st); updateDirectory(struct directory *directory, const struct stat *st);
static enum update_return static void
updateInDirectory(struct directory *directory, updateInDirectory(struct directory *directory,
const char *name, const struct stat *st) const char *name, const struct stat *st)
{ {
...@@ -241,25 +232,23 @@ updateInDirectory(struct directory *directory, ...@@ -241,25 +232,23 @@ updateInDirectory(struct directory *directory,
if (song == NULL) { if (song == NULL) {
song = song_file_load(shortname, directory); song = song_file_load(shortname, directory);
if (song == NULL) if (song == NULL)
return -1; return;
songvec_add(&directory->songs, song); songvec_add(&directory->songs, song);
modified = true;
LOG("added %s\n", name); LOG("added %s\n", name);
return UPDATE_RETURN_UPDATED;
} else if (st->st_mtime != song->mtime) { } else if (st->st_mtime != song->mtime) {
LOG("updating %s\n", name); LOG("updating %s\n", name);
if (!song_file_update(song)) if (!song_file_update(song))
delete_song(directory, song); delete_song(directory, song);
return UPDATE_RETURN_UPDATED; modified = true;
} }
return UPDATE_RETURN_NOUPDATE;
} else if (S_ISDIR(st->st_mode)) { } else if (S_ISDIR(st->st_mode)) {
struct directory *subdir; struct directory *subdir;
enum update_return ret; bool ret;
if (inodeFoundInParent(directory, st->st_ino, st->st_dev)) if (inodeFoundInParent(directory, st->st_ino, st->st_dev))
return UPDATE_RETURN_ERROR; return;
subdir = directory_get_child(directory, name); subdir = directory_get_child(directory, name);
if (subdir == NULL) if (subdir == NULL)
...@@ -268,13 +257,10 @@ updateInDirectory(struct directory *directory, ...@@ -268,13 +257,10 @@ updateInDirectory(struct directory *directory,
assert(directory == subdir->parent); assert(directory == subdir->parent);
ret = updateDirectory(subdir, st); ret = updateDirectory(subdir, st);
if (ret == UPDATE_RETURN_ERROR || directory_is_empty(subdir)) if (!ret)
delete_directory(subdir); delete_directory(subdir);
return ret;
} else { } else {
DEBUG("update: %s is not a directory or music\n", name); DEBUG("update: %s is not a directory or music\n", name);
return UPDATE_RETURN_NOUPDATE;
} }
} }
...@@ -284,14 +270,13 @@ static int skip_path(const char *path) ...@@ -284,14 +270,13 @@ static int skip_path(const char *path)
return (path[0] == '.' || strchr(path, '\n')) ? 1 : 0; return (path[0] == '.' || strchr(path, '\n')) ? 1 : 0;
} }
static enum update_return static bool
updateDirectory(struct directory *directory, const struct stat *st) updateDirectory(struct directory *directory, const struct stat *st)
{ {
DIR *dir; DIR *dir;
const char *dirname = directory_get_path(directory); const char *dirname = directory_get_path(directory);
struct dirent *ent; struct dirent *ent;
char path_max_tmp[MPD_PATH_MAX]; char path_max_tmp[MPD_PATH_MAX];
enum update_return ret = UPDATE_RETURN_NOUPDATE, ret2;
assert(S_ISDIR(st->st_mode)); assert(S_ISDIR(st->st_mode));
...@@ -299,10 +284,9 @@ updateDirectory(struct directory *directory, const struct stat *st) ...@@ -299,10 +284,9 @@ updateDirectory(struct directory *directory, const struct stat *st)
dir = opendir(opendir_path(path_max_tmp, dirname)); dir = opendir(opendir_path(path_max_tmp, dirname));
if (!dir) if (!dir)
return UPDATE_RETURN_ERROR; return false;
if (removeDeletedFromDirectory(path_max_tmp, directory) > 0) removeDeletedFromDirectory(path_max_tmp, directory);
ret = UPDATE_RETURN_UPDATED;
while ((ent = readdir(dir))) { while ((ent = readdir(dir))) {
char *utf8; char *utf8;
...@@ -320,17 +304,14 @@ updateDirectory(struct directory *directory, const struct stat *st) ...@@ -320,17 +304,14 @@ updateDirectory(struct directory *directory, const struct stat *st)
dirname, strlen(dirname)); dirname, strlen(dirname));
if (myStat(path_max_tmp, &st2) == 0) if (myStat(path_max_tmp, &st2) == 0)
ret2 = updateInDirectory(directory, path_max_tmp, updateInDirectory(directory, path_max_tmp, &st2);
&st2);
else else
ret2 = delete_path(path_max_tmp); delete_path(path_max_tmp);
if (ret == UPDATE_RETURN_NOUPDATE)
ret = ret2;
} }
closedir(dir); closedir(dir);
return ret; return true;
} }
static struct directory * static struct directory *
...@@ -381,38 +362,35 @@ addParentPathToDB(const char *utf8path) ...@@ -381,38 +362,35 @@ addParentPathToDB(const char *utf8path)
return directory; return directory;
} }
static enum update_return updatePath(const char *path) static void
updatePath(const char *path)
{ {
struct stat st; struct stat st;
if (myStat(path, &st) < 0) if (myStat(path, &st) == 0)
return delete_path(path); updateInDirectory(addParentPathToDB(path), path, &st);
else
return updateInDirectory(addParentPathToDB(path), path, &st); delete_path(path);
} }
static void * update_task(void *_path) static void * update_task(void *_path)
{ {
enum update_return ret = UPDATE_RETURN_NOUPDATE;
if (_path != NULL && !isRootDirectory(_path)) { if (_path != NULL && !isRootDirectory(_path)) {
ret = updatePath((char *)_path); updatePath((char *)_path);
free(_path); free(_path);
} else { } else {
struct directory *directory = db_get_root(); struct directory *directory = db_get_root();
struct stat st; struct stat st;
if (myStat(directory_get_path(directory), &st) == 0) if (myStat(directory_get_path(directory), &st) == 0)
ret = updateDirectory(directory, &st); updateDirectory(directory, &st);
else
ret = UPDATE_RETURN_ERROR;
} }
if (ret == UPDATE_RETURN_UPDATED && db_save() < 0) if (modified)
ret = UPDATE_RETURN_ERROR; db_save();
progress = UPDATE_PROGRESS_DONE; progress = UPDATE_PROGRESS_DONE;
wakeup_main_task(); wakeup_main_task();
return (void *)ret; return NULL;
} }
static void spawn_update_task(char *path) static void spawn_update_task(char *path)
...@@ -422,6 +400,7 @@ static void spawn_update_task(char *path) ...@@ -422,6 +400,7 @@ static void spawn_update_task(char *path)
assert(pthread_equal(pthread_self(), main_task)); assert(pthread_equal(pthread_self(), main_task));
progress = UPDATE_PROGRESS_RUNNING; progress = UPDATE_PROGRESS_RUNNING;
modified = false;
pthread_attr_init(&attr); pthread_attr_init(&attr);
if (pthread_create(&update_thr, &attr, update_task, path)) if (pthread_create(&update_thr, &attr, update_task, path))
FATAL("Failed to spawn update task: %s\n", strerror(errno)); FATAL("Failed to spawn update task: %s\n", strerror(errno));
...@@ -457,9 +436,6 @@ directory_update_init(char *path) ...@@ -457,9 +436,6 @@ directory_update_init(char *path)
void reap_update_task(void) void reap_update_task(void)
{ {
void *thread_return;
enum update_return ret;
assert(pthread_equal(pthread_self(), main_task)); assert(pthread_equal(pthread_self(), main_task));
if (progress == UPDATE_PROGRESS_IDLE) if (progress == UPDATE_PROGRESS_IDLE)
...@@ -477,10 +453,10 @@ void reap_update_task(void) ...@@ -477,10 +453,10 @@ void reap_update_task(void)
if (progress != UPDATE_PROGRESS_DONE) if (progress != UPDATE_PROGRESS_DONE)
return; return;
if (pthread_join(update_thr, &thread_return)) if (pthread_join(update_thr, NULL))
FATAL("error joining update thread: %s\n", strerror(errno)); FATAL("error joining update thread: %s\n", strerror(errno));
ret = (enum update_return)(size_t)thread_return;
if (ret == UPDATE_RETURN_UPDATED) if (modified)
playlistVersionChange(); playlistVersionChange();
if (update_paths_nr) { if (update_paths_nr) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment