aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2008-10-04 21:00:47 -0700
committerEric Wong <normalperson@yhbt.net>2008-10-04 21:00:52 -0700
commit3e0c1bcf6237f42506cd0d74046e74a70fff0cb7 (patch)
tree29340c40beff08df42d8a05a296172959dacec7d /src
parent662b6bc9d75d879e52456f680fb1c4fdd0053996 (diff)
parent18ba438d902c801c5f1a6a37d43c87a779e06a84 (diff)
downloadmpd-3e0c1bcf6237f42506cd0d74046e74a70fff0cb7.tar.gz
mpd-3e0c1bcf6237f42506cd0d74046e74a70fff0cb7.tar.xz
mpd-3e0c1bcf6237f42506cd0d74046e74a70fff0cb7.zip
Merge commit 'box/directory' into ew/song-locks
* commit 'box/directory': command: get rid of specialized list handlers directory: simplify list update handling logic main_notify: define main_task so we can use it for assertions directory: streamline deletes Conflicts: src/command.c
Diffstat (limited to '')
-rw-r--r--src/command.c218
-rw-r--r--src/directory.c152
-rw-r--r--src/directory.h7
-rw-r--r--src/main_notify.c3
-rw-r--r--src/main_notify.h4
5 files changed, 159 insertions, 225 deletions
diff --git a/src/command.c b/src/command.c
index 28b6ee3bb..cc5f615c7 100644
--- a/src/command.c
+++ b/src/command.c
@@ -127,8 +127,6 @@
typedef struct _CommandEntry CommandEntry;
typedef int (*CommandHandlerFunction) (int, int *, int, char **);
-typedef int (*CommandListHandlerFunction)
- (int, int *, int, char **, struct strnode *, CommandEntry *);
/* if min: -1 don't check args *
* if max: -1 no max args */
@@ -138,7 +136,6 @@ struct _CommandEntry {
int max;
int reqPermission;
CommandHandlerFunction handler;
- CommandListHandlerFunction listHandler;
};
/* this should really be "need a non-negative integer": */
@@ -152,23 +149,8 @@ static const char check_non_negative[] = "\"%s\" is not an integer >= 0";
static const char *current_command;
static int command_listNum;
-
-static CommandEntry *getCommandEntryFromString(char *string, int *permission);
-
static List *commandList;
-static CommandEntry *newCommandEntry(void)
-{
- CommandEntry *cmd = xmalloc(sizeof(CommandEntry));
- cmd->cmd = NULL;
- cmd->min = 0;
- cmd->max = 0;
- cmd->handler = NULL;
- cmd->listHandler = NULL;
- cmd->reqPermission = 0;
- return cmd;
-}
-
static void command_error_va(int fd, int error, const char *fmt, va_list args)
{
if (current_command && fd != STDERR_FILENO) {
@@ -271,15 +253,13 @@ static void addCommand(const char *name,
int reqPermission,
int minargs,
int maxargs,
- CommandHandlerFunction handler_func,
- CommandListHandlerFunction listHandler_func)
+ CommandHandlerFunction handler_func)
{
- CommandEntry *cmd = newCommandEntry();
+ CommandEntry *cmd = xmalloc(sizeof(CommandEntry));
cmd->cmd = name;
cmd->min = minargs;
cmd->max = maxargs;
cmd->handler = handler_func;
- cmd->listHandler = listHandler_func;
cmd->reqPermission = reqPermission;
insertInList(commandList, cmd->cmd, cmd);
@@ -813,47 +793,17 @@ static int print_update_result(int fd, int ret)
return -1;
}
-static int listHandleUpdate(int fd,
- mpd_unused int *permission,
- mpd_unused int argc,
- char *argv[],
- struct strnode *cmdnode, CommandEntry * cmd)
-{
- static char **pathv;
- static int pathc;
- CommandEntry *nextCmd = NULL;
- struct strnode *next = cmdnode->next;
- int last = pathc++;
-
- pathv = xrealloc(pathv, pathc * sizeof(char *));
- pathv[last] = sanitizePathDup(argc == 2 ? argv[1] : "");
-
- if (next)
- nextCmd = getCommandEntryFromString(next->data, permission);
-
- if (cmd != nextCmd) {
- int ret = print_update_result(fd, updateInit(pathc, pathv));
- if (pathc) {
- assert(pathv);
- free(pathv);
- pathv = NULL;
- pathc = 0;
- }
- return ret;
- }
-
- return 0;
-}
-
static int handleUpdate(int fd, mpd_unused int *permission,
mpd_unused int argc, char *argv[])
{
- char *pathv[1];
+ char *path = NULL;
assert(argc <= 2);
- if (argc == 2)
- pathv[0] = sanitizePathDup(argv[1]);
- return print_update_result(fd, updateInit(argc - 1, pathv));
+ if (argc == 2 && !(path = sanitizePathDup(argv[1]))) {
+ commandError(fd, ACK_ERROR_ARG, "invalid path");
+ return -1;
+ }
+ return print_update_result(fd, directory_update_init(path));
}
static int handleNext(mpd_unused int fd, mpd_unused int *permission,
@@ -1263,70 +1213,70 @@ void initCommands(void)
{
commandList = makeList(free, 1);
- /* addCommand(name, permission, min, max, handler, list handler); */
- addCommand(COMMAND_PLAY, PERMISSION_CONTROL, 0, 1, handlePlay, NULL);
- addCommand(COMMAND_PLAYID, PERMISSION_CONTROL, 0, 1, handlePlayId, NULL);
- addCommand(COMMAND_STOP, PERMISSION_CONTROL, 0, 0, handleStop, NULL);
- addCommand(COMMAND_CURRENTSONG, PERMISSION_READ, 0, 0, handleCurrentSong, NULL);
- addCommand(COMMAND_PAUSE, PERMISSION_CONTROL, 0, 1, handlePause, NULL);
- addCommand(COMMAND_STATUS, PERMISSION_READ, 0, 0, commandStatus, NULL);
- addCommand(COMMAND_KILL, PERMISSION_ADMIN, -1, -1, handleKill, NULL);
- addCommand(COMMAND_CLOSE, PERMISSION_NONE, -1, -1, handleClose, NULL);
- addCommand(COMMAND_ADD, PERMISSION_ADD, 1, 1, handleAdd, NULL);
- addCommand(COMMAND_ADDID, PERMISSION_ADD, 1, 2, handleAddId, NULL);
- addCommand(COMMAND_DELETE, PERMISSION_CONTROL, 1, 1, handleDelete, NULL);
- addCommand(COMMAND_DELETEID, PERMISSION_CONTROL, 1, 1, handleDeleteId, NULL);
- addCommand(COMMAND_PLAYLIST, PERMISSION_READ, 0, 0, handlePlaylist, NULL);
- addCommand(COMMAND_PLAYLISTID, PERMISSION_READ, 0, 1, handlePlaylistId, NULL);
- addCommand(COMMAND_SHUFFLE, PERMISSION_CONTROL, 0, 0, handleShuffle, NULL);
- addCommand(COMMAND_CLEAR, PERMISSION_CONTROL, 0, 0, handleClear, NULL);
- addCommand(COMMAND_SAVE, PERMISSION_CONTROL, 1, 1, handleSave, NULL);
- addCommand(COMMAND_LOAD, PERMISSION_ADD, 1, 1, handleLoad, NULL);
- addCommand(COMMAND_LISTPLAYLIST, PERMISSION_READ, 1, 1, handleListPlaylist, NULL);
- addCommand(COMMAND_LISTPLAYLISTINFO, PERMISSION_READ, 1, 1, handleListPlaylistInfo, NULL);
- addCommand(COMMAND_LSINFO, PERMISSION_READ, 0, 1, handleLsInfo, NULL);
- addCommand(COMMAND_RM, PERMISSION_CONTROL, 1, 1, handleRm, NULL);
- addCommand(COMMAND_PLAYLISTINFO, PERMISSION_READ, 0, 1, handlePlaylistInfo, NULL);
- addCommand(COMMAND_FIND, PERMISSION_READ, 2, -1, handleFind, NULL);
- addCommand(COMMAND_SEARCH, PERMISSION_READ, 2, -1, handleSearch, NULL);
- addCommand(COMMAND_UPDATE, PERMISSION_ADMIN, 0, 1, handleUpdate, listHandleUpdate);
- addCommand(COMMAND_NEXT, PERMISSION_CONTROL, 0, 0, handleNext, NULL);
- addCommand(COMMAND_PREVIOUS, PERMISSION_CONTROL, 0, 0, handlePrevious, NULL);
- addCommand(COMMAND_LISTALL, PERMISSION_READ, 0, 1, handleListAll, NULL);
- addCommand(COMMAND_VOLUME, PERMISSION_CONTROL, 1, 1, handleVolume, NULL);
- addCommand(COMMAND_REPEAT, PERMISSION_CONTROL, 1, 1, handleRepeat, NULL);
- addCommand(COMMAND_RANDOM, PERMISSION_CONTROL, 1, 1, handleRandom, NULL);
- addCommand(COMMAND_STATS, PERMISSION_READ, 0, 0, handleStats, NULL);
- addCommand(COMMAND_CLEAR_ERROR, PERMISSION_CONTROL, 0, 0, handleClearError, NULL);
- addCommand(COMMAND_LIST, PERMISSION_READ, 1, -1, handleList, NULL);
- addCommand(COMMAND_MOVE, PERMISSION_CONTROL, 2, 2, handleMove, NULL);
- addCommand(COMMAND_MOVEID, PERMISSION_CONTROL, 2, 2, handleMoveId, NULL);
- addCommand(COMMAND_SWAP, PERMISSION_CONTROL, 2, 2, handleSwap, NULL);
- addCommand(COMMAND_SWAPID, PERMISSION_CONTROL, 2, 2, handleSwapId, NULL);
- addCommand(COMMAND_SEEK, PERMISSION_CONTROL, 2, 2, handleSeek, NULL);
- addCommand(COMMAND_SEEKID, PERMISSION_CONTROL, 2, 2, handleSeekId, NULL);
- addCommand(COMMAND_LISTALLINFO, PERMISSION_READ, 0, 1, handleListAllInfo, NULL);
- addCommand(COMMAND_PING, PERMISSION_NONE, 0, 0, handlePing, NULL);
- addCommand(COMMAND_SETVOL, PERMISSION_CONTROL, 1, 1, handleSetVol, NULL);
- addCommand(COMMAND_PASSWORD, PERMISSION_NONE, 1, 1, handlePassword, NULL);
- addCommand(COMMAND_CROSSFADE, PERMISSION_CONTROL, 1, 1, handleCrossfade, NULL);
- addCommand(COMMAND_URL_HANDLERS, PERMISSION_READ, 0, 0, handleUrlHandlers, NULL);
- addCommand(COMMAND_PLCHANGES, PERMISSION_READ, 1, 1, handlePlaylistChanges, NULL);
- addCommand(COMMAND_PLCHANGESPOSID, PERMISSION_READ, 1, 1, handlePlaylistChangesPosId, NULL);
- addCommand(COMMAND_ENABLE_DEV, PERMISSION_ADMIN, 1, 1, handleEnableDevice, NULL);
- addCommand(COMMAND_DISABLE_DEV, PERMISSION_ADMIN, 1, 1, handleDisableDevice, NULL);
- addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices, NULL);
- addCommand(COMMAND_COMMANDS, PERMISSION_NONE, 0, 0, handleCommands, NULL);
- addCommand(COMMAND_NOTCOMMANDS, PERMISSION_NONE, 0, 0, handleNotcommands, NULL);
- addCommand(COMMAND_PLAYLISTCLEAR, PERMISSION_CONTROL, 1, 1, handlePlaylistClear, NULL);
- addCommand(COMMAND_PLAYLISTADD, PERMISSION_CONTROL, 2, 2, handlePlaylistAdd, NULL);
- addCommand(COMMAND_PLAYLISTFIND, PERMISSION_READ, 2, -1, handlePlaylistFind, NULL);
- addCommand(COMMAND_PLAYLISTSEARCH, PERMISSION_READ, 2, -1, handlePlaylistSearch, NULL);
- addCommand(COMMAND_PLAYLISTMOVE, PERMISSION_CONTROL, 3, 3, handlePlaylistMove, NULL);
- addCommand(COMMAND_PLAYLISTDELETE, PERMISSION_CONTROL, 2, 2, handlePlaylistDelete, NULL);
- addCommand(COMMAND_TAGTYPES, PERMISSION_READ, 0, 0, handleTagTypes, NULL);
- addCommand(COMMAND_COUNT, PERMISSION_READ, 2, -1, handleCount, NULL);
- addCommand(COMMAND_RENAME, PERMISSION_CONTROL, 2, 2, handleRename, NULL);
+ /* addCommand(name, permission, min, max, handler); */
+ addCommand(COMMAND_PLAY, PERMISSION_CONTROL, 0, 1, handlePlay);
+ addCommand(COMMAND_PLAYID, PERMISSION_CONTROL, 0, 1, handlePlayId);
+ addCommand(COMMAND_STOP, PERMISSION_CONTROL, 0, 0, handleStop);
+ addCommand(COMMAND_CURRENTSONG, PERMISSION_READ, 0, 0, handleCurrentSong);
+ addCommand(COMMAND_PAUSE, PERMISSION_CONTROL, 0, 1, handlePause);
+ addCommand(COMMAND_STATUS, PERMISSION_READ, 0, 0, commandStatus);
+ addCommand(COMMAND_KILL, PERMISSION_ADMIN, -1, -1, handleKill);
+ addCommand(COMMAND_CLOSE, PERMISSION_NONE, -1, -1, handleClose);
+ addCommand(COMMAND_ADD, PERMISSION_ADD, 1, 1, handleAdd);
+ addCommand(COMMAND_ADDID, PERMISSION_ADD, 1, 2, handleAddId);
+ addCommand(COMMAND_DELETE, PERMISSION_CONTROL, 1, 1, handleDelete);
+ addCommand(COMMAND_DELETEID, PERMISSION_CONTROL, 1, 1, handleDeleteId);
+ addCommand(COMMAND_PLAYLIST, PERMISSION_READ, 0, 0, handlePlaylist);
+ addCommand(COMMAND_PLAYLISTID, PERMISSION_READ, 0, 1, handlePlaylistId);
+ addCommand(COMMAND_SHUFFLE, PERMISSION_CONTROL, 0, 0, handleShuffle);
+ addCommand(COMMAND_CLEAR, PERMISSION_CONTROL, 0, 0, handleClear);
+ addCommand(COMMAND_SAVE, PERMISSION_CONTROL, 1, 1, handleSave);
+ addCommand(COMMAND_LOAD, PERMISSION_ADD, 1, 1, handleLoad);
+ addCommand(COMMAND_LISTPLAYLIST, PERMISSION_READ, 1, 1, handleListPlaylist);
+ addCommand(COMMAND_LISTPLAYLISTINFO, PERMISSION_READ, 1, 1, handleListPlaylistInfo);
+ addCommand(COMMAND_LSINFO, PERMISSION_READ, 0, 1, handleLsInfo);
+ addCommand(COMMAND_RM, PERMISSION_CONTROL, 1, 1, handleRm);
+ addCommand(COMMAND_PLAYLISTINFO, PERMISSION_READ, 0, 1, handlePlaylistInfo);
+ addCommand(COMMAND_FIND, PERMISSION_READ, 2, -1, handleFind);
+ addCommand(COMMAND_SEARCH, PERMISSION_READ, 2, -1, handleSearch);
+ addCommand(COMMAND_UPDATE, PERMISSION_ADMIN, 0, 1, handleUpdate);
+ addCommand(COMMAND_NEXT, PERMISSION_CONTROL, 0, 0, handleNext);
+ addCommand(COMMAND_PREVIOUS, PERMISSION_CONTROL, 0, 0, handlePrevious);
+ addCommand(COMMAND_LISTALL, PERMISSION_READ, 0, 1, handleListAll);
+ addCommand(COMMAND_VOLUME, PERMISSION_CONTROL, 1, 1, handleVolume);
+ addCommand(COMMAND_REPEAT, PERMISSION_CONTROL, 1, 1, handleRepeat);
+ addCommand(COMMAND_RANDOM, PERMISSION_CONTROL, 1, 1, handleRandom);
+ addCommand(COMMAND_STATS, PERMISSION_READ, 0, 0, handleStats);
+ addCommand(COMMAND_CLEAR_ERROR, PERMISSION_CONTROL, 0, 0, handleClearError);
+ addCommand(COMMAND_LIST, PERMISSION_READ, 1, -1, handleList);
+ addCommand(COMMAND_MOVE, PERMISSION_CONTROL, 2, 2, handleMove);
+ addCommand(COMMAND_MOVEID, PERMISSION_CONTROL, 2, 2, handleMoveId);
+ addCommand(COMMAND_SWAP, PERMISSION_CONTROL, 2, 2, handleSwap);
+ addCommand(COMMAND_SWAPID, PERMISSION_CONTROL, 2, 2, handleSwapId);
+ addCommand(COMMAND_SEEK, PERMISSION_CONTROL, 2, 2, handleSeek);
+ addCommand(COMMAND_SEEKID, PERMISSION_CONTROL, 2, 2, handleSeekId);
+ addCommand(COMMAND_LISTALLINFO, PERMISSION_READ, 0, 1, handleListAllInfo);
+ addCommand(COMMAND_PING, PERMISSION_NONE, 0, 0, handlePing);
+ addCommand(COMMAND_SETVOL, PERMISSION_CONTROL, 1, 1, handleSetVol);
+ addCommand(COMMAND_PASSWORD, PERMISSION_NONE, 1, 1, handlePassword);
+ addCommand(COMMAND_CROSSFADE, PERMISSION_CONTROL, 1, 1, handleCrossfade);
+ addCommand(COMMAND_URL_HANDLERS, PERMISSION_READ, 0, 0, handleUrlHandlers);
+ addCommand(COMMAND_PLCHANGES, PERMISSION_READ, 1, 1, handlePlaylistChanges);
+ addCommand(COMMAND_PLCHANGESPOSID, PERMISSION_READ, 1, 1, handlePlaylistChangesPosId);
+ addCommand(COMMAND_ENABLE_DEV, PERMISSION_ADMIN, 1, 1, handleEnableDevice);
+ addCommand(COMMAND_DISABLE_DEV, PERMISSION_ADMIN, 1, 1, handleDisableDevice);
+ addCommand(COMMAND_DEVICES, PERMISSION_READ, 0, 0, handleDevices);
+ addCommand(COMMAND_COMMANDS, PERMISSION_NONE, 0, 0, handleCommands);
+ addCommand(COMMAND_NOTCOMMANDS, PERMISSION_NONE, 0, 0, handleNotcommands);
+ addCommand(COMMAND_PLAYLISTCLEAR, PERMISSION_CONTROL, 1, 1, handlePlaylistClear);
+ addCommand(COMMAND_PLAYLISTADD, PERMISSION_CONTROL, 2, 2, handlePlaylistAdd);
+ addCommand(COMMAND_PLAYLISTFIND, PERMISSION_READ, 2, -1, handlePlaylistFind);
+ addCommand(COMMAND_PLAYLISTSEARCH, PERMISSION_READ, 2, -1, handlePlaylistSearch);
+ addCommand(COMMAND_PLAYLISTMOVE, PERMISSION_CONTROL, 3, 3, handlePlaylistMove);
+ addCommand(COMMAND_PLAYLISTDELETE, PERMISSION_CONTROL, 2, 2, handlePlaylistDelete);
+ addCommand(COMMAND_TAGTYPES, PERMISSION_READ, 0, 0, handleTagTypes);
+ addCommand(COMMAND_COUNT, PERMISSION_READ, 2, -1, handleCount);
+ addCommand(COMMAND_RENAME, PERMISSION_CONTROL, 2, 2, handleRename);
sortList(commandList);
}
@@ -1407,24 +1357,6 @@ static CommandEntry *getCommandEntryAndCheckArgcAndPermission(int fd,
return cmd;
}
-static CommandEntry *getCommandEntryFromString(char *string, int *permission)
-{
- CommandEntry *cmd = NULL;
- char *argv[COMMAND_ARGV_MAX] = { NULL };
- char *duplicated = xstrdup(string);
- int argc = buffer2array(duplicated, argv, COMMAND_ARGV_MAX);
-
- if (0 == argc)
- goto out;
-
- cmd = getCommandEntryAndCheckArgcAndPermission(0, permission,
- argc, argv);
-
-out:
- free(duplicated);
- return cmd;
-}
-
static int processCommandInternal(int fd, mpd_unused int *permission,
char *commandString, struct strnode *cmdnode)
{
@@ -1440,12 +1372,8 @@ static int processCommandInternal(int fd, mpd_unused int *permission,
if ((cmd = getCommandEntryAndCheckArgcAndPermission(fd, permission,
argc, argv))) {
- if (!cmdnode || !cmd->listHandler) {
+ if (!cmdnode)
ret = cmd->handler(fd, permission, argc, argv);
- } else {
- ret = cmd->listHandler(fd, permission, argc, argv,
- cmdnode, cmd);
- }
}
current_command = NULL;
diff --git a/src/directory.c b/src/directory.c
index fc9c6b41d..1cd9da9eb 100644
--- a/src/directory.c
+++ b/src/directory.c
@@ -52,13 +52,18 @@ enum update_progress {
UPDATE_PROGRESS_DONE = 2
} progress;
+/* make this dynamic?, or maybe this is big enough... */
+static char *update_paths[32];
+static size_t update_paths_nr;
+
static Directory *music_root;
static time_t directory_dbModTime;
static pthread_t update_thr;
-static int directory_updateJobId;
+static const int update_task_id_max = 1 << 15;
+static int update_task_id;
static int addToDirectory(Directory * directory, const char *name);
@@ -70,8 +75,7 @@ static enum update_return updateDirectory(Directory * directory);
static void deleteEmptyDirectoriesInDirectory(Directory * directory);
-static void removeSongFromDirectory(Directory * directory,
- const char *shortname);
+static void delete_song(Directory *dir, Song *del);
static enum update_return addSubDirectoryToDirectory(Directory * directory,
const char *name, struct stat *st);
@@ -98,87 +102,84 @@ static char *getDbFile(void)
int isUpdatingDB(void)
{
- return (progress != UPDATE_PROGRESS_IDLE) ? directory_updateJobId : 0;
-}
-
-void reap_update_task(void)
-{
- enum update_return ret;
-
- if (progress != UPDATE_PROGRESS_DONE)
- return;
- if (pthread_join(update_thr, (void **)&ret))
- FATAL("error joining update thread: %s\n", strerror(errno));
- if (ret == UPDATE_RETURN_UPDATED)
- playlistVersionChange();
- progress = UPDATE_PROGRESS_IDLE;
+ return (progress != UPDATE_PROGRESS_IDLE) ? update_task_id : 0;
}
-/* @argv represents a null-terminated array of (null-terminated) strings */
-static void * update_task(void *argv)
+static void * update_task(void *_path)
{
enum update_return ret = UPDATE_RETURN_NOUPDATE;
- if (argv) {
- char **pathv;
- for (pathv = (char **)argv; *pathv; pathv++) {
- switch (updatePath(*pathv)) {
- case UPDATE_RETURN_ERROR:
- ret = UPDATE_RETURN_ERROR;
- goto out;
- case UPDATE_RETURN_NOUPDATE:
- break;
- case UPDATE_RETURN_UPDATED:
- ret = UPDATE_RETURN_UPDATED;
- }
- free(*pathv);
- }
- free(argv);
+ if (_path) {
+ ret = updatePath((char *)_path);
+ free(_path);
} else {
ret = updateDirectory(music_root);
}
if (ret == UPDATE_RETURN_UPDATED && writeDirectoryDB() < 0)
ret = UPDATE_RETURN_ERROR;
-out:
progress = UPDATE_PROGRESS_DONE;
wakeup_main_task();
return (void *)ret;
}
-int updateInit(int argc, char *argv[])
+static void spawn_update_task(char *path)
{
pthread_attr_t attr;
- char **pathv = NULL;
- int i;
- if (progress != UPDATE_PROGRESS_IDLE) {
- for (i = argc; --i >= 0; )
- free(argv[i]);
- return -1;
- }
-
- for (i = argc; --i >= 0; ) {
- if (!argv[i])
- return -2;
- }
+ assert(pthread_equal(pthread_self(), main_task));
progress = UPDATE_PROGRESS_RUNNING;
- if (argc > 0) {
- pathv = xmalloc((argc + 1) * sizeof(char *));
- memcpy(pathv, argv, argc * sizeof(char *));
- pathv[argc] = NULL;
- }
-
pthread_attr_init(&attr);
- if (pthread_create(&update_thr, &attr, update_task, pathv))
+ if (pthread_create(&update_thr, &attr, update_task, path))
FATAL("Failed to spawn update task: %s\n", strerror(errno));
- directory_updateJobId++;
- if (directory_updateJobId > 1 << 15)
- directory_updateJobId = 1;
- DEBUG("updateInit: spawned update thread for update job id %i\n",
- (int)directory_updateJobId);
- return directory_updateJobId;
+ if (++update_task_id > update_task_id_max)
+ update_task_id = 1;
+ DEBUG("spawned thread for update job id %i\n", update_task_id);
+}
+
+void reap_update_task(void)
+{
+ enum update_return ret;
+
+ assert(pthread_equal(pthread_self(), main_task));
+
+ if (progress != UPDATE_PROGRESS_DONE)
+ return;
+ if (pthread_join(update_thr, (void **)&ret))
+ FATAL("error joining update thread: %s\n", strerror(errno));
+ if (ret == UPDATE_RETURN_UPDATED)
+ playlistVersionChange();
+
+ if (update_paths_nr) {
+ char *path = update_paths[0];
+ memmove(&update_paths[0], &update_paths[1],
+ --update_paths_nr * sizeof(char *));
+ spawn_update_task(path);
+ } else {
+ progress = UPDATE_PROGRESS_IDLE;
+ }
+}
+
+int directory_update_init(char *path)
+{
+ assert(pthread_equal(pthread_self(), main_task));
+
+ if (progress != UPDATE_PROGRESS_IDLE) {
+ int next_task_id;
+
+ if (!path)
+ return -1;
+ if (update_paths_nr == ARRAY_SIZE(update_paths))
+ return -1;
+ assert(update_paths_nr < ARRAY_SIZE(update_paths));
+ update_paths[update_paths_nr++] = path;
+ next_task_id = update_task_id + update_paths_nr;
+
+ return next_task_id > update_task_id_max ? 1 : next_task_id;
+ }
+ spawn_update_task(path);
+ return update_task_id;
}
static void directory_set_stat(Directory * dir, const struct stat *st)
@@ -212,16 +213,12 @@ static void freeDirectory(Directory * directory)
/*getDirectoryPath(NULL); */
}
-static void removeSongFromDirectory(Directory * directory, const char *shortname)
+static void delete_song(Directory *dir, Song *del)
{
- Song *song = songvec_find(&directory->songs, shortname);
-
- if (song) {
- char path_max_tmp[MPD_PATH_MAX]; /* wasteful */
- LOG("removing: %s\n", get_song_url(path_max_tmp, song));
- songvec_delete(&directory->songs, song);
- freeSong(song); /* FIXME racy */
- }
+ char path_max_tmp[MPD_PATH_MAX]; /* wasteful */
+ LOG("removing: %s\n", get_song_url(path_max_tmp, del));
+ songvec_delete(&dir->songs, del);
+ freeSong(del); /* FIXME racy */
}
static void deleteEmptyDirectoriesInDirectory(Directory * directory)
@@ -256,7 +253,7 @@ updateInDirectory(Directory * directory, const char *name)
} else if (st.st_mtime != song->mtime) {
LOG("updating %s\n", name);
if (updateSongInfo(song) < 0)
- removeSongFromDirectory(directory, shortname);
+ delete_song(directory, song);
return UPDATE_RETURN_UPDATED;
}
} else if (S_ISDIR(st.st_mode)) {
@@ -308,7 +305,7 @@ removeDeletedFromDirectory(char *path_max_tmp, Directory * directory)
strcpy(path_max_tmp, song->url);
if (!isFile(path_max_tmp, NULL)) {
- removeSongFromDirectory(directory, song->url);
+ delete_song(directory, song);
ret = UPDATE_RETURN_UPDATED;
}
}
@@ -322,6 +319,7 @@ static Directory *addDirectoryPathToDB(const char *utf8path)
char *parent;
Directory *parentDirectory;
Directory *directory;
+ Song *conflicting;
parent = parent_path(path_max_tmp, utf8path);
@@ -348,7 +346,10 @@ static Directory *addDirectoryPathToDB(const char *utf8path)
/* if we're adding directory paths, make sure to delete filenames
with potentially the same name */
- removeSongFromDirectory(parentDirectory, mpd_basename(directory->path));
+ conflicting = songvec_find(&parentDirectory->songs,
+ mpd_basename(directory->path));
+ if (conflicting)
+ delete_song(parentDirectory, conflicting);
return directory;
}
@@ -419,14 +420,13 @@ static enum update_return updatePath(const char *utf8path)
else if (updateSongInfo(song) == 0)
return UPDATE_RETURN_UPDATED;
else {
- removeSongFromDirectory(parentDirectory,
- song->url);
+ delete_song(parentDirectory, song);
return UPDATE_RETURN_UPDATED;
}
}
/* if updateDirectory fails, means we should delete it */
else {
- removeSongFromDirectory(parentDirectory, song->url);
+ delete_song(parentDirectory, song);
ret = UPDATE_RETURN_UPDATED;
/* don't return, path maybe a directory now */
}
diff --git a/src/directory.h b/src/directory.h
index eb1b35aa7..20b784166 100644
--- a/src/directory.h
+++ b/src/directory.h
@@ -43,11 +43,10 @@ int isUpdatingDB(void);
/*
* returns the non-negative update job ID on success,
- * -1 if busy, -2 if invalid argument
- * @argv itself is safe to free once updateInit returns, but the
- * string values contained by @argv MUST NOT be freed manually
+ * returns -1 if busy
+ * @path will be freed by this function and should not be reused
*/
-int updateInit(int argc, char *argv[]);
+int directory_update_init(char *path);
void directory_init(void);
diff --git a/src/main_notify.c b/src/main_notify.c
index 2c546633d..04ceac62d 100644
--- a/src/main_notify.c
+++ b/src/main_notify.c
@@ -24,6 +24,8 @@
#include "gcc.h"
#include "log.h"
+pthread_t main_task;
+
static struct ioOps main_notify_IO;
static int main_pipe[2];
@@ -55,6 +57,7 @@ static int ioops_consume(int fd_count, fd_set * rfds,
void init_main_notify(void)
{
+ main_task = pthread_self();
init_async_pipe(main_pipe);
main_notify_IO.fdset = ioops_fdset;
main_notify_IO.consume = ioops_consume;
diff --git a/src/main_notify.h b/src/main_notify.h
index db36042a7..dc743b833 100644
--- a/src/main_notify.h
+++ b/src/main_notify.h
@@ -21,6 +21,10 @@
#ifndef MAIN_NOTIFY_H
#define MAIN_NOTIFY_H
+#include <pthread.h>
+
+extern pthread_t main_task;
+
void init_main_notify(void);
void wakeup_main_task(void);