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
PackageLinkDirectory.cpp
PackageLinksDirectory.cpp
PackageLinksListener.cpp
PackageNode.cpp
PackageNodeAttribute.cpp
PackageSymlink.cpp

View File

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

View File

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

View File

@ -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<PackageLinkDirectory*>(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:...
}

View File

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

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 "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<Package> 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<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 "PackageDomain.h"
#include "PackageLinksListener.h"
class Directory;
@ -32,7 +33,8 @@ enum MountType {
};
class Volume : public DoublyLinkedListLinkImpl<Volume> {
class Volume : public DoublyLinkedListLinkImpl<Volume>,
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;