WIP towards dependency package links
* Add ResolvableFamily and DependencyFamily classes for grouping equally
named resolvables/dependencies.
* Add hash tables to PackageFSRoot to track resolvables and
dependencies. That is done in {Add,Remove}Package.
* Resolvable does now have a list of Dependency objects, the ones it
satisfies.
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
Dependency::Dependency(Package* package)
|
||||
:
|
||||
fPackage(package),
|
||||
fFamily(NULL),
|
||||
fResolvable(NULL),
|
||||
fName(NULL),
|
||||
fVersion(NULL),
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
class DependencyFamily;
|
||||
class Package;
|
||||
class Resolvable;
|
||||
class Version;
|
||||
@@ -34,21 +35,41 @@ public:
|
||||
// version is optional; object takes over
|
||||
// ownership
|
||||
|
||||
void SetFamily(DependencyFamily* family)
|
||||
{ fFamily = family; }
|
||||
DependencyFamily* Family() const
|
||||
{ return fFamily; }
|
||||
|
||||
void SetResolvable(::Resolvable* resolvable)
|
||||
{ fResolvable = resolvable; }
|
||||
::Resolvable* Resolvable() const
|
||||
{ return fResolvable; }
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
|
||||
private:
|
||||
Package* fPackage;
|
||||
DependencyFamily* fFamily;
|
||||
::Resolvable* fResolvable;
|
||||
char* fName;
|
||||
Version* fVersion;
|
||||
BPackageResolvableOperator fVersionOperator;
|
||||
|
||||
public: // conceptually package private
|
||||
DoublyLinkedListLink<Dependency> fFamilyListLink;
|
||||
DoublyLinkedListLink<Dependency> fResolvableListLink;
|
||||
};
|
||||
|
||||
|
||||
typedef DoublyLinkedList<Dependency> DependencyList;
|
||||
|
||||
typedef DoublyLinkedList<Dependency,
|
||||
DoublyLinkedListMemberGetLink<Dependency,
|
||||
&Dependency::fFamilyListLink> > FamilyDependencyList;
|
||||
|
||||
typedef DoublyLinkedList<Dependency,
|
||||
DoublyLinkedListMemberGetLink<Dependency,
|
||||
&Dependency::fResolvableListLink> > ResolvableDependencyList;
|
||||
|
||||
|
||||
#endif // DEPENDENCY_H
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DEPENDENCY_FAMILY_H
|
||||
#define DEPENDENCY_FAMILY_H
|
||||
|
||||
|
||||
#include <util/khash.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "Dependency.h"
|
||||
|
||||
|
||||
class DependencyFamily {
|
||||
public:
|
||||
void AddDependency(Dependency* dependency);
|
||||
void RemoveDependency(Dependency* dependency);
|
||||
|
||||
const char* Name() const;
|
||||
|
||||
bool IsLastDependency(Dependency* dependency) const;
|
||||
|
||||
DependencyFamily*& HashLink() { return fHashLink; }
|
||||
|
||||
private:
|
||||
DependencyFamily* fHashLink;
|
||||
FamilyDependencyList fDependencies;
|
||||
};
|
||||
|
||||
|
||||
inline void
|
||||
DependencyFamily::AddDependency(Dependency* dependency)
|
||||
{
|
||||
fDependencies.Add(dependency);
|
||||
dependency->SetFamily(this);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
DependencyFamily::RemoveDependency(Dependency* dependency)
|
||||
{
|
||||
dependency->SetFamily(NULL);
|
||||
fDependencies.Remove(dependency);
|
||||
}
|
||||
|
||||
|
||||
inline const char*
|
||||
DependencyFamily::Name() const
|
||||
{
|
||||
Dependency* head = fDependencies.Head();
|
||||
return head != NULL ? head->Name() : NULL;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
DependencyFamily::IsLastDependency(Dependency* dependency) const
|
||||
{
|
||||
return fDependencies.Head() == dependency
|
||||
&& fDependencies.Tail() == dependency;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DependencyFamilyHashDefinition
|
||||
|
||||
|
||||
struct DependencyFamilyHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef DependencyFamily ValueType;
|
||||
|
||||
size_t HashKey(const char* key) const
|
||||
{
|
||||
return key != NULL ? hash_hash_string(key) : 0;
|
||||
}
|
||||
|
||||
size_t Hash(const DependencyFamily* value) const
|
||||
{
|
||||
return HashKey(value->Name());
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const DependencyFamily* value) const
|
||||
{
|
||||
return strcmp(value->Name(), key) == 0;
|
||||
}
|
||||
|
||||
DependencyFamily*& GetLink(DependencyFamily* value) const
|
||||
{
|
||||
return value->HashLink();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef BOpenHashTable<DependencyFamilyHashDefinition>
|
||||
DependencyFamilyHashTable;
|
||||
|
||||
|
||||
#endif // DEPENDENCY_FAMILY_H
|
||||
@@ -30,6 +30,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
||||
PackageNodeAttribute.cpp
|
||||
PackageSymlink.cpp
|
||||
Resolvable.cpp
|
||||
ResolvableFamily.cpp
|
||||
UnpackingAttributeCookie.cpp
|
||||
UnpackingAttributeDirectoryCookie.cpp
|
||||
UnpackingDirectory.cpp
|
||||
|
||||
@@ -60,7 +60,11 @@ public:
|
||||
int Open();
|
||||
void Close();
|
||||
|
||||
const PackageNodeList& Nodes() const { return fNodes; }
|
||||
const PackageNodeList& Nodes() const { return fNodes; }
|
||||
const ResolvableList& Resolvables() const
|
||||
{ return fResolvables; }
|
||||
const DependencyList& Dependencies() const
|
||||
{ return fDependencies; }
|
||||
|
||||
private:
|
||||
mutex fLock;
|
||||
|
||||
@@ -64,6 +64,14 @@ PackageFSRoot::Init()
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
error = fResolvables.Init();
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
error = fDependencies.Init();
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -159,14 +167,24 @@ PackageFSRoot::UnregisterVolume(Volume* volume)
|
||||
status_t
|
||||
PackageFSRoot::AddPackage(Package* package)
|
||||
{
|
||||
return fPackageLinksDirectory->AddPackage(package);
|
||||
PackageFSRootWriteLocker writeLocker(this);
|
||||
|
||||
status_t error = _AddPackage(package);
|
||||
if (error != B_OK) {
|
||||
_RemovePackage(package);
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageFSRoot::RemovePackage(Package* package)
|
||||
{
|
||||
fPackageLinksDirectory->RemovePackage(package);
|
||||
PackageFSRootWriteLocker writeLocker(this);
|
||||
|
||||
_RemovePackage(package);
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +227,100 @@ PackageFSRoot::_RemoveVolume(Volume* volume)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PackageFSRoot::_AddPackage(Package* package)
|
||||
{
|
||||
ResolvableDependencyList dependenciesToUpdate;
|
||||
|
||||
// register resolvables
|
||||
for (ResolvableList::ConstIterator it
|
||||
= package->Resolvables().GetIterator();
|
||||
Resolvable* resolvable = it.Next();) {
|
||||
if (ResolvableFamily* family
|
||||
= fResolvables.Lookup(resolvable->Name())) {
|
||||
family->AddResolvable(resolvable, dependenciesToUpdate);
|
||||
} else {
|
||||
ResolvableFamily* family = new(std::nothrow) ResolvableFamily;
|
||||
if (family == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
family->AddResolvable(resolvable, dependenciesToUpdate);
|
||||
fResolvables.Insert(family);
|
||||
}
|
||||
}
|
||||
|
||||
// register dependencies
|
||||
for (DependencyList::ConstIterator it
|
||||
= package->Dependencies().GetIterator();
|
||||
Dependency* dependency = it.Next();) {
|
||||
if (DependencyFamily* family
|
||||
= fDependencies.Lookup(dependency->Name())) {
|
||||
family->AddDependency(dependency);
|
||||
} else {
|
||||
DependencyFamily* family = new(std::nothrow) DependencyFamily;
|
||||
if (family == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
family->AddDependency(dependency);
|
||||
fDependencies.Insert(family);
|
||||
}
|
||||
|
||||
dependenciesToUpdate.Add(dependency);
|
||||
}
|
||||
|
||||
return fPackageLinksDirectory->AddPackage(package);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageFSRoot::_RemovePackage(Package* package)
|
||||
{
|
||||
fPackageLinksDirectory->RemovePackage(package);
|
||||
|
||||
// unregister dependencies
|
||||
for (DependencyList::ConstIterator it
|
||||
= package->Dependencies().GetIterator();
|
||||
Dependency* dependency = it.Next();) {
|
||||
if (DependencyFamily* family = dependency->Family()) {
|
||||
if (family->IsLastDependency(dependency)) {
|
||||
fDependencies.Remove(family);
|
||||
family->RemoveDependency(dependency);
|
||||
delete family;
|
||||
} else
|
||||
family->RemoveDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
// unregister resolvables
|
||||
ResolvableDependencyList dependenciesToUpdate;
|
||||
|
||||
for (ResolvableList::ConstIterator it
|
||||
= package->Resolvables().GetIterator();
|
||||
Resolvable* resolvable = it.Next();) {
|
||||
if (ResolvableFamily* family = resolvable->Family()) {
|
||||
if (family->IsLastResolvable(resolvable)) {
|
||||
fResolvables.Remove(family);
|
||||
family->RemoveResolvable(resolvable, dependenciesToUpdate);
|
||||
delete family;
|
||||
} else
|
||||
family->RemoveResolvable(resolvable, dependenciesToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
_ResolveDependencies(dependenciesToUpdate);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageFSRoot::_ResolveDependencies(ResolvableDependencyList& dependencies)
|
||||
{
|
||||
if (dependencies.IsEmpty())
|
||||
return;
|
||||
|
||||
// TODO:...
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
PackageFSRoot::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID,
|
||||
PackageFSRoot*& _root)
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#include "DependencyFamily.h"
|
||||
#include "ResolvableFamily.h"
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
@@ -58,6 +60,12 @@ private:
|
||||
status_t _AddVolume(Volume* volume);
|
||||
void _RemoveVolume(Volume* volume);
|
||||
|
||||
status_t _AddPackage(Package* package);
|
||||
void _RemovePackage(Package* package);
|
||||
|
||||
void _ResolveDependencies(
|
||||
ResolvableDependencyList& dependencies);
|
||||
|
||||
static status_t _GetOrCreateRoot(dev_t deviceID, ino_t nodeID,
|
||||
PackageFSRoot*& _root);
|
||||
static PackageFSRoot* _FindRootLocked(dev_t deviceID, ino_t nodeID);
|
||||
@@ -73,6 +81,8 @@ private:
|
||||
VolumeList fVolumes;
|
||||
Volume* fSystemVolume;
|
||||
PackageLinksDirectory* fPackageLinksDirectory;
|
||||
ResolvableFamilyHashTable fResolvables;
|
||||
DependencyFamilyHashTable fDependencies;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
#include "Version.h"
|
||||
|
||||
|
||||
Resolvable::Resolvable(Package* package)
|
||||
Resolvable::Resolvable(::Package* package)
|
||||
:
|
||||
fPackage(package),
|
||||
fFamily(NULL),
|
||||
fName(NULL),
|
||||
fVersion(NULL)
|
||||
{
|
||||
@@ -38,3 +39,34 @@ Resolvable::Init(const char* name, Version* version)
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Resolvable::AddDependency(Dependency* dependency)
|
||||
{
|
||||
fDependencies.Add(dependency);
|
||||
dependency->SetResolvable(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Resolvable::RemoveDependency(Dependency* dependency)
|
||||
{
|
||||
fDependencies.Remove(dependency);
|
||||
dependency->SetResolvable(NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Resolvable::MoveDependencies(ResolvableDependencyList& dependencies)
|
||||
{
|
||||
if (fDependencies.IsEmpty())
|
||||
return;
|
||||
|
||||
for (ResolvableDependencyList::Iterator it = fDependencies.GetIterator();
|
||||
Dependency* dependency = it.Next();) {
|
||||
dependency->SetResolvable(NULL);
|
||||
}
|
||||
|
||||
dependencies.MoveFrom(&fDependencies);
|
||||
}
|
||||
|
||||
@@ -10,29 +10,55 @@
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "Dependency.h"
|
||||
|
||||
|
||||
class Package;
|
||||
class ResolvableFamily;
|
||||
class Version;
|
||||
|
||||
|
||||
class Resolvable : public BReferenceable,
|
||||
public DoublyLinkedListLinkImpl<Resolvable> {
|
||||
public:
|
||||
Resolvable(Package* package);
|
||||
Resolvable(::Package* package);
|
||||
virtual ~Resolvable();
|
||||
|
||||
status_t Init(const char* name, Version* version);
|
||||
// version is optional; object takes over
|
||||
// ownership (even in case of error)
|
||||
|
||||
::Package* Package() const { return fPackage; }
|
||||
|
||||
void SetFamily(ResolvableFamily* family)
|
||||
{ fFamily = family; }
|
||||
ResolvableFamily* Family() const
|
||||
{ return fFamily; }
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
|
||||
void AddDependency(Dependency* dependency);
|
||||
void RemoveDependency(Dependency* dependency);
|
||||
void MoveDependencies(
|
||||
ResolvableDependencyList& dependencies);
|
||||
|
||||
private:
|
||||
Package* fPackage;
|
||||
::Package* fPackage;
|
||||
ResolvableFamily* fFamily;
|
||||
char* fName;
|
||||
Version* fVersion;
|
||||
ResolvableDependencyList fDependencies;
|
||||
|
||||
public: // conceptually package private
|
||||
DoublyLinkedListLink<Resolvable> fFamilyListLink;
|
||||
};
|
||||
|
||||
|
||||
typedef DoublyLinkedList<Resolvable> ResolvableList;
|
||||
|
||||
typedef DoublyLinkedList<Resolvable,
|
||||
DoublyLinkedListMemberGetLink<Resolvable,
|
||||
&Resolvable::fFamilyListLink> > FamilyResolvableList;
|
||||
|
||||
|
||||
#endif // RESOLVABLE_H
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ResolvableFamily.h"
|
||||
|
||||
#include "Package.h"
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
void
|
||||
ResolvableFamily::AddResolvable(Resolvable* resolvable,
|
||||
ResolvableDependencyList& dependenciesToUpdate)
|
||||
{
|
||||
// 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* otherResolvable = NULL;
|
||||
for (FamilyResolvableList::Iterator it = fResolvables.GetIterator();
|
||||
(otherResolvable = it.Next()) != NULL;) {
|
||||
if (otherResolvable->Package()->Domain()->Volume()->MountType()
|
||||
<= mountType) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fResolvables.InsertBefore(otherResolvable, resolvable);
|
||||
resolvable->SetFamily(this);
|
||||
|
||||
// all dependencies after the inserted resolvable potentially need to be
|
||||
// updated
|
||||
while ((resolvable = fResolvables.GetNext(resolvable)) != NULL)
|
||||
resolvable->MoveDependencies(dependenciesToUpdate);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolvableFamily::RemoveResolvable(Resolvable* resolvable,
|
||||
ResolvableDependencyList& dependenciesToUpdate)
|
||||
{
|
||||
resolvable->SetFamily(NULL);
|
||||
fResolvables.Remove(resolvable);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef RESOLVABLE_FAMILY_H
|
||||
#define RESOLVABLE_FAMILY_H
|
||||
|
||||
|
||||
#include <util/khash.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "Resolvable.h"
|
||||
|
||||
|
||||
class ResolvableFamily {
|
||||
public:
|
||||
void AddResolvable(Resolvable* resolvable,
|
||||
ResolvableDependencyList&
|
||||
dependenciesToUpdate);
|
||||
void RemoveResolvable(Resolvable* resolvable,
|
||||
ResolvableDependencyList&
|
||||
dependenciesToUpdate);
|
||||
|
||||
const char* Name() const;
|
||||
|
||||
bool IsLastResolvable(Resolvable* resolvable) const;
|
||||
|
||||
ResolvableFamily*& HashLink() { return fHashLink; }
|
||||
|
||||
private:
|
||||
ResolvableFamily* fHashLink;
|
||||
FamilyResolvableList fResolvables;
|
||||
};
|
||||
|
||||
|
||||
inline const char*
|
||||
ResolvableFamily::Name() const
|
||||
{
|
||||
Resolvable* head = fResolvables.Head();
|
||||
return head != NULL ? head->Name() : NULL;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
ResolvableFamily::IsLastResolvable(Resolvable* resolvable) const
|
||||
{
|
||||
return fResolvables.Head() == resolvable
|
||||
&& fResolvables.Tail() == resolvable;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ResolvableFamilyHashDefinition
|
||||
|
||||
|
||||
struct ResolvableFamilyHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef ResolvableFamily ValueType;
|
||||
|
||||
size_t HashKey(const char* key) const
|
||||
{
|
||||
return key != NULL ? hash_hash_string(key) : 0;
|
||||
}
|
||||
|
||||
size_t Hash(const ResolvableFamily* value) const
|
||||
{
|
||||
return HashKey(value->Name());
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const ResolvableFamily* value) const
|
||||
{
|
||||
return strcmp(value->Name(), key) == 0;
|
||||
}
|
||||
|
||||
ResolvableFamily*& GetLink(ResolvableFamily* value) const
|
||||
{
|
||||
return value->HashLink();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef BOpenHashTable<ResolvableFamilyHashDefinition>
|
||||
ResolvableFamilyHashTable;
|
||||
|
||||
|
||||
#endif // RESOLVABLE_FAMILY_H
|
||||
Reference in New Issue
Block a user