packagefs: Remove support for multiple package domains per volume

That also get rid of the job stuff and the package loader thread.
This commit is contained in:
Ingo Weinhold 2013-04-07 12:57:15 +02:00
parent af5c10ab19
commit 6978941aac
10 changed files with 203 additions and 439 deletions

View File

@ -28,7 +28,6 @@ HAIKU_PACKAGE_FS_SOURCES =
Query.cpp
Package.cpp
PackageDirectory.cpp
PackageDomain.cpp
PackageFile.cpp
PackageFSRoot.cpp
PackageLeafNode.cpp

View File

@ -21,10 +21,10 @@
#include "DebugSupport.h"
#include "PackageDirectory.h"
#include "PackageDomain.h"
#include "PackageFile.h"
#include "PackageSymlink.h"
#include "Version.h"
#include "Volume.h"
using namespace BPackageKit;
@ -300,9 +300,9 @@ private:
// #pragma mark - Package
Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
Package::Package(::Volume* volume, dev_t deviceID, ino_t nodeID)
:
fDomain(domain),
fVolume(volume),
fFileName(NULL),
fName(NULL),
fInstallPath(NULL),
@ -461,7 +461,7 @@ Package::Open()
}
// open the file
fFD = openat(fDomain->DirectoryFD(), fFileName, O_RDONLY);
fFD = openat(fVolume->PackagesDirectoryFD(), fFileName, O_RDONLY);
if (fFD < 0) {
ERROR("Failed to open package file \"%s\"\n", fFileName);
return errno;

View File

@ -24,22 +24,22 @@
using BPackageKit::BPackageArchitecture;
class PackageDomain;
class PackageLinkDirectory;
class Volume;
class Version;
class Package : public BReferenceable,
public DoublyLinkedListLinkImpl<Package> {
public:
Package(PackageDomain* domain, dev_t deviceID,
Package(::Volume* volume, dev_t deviceID,
ino_t nodeID);
~Package();
status_t Init(const char* fileName);
status_t Load();
PackageDomain* Domain() const { return fDomain; }
::Volume* Volume() const { return fVolume; }
const char* FileName() const { return fFileName; }
status_t SetName(const char* name);
@ -93,7 +93,7 @@ private:
private:
mutex fLock;
PackageDomain* fDomain;
::Volume* fVolume;
char* fFileName;
char* fName;
char* fInstallPath;

View File

@ -1,143 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PackageDomain.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <NodeMonitor.h>
#include <AutoDeleter.h>
#include <fs/KPath.h>
#include <team.h>
#include <vfs.h>
#include "DebugSupport.h"
#include "Volume.h"
PackageDomain::PackageDomain(::Volume* volume)
:
fVolume(volume),
fPath(NULL),
fDirFD(-1)
{
}
PackageDomain::~PackageDomain()
{
PRINT("PackageDomain::~PackageDomain()\n");
Package* package = fPackages.Clear(true);
while (package != NULL) {
Package* next = package->FileNameHashTableNext();
package->ReleaseReference();
package = next;
}
if (fDirFD >= 0)
close(fDirFD);
free(fPath);
}
status_t
PackageDomain::Init(const char* path, struct stat* _st)
{
// Open the directory. We want the path be interpreted depending on from
// where it came (kernel or userland), but we always want a FD in the kernel
// I/O context. There's no VFS service method to do that for us, so we need
// to do that ourselves.
bool calledFromKernel
= team_get_current_team_id() == team_get_kernel_team_id();
// Not entirely correct, but good enough for now. The only alternative
// is to have that information passed in as well.
struct vnode* vnode;
status_t error;
if (path != NULL) {
error = vfs_get_vnode_from_path(path, calledFromKernel, &vnode);
} else {
// No path given -- use the "packages" directory at our mount point.
error = vfs_entry_ref_to_vnode(fVolume->MountPointDeviceID(),
fVolume->MountPointNodeID(), "packages", &vnode);
}
if (error != B_OK) {
ERROR("Failed to open package domain \"%s\"\n", strerror(error));
RETURN_ERROR(error);
}
fDirFD = vfs_open_vnode(vnode, O_RDONLY, true);
if (fDirFD < 0) {
ERROR("Failed to open package domain \"%s\"\n", strerror(fDirFD));
vfs_put_vnode(vnode);
RETURN_ERROR(fDirFD);
}
// Our vnode reference has been transferred to the FD.
// Is it a directory at all?
struct stat st;
if (fstat(fDirFD, &st) < 0)
RETURN_ERROR(errno);
fDeviceID = st.st_dev;
fNodeID = st.st_ino;
// get a normalized path
KPath normalizedPath;
if (normalizedPath.InitCheck() != B_OK)
RETURN_ERROR(normalizedPath.InitCheck());
char* normalizedPathBuffer = normalizedPath.LockBuffer();
error = vfs_entry_ref_to_path(fDeviceID, fNodeID, NULL,
normalizedPathBuffer, normalizedPath.BufferSize());
if (error != B_OK)
RETURN_ERROR(error);
fPath = strdup(normalizedPathBuffer);
if (fPath == NULL)
RETURN_ERROR(B_NO_MEMORY);
// init packages hash table
error = fPackages.Init();
if (error != B_OK)
return error;
if (_st != NULL)
*_st = st;
return B_OK;
}
void
PackageDomain::AddPackage(Package* package)
{
fPackages.Insert(package);
package->AcquireReference();
}
void
PackageDomain::RemovePackage(Package* package)
{
fPackages.Remove(package);
package->ReleaseReference();
}
Package*
PackageDomain::FindPackage(const char* fileName) const
{
return fPackages.Lookup(fileName);
}

View File

@ -1,53 +0,0 @@
/*
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_DOMAIN_H
#define PACKAGE_DOMAIN_H
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include "Package.h"
struct stat;
class Volume;
class PackageDomain : public BReferenceable,
public DoublyLinkedListLinkImpl<PackageDomain> {
public:
PackageDomain(::Volume* volume);
~PackageDomain();
::Volume* Volume() const { return fVolume; }
const char* Path() const { return fPath; }
int DirectoryFD() { return fDirFD; }
dev_t DeviceID() { return fDeviceID; }
ino_t NodeID() { return fNodeID; }
status_t Init(const char* path, struct stat* _st);
void AddPackage(Package* package);
void RemovePackage(Package* package);
Package* FindPackage(const char* fileName) const;
const PackageFileNameHashTable& Packages() const
{ return fPackages; }
private:
::Volume* fVolume;
char* fPath;
int fDirFD;
dev_t fDeviceID;
ino_t fNodeID;
PackageFileNameHashTable fPackages;
};
#endif // PACKAGE_DOMAIN_H

View File

@ -99,11 +99,11 @@ PackageLinkDirectory::AddPackage(Package* package,
// 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();
MountType mountType = package->Volume()->MountType();
Package* otherPackage = NULL;
for (PackageList::Iterator it = fPackages.GetIterator();
(otherPackage = it.Next()) != NULL;) {
if (otherPackage->Domain()->Volume()->MountType() <= mountType)
if (otherPackage->Volume()->MountType() <= mountType)
break;
}

View File

@ -94,7 +94,7 @@ PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener)
fLinkPath = package->InstallPath();
if (fLinkPath == NULL) {
fLinkPath = link_path_for_mount_type(
package->Domain()->Volume()->MountType());
package->Volume()->MountType());
}
} else
fLinkPath = kUnknownLinkTarget;

View File

@ -17,11 +17,11 @@ ResolvableFamily::AddResolvable(Resolvable* resolvable,
// Find the insertion point in the list. We sort by mount type -- the more
// specific the higher the priority.
MountType mountType
= resolvable->Package()->Domain()->Volume()->MountType();
= resolvable->Package()->Volume()->MountType();
Resolvable* otherResolvable = NULL;
for (FamilyResolvableList::Iterator it = fResolvables.GetIterator();
(otherResolvable = it.Next()) != NULL;) {
if (otherResolvable->Package()->Domain()->Volume()->MountType()
if (otherResolvable->Package()->Volume()->MountType()
<= mountType) {
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@ -23,6 +23,8 @@
#include <AutoDeleter.h>
#include <fs/KPath.h>
#include <team.h>
#include <vfs.h>
#include "AttributeIndex.h"
@ -63,51 +65,112 @@ const char* const* kHomeShineThroughDirectories
const size_t kMaxActivationRequestSize = 10 * 1024 * 1024;
// #pragma mark - Job
// #pragma mark - ShineThroughDirectory
struct Volume::Job : DoublyLinkedListLinkImpl<Job> {
Job(Volume* volume)
struct Volume::PackagesDirectory {
PackagesDirectory()
:
fVolume(volume)
fPath(NULL),
fDirFD(-1)
{
}
virtual ~Job()
~PackagesDirectory()
{
if (fDirFD >= 0)
close(fDirFD);
free(fPath);
}
virtual void Do() = 0;
protected:
Volume* fVolume;
};
// #pragma mark - AddPackageDomainJob
struct Volume::AddPackageDomainJob : Job {
AddPackageDomainJob(Volume* volume, PackageDomain* domain)
:
Job(volume),
fDomain(domain)
const char* Path() const
{
fDomain->AcquireReference();
return fPath;
}
virtual ~AddPackageDomainJob()
int DirectoryFD() const
{
fDomain->ReleaseReference();
return fDirFD;
}
virtual void Do()
dev_t DeviceID() const
{
fVolume->_AddPackageDomain(fDomain, true);
return fDeviceID;
}
ino_t NodeID() const
{
return fNodeID;
}
status_t Init(const char* path, dev_t mountPointDeviceID,
ino_t mountPointNodeID, struct stat& _st)
{
// Open the directory. We want the path be interpreted depending on from
// where it came (kernel or userland), but we always want a FD in the
// kernel I/O context. There's no VFS service method to do that for us,
// so we need to do that ourselves.
bool calledFromKernel
= team_get_current_team_id() == team_get_kernel_team_id();
// Not entirely correct, but good enough for now. The only
// alternative is to have that information passed in as well.
struct vnode* vnode;
status_t error;
if (path != NULL) {
error = vfs_get_vnode_from_path(path, calledFromKernel, &vnode);
} else {
// No path given -- use the "packages" directory at our mount point.
error = vfs_entry_ref_to_vnode(mountPointDeviceID, mountPointNodeID,
"packages", &vnode);
}
if (error != B_OK) {
ERROR("Failed to open package domain \"%s\"\n", strerror(error));
RETURN_ERROR(error);
}
fDirFD = vfs_open_vnode(vnode, O_RDONLY, true);
if (fDirFD < 0) {
ERROR("Failed to open package domain \"%s\"\n", strerror(fDirFD));
vfs_put_vnode(vnode);
RETURN_ERROR(fDirFD);
}
// Our vnode reference has been transferred to the FD.
// Is it a directory at all?
struct stat& st = _st;
if (fstat(fDirFD, &st) < 0)
RETURN_ERROR(errno);
fDeviceID = st.st_dev;
fNodeID = st.st_ino;
// get a normalized path
KPath normalizedPath;
if (normalizedPath.InitCheck() != B_OK)
RETURN_ERROR(normalizedPath.InitCheck());
char* normalizedPathBuffer = normalizedPath.LockBuffer();
error = vfs_entry_ref_to_path(fDeviceID, fNodeID, NULL,
normalizedPathBuffer, normalizedPath.BufferSize());
if (error != B_OK)
RETURN_ERROR(error);
fPath = strdup(normalizedPathBuffer);
if (fPath == NULL)
RETURN_ERROR(B_NO_MEMORY);
return B_OK;
}
private:
PackageDomain* fDomain;
char* fPath;
int fDirFD;
dev_t fDeviceID;
ino_t fNodeID;
};
@ -264,22 +327,32 @@ Volume::Volume(fs_volume* fsVolume)
fFSVolume(fsVolume),
fRootDirectory(NULL),
fPackageFSRoot(NULL),
fPackageLoader(-1),
fNextNodeID(kRootDirectoryID + 1),
fTerminating(false)
fPackagesDirectory(NULL),
fNextNodeID(kRootDirectoryID + 1)
{
rw_lock_init(&fLock, "packagefs volume");
mutex_init(&fJobQueueLock, "packagefs volume job queue");
fJobQueueCondition.Init(this, "packagefs volume job queue");
}
Volume::~Volume()
{
_TerminatePackageLoader();
// remove the packages from the node tree
{
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this);
for (PackageFileNameHashTable::Iterator it = fPackages.GetIterator();
Package* package = it.Next();) {
_RemovePackageContent(package, NULL, false);
}
}
while (PackageDomain* packageDomain = fPackageDomains.Head())
_RemovePackageDomain(packageDomain);
// delete the packages
Package* package = fPackages.Clear(true);
while (package != NULL) {
Package* next = package->FileNameHashTableNext();
package->ReleaseReference();
package = next;
}
// delete all indices
Index* index = fIndices.Clear(true);
@ -307,11 +380,17 @@ Volume::~Volume()
if (fRootDirectory != NULL)
fRootDirectory->ReleaseReference();
mutex_destroy(&fJobQueueLock);
rw_lock_destroy(&fLock);
}
int
Volume::PackagesDirectoryFD() const
{
return fPackagesDirectory->DirectoryFD();
}
status_t
Volume::Mount(const char* parameterString)
{
@ -324,6 +403,10 @@ Volume::Mount(const char* parameterString)
if (error != B_OK)
RETURN_ERROR(error);
error = fPackages.Init();
if (error != B_OK)
RETURN_ERROR(error);
error = fIndices.Init();
if (error != B_OK)
RETURN_ERROR(error);
@ -425,14 +508,14 @@ Volume::Mount(const char* parameterString)
if (error != B_OK)
RETURN_ERROR(error);
// create initial package domain
PackageDomain* packageDomain = new(std::nothrow) PackageDomain(this);
if (packageDomain == NULL)
// create package domain
fPackagesDirectory = new(std::nothrow) PackagesDirectory;
if (fPackagesDirectory == NULL)
RETURN_ERROR(B_NO_MEMORY);
BReference<PackageDomain> packageDomainReference(packageDomain, true);
struct stat st;
error = packageDomain->Init(packages, &st);
error = fPackagesDirectory->Init(packages, fMountPoint.deviceID,
fMountPoint.nodeID, st);
if (error != B_OK)
RETURN_ERROR(error);
@ -481,17 +564,11 @@ Volume::Mount(const char* parameterString)
if (error != B_OK)
RETURN_ERROR(error);
// add initial package domain
error = _AddPackageDomain(packageDomain, false);
// add initial packages
error = _AddInitialPackages();
if (error != B_OK)
RETURN_ERROR(error);
// spawn package loader thread
fPackageLoader = spawn_kernel_thread(&_PackageLoaderEntry,
"package loader", B_NORMAL_PRIORITY, this);
if (fPackageLoader < 0)
RETURN_ERROR(fPackageLoader);
// publish the root node
fRootDirectory->AcquireReference();
error = PublishVNode(fRootDirectory);
@ -505,9 +582,6 @@ Volume::Mount(const char* parameterString)
if (error != B_OK)
RETURN_ERROR(error);
// run the package loader
resume_thread(fPackageLoader);
return B_OK;
}
@ -515,7 +589,6 @@ Volume::Mount(const char* parameterString)
void
Volume::Unmount()
{
_TerminatePackageLoader();
}
@ -534,10 +607,8 @@ Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size)
info.mountType = fMountType;
info.rootDeviceID = fPackageFSRoot->DeviceID();
info.rootDirectoryID = fPackageFSRoot->NodeID();
PackageDomain* domain = fPackageDomains.Head();
info.packagesDeviceID = domain != NULL ? domain->DeviceID() : -1;
info.packagesDirectoryID = domain != NULL ? domain->NodeID() : -1;
info.packagesDeviceID = fPackagesDirectory->DeviceID();
info.packagesDirectoryID = fPackagesDirectory->NodeID();
RETURN_ERROR(user_memcpy(buffer, &info, sizeof(info)));
}
@ -552,13 +623,9 @@ Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size)
VolumeReadLocker volumeReadLocker(this);
PackageDomain* domain = fPackageDomains.Head();
if (domain == NULL)
RETURN_ERROR(B_BAD_VALUE);
uint32 packageIndex = 0;
for (PackageFileNameHashTable::Iterator it
= domain->Packages().GetIterator(); it.HasNext();
= fPackages.GetIterator(); it.HasNext();
packageIndex++) {
Package* package = it.Next();
PackageFSPackageInfo info;
@ -572,7 +639,7 @@ Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size)
return B_BAD_ADDRESS;
}
uint32 packageCount = domain->Packages().CountElements();
uint32 packageCount = fPackages.CountElements();
RETURN_ERROR(user_memcpy(&request->packageCount, &packageCount,
sizeof(packageCount)));
}
@ -685,28 +752,6 @@ Volume::PublishVNode(Node* node)
}
status_t
Volume::AddPackageDomain(const char* path)
{
PackageDomain* packageDomain = new(std::nothrow) PackageDomain(this);
if (packageDomain == NULL)
RETURN_ERROR(B_NO_MEMORY);
BReference<PackageDomain> packageDomainReference(packageDomain, true);
status_t error = packageDomain->Init(path, NULL);
if (error != B_OK)
RETURN_ERROR(error);
Job* job = new(std::nothrow) AddPackageDomainJob(this, packageDomain);
if (job == NULL)
RETURN_ERROR(B_NO_MEMORY);
_PushJob(job);
return B_OK;
}
void
Volume::PackageLinkNodeAdded(Node* node)
{
@ -736,84 +781,23 @@ Volume::PackageLinkNodeChanged(Node* node, uint32 statFields,
}
/*static*/ status_t
Volume::_PackageLoaderEntry(void* data)
{
return ((Volume*)data)->_PackageLoader();
}
status_t
Volume::_PackageLoader()
Volume::_AddInitialPackages()
{
while (!fTerminating) {
MutexLocker jobQueueLocker(fJobQueueLock);
Job* job = fJobQueue.RemoveHead();
if (job == NULL) {
// no job yet -- wait for someone notifying us
ConditionVariableEntry waitEntry;
fJobQueueCondition.Add(&waitEntry);
jobQueueLocker.Unlock();
waitEntry.Wait();
continue;
}
// do the job
jobQueueLocker.Unlock();
job->Do();
delete job;
}
return B_OK;
}
void
Volume::_TerminatePackageLoader()
{
fTerminating = true;
if (fPackageLoader >= 0) {
MutexLocker jobQueueLocker(fJobQueueLock);
fJobQueueCondition.NotifyOne();
jobQueueLocker.Unlock();
wait_for_thread(fPackageLoader, NULL);
fPackageLoader = -1;
}
// empty the job queue
while (Job* job = fJobQueue.RemoveHead())
delete job;
}
void
Volume::_PushJob(Job* job)
{
MutexLocker jobQueueLocker(fJobQueueLock);
fJobQueue.Add(job);
fJobQueueCondition.NotifyOne();
}
status_t
Volume::_AddPackageDomain(PackageDomain* domain, bool notify)
{
dprintf("packagefs: Adding package domain \"%s\"\n", domain->Path());
dprintf("packagefs: Adding packages from \"%s\"\n",
fPackagesDirectory->Path());
// iterate through the dir and create packages
int fd = dup(domain->DirectoryFD());
int fd = dup(fPackagesDirectory->DirectoryFD());
if (fd < 0) {
ERROR("Failed to dup() package domain FD: %s\n", strerror(errno));
ERROR("Failed to dup() packages directory FD: %s\n", strerror(errno));
RETURN_ERROR(errno);
}
DIR* dir = fdopendir(fd);
if (dir == NULL) {
ERROR("Failed to open package domain directory \"%s\": %s\n",
domain->Path(), strerror(errno));
ERROR("Failed to open packages directory \"%s\": %s\n",
fPackagesDirectory->Path(), strerror(errno));
RETURN_ERROR(errno);
}
CObjectDeleter<DIR, int> dirCloser(dir, closedir);
@ -824,53 +808,56 @@ Volume::_AddPackageDomain(PackageDomain* domain, bool notify)
continue;
Package* package;
if (_LoadPackage(domain, entry->d_name, package) != B_OK)
if (_LoadPackage(entry->d_name, package) != B_OK)
continue;
BReference<Package> packageReference(package, true);
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this);
domain->AddPackage(package);
_AddPackage(package);
}
// add the packages to the node tree
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this);
for (PackageFileNameHashTable::Iterator it
= domain->Packages().GetIterator(); Package* package = it.Next();) {
status_t error = _AddPackageContent(package, notify);
for (PackageFileNameHashTable::Iterator it = fPackages.GetIterator();
Package* package = it.Next();) {
status_t error = _AddPackageContent(package, false);
if (error != B_OK) {
for (it.Rewind(); Package* activePackage = it.Next();) {
if (activePackage == package)
break;
_RemovePackageContent(activePackage, NULL, notify);
_RemovePackageContent(activePackage, NULL, false);
}
RETURN_ERROR(error);
}
}
fPackageDomains.Add(domain);
domain->AcquireReference();
return B_OK;
}
void
Volume::_RemovePackageDomain(PackageDomain* domain)
inline void
Volume::_AddPackage(Package* package)
{
// remove the domain's packages from the node tree
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
VolumeWriteLocker volumeLocker(this);
for (PackageFileNameHashTable::Iterator it
= domain->Packages().GetIterator(); Package* package = it.Next();) {
_RemovePackageContent(package, NULL, false);
}
fPackages.Insert(package);
package->AcquireReference();
}
// remove the domain
fPackageDomains.Remove(domain);
domain->ReleaseReference();
inline void
Volume::_RemovePackage(Package* package)
{
fPackages.Remove(package);
package->ReleaseReference();
}
inline Package*
Volume::_FindPackage(const char* fileName) const
{
return fPackages.Lookup(fileName);
}
@ -1336,19 +1323,18 @@ Volume::_RemoveNodeAndVNode(Node* node)
}
/*static*/ status_t
Volume::_LoadPackage(PackageDomain* domain, const char* name,
Package*& _package)
status_t
Volume::_LoadPackage(const char* name, Package*& _package)
{
// check whether the entry is a file
struct stat st;
if (fstatat(domain->DirectoryFD(), name, &st, 0) < 0
if (fstatat(fPackagesDirectory->DirectoryFD(), name, &st, 0) < 0
|| !S_ISREG(st.st_mode)) {
return B_BAD_VALUE;
}
// create a package
Package* package = new(std::nothrow) Package(domain, st.st_dev, st.st_ino);
Package* package = new(std::nothrow) Package(this, st.st_dev, st.st_ino);
if (package == NULL)
RETURN_ERROR(B_NO_MEMORY);
BReference<Package> packageReference(package, true);
@ -1369,12 +1355,6 @@ Volume::_LoadPackage(PackageDomain* domain, const char* name,
status_t
Volume::_ChangeActivation(ActivationChangeRequest& request)
{
// TODO: Would need locking, but will be irrelevant when removing the support
// for multiple package domains.
PackageDomain* domain = fPackageDomains.Head();
if (domain == NULL)
RETURN_ERROR(B_BAD_VALUE);
// first check the request
int32 newPackageCount = 0;
int32 oldPackageCount = 0;
@ -1384,14 +1364,14 @@ Volume::_ChangeActivation(ActivationChangeRequest& request)
for (ActivationChangeRequest::Iterator it = request.GetIterator();
it.HasNext();) {
PackageFSActivationChangeItem* item = it.Next();
if (item->parentDeviceID != domain->DeviceID()
|| item->parentDirectoryID != domain->NodeID()) {
if (item->parentDeviceID != fPackagesDirectory->DeviceID()
|| item->parentDirectoryID != fPackagesDirectory->NodeID()) {
ERROR("Volume::_ChangeActivation(): mismatching packages "
"domain\n");
"directory\n");
RETURN_ERROR(B_BAD_VALUE);
}
Package* package = domain->FindPackage(item->name);
Package* package = _FindPackage(item->name);
// TODO: We should better look up the package by node_ref!
if (item->type == PACKAGE_FS_ACTIVATE_PACKAGE) {
if (package != NULL) {
@ -1449,7 +1429,7 @@ INFORM("Volume::_ChangeActivation(): %" B_PRId32 " new packages, %" B_PRId32 " o
}
Package* package;
status_t error = _LoadPackage(domain, item->name, package);
status_t error = _LoadPackage(item->name, package);
if (error != B_OK) {
ERROR("Volume::_ChangeActivation(): failed to load package "
"\"%s\"\n", item->name);
@ -1476,11 +1456,11 @@ INFORM("Volume::_ChangeActivation(): %" B_PRId32 " new packages, %" B_PRId32 " o
continue;
}
Package* package = domain->FindPackage(item->name);
Package* package = _FindPackage(item->name);
// TODO: We should better look up the package by node_ref!
oldPackageReferences[oldPackageIndex++].SetTo(package);
_RemovePackageContent(package, NULL, true);
domain->RemovePackage(package);
_RemovePackage(package);
INFORM("package \"%s\" deactivated\n", package->FileName());
}
// TODO: Since package removal cannot fail, consider adding the new packages
@ -1492,12 +1472,12 @@ INFORM("package \"%s\" deactivated\n", package->FileName());
for (newPackageIndex = 0; newPackageIndex < newPackageCount;
newPackageIndex++) {
Package* package = newPackageReferences[newPackageIndex];
domain->AddPackage(package);
_AddPackage(package);
// add the package to the node tree
error = _AddPackageContent(package, true);
if (error != B_OK) {
domain->RemovePackage(package);
_RemovePackage(package);
break;
}
INFORM("package \"%s\" activated\n", package->FileName());
@ -1508,19 +1488,19 @@ INFORM("package \"%s\" activated\n", package->FileName());
for (int32 i = newPackageIndex - 1; i >= 0; i--) {
Package* package = newPackageReferences[i];
_RemovePackageContent(package, NULL, true);
domain->RemovePackage(package);
_RemovePackage(package);
}
for (int32 i = oldPackageCount - 1; i >= 0; i--) {
Package* package = oldPackageReferences[i];
domain->AddPackage(package);
_AddPackage(package);
if (_AddPackageContent(package, true) != B_OK) {
// nothing we can do here
ERROR("Volume::_ChangeActivation(): failed to roll back "
"deactivation of package \"%s\" after error\n",
package->FileName());
domain->RemovePackage(package);
_RemovePackage(package);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VOLUME_H
@ -19,7 +19,7 @@
#include "Index.h"
#include "Node.h"
#include "NodeListener.h"
#include "PackageDomain.h"
#include "Package.h"
#include "PackageLinksListener.h"
#include "Query.h"
@ -51,6 +51,8 @@ public:
::MountType MountType() const { return fMountType; }
int PackagesDirectoryFD() const;
void SetPackageFSRoot(::PackageFSRoot* root)
{ fPackageFSRoot = root; }
::PackageFSRoot* PackageFSRoot() const
@ -94,8 +96,6 @@ public:
status_t RemoveVNode(ino_t nodeID);
status_t PublishVNode(Node* node);
status_t AddPackageDomain(const char* path);
private:
// PackageLinksListener
virtual void PackageLinkNodeAdded(Node* node);
@ -105,29 +105,16 @@ private:
const OldNodeAttributes& oldAttributes);
private:
struct Job;
struct AddPackageDomainJob;
struct DomainDirectoryEventJob;
struct PackagesDirectory;
struct ShineThroughDirectory;
struct ActivationChangeRequest;
friend struct AddPackageDomainJob;
typedef DoublyLinkedList<Job> JobList;
typedef DoublyLinkedList<PackageDomain> PackageDomainList;
private:
static status_t _PackageLoaderEntry(void* data);
status_t _PackageLoader();
status_t _AddInitialPackages();
void _TerminatePackageLoader();
void _PushJob(Job* job);
status_t _AddInitialPackageDomain(const char* path);
status_t _AddPackageDomain(PackageDomain* domain,
bool notify);
void _RemovePackageDomain(PackageDomain* domain);
inline void _AddPackage(Package* package);
inline void _RemovePackage(Package* package);
inline Package* _FindPackage(const char* fileName) const;
status_t _AddPackageContent(Package* package,
bool notify);
@ -155,8 +142,8 @@ private:
void _RemoveNodeAndVNode(Node* node);
// caller must hold a reference
static status_t _LoadPackage(PackageDomain* domain,
const char* name, Package*& _package);
status_t _LoadPackage(const char* name,
Package*& _package);
status_t _ChangeActivation(
ActivationChangeRequest& request);
@ -187,8 +174,7 @@ private:
Directory* fRootDirectory;
::PackageFSRoot* fPackageFSRoot;
::MountType fMountType;
thread_id fPackageLoader;
PackageDomainList fPackageDomains;
PackagesDirectory* fPackagesDirectory;
struct {
dev_t deviceID;
@ -197,16 +183,11 @@ private:
NodeIDHashTable fNodes;
NodeListenerHashTable fNodeListeners;
PackageFileNameHashTable fPackages;
QueryList fQueries;
IndexHashTable fIndices;
JobList fJobQueue;
mutex fJobQueueLock;
ConditionVariable fJobQueueCondition;
ino_t fNextNodeID;
volatile bool fTerminating;
};