/* Thread: scan */ static void * filescanner(void *arg) { int ret; ret = db_perthread_init(); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Error: DB init failed\n"); pthread_exit(NULL); } ret = db_watch_clear(); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Error: could not clear old watches from DB\n"); pthread_exit(NULL); } ret = db_groups_clear(); if (ret < 0) { DPRINTF(E_LOG, L_SCAN, "Error: could not clear old groups from DB\n"); pthread_exit(NULL); } /* Recompute all songalbumids, in case the SQLite DB got transferred * to a different host; the hash is not portable. * It will also rebuild the groups we just cleared. */ db_files_update_songalbumid(); bulk_scan(); db_hook_post_scan(); if (!scan_exit) { /* Enable inotify */ event_add(&inoev, NULL); event_base_dispatch(evbase_scan); } if (!scan_exit) DPRINTF(E_FATAL, L_SCAN, "Scan event loop terminated ahead of time!\n"); db_perthread_deinit(); pthread_exit(NULL); }
static void initscan() { time_t starttime; time_t endtime; bool clear_queue_disabled; int i; scanning = true; starttime = time(NULL); listener_notify(LISTENER_UPDATE); // Only clear the queue if enabled (default) in config clear_queue_disabled = cfg_getbool(cfg_getsec(cfg, "mpd"), "clear_queue_on_stop_disable"); if (!clear_queue_disabled) { db_queue_clear(0); } for (i = 0; sources[i]; i++) { if (!sources[i]->disabled && sources[i]->initscan) sources[i]->initscan(); } if (! (cfg_getbool(cfg_getsec(cfg, "library"), "filescan_disable"))) { 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 init scan 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); }
/* Thread: scan */ static void bulk_scan(int flags) { cfg_t *lib; int ndirs; char *path; char *deref; time_t start; time_t end; int i; start = time(NULL); playlists = NULL; dirstack = NULL; lib = cfg_getsec(cfg, "library"); ndirs = cfg_size(lib, "directories"); for (i = 0; i < ndirs; i++) { path = cfg_getnstr(lib, "directories", i); deref = m_realpath(path); if (!deref) { DPRINTF(E_LOG, L_SCAN, "Skipping library directory %s, could not dereference: %s\n", path, strerror(errno)); /* Assume dir is mistakenly not mounted, so just disable everything and update timestamps */ db_file_disable_bymatch(path, "", 0); db_pl_disable_bymatch(path, "", 0); db_file_ping_bymatch(path, 1); db_pl_ping_bymatch(path, 1); continue; } counter = 0; db_transaction_begin(); process_directories(deref, flags); db_transaction_end(); free(deref); if (scan_exit) return; } if (!(flags & F_SCAN_FAST) && playlists) process_deferred_playlists(); if (scan_exit) return; if (dirstack) DPRINTF(E_LOG, L_SCAN, "WARNING: unhandled leftover directories\n"); end = time(NULL); if (flags & F_SCAN_FAST) { DPRINTF(E_LOG, L_SCAN, "Bulk library scan completed in %.f sec (with file scan disabled)\n", difftime(end, start)); } else { /* Protect spotify from the imminent purge if rescanning */ if (flags & F_SCAN_RESCAN) { db_file_ping_bymatch("spotify:", 0); db_pl_ping_bymatch("spotify:", 0); } DPRINTF(E_DBG, L_SCAN, "Purging old database content\n"); db_purge_cruft(start); DPRINTF(E_LOG, L_SCAN, "Bulk library scan completed in %.f sec\n", difftime(end, start)); DPRINTF(E_DBG, L_SCAN, "Running post library scan jobs\n"); db_hook_post_scan(); } }