packagefs: Share string instances globally
Introduce a class String which refers to shared private data that is registered in a global hash table (in class StringPool) and use the class consequently. This eliminates duplicate allocations for the same string and also speeds up tests for equality. There's quite a bit overhead for the management structures (apparently even more than for the string data itself), but due to almost all strings being used multiple times this still almost halves the memory usage for string data.
This commit is contained in:
parent
1848fdc329
commit
d07c930c1e
@ -53,6 +53,9 @@ HAIKU_PACKAGE_FS_SOURCES =
|
||||
Resolvable.cpp
|
||||
ResolvableFamily.cpp
|
||||
SizeIndex.cpp
|
||||
String.cpp
|
||||
StringConstants.cpp
|
||||
StringPool.cpp
|
||||
UnpackingAttributeCookie.cpp
|
||||
UnpackingAttributeDirectoryCookie.cpp
|
||||
UnpackingDirectory.cpp
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "String.h"
|
||||
|
||||
|
||||
class AttributeIndex;
|
||||
class AttributeIndexTreeValue;
|
||||
@ -28,12 +30,12 @@ public:
|
||||
AttributeIndexTreeValue* Cookie() const
|
||||
{ return fCookie; }
|
||||
|
||||
const char* IndexName() const
|
||||
const String& IndexName() const
|
||||
{ return fIndexName; }
|
||||
|
||||
private:
|
||||
AttributeIndex* fIndex;
|
||||
const char* fIndexName;
|
||||
const String& fIndexName;
|
||||
uint32 fIndexType;
|
||||
AttributeIndexTreeValue* fCookie;
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
Index::Index()
|
||||
:
|
||||
fVolume(NULL),
|
||||
fName(NULL),
|
||||
fName(),
|
||||
fType(0),
|
||||
fKeyLength(0),
|
||||
fFixedKeyLength(true)
|
||||
@ -28,7 +28,6 @@ Index::Index()
|
||||
|
||||
Index::~Index()
|
||||
{
|
||||
free(fName);
|
||||
}
|
||||
|
||||
|
||||
@ -36,8 +35,7 @@ status_t
|
||||
Index::Init(Volume* volume, const char* name, uint32 type, bool fixedKeyLength,
|
||||
size_t keyLength)
|
||||
{
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
if (!fName.SetTo(name))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fVolume = volume;
|
||||
|
@ -13,6 +13,9 @@
|
||||
#include <util/khash.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "String.h"
|
||||
#include "StringKey.h"
|
||||
|
||||
|
||||
class AbstractIndexIterator;
|
||||
class IndexIterator;
|
||||
@ -34,7 +37,7 @@ public:
|
||||
|
||||
Volume* GetVolume() const { return fVolume; }
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
const String& Name() const { return fName; }
|
||||
uint32 Type() const { return fType; }
|
||||
bool HasFixedKeyLength() const
|
||||
{ return fFixedKeyLength; }
|
||||
@ -64,7 +67,7 @@ protected:
|
||||
protected:
|
||||
Index* fHashLink;
|
||||
Volume* fVolume;
|
||||
char* fName;
|
||||
String fName;
|
||||
uint32 fType;
|
||||
size_t fKeyLength;
|
||||
bool fFixedKeyLength;
|
||||
@ -98,22 +101,22 @@ private:
|
||||
|
||||
|
||||
struct IndexHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef StringKey KeyType;
|
||||
typedef Index ValueType;
|
||||
|
||||
size_t HashKey(const char* key) const
|
||||
size_t HashKey(const StringKey& key) const
|
||||
{
|
||||
return key != NULL ? hash_hash_string(key) : 0;
|
||||
return key.Hash();
|
||||
}
|
||||
|
||||
size_t Hash(const Index* value) const
|
||||
{
|
||||
return HashKey(value->Name());
|
||||
return value->Name().Hash();
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const Index* value) const
|
||||
bool Compare(const StringKey& key, const Index* value) const
|
||||
{
|
||||
return strcmp(value->Name(), key) == 0;
|
||||
return key == value->Name();
|
||||
}
|
||||
|
||||
Index*& GetLink(Index* value) const
|
||||
|
@ -84,7 +84,7 @@ struct Query::QueryPolicy {
|
||||
|
||||
static status_t IndexSetTo(Index& index, const char* attribute)
|
||||
{
|
||||
index.index = index.query->fVolume->FindIndex(attribute);
|
||||
index.index = index.query->fVolume->FindIndex(StringKey(attribute));
|
||||
return index.index != NULL ? B_OK : B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
@ -181,7 +181,8 @@ struct Query::QueryPolicy {
|
||||
{
|
||||
// TODO: Creating a cookie is quite a bit of overhead.
|
||||
AttributeCookie* cookie;
|
||||
status_t error = node->OpenAttribute(attribute, O_RDONLY, cookie);
|
||||
status_t error = node->OpenAttribute(StringKey(attribute), O_RDONLY,
|
||||
cookie);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "GlobalFactory.h"
|
||||
#include "Query.h"
|
||||
#include "PackageFSRoot.h"
|
||||
#include "StringConstants.h"
|
||||
#include "StringPool.h"
|
||||
#include "Utils.h"
|
||||
#include "Volume.h"
|
||||
|
||||
@ -181,7 +183,8 @@ packagefs_lookup(fs_volume* fsVolume, fs_vnode* fsDir, const char* entryName,
|
||||
|
||||
// resolve normal entries -- look up the node
|
||||
NodeReadLocker dirLocker(dir);
|
||||
Node* node = dynamic_cast<Directory*>(dir)->FindChild(entryName);
|
||||
String entryNameString;
|
||||
Node* node = dynamic_cast<Directory*>(dir)->FindChild(StringKey(entryName));
|
||||
if (node == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
BReference<Node> nodeReference(node);
|
||||
@ -792,7 +795,7 @@ packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
|
||||
return error;
|
||||
|
||||
AttributeCookie* cookie;
|
||||
error = node->OpenAttribute(name, openMode, cookie);
|
||||
error = node->OpenAttribute(StringKey(name), openMode, cookie);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -976,7 +979,7 @@ packagefs_read_index_stat(fs_volume* fsVolume, const char* name,
|
||||
|
||||
FUNCTION("volume: %p, name: \"%s\", stat: %p\n", volume, name, stat);
|
||||
|
||||
Index* index = volume->FindIndex(name);
|
||||
Index* index = volume->FindIndex(StringKey(name));
|
||||
if (index == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
@ -1093,9 +1096,25 @@ packagefs_std_ops(int32 op, ...)
|
||||
init_debugging();
|
||||
PRINT("package_std_ops(): B_MODULE_INIT\n");
|
||||
|
||||
status_t error = GlobalFactory::CreateDefault();
|
||||
status_t error = StringPool::Init();
|
||||
if (error != B_OK) {
|
||||
ERROR("Failed to init StringPool\n");
|
||||
exit_debugging();
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!StringConstants::Init()) {
|
||||
ERROR("Failed to init string constants\n");
|
||||
StringPool::Cleanup();
|
||||
exit_debugging();
|
||||
return error;
|
||||
}
|
||||
|
||||
error = GlobalFactory::CreateDefault();
|
||||
if (error != B_OK) {
|
||||
ERROR("Failed to init GlobalFactory\n");
|
||||
StringConstants::Cleanup();
|
||||
StringPool::Cleanup();
|
||||
exit_debugging();
|
||||
return error;
|
||||
}
|
||||
@ -1104,6 +1123,8 @@ packagefs_std_ops(int32 op, ...)
|
||||
if (error != B_OK) {
|
||||
ERROR("Failed to init PackageFSRoot\n");
|
||||
GlobalFactory::DeleteDefault();
|
||||
StringConstants::Cleanup();
|
||||
StringPool::Cleanup();
|
||||
exit_debugging();
|
||||
return error;
|
||||
}
|
||||
@ -1116,6 +1137,8 @@ packagefs_std_ops(int32 op, ...)
|
||||
PRINT("package_std_ops(): B_MODULE_UNINIT\n");
|
||||
PackageFSRoot::GlobalUninit();
|
||||
GlobalFactory::DeleteDefault();
|
||||
StringConstants::Cleanup();
|
||||
StringPool::Cleanup();
|
||||
exit_debugging();
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -16,11 +16,7 @@
|
||||
#include "AttributeCookie.h"
|
||||
#include "DebugSupport.h"
|
||||
#include "Package.h"
|
||||
|
||||
|
||||
static const char* const kAttributeNames[AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT] = {
|
||||
"SYS:PACKAGE"
|
||||
};
|
||||
#include "StringConstants.h"
|
||||
|
||||
|
||||
class AutoPackageAttributeCookie : public AttributeCookie {
|
||||
@ -81,11 +77,11 @@ private:
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
AutoPackageAttributes::AttributeForName(const char* name,
|
||||
AutoPackageAttributes::AttributeForName(const StringKey& name,
|
||||
AutoPackageAttribute& _attribute)
|
||||
{
|
||||
for (int i = 0; i < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT; i++) {
|
||||
if (strcmp(name, kAttributeNames[i]) == 0) {
|
||||
if (name == StringConstants::Get().kAutoPackageAttributeNames[i]) {
|
||||
_attribute = (AutoPackageAttribute)i;
|
||||
return true;
|
||||
}
|
||||
@ -95,12 +91,11 @@ AutoPackageAttributes::AttributeForName(const char* name,
|
||||
}
|
||||
|
||||
|
||||
/*static*/ const char*
|
||||
/*static*/ const String&
|
||||
AutoPackageAttributes::NameForAttribute(AutoPackageAttribute attribute)
|
||||
{
|
||||
if (attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
|
||||
return kAttributeNames[attribute];
|
||||
return NULL;
|
||||
ASSERT(attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT);
|
||||
return StringConstants::Get().kAutoPackageAttributeNames[attribute];
|
||||
}
|
||||
|
||||
|
||||
@ -124,7 +119,7 @@ AutoPackageAttributes::GetAttributeValue(const Package* package,
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
AutoPackageAttributes::OpenCookie(Package* package, const char* name,
|
||||
AutoPackageAttributes::OpenCookie(Package* package, const StringKey& name,
|
||||
int openMode, AttributeCookie*& _cookie)
|
||||
{
|
||||
if (package == NULL)
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "StringKey.h"
|
||||
|
||||
|
||||
class AttributeCookie;
|
||||
class Package;
|
||||
@ -22,16 +24,17 @@ enum AutoPackageAttribute {
|
||||
|
||||
|
||||
struct AutoPackageAttributes {
|
||||
static bool AttributeForName(const char* name,
|
||||
static bool AttributeForName(const StringKey& name,
|
||||
AutoPackageAttribute& _attribute);
|
||||
static const char* NameForAttribute(
|
||||
static const String& NameForAttribute(
|
||||
AutoPackageAttribute attribute);
|
||||
static const void* GetAttributeValue(const Package* package,
|
||||
AutoPackageAttribute attribute,
|
||||
off_t& _size, uint32& _type);
|
||||
|
||||
static status_t OpenCookie(Package* package, const char* name,
|
||||
int openMode, AttributeCookie*& _cookie);
|
||||
static status_t OpenCookie(Package* package,
|
||||
const StringKey& name, int openMode,
|
||||
AttributeCookie*& _cookie);
|
||||
};
|
||||
|
||||
|
||||
|
@ -31,9 +31,9 @@ Directory::~Directory()
|
||||
|
||||
|
||||
status_t
|
||||
Directory::Init(Directory* parent, const char* name, uint32 flags)
|
||||
Directory::Init(Directory* parent, const String& name)
|
||||
{
|
||||
status_t error = Node::Init(parent, name, flags);
|
||||
status_t error = Node::Init(parent, name);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -104,7 +104,7 @@ Directory::RemoveChild(Node* node)
|
||||
|
||||
|
||||
Node*
|
||||
Directory::FindChild(const char* name)
|
||||
Directory::FindChild(const StringKey& name)
|
||||
{
|
||||
return fChildTable.Lookup(name);
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ public:
|
||||
Directory(ino_t id);
|
||||
virtual ~Directory();
|
||||
|
||||
virtual status_t Init(Directory* parent, const char* name,
|
||||
uint32 flags);
|
||||
virtual status_t Init(Directory* parent, const String& name);
|
||||
|
||||
virtual mode_t Mode() const;
|
||||
virtual off_t FileSize() const;
|
||||
@ -41,7 +40,7 @@ public:
|
||||
|
||||
void AddChild(Node* node);
|
||||
void RemoveChild(Node* node);
|
||||
Node* FindChild(const char* name);
|
||||
Node* FindChild(const StringKey& name);
|
||||
|
||||
inline Node* FirstChild() const;
|
||||
inline Node* NextChild(Node* node) const;
|
||||
|
@ -17,7 +17,7 @@ Node::Node(ino_t id)
|
||||
:
|
||||
fID(id),
|
||||
fParent(NULL),
|
||||
fName(NULL),
|
||||
fName(),
|
||||
fFlags(0)
|
||||
{
|
||||
rw_lock_init(&fLock, "packagefs node");
|
||||
@ -26,29 +26,16 @@ Node::Node(ino_t id)
|
||||
|
||||
Node::~Node()
|
||||
{
|
||||
if ((fFlags & NODE_FLAG_OWNS_NAME) != 0)
|
||||
free(fName);
|
||||
|
||||
rw_lock_destroy(&fLock);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Node::Init(Directory* parent, const char* name, uint32 flags)
|
||||
Node::Init(Directory* parent, const String& name)
|
||||
{
|
||||
fParent = parent;
|
||||
fFlags = flags;
|
||||
|
||||
if ((flags & NODE_FLAG_CONST_NAME) != 0
|
||||
|| (flags & NODE_FLAG_KEEP_NAME) != 0) {
|
||||
fName = const_cast<char*>(name);
|
||||
} else {
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
fFlags |= NODE_FLAG_OWNS_NAME;
|
||||
}
|
||||
|
||||
fName = name;
|
||||
fFlags = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -110,7 +97,8 @@ Node::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
|
||||
|
||||
|
||||
status_t
|
||||
Node::OpenAttribute(const char* name, int openMode, AttributeCookie*& _cookie)
|
||||
Node::OpenAttribute(const StringKey& name, int openMode,
|
||||
AttributeCookie*& _cookie)
|
||||
{
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
@ -124,7 +112,7 @@ Node::IndexAttribute(AttributeIndexer* indexer)
|
||||
|
||||
|
||||
void*
|
||||
Node::IndexCookieForAttribute(const char* name) const
|
||||
Node::IndexCookieForAttribute(const StringKey& name) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include <util/khash.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "String.h"
|
||||
#include "StringKey.h"
|
||||
|
||||
|
||||
class AttributeCookie;
|
||||
class AttributeDirectoryCookie;
|
||||
@ -26,14 +29,7 @@ class PackageNode;
|
||||
|
||||
// node flags
|
||||
enum {
|
||||
NODE_FLAG_KEEP_NAME = 0x01,
|
||||
// Init(): Take over ownership of the given name (i.e. free in
|
||||
// destructor).
|
||||
NODE_FLAG_CONST_NAME = 0x02,
|
||||
// Init(): The given name is a constant that won't go away during the
|
||||
// lifetime of the object. No need to copy.
|
||||
NODE_FLAG_OWNS_NAME = NODE_FLAG_KEEP_NAME,
|
||||
NODE_FLAG_KNOWN_TO_VFS = 0x04,
|
||||
NODE_FLAG_KNOWN_TO_VFS = 0x01
|
||||
// internal flag
|
||||
};
|
||||
|
||||
@ -50,17 +46,14 @@ public:
|
||||
|
||||
ino_t ID() const { return fID; }
|
||||
Directory* Parent() const { return fParent; }
|
||||
const char* Name() const { return fName; }
|
||||
const String& Name() const { return fName; }
|
||||
|
||||
Node*& NameHashTableNext()
|
||||
{ return fNameHashTableNext; }
|
||||
Node*& IDHashTableNext()
|
||||
{ return fIDHashTableNext; }
|
||||
|
||||
virtual status_t Init(Directory* parent, const char* name,
|
||||
uint32 flags);
|
||||
// If specified to keep the name, it does
|
||||
// so also on error.
|
||||
virtual status_t Init(Directory* parent, const String& name);
|
||||
|
||||
virtual status_t VFSInit(dev_t deviceID);
|
||||
// base class version must be called on
|
||||
@ -87,17 +80,18 @@ public:
|
||||
|
||||
virtual status_t OpenAttributeDirectory(
|
||||
AttributeDirectoryCookie*& _cookie);
|
||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||
AttributeCookie*& _cookie);
|
||||
virtual status_t OpenAttribute(const StringKey& name,
|
||||
int openMode, AttributeCookie*& _cookie);
|
||||
|
||||
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
virtual void* IndexCookieForAttribute(const StringKey& name)
|
||||
const;
|
||||
|
||||
protected:
|
||||
rw_lock fLock;
|
||||
ino_t fID;
|
||||
Directory* fParent;
|
||||
char* fName;
|
||||
String fName;
|
||||
Node* fNameHashTableNext;
|
||||
Node* fIDHashTableNext;
|
||||
uint32 fFlags;
|
||||
@ -143,22 +137,22 @@ Node::IsKnownToVFS() const
|
||||
|
||||
|
||||
struct NodeNameHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef StringKey KeyType;
|
||||
typedef Node ValueType;
|
||||
|
||||
size_t HashKey(const char* key) const
|
||||
size_t HashKey(const StringKey& key) const
|
||||
{
|
||||
return hash_hash_string(key);
|
||||
return key.Hash();
|
||||
}
|
||||
|
||||
size_t Hash(const Node* value) const
|
||||
{
|
||||
return HashKey(value->Name());
|
||||
return value->Name().Hash();
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const Node* value) const
|
||||
bool Compare(const StringKey& key, const Node* value) const
|
||||
{
|
||||
return strcmp(value->Name(), key) == 0;
|
||||
return key == value->Name();
|
||||
}
|
||||
|
||||
Node*& GetLink(Node* value) const
|
||||
|
@ -36,7 +36,7 @@ OldUnpackingNodeAttributes::FileSize() const
|
||||
|
||||
|
||||
void*
|
||||
OldUnpackingNodeAttributes::IndexCookieForAttribute(const char* name) const
|
||||
OldUnpackingNodeAttributes::IndexCookieForAttribute(const StringKey& name) const
|
||||
{
|
||||
return fPackageNode != NULL
|
||||
? fPackageNode->IndexCookieForAttribute(name) : NULL;
|
||||
|
@ -19,7 +19,8 @@ public:
|
||||
|
||||
virtual timespec ModifiedTime() const;
|
||||
virtual off_t FileSize() const;
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
virtual void* IndexCookieForAttribute(const StringKey& name)
|
||||
const;
|
||||
|
||||
private:
|
||||
PackageNode* fPackageNode;
|
||||
|
@ -80,7 +80,7 @@ UnpackingAttributeCookie::~UnpackingAttributeCookie()
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
UnpackingAttributeCookie::Open(PackageNode* packageNode, const char* name,
|
||||
UnpackingAttributeCookie::Open(PackageNode* packageNode, const StringKey& name,
|
||||
int openMode, AttributeCookie*& _cookie)
|
||||
{
|
||||
if (packageNode == NULL)
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include "AttributeCookie.h"
|
||||
#include "StringKey.h"
|
||||
|
||||
|
||||
class AttributeIndexer;
|
||||
@ -23,8 +24,9 @@ public:
|
||||
int openMode);
|
||||
virtual ~UnpackingAttributeCookie();
|
||||
|
||||
static status_t Open(PackageNode* packageNode, const char* name,
|
||||
int openMode, AttributeCookie*& _cookie);
|
||||
static status_t Open(PackageNode* packageNode,
|
||||
const StringKey& name, int openMode,
|
||||
AttributeCookie*& _cookie);
|
||||
|
||||
virtual status_t ReadAttribute(off_t offset, void* buffer,
|
||||
size_t* bufferSize);
|
||||
|
@ -75,12 +75,10 @@ UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
|
||||
}
|
||||
|
||||
// get the attribute name
|
||||
const char* name;
|
||||
if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) {
|
||||
name = AutoPackageAttributes::NameForAttribute(
|
||||
(AutoPackageAttribute)fState);
|
||||
} else
|
||||
name = fAttribute->Name();
|
||||
const String& name = fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT
|
||||
? AutoPackageAttributes::NameForAttribute(
|
||||
(AutoPackageAttribute)fState)
|
||||
: fAttribute->Name();
|
||||
|
||||
// fill in the entry name -- checks whether the entry fits into the
|
||||
// buffer
|
||||
|
@ -170,7 +170,7 @@ UnpackingDirectory::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
|
||||
|
||||
|
||||
status_t
|
||||
UnpackingDirectory::OpenAttribute(const char* name, int openMode,
|
||||
UnpackingDirectory::OpenAttribute(const StringKey& name, int openMode,
|
||||
AttributeCookie*& _cookie)
|
||||
{
|
||||
return UnpackingAttributeCookie::Open(fPackageDirectories.Head(), name,
|
||||
@ -187,7 +187,7 @@ UnpackingDirectory::IndexAttribute(AttributeIndexer* indexer)
|
||||
|
||||
|
||||
void*
|
||||
UnpackingDirectory::IndexCookieForAttribute(const char* name) const
|
||||
UnpackingDirectory::IndexCookieForAttribute(const StringKey& name) const
|
||||
{
|
||||
if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
|
||||
return packageDirectory->IndexCookieForAttribute(name);
|
||||
|
@ -36,11 +36,12 @@ public:
|
||||
|
||||
virtual status_t OpenAttributeDirectory(
|
||||
AttributeDirectoryCookie*& _cookie);
|
||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||
AttributeCookie*& _cookie);
|
||||
virtual status_t OpenAttribute(const StringKey& name,
|
||||
int openMode, AttributeCookie*& _cookie);
|
||||
|
||||
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
virtual void* IndexCookieForAttribute(const StringKey& name)
|
||||
const;
|
||||
|
||||
private:
|
||||
PackageDirectoryList fPackageDirectories;
|
||||
|
@ -216,7 +216,7 @@ UnpackingLeafNode::CloneTransferPackageNodes(ino_t id, UnpackingNode*& _newNode)
|
||||
if (clone == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = clone->Init(Parent(), Name(), 0);
|
||||
status_t error = clone->Init(Parent(), Name());
|
||||
if (error != B_OK) {
|
||||
delete clone;
|
||||
return error;
|
||||
@ -260,8 +260,8 @@ UnpackingLeafNode::ReadSymlink(void* buffer, size_t* bufferSize)
|
||||
if (packageNode == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
const char* linkPath = packageNode->SymlinkPath();
|
||||
if (linkPath == NULL) {
|
||||
const String& linkPath = packageNode->SymlinkPath();
|
||||
if (linkPath[0] == '\0') {
|
||||
*bufferSize = 0;
|
||||
return B_OK;
|
||||
}
|
||||
@ -283,7 +283,7 @@ UnpackingLeafNode::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
|
||||
|
||||
|
||||
status_t
|
||||
UnpackingLeafNode::OpenAttribute(const char* name, int openMode,
|
||||
UnpackingLeafNode::OpenAttribute(const StringKey& name, int openMode,
|
||||
AttributeCookie*& _cookie)
|
||||
{
|
||||
return UnpackingAttributeCookie::Open(_ActivePackageNode(), name, openMode,
|
||||
@ -300,7 +300,7 @@ UnpackingLeafNode::IndexAttribute(AttributeIndexer* indexer)
|
||||
|
||||
|
||||
void*
|
||||
UnpackingLeafNode::IndexCookieForAttribute(const char* name) const
|
||||
UnpackingLeafNode::IndexCookieForAttribute(const StringKey& name) const
|
||||
{
|
||||
if (PackageLeafNode* packageNode = _ActivePackageNode())
|
||||
return packageNode->IndexCookieForAttribute(name);
|
||||
|
@ -48,11 +48,12 @@ public:
|
||||
|
||||
virtual status_t OpenAttributeDirectory(
|
||||
AttributeDirectoryCookie*& _cookie);
|
||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||
AttributeCookie*& _cookie);
|
||||
virtual status_t OpenAttribute(const StringKey& name,
|
||||
int openMode, AttributeCookie*& _cookie);
|
||||
|
||||
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
virtual void* IndexCookieForAttribute(const StringKey& name)
|
||||
const;
|
||||
|
||||
private:
|
||||
inline PackageLeafNode* _ActivePackageNode() const;
|
||||
|
@ -88,8 +88,6 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
|
||||
RETURN_ERROR(B_BAD_DATA);
|
||||
}
|
||||
|
||||
status_t error;
|
||||
|
||||
// get the file mode -- filter out write permissions
|
||||
mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH);
|
||||
|
||||
@ -100,17 +98,16 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
|
||||
node = new(std::nothrow) PackageFile(fPackage, mode, entry->Data());
|
||||
} else if (S_ISLNK(mode)) {
|
||||
// symlink
|
||||
String path;
|
||||
if (!path.SetTo(entry->SymlinkPath()))
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
PackageSymlink* symlink = new(std::nothrow) PackageSymlink(
|
||||
fPackage, mode);
|
||||
if (symlink == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
error = symlink->SetSymlinkPath(entry->SymlinkPath());
|
||||
if (error != B_OK) {
|
||||
delete symlink;
|
||||
return error;
|
||||
}
|
||||
|
||||
symlink->SetSymlinkPath(path);
|
||||
node = symlink;
|
||||
} else if (S_ISDIR(mode)) {
|
||||
// directory
|
||||
@ -122,7 +119,11 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
BReference<PackageNode> nodeReference(node, true);
|
||||
|
||||
error = node->Init(parentDir, entry->Name());
|
||||
String entryName;
|
||||
if (!entryName.SetTo(entry->Name()))
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
status_t error = node->Init(parentDir, entryName);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
@ -147,17 +148,16 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
|
||||
|
||||
PackageNode* node = (PackageNode*)entry->UserToken();
|
||||
|
||||
String name;
|
||||
if (!name.SetTo(attribute->Name()))
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
PackageNodeAttribute* nodeAttribute = new(std::nothrow)
|
||||
PackageNodeAttribute(attribute->Type(), attribute->Data());
|
||||
if (nodeAttribute == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY)
|
||||
|
||||
status_t error = nodeAttribute->Init(attribute->Name());
|
||||
if (error != B_OK) {
|
||||
delete nodeAttribute;
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
nodeAttribute->Init(name);
|
||||
node->AddAttribute(nodeAttribute);
|
||||
|
||||
return B_OK;
|
||||
@ -173,10 +173,22 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
|
||||
{
|
||||
switch (value.attributeID) {
|
||||
case B_PACKAGE_INFO_NAME:
|
||||
return fPackage->SetName(value.string);
|
||||
{
|
||||
String name;
|
||||
if (!name.SetTo(value.string))
|
||||
return B_NO_MEMORY;
|
||||
fPackage->SetName(name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case B_PACKAGE_INFO_INSTALL_PATH:
|
||||
return fPackage->SetInstallPath(value.string);
|
||||
{
|
||||
String path;
|
||||
if (!path.SetTo(value.string))
|
||||
return B_NO_MEMORY;
|
||||
fPackage->SetInstallPath(path);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case B_PACKAGE_INFO_VERSION:
|
||||
{
|
||||
@ -303,9 +315,9 @@ private:
|
||||
Package::Package(::Volume* volume, dev_t deviceID, ino_t nodeID)
|
||||
:
|
||||
fVolume(volume),
|
||||
fFileName(NULL),
|
||||
fName(NULL),
|
||||
fInstallPath(NULL),
|
||||
fFileName(),
|
||||
fName(),
|
||||
fInstallPath(),
|
||||
fVersion(NULL),
|
||||
fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
|
||||
fLinkDirectory(NULL),
|
||||
@ -329,9 +341,6 @@ Package::~Package()
|
||||
while (Dependency* dependency = fDependencies.RemoveHead())
|
||||
delete dependency;
|
||||
|
||||
free(fFileName);
|
||||
free(fName);
|
||||
free(fInstallPath);
|
||||
delete fVersion;
|
||||
|
||||
mutex_destroy(&fLock);
|
||||
@ -341,8 +350,7 @@ Package::~Package()
|
||||
status_t
|
||||
Package::Init(const char* fileName)
|
||||
{
|
||||
fFileName = strdup(fileName);
|
||||
if (fFileName == NULL)
|
||||
if (!fFileName.SetTo(fileName))
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
return B_OK;
|
||||
@ -379,31 +387,17 @@ Package::Load()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Package::SetName(const char* name)
|
||||
void
|
||||
Package::SetName(const String& name)
|
||||
{
|
||||
if (fName != NULL)
|
||||
free(fName);
|
||||
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
return B_OK;
|
||||
fName = name;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Package::SetInstallPath(const char* installPath)
|
||||
void
|
||||
Package::SetInstallPath(const String& installPath)
|
||||
{
|
||||
if (fInstallPath != NULL)
|
||||
free(fInstallPath);
|
||||
|
||||
fInstallPath = strdup(installPath);
|
||||
if (fInstallPath == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
return B_OK;
|
||||
fInstallPath = installPath;
|
||||
}
|
||||
|
||||
|
||||
@ -463,14 +457,14 @@ Package::Open()
|
||||
// open the file
|
||||
fFD = openat(fVolume->PackagesDirectoryFD(), fFileName, O_RDONLY);
|
||||
if (fFD < 0) {
|
||||
ERROR("Failed to open package file \"%s\"\n", fFileName);
|
||||
ERROR("Failed to open package file \"%s\"\n", fFileName.Data());
|
||||
return errno;
|
||||
}
|
||||
|
||||
// stat it to verify that it's still the same file
|
||||
struct stat st;
|
||||
if (fstat(fFD, &st) < 0) {
|
||||
ERROR("Failed to stat package file \"%s\"\n", fFileName);
|
||||
ERROR("Failed to stat package file \"%s\"\n", fFileName.Data());
|
||||
close(fFD);
|
||||
fFD = -1;
|
||||
return errno;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "Dependency.h"
|
||||
#include "PackageNode.h"
|
||||
#include "Resolvable.h"
|
||||
#include "String.h"
|
||||
|
||||
|
||||
using BPackageKit::BPackageArchitecture;
|
||||
@ -40,18 +41,18 @@ public:
|
||||
status_t Load();
|
||||
|
||||
::Volume* Volume() const { return fVolume; }
|
||||
const char* FileName() const { return fFileName; }
|
||||
const String& FileName() const { return fFileName; }
|
||||
|
||||
status_t SetName(const char* name);
|
||||
const char* Name() const { return fName; }
|
||||
void SetName(const String& name);
|
||||
const String& Name() const { return fName; }
|
||||
|
||||
dev_t DeviceID() const
|
||||
{ return fDeviceID; }
|
||||
ino_t NodeID() const
|
||||
{ return fNodeID; }
|
||||
|
||||
status_t SetInstallPath(const char* installPath);
|
||||
const char* InstallPath() const { return fInstallPath; }
|
||||
void SetInstallPath(const String& installPath);
|
||||
const String& InstallPath() const { return fInstallPath; }
|
||||
|
||||
void SetVersion(::Version* version);
|
||||
// takes over object ownership
|
||||
@ -94,9 +95,9 @@ private:
|
||||
private:
|
||||
mutex fLock;
|
||||
::Volume* fVolume;
|
||||
char* fFileName;
|
||||
char* fName;
|
||||
char* fInstallPath;
|
||||
String fFileName;
|
||||
String fName;
|
||||
String fInstallPath;
|
||||
::Version* fVersion;
|
||||
BPackageArchitecture fArchitecture;
|
||||
PackageLinkDirectory* fLinkDirectory;
|
||||
@ -145,7 +146,7 @@ struct PackageFileNameHashDefinition {
|
||||
|
||||
size_t Hash(const Package* value) const
|
||||
{
|
||||
return HashKey(value->FileName());
|
||||
return value->FileName().Hash();
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const Package* value) const
|
||||
|
@ -19,10 +19,10 @@ PackageLeafNode::~PackageLeafNode()
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
String
|
||||
PackageLeafNode::SymlinkPath() const
|
||||
{
|
||||
return NULL;
|
||||
return String();
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@ public:
|
||||
PackageLeafNode(Package* package, mode_t mode);
|
||||
virtual ~PackageLeafNode();
|
||||
|
||||
virtual const char* SymlinkPath() const;
|
||||
virtual String SymlinkPath() const;
|
||||
|
||||
virtual status_t Read(off_t offset, void* buffer,
|
||||
size_t* bufferSize);
|
||||
|
@ -17,7 +17,7 @@ PackageNode::PackageNode(Package* package, mode_t mode)
|
||||
:
|
||||
fPackage(package),
|
||||
fParent(NULL),
|
||||
fName(NULL),
|
||||
fName(),
|
||||
fMode(mode),
|
||||
fUserID(0),
|
||||
fGroupID(0)
|
||||
@ -29,19 +29,14 @@ PackageNode::~PackageNode()
|
||||
{
|
||||
while (PackageNodeAttribute* attribute = fAttributes.RemoveHead())
|
||||
delete attribute;
|
||||
|
||||
free(fName);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PackageNode::Init(PackageDirectory* parent, const char* name)
|
||||
PackageNode::Init(PackageDirectory* parent, const String& name)
|
||||
{
|
||||
fParent = parent;
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
fName = name;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -83,11 +78,11 @@ PackageNode::RemoveAttribute(PackageNodeAttribute* attribute)
|
||||
|
||||
|
||||
PackageNodeAttribute*
|
||||
PackageNode::FindAttribute(const char* name) const
|
||||
PackageNode::FindAttribute(const StringKey& name) const
|
||||
{
|
||||
for (PackageNodeAttributeList::ConstIterator it = fAttributes.GetIterator();
|
||||
PackageNodeAttribute* attribute = it.Next();) {
|
||||
if (strcmp(attribute->Name(), name) == 0)
|
||||
if (name == attribute->Name())
|
||||
return attribute;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "IndexedAttributeOwner.h"
|
||||
#include "PackageNodeAttribute.h"
|
||||
#include "StringKey.h"
|
||||
|
||||
|
||||
class AttributeIndexer;
|
||||
@ -34,10 +35,10 @@ public:
|
||||
// must otherwise make sure the package
|
||||
// still exists.
|
||||
PackageDirectory* Parent() const { return fParent; }
|
||||
const char* Name() const { return fName; }
|
||||
const String& Name() const { return fName; }
|
||||
|
||||
virtual status_t Init(PackageDirectory* parent,
|
||||
const char* name);
|
||||
const String& name);
|
||||
|
||||
virtual status_t VFSInit(dev_t deviceID, ino_t nodeID);
|
||||
virtual void VFSUninit();
|
||||
@ -65,11 +66,12 @@ public:
|
||||
const PackageNodeAttributeList& Attributes() const
|
||||
{ return fAttributes; }
|
||||
|
||||
PackageNodeAttribute* FindAttribute(const char* name) const;
|
||||
PackageNodeAttribute* FindAttribute(const StringKey& name) const;
|
||||
|
||||
virtual void UnsetIndexCookie(void* attributeCookie);
|
||||
|
||||
inline void* IndexCookieForAttribute(const char* name) const;
|
||||
inline void* IndexCookieForAttribute(const StringKey& name)
|
||||
const;
|
||||
|
||||
protected:
|
||||
void NonVirtualVFSUninit()
|
||||
@ -80,7 +82,7 @@ protected:
|
||||
protected:
|
||||
Package* fPackage;
|
||||
PackageDirectory* fParent;
|
||||
char* fName;
|
||||
String fName;
|
||||
mode_t fMode;
|
||||
uid_t fUserID;
|
||||
gid_t fGroupID;
|
||||
@ -90,7 +92,7 @@ protected:
|
||||
|
||||
|
||||
void*
|
||||
PackageNode::IndexCookieForAttribute(const char* name) const
|
||||
PackageNode::IndexCookieForAttribute(const StringKey& name) const
|
||||
{
|
||||
PackageNodeAttribute* attribute = FindAttribute(name);
|
||||
return attribute != NULL ? attribute->IndexCookie() : NULL;
|
||||
|
@ -14,7 +14,7 @@ PackageNodeAttribute::PackageNodeAttribute(uint32 type,
|
||||
const BPackageData& data)
|
||||
:
|
||||
fData(data),
|
||||
fName(NULL),
|
||||
fName(),
|
||||
fIndexCookie(NULL),
|
||||
fType(type)
|
||||
{
|
||||
@ -23,13 +23,11 @@ PackageNodeAttribute::PackageNodeAttribute(uint32 type,
|
||||
|
||||
PackageNodeAttribute::~PackageNodeAttribute()
|
||||
{
|
||||
free(fName);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PackageNodeAttribute::Init(const char* name)
|
||||
void
|
||||
PackageNodeAttribute::Init(const String& name)
|
||||
{
|
||||
fName = strdup(name);
|
||||
return fName != NULL ? B_OK : B_NO_MEMORY;
|
||||
fName = name;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <package/hpkg/PackageData.h>
|
||||
|
||||
#include "String.h"
|
||||
|
||||
|
||||
using BPackageKit::BHPKG::BPackageData;
|
||||
|
||||
@ -23,11 +25,11 @@ public:
|
||||
const BPackageData& data);
|
||||
~PackageNodeAttribute();
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
const String& Name() const { return fName; }
|
||||
uint32 Type() const { return fType; }
|
||||
const BPackageData& Data() const { return fData; }
|
||||
|
||||
status_t Init(const char* name);
|
||||
void Init(const String& name);
|
||||
|
||||
void SetIndexCookie(void* cookie)
|
||||
{ fIndexCookie = cookie; }
|
||||
@ -36,7 +38,7 @@ public:
|
||||
|
||||
protected:
|
||||
BPackageData fData;
|
||||
char* fName;
|
||||
String fName;
|
||||
void* fIndexCookie;
|
||||
uint32 fType;
|
||||
};
|
||||
|
@ -13,29 +13,24 @@
|
||||
PackageSymlink::PackageSymlink(Package* package, mode_t mode)
|
||||
:
|
||||
PackageLeafNode(package, mode),
|
||||
fSymlinkPath(NULL)
|
||||
fSymlinkPath()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PackageSymlink::~PackageSymlink()
|
||||
{
|
||||
free(fSymlinkPath);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PackageSymlink::SetSymlinkPath(const char* path)
|
||||
void
|
||||
PackageSymlink::SetSymlinkPath(const String& path)
|
||||
{
|
||||
if (path == NULL)
|
||||
return B_OK;
|
||||
|
||||
fSymlinkPath = strdup(path);
|
||||
return fSymlinkPath != NULL ? B_OK : B_NO_MEMORY;
|
||||
fSymlinkPath = path;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
String
|
||||
PackageSymlink::SymlinkPath() const
|
||||
{
|
||||
return fSymlinkPath;
|
||||
|
@ -14,12 +14,12 @@ public:
|
||||
PackageSymlink(Package* package, mode_t mode);
|
||||
virtual ~PackageSymlink();
|
||||
|
||||
status_t SetSymlinkPath(const char* path);
|
||||
void SetSymlinkPath(const String& path);
|
||||
|
||||
virtual const char* SymlinkPath() const;
|
||||
virtual String SymlinkPath() const;
|
||||
|
||||
private:
|
||||
char* fSymlinkPath;
|
||||
String fSymlinkPath;
|
||||
};
|
||||
|
||||
|
||||
|
@ -14,15 +14,12 @@
|
||||
|
||||
#include "DebugSupport.h"
|
||||
#include "PackageLinksListener.h"
|
||||
#include "StringConstants.h"
|
||||
#include "Utils.h"
|
||||
#include "Version.h"
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
static const char* const kSelfLinkName = ".self";
|
||||
static const char* const kSettingsLinkName = ".settings";
|
||||
|
||||
|
||||
PackageLinkDirectory::PackageLinkDirectory()
|
||||
:
|
||||
Directory(0),
|
||||
@ -63,6 +60,7 @@ PackageLinkDirectory::Init(Directory* parent, Package* package)
|
||||
char* name = (char*)malloc(size);
|
||||
if (name == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter nameDeleter(name);
|
||||
|
||||
memcpy(name, package->Name(), nameLength + 1);
|
||||
if (version != NULL) {
|
||||
@ -70,8 +68,12 @@ PackageLinkDirectory::Init(Directory* parent, Package* package)
|
||||
version->ToString(name + nameLength + 1, size - nameLength - 1);
|
||||
}
|
||||
|
||||
String nameString;
|
||||
if (!nameString.SetTo(name))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// init the directory/node
|
||||
status_t error = Init(parent, name, NODE_FLAG_KEEP_NAME);
|
||||
status_t error = Init(parent, nameString);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
@ -83,9 +85,9 @@ PackageLinkDirectory::Init(Directory* parent, Package* package)
|
||||
|
||||
|
||||
status_t
|
||||
PackageLinkDirectory::Init(Directory* parent, const char* name, uint32 flags)
|
||||
PackageLinkDirectory::Init(Directory* parent, const String& name)
|
||||
{
|
||||
return Directory::Init(parent, name, flags);
|
||||
return Directory::Init(parent, name);
|
||||
}
|
||||
|
||||
|
||||
@ -176,12 +178,13 @@ PackageLinkDirectory::_Update(PackageLinksListener* listener)
|
||||
|
||||
// create/update self and settings link
|
||||
status_t error = _CreateOrUpdateLink(fSelfLink, package,
|
||||
Link::TYPE_INSTALLATION_LOCATION, kSelfLinkName, listener);
|
||||
Link::TYPE_INSTALLATION_LOCATION, StringConstants::Get().kSelfLinkName,
|
||||
listener);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
error = _CreateOrUpdateLink(fSettingsLink, package, Link::TYPE_SETTINGS,
|
||||
kSettingsLinkName, listener);
|
||||
StringConstants::Get().kSettingsLinkName, listener);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
@ -219,7 +222,7 @@ PackageLinkDirectory::_UpdateDependencies(PackageLinksListener* listener)
|
||||
if (link == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = link->Init(this, dependency->Name(), 0);
|
||||
status_t error = link->Init(this, dependency->Name());
|
||||
if (error != B_OK) {
|
||||
delete link;
|
||||
RETURN_ERROR(error);
|
||||
@ -256,14 +259,14 @@ PackageLinkDirectory::_RemoveLink(Link* link, PackageLinksListener* listener)
|
||||
|
||||
status_t
|
||||
PackageLinkDirectory::_CreateOrUpdateLink(Link*& link, Package* package,
|
||||
Link::Type type, const char* name, PackageLinksListener* listener)
|
||||
Link::Type type, const String& name, PackageLinksListener* listener)
|
||||
{
|
||||
if (link == NULL) {
|
||||
link = new(std::nothrow) Link(package, type);
|
||||
if (link == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = link->Init(this, name, NODE_FLAG_CONST_NAME);
|
||||
status_t error = link->Init(this, name);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
|
@ -20,8 +20,7 @@ public:
|
||||
virtual ~PackageLinkDirectory();
|
||||
|
||||
status_t Init(Directory* parent, Package* package);
|
||||
virtual status_t Init(Directory* parent, const char* name,
|
||||
uint32 flags);
|
||||
virtual status_t Init(Directory* parent, const String& name);
|
||||
|
||||
virtual timespec ModifiedTime() const;
|
||||
|
||||
@ -60,7 +59,7 @@ private:
|
||||
|
||||
status_t _CreateOrUpdateLink(Link*& link,
|
||||
Package* package, Link::Type type,
|
||||
const char* name,
|
||||
const String& name,
|
||||
PackageLinksListener* listener);
|
||||
void _RemoveLink(Link* link,
|
||||
PackageLinksListener* listener);
|
||||
|
@ -98,7 +98,7 @@ PackageLinkSymlink::Update(Package* package, PackageLinksListener* listener)
|
||||
|
||||
if (package != NULL) {
|
||||
fLinkPath = package->InstallPath();
|
||||
if (fLinkPath != NULL) {
|
||||
if (fLinkPath[0] != '\0') {
|
||||
if (fType == TYPE_SETTINGS)
|
||||
fLinkPath = ".self/settings";
|
||||
} else {
|
||||
|
@ -17,7 +17,7 @@ Dependency::Dependency(::Package* package)
|
||||
fPackage(package),
|
||||
fFamily(NULL),
|
||||
fResolvable(NULL),
|
||||
fName(NULL),
|
||||
fName(),
|
||||
fVersion(NULL),
|
||||
fVersionOperator(B_PACKAGE_RESOLVABLE_OP_EQUAL)
|
||||
{
|
||||
@ -26,7 +26,6 @@ Dependency::Dependency(::Package* package)
|
||||
|
||||
Dependency::~Dependency()
|
||||
{
|
||||
free(fName);
|
||||
delete fVersion;
|
||||
}
|
||||
|
||||
@ -34,8 +33,7 @@ Dependency::~Dependency()
|
||||
status_t
|
||||
Dependency::Init(const char* name)
|
||||
{
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
if (!fName.SetTo(name))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "String.h"
|
||||
|
||||
|
||||
class DependencyFamily;
|
||||
class Package;
|
||||
@ -52,13 +54,13 @@ public:
|
||||
bool ResolvableCompatibleVersionMatches(
|
||||
Version* resolvableVersion) const;
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
const String& Name() const { return fName; }
|
||||
|
||||
private:
|
||||
::Package* fPackage;
|
||||
DependencyFamily* fFamily;
|
||||
::Resolvable* fResolvable;
|
||||
char* fName;
|
||||
String fName;
|
||||
Version* fVersion;
|
||||
BPackageResolvableOperator fVersionOperator;
|
||||
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
void AddDependenciesToList(
|
||||
ResolvableDependencyList& list) const;
|
||||
|
||||
const char* Name() const;
|
||||
String Name() const;
|
||||
|
||||
bool IsLastDependency(Dependency* dependency) const;
|
||||
|
||||
@ -58,11 +58,11 @@ DependencyFamily::AddDependenciesToList(ResolvableDependencyList& list) const
|
||||
}
|
||||
|
||||
|
||||
inline const char*
|
||||
inline String
|
||||
DependencyFamily::Name() const
|
||||
{
|
||||
Dependency* head = fDependencies.Head();
|
||||
return head != NULL ? head->Name() : NULL;
|
||||
return head != NULL ? head->Name() : String();
|
||||
}
|
||||
|
||||
|
||||
@ -78,22 +78,22 @@ DependencyFamily::IsLastDependency(Dependency* dependency) const
|
||||
|
||||
|
||||
struct DependencyFamilyHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef String KeyType;
|
||||
typedef DependencyFamily ValueType;
|
||||
|
||||
size_t HashKey(const char* key) const
|
||||
size_t HashKey(const String& key) const
|
||||
{
|
||||
return key != NULL ? hash_hash_string(key) : 0;
|
||||
return key.Hash();
|
||||
}
|
||||
|
||||
size_t Hash(const DependencyFamily* value) const
|
||||
{
|
||||
return HashKey(value->Name());
|
||||
return value->Name().Hash();
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const DependencyFamily* value) const
|
||||
bool Compare(const String& key, const DependencyFamily* value) const
|
||||
{
|
||||
return strcmp(value->Name(), key) == 0;
|
||||
return key == value->Name();
|
||||
}
|
||||
|
||||
DependencyFamily*& GetLink(DependencyFamily* value) const
|
||||
|
@ -15,7 +15,7 @@ Resolvable::Resolvable(::Package* package)
|
||||
:
|
||||
fPackage(package),
|
||||
fFamily(NULL),
|
||||
fName(NULL),
|
||||
fName(),
|
||||
fVersion(NULL),
|
||||
fCompatibleVersion(NULL)
|
||||
{
|
||||
@ -24,7 +24,6 @@ Resolvable::Resolvable(::Package* package)
|
||||
|
||||
Resolvable::~Resolvable()
|
||||
{
|
||||
free(fName);
|
||||
delete fVersion;
|
||||
delete fCompatibleVersion;
|
||||
}
|
||||
@ -37,8 +36,7 @@ Resolvable::Init(const char* name, ::Version* version,
|
||||
fVersion = version;
|
||||
fCompatibleVersion = compatibleVersion;
|
||||
|
||||
fName = strdup(name);
|
||||
if (fName == NULL)
|
||||
if (!fName.SetTo(name))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
ResolvableFamily* Family() const
|
||||
{ return fFamily; }
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
const String& Name() const { return fName; }
|
||||
::Version* Version() const { return fVersion; }
|
||||
::Version* CompatibleVersion() const
|
||||
{ return fCompatibleVersion; }
|
||||
@ -50,7 +50,7 @@ public:
|
||||
private:
|
||||
::Package* fPackage;
|
||||
ResolvableFamily* fFamily;
|
||||
char* fName;
|
||||
String fName;
|
||||
::Version* fVersion;
|
||||
::Version* fCompatibleVersion;
|
||||
ResolvableDependencyList fDependencies;
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
|
||||
bool ResolveDependency(Dependency* dependency);
|
||||
|
||||
const char* Name() const;
|
||||
String Name() const;
|
||||
|
||||
bool IsLastResolvable(Resolvable* resolvable) const;
|
||||
|
||||
@ -35,11 +35,11 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline const char*
|
||||
inline String
|
||||
ResolvableFamily::Name() const
|
||||
{
|
||||
Resolvable* head = fResolvables.Head();
|
||||
return head != NULL ? head->Name() : NULL;
|
||||
return head != NULL ? head->Name() : String();
|
||||
}
|
||||
|
||||
|
||||
@ -55,22 +55,22 @@ ResolvableFamily::IsLastResolvable(Resolvable* resolvable) const
|
||||
|
||||
|
||||
struct ResolvableFamilyHashDefinition {
|
||||
typedef const char* KeyType;
|
||||
typedef String KeyType;
|
||||
typedef ResolvableFamily ValueType;
|
||||
|
||||
size_t HashKey(const char* key) const
|
||||
size_t HashKey(const String& key) const
|
||||
{
|
||||
return key != NULL ? hash_hash_string(key) : 0;
|
||||
return key.Hash();
|
||||
}
|
||||
|
||||
size_t Hash(const ResolvableFamily* value) const
|
||||
{
|
||||
return HashKey(value->Name());
|
||||
return value->Name().Hash();
|
||||
}
|
||||
|
||||
bool Compare(const char* key, const ResolvableFamily* value) const
|
||||
bool Compare(const String& key, const ResolvableFamily* value) const
|
||||
{
|
||||
return strcmp(value->Name(), key) == 0;
|
||||
return key == value->Name();
|
||||
}
|
||||
|
||||
ResolvableFamily*& GetLink(ResolvableFamily* value) const
|
||||
|
34
src/add-ons/kernel/file_systems/packagefs/util/String.cpp
Normal file
34
src/add-ons/kernel/file_systems/packagefs/util/String.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "String.h"
|
||||
|
||||
|
||||
bool
|
||||
String::SetToExactLength(const char* string, size_t length)
|
||||
{
|
||||
StringData* data = StringPool::Get(string, length);
|
||||
if (data == NULL)
|
||||
return false;
|
||||
|
||||
fData->ReleaseReference();
|
||||
fData = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
String&
|
||||
String::operator=(const String& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
fData->ReleaseReference();
|
||||
fData = other.fData;
|
||||
fData->AcquireReference();
|
||||
|
||||
return *this;
|
||||
}
|
120
src/add-ons/kernel/file_systems/packagefs/util/String.h
Normal file
120
src/add-ons/kernel/file_systems/packagefs/util/String.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
|
||||
#include "StringPool.h"
|
||||
|
||||
|
||||
class String {
|
||||
public:
|
||||
String();
|
||||
String(const String& other);
|
||||
~String();
|
||||
|
||||
bool SetTo(const char* string);
|
||||
bool SetTo(const char* string, size_t maxLength);
|
||||
bool SetToExactLength(const char* string,
|
||||
size_t length);
|
||||
|
||||
const char* Data() const;
|
||||
uint32 Hash() const;
|
||||
|
||||
bool IsEmpty() const;
|
||||
|
||||
String& operator=(const String& other);
|
||||
|
||||
bool operator==(const String& other) const;
|
||||
bool operator!=(const String& other) const;
|
||||
|
||||
operator const char*() const;
|
||||
|
||||
private:
|
||||
StringData* fData;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
String::String()
|
||||
:
|
||||
fData(StringData::GetEmpty())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
String::String(const String& other)
|
||||
:
|
||||
fData(other.fData)
|
||||
{
|
||||
fData->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
String::~String()
|
||||
{
|
||||
fData->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
String::SetTo(const char* string)
|
||||
{
|
||||
return SetToExactLength(string, strlen(string));
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
String::SetTo(const char* string, size_t maxLength)
|
||||
{
|
||||
return SetToExactLength(string, strnlen(string, maxLength));
|
||||
}
|
||||
|
||||
|
||||
inline const char*
|
||||
String::Data() const
|
||||
{
|
||||
return fData->String();
|
||||
}
|
||||
|
||||
|
||||
inline uint32
|
||||
String::Hash() const
|
||||
{
|
||||
return fData->Hash();
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
String::IsEmpty() const
|
||||
{
|
||||
return fData == StringData::Empty();
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
String::operator==(const String& other) const
|
||||
{
|
||||
return fData == other.fData;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
String::operator!=(const String& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
String::operator const char*() const
|
||||
{
|
||||
return fData->String();
|
||||
}
|
||||
|
||||
|
||||
#endif // STRING_H
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "StringConstants.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
StringConstants StringConstants::sDefaultInstance;
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
StringConstants::Init()
|
||||
{
|
||||
new(&sDefaultInstance) StringConstants;
|
||||
if (!sDefaultInstance._Init()) {
|
||||
sDefaultInstance.Cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
StringConstants::Cleanup()
|
||||
{
|
||||
sDefaultInstance.~StringConstants();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
StringConstants::_Init()
|
||||
{
|
||||
// generate the member variable initializations
|
||||
#define DEFINE_STRING_CONSTANT(name, value) \
|
||||
if (!name.SetTo(value)) \
|
||||
return false;
|
||||
#define DEFINE_STRING_ARRAY_CONSTANT(name, size, ...) \
|
||||
{ \
|
||||
const char* const _values[size] = { __VA_ARGS__ }; \
|
||||
for (size_t i = 0; i < sizeof(_values) / sizeof(_values[0]); \
|
||||
i++) { \
|
||||
if (!name[i].SetTo(_values[i])) \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
#include "StringConstantsPrivate.h"
|
||||
|
||||
#undef DEFINE_STRING_CONSTANT
|
||||
#undef DEFINE_STRING_ARRAY_CONSTANT
|
||||
|
||||
return true;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef STRING_CONSTANTS_H
|
||||
#define STRING_CONSTANTS_H
|
||||
|
||||
|
||||
#include "AutoPackageAttributes.h"
|
||||
// for the kAutoPackageAttributeNames array size
|
||||
#include "String.h"
|
||||
|
||||
|
||||
class StringConstants {
|
||||
public:
|
||||
// generate the member variable declarations
|
||||
#define DEFINE_STRING_CONSTANT(name, value) \
|
||||
String name;
|
||||
#define DEFINE_STRING_ARRAY_CONSTANT(name, size, ...) \
|
||||
String name[size];
|
||||
|
||||
#include "StringConstantsPrivate.h"
|
||||
|
||||
#undef DEFINE_STRING_CONSTANT
|
||||
#undef DEFINE_STRING_ARRAY_CONSTANT
|
||||
|
||||
public:
|
||||
static bool Init();
|
||||
static void Cleanup();
|
||||
|
||||
static const StringConstants& Get()
|
||||
{ return sDefaultInstance; }
|
||||
|
||||
private:
|
||||
bool _Init();
|
||||
|
||||
private:
|
||||
static StringConstants sDefaultInstance;
|
||||
};
|
||||
|
||||
|
||||
#endif // STRING_CONSTANTS_H
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
// This file is included in StringConstants.h and StringConstants.cpp with the
|
||||
// macros DEFINE_STRING[_ARRAY]_CONSTANT() defined to generate the member
|
||||
// variable declarations respectively the initializations.
|
||||
|
||||
|
||||
DEFINE_STRING_CONSTANT(kPackageLinksDirectoryName, "package-links")
|
||||
DEFINE_STRING_CONSTANT(kSelfLinkName, ".self")
|
||||
DEFINE_STRING_CONSTANT(kSettingsLinkName, ".settings")
|
||||
|
||||
DEFINE_STRING_ARRAY_CONSTANT(kAutoPackageAttributeNames,
|
||||
AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT,
|
||||
"SYS:PACKAGE")
|
56
src/add-ons/kernel/file_systems/packagefs/util/StringKey.h
Normal file
56
src/add-ons/kernel/file_systems/packagefs/util/StringKey.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef STRING_KEY_H
|
||||
#define STRING_KEY_H
|
||||
|
||||
|
||||
#include "String.h"
|
||||
|
||||
|
||||
class StringKey {
|
||||
public:
|
||||
StringKey(const ::String& string)
|
||||
:
|
||||
fString(string.Data()),
|
||||
fHash(string.Hash())
|
||||
{
|
||||
}
|
||||
|
||||
explicit StringKey(const char* string)
|
||||
:
|
||||
fString(string),
|
||||
fHash(hash_hash_string(string))
|
||||
{
|
||||
}
|
||||
|
||||
const char* String() const
|
||||
{
|
||||
return fString;
|
||||
}
|
||||
|
||||
uint32 Hash() const
|
||||
{
|
||||
return fHash;
|
||||
}
|
||||
|
||||
bool operator==(const ::String& other) const
|
||||
{
|
||||
if (fHash != other.Hash())
|
||||
return false;
|
||||
return fString == other.Data() || strcmp(fString, other.Data()) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const ::String& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* fString;
|
||||
uint32 fHash;
|
||||
};
|
||||
|
||||
|
||||
#endif // STRING_KEY_H
|
154
src/add-ons/kernel/file_systems/packagefs/util/StringPool.cpp
Normal file
154
src/add-ons/kernel/file_systems/packagefs/util/StringPool.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "StringPool.h"
|
||||
|
||||
#include "DebugSupport.h"
|
||||
|
||||
|
||||
static const size_t kInitialStringTableSize = 128;
|
||||
|
||||
static char sStringsBuffer[sizeof(StringDataHash)];
|
||||
|
||||
StringData StringData::fEmptyString(StringDataKey("", 0));
|
||||
|
||||
mutex StringPool::sLock;
|
||||
StringDataHash* StringPool::sStrings;
|
||||
|
||||
|
||||
// #pragma mark - StringData
|
||||
|
||||
|
||||
/*static*/ void
|
||||
StringData::Init()
|
||||
{
|
||||
new(&fEmptyString) StringData(StringDataKey("", 0));
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - StringPool
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
StringPool::Init()
|
||||
{
|
||||
sStrings = new(sStringsBuffer) StringDataHash;
|
||||
status_t error = sStrings->Init(kInitialStringTableSize);
|
||||
if (error != B_OK) {
|
||||
sStrings->~StringDataHash();
|
||||
sStrings = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
mutex_init(&sLock, "string pool");
|
||||
|
||||
StringData::Init();
|
||||
sStrings->Insert(StringData::Empty());
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
StringPool::Cleanup()
|
||||
{
|
||||
sStrings->Remove(StringData::Empty());
|
||||
|
||||
sStrings->~StringDataHash();
|
||||
sStrings = NULL;
|
||||
|
||||
mutex_destroy(&sLock);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ inline StringData*
|
||||
StringPool::_GetLocked(const StringDataKey& key)
|
||||
{
|
||||
if (StringData* string = sStrings->Lookup(key)) {
|
||||
if (!string->AcquireReference())
|
||||
return string;
|
||||
|
||||
// The object was fully dereferenced and will be deleted. Remove it
|
||||
// from the hash table, so it isn't in the way.
|
||||
sStrings->Remove(string);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ StringData*
|
||||
StringPool::Get(const char* string, size_t length)
|
||||
{
|
||||
MutexLocker locker(sLock);
|
||||
StringDataKey key(string, length);
|
||||
StringData* data = _GetLocked(key);
|
||||
if (data != NULL)
|
||||
return data;
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
StringData* newString = StringData::Create(key);
|
||||
if (newString == NULL)
|
||||
return NULL;
|
||||
|
||||
locker.Lock();
|
||||
|
||||
data = _GetLocked(key);
|
||||
if (data != NULL) {
|
||||
locker.Unlock();
|
||||
newString->Delete();
|
||||
return data;
|
||||
}
|
||||
|
||||
sStrings->Insert(newString);
|
||||
return newString;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
StringPool::LastReferenceReleased(StringData* data)
|
||||
{
|
||||
MutexLocker locker(sLock);
|
||||
sStrings->Remove(data);
|
||||
locker.Unlock();
|
||||
data->Delete();
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
StringPool::DumpUsageStatistics()
|
||||
{
|
||||
size_t unsharedStringCount = 0;
|
||||
size_t totalReferenceCount = 0;
|
||||
size_t totalStringSize = 0;
|
||||
size_t totalStringSizeWithDuplicates = 0;
|
||||
|
||||
MutexLocker locker(sLock);
|
||||
for (StringDataHash::Iterator it = sStrings->GetIterator(); it.HasNext();) {
|
||||
StringData* data = it.Next();
|
||||
int32 referenceCount = data->CountReferences();
|
||||
totalReferenceCount += referenceCount;
|
||||
if (referenceCount == 1)
|
||||
unsharedStringCount++;
|
||||
|
||||
size_t stringSize = strlen(data->String() + 1);
|
||||
totalStringSize += stringSize;
|
||||
totalStringSizeWithDuplicates += stringSize * referenceCount;
|
||||
}
|
||||
|
||||
size_t stringCount = sStrings->CountElements();
|
||||
size_t overhead = stringCount * (sizeof(StringData) - 1);
|
||||
|
||||
INFORM("StringPool usage:\n");
|
||||
INFORM(" total unique strings: %8zu, %8zu bytes, overhead: %zu bytes\n",
|
||||
stringCount, totalStringSize, overhead);
|
||||
INFORM(" total strings with dups: %8zu, %8zu bytes\n", totalReferenceCount,
|
||||
totalStringSizeWithDuplicates);
|
||||
INFORM(" unshared strings: %8zu\n", unsharedStringCount);
|
||||
INFORM(" bytes saved: %8zd\n",
|
||||
(ssize_t)(totalStringSizeWithDuplicates - totalStringSize - overhead));
|
||||
}
|
192
src/add-ons/kernel/file_systems/packagefs/util/StringPool.h
Normal file
192
src/add-ons/kernel/file_systems/packagefs/util/StringPool.h
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef STRING_POOL_H
|
||||
#define STRING_POOL_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/khash.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
|
||||
class StringData;
|
||||
|
||||
|
||||
class StringDataKey {
|
||||
public:
|
||||
StringDataKey(const char* string, size_t length)
|
||||
:
|
||||
fString(string),
|
||||
fLength(length),
|
||||
fHash(hash_hash_string_part(string, length))
|
||||
{
|
||||
}
|
||||
|
||||
const char* String() const
|
||||
{
|
||||
return fString;
|
||||
}
|
||||
|
||||
size_t Length() const
|
||||
{
|
||||
return fLength;
|
||||
}
|
||||
|
||||
uint32 Hash() const
|
||||
{
|
||||
return fHash;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* fString;
|
||||
size_t fLength;
|
||||
uint32 fHash;
|
||||
};
|
||||
|
||||
|
||||
struct StringDataHashDefinition;
|
||||
typedef BOpenHashTable<StringDataHashDefinition> StringDataHash;
|
||||
|
||||
|
||||
class StringPool {
|
||||
public:
|
||||
static status_t Init();
|
||||
static void Cleanup();
|
||||
|
||||
static StringData* Get(const char* string, size_t length);
|
||||
static void LastReferenceReleased(StringData* data);
|
||||
|
||||
static void DumpUsageStatistics();
|
||||
|
||||
private:
|
||||
static StringData* _GetLocked(const StringDataKey& key);
|
||||
|
||||
private:
|
||||
static mutex sLock;
|
||||
static StringDataHash* sStrings;
|
||||
};
|
||||
|
||||
|
||||
class StringData {
|
||||
public:
|
||||
static void Init();
|
||||
|
||||
static StringData* Create(const StringDataKey& key)
|
||||
{
|
||||
void* data = malloc(sizeof(StringData) + key.Length());
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
return new(data) StringData(key);
|
||||
}
|
||||
|
||||
static StringData* Empty()
|
||||
{
|
||||
return &fEmptyString;
|
||||
}
|
||||
|
||||
static StringData* GetEmpty()
|
||||
{
|
||||
fEmptyString.AcquireReference();
|
||||
return &fEmptyString;
|
||||
}
|
||||
|
||||
void Delete()
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
bool AcquireReference()
|
||||
{
|
||||
return atomic_add(&fReferenceCount, 1) == 0;
|
||||
}
|
||||
|
||||
void ReleaseReference()
|
||||
{
|
||||
if (atomic_add(&fReferenceCount, -1) == 1)
|
||||
StringPool::LastReferenceReleased(this);
|
||||
}
|
||||
|
||||
// debugging only
|
||||
int32 CountReferences() const
|
||||
{
|
||||
return fReferenceCount;
|
||||
}
|
||||
|
||||
const char* String() const
|
||||
{
|
||||
return fString;
|
||||
}
|
||||
|
||||
uint32 Hash() const
|
||||
{
|
||||
return fHash;
|
||||
}
|
||||
|
||||
StringData*& HashNext()
|
||||
{
|
||||
return fHashNext;
|
||||
}
|
||||
|
||||
private:
|
||||
StringData(const StringDataKey& key)
|
||||
:
|
||||
fReferenceCount(1),
|
||||
fHash(key.Hash())
|
||||
{
|
||||
memcpy(fString, key.String(), key.Length());
|
||||
fString[key.Length()] = '\0';
|
||||
}
|
||||
|
||||
~StringData()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static StringData fEmptyString;
|
||||
|
||||
StringData* fHashNext;
|
||||
int32 fReferenceCount;
|
||||
uint32 fHash;
|
||||
char fString[1];
|
||||
};
|
||||
|
||||
|
||||
struct StringDataHashDefinition {
|
||||
typedef StringDataKey KeyType;
|
||||
typedef StringData ValueType;
|
||||
|
||||
size_t HashKey(const StringDataKey& key) const
|
||||
{
|
||||
return key.Hash();
|
||||
}
|
||||
|
||||
size_t Hash(const StringData* value) const
|
||||
{
|
||||
return value->Hash();
|
||||
}
|
||||
|
||||
bool Compare(const StringDataKey& key, const StringData* value) const
|
||||
{
|
||||
return key.Hash() == value->Hash()
|
||||
&& strncmp(value->String(), key.String(), key.Length()) == 0
|
||||
&& value->String()[key.Length()] == '\0';
|
||||
}
|
||||
|
||||
StringData*& GetLink(StringData* value) const
|
||||
{
|
||||
return value->HashNext();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // STRING_POOL_H
|
@ -22,11 +22,11 @@ static const char* const kVersionPartPlaceholder = "_";
|
||||
|
||||
|
||||
static int
|
||||
compare_version_part(const char* a, const char* b)
|
||||
compare_version_part(const String& a, const String& b)
|
||||
{
|
||||
if (a == NULL)
|
||||
return b != NULL ? -1 : 0;
|
||||
if (b == NULL)
|
||||
if (a.IsEmpty())
|
||||
return b.IsEmpty() ? 0 : -1;
|
||||
if (b.IsEmpty())
|
||||
return 1;
|
||||
|
||||
return BPrivate::NaturalCompare(a, b);
|
||||
@ -35,10 +35,10 @@ compare_version_part(const char* a, const char* b)
|
||||
|
||||
Version::Version()
|
||||
:
|
||||
fMajor(NULL),
|
||||
fMinor(NULL),
|
||||
fMicro(NULL),
|
||||
fPreRelease(NULL),
|
||||
fMajor(),
|
||||
fMinor(),
|
||||
fMicro(),
|
||||
fPreRelease(),
|
||||
fRevision(0)
|
||||
{
|
||||
}
|
||||
@ -46,10 +46,6 @@ Version::Version()
|
||||
|
||||
Version::~Version()
|
||||
{
|
||||
free(fMajor);
|
||||
free(fMinor);
|
||||
free(fMicro);
|
||||
free(fPreRelease);
|
||||
}
|
||||
|
||||
|
||||
@ -58,26 +54,22 @@ Version::Init(const char* major, const char* minor, const char* micro,
|
||||
const char* preRelease, uint32 revision)
|
||||
{
|
||||
if (major != NULL) {
|
||||
fMajor = strdup(major);
|
||||
if (fMajor == NULL)
|
||||
if (!fMajor.SetTo(major))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (minor != NULL) {
|
||||
fMinor = strdup(minor);
|
||||
if (fMinor == NULL)
|
||||
if (!fMinor.SetTo(minor))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (micro != NULL) {
|
||||
fMicro = strdup(micro);
|
||||
if (fMicro == NULL)
|
||||
if (!fMicro.SetTo(micro))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (preRelease != NULL) {
|
||||
fPreRelease = strdup(preRelease);
|
||||
if (fPreRelease == NULL)
|
||||
if (!fPreRelease.SetTo(preRelease))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
@ -124,10 +116,10 @@ Version::Compare(const Version& other) const
|
||||
// The pre-version works differently: The empty string is greater than any
|
||||
// non-empty string (e.g. "R1" is newer than "R1-rc2"). So we catch the
|
||||
// empty string cases first.
|
||||
if (fPreRelease == NULL) {
|
||||
if (other.fPreRelease != NULL)
|
||||
if (fPreRelease.IsEmpty()) {
|
||||
if (!other.fPreRelease.IsEmpty())
|
||||
return 1;
|
||||
} else if (other.fPreRelease == NULL) {
|
||||
} else if (other.fPreRelease.IsEmpty()) {
|
||||
return -1;
|
||||
} else {
|
||||
// both are non-null -- compare normally
|
||||
@ -180,27 +172,27 @@ Version::ToString(char* buffer, size_t bufferSize) const
|
||||
const char* minor = fMinor;
|
||||
const char* micro = fMicro;
|
||||
|
||||
if (micro != NULL && minor == NULL)
|
||||
if (micro[0] != '\0' && minor[0] == '\0')
|
||||
minor = kVersionPartPlaceholder;
|
||||
if (minor != NULL && major == NULL)
|
||||
if (minor[0] != '\0' && major[0] == '\0')
|
||||
major = kVersionPartPlaceholder;
|
||||
|
||||
size_t size = strlcpy(buffer, major, bufferSize);
|
||||
|
||||
if (minor != NULL) {
|
||||
if (minor[0] != '\0') {
|
||||
size_t offset = std::min(bufferSize, size);
|
||||
size += snprintf(buffer + offset, bufferSize - offset, ".%s", minor);
|
||||
}
|
||||
|
||||
if (micro != NULL) {
|
||||
if (micro[0] != '\0') {
|
||||
size_t offset = std::min(bufferSize, size);
|
||||
size += snprintf(buffer + offset, bufferSize - offset, ".%s", micro);
|
||||
}
|
||||
|
||||
if (fPreRelease != NULL) {
|
||||
if (fPreRelease[0] != '\0') {
|
||||
size_t offset = std::min(bufferSize, size);
|
||||
size += snprintf(buffer + offset, bufferSize - offset, "~%s",
|
||||
fPreRelease);
|
||||
fPreRelease.Data());
|
||||
}
|
||||
|
||||
if (fRevision != 0) {
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <package/PackageResolvableOperator.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include "String.h"
|
||||
|
||||
|
||||
using namespace BPackageKit;
|
||||
|
||||
@ -35,10 +37,10 @@ public:
|
||||
// been (excluding the terminating null)
|
||||
|
||||
private:
|
||||
char* fMajor;
|
||||
char* fMinor;
|
||||
char* fMicro;
|
||||
char* fPreRelease;
|
||||
String fMajor;
|
||||
String fMinor;
|
||||
String fMicro;
|
||||
String fPreRelease;
|
||||
uint32 fRevision;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ OldNodeAttributes::~OldNodeAttributes()
|
||||
|
||||
|
||||
void*
|
||||
OldNodeAttributes::IndexCookieForAttribute(const char* name) const
|
||||
OldNodeAttributes::IndexCookieForAttribute(const StringKey& name) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <util/DoublyLinkedList.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include "StringKey.h"
|
||||
|
||||
|
||||
class Node;
|
||||
|
||||
@ -24,7 +26,8 @@ public:
|
||||
|
||||
virtual timespec ModifiedTime() const = 0;
|
||||
virtual off_t FileSize() const = 0;
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
virtual void* IndexCookieForAttribute(const StringKey& name)
|
||||
const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "DebugSupport.h"
|
||||
#include "PackageLinksDirectory.h"
|
||||
#include "StringConstants.h"
|
||||
|
||||
|
||||
//#define TRACE_DEPENDENCIES_ENABLED
|
||||
@ -22,9 +23,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
static const char* const kPackageLinksDirectoryName = "package-links";
|
||||
|
||||
|
||||
mutex PackageFSRoot::sRootListLock = MUTEX_INITIALIZER("packagefs root list");
|
||||
PackageFSRoot::RootList PackageFSRoot::sRootList;
|
||||
|
||||
@ -71,7 +69,7 @@ PackageFSRoot::Init()
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = fPackageLinksDirectory->Init(NULL,
|
||||
kPackageLinksDirectoryName, 0);
|
||||
StringConstants::Get().kPackageLinksDirectoryName);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
@ -243,7 +241,7 @@ PackageFSRoot::_RemoveVolume(Volume* volume)
|
||||
status_t
|
||||
PackageFSRoot::_AddPackage(Package* package)
|
||||
{
|
||||
TRACE_DEPENDENCIES("adding package \"%s\"\n", package->Name());
|
||||
TRACE_DEPENDENCIES("adding package \"%s\"\n", package->Name().Data());
|
||||
|
||||
ResolvableDependencyList dependenciesToUpdate;
|
||||
|
||||
@ -306,7 +304,7 @@ PackageFSRoot::_AddPackage(Package* package)
|
||||
void
|
||||
PackageFSRoot::_RemovePackage(Package* package)
|
||||
{
|
||||
TRACE_DEPENDENCIES("removing package \"%s\"\n", package->Name());
|
||||
TRACE_DEPENDENCIES("removing package \"%s\"\n", package->Name().Data());
|
||||
|
||||
fPackageLinksDirectory->RemovePackage(package);
|
||||
|
||||
|
@ -485,12 +485,16 @@ Volume::Mount(const char* parameterString)
|
||||
}
|
||||
}
|
||||
|
||||
String volumeNameString;
|
||||
if (!volumeNameString.SetTo(volumeName))
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
// create the root node
|
||||
fRootDirectory
|
||||
= new(std::nothrow) ::RootDirectory(kRootDirectoryID, st.st_mtim);
|
||||
if (fRootDirectory == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
fRootDirectory->Init(NULL, volumeName, 0);
|
||||
fRootDirectory->Init(NULL, volumeNameString);
|
||||
fNodes.Insert(fRootDirectory);
|
||||
fRootDirectory->AcquireReference();
|
||||
// one reference for the table
|
||||
@ -529,6 +533,8 @@ Volume::Mount(const char* parameterString)
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
StringPool::DumpUsageStatistics();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -1318,7 +1324,7 @@ Volume::_RemovePackageNode(Directory* directory, PackageNode* packageNode,
|
||||
|
||||
|
||||
status_t
|
||||
Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const char* name,
|
||||
Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const String& name,
|
||||
UnpackingNode*& _node)
|
||||
{
|
||||
UnpackingNode* unpackingNode;
|
||||
@ -1335,7 +1341,7 @@ Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const char* name,
|
||||
Node* node = unpackingNode->GetNode();
|
||||
BReference<Node> nodeReference(node, true);
|
||||
|
||||
status_t error = node->Init(parent, name, 0);
|
||||
status_t error = node->Init(parent, name);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
@ -1541,7 +1547,7 @@ INFORM("Volume::_ChangeActivation(): %" B_PRId32 " new packages, %" B_PRId32 " o
|
||||
oldPackageReferences[oldPackageIndex++].SetTo(package);
|
||||
_RemovePackageContent(package, NULL, true);
|
||||
_RemovePackage(package);
|
||||
INFORM("package \"%s\" deactivated\n", package->FileName());
|
||||
INFORM("package \"%s\" deactivated\n", package->FileName().Data());
|
||||
}
|
||||
// TODO: Since package removal cannot fail, consider adding the new packages
|
||||
// first. The reactivation case may make that problematic, since two packages
|
||||
@ -1560,7 +1566,7 @@ INFORM("package \"%s\" deactivated\n", package->FileName());
|
||||
_RemovePackage(package);
|
||||
break;
|
||||
}
|
||||
INFORM("package \"%s\" activated\n", package->FileName());
|
||||
INFORM("package \"%s\" activated\n", package->FileName().Data());
|
||||
}
|
||||
|
||||
// Try to roll back the changes, if an error occurred.
|
||||
@ -1579,7 +1585,7 @@ INFORM("package \"%s\" activated\n", package->FileName());
|
||||
// nothing we can do here
|
||||
ERROR("Volume::_ChangeActivation(): failed to roll back "
|
||||
"deactivation of package \"%s\" after error\n",
|
||||
package->FileName());
|
||||
package->FileName().Data());
|
||||
_RemovePackage(package);
|
||||
}
|
||||
}
|
||||
@ -1619,7 +1625,11 @@ Volume::_CreateShineThroughDirectory(Directory* parent, const char* name,
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
BReference<ShineThroughDirectory> directoryReference(directory, true);
|
||||
|
||||
status_t error = directory->Init(parent, name, 0);
|
||||
String nameString;
|
||||
if (!nameString.SetTo(name))
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
status_t error = directory->Init(parent, nameString);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
const void* oldKey, size_t oldLength,
|
||||
const void* newKey, size_t newLength);
|
||||
|
||||
Index* FindIndex(const char* name) const
|
||||
Index* FindIndex(const StringKey& name) const
|
||||
{ return fIndices.Lookup(name); }
|
||||
IndexDirIterator GetIndexDirIterator() const
|
||||
{ return fIndices.GetIterator(); }
|
||||
@ -139,7 +139,7 @@ private:
|
||||
bool notify);
|
||||
|
||||
status_t _CreateUnpackingNode(mode_t mode,
|
||||
Directory* parent, const char* name,
|
||||
Directory* parent, const String& name,
|
||||
UnpackingNode*& _node);
|
||||
// does *not* return a reference
|
||||
void _RemoveNode(Node* node);
|
||||
|
Loading…
Reference in New Issue
Block a user