[library] support forced metadata scan of library, via '.meta-rescan' file

This commit is contained in:
whatdoineed2do/Ray 2019-06-08 15:10:55 +01:00 committed by ejurgensen
parent b240460469
commit 8f311d4360
4 changed files with 105 additions and 3 deletions

View File

@ -417,6 +417,9 @@ Now you can make a cron job that runs this command:
When forked-daapd detects a file with filename ending .init-rescan it will
perform a bulk scan similar to the startup scan.
Alternatively, you can force a metadata scan of the library even if the
files have not changed by creating a filename ending `.meta-rescan`.
### Troubleshooting library issues

View File

@ -294,6 +294,49 @@ rescan(void *arg, int *ret)
return COMMAND_END;
}
static enum command_state
metarescan(void *arg, int *ret)
{
time_t starttime;
time_t endtime;
int i;
DPRINTF(E_LOG, L_LIB, "Library meta rescan triggered\n");
listener_notify(LISTENER_UPDATE);
starttime = time(NULL);
for (i = 0; sources[i]; i++)
{
if (!sources[i]->disabled && sources[i]->metarescan)
{
DPRINTF(E_INFO, L_LIB, "Meta rescan library source '%s'\n", sources[i]->name);
sources[i]->metarescan();
}
else
{
DPRINTF(E_INFO, L_LIB, "Library source '%s' is disabled\n", sources[i]->name);
}
}
purge_cruft(starttime);
DPRINTF(E_DBG, L_LIB, "Running post library scan jobs\n");
db_hook_post_scan();
endtime = time(NULL);
DPRINTF(E_LOG, L_LIB, "Library meta rescan completed in %.f sec (%d changes)\n", difftime(endtime, starttime), deferred_update_notifications);
scanning = false;
if (handle_deferred_update_notifications())
listener_notify(LISTENER_UPDATE | LISTENER_DATABASE);
else
listener_notify(LISTENER_UPDATE);
*ret = 0;
return COMMAND_END;
}
static enum command_state
fullrescan(void *arg, int *ret)
{
@ -382,6 +425,18 @@ library_rescan()
commands_exec_async(cmdbase, rescan, NULL);
}
void
library_metarescan()
{
if (scanning)
{
DPRINTF(E_INFO, L_LIB, "Scan already running, ignoring request to trigger metadata scan\n");
return;
}
scanning = true; // TODO Guard "scanning" with a mutex
commands_exec_async(cmdbase, metarescan, NULL);
}
void
library_fullrescan()
{

View File

@ -61,6 +61,11 @@ struct library_source
*/
int (*rescan)(void);
/*
* Run a metadata rescan of library even if files not changed (called from the library thread)
*/
int (*metarescan)(void);
/*
* Run a full rescan (purge library entries and rescan) (called from the library thread)
*/
@ -99,6 +104,9 @@ library_queue_add(const char *path, int position, int *count, int *new_item_id);
void
library_rescan();
void
library_metarescan();
void
library_fullrescan();

View File

@ -76,6 +76,7 @@
#define F_SCAN_RESCAN (1 << 1)
#define F_SCAN_FAST (1 << 2)
#define F_SCAN_MOVED (1 << 3)
#define F_SCAN_METARESCAN (1 << 4)
#define F_SCAN_TYPE_FILE (1 << 0)
#define F_SCAN_TYPE_PODCAST (1 << 1)
@ -96,6 +97,7 @@ enum file_type {
FILE_CTRL_LASTFM,
FILE_CTRL_SPOTIFY,
FILE_CTRL_INITSCAN,
FILE_CTRL_METASCAN, // forced scan for meta, preserves existing db records
FILE_CTRL_FULLSCAN,
};
@ -366,6 +368,9 @@ file_type_get(const char *path) {
if (strcasecmp(ext, ".init-rescan") == 0)
return FILE_CTRL_INITSCAN;
if (strcasecmp(ext, ".meta-rescan") == 0)
return FILE_CTRL_METASCAN;
if (strcasecmp(ext, ".full-rescan") == 0)
return FILE_CTRL_FULLSCAN;
@ -477,9 +482,12 @@ process_regular_file(const char *file, struct stat *sb, int type, int flags, int
// Will return 0 if file is not in library or if file mtime is newer than library timestamp
// - note if mtime is 0 then we always scan the file
ret = db_file_ping_bypath(file, sb->st_mtime);
if ((sb->st_mtime != 0) && (ret != 0))
return;
if (!(flags & F_SCAN_METARESCAN))
{
ret = db_file_ping_bypath(file, sb->st_mtime);
if ((sb->st_mtime != 0) && (ret != 0))
return;
}
// File is new or modified - (re)scan metadata and update file in library
memset(&mfi, 0, sizeof(struct media_file_info));
@ -624,6 +632,15 @@ process_file(char *file, struct stat *sb, int type, int flags, int dir_id)
library_rescan();
break;
case FILE_CTRL_METASCAN:
if (flags & F_SCAN_BULK)
break;
DPRINTF(E_LOG, L_SCAN, "Meta rescan triggered, found meta-rescan file: %s\n", file);
library_metarescan();
break;
case FILE_CTRL_FULLSCAN:
if (flags & F_SCAN_BULK)
break;
@ -1630,6 +1647,24 @@ filescanner_rescan()
return 0;
}
static int
filescanner_metarescan()
{
DPRINTF(E_LOG, L_SCAN, "meta rescan triggered\n");
inofd_event_unset(); // Clears all inotify watches
db_watch_clear();
inofd_event_set();
bulk_scan(F_SCAN_BULK | F_SCAN_METARESCAN);
if (!library_is_exiting())
{
/* Enable inotify */
event_add(inoev, NULL);
}
return 0;
}
static int
filescanner_fullrescan()
{
@ -2133,6 +2168,7 @@ struct library_source filescanner =
.deinit = filescanner_deinit,
.initscan = filescanner_initscan,
.rescan = filescanner_rescan,
.metarescan = filescanner_metarescan,
.fullrescan = filescanner_fullrescan,
.playlist_add = playlist_add,
.playlist_remove = playlist_remove,