Add NameIndex class and create instance in Volume
This commit is contained in:
parent
804a92da7a
commit
3897e7298e
@ -18,6 +18,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
||||
GlobalFactory.cpp
|
||||
Index.cpp
|
||||
kernel_interface.cpp
|
||||
NameIndex.cpp
|
||||
Node.cpp
|
||||
NodeListener.cpp
|
||||
Package.cpp
|
||||
|
370
src/add-ons/kernel/file_systems/packagefs/NameIndex.cpp
Normal file
370
src/add-ons/kernel/file_systems/packagefs/NameIndex.cpp
Normal file
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include <util/TwoKeyAVLTree.h>
|
||||
|
||||
#include "DebugSupport.h"
|
||||
#include "IndexImpl.h"
|
||||
#include "NameIndex.h"
|
||||
#include "Node.h"
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
// #pragma mark - NameIndexPrimaryKey
|
||||
|
||||
|
||||
class NameIndexPrimaryKey {
|
||||
public:
|
||||
NameIndexPrimaryKey(const Node* entry, const char* name = NULL)
|
||||
:
|
||||
entry(entry),
|
||||
name(name ? name : entry->Name())
|
||||
{
|
||||
}
|
||||
|
||||
NameIndexPrimaryKey(const char* name)
|
||||
:
|
||||
entry(NULL),
|
||||
name(name)
|
||||
{
|
||||
}
|
||||
|
||||
const Node* entry;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NameIndexGetPrimaryKey
|
||||
|
||||
|
||||
class NameIndexGetPrimaryKey {
|
||||
public:
|
||||
inline NameIndexPrimaryKey operator()(const Node* a)
|
||||
{
|
||||
return NameIndexPrimaryKey(a);
|
||||
}
|
||||
|
||||
inline NameIndexPrimaryKey operator()(const Node* a) const
|
||||
{
|
||||
return NameIndexPrimaryKey(a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NameIndexPrimaryKeyCompare
|
||||
|
||||
|
||||
class NameIndexPrimaryKeyCompare
|
||||
{
|
||||
public:
|
||||
inline int operator()(const NameIndexPrimaryKey &a,
|
||||
const NameIndexPrimaryKey &b) const
|
||||
{
|
||||
if (a.entry != NULL && a.entry == b.entry)
|
||||
return 0;
|
||||
return strcmp(a.name, b.name) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - EntryTree
|
||||
|
||||
|
||||
typedef TwoKeyAVLTree<Node*, NameIndexPrimaryKey, NameIndexPrimaryKeyCompare,
|
||||
NameIndexGetPrimaryKey> _EntryTree;
|
||||
|
||||
class NameIndex::EntryTree : public _EntryTree {
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NameIndexIterator
|
||||
|
||||
|
||||
class NameIndexIterator : public AbstractIndexIterator,
|
||||
public NodeListener {
|
||||
public:
|
||||
NameIndexIterator();
|
||||
virtual ~NameIndexIterator();
|
||||
|
||||
virtual Node* Current();
|
||||
virtual Node* Current(void* buffer, size_t* _keyLength);
|
||||
virtual Node* Previous();
|
||||
virtual Node* Next();
|
||||
|
||||
virtual status_t Suspend();
|
||||
virtual status_t Resume();
|
||||
|
||||
bool SetTo(NameIndex* index, const char* name,
|
||||
bool ignoreValue = false);
|
||||
|
||||
virtual void NodeRemoved(Node* node);
|
||||
|
||||
private:
|
||||
friend class NameIndex;
|
||||
|
||||
typedef AbstractIndexIterator BaseClass;
|
||||
|
||||
private:
|
||||
NameIndex* fIndex;
|
||||
NameIndex::EntryTree::Iterator fIterator;
|
||||
bool fSuspended;
|
||||
bool fIsNext;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NameIndex
|
||||
|
||||
|
||||
NameIndex::NameIndex()
|
||||
:
|
||||
Index(),
|
||||
fEntries(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NameIndex::~NameIndex()
|
||||
{
|
||||
if (fVolume != NULL)
|
||||
fVolume->RemoveNodeListener(this);
|
||||
|
||||
delete fEntries;
|
||||
// Actually we would need to maintain a list of iterators and unset the
|
||||
// still existing iterators here. But since the name index is deleted
|
||||
// when the volume is unmounted, there shouldn't be any iterators left
|
||||
// anymore.
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NameIndex::Init(Volume* volume)
|
||||
{
|
||||
status_t error = Index::Init(volume, "name", B_STRING_TYPE, false);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fEntries = new(std::nothrow) EntryTree;
|
||||
if (fEntries == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fVolume = volume;
|
||||
fVolume->AddNodeListener(this, NULL);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
NameIndex::CountEntries() const
|
||||
{
|
||||
return fEntries->CountItems();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameIndex::NodeAdded(Node* node)
|
||||
{
|
||||
fEntries->Insert(node);
|
||||
|
||||
// udpate live queries
|
||||
_UpdateLiveQueries(node, NULL, node->Name());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameIndex::NodeRemoved(Node* node)
|
||||
{
|
||||
fEntries->Remove(node, node);
|
||||
|
||||
// udpate live queries
|
||||
_UpdateLiveQueries(node, node->Name(), NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameIndex::NodeChanged(Node* node, uint32 statFields)
|
||||
{
|
||||
// nothing to do -- the name remains the same
|
||||
}
|
||||
|
||||
|
||||
AbstractIndexIterator*
|
||||
NameIndex::InternalGetIterator()
|
||||
{
|
||||
NameIndexIterator* iterator = new(std::nothrow) NameIndexIterator;
|
||||
if (iterator != NULL) {
|
||||
if (!iterator->SetTo(this, NULL, true)) {
|
||||
delete iterator;
|
||||
iterator = NULL;
|
||||
}
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
|
||||
|
||||
AbstractIndexIterator*
|
||||
NameIndex::InternalFind(const void* _key, size_t length)
|
||||
{
|
||||
if (_key == NULL || length == 0)
|
||||
return NULL;
|
||||
|
||||
const char* key = (const char*)_key;
|
||||
|
||||
// if the key is not null-terminated, copy it
|
||||
char clonedKey[kMaxIndexKeyLength];
|
||||
if (key[length - 1] != '\0') {
|
||||
if (length >= kMaxIndexKeyLength)
|
||||
length = kMaxIndexKeyLength - 1;
|
||||
|
||||
memcpy(clonedKey, key, length);
|
||||
clonedKey[length] = '\0';
|
||||
length++;
|
||||
key = clonedKey;
|
||||
}
|
||||
|
||||
NameIndexIterator* iterator = new(std::nothrow) NameIndexIterator;
|
||||
if (iterator != NULL) {
|
||||
if (!iterator->SetTo(this, (const char*)key)) {
|
||||
delete iterator;
|
||||
iterator = NULL;
|
||||
}
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameIndex::_UpdateLiveQueries(Node* entry, const char* oldName,
|
||||
const char* newName)
|
||||
{
|
||||
fVolume->UpdateLiveQueries(entry, Name(), Type(),
|
||||
oldName, oldName ? strlen(oldName) : 0,
|
||||
newName, newName ? strlen(newName) : 0);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - NameIndexIterator
|
||||
|
||||
|
||||
NameIndexIterator::NameIndexIterator()
|
||||
:
|
||||
AbstractIndexIterator(),
|
||||
fIndex(NULL),
|
||||
fIterator(),
|
||||
fSuspended(false),
|
||||
fIsNext(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NameIndexIterator::~NameIndexIterator()
|
||||
{
|
||||
SetTo(NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
Node*
|
||||
NameIndexIterator::Current()
|
||||
{
|
||||
return fIndex != NULL
|
||||
&& fIterator.Current() != NULL ? *fIterator.Current() : NULL;
|
||||
}
|
||||
|
||||
|
||||
Node*
|
||||
NameIndexIterator::Current(void* buffer, size_t* _keyLength)
|
||||
{
|
||||
Node* entry = Current();
|
||||
if (entry != NULL) {
|
||||
strlcpy((char*)buffer, entry->Name(), kMaxIndexKeyLength);
|
||||
*_keyLength = strlen(entry->Name());
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
Node*
|
||||
NameIndexIterator::Previous()
|
||||
{
|
||||
if (fSuspended)
|
||||
return NULL;
|
||||
if (!(fIterator.Current() != NULL && fIsNext))
|
||||
fIterator.Previous();
|
||||
fIsNext = false;
|
||||
return fIndex != NULL
|
||||
&& fIterator.Current() != NULL ? *fIterator.Current() : NULL;
|
||||
}
|
||||
|
||||
|
||||
Node*
|
||||
NameIndexIterator::Next()
|
||||
{
|
||||
if (fSuspended)
|
||||
return NULL;
|
||||
if (!(fIterator.Current() != NULL && fIsNext))
|
||||
fIterator.Next();
|
||||
fIsNext = false;
|
||||
return fIndex != NULL
|
||||
&& fIterator.Current() != NULL ? *fIterator.Current() : NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NameIndexIterator::Suspend()
|
||||
{
|
||||
status_t error = !fSuspended ? B_OK : B_BAD_VALUE;
|
||||
if (error == B_OK) {
|
||||
if (fIterator.Current() != NULL)
|
||||
fIndex->GetVolume()->AddNodeListener(this, *fIterator.Current());
|
||||
|
||||
fSuspended = true;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NameIndexIterator::Resume()
|
||||
{
|
||||
status_t error = fSuspended ? B_OK : B_BAD_VALUE;
|
||||
if (error == B_OK) {
|
||||
if (fIterator.Current() != NULL)
|
||||
fIndex->GetVolume()->RemoveNodeListener(this);
|
||||
|
||||
fSuspended = false;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NameIndexIterator::SetTo(NameIndex* index, const char* name, bool ignoreValue)
|
||||
{
|
||||
Resume();
|
||||
|
||||
fIndex = index;
|
||||
fSuspended = false;
|
||||
fIsNext = false;
|
||||
if (fIndex != NULL) {
|
||||
if (ignoreValue) {
|
||||
fIndex->fEntries->GetIterator(&fIterator);
|
||||
return fIterator.Current() != NULL;
|
||||
}
|
||||
return fIndex->fEntries->FindFirst(name, &fIterator);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NameIndexIterator::NodeRemoved(Node* node)
|
||||
{
|
||||
Resume();
|
||||
fIsNext = Next();
|
||||
Suspend();
|
||||
}
|
47
src/add-ons/kernel/file_systems/packagefs/NameIndex.h
Normal file
47
src/add-ons/kernel/file_systems/packagefs/NameIndex.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef NAME_INDEX_H
|
||||
#define NAME_INDEX_H
|
||||
|
||||
|
||||
#include "Index.h"
|
||||
#include "NodeListener.h"
|
||||
|
||||
|
||||
class NameIndexIterator;
|
||||
|
||||
|
||||
class NameIndex : public Index, private NodeListener {
|
||||
public:
|
||||
NameIndex();
|
||||
virtual ~NameIndex();
|
||||
|
||||
status_t Init(Volume* volume);
|
||||
|
||||
virtual int32 CountEntries() const;
|
||||
|
||||
private:
|
||||
virtual void NodeAdded(Node* node);
|
||||
virtual void NodeRemoved(Node* node);
|
||||
virtual void NodeChanged(Node* node, uint32 statFields);
|
||||
|
||||
protected:
|
||||
virtual AbstractIndexIterator* InternalGetIterator();
|
||||
virtual AbstractIndexIterator* InternalFind(const void* key,
|
||||
size_t length);
|
||||
|
||||
private:
|
||||
class EntryTree;
|
||||
friend class NameIndexIterator;
|
||||
|
||||
void _UpdateLiveQueries(Node* entry,
|
||||
const char* oldName, const char* newName);
|
||||
|
||||
private:
|
||||
EntryTree* fEntries;
|
||||
};
|
||||
|
||||
|
||||
#endif // NAME_INDEX_H
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "DebugSupport.h"
|
||||
#include "kernel_interface.h"
|
||||
#include "NameIndex.h"
|
||||
#include "PackageDirectory.h"
|
||||
#include "PackageFile.h"
|
||||
#include "PackageFSRoot.h"
|
||||
@ -507,6 +508,19 @@ Volume::Mount(const char* parameterString)
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
// create the name index
|
||||
NameIndex* index = new(std::nothrow) NameIndex;
|
||||
if (index == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
error = index->Init(this);
|
||||
if (error != B_OK) {
|
||||
delete index;
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
fIndices.Insert(index);
|
||||
|
||||
// get the mount parameters
|
||||
const char* packages = NULL;
|
||||
const char* volumeName = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user