WIP: Create empty package links directories

* Rename PackageFamily to PackageLinkDirectory and derive from
  Directory.
* PackageLinksDirectory: Add the PackageLinkDirectory objects as
  children and remove the no longer needed hash table (we use the
  Directory's child hash table).
This commit is contained in:
Ingo Weinhold 2011-06-24 02:15:56 +02:00
parent 05d7d4818e
commit 4031a32acc
9 changed files with 238 additions and 185 deletions

View File

@ -20,10 +20,10 @@ HAIKU_PACKAGE_FS_SOURCES =
Package.cpp
PackageDirectory.cpp
PackageDomain.cpp
PackageFamily.cpp
PackageFile.cpp
PackageFSRoot.cpp
PackageLeafNode.cpp
PackageLinkDirectory.cpp
PackageLinksDirectory.cpp
PackageNode.cpp
PackageNodeAttribute.cpp

View File

@ -25,7 +25,7 @@ Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
fFileName(NULL),
fName(NULL),
fVersion(NULL),
fFamily(NULL),
fLinkDirectory(NULL),
fFD(-1),
fOpenCount(0),
fNodeID(nodeID),

View File

@ -20,7 +20,7 @@
class PackageDomain;
class PackageFamily;
class PackageLinkDirectory;
class Version;
@ -44,10 +44,11 @@ public:
::Version* Version() const
{ return fVersion; }
void SetFamily(PackageFamily* family)
{ fFamily = family; }
PackageFamily* Family() const
{ return fFamily; }
void SetLinkDirectory(
PackageLinkDirectory* linkDirectory)
{ fLinkDirectory = linkDirectory; }
PackageLinkDirectory* LinkDirectory() const
{ return fLinkDirectory; }
Package*& FileNameHashTableNext()
{ return fFileNameHashTableNext; }
@ -67,7 +68,7 @@ private:
char* fFileName;
char* fName;
::Version* fVersion;
PackageFamily* fFamily;
PackageLinkDirectory* fLinkDirectory;
int fFD;
uint32 fOpenCount;
Package* fFileNameHashTableNext;

View File

@ -1,78 +0,0 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PackageFamily.h"
#include <stdlib.h>
#include <string.h>
#include "DebugSupport.h"
#include "Version.h"
PackageFamily::PackageFamily()
:
fName(NULL)
{
}
PackageFamily::~PackageFamily()
{
while (Package* package = fPackages.RemoveHead())
package->SetFamily(NULL);
free(fName);
}
status_t
PackageFamily::Init(Package* package)
{
// compute the allocation size needed for the versioned name
size_t nameLength = strlen(package->Name());
size_t size = nameLength + 1;
Version* version = package->Version();
if (version != NULL) {
size += 1 + version->ToString(NULL, 0);
// + 1 for the '-'
}
// allocate the name and compose it
fName = (char*)malloc(size);
if (fName == NULL)
return B_NO_MEMORY;
memcpy(fName, package->Name(), nameLength + 1);
if (version != NULL) {
fName[nameLength] = '-';
version->ToString(fName + nameLength + 1, size - nameLength - 1);
}
// add the package
AddPackage(package);
return B_OK;
}
void
PackageFamily::AddPackage(Package* package)
{
fPackages.Add(package);
package->SetFamily(this);
}
void
PackageFamily::RemovePackage(Package* package)
{
ASSERT(package->Family() == this);
package->SetFamily(NULL);
fPackages.Remove(package);
}

View File

@ -1,71 +0,0 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_FAMILY_H
#define PACKAGE_FAMILY_H
#include <Referenceable.h>
#include "Package.h"
/*! A set of equally named and versioned packages.
This should only happen when the same package is installed in multiple
domains (e.g. common and home).
*/
class PackageFamily {
public:
PackageFamily();
~PackageFamily();
status_t Init(Package* package);
const char* Name() const { return fName; }
void AddPackage(Package* package);
void RemovePackage(Package* package);
bool IsEmpty() const
{ return fPackages.IsEmpty(); }
PackageFamily*& HashNext() { return fHashNext; }
private:
PackageFamily* fHashNext;
char* fName;
PackageList fPackages;
};
struct PackageFamilyHashDefinition {
typedef const char* KeyType;
typedef PackageFamily ValueType;
size_t HashKey(const char* key) const
{
return hash_hash_string(key);
}
size_t Hash(const PackageFamily* value) const
{
return HashKey(value->Name());
}
bool Compare(const char* key, const PackageFamily* value) const
{
return strcmp(value->Name(), key) == 0;
}
PackageFamily*& GetLink(PackageFamily* value) const
{
return value->HashNext();
}
};
typedef BOpenHashTable<PackageFamilyHashDefinition> PackageFamilyHashTable;
#endif // PACKAGE_FAMILY_H

View File

@ -0,0 +1,151 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "PackageLinkDirectory.h"
#include <AutoDeleter.h>
#include "EmptyAttributeDirectoryCookie.h"
#include "DebugSupport.h"
#include "Utils.h"
#include "Version.h"
PackageLinkDirectory::PackageLinkDirectory()
:
Directory(0)
// the ID needs to be assigned later, when added to a volume
{
get_real_time(fModifiedTime);
}
PackageLinkDirectory::~PackageLinkDirectory()
{
}
status_t
PackageLinkDirectory::Init(Directory* parent, Package* package)
{
// compute the allocation size needed for the versioned name
size_t nameLength = strlen(package->Name());
size_t size = nameLength + 1;
Version* version = package->Version();
if (version != NULL) {
size += 1 + version->ToString(NULL, 0);
// + 1 for the '-'
}
// allocate the name and compose it
char* name = (char*)malloc(size);
if (name == NULL)
return B_NO_MEMORY;
MemoryDeleter nameDeleter(name);
memcpy(name, package->Name(), nameLength + 1);
if (version != NULL) {
name[nameLength] = '-';
version->ToString(name + nameLength + 1, size - nameLength - 1);
}
// init the directory/node
status_t error = Init(parent, name);
// TODO: This copies the name unnecessarily!
if (error != B_OK)
RETURN_ERROR(error);
// add the package
AddPackage(package);
return B_OK;
}
status_t
PackageLinkDirectory::Init(Directory* parent, const char* name)
{
return Directory::Init(parent, name);
}
mode_t
PackageLinkDirectory::Mode() const
{
return S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
}
uid_t
PackageLinkDirectory::UserID() const
{
return 0;
}
gid_t
PackageLinkDirectory::GroupID() const
{
return 0;
}
timespec
PackageLinkDirectory::ModifiedTime() const
{
return fModifiedTime;
}
off_t
PackageLinkDirectory::FileSize() const
{
return 0;
}
status_t
PackageLinkDirectory::OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie)
{
AttributeDirectoryCookie* cookie
= new(std::nothrow) EmptyAttributeDirectoryCookie;
if (cookie == NULL)
return B_NO_MEMORY;
_cookie = cookie;
return B_OK;
}
status_t
PackageLinkDirectory::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie)
{
return B_ENTRY_NOT_FOUND;
}
void
PackageLinkDirectory::AddPackage(Package* package)
{
// TODO: Add in priority order!
fPackages.Add(package);
package->SetLinkDirectory(this);
}
void
PackageLinkDirectory::RemovePackage(Package* package)
{
ASSERT(package->LinkDirectory() == this);
package->SetLinkDirectory(NULL);
fPackages.Remove(package);
// TODO: Check whether that was the top priority package!
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_LINK_DIRECTORY_H
#define PACKAGE_LINK_DIRECTORY_H
#include "Directory.h"
#include "Package.h"
class PackageLinkDirectory : public Directory {
public:
PackageLinkDirectory();
virtual ~PackageLinkDirectory();
status_t Init(Directory* parent, Package* package);
virtual status_t Init(Directory* parent, const char* name);
virtual mode_t Mode() const;
virtual uid_t UserID() const;
virtual gid_t GroupID() const;
virtual timespec ModifiedTime() const;
virtual off_t FileSize() const;
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie);
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie);
void AddPackage(Package* package);
void RemovePackage(Package* package);
bool IsEmpty() const
{ return fPackages.IsEmpty(); }
private:
timespec fModifiedTime;
PackageList fPackages;
};
#endif // PACKAGE_LINK_DIRECTORY_H

