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.
This commit is contained in:
Ingo Weinhold 2011-06-24 03:08:10 +02:00
parent 4031a32acc
commit 3e7333b7c1
9 changed files with 173 additions and 20 deletions

View File

@ -25,6 +25,7 @@ HAIKU_PACKAGE_FS_SOURCES =
PackageLeafNode.cpp PackageLeafNode.cpp
PackageLinkDirectory.cpp PackageLinkDirectory.cpp
PackageLinksDirectory.cpp PackageLinksDirectory.cpp
PackageLinksListener.cpp
PackageNode.cpp PackageNode.cpp
PackageNodeAttribute.cpp PackageNodeAttribute.cpp
PackageSymlink.cpp PackageSymlink.cpp

View File

@ -10,6 +10,7 @@
#include "EmptyAttributeDirectoryCookie.h" #include "EmptyAttributeDirectoryCookie.h"
#include "DebugSupport.h" #include "DebugSupport.h"
#include "PackageLinksListener.h"
#include "Utils.h" #include "Utils.h"
#include "Version.h" #include "Version.h"
@ -60,7 +61,7 @@ PackageLinkDirectory::Init(Directory* parent, Package* package)
RETURN_ERROR(error); RETURN_ERROR(error);
// add the package // add the package
AddPackage(package); AddPackage(package, NULL);
return B_OK; return B_OK;
} }
@ -131,21 +132,40 @@ PackageLinkDirectory::OpenAttribute(const char* name, int openMode,
void 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! // TODO: Add in priority order!
fPackages.Add(package); fPackages.Add(package);
package->SetLinkDirectory(this); package->SetLinkDirectory(this);
if (listener != NULL)
listener->PackageLinkDirectoryAdded(this);
// TODO: The notifications should only happen as necessary!
} }
void void
PackageLinkDirectory::RemovePackage(Package* package) PackageLinkDirectory::RemovePackage(Package* package,
PackageLinksListener* listener)
{ {
ASSERT(package->LinkDirectory() == this); ASSERT(package->LinkDirectory() == this);
NodeWriteLocker writeLocker(this);
if (listener != NULL)
listener->PackageLinkDirectoryRemoved(this);
package->SetLinkDirectory(NULL); package->SetLinkDirectory(NULL);
fPackages.Remove(package); fPackages.Remove(package);
// TODO: Check whether that was the top priority 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!
} }

View File

@ -10,6 +10,9 @@
#include "Package.h" #include "Package.h"
class PackageLinksListener;
class PackageLinkDirectory : public Directory { class PackageLinkDirectory : public Directory {
public: public:
PackageLinkDirectory(); PackageLinkDirectory();
@ -29,8 +32,10 @@ public:
virtual status_t OpenAttribute(const char* name, int openMode, virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie); AttributeCookie*& _cookie);
void AddPackage(Package* package); void AddPackage(Package* package,
void RemovePackage(Package* package); PackageLinksListener* listener);
void RemovePackage(Package* package,
PackageLinksListener* listener);
bool IsEmpty() const bool IsEmpty() const
{ return fPackages.IsEmpty(); } { return fPackages.IsEmpty(); }

View File

@ -11,12 +11,14 @@
#include "EmptyAttributeDirectoryCookie.h" #include "EmptyAttributeDirectoryCookie.h"
#include "DebugSupport.h" #include "DebugSupport.h"
#include "PackageLinkDirectory.h" #include "PackageLinkDirectory.h"
#include "PackageLinksListener.h"
#include "Utils.h" #include "Utils.h"
PackageLinksDirectory::PackageLinksDirectory() PackageLinksDirectory::PackageLinksDirectory()
: :
Directory(0) Directory(0),
fListener(NULL)
// the ID needs to be assigned later, when added to a volume // the ID needs to be assigned later, when added to a volume
{ {
get_real_time(fModifiedTime); get_real_time(fModifiedTime);
@ -111,18 +113,26 @@ PackageLinksDirectory::AddPackage(Package* package)
// add the link directory // add the link directory
NodeWriteLocker writeLocker(this); NodeWriteLocker writeLocker(this);
if (Node* child = FindChild(linkDirectory->Name())) { if (Node* child = FindChild(linkDirectory->Name())) {
// There already is an entry with the name.
PackageLinkDirectory* otherLinkDirectory PackageLinkDirectory* otherLinkDirectory
= dynamic_cast<PackageLinkDirectory*>(child); = dynamic_cast<PackageLinkDirectory*>(child);
if (otherLinkDirectory != NULL) if (otherLinkDirectory != NULL)
RETURN_ERROR(B_BAD_VALUE); 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 = otherLinkDirectory;
linkDirectory->AddPackage(package); linkDirectory->AddPackage(package, fListener);
} else } else {
// No entry is in the way, so just add the link directory.
AddChild(linkDirectory); AddChild(linkDirectory);
// TODO:... if (fListener != NULL) {
NodeWriteLocker linkDirectoryWriteLocker(linkDirectory);
fListener->PackageLinkDirectoryAdded(linkDirectory);
}
}
return B_OK; return B_OK;
} }
@ -140,12 +150,10 @@ PackageLinksDirectory::RemovePackage(Package* package)
NodeWriteLocker writeLocker(this); NodeWriteLocker writeLocker(this);
linkDirectory->RemovePackage(package); linkDirectory->RemovePackage(package, fListener);
// if empty, remove the link directory itself // if empty, remove the link directory itself
if (linkDirectory->IsEmpty()) if (linkDirectory->IsEmpty())
RemoveChild(linkDirectory); RemoveChild(linkDirectory);
// TODO:...
} }

