Commit 681e012f authored by Max Kellermann's avatar Max Kellermann

db/update: cancel the update on shutdown

parent 3be36643
...@@ -9,6 +9,7 @@ ver 0.19 (not yet released) ...@@ -9,6 +9,7 @@ ver 0.19 (not yet released)
- proxy: forward "idle" events - proxy: forward "idle" events
- proxy: copy "Last-Modified" from remote directories - proxy: copy "Last-Modified" from remote directories
- upnp: new plugin - upnp: new plugin
- cancel the update on shutdown
* storage * storage
- music_directory can point to a remote file server - music_directory can point to a remote file server
- nfs: new plugin - nfs: new plugin
......
...@@ -596,6 +596,9 @@ int mpd_main(int argc, char *argv[]) ...@@ -596,6 +596,9 @@ int mpd_main(int argc, char *argv[])
#if defined(ENABLE_DATABASE) && defined(ENABLE_INOTIFY) #if defined(ENABLE_DATABASE) && defined(ENABLE_INOTIFY)
mpd_inotify_finish(); mpd_inotify_finish();
if (instance->update != nullptr)
instance->update->CancelAllAsync();
#endif #endif
if (state_file != nullptr) { if (state_file != nullptr) {
......
...@@ -50,6 +50,10 @@ public: ...@@ -50,6 +50,10 @@ public:
bool Push(const char *path, bool discard, unsigned id); bool Push(const char *path, bool discard, unsigned id);
UpdateQueueItem Pop(); UpdateQueueItem Pop();
void Clear() {
update_queue = decltype(update_queue)();
}
}; };
#endif #endif
...@@ -47,6 +47,23 @@ UpdateService::UpdateService(EventLoop &_loop, SimpleDatabase &_db, ...@@ -47,6 +47,23 @@ UpdateService::UpdateService(EventLoop &_loop, SimpleDatabase &_db,
{ {
} }
UpdateService::~UpdateService()
{
CancelAllAsync();
if (update_thread.IsDefined())
update_thread.Join();
}
void
UpdateService::CancelAllAsync()
{
assert(GetEventLoop().IsInsideOrNull());
queue.Clear();
walk.Cancel();
}
inline void inline void
UpdateService::Task() UpdateService::Task()
{ {
...@@ -94,6 +111,8 @@ UpdateService::StartThread(UpdateQueueItem &&i) ...@@ -94,6 +111,8 @@ UpdateService::StartThread(UpdateQueueItem &&i)
next = std::move(i); next = std::move(i);
walk.Prepare();
Error error; Error error;
if (!update_thread.Start(Task, this, error)) if (!update_thread.Start(Task, this, error))
FatalError(error); FatalError(error);
......
...@@ -64,6 +64,8 @@ public: ...@@ -64,6 +64,8 @@ public:
Storage &_storage, Storage &_storage,
DatabaseListener &_listener); DatabaseListener &_listener);
~UpdateService();
/** /**
* Returns a non-zero job id when we are currently updating * Returns a non-zero job id when we are currently updating
* the database. * the database.
...@@ -82,6 +84,12 @@ public: ...@@ -82,6 +84,12 @@ public:
gcc_nonnull_all gcc_nonnull_all
unsigned Enqueue(const char *path, bool discard); unsigned Enqueue(const char *path, bool discard);
/**
* Clear the queue and cancel the current update. Does not
* wait for the thread to exit.
*/
void CancelAllAsync();
private: private:
/* virtual methods from class DeferredMonitor */ /* virtual methods from class DeferredMonitor */
virtual void RunDeferred() override; virtual void RunDeferred() override;
......
...@@ -358,7 +358,7 @@ UpdateWalk::UpdateDirectory(Directory &directory, const FileInfo &info) ...@@ -358,7 +358,7 @@ UpdateWalk::UpdateDirectory(Directory &directory, const FileInfo &info)
PurgeDeletedFromDirectory(directory); PurgeDeletedFromDirectory(directory);
const char *name_utf8; const char *name_utf8;
while ((name_utf8 = reader->Read()) != nullptr) { while (!cancel && (name_utf8 = reader->Read()) != nullptr) {
if (skip_path(name_utf8)) if (skip_path(name_utf8))
continue; continue;
......
...@@ -48,6 +48,13 @@ class UpdateWalk final { ...@@ -48,6 +48,13 @@ class UpdateWalk final {
bool walk_discard; bool walk_discard;
bool modified; bool modified;
/**
* Set to true by the main thread when the update thread shall
* cancel as quickly as possible. Access to this flag is
* unprotected.
*/
volatile bool cancel;
Storage &storage; Storage &storage;
DatabaseEditor editor; DatabaseEditor editor;
...@@ -57,6 +64,22 @@ public: ...@@ -57,6 +64,22 @@ public:
Storage &_storage); Storage &_storage);
/** /**
* Cancel the current update and quit the Walk() method as
* soon as possible.
*/
void Cancel() {
cancel = true;
}
/**
* Call from the main thread before starting the update
* thread.
*/
void Prepare() {
cancel = false;
}
/**
* Returns true if the database was modified. * Returns true if the database was modified.
*/ */
bool Walk(Directory &root, const char *path, bool discard); bool Walk(Directory &root, const char *path, bool discard);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment