Fix package link updates/node monitoring

* PackageLinksListener: Rename methods from *Directory*() to *Node*()
  and change parameter to Node*. Also add a *Changed() method.
* PackageLinkDirectory: Update only when necessary and what is necessary
  (currently only the self link).
This commit is contained in:
Ingo Weinhold
2011-11-25 06:18:11 +01:00
parent 265b7e0dfc
commit d8ea0a8a31
6 changed files with 107 additions and 49 deletions
@@ -9,6 +9,8 @@
#include <algorithm> #include <algorithm>
#include <new> #include <new>
#include <NodeMonitor.h>
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include "EmptyAttributeDirectoryCookie.h" #include "EmptyAttributeDirectoryCookie.h"
@@ -49,18 +51,22 @@ class PackageLinkDirectory::SelfLink : public Node {
public: public:
SelfLink(Package* package) SelfLink(Package* package)
: :
Node(0), Node(0)
fPackage(package),
fLinkPath(link_path_for_mount_type(
package->Domain()->Volume()->MountType()))
{ {
get_real_time(fModifiedTime); Update(package);
} }
virtual ~SelfLink() virtual ~SelfLink()
{ {
} }
void Update(Package* package)
{
fLinkPath = link_path_for_mount_type(
package->Domain()->Volume()->MountType());
get_real_time(fModifiedTime);
}
virtual mode_t Mode() const virtual mode_t Mode() const
{ {
return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
@@ -124,7 +130,6 @@ public:
} }
private: private:
Package* fPackage;
timespec fModifiedTime; timespec fModifiedTime;
const char* fLinkPath; const char* fLinkPath;
}; };
@@ -153,17 +158,6 @@ PackageLinkDirectory::~PackageLinkDirectory()
status_t status_t
PackageLinkDirectory::Init(Directory* parent, Package* package) PackageLinkDirectory::Init(Directory* parent, Package* package)
{ {
// create the self link
fSelfLink = new(std::nothrow) SelfLink(package);
if (fSelfLink == NULL)
return B_NO_MEMORY;
status_t error = fSelfLink->Init(this, kSelfLinkName, NODE_FLAG_CONST_NAME);
if (error != B_OK)
RETURN_ERROR(error);
AddChild(fSelfLink);
// compute the allocation size needed for the versioned name // compute the allocation size needed for the versioned name
size_t nameLength = strlen(package->Name()); size_t nameLength = strlen(package->Name());
size_t size = nameLength + 1; size_t size = nameLength + 1;
@@ -186,7 +180,7 @@ PackageLinkDirectory::Init(Directory* parent, Package* package)
} }
// init the directory/node // init the directory/node
error = Init(parent, name, NODE_FLAG_KEEP_NAME); status_t error = Init(parent, name, NODE_FLAG_KEEP_NAME);
if (error != B_OK) if (error != B_OK)
RETURN_ERROR(error); RETURN_ERROR(error);
@@ -267,16 +261,21 @@ PackageLinkDirectory::AddPackage(Package* package,
{ {
NodeWriteLocker writeLocker(this); NodeWriteLocker writeLocker(this);
if (listener != NULL) // Find the insertion point in the list. We sort by mount type -- the more
listener->PackageLinkDirectoryRemoved(this); // specific the higher the priority.
MountType mountType = package->Domain()->Volume()->MountType();
Package* otherPackage = NULL;
for (PackageList::Iterator it = fPackages.GetIterator();
(otherPackage = it.Next()) != NULL;) {
if (otherPackage->Domain()->Volume()->MountType() <= mountType)
break;
}
// TODO: Add in priority order! fPackages.InsertBefore(otherPackage, package);
fPackages.Add(package);
package->SetLinkDirectory(this); package->SetLinkDirectory(this);
if (listener != NULL) if (package == fPackages.Head())
listener->PackageLinkDirectoryAdded(this); _Update(listener);
// TODO: The notifications should only happen as necessary!
} }
@@ -288,14 +287,62 @@ PackageLinkDirectory::RemovePackage(Package* package,
NodeWriteLocker writeLocker(this); NodeWriteLocker writeLocker(this);
if (listener != NULL) bool firstPackage = package == fPackages.Head();
listener->PackageLinkDirectoryRemoved(this);
package->SetLinkDirectory(NULL); package->SetLinkDirectory(NULL);
fPackages.Remove(package); fPackages.Remove(package);
// TODO: Check whether that was the top priority package!
if (listener != NULL && !IsEmpty()) if (firstPackage)
listener->PackageLinkDirectoryAdded(this); _Update(listener);
// TODO: The notifications should only happen as necessary! }
status_t
PackageLinkDirectory::_Update(PackageLinksListener* listener)
{
// check, if empty
Package* package = fPackages.Head();
if (package == NULL) {
// remove self link, if any
if (fSelfLink != NULL) {
NodeWriteLocker selfLinkLocker(fSelfLink);
if (listener != NULL)
listener->PackageLinkNodeRemoved(fSelfLink);
RemoveChild(fSelfLink);
fSelfLink->ReleaseReference();
fSelfLink = NULL;
}
return B_OK;
}
// create/update self link
if (fSelfLink == NULL) {
fSelfLink = new(std::nothrow) SelfLink(package);
if (fSelfLink == NULL)
return B_NO_MEMORY;
status_t error = fSelfLink->Init(this, kSelfLinkName,
NODE_FLAG_CONST_NAME);
if (error != B_OK)
RETURN_ERROR(error);
AddChild(fSelfLink);
if (listener != NULL) {
NodeWriteLocker selfLinkLocker(fSelfLink);
listener->PackageLinkNodeAdded(fSelfLink);
}
} else {
NodeWriteLocker selfLinkLocker(fSelfLink);
fSelfLink->Update(package);
if (listener != NULL) {
listener->PackageLinkNodeChanged(fSelfLink,
B_STAT_SIZE | B_STAT_MODIFICATION_TIME);
}
}
return B_OK;
} }
@@ -44,6 +44,9 @@ public:
private: private:
class SelfLink; class SelfLink;
private:
status_t _Update(PackageLinksListener* listener);
private: private:
timespec fModifiedTime; timespec fModifiedTime;
PackageList fPackages; PackageList fPackages;
@@ -123,7 +123,7 @@ PackageLinksDirectory::AddPackage(Package* package)
if (fListener != NULL) { if (fListener != NULL) {
NodeWriteLocker linkDirectoryWriteLocker(linkDirectory); NodeWriteLocker linkDirectoryWriteLocker(linkDirectory);
fListener->PackageLinkDirectoryAdded(linkDirectory); fListener->PackageLinkNodeAdded(linkDirectory);
} }
} }
@@ -6,17 +6,20 @@
#define PACKAGE_LINKS_LISTENER_H #define PACKAGE_LINKS_LISTENER_H
class PackageLinkDirectory; #include <SupportDefs.h>
class Node;
class PackageLinksListener { class PackageLinksListener {
public: public:
virtual ~PackageLinksListener(); virtual ~PackageLinksListener();
virtual void PackageLinkDirectoryAdded( virtual void PackageLinkNodeAdded(Node* node) = 0;
PackageLinkDirectory* directory) = 0; virtual void PackageLinkNodeRemoved(Node* node) = 0;
virtual void PackageLinkDirectoryRemoved( virtual void PackageLinkNodeChanged(Node* node,
PackageLinkDirectory* directory) = 0; uint32 statFields) = 0;
}; };
@@ -639,22 +639,27 @@ Volume::AddPackageDomain(const char* path)
void void
Volume::PackageLinkDirectoryAdded(PackageLinkDirectory* directory) Volume::PackageLinkNodeAdded(Node* node)
{ {
_AddPackageLinksNode(directory); _AddPackageLinksNode(node);
notify_entry_created(ID(), directory->Parent()->ID(), directory->Name(), notify_entry_created(ID(), node->Parent()->ID(), node->Name(), node->ID());
directory->ID());
} }
void void
Volume::PackageLinkDirectoryRemoved(PackageLinkDirectory* directory) Volume::PackageLinkNodeRemoved(Node* node)
{ {
_RemovePackageLinksNode(directory); _RemovePackageLinksNode(node);
notify_entry_removed(ID(), directory->Parent()->ID(), directory->Name(), notify_entry_removed(ID(), node->Parent()->ID(), node->Name(), node->ID());
directory->ID()); }
void
Volume::PackageLinkNodeChanged(Node* node, uint32 statFields)
{
notify_stat_changed(ID(), node->ID(), statFields);
} }
@@ -76,10 +76,10 @@ public:
private: private:
// PackageLinksListener // PackageLinksListener
virtual void PackageLinkDirectoryAdded( virtual void PackageLinkNodeAdded(Node* node);
PackageLinkDirectory* directory); virtual void PackageLinkNodeRemoved(Node* node);
virtual void PackageLinkDirectoryRemoved( virtual void PackageLinkNodeChanged(Node* node,
PackageLinkDirectory* directory); uint32 statFields);
private: private:
struct Job; struct Job;