View File

@ -10,6 +10,7 @@
class Package; class Package;
class PackageLinksListener;
class PackageLinksDirectory : public Directory { class PackageLinksDirectory : public Directory {
@ -30,11 +31,15 @@ public:
virtual status_t OpenAttribute(const char* name, int openMode, virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie); AttributeCookie*& _cookie);
void SetListener(PackageLinksListener* listener)
{ fListener = listener; }
status_t AddPackage(Package* package); status_t AddPackage(Package* package);
void RemovePackage(Package* package); void RemovePackage(Package* package);
private: private:
timespec fModifiedTime; timespec fModifiedTime;
PackageLinksListener* fListener;
}; };

View File

@ -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()
{
}

View File

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

View File

@ -35,6 +35,7 @@
#include "PackageDirectory.h" #include "PackageDirectory.h"
#include "PackageFile.h" #include "PackageFile.h"
#include "PackageFSRoot.h" #include "PackageFSRoot.h"
#include "PackageLinkDirectory.h"
#include "PackageLinksDirectory.h" #include "PackageLinksDirectory.h"
#include "PackageSymlink.h" #include "PackageSymlink.h"
#include "Resolvable.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 /*static*/ status_t
Volume::_PackageLoaderEntry(void* data) Volume::_PackageLoaderEntry(void* data)
{ {
@ -734,6 +749,7 @@ Volume::_AddPackageDomain(PackageDomain* domain, bool notify)
} }
// add the packages to the node tree // add the packages to the node tree
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this); VolumeWriteLocker volumeLocker(this);
for (PackageFileNameHashTable::Iterator it for (PackageFileNameHashTable::Iterator it
= domain->Packages().GetIterator(); Package* package = it.Next();) { = domain->Packages().GetIterator(); Package* package = it.Next();) {
@ -1216,6 +1232,7 @@ Volume::_DomainEntryCreated(PackageDomain* domain, dev_t deviceID,
if (error != B_OK) if (error != B_OK)
return; return;
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this); VolumeWriteLocker volumeLocker(this);
domain->AddPackage(package); domain->AddPackage(package);
@ -1244,6 +1261,7 @@ Volume::_DomainEntryRemoved(PackageDomain* domain, dev_t deviceID,
BReference<Package> packageReference(package); BReference<Package> packageReference(package);
// remove the package // remove the package
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this); VolumeWriteLocker volumeLocker(this);
_RemovePackageContent(package, NULL, true); _RemovePackageContent(package, NULL, true);
domain->RemovePackage(package); domain->RemovePackage(package);
@ -1388,12 +1406,12 @@ Volume::_AddPackageLinksDirectory()
NodeWriteLocker rootDirectoryWriteLocker(fRootDirectory); NodeWriteLocker rootDirectoryWriteLocker(fRootDirectory);
NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory); NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory);
packageLinksDirectory->SetID(fNextNodeID++);
packageLinksDirectory->SetParent(fRootDirectory); packageLinksDirectory->SetParent(fRootDirectory);
fRootDirectory->AddChild(packageLinksDirectory); fRootDirectory->AddChild(packageLinksDirectory);
fNodes.Insert(packageLinksDirectory);
packageLinksDirectory->AcquireReference(); _AddPackageLinksNode(packageLinksDirectory);
packageLinksDirectory->SetListener(this);
return B_OK; return B_OK;
} }
@ -1410,7 +1428,54 @@ Volume::_RemovePackageLinksDirectory()
NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory); NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory);
if (packageLinksDirectory->Parent() == fRootDirectory) { if (packageLinksDirectory->Parent() == fRootDirectory) {
_RemoveNode(packageLinksDirectory); packageLinksDirectory->SetListener(NULL);
_RemovePackageLinksNode(packageLinksDirectory);
packageLinksDirectory->SetParent(NULL); 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<Directory*>(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<Directory*>(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;
}

View File

@ -16,6 +16,7 @@
#include "Node.h" #include "Node.h"
#include "PackageDomain.h" #include "PackageDomain.h"
#include "PackageLinksListener.h"
class Directory; class Directory;
@ -32,7 +33,8 @@ enum MountType {
}; };
class Volume : public DoublyLinkedListLinkImpl<Volume> { class Volume : public DoublyLinkedListLinkImpl<Volume>,
private PackageLinksListener {
public: public:
Volume(fs_volume* fsVolume); Volume(fs_volume* fsVolume);
~Volume(); ~Volume();
@ -72,6 +74,13 @@ public:
status_t AddPackageDomain(const char* path); status_t AddPackageDomain(const char* path);
private:
// PackageLinksListener
virtual void PackageLinkDirectoryAdded(
PackageLinkDirectory* directory);
virtual void PackageLinkDirectoryRemoved(
PackageLinkDirectory* directory);
private: private:
struct Job; struct Job;
struct AddPackageDomainJob; struct AddPackageDomainJob;
@ -147,6 +156,10 @@ private:
status_t _AddPackageLinksDirectory(); status_t _AddPackageLinksDirectory();
void _RemovePackageLinksDirectory(); void _RemovePackageLinksDirectory();
void _AddPackageLinksNode(Node* node);
void _RemovePackageLinksNode(Node* node);
inline Volume* _SystemVolumeIfNotSelf() const;
private: private:
mutable rw_lock fLock; mutable rw_lock fLock;