Add Index base class and index table in Volume

This commit is contained in:
Ingo Weinhold 2011-07-05 22:55:24 +02:00
parent 67f11c47a7
commit 804a92da7a
6 changed files with 379 additions and 0 deletions

View File

@ -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;
}

View File

@ -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 <string.h>
#include <SupportDefs.h>
#include <util/khash.h>
#include <util/OpenHashTable.h>
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<IndexHashDefinition> IndexHashTable;
#endif // INDEX_H

View File

@ -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

View File

@ -16,6 +16,7 @@ HAIKU_PACKAGE_FS_SOURCES =
Directory.cpp
EmptyAttributeDirectoryCookie.cpp
GlobalFactory.cpp
Index.cpp
kernel_interface.cpp
Node.cpp
NodeListener.cpp

View File

@ -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;

View File

@ -14,6 +14,7 @@
#include <util/DoublyLinkedList.h>
#include <util/KMessage.h>
#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;