aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/protocol.xml14
-rw-r--r--src/command.c24
-rw-r--r--src/main.c2
-rw-r--r--src/update.c12
-rw-r--r--src/update.h2
-rw-r--r--src/update_internal.h6
-rw-r--r--src/update_queue.c34
-rw-r--r--src/update_walk.c14
8 files changed, 81 insertions, 27 deletions
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 922d27676..29cb09a43 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -1245,6 +1245,20 @@ OK
</para>
</listitem>
</varlistentry>
+ <varlistentry id="command_rescan">
+ <term>
+ <cmdsynopsis>
+ <command>rescan</command>
+ <arg choice="opt"><replaceable>URI</replaceable></arg>
+ </cmdsynopsis>
+ </term>
+ <listitem>
+ <para>
+ Same as <command>update</command>, but also rescans
+ unmodified files.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</section>
diff --git a/src/command.c b/src/command.c
index 8298a4048..7c2743975 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1025,7 +1025,28 @@ handle_update(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
if (argc == 2)
path = argv[1];
- ret = update_enqueue(path);
+ ret = update_enqueue(path, false);
+ if (ret > 0) {
+ client_printf(client, "updating_db: %i\n", ret);
+ return COMMAND_RETURN_OK;
+ } else {
+ command_error(client, ACK_ERROR_UPDATE_ALREADY,
+ "already updating");
+ return COMMAND_RETURN_ERROR;
+ }
+}
+
+static enum command_return
+handle_rescan(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
+{
+ const char *path = NULL;
+ unsigned ret;
+
+ assert(argc <= 2);
+ if (argc == 2)
+ path = argv[1];
+
+ ret = update_enqueue(path, true);
if (ret > 0) {
client_printf(client, "updating_db: %i\n", ret);
return COMMAND_RETURN_OK;
@@ -1731,6 +1752,7 @@ static const struct command commands[] = {
{ "random", PERMISSION_CONTROL, 1, 1, handle_random },
{ "rename", PERMISSION_CONTROL, 2, 2, handle_rename },
{ "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat },
+ { "rescan", PERMISSION_ADMIN, 0, 1, handle_rescan },
{ "rm", PERMISSION_CONTROL, 1, 1, handle_rm },
{ "save", PERMISSION_CONTROL, 1, 1, handle_save },
{ "search", PERMISSION_READ, 2, -1, handle_search },
diff --git a/src/main.c b/src/main.c
index 952e6d1fe..56627b665 100644
--- a/src/main.c
+++ b/src/main.c
@@ -362,7 +362,7 @@ int main(int argc, char *argv[])
if (create_db) {
/* the database failed to load: recreate the
database */
- unsigned job = update_enqueue(NULL);
+ unsigned job = update_enqueue(NULL, true);
if (job == 0)
g_error("directory update failed");
}
diff --git a/src/update.c b/src/update.c
index a8d4f3e10..8570d8ab3 100644
--- a/src/update.c
+++ b/src/update.c
@@ -52,6 +52,9 @@ static unsigned update_task_id;
/** used by the main thread to notify the update thread */
struct notify update_notify;
+/* XXX this flag is passed to update_task() */
+static bool discard;
+
unsigned
isUpdatingDB(void)
{
@@ -62,7 +65,7 @@ static void * update_task(void *_path)
{
const char *path = _path;
- modified = update_walk(path);
+ modified = update_walk(path, discard);
g_free(_path);
if (modified || !db_exists())
@@ -93,7 +96,7 @@ spawn_update_task(const char *path)
}
unsigned
-update_enqueue(const char *path)
+update_enqueue(const char *path, bool _discard)
{
assert(g_thread_self() == main_task);
@@ -102,13 +105,14 @@ update_enqueue(const char *path)
if (progress != UPDATE_PROGRESS_IDLE) {
unsigned next_task_id =
- update_queue_push(path, update_task_id);
+ update_queue_push(path, discard, update_task_id);
if (next_task_id == 0)
return 0;
return next_task_id > update_task_id_max ? 1 : next_task_id;
}
+ discard = _discard;
spawn_update_task(path);
idle_add(IDLE_UPDATE);
@@ -135,7 +139,7 @@ static void update_finished_event(void)
idle_add(IDLE_DATABASE);
}
- path = update_queue_shift();
+ path = update_queue_shift(&discard);
if (path != NULL) {
/* schedule the next path */
spawn_update_task(path);
diff --git a/src/update.h b/src/update.h
index 9a51afc01..109126299 100644
--- a/src/update.h
+++ b/src/update.h
@@ -35,6 +35,6 @@ isUpdatingDB(void);
* @return the job id, or 0 on error
*/
unsigned
-update_enqueue(const char *path);
+update_enqueue(const char *path, bool discard);
#endif
diff --git a/src/update_internal.h b/src/update_internal.h
index b22b3c6b2..14701feb5 100644
--- a/src/update_internal.h
+++ b/src/update_internal.h
@@ -33,10 +33,10 @@ struct directory;
extern struct notify update_notify;
unsigned
-update_queue_push(const char *path, unsigned base);
+update_queue_push(const char *path, bool discard, unsigned base);
char *
-update_queue_shift(void);
+update_queue_shift(bool *discard_r);
void
update_walk_global_init(void);
@@ -48,7 +48,7 @@ update_walk_global_finish(void);
* Returns true if the database was modified.
*/
bool
-update_walk(const char *path);
+update_walk(const char *path, bool discard);
void
update_remove_global_init(void);
diff --git a/src/update_queue.c b/src/update_queue.c
index ef1753c21..60e752a62 100644
--- a/src/update_queue.c
+++ b/src/update_queue.c
@@ -25,31 +25,41 @@
#include <string.h>
/* make this dynamic?, or maybe this is big enough... */
-static char *update_paths[32];
-static size_t update_paths_nr;
+static struct {
+ char *path;
+ bool discard;
+} update_queue[32];
+
+static size_t update_queue_length;
unsigned
-update_queue_push(const char *path, unsigned base)
+update_queue_push(const char *path, bool discard, unsigned base)
{
- assert(update_paths_nr <= G_N_ELEMENTS(update_paths));
+ assert(update_queue_length <= G_N_ELEMENTS(update_queue));
- if (update_paths_nr == G_N_ELEMENTS(update_paths))
+ if (update_queue_length == G_N_ELEMENTS(update_queue))
return 0;
- update_paths[update_paths_nr++] = g_strdup(path);
- return base + update_paths_nr;
+ update_queue[update_queue_length].path = g_strdup(path);
+ update_queue[update_queue_length].discard = discard;
+
+ ++update_queue_length;
+
+ return base + update_queue_length;
}
char *
-update_queue_shift(void)
+update_queue_shift(bool *discard_r)
{
char *path;
- if (update_paths_nr == 0)
+ if (update_queue_length == 0)
return NULL;
- path = update_paths[0];
- memmove(&update_paths[0], &update_paths[1],
- --update_paths_nr * sizeof(char *));
+ path = update_queue[0].path;
+ *discard_r = update_queue[0].discard;
+
+ memmove(&update_queue[0], &update_queue[1],
+ --update_queue_length * sizeof(update_queue[0]));
return path;
}
diff --git a/src/update_walk.c b/src/update_walk.c
index 967795cff..b79e95ae0 100644
--- a/src/update_walk.c
+++ b/src/update_walk.c
@@ -39,6 +39,7 @@
#include <stdlib.h>
#include <errno.h>
+static bool walk_discard;
static bool modified;
#ifndef WIN32
@@ -350,7 +351,8 @@ update_archive_file(struct directory *parent, const char *name,
char *filepath;
directory = dirvec_find(&parent->children, name);
- if (directory != NULL && directory->mtime == st->st_mtime)
+ if (directory != NULL && directory->mtime == st->st_mtime &&
+ !walk_discard)
/* MPD has already scanned the archive, and it hasn't
changed since - don't consider updating it */
return;
@@ -405,7 +407,7 @@ update_container_file( struct directory* directory,
if (contdir != NULL)
{
// modification time not eq. file mod. time
- if (contdir->mtime != st->st_mtime)
+ if (contdir->mtime != st->st_mtime || walk_discard)
{
g_message("removing container file: %s", pathname);
@@ -470,7 +472,8 @@ update_regular_file(struct directory *directory,
{
struct song* song = songvec_find(&directory->songs, name);
- if (!(song != NULL && st->st_mtime == song->mtime) &&
+ if (!(song != NULL && st->st_mtime == song->mtime &&
+ !walk_discard) &&
plugin->container_scan != NULL)
{
if (update_container_file(directory, name, st, plugin))
@@ -491,7 +494,7 @@ update_regular_file(struct directory *directory,
modified = true;
g_message("added %s/%s",
directory_get_path(directory), name);
- } else if (st->st_mtime != song->mtime) {
+ } else if (st->st_mtime != song->mtime || walk_discard) {
g_message("updating %s/%s",
directory_get_path(directory), name);
if (!song_file_update(song))
@@ -737,8 +740,9 @@ updatePath(const char *path)
}
bool
-update_walk(const char *path)
+update_walk(const char *path, bool discard)
{
+ walk_discard = discard;
modified = false;
if (path != NULL && !isRootDirectory(path)) {