From 3e7333b7c188f2193a1bc5109c101461f33197b9 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 24 Jun 2011 03:08:10 +0200 Subject: [PATCH] Add package link directories to system volume * Add PackageLinksListener interface. It is used by PackageLink[s]Directory to notify a listener about changes. * Volume does now implement PackageLinksListener and recursively adds/ removes package link directories. This makes the package link directories appear at least. They are still empty. --- .../kernel/file_systems/packagefs/Jamfile | 1 + .../packagefs/PackageLinkDirectory.cpp | 28 ++++++- .../packagefs/PackageLinkDirectory.h | 9 ++- .../packagefs/PackageLinksDirectory.cpp | 24 ++++-- .../packagefs/PackageLinksDirectory.h | 5 ++ .../packagefs/PackageLinksListener.cpp | 13 ++++ .../packagefs/PackageLinksListener.h | 23 ++++++ .../kernel/file_systems/packagefs/Volume.cpp | 75 +++++++++++++++++-- .../kernel/file_systems/packagefs/Volume.h | 15 +++- 9 files changed, 173 insertions(+), 20 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.cpp create mode 100644 src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 9431073366..d9a68ab980 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -25,6 +25,7 @@ HAIKU_PACKAGE_FS_SOURCES = PackageLeafNode.cpp PackageLinkDirectory.cpp PackageLinksDirectory.cpp + PackageLinksListener.cpp PackageNode.cpp PackageNodeAttribute.cpp PackageSymlink.cpp diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp index fa735f3196..eb9879ee72 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp @@ -10,6 +10,7 @@ #include "EmptyAttributeDirectoryCookie.h" #include "DebugSupport.h" +#include "PackageLinksListener.h" #include "Utils.h" #include "Version.h" @@ -60,7 +61,7 @@ PackageLinkDirectory::Init(Directory* parent, Package* package) RETURN_ERROR(error); // add the package - AddPackage(package); + AddPackage(package, NULL); return B_OK; } @@ -131,21 +132,40 @@ PackageLinkDirectory::OpenAttribute(const char* name, int openMode, void -PackageLinkDirectory::AddPackage(Package* package) +PackageLinkDirectory::AddPackage(Package* package, + PackageLinksListener* listener) { + NodeWriteLocker writeLocker(this); + + if (listener != NULL) + listener->PackageLinkDirectoryRemoved(this); + // TODO: Add in priority order! fPackages.Add(package); package->SetLinkDirectory(this); + + if (listener != NULL) + listener->PackageLinkDirectoryAdded(this); + // TODO: The notifications should only happen as necessary! } void -PackageLinkDirectory::RemovePackage(Package* package) +PackageLinkDirectory::RemovePackage(Package* package, + PackageLinksListener* listener) { - ASSERT(package->LinkDirectory() == this); + NodeWriteLocker writeLocker(this); + + if (listener != NULL) + listener->PackageLinkDirectoryRemoved(this); + 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! } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h index 6b8841f340..8fbaf8fa4c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h @@ -10,6 +10,9 @@ #include "Package.h" +class PackageLinksListener; + + class PackageLinkDirectory : public Directory { public: PackageLinkDirectory(); @@ -29,8 +32,10 @@ public: virtual status_t OpenAttribute(const char* name, int openMode, AttributeCookie*& _cookie); - void AddPackage(Package* package); - void RemovePackage(Package* package); + void AddPackage(Package* package, + PackageLinksListener* listener); + void RemovePackage(Package* package, + PackageLinksListener* listener); bool IsEmpty() const { return fPackages.IsEmpty(); } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp index c37182dec6..b787d1717d 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp @@ -11,12 +11,14 @@ #include "EmptyAttributeDirectoryCookie.h" #include "DebugSupport.h" #include "PackageLinkDirectory.h" +#include "PackageLinksListener.h" #include "Utils.h" PackageLinksDirectory::PackageLinksDirectory() : - Directory(0) + Directory(0), + fListener(NULL) // the ID needs to be assigned later, when added to a volume { get_real_time(fModifiedTime); @@ -111,18 +113,26 @@ PackageLinksDirectory::AddPackage(Package* package) // add the link directory NodeWriteLocker writeLocker(this); if (Node* child = FindChild(linkDirectory->Name())) { + // There already is an entry with the name. PackageLinkDirectory* otherLinkDirectory = dynamic_cast(child); if (otherLinkDirectory != NULL) RETURN_ERROR(B_BAD_VALUE); - linkDirectory->RemovePackage(package); + // There's already a package link directory. Delete the one we created + // and add the package to the pre-existing one. + linkDirectory->RemovePackage(package, NULL); linkDirectory = otherLinkDirectory; - linkDirectory->AddPackage(package); - } else + linkDirectory->AddPackage(package, fListener); + } else { + // No entry is in the way, so just add the link directory. AddChild(linkDirectory); -// TODO:... + if (fListener != NULL) { + NodeWriteLocker linkDirectoryWriteLocker(linkDirectory); + fListener->PackageLinkDirectoryAdded(linkDirectory); + } + } return B_OK; } @@ -140,12 +150,10 @@ PackageLinksDirectory::RemovePackage(Package* package) NodeWriteLocker writeLocker(this); - linkDirectory->RemovePackage(package); + linkDirectory->RemovePackage(package, fListener); // if empty, remove the link directory itself if (linkDirectory->IsEmpty()) RemoveChild(linkDirectory); - -// TODO:... } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h index c1659ee324..00cea75715 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h @@ -10,6 +10,7 @@ class Package; +class PackageLinksListener; class PackageLinksDirectory : public Directory { @@ -30,11 +31,15 @@ public: virtual status_t OpenAttribute(const char* name, int openMode, AttributeCookie*& _cookie); + void SetListener(PackageLinksListener* listener) + { fListener = listener; } + status_t AddPackage(Package* package); void RemovePackage(Package* package); private: timespec fModifiedTime; + PackageLinksListener* fListener; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.cpp new file mode 100644 index 0000000000..0849fc7968 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.cpp @@ -0,0 +1,13 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "PackageLinksListener.h" + + + +PackageLinksListener::~PackageLinksListener() +{ +} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h new file mode 100644 index 0000000000..e97bf752d1 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksListener.h @@ -0,0 +1,23 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef PACKAGE_LINKS_LISTENER_H +#define PACKAGE_LINKS_LISTENER_H + + +class PackageLinkDirectory; + + +class PackageLinksListener { +public: + virtual ~PackageLinksListener(); + + virtual void PackageLinkDirectoryAdded( + PackageLinkDirectory* directory) = 0; + virtual void PackageLinkDirectoryRemoved( + PackageLinkDirectory* directory) = 0; +}; + + +#endif // PACKAGE_LINKS_LISTENER_H diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 6d14b6f330..332d72eb28 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -35,6 +35,7 @@ #include "PackageDirectory.h" #include "PackageFile.h" #include "PackageFSRoot.h" +#include "PackageLinkDirectory.h" #include "PackageLinksDirectory.h" #include "PackageSymlink.h" #include "Resolvable.h" @@ -619,6 +620,20 @@ Volume::AddPackageDomain(const char* path) } +void +Volume::PackageLinkDirectoryAdded(PackageLinkDirectory* directory) +{ + _AddPackageLinksNode(directory); +} + + +void +Volume::PackageLinkDirectoryRemoved(PackageLinkDirectory* directory) +{ + _RemovePackageLinksNode(directory); +} + + /*static*/ status_t Volume::_PackageLoaderEntry(void* data) { @@ -734,6 +749,7 @@ Volume::_AddPackageDomain(PackageDomain* domain, bool notify) } // add the packages to the node tree + VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); VolumeWriteLocker volumeLocker(this); for (PackageFileNameHashTable::Iterator it = domain->Packages().GetIterator(); Package* package = it.Next();) { @@ -1216,6 +1232,7 @@ Volume::_DomainEntryCreated(PackageDomain* domain, dev_t deviceID, if (error != B_OK) return; + VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); VolumeWriteLocker volumeLocker(this); domain->AddPackage(package); @@ -1244,6 +1261,7 @@ Volume::_DomainEntryRemoved(PackageDomain* domain, dev_t deviceID, BReference packageReference(package); // remove the package + VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf()); VolumeWriteLocker volumeLocker(this); _RemovePackageContent(package, NULL, true); domain->RemovePackage(package); @@ -1388,12 +1406,12 @@ Volume::_AddPackageLinksDirectory() NodeWriteLocker rootDirectoryWriteLocker(fRootDirectory); NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory); - packageLinksDirectory->SetID(fNextNodeID++); packageLinksDirectory->SetParent(fRootDirectory); - fRootDirectory->AddChild(packageLinksDirectory); - fNodes.Insert(packageLinksDirectory); - packageLinksDirectory->AcquireReference(); + + _AddPackageLinksNode(packageLinksDirectory); + + packageLinksDirectory->SetListener(this); return B_OK; } @@ -1410,7 +1428,54 @@ Volume::_RemovePackageLinksDirectory() NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory); if (packageLinksDirectory->Parent() == fRootDirectory) { - _RemoveNode(packageLinksDirectory); + packageLinksDirectory->SetListener(NULL); + _RemovePackageLinksNode(packageLinksDirectory); packageLinksDirectory->SetParent(NULL); } } + + +void +Volume::_AddPackageLinksNode(Node* node) +{ + node->SetID(fNextNodeID++); + + fNodes.Insert(node); + node->AcquireReference(); + + // If this is a directory, recursively add descendants. The directory tree + // for the package links isn't deep, so we can do recursion. + if (Directory* directory = dynamic_cast(node)) { + for (Node* child = directory->FirstChild(); child != NULL; + child = directory->NextChild(child)) { + NodeWriteLocker childWriteLocker(child); + _AddPackageLinksNode(child); + } + } +} + + +void +Volume::_RemovePackageLinksNode(Node* node) +{ + // If this is a directory, recursively remove descendants. The directory + // tree for the package links isn't deep, so we can do recursion. + if (Directory* directory = dynamic_cast(node)) { + for (Node* child = directory->FirstChild(); child != NULL; + child = directory->NextChild(child)) { + NodeWriteLocker childWriteLocker(child); + _RemovePackageLinksNode(child); + } + } + + _RemoveNode(node); +} + + +inline Volume* +Volume::_SystemVolumeIfNotSelf() const +{ + if (Volume* systemVolume = fPackageFSRoot->SystemVolume()) + return systemVolume == this ? NULL : systemVolume; + return NULL; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index 7dc209f4af..f516f0fb44 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -16,6 +16,7 @@ #include "Node.h" #include "PackageDomain.h" +#include "PackageLinksListener.h" class Directory; @@ -32,7 +33,8 @@ enum MountType { }; -class Volume : public DoublyLinkedListLinkImpl { +class Volume : public DoublyLinkedListLinkImpl, + private PackageLinksListener { public: Volume(fs_volume* fsVolume); ~Volume(); @@ -72,6 +74,13 @@ public: status_t AddPackageDomain(const char* path); +private: + // PackageLinksListener + virtual void PackageLinkDirectoryAdded( + PackageLinkDirectory* directory); + virtual void PackageLinkDirectoryRemoved( + PackageLinkDirectory* directory); + private: struct Job; struct AddPackageDomainJob; @@ -147,6 +156,10 @@ private: status_t _AddPackageLinksDirectory(); void _RemovePackageLinksDirectory(); + void _AddPackageLinksNode(Node* node); + void _RemovePackageLinksNode(Node* node); + + inline Volume* _SystemVolumeIfNotSelf() const; private: mutable rw_lock fLock;