View File

@ -10,6 +10,7 @@
#include "EmptyAttributeDirectoryCookie.h"
#include "DebugSupport.h"
#include "PackageLinkDirectory.h"
#include "Utils.h"
@ -30,10 +31,6 @@ PackageLinksDirectory::~PackageLinksDirectory()
status_t
PackageLinksDirectory::Init(Directory* parent, const char* name)
{
status_t error = fPackageFamilies.Init();
if (error != B_OK)
RETURN_ERROR(error);
return Directory::Init(parent, name);
}
@ -98,26 +95,32 @@ PackageLinksDirectory::OpenAttribute(const char* name, int openMode,
status_t
PackageLinksDirectory::AddPackage(Package* package)
{
// Create a package family -- there might already be one, but since that's
// unlikely, we don't bother to check and recheck later.
PackageFamily* packageFamily = new(std::nothrow) PackageFamily;
if (packageFamily == NULL)
// Create a package link directory -- there might already be one, but since
// that's unlikely, we don't bother to check and recheck later.
PackageLinkDirectory* linkDirectory
= new(std::nothrow) PackageLinkDirectory;
if (linkDirectory == NULL)
return B_NO_MEMORY;
ObjectDeleter<PackageFamily> packageFamilyDeleter(packageFamily);
BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory,
true);
status_t error = packageFamily->Init(package);
status_t error = linkDirectory->Init(this, package);
if (error != B_OK)
RETURN_ERROR(error);
// add the family
// add the link directory
NodeWriteLocker writeLocker(this);
if (PackageFamily* otherPackageFamily
= fPackageFamilies.Lookup(packageFamily->Name())) {
packageFamily->RemovePackage(package);
packageFamily = otherPackageFamily;
packageFamily->AddPackage(package);
if (Node* child = FindChild(linkDirectory->Name())) {
PackageLinkDirectory* otherLinkDirectory
= dynamic_cast<PackageLinkDirectory*>(child);
if (otherLinkDirectory != NULL)
RETURN_ERROR(B_BAD_VALUE);
linkDirectory->RemovePackage(package);
linkDirectory = otherLinkDirectory;
linkDirectory->AddPackage(package);
} else
fPackageFamilies.Insert(packageFamilyDeleter.Detach());
AddChild(linkDirectory);
// TODO:...
@ -128,18 +131,20 @@ PackageLinksDirectory::AddPackage(Package* package)
void
PackageLinksDirectory::RemovePackage(Package* package)
{
NodeWriteLocker writeLocker(this);
PackageFamily* packageFamily = package->Family();
if (packageFamily == NULL)
// get the package's link directory and remove the package from it
PackageLinkDirectory* linkDirectory = package->LinkDirectory();
if (linkDirectory == NULL)
return;
packageFamily->RemovePackage(package);
BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory);
if (packageFamily->IsEmpty()) {
fPackageFamilies.Remove(packageFamily);
delete packageFamily;
}
NodeWriteLocker writeLocker(this);
linkDirectory->RemovePackage(package);
// if empty, remove the link directory itself
if (linkDirectory->IsEmpty())
RemoveChild(linkDirectory);
// TODO:...
}

View File

@ -7,7 +7,9 @@
#include "Directory.h"
#include "PackageFamily.h"
class Package;
class PackageLinksDirectory : public Directory {
@ -33,7 +35,6 @@ public:
private:
timespec fModifiedTime;
PackageFamilyHashTable fPackageFamilies;
};