Add NameIndex class and create instance in Volume
This commit is contained in:
@@ -18,6 +18,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
|||||||
GlobalFactory.cpp
|
GlobalFactory.cpp
|
||||||
Index.cpp
|
Index.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
|
NameIndex.cpp
|
||||||
Node.cpp
|
Node.cpp
|
||||||
NodeListener.cpp
|
NodeListener.cpp
|
||||||
Package.cpp
|
Package.cpp
|
||||||
|
|||||||
@@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* 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 "DebugSupport.h"
|
||||||
#include "kernel_interface.h"
|
#include "kernel_interface.h"
|
||||||
|
#include "NameIndex.h"
|
||||||
#include "PackageDirectory.h"
|
#include "PackageDirectory.h"
|
||||||
#include "PackageFile.h"
|
#include "PackageFile.h"
|
||||||
#include "PackageFSRoot.h"
|
#include "PackageFSRoot.h"
|
||||||
@@ -507,6 +508,19 @@ Volume::Mount(const char* parameterString)
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
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
|
// get the mount parameters
|
||||||
const char* packages = NULL;
|
const char* packages = NULL;
|
||||||
const char* volumeName = NULL;
|
const char* volumeName = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user