From d07c930c1eb710289922edd3abf5244c259a86c6 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 11 May 2013 23:31:36 +0200 Subject: [PATCH] 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. --- .../kernel/file_systems/packagefs/Jamfile | 3 + .../packagefs/indices/AttributeIndexer.h | 6 +- .../file_systems/packagefs/indices/Index.cpp | 6 +- .../file_systems/packagefs/indices/Index.h | 19 +- .../file_systems/packagefs/indices/Query.cpp | 5 +- .../packagefs/kernel_interface.cpp | 31 ++- .../packagefs/nodes/AutoPackageAttributes.cpp | 19 +- .../packagefs/nodes/AutoPackageAttributes.h | 11 +- .../packagefs/nodes/Directory.cpp | 6 +- .../file_systems/packagefs/nodes/Directory.h | 5 +- .../file_systems/packagefs/nodes/Node.cpp | 26 +-- .../file_systems/packagefs/nodes/Node.h | 42 ++-- .../nodes/OldUnpackingNodeAttributes.cpp | 2 +- .../nodes/OldUnpackingNodeAttributes.h | 3 +- .../nodes/UnpackingAttributeCookie.cpp | 2 +- .../nodes/UnpackingAttributeCookie.h | 6 +- .../UnpackingAttributeDirectoryCookie.cpp | 10 +- .../packagefs/nodes/UnpackingDirectory.cpp | 4 +- .../packagefs/nodes/UnpackingDirectory.h | 7 +- .../packagefs/nodes/UnpackingLeafNode.cpp | 10 +- .../packagefs/nodes/UnpackingLeafNode.h | 7 +- .../packagefs/package/Package.cpp | 88 ++++---- .../file_systems/packagefs/package/Package.h | 19 +- .../packagefs/package/PackageLeafNode.cpp | 4 +- .../packagefs/package/PackageLeafNode.h | 2 +- .../packagefs/package/PackageNode.cpp | 15 +- .../packagefs/package/PackageNode.h | 14 +- .../package/PackageNodeAttribute.cpp | 10 +- .../packagefs/package/PackageNodeAttribute.h | 8 +- .../packagefs/package/PackageSymlink.cpp | 15 +- .../packagefs/package/PackageSymlink.h | 6 +- .../package_links/PackageLinkDirectory.cpp | 27 +-- .../package_links/PackageLinkDirectory.h | 5 +- .../package_links/PackageLinkSymlink.cpp | 2 +- .../packagefs/resolvables/Dependency.cpp | 6 +- .../packagefs/resolvables/Dependency.h | 6 +- .../packagefs/resolvables/DependencyFamily.h | 18 +- .../packagefs/resolvables/Resolvable.cpp | 6 +- .../packagefs/resolvables/Resolvable.h | 4 +- .../packagefs/resolvables/ResolvableFamily.h | 18 +- .../file_systems/packagefs/util/String.cpp | 34 ++++ .../file_systems/packagefs/util/String.h | 120 +++++++++++ .../packagefs/util/StringConstants.cpp | 58 ++++++ .../packagefs/util/StringConstants.h | 42 ++++ .../packagefs/util/StringConstantsPrivate.h | 18 ++ .../file_systems/packagefs/util/StringKey.h | 56 +++++ .../packagefs/util/StringPool.cpp | 154 ++++++++++++++ .../file_systems/packagefs/util/StringPool.h | 192 ++++++++++++++++++ .../file_systems/packagefs/util/Version.cpp | 50 ++--- .../file_systems/packagefs/util/Version.h | 10 +- .../packagefs/volume/NodeListener.cpp | 2 +- .../packagefs/volume/NodeListener.h | 5 +- .../packagefs/volume/PackageFSRoot.cpp | 10 +- .../file_systems/packagefs/volume/Volume.cpp | 24 ++- .../file_systems/packagefs/volume/Volume.h | 4 +- 55 files changed, 980 insertions(+), 302 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/String.cpp create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/String.h create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/StringConstants.cpp create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/StringConstants.h create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/StringConstantsPrivate.h create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/StringKey.h create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/StringPool.cpp create mode 100644 src/add-ons/kernel/file_systems/packagefs/util/StringPool.h diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 203e8507d7..7a4833ebea 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/indices/AttributeIndexer.h b/src/add-ons/kernel/file_systems/packagefs/indices/AttributeIndexer.h index f332b29f69..ccd5dbc438 100644 --- a/src/add-ons/kernel/file_systems/packagefs/indices/AttributeIndexer.h +++ b/src/add-ons/kernel/file_systems/packagefs/indices/AttributeIndexer.h @@ -8,6 +8,8 @@ #include +#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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/indices/Index.cpp b/src/add-ons/kernel/file_systems/packagefs/indices/Index.cpp index 8b4ec21477..efdf4dab9c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/indices/Index.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/indices/Index.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/indices/Index.h b/src/add-ons/kernel/file_systems/packagefs/indices/Index.h index 751eaeadf0..7f82ee6f4e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/indices/Index.h +++ b/src/add-ons/kernel/file_systems/packagefs/indices/Index.h @@ -13,6 +13,9 @@ #include #include +#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 diff --git a/src/add-ons/kernel/file_systems/packagefs/indices/Query.cpp b/src/add-ons/kernel/file_systems/packagefs/indices/Query.cpp index 2f5d39c632..b92c1ea230 100644 --- a/src/add-ons/kernel/file_systems/packagefs/indices/Query.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/indices/Query.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp index 77f833e662..260ea197a4 100644 --- a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp @@ -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(dir)->FindChild(entryName); + String entryNameString; + Node* node = dynamic_cast(dir)->FindChild(StringKey(entryName)); if (node == NULL) return B_ENTRY_NOT_FOUND; BReference 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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp index fac17f9c25..37fdad00bf 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.cpp @@ -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) diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.h b/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.h index cbb4d05818..b1a75bf8b4 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/AutoPackageAttributes.h @@ -8,6 +8,8 @@ #include +#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); }; diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.cpp index 0ac01c5f8a..72a1c0a4f2 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.cpp @@ -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); } diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.h b/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.h index c117d1ec08..402bf45587 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/Node.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/Node.cpp index d5e3bb1627..aec69b5db0 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/Node.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/Node.cpp @@ -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(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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/Node.h b/src/add-ons/kernel/file_systems/packagefs/nodes/Node.h index 50c05381f1..3924fb0048 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/Node.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/Node.h @@ -16,6 +16,9 @@ #include #include +#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 Node ValueType; + 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 diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.cpp index 173a1daf6a..81ea4536d7 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.h b/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.h index c9f348360b..f26f9a139c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/OldUnpackingNodeAttributes.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.cpp index 714bb7d780..8809199fae 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.cpp @@ -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) diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.h b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.h index 8a20257efa..a3ae60bc2c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeCookie.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeDirectoryCookie.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeDirectoryCookie.cpp index ab2d3db30f..9d757b224e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeDirectoryCookie.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingAttributeDirectoryCookie.cpp @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.cpp index ee67354819..22410b9d16 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.cpp @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.h b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.h index baad89b1d5..4cebf6da8c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.cpp b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.cpp index bb68b71db9..51f80bb784 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.cpp @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.h b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.h index e3bb4f175c..914e9a4903 100644 --- a/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingLeafNode.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/package/Package.cpp b/src/add-ons/kernel/file_systems/packagefs/package/Package.cpp index ee04cc662e..bddb40980e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/Package.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package/Package.cpp @@ -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 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; diff --git a/src/add-ons/kernel/file_systems/packagefs/package/Package.h b/src/add-ons/kernel/file_systems/packagefs/package/Package.h index b8495b5e5d..ffe3ab9471 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/Package.h +++ b/src/add-ons/kernel/file_systems/packagefs/package/Package.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.cpp b/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.cpp index 94a680432a..f87645f4a7 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.cpp @@ -19,10 +19,10 @@ PackageLeafNode::~PackageLeafNode() } -const char* +String PackageLeafNode::SymlinkPath() const { - return NULL; + return String(); } diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.h b/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.h index b5fca3e0e2..0a5561622e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageLeafNode.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.cpp b/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.cpp index 06eb88110a..1888da39d8 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.h b/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.h index 8f9ed2f048..c2a68153e2 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageNode.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.cpp b/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.cpp index cd80d831ac..63cda955b8 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.h b/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.h index 361dd81647..f467af8b29 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.h +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageNodeAttribute.h @@ -10,6 +10,8 @@ #include +#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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.cpp b/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.cpp index 8f9961aa56..1ae619305f 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.h b/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.h index 65940c7856..2dd775266c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.h +++ b/src/add-ons/kernel/file_systems/packagefs/package/PackageSymlink.h @@ -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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.cpp index 24e505bbf7..cb96ee9a0c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.cpp @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.h b/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.h index c0af9ab3ef..2bdf2c59eb 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkDirectory.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkSymlink.cpp b/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkSymlink.cpp index ad4cdebd13..ec287cfe6e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkSymlink.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/package_links/PackageLinkSymlink.cpp @@ -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 { diff --git a/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.cpp b/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.cpp index c4c34a4132..30f02dfc23 100644 --- a/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.h b/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.h index bab31c2d5b..4997110b24 100644 --- a/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.h +++ b/src/add-ons/kernel/file_systems/packagefs/resolvables/Dependency.h @@ -12,6 +12,8 @@ #include +#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; diff --git a/src/add-ons/kernel/file_systems/packagefs/resolvables/DependencyFamily.h b/src/add-ons/kernel/file_systems/packagefs/resolvables/DependencyFamily.h index fa9daf1d0b..25cd4595da 100644 --- a/src/add-ons/kernel/file_systems/packagefs/resolvables/DependencyFamily.h +++ b/src/add-ons/kernel/file_systems/packagefs/resolvables/DependencyFamily.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.cpp b/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.cpp index 43a7414d0f..b8daec8499 100644 --- a/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.h b/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.h index 87d4509f61..298737a817 100644 --- a/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.h +++ b/src/add-ons/kernel/file_systems/packagefs/resolvables/Resolvable.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/resolvables/ResolvableFamily.h b/src/add-ons/kernel/file_systems/packagefs/resolvables/ResolvableFamily.h index 7d0a87fcbc..d5d8d643c0 100644 --- a/src/add-ons/kernel/file_systems/packagefs/resolvables/ResolvableFamily.h +++ b/src/add-ons/kernel/file_systems/packagefs/resolvables/ResolvableFamily.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/util/String.cpp b/src/add-ons/kernel/file_systems/packagefs/util/String.cpp new file mode 100644 index 0000000000..785abeb3bf --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/String.cpp @@ -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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/util/String.h b/src/add-ons/kernel/file_systems/packagefs/util/String.h new file mode 100644 index 0000000000..3025e972df --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/String.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/util/StringConstants.cpp b/src/add-ons/kernel/file_systems/packagefs/util/StringConstants.cpp new file mode 100644 index 0000000000..04de05eac8 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/StringConstants.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "StringConstants.h" + +#include + + +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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/util/StringConstants.h b/src/add-ons/kernel/file_systems/packagefs/util/StringConstants.h new file mode 100644 index 0000000000..129856c830 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/StringConstants.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/util/StringConstantsPrivate.h b/src/add-ons/kernel/file_systems/packagefs/util/StringConstantsPrivate.h new file mode 100644 index 0000000000..a50b21c682 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/StringConstantsPrivate.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") diff --git a/src/add-ons/kernel/file_systems/packagefs/util/StringKey.h b/src/add-ons/kernel/file_systems/packagefs/util/StringKey.h new file mode 100644 index 0000000000..209aa0c96b --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/StringKey.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/util/StringPool.cpp b/src/add-ons/kernel/file_systems/packagefs/util/StringPool.cpp new file mode 100644 index 0000000000..d67019f914 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/StringPool.cpp @@ -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)); +} diff --git a/src/add-ons/kernel/file_systems/packagefs/util/StringPool.h b/src/add-ons/kernel/file_systems/packagefs/util/StringPool.h new file mode 100644 index 0000000000..2a97b2aace --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/util/StringPool.h @@ -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 + +#include +#include + +#include + +#include +#include +#include + + +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 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 diff --git a/src/add-ons/kernel/file_systems/packagefs/util/Version.cpp b/src/add-ons/kernel/file_systems/packagefs/util/Version.cpp index 849453f595..ed4542a587 100644 --- a/src/add-ons/kernel/file_systems/packagefs/util/Version.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/util/Version.cpp @@ -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) { diff --git a/src/add-ons/kernel/file_systems/packagefs/util/Version.h b/src/add-ons/kernel/file_systems/packagefs/util/Version.h index 8ce58af21f..30a798ae2d 100644 --- a/src/add-ons/kernel/file_systems/packagefs/util/Version.h +++ b/src/add-ons/kernel/file_systems/packagefs/util/Version.h @@ -9,6 +9,8 @@ #include #include +#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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.cpp b/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.cpp index d38064ed32..18b4b29a6b 100644 --- a/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.cpp @@ -16,7 +16,7 @@ OldNodeAttributes::~OldNodeAttributes() void* -OldNodeAttributes::IndexCookieForAttribute(const char* name) const +OldNodeAttributes::IndexCookieForAttribute(const StringKey& name) const { return NULL; } diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.h b/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.h index 1d583acb4b..89e3dc00c6 100644 --- a/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.h +++ b/src/add-ons/kernel/file_systems/packagefs/volume/NodeListener.h @@ -11,6 +11,8 @@ #include #include +#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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/PackageFSRoot.cpp b/src/add-ons/kernel/file_systems/packagefs/volume/PackageFSRoot.cpp index 74ee53b90c..268bbb5b62 100644 --- a/src/add-ons/kernel/file_systems/packagefs/volume/PackageFSRoot.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/volume/PackageFSRoot.cpp @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp index 6f9f788442..f04fd504e5 100644 --- a/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp @@ -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 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 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); diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/Volume.h b/src/add-ons/kernel/file_systems/packagefs/volume/Volume.h index 525a979ff3..2e34a70f79 100644 --- a/src/add-ons/kernel/file_systems/packagefs/volume/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/volume/Volume.h @@ -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);