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:
@@ -20,10 +20,10 @@ HAIKU_PACKAGE_FS_SOURCES =
|
|||||||
Package.cpp
|
Package.cpp
|
||||||
PackageDirectory.cpp
|
PackageDirectory.cpp
|
||||||
PackageDomain.cpp
|
PackageDomain.cpp
|
||||||
PackageFamily.cpp
|
|
||||||
PackageFile.cpp
|
PackageFile.cpp
|
||||||
PackageFSRoot.cpp
|
PackageFSRoot.cpp
|
||||||
PackageLeafNode.cpp
|
PackageLeafNode.cpp
|
||||||
|
PackageLinkDirectory.cpp
|
||||||
PackageLinksDirectory.cpp
|
PackageLinksDirectory.cpp
|
||||||
PackageNode.cpp
|
PackageNode.cpp
|
||||||
PackageNodeAttribute.cpp
|
PackageNodeAttribute.cpp
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
|
|||||||
fFileName(NULL),
|
fFileName(NULL),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
fVersion(NULL),
|
fVersion(NULL),
|
||||||
fFamily(NULL),
|
fLinkDirectory(NULL),
|
||||||
fFD(-1),
|
fFD(-1),
|
||||||
fOpenCount(0),
|
fOpenCount(0),
|
||||||
fNodeID(nodeID),
|
fNodeID(nodeID),
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class PackageDomain;
|
class PackageDomain;
|
||||||
class PackageFamily;
|
class PackageLinkDirectory;
|
||||||
class Version;
|
class Version;
|
||||||
|
|
||||||
|
|
||||||
@@ -44,10 +44,11 @@ public:
|
|||||||
::Version* Version() const
|
::Version* Version() const
|
||||||
{ return fVersion; }
|
{ return fVersion; }
|
||||||
|
|
||||||
void SetFamily(PackageFamily* family)
|
void SetLinkDirectory(
|
||||||
{ fFamily = family; }
|
PackageLinkDirectory* linkDirectory)
|
||||||
PackageFamily* Family() const
|
{ fLinkDirectory = linkDirectory; }
|
||||||
{ return fFamily; }
|
PackageLinkDirectory* LinkDirectory() const
|
||||||
|
{ return fLinkDirectory; }
|
||||||
|
|
||||||
Package*& FileNameHashTableNext()
|
Package*& FileNameHashTableNext()
|
||||||
{ return fFileNameHashTableNext; }
|
{ return fFileNameHashTableNext; }
|
||||||
@@ -67,7 +68,7 @@ private:
|
|||||||
char* fFileName;
|
char* fFileName;
|
||||||
char* fName;
|
char* fName;
|
||||||
::Version* fVersion;
|
::Version* fVersion;
|
||||||
PackageFamily* fFamily;
|
PackageLinkDirectory* fLinkDirectory;
|
||||||
int fFD;
|
int fFD;
|
||||||
uint32 fOpenCount;
|
uint32 fOpenCount;
|
||||||
Package* fFileNameHashTableNext;
|
Package* fFileNameHashTableNext;
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011, Ingo Weinhold, [email protected].
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011, Ingo Weinhold, [email protected].
|
|
||||||
* 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
|
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* 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!
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* 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
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "EmptyAttributeDirectoryCookie.h"
|
#include "EmptyAttributeDirectoryCookie.h"
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
|
#include "PackageLinkDirectory.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -30,10 +31,6 @@ PackageLinksDirectory::~PackageLinksDirectory()
|
|||||||
status_t
|
status_t
|
||||||
PackageLinksDirectory::Init(Directory* parent, const char* name)
|
PackageLinksDirectory::Init(Directory* parent, const char* name)
|
||||||
{
|
{
|
||||||
status_t error = fPackageFamilies.Init();
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
|
|
||||||
return Directory::Init(parent, name);
|
return Directory::Init(parent, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,26 +95,32 @@ PackageLinksDirectory::OpenAttribute(const char* name, int openMode,
|
|||||||
status_t
|
status_t
|
||||||
PackageLinksDirectory::AddPackage(Package* package)
|
PackageLinksDirectory::AddPackage(Package* package)
|
||||||
{
|
{
|
||||||
// Create a package family -- there might already be one, but since that's
|
// Create a package link directory -- there might already be one, but since
|
||||||
// unlikely, we don't bother to check and recheck later.
|
// that's unlikely, we don't bother to check and recheck later.
|
||||||
PackageFamily* packageFamily = new(std::nothrow) PackageFamily;
|
PackageLinkDirectory* linkDirectory
|
||||||
if (packageFamily == NULL)
|
= new(std::nothrow) PackageLinkDirectory;
|
||||||
|
if (linkDirectory == NULL)
|
||||||
return B_NO_MEMORY;
|
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)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
// add the family
|
// add the link directory
|
||||||
NodeWriteLocker writeLocker(this);
|
NodeWriteLocker writeLocker(this);
|
||||||
if (PackageFamily* otherPackageFamily
|
if (Node* child = FindChild(linkDirectory->Name())) {
|
||||||
= fPackageFamilies.Lookup(packageFamily->Name())) {
|
PackageLinkDirectory* otherLinkDirectory
|
||||||
packageFamily->RemovePackage(package);
|
= dynamic_cast<PackageLinkDirectory*>(child);
|
||||||
packageFamily = otherPackageFamily;
|
if (otherLinkDirectory != NULL)
|
||||||
packageFamily->AddPackage(package);
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
|
|
||||||
|
linkDirectory->RemovePackage(package);
|
||||||
|
linkDirectory = otherLinkDirectory;
|
||||||
|
linkDirectory->AddPackage(package);
|
||||||
} else
|
} else
|
||||||
fPackageFamilies.Insert(packageFamilyDeleter.Detach());
|
AddChild(linkDirectory);
|
||||||
|
|
||||||
// TODO:...
|
// TODO:...
|
||||||
|
|
||||||
@@ -128,18 +131,20 @@ PackageLinksDirectory::AddPackage(Package* package)
|
|||||||
void
|
void
|
||||||
PackageLinksDirectory::RemovePackage(Package* package)
|
PackageLinksDirectory::RemovePackage(Package* package)
|
||||||
{
|
{
|
||||||
NodeWriteLocker writeLocker(this);
|
// get the package's link directory and remove the package from it
|
||||||
|
PackageLinkDirectory* linkDirectory = package->LinkDirectory();
|
||||||
PackageFamily* packageFamily = package->Family();
|
if (linkDirectory == NULL)
|
||||||
if (packageFamily == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
packageFamily->RemovePackage(package);
|
BReference<PackageLinkDirectory> linkDirectoryReference(linkDirectory);
|
||||||
|
|
||||||
if (packageFamily->IsEmpty()) {
|
NodeWriteLocker writeLocker(this);
|
||||||
fPackageFamilies.Remove(packageFamily);
|
|
||||||
delete packageFamily;
|
linkDirectory->RemovePackage(package);
|
||||||
}
|
|
||||||
|
// if empty, remove the link directory itself
|
||||||
|
if (linkDirectory->IsEmpty())
|
||||||
|
RemoveChild(linkDirectory);
|
||||||
|
|
||||||
// TODO:...
|
// TODO:...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
#include "PackageFamily.h"
|
|
||||||
|
|
||||||
|
class Package;
|
||||||
|
|
||||||
|
|
||||||
class PackageLinksDirectory : public Directory {
|
class PackageLinksDirectory : public Directory {
|
||||||
@@ -33,7 +35,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
timespec fModifiedTime;
|
timespec fModifiedTime;
|
||||||
PackageFamilyHashTable fPackageFamilies;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user