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:
Ingo Weinhold
2011-11-25 06:18:12 +01:00
parent 3068366ed1
commit 7d2fa6f0f8
11 changed files with 441 additions and 6 deletions
@@ -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