diff --git a/src/add-ons/kernel/file_systems/packagefs/Index.cpp b/src/add-ons/kernel/file_systems/packagefs/Index.cpp new file mode 100644 index 0000000000..88cc9fcb2b --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/Index.cpp @@ -0,0 +1,205 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "Index.h" + +#include "DebugSupport.h" +#include "Node.h" +#include "IndexImpl.h" + + +// #pragma mark - Index + + +Index::Index() + : + fVolume(NULL), + fName(NULL), + fType(0), + fKeyLength(0), + fFixedKeyLength(true) +{ +} + + +Index::~Index() +{ + free(fName); +} + + +status_t +Index::Init(Volume* volume, const char* name, uint32 type, bool fixedKeyLength, + size_t keyLength) +{ + fName = strdup(name); + if (fName == NULL) + return B_NO_MEMORY; + + fVolume = volume; + fType = type; + fKeyLength = keyLength; + fFixedKeyLength = fixedKeyLength; + + return B_OK; +} + + +bool +Index::GetIterator(IndexIterator* iterator) +{ + bool result = false; + if (iterator) { + AbstractIndexIterator* actualIterator = InternalGetIterator(); + if (actualIterator) { + iterator->SetIterator(actualIterator); + result = true; + } + } + return result; +} + + +bool +Index::Find(const void* key, size_t length, IndexIterator* iterator) +{ + bool result = false; + if (key && iterator) { + AbstractIndexIterator* actualIterator = InternalFind(key, length); + if (actualIterator) { + iterator->SetIterator(actualIterator); + result = true; + } + } + return result; +} + + +void +Index::Dump() +{ + D( + PRINT(("Index: `%s', type: %lx\n", Name(), Type())); + for (IndexIterator it(this); it.Current(); it.Next()) { + Node* node = it.Current(); + PRINT((" node: `%s', dir: %lld\n", node->GetName(), + node->Parent()->ID())); + } + ) +} + + +// #pragma mark - IndexIterator + + +IndexIterator::IndexIterator() + : + fIterator(NULL) +{ +} + + +IndexIterator::IndexIterator(Index* index) + : + fIterator(NULL) +{ + if (index) + index->GetIterator(this); +} + + +IndexIterator::~IndexIterator() +{ + SetIterator(NULL); +} + + +Node* +IndexIterator::Current() +{ + return fIterator != NULL ? fIterator->Current() : NULL; +} + + +Node* +IndexIterator::Current(void* buffer, size_t* _keyLength) +{ + return fIterator != NULL ? fIterator->Current(buffer, _keyLength) : NULL; +} + + +Node* +IndexIterator::Previous() +{ + return fIterator != NULL ? fIterator->Previous() : NULL; +} + + +Node* +IndexIterator::Next() +{ + return fIterator != NULL ? fIterator->Next() : NULL; +} + + +Node* +IndexIterator::Next(void* buffer, size_t* _keyLength) +{ + Node* node = NULL; + if (fIterator != NULL && fIterator->Next()) + node = Current(buffer, _keyLength); + return node; +} + + +status_t +IndexIterator::Suspend() +{ + return fIterator != NULL ? fIterator->Suspend() : B_BAD_VALUE; +} + + +status_t +IndexIterator::Resume() +{ + return fIterator != NULL ? fIterator->Resume() : B_BAD_VALUE; +} + + +void +IndexIterator::SetIterator(AbstractIndexIterator* iterator) +{ + delete fIterator; + fIterator = iterator; +} + + +// #pragma mark - AbstractIndexIterator + + +AbstractIndexIterator::AbstractIndexIterator() +{ +} + + +AbstractIndexIterator::~AbstractIndexIterator() +{ +} + + +status_t +AbstractIndexIterator::Suspend() +{ + return B_OK; +} + + +status_t +AbstractIndexIterator::Resume() +{ + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/packagefs/Index.h b/src/add-ons/kernel/file_systems/packagefs/Index.h new file mode 100644 index 0000000000..cd3c69315e --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/Index.h @@ -0,0 +1,128 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef INDEX_H +#define INDEX_H + + +#include + +#include + +#include +#include + + +class AbstractIndexIterator; +class IndexIterator; +class Node; +class Volume; + + +static const size_t kMaxIndexKeyLength = 256; + + +class Index { +public: + Index(); + virtual ~Index(); + + status_t Init(Volume* volume, const char* name, + uint32 type, bool fixedKeyLength, + size_t keyLength = 0); + + Volume* GetVolume() const { return fVolume; } + + const char* Name() const { return fName; } + uint32 Type() const { return fType; } + bool HasFixedKeyLength() const + { return fFixedKeyLength; } + size_t KeyLength() const { return fKeyLength; } + + virtual int32 CountEntries() const = 0; + + bool GetIterator(IndexIterator* iterator); + bool Find(const void* key, size_t length, + IndexIterator* iterator); + + Index*& IndexHashLink() + { return fHashLink; } + + // debugging + void Dump(); + +protected: + virtual AbstractIndexIterator* InternalGetIterator() = 0; + virtual AbstractIndexIterator* InternalFind(const void* key, + size_t length) = 0; + +protected: + Index* fHashLink; + Volume* fVolume; + char* fName; + uint32 fType; + size_t fKeyLength; + bool fFixedKeyLength; +}; + + +class IndexIterator { +public: + IndexIterator(); + IndexIterator(Index* index); + ~IndexIterator(); + + Node* Current(); + Node* Current(void* buffer, size_t* _keyLength); + Node* Previous(); + Node* Next(); + Node* Next(void* buffer, size_t* _keyLength); + + status_t Suspend(); + status_t Resume(); + +private: + void SetIterator(AbstractIndexIterator* iterator); + +private: + friend class Index; + +private: + AbstractIndexIterator* fIterator; +}; + + +// #pragma mark - IndexHashDefinition + + +struct IndexHashDefinition { + typedef const char* KeyType; + typedef Index ValueType; + + size_t HashKey(const char* key) const + { + return key != NULL ? hash_hash_string(key) : 0; + } + + size_t Hash(const Index* value) const + { + return HashKey(value->Name()); + } + + bool Compare(const char* key, const Index* value) const + { + return strcmp(value->Name(), key) == 0; + } + + Index*& GetLink(Index* value) const + { + return value->IndexHashLink(); + } +}; + + +typedef BOpenHashTable IndexHashTable; + + +#endif // INDEX_H diff --git a/src/add-ons/kernel/file_systems/packagefs/IndexImpl.h b/src/add-ons/kernel/file_systems/packagefs/IndexImpl.h new file mode 100644 index 0000000000..3dae8e6277 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/IndexImpl.h @@ -0,0 +1,28 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef INDEX_IMPL_H +#define INDEX_IMPL_H + + +#include "Index.h" +#include "Node.h" + + +class AbstractIndexIterator { +public: + AbstractIndexIterator(); + virtual ~AbstractIndexIterator(); + + virtual Node* Current() = 0; + virtual Node* Current(void* buffer, size_t* _keyLength) = 0; + virtual Node* Previous() = 0; + virtual Node* Next() = 0; + + virtual status_t Suspend(); + virtual status_t Resume(); +}; + + +#endif // INDEX_IMPL_H diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 34f2d68ee5..0f00d36f7c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -16,6 +16,7 @@ HAIKU_PACKAGE_FS_SOURCES = Directory.cpp EmptyAttributeDirectoryCookie.cpp GlobalFactory.cpp + Index.cpp kernel_interface.cpp Node.cpp NodeListener.cpp diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 2a3cf330da..bea3475acb 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -460,6 +460,14 @@ Volume::~Volume() while (PackageDomain* packageDomain = fPackageDomains.Head()) _RemovePackageDomain(packageDomain); + // delete all indices + Index* index = fIndices.Clear(true); + while (index != NULL) { + Index* next = index->IndexHashLink(); + delete index; + index = next; + } + // remove all nodes from the ID hash table Node* node = fNodes.Clear(true); while (node != NULL) { @@ -495,6 +503,10 @@ Volume::Mount(const char* parameterString) if (error != B_OK) RETURN_ERROR(error); + error = fIndices.Init(); + if (error != B_OK) + RETURN_ERROR(error); + // get the mount parameters const char* packages = NULL; const char* volumeName = NULL; diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index 6dc1fd4c23..438b134ecf 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -14,6 +14,7 @@ #include #include +#include "Index.h" #include "Node.h" #include "NodeListener.h" #include "PackageDomain.h" @@ -71,6 +72,9 @@ public: Node* node); void RemoveNodeListener(NodeListener* listener); + Index* FindIndex(const char* name) const + { return fIndices.Lookup(name); } + // VFS wrappers status_t GetVNode(ino_t nodeID, Node*& _node); status_t PutVNode(ino_t nodeID); @@ -188,6 +192,7 @@ private: NodeIDHashTable fNodes; NodeListenerHashTable fNodeListeners; + IndexHashTable fIndices; JobList fJobQueue; mutex fJobQueueLock;