From 9e4096146fa5a20df2fc06301683853029851163 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 8 Apr 2013 15:19:11 +0200 Subject: [PATCH] package daemon: Add a Listener interface for Volume * This way, Volume doesn't have to know Root. * Suppress listener notifications for node monitoring events when there are were already events pending. --- src/servers/package/Root.cpp | 6 ++---- src/servers/package/Root.h | 12 +++++++----- src/servers/package/Volume.cpp | 29 +++++++++++++++++++++++++---- src/servers/package/Volume.h | 15 ++++++++++++++- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/servers/package/Root.cpp b/src/servers/package/Root.cpp index 6553f4bba7..f05dcc66cb 100644 --- a/src/servers/package/Root.cpp +++ b/src/servers/package/Root.cpp @@ -14,7 +14,6 @@ #include #include "DebugSupport.h" -#include "Volume.h" // #pragma mark - InitVolumePackagesJob @@ -29,7 +28,7 @@ struct Root::InitPackagesJob : public Job { virtual void Do() { - fVolume->InitPackages(); + fVolume->InitPackages(fVolume->GetRoot()); } private: @@ -210,9 +209,8 @@ Root::FindVolume(dev_t deviceID) const void -Root::HandleNodeMonitorEvents(Volume* volume) +Root::VolumeNodeMonitorEventOccurred(Volume* volume) { -// TODO: Don't push a new one, if one is already pending! _QueueJob(new(std::nothrow) HandleNodeMonitorEventsJob(volume)); } diff --git a/src/servers/package/Root.h b/src/servers/package/Root.h index 288f5088e9..2c7f328f08 100644 --- a/src/servers/package/Root.h +++ b/src/servers/package/Root.h @@ -19,12 +19,10 @@ #include #include "JobQueue.h" +#include "Volume.h" -class Volume; - - -class Root : public BReferenceable { +class Root : public BReferenceable, private Volume::Listener { public: Root(); virtual ~Root(); @@ -42,7 +40,9 @@ public: Volume* FindVolume(dev_t deviceID) const; - void HandleNodeMonitorEvents(Volume* volume); +private: + // Volume::Listener + virtual void VolumeNodeMonitorEventOccurred(Volume* volume); protected: virtual void LastReferenceReleased(); @@ -52,6 +52,8 @@ private: struct DeleteVolumeJob; struct HandleNodeMonitorEventsJob; + friend struct InitPackagesJob; + private: Volume** _GetVolume(PackageFSMountType mountType); diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index 8c330847fd..a1945c1e77 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -24,7 +24,14 @@ #include #include "DebugSupport.h" -#include "Root.h" + + +// #pragma mark - Listener + + +Volume::Listener::~Listener() +{ +} // #pragma mark - NodeMonitorEvent @@ -67,6 +74,7 @@ Volume::Volume(BLooper* looper) fRootDirectoryRef(), fPackagesDirectoryRef(), fRoot(NULL), + fListener(NULL), fPackagesByFileName(), fPackagesByNodeRef(), fPendingNodeMonitorEventsLock("pending node monitor events"), @@ -78,6 +86,9 @@ Volume::Volume(BLooper* looper) Volume::~Volume() { + Unmounted(); + // need for error case in InitPackages() + fPackagesByFileName.Clear(); Package* package = fPackagesByNodeRef.Clear(true); @@ -153,7 +164,7 @@ Volume::Init(const node_ref& rootDirectoryRef, node_ref& _packageRootRef) status_t -Volume::InitPackages() +Volume::InitPackages(Listener* listener) { // node-monitor the volume's packages directory status_t error = watch_node(&fPackagesDirectoryRef, B_WATCH_DIRECTORY, @@ -166,6 +177,8 @@ Volume::InitPackages() // packages directory won't work correctly. } + fListener = listener; + // read the packages directory and get the active packages int fd = OpenRootDirectory(); if (fd < 0) { @@ -190,7 +203,13 @@ Volume::InitPackages() void Volume::Unmounted() { - stop_watching(BMessenger(this)); + if (fListener != NULL) { + stop_watching(BMessenger(this)); + fListener = NULL; + } + + if (BLooper* looper = Looper()) + looper->RemoveHandler(this); } @@ -324,10 +343,12 @@ Volume::_QueueNodeMonitorEvent(const BString& name, bool wasCreated) } AutoLocker eventsLock(fPendingNodeMonitorEventsLock); + bool firstEvent = fPendingNodeMonitorEvents.IsEmpty(); fPendingNodeMonitorEvents.Add(event); eventsLock.Unlock(); - fRoot->HandleNodeMonitorEvents(this); + if (firstEvent && fListener != NULL) + fListener->VolumeNodeMonitorEventOccurred(this); } diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h index c791cae258..24eab04c6d 100644 --- a/src/servers/package/Volume.h +++ b/src/servers/package/Volume.h @@ -25,13 +25,16 @@ class Root; class Volume : public BHandler { +public: + class Listener; + public: Volume(BLooper* looper); virtual ~Volume(); status_t Init(const node_ref& rootDirectoryRef, node_ref& _packageRootRef); - status_t InitPackages(); + status_t InitPackages(Listener* listener); void Unmounted(); @@ -88,6 +91,7 @@ private: node_ref fRootDirectoryRef; node_ref fPackagesDirectoryRef; Root* fRoot; + Listener* fListener; PackageFileNameHashTable fPackagesByFileName; PackageNodeRefHashTable fPackagesByNodeRef; BLocker fPendingNodeMonitorEventsLock; @@ -95,4 +99,13 @@ private: }; +class Volume::Listener { +public: + virtual ~Listener(); + + virtual void VolumeNodeMonitorEventOccurred(Volume* volume) + = 0; +}; + + #endif // VOLUME_H