diff options
author | Eric Wong <normalperson@yhbt.net> | 2008-10-04 21:00:47 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2008-10-04 21:00:52 -0700 |
commit | 3e0c1bcf6237f42506cd0d74046e74a70fff0cb7 (patch) | |
tree | 29340c40beff08df42d8a05a296172959dacec7d /src | |
parent | 662b6bc9d75d879e52456f680fb1c4fdd0053996 (diff) | |
parent | 18ba438d902c801c5f1a6a37d43c87a779e06a84 (diff) | |
download | mpd-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.c | 218 | ||||
-rw-r--r-- | src/directory.c | 152 | ||||
-rw-r--r-- | src/directory.h | 7 | ||||
-rw-r--r-- | src/main_notify.c | 3 | ||||
-rw-r--r-- | src/main_notify.h | 4 |
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); |