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.
This commit is contained in:
Ingo Weinhold
2013-04-08 15:19:11 +02:00
parent 8fb3930a42
commit 9e4096146f
4 changed files with 48 additions and 14 deletions
+2 -4
View File
@@ -14,7 +14,6 @@
#include <Path.h> #include <Path.h>
#include "DebugSupport.h" #include "DebugSupport.h"
#include "Volume.h"
// #pragma mark - InitVolumePackagesJob // #pragma mark - InitVolumePackagesJob
@@ -29,7 +28,7 @@ struct Root::InitPackagesJob : public Job {
virtual void Do() virtual void Do()
{ {
fVolume->InitPackages(); fVolume->InitPackages(fVolume->GetRoot());
} }
private: private:
@@ -210,9 +209,8 @@ Root::FindVolume(dev_t deviceID) const
void 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)); _QueueJob(new(std::nothrow) HandleNodeMonitorEventsJob(volume));
} }
+7 -5
View File
@@ -19,12 +19,10 @@
#include <packagefs.h> #include <packagefs.h>
#include "JobQueue.h" #include "JobQueue.h"
#include "Volume.h"
class Volume; class Root : public BReferenceable, private Volume::Listener {
class Root : public BReferenceable {
public: public:
Root(); Root();
virtual ~Root(); virtual ~Root();
@@ -42,7 +40,9 @@ public:
Volume* FindVolume(dev_t deviceID) const; Volume* FindVolume(dev_t deviceID) const;
void HandleNodeMonitorEvents(Volume* volume); private:
// Volume::Listener
virtual void VolumeNodeMonitorEventOccurred(Volume* volume);
protected: protected:
virtual void LastReferenceReleased(); virtual void LastReferenceReleased();
@@ -52,6 +52,8 @@ private:
struct DeleteVolumeJob; struct DeleteVolumeJob;
struct HandleNodeMonitorEventsJob; struct HandleNodeMonitorEventsJob;
friend struct InitPackagesJob;
private: private:
Volume** _GetVolume(PackageFSMountType mountType); Volume** _GetVolume(PackageFSMountType mountType);
+25 -4
View File
@@ -24,7 +24,14 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include "DebugSupport.h" #include "DebugSupport.h"
#include "Root.h"
// #pragma mark - Listener
Volume::Listener::~Listener()
{
}
// #pragma mark - NodeMonitorEvent // #pragma mark - NodeMonitorEvent
@@ -67,6 +74,7 @@ Volume::Volume(BLooper* looper)
fRootDirectoryRef(), fRootDirectoryRef(),
fPackagesDirectoryRef(), fPackagesDirectoryRef(),
fRoot(NULL), fRoot(NULL),
fListener(NULL),
fPackagesByFileName(), fPackagesByFileName(),
fPackagesByNodeRef(), fPackagesByNodeRef(),
fPendingNodeMonitorEventsLock("pending node monitor events"), fPendingNodeMonitorEventsLock("pending node monitor events"),
@@ -78,6 +86,9 @@ Volume::Volume(BLooper* looper)
Volume::~Volume() Volume::~Volume()
{ {
Unmounted();
// need for error case in InitPackages()
fPackagesByFileName.Clear(); fPackagesByFileName.Clear();
Package* package = fPackagesByNodeRef.Clear(true); Package* package = fPackagesByNodeRef.Clear(true);
@@ -153,7 +164,7 @@ Volume::Init(const node_ref& rootDirectoryRef, node_ref& _packageRootRef)
status_t status_t
Volume::InitPackages() Volume::InitPackages(Listener* listener)
{ {
// node-monitor the volume's packages directory // node-monitor the volume's packages directory
status_t error = watch_node(&fPackagesDirectoryRef, B_WATCH_DIRECTORY, status_t error = watch_node(&fPackagesDirectoryRef, B_WATCH_DIRECTORY,
@@ -166,6 +177,8 @@ Volume::InitPackages()
// packages directory won't work correctly. // packages directory won't work correctly.
} }
fListener = listener;
// read the packages directory and get the active packages // read the packages directory and get the active packages
int fd = OpenRootDirectory(); int fd = OpenRootDirectory();
if (fd < 0) { if (fd < 0) {
@@ -190,7 +203,13 @@ Volume::InitPackages()
void void
Volume::Unmounted() 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<BLocker> eventsLock(fPendingNodeMonitorEventsLock); AutoLocker<BLocker> eventsLock(fPendingNodeMonitorEventsLock);
bool firstEvent = fPendingNodeMonitorEvents.IsEmpty();
fPendingNodeMonitorEvents.Add(event); fPendingNodeMonitorEvents.Add(event);
eventsLock.Unlock(); eventsLock.Unlock();
fRoot->HandleNodeMonitorEvents(this); if (firstEvent && fListener != NULL)
fListener->VolumeNodeMonitorEventOccurred(this);
} }
+14 -1
View File
@@ -25,13 +25,16 @@ class Root;
class Volume : public BHandler { class Volume : public BHandler {
public:
class Listener;
public: public:
Volume(BLooper* looper); Volume(BLooper* looper);
virtual ~Volume(); virtual ~Volume();
status_t Init(const node_ref& rootDirectoryRef, status_t Init(const node_ref& rootDirectoryRef,
node_ref& _packageRootRef); node_ref& _packageRootRef);
status_t InitPackages(); status_t InitPackages(Listener* listener);
void Unmounted(); void Unmounted();
@@ -88,6 +91,7 @@ private:
node_ref fRootDirectoryRef; node_ref fRootDirectoryRef;
node_ref fPackagesDirectoryRef; node_ref fPackagesDirectoryRef;
Root* fRoot; Root* fRoot;
Listener* fListener;
PackageFileNameHashTable fPackagesByFileName; PackageFileNameHashTable fPackagesByFileName;
PackageNodeRefHashTable fPackagesByNodeRef; PackageNodeRefHashTable fPackagesByNodeRef;
BLocker fPendingNodeMonitorEventsLock; BLocker fPendingNodeMonitorEventsLock;
@@ -95,4 +99,13 @@ private:
}; };
class Volume::Listener {
public:
virtual ~Listener();
virtual void VolumeNodeMonitorEventOccurred(Volume* volume)
= 0;
};
#endif // VOLUME_H #endif // VOLUME_H