From d8ea0a8a31ee4d741497bb8b2b08bd52577b06db Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 25 Jun 2011 02:32:32 +0200 Subject: [PATCH] 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). --- .../packagefs/PackageLinkDirectory.cpp | 109 +++++++++++++----- .../packagefs/PackageLinkDirectory.h | 3 + .../packagefs/PackageLinksDirectory.cpp | 2 +- .../packagefs/PackageLinksListener.h | 13 ++- .../kernel/file_systems/packagefs/Volume.cpp | 21 ++-- .../kernel/file_systems/packagefs/Volume.h | 8 +- 6 files changed, 107 insertions(+), 49 deletions(-) diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp index 4af01851e7..ee4ba52ef1 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp @@ -9,6 +9,8 @@ #include #include +#include + #include #include "EmptyAttributeDirectoryCookie.h" @@ -49,18 +51,22 @@ class PackageLinkDirectory::SelfLink : public Node { public: SelfLink(Package* package) : - Node(0), - fPackage(package), - fLinkPath(link_path_for_mount_type( - package->Domain()->Volume()->MountType())) + Node(0) { - get_real_time(fModifiedTime); + Update(package); } 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 { return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH @@ -124,7 +130,6 @@ public: } private: - Package* fPackage; timespec fModifiedTime; const char* fLinkPath; }; @@ -153,17 +158,6 @@ PackageLinkDirectory::~PackageLinkDirectory() status_t 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 size_t nameLength = strlen(package->Name()); size_t size = nameLength + 1; @@ -186,7 +180,7 @@ PackageLinkDirectory::Init(Directory* parent, Package* package) } // 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) RETURN_ERROR(error); @@ -267,16 +261,21 @@ PackageLinkDirectory::AddPackage(Package* package, { NodeWriteLocker writeLocker(this); - if (listener != NULL) - listener->PackageLinkDirectoryRemoved(this); + // Find the insertion point in the list. We sort by mount type -- the more + // 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.Add(package); + fPackages.InsertBefore(otherPackage, package); package->SetLinkDirectory(this); - if (listener != NULL) - listener->PackageLinkDirectoryAdded(this); - // TODO: The notifications should only happen as necessary! + if (package == fPackages.Head()) + _Update(listener); } @@ -288,14 +287,62 @@ PackageLinkDirectory::RemovePackage(Package* package, NodeWriteLocker writeLocker(this); - if (listener != NULL) - listener->PackageLinkDirectoryRemoved(this); + bool firstPackage = package == fPackages.Head(); package->SetLinkDirectory(NULL); fPackages.Remove(package); - // TODO: Check whether that was the top priority package! - if (listener != NULL && !IsEmpty()) - listener->PackageLinkDirectoryAdded(this); - // TODO: The notifications should only happen as necessary! + if (firstPackage) + _Update(listener); +} + + +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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h index b32c07a6e7..ee87220167 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h @@ -44,6 +44,9 @@ public: private: class SelfLink; +private: + status_t _Update(PackageLinksListener* listener); + private: timespec fModifiedTime; PackageList fPackages; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp index d7cd7f6d8b..848eb5af91 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp @@ -123,7 +123,7 @@ PackageLinksDirectory::AddPackage(Package* package) if (fListener != NULL) { NodeWriteLocker linkDirectoryWriteLocker(linkDirectory); - fListener->PackageLinkDirectoryAdded(linkDirectory); + fListener->PackageLinkNodeAdded(linkDirectory); } } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h index e97bf752d1..4d3e7644ed 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h @@ -6,17 +6,20 @@ #define PACKAGE_LINKS_LISTENER_H -class PackageLinkDirectory; +#include + + +class Node; class PackageLinksListener { public: virtual ~PackageLinksListener(); - virtual void PackageLinkDirectoryAdded( - PackageLinkDirectory* directory) = 0; - virtual void PackageLinkDirectoryRemoved( - PackageLinkDirectory* directory) = 0; + virtual void PackageLinkNodeAdded(Node* node) = 0; + virtual void PackageLinkNodeRemoved(Node* node) = 0; + virtual void PackageLinkNodeChanged(Node* node, + uint32 statFields) = 0; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 6ea71622bc..3ed87091ab 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -639,22 +639,27 @@ Volume::AddPackageDomain(const char* path) void -Volume::PackageLinkDirectoryAdded(PackageLinkDirectory* directory) +Volume::PackageLinkNodeAdded(Node* node) { - _AddPackageLinksNode(directory); + _AddPackageLinksNode(node); - notify_entry_created(ID(), directory->Parent()->ID(), directory->Name(), - directory->ID()); + notify_entry_created(ID(), node->Parent()->ID(), node->Name(), node->ID()); } void -Volume::PackageLinkDirectoryRemoved(PackageLinkDirectory* directory) +Volume::PackageLinkNodeRemoved(Node* node) { - _RemovePackageLinksNode(directory); + _RemovePackageLinksNode(node); - notify_entry_removed(ID(), directory->Parent()->ID(), directory->Name(), - directory->ID()); + notify_entry_removed(ID(), node->Parent()->ID(), node->Name(), node->ID()); +} + + +void +Volume::PackageLinkNodeChanged(Node* node, uint32 statFields) +{ + notify_stat_changed(ID(), node->ID(), statFields); } diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index 311a2c1f08..c293aab9ed 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -76,10 +76,10 @@ public: private: // PackageLinksListener - virtual void PackageLinkDirectoryAdded( - PackageLinkDirectory* directory); - virtual void PackageLinkDirectoryRemoved( - PackageLinkDirectory* directory); + virtual void PackageLinkNodeAdded(Node* node); + virtual void PackageLinkNodeRemoved(Node* node); + virtual void PackageLinkNodeChanged(Node* node, + uint32 statFields); private: struct Job;