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-06-25 02:32:32 +02:00
parent 35eeebddc4
commit cd81fea02d
6 changed files with 107 additions and 49 deletions

View File

@ -9,6 +9,8 @@
#include <algorithm>
#include <new>
#include <NodeMonitor.h>
#include <AutoDeleter.h>
#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;
}

View File

@ -44,6 +44,9 @@ public:
private:
class SelfLink;
private:
status_t _Update(PackageLinksListener* listener);
private:
timespec fModifiedTime;
PackageList fPackages;

View File

@ -123,7 +123,7 @@ PackageLinksDirectory::AddPackage(Package* package)
if (fListener != NULL) {
NodeWriteLocker linkDirectoryWriteLocker(linkDirectory);
fListener->PackageLinkDirectoryAdded(linkDirectory);
fListener->PackageLinkNodeAdded(linkDirectory);
}
}

View File

@ -6,17 +6,20 @@
#define PACKAGE_LINKS_LISTENER_H
class PackageLinkDirectory;
#include <SupportDefs.h>
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;
};

View File

@ -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);
}

View File

@ -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;