Attribute index support for non-special attributes
* Add AttributeIndex class. * Each attribute does now have an attribute index cookie. The new attribute index service methods Node::IndexAttribute() and IndexCookieForAttribute() create+set/retrieve the cookie. The cookie is actually the attribute index's tree node. * Add OldNodeAttribute::IndexCookieForAttribute() so the cookie is available when the node changes.
This commit is contained in:
parent
4d67e7847b
commit
55b969b13b
410
src/add-ons/kernel/file_systems/packagefs/AttributeIndex.cpp
Normal file
410
src/add-ons/kernel/file_systems/packagefs/AttributeIndex.cpp
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "AttributeIndex.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
|
#include <util/AVLTree.h>
|
||||||
|
#include <util/SinglyLinkedList.h>
|
||||||
|
|
||||||
|
#include <file_systems/QueryParserUtils.h>
|
||||||
|
|
||||||
|
#include "AttributeIndexer.h"
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
#include "IndexImpl.h"
|
||||||
|
#include "Node.h"
|
||||||
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct AttributeIndexTreeKey {
|
||||||
|
const void* data;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
AttributeIndexTreeKey()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AttributeIndexTreeKey(const void* data, size_t length)
|
||||||
|
:
|
||||||
|
data(data),
|
||||||
|
length(length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct AttributeIndexTreeValue : AVLTreeNode {
|
||||||
|
Node* node;
|
||||||
|
IndexedAttributeOwner* owner;
|
||||||
|
void* attributeCookie;
|
||||||
|
size_t length;
|
||||||
|
uint8 data[0];
|
||||||
|
|
||||||
|
static AttributeIndexTreeValue* Create(IndexedAttributeOwner* owner,
|
||||||
|
void* attributeCookie, size_t length)
|
||||||
|
{
|
||||||
|
AttributeIndexTreeValue* self = (AttributeIndexTreeValue*)malloc(
|
||||||
|
sizeof(AttributeIndexTreeValue) + length);
|
||||||
|
if (self == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
self->owner = owner;
|
||||||
|
self->attributeCookie = attributeCookie;
|
||||||
|
self->length = length;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delete()
|
||||||
|
{
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct AttributeIndex::TreeDefinition {
|
||||||
|
typedef TreeKey Key;
|
||||||
|
typedef TreeValue Value;
|
||||||
|
|
||||||
|
TreeDefinition(uint32 type)
|
||||||
|
:
|
||||||
|
fType(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AVLTreeNode* GetAVLTreeNode(Value* value) const
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* GetValue(AVLTreeNode* node) const
|
||||||
|
{
|
||||||
|
return static_cast<Value*>(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const Key& a, const Value* b) const
|
||||||
|
{
|
||||||
|
return QueryParser::compareKeys(fType, a.data, a.length, b->data,
|
||||||
|
b->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const Value* a, const Value* b) const
|
||||||
|
{
|
||||||
|
return QueryParser::compareKeys(fType, a->data, a->length, b->data,
|
||||||
|
b->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fType;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - NodeTree
|
||||||
|
|
||||||
|
|
||||||
|
struct AttributeIndex::NodeTree : public AVLTree<TreeDefinition> {
|
||||||
|
typedef TreeValue Node;
|
||||||
|
|
||||||
|
NodeTree(const TreeDefinition& definition)
|
||||||
|
:
|
||||||
|
AVLTree<TreeDefinition>(definition)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - IteratorList
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndex::IteratorList : public SinglyLinkedList<Iterator> {};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Iterator
|
||||||
|
|
||||||
|
|
||||||
|
struct AttributeIndex::IteratorPolicy {
|
||||||
|
typedef AttributeIndex Index;
|
||||||
|
typedef TreeKey Value;
|
||||||
|
typedef AttributeIndex::NodeTree NodeTree;
|
||||||
|
typedef TreeValue TreeNode;
|
||||||
|
typedef IteratorPolicy TreePolicy;
|
||||||
|
|
||||||
|
static NodeTree* GetNodeTree(Index* index)
|
||||||
|
{
|
||||||
|
return index->fNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetTreeNodeValue(TreeNode* node, void* buffer,
|
||||||
|
size_t* _keyLength)
|
||||||
|
{
|
||||||
|
if (node->length > 0)
|
||||||
|
memcpy(buffer, node->data, node->length);
|
||||||
|
*_keyLength = node->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Node* GetNode(TreeNode* treeNode)
|
||||||
|
{
|
||||||
|
return treeNode->node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TreeNode* GetFirstTreeNode(Index* index)
|
||||||
|
{
|
||||||
|
return index->fNodes->GetIterator().Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
static TreeNode* FindClosestTreeNode(Index* index, const Value& value)
|
||||||
|
{
|
||||||
|
return index->fNodes->FindClosest(value, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndex::Iterator : public GenericIndexIterator<IteratorPolicy>,
|
||||||
|
public SinglyLinkedListLinkImpl<Iterator> {
|
||||||
|
public:
|
||||||
|
virtual void NodeChanged(Node* node, uint32 statFields,
|
||||||
|
const OldNodeAttributes& oldAttributes);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - AttributeIndexer
|
||||||
|
|
||||||
|
|
||||||
|
AttributeIndexer::AttributeIndexer(AttributeIndex* index)
|
||||||
|
:
|
||||||
|
fIndex(index),
|
||||||
|
fIndexName(index->Name()),
|
||||||
|
fIndexType(index->Type()),
|
||||||
|
fCookie(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AttributeIndexer::~AttributeIndexer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AttributeIndexer::CreateCookie(IndexedAttributeOwner* owner,
|
||||||
|
void* attributeCookie, uint32 attributeType, size_t attributeSize,
|
||||||
|
void*& _data, size_t& _toRead)
|
||||||
|
{
|
||||||
|
// check the attribute type and size
|
||||||
|
if (attributeType != fIndexType)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (fIndex->HasFixedKeyLength()) {
|
||||||
|
if (attributeSize != fIndex->KeyLength())
|
||||||
|
return B_ERROR;
|
||||||
|
} else if (attributeSize > kMaxIndexKeyLength)
|
||||||
|
attributeSize = kMaxIndexKeyLength;
|
||||||
|
|
||||||
|
// create the tree value
|
||||||
|
fCookie = AttributeIndexTreeValue::Create(owner, attributeCookie,
|
||||||
|
attributeSize);
|
||||||
|
if (fCookie == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
_data = fCookie->data;
|
||||||
|
_toRead = attributeSize;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AttributeIndexer::DeleteCookie()
|
||||||
|
{
|
||||||
|
fCookie->Delete();
|
||||||
|
fCookie = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - AttributeIndex
|
||||||
|
|
||||||
|
|
||||||
|
AttributeIndex::AttributeIndex()
|
||||||
|
:
|
||||||
|
Index(),
|
||||||
|
fNodes(NULL),
|
||||||
|
fIteratorsToUpdate(NULL),
|
||||||
|
fIndexer(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AttributeIndex::~AttributeIndex()
|
||||||
|
{
|
||||||
|
if (IsListening())
|
||||||
|
fVolume->RemoveNodeListener(this);
|
||||||
|
|
||||||
|
ASSERT(fIteratorsToUpdate->IsEmpty());
|
||||||
|
|
||||||
|
delete fIteratorsToUpdate;
|
||||||
|
delete fNodes;
|
||||||
|
delete fIndexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
AttributeIndex::Init(Volume* volume, const char* name, uint32 type,
|
||||||
|
size_t keyLength)
|
||||||
|
{
|
||||||
|
status_t error = Index::Init(volume, name, type, keyLength > 0, keyLength);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// TODO: Letting each attribute index be a listener is gets more expensive
|
||||||
|
// the more attribute indices we have. Since most attribute indices are
|
||||||
|
// rather sparse, it might be a good idea to rather let Volume iterate
|
||||||
|
// through the actual attributes of an added node and look up and call the
|
||||||
|
// index for each one explicitly. When removing the node, the volume would
|
||||||
|
// iterate through the attributes again and determine based on the index
|
||||||
|
// cookie whether an index has to be notified.
|
||||||
|
fVolume->AddNodeListener(this, NULL);
|
||||||
|
|
||||||
|
fNodes = new(std::nothrow) NodeTree(TreeDefinition(type));
|
||||||
|
fIteratorsToUpdate = new(std::nothrow) IteratorList;
|
||||||
|
fIndexer = new(std::nothrow) AttributeIndexer(this);
|
||||||
|
|
||||||
|
if (fNodes == NULL || fIteratorsToUpdate == NULL || fIndexer == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
AttributeIndex::CountEntries() const
|
||||||
|
{
|
||||||
|
return fNodes->Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AttributeIndex::NodeAdded(Node* node)
|
||||||
|
{
|
||||||
|
if (node->IndexAttribute(fIndexer) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TreeValue* treeValue = fIndexer->Cookie();
|
||||||
|
treeValue->node = node;
|
||||||
|
|
||||||
|
fNodes->Insert(treeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AttributeIndex::NodeRemoved(Node* node)
|
||||||
|
{
|
||||||
|
TreeValue* treeValue = (TreeValue*)node->IndexCookieForAttribute(Name());
|
||||||
|
if (treeValue == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
treeValue->owner->UnsetIndexCookie(treeValue->attributeCookie);
|
||||||
|
fNodes->Remove(treeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AttributeIndex::NodeChanged(Node* node, uint32 statFields,
|
||||||
|
const OldNodeAttributes& oldAttributes)
|
||||||
|
{
|
||||||
|
IteratorList iterators;
|
||||||
|
iterators.MoveFrom(fIteratorsToUpdate);
|
||||||
|
|
||||||
|
TreeValue* oldTreeValue
|
||||||
|
= (TreeValue*)oldAttributes.IndexCookieForAttribute(Name());
|
||||||
|
TreeValue* treeValue = (TreeValue*)node->IndexCookieForAttribute(Name());
|
||||||
|
if (treeValue == NULL && oldTreeValue == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// move the iterators that point to the node to the previous node
|
||||||
|
if (oldTreeValue != NULL) {
|
||||||
|
for (IteratorList::Iterator it = iterators.GetIterator();
|
||||||
|
Iterator* iterator = it.Next();) {
|
||||||
|
iterator->NodeChangeBegin(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the node
|
||||||
|
fNodes->Remove(oldTreeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-insert the node
|
||||||
|
if (treeValue != NULL)
|
||||||
|
fNodes->Insert(treeValue);
|
||||||
|
|
||||||
|
// Move the iterators to the next node again. If the node hasn't changed
|
||||||
|
// its place, they will point to it again, otherwise to the node originally
|
||||||
|
// succeeding it.
|
||||||
|
if (oldTreeValue != NULL) {
|
||||||
|
for (IteratorList::Iterator it = iterators.GetIterator();
|
||||||
|
Iterator* iterator = it.Next();) {
|
||||||
|
iterator->NodeChangeEnd(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update live queries
|
||||||
|
fVolume->UpdateLiveQueries(node, Name(), Type(),
|
||||||
|
oldTreeValue != NULL ? oldTreeValue->data : NULL,
|
||||||
|
oldTreeValue != NULL ? oldTreeValue->length : 0,
|
||||||
|
treeValue != NULL ? treeValue->data : NULL,
|
||||||
|
treeValue != NULL ? treeValue->length : 0);
|
||||||
|
|
||||||
|
if (oldTreeValue != NULL)
|
||||||
|
oldTreeValue->Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbstractIndexIterator*
|
||||||
|
AttributeIndex::InternalGetIterator()
|
||||||
|
{
|
||||||
|
Iterator* iterator = new(std::nothrow) Iterator;
|
||||||
|
if (iterator != NULL) {
|
||||||
|
if (!iterator->SetTo(this, TreeKey(), true)) {
|
||||||
|
delete iterator;
|
||||||
|
iterator = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbstractIndexIterator*
|
||||||
|
AttributeIndex::InternalFind(const void* key, size_t length)
|
||||||
|
{
|
||||||
|
if (key == NULL)
|
||||||
|
return NULL;
|
||||||
|
Iterator* iterator = new(std::nothrow) Iterator;
|
||||||
|
if (iterator != NULL) {
|
||||||
|
if (!iterator->SetTo(this, TreeKey(key, length))) {
|
||||||
|
delete iterator;
|
||||||
|
iterator = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AttributeIndex::_AddIteratorToUpdate(Iterator* iterator)
|
||||||
|
{
|
||||||
|
fIteratorsToUpdate->Add(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Iterator
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AttributeIndex::Iterator::NodeChanged(Node* node, uint32 statFields,
|
||||||
|
const OldNodeAttributes& oldAttributes)
|
||||||
|
{
|
||||||
|
fIndex->_AddIteratorToUpdate(this);
|
||||||
|
}
|
63
src/add-ons/kernel/file_systems/packagefs/AttributeIndex.h
Normal file
63
src/add-ons/kernel/file_systems/packagefs/AttributeIndex.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ATTRIBUTE_INDEX_H
|
||||||
|
#define ATTRIBUTE_INDEX_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "Index.h"
|
||||||
|
#include "NodeListener.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndexer;
|
||||||
|
struct AttributeIndexTreeKey;
|
||||||
|
struct AttributeIndexTreeValue;
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndex : public Index, private NodeListener {
|
||||||
|
public:
|
||||||
|
AttributeIndex();
|
||||||
|
virtual ~AttributeIndex();
|
||||||
|
|
||||||
|
status_t Init(Volume* volume, const char* name,
|
||||||
|
uint32 type, size_t keyLength);
|
||||||
|
|
||||||
|
virtual int32 CountEntries() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void NodeAdded(Node* node);
|
||||||
|
virtual void NodeRemoved(Node* node);
|
||||||
|
virtual void NodeChanged(Node* node, uint32 statFields,
|
||||||
|
const OldNodeAttributes& oldAttributes);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual AbstractIndexIterator* InternalGetIterator();
|
||||||
|
virtual AbstractIndexIterator* InternalFind(const void* key,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef AttributeIndexTreeKey TreeKey;
|
||||||
|
typedef AttributeIndexTreeValue TreeValue;
|
||||||
|
struct TreeDefinition;
|
||||||
|
struct NodeTree;
|
||||||
|
|
||||||
|
struct IteratorPolicy;
|
||||||
|
class Iterator;
|
||||||
|
class IteratorList;
|
||||||
|
friend class Iterator;
|
||||||
|
friend struct IteratorPolicy;
|
||||||
|
|
||||||
|
friend class AttributeIndexer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _AddIteratorToUpdate(Iterator* iterator);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeTree* fNodes;
|
||||||
|
IteratorList* fIteratorsToUpdate;
|
||||||
|
AttributeIndexer* fIndexer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ATTRIBUTE_INDEX_H
|
42
src/add-ons/kernel/file_systems/packagefs/AttributeIndexer.h
Normal file
42
src/add-ons/kernel/file_systems/packagefs/AttributeIndexer.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ATTRIBUTE_INDEXER_H
|
||||||
|
#define ATTRIBUTE_INDEXER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndex;
|
||||||
|
class AttributeIndexTreeValue;
|
||||||
|
class IndexedAttributeOwner;
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndexer {
|
||||||
|
public:
|
||||||
|
AttributeIndexer(AttributeIndex* index);
|
||||||
|
~AttributeIndexer();
|
||||||
|
|
||||||
|
status_t CreateCookie(IndexedAttributeOwner* owner,
|
||||||
|
void* attributeCookie, uint32 attributeType,
|
||||||
|
size_t attributeSize, void*& _data,
|
||||||
|
size_t& _toRead);
|
||||||
|
void DeleteCookie();
|
||||||
|
|
||||||
|
AttributeIndexTreeValue* Cookie() const
|
||||||
|
{ return fCookie; }
|
||||||
|
|
||||||
|
const char* IndexName() const
|
||||||
|
{ return fIndexName; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
AttributeIndex* fIndex;
|
||||||
|
const char* fIndexName;
|
||||||
|
uint32 fIndexType;
|
||||||
|
AttributeIndexTreeValue* fCookie;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ATTRIBUTE_INDEX_H
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "IndexedAttributeOwner.h"
|
||||||
|
|
||||||
|
|
||||||
|
IndexedAttributeOwner::~IndexedAttributeOwner()
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef INDEXED_ATTRIBUTE_OWNER_H
|
||||||
|
#define INDEXED_ATTRIBUTE_OWNER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class IndexedAttributeOwner {
|
||||||
|
public:
|
||||||
|
virtual ~IndexedAttributeOwner();
|
||||||
|
|
||||||
|
virtual void UnsetIndexCookie(void* attributeCookie) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // INDEXED_ATTRIBUTE_OWNER_H
|
@ -9,6 +9,7 @@ UsePrivateHeaders shared storage ;
|
|||||||
HAIKU_PACKAGE_FS_SOURCES =
|
HAIKU_PACKAGE_FS_SOURCES =
|
||||||
AttributeCookie.cpp
|
AttributeCookie.cpp
|
||||||
AttributeDirectoryCookie.cpp
|
AttributeDirectoryCookie.cpp
|
||||||
|
AttributeIndex.cpp
|
||||||
AutoPackageAttributes.cpp
|
AutoPackageAttributes.cpp
|
||||||
BlockBufferCacheKernel.cpp
|
BlockBufferCacheKernel.cpp
|
||||||
DebugSupport.cpp
|
DebugSupport.cpp
|
||||||
@ -17,6 +18,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
|||||||
EmptyAttributeDirectoryCookie.cpp
|
EmptyAttributeDirectoryCookie.cpp
|
||||||
GlobalFactory.cpp
|
GlobalFactory.cpp
|
||||||
Index.cpp
|
Index.cpp
|
||||||
|
IndexedAttributeOwner.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
LastModifiedIndex.cpp
|
LastModifiedIndex.cpp
|
||||||
NameIndex.cpp
|
NameIndex.cpp
|
||||||
|
@ -77,3 +77,17 @@ Node::SetParent(Directory* parent)
|
|||||||
{
|
{
|
||||||
fParent = parent;
|
fParent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Node::IndexAttribute(AttributeIndexer* indexer)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
Node::IndexCookieForAttribute(const char* name) const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
class AttributeCookie;
|
class AttributeCookie;
|
||||||
class AttributeDirectoryCookie;
|
class AttributeDirectoryCookie;
|
||||||
|
class AttributeIndexer;
|
||||||
class Directory;
|
class Directory;
|
||||||
class PackageNode;
|
class PackageNode;
|
||||||
|
|
||||||
@ -83,6 +84,9 @@ public:
|
|||||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||||
AttributeCookie*& _cookie) = 0;
|
AttributeCookie*& _cookie) = 0;
|
||||||
|
|
||||||
|
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||||
|
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
rw_lock fLock;
|
rw_lock fLock;
|
||||||
ino_t fID;
|
ino_t fID;
|
||||||
|
@ -15,6 +15,13 @@ OldNodeAttributes::~OldNodeAttributes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
OldNodeAttributes::IndexCookieForAttribute(const char* name) const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - NodeListener
|
// #pragma mark - NodeListener
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ public:
|
|||||||
|
|
||||||
virtual timespec ModifiedTime() const = 0;
|
virtual timespec ModifiedTime() const = 0;
|
||||||
virtual off_t FileSize() const = 0;
|
virtual off_t FileSize() const = 0;
|
||||||
|
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,3 +33,11 @@ OldUnpackingNodeAttributes::FileSize() const
|
|||||||
{
|
{
|
||||||
return fPackageNode != NULL ? fPackageNode->FileSize() : 0;
|
return fPackageNode != NULL ? fPackageNode->FileSize() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
OldUnpackingNodeAttributes::IndexCookieForAttribute(const char* name) const
|
||||||
|
{
|
||||||
|
return fPackageNode != NULL
|
||||||
|
? fPackageNode->IndexCookieForAttribute(name) : NULL;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ public:
|
|||||||
|
|
||||||
virtual timespec ModifiedTime() const;
|
virtual timespec ModifiedTime() const;
|
||||||
virtual off_t FileSize() const;
|
virtual off_t FileSize() const;
|
||||||
|
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PackageNode* fPackageNode;
|
PackageNode* fPackageNode;
|
||||||
|
@ -90,3 +90,10 @@ PackageNode::FindAttribute(const char* name) const
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageNode::UnsetIndexCookie(void* attributeCookie)
|
||||||
|
{
|
||||||
|
((PackageNodeAttribute*)attributeCookie)->SetIndexCookie(NULL);
|
||||||
|
}
|
||||||
|
@ -12,14 +12,16 @@
|
|||||||
|
|
||||||
#include <util/SinglyLinkedList.h>
|
#include <util/SinglyLinkedList.h>
|
||||||
|
|
||||||
|
#include "IndexedAttributeOwner.h"
|
||||||
#include "PackageNodeAttribute.h"
|
#include "PackageNodeAttribute.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndexer;
|
||||||
class Package;
|
class Package;
|
||||||
class PackageDirectory;
|
class PackageDirectory;
|
||||||
|
|
||||||
|
|
||||||
class PackageNode : public BReferenceable,
|
class PackageNode : public BReferenceable, public IndexedAttributeOwner,
|
||||||
public SinglyLinkedListLinkImpl<PackageNode> {
|
public SinglyLinkedListLinkImpl<PackageNode> {
|
||||||
public:
|
public:
|
||||||
PackageNode(Package* package, mode_t mode);
|
PackageNode(Package* package, mode_t mode);
|
||||||
@ -59,6 +61,10 @@ public:
|
|||||||
|
|
||||||
PackageNodeAttribute* FindAttribute(const char* name) const;
|
PackageNodeAttribute* FindAttribute(const char* name) const;
|
||||||
|
|
||||||
|
virtual void UnsetIndexCookie(void* attributeCookie);
|
||||||
|
|
||||||
|
inline void* IndexCookieForAttribute(const char* name) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Package* fPackage;
|
Package* fPackage;
|
||||||
PackageDirectory* fParent;
|
PackageDirectory* fParent;
|
||||||
@ -71,6 +77,14 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
PackageNode::IndexCookieForAttribute(const char* name) const
|
||||||
|
{
|
||||||
|
PackageNodeAttribute* attribute = FindAttribute(name);
|
||||||
|
return attribute != NULL ? attribute->IndexCookie() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef SinglyLinkedList<PackageNode> PackageNodeList;
|
typedef SinglyLinkedList<PackageNode> PackageNodeList;
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ PackageNodeAttribute::PackageNodeAttribute(uint32 type,
|
|||||||
:
|
:
|
||||||
fData(data),
|
fData(data),
|
||||||
fName(NULL),
|
fName(NULL),
|
||||||
|
fIndexCookie(NULL),
|
||||||
fType(type)
|
fType(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,15 @@ public:
|
|||||||
|
|
||||||
status_t Init(const char* name);
|
status_t Init(const char* name);
|
||||||
|
|
||||||
|
void SetIndexCookie(void* cookie)
|
||||||
|
{ fIndexCookie = cookie; }
|
||||||
|
void* IndexCookie() const
|
||||||
|
{ return fIndexCookie; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BPackageData fData;
|
BPackageData fData;
|
||||||
char* fName;
|
char* fName;
|
||||||
|
void* fIndexCookie;
|
||||||
uint32 fType;
|
uint32 fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "AttributeIndexer.h"
|
||||||
#include "AutoPackageAttributes.h"
|
#include "AutoPackageAttributes.h"
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
#include "GlobalFactory.h"
|
#include "GlobalFactory.h"
|
||||||
@ -108,21 +109,7 @@ status_t
|
|||||||
UnpackingAttributeCookie::ReadAttribute(off_t offset, void* buffer,
|
UnpackingAttributeCookie::ReadAttribute(off_t offset, void* buffer,
|
||||||
size_t* bufferSize)
|
size_t* bufferSize)
|
||||||
{
|
{
|
||||||
const BPackageData& data = fAttribute->Data();
|
return ReadAttribute(fPackageNode, fAttribute, offset, buffer, bufferSize);
|
||||||
if (data.IsEncodedInline()) {
|
|
||||||
// inline data
|
|
||||||
BBufferDataReader dataReader(data.InlineData(), data.CompressedSize());
|
|
||||||
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// data not inline -- open the package
|
|
||||||
int fd = fPackage->Open();
|
|
||||||
if (fd < 0)
|
|
||||||
RETURN_ERROR(fd);
|
|
||||||
PackageCloser packageCloser(fPackage);
|
|
||||||
|
|
||||||
BFDDataReader dataReader(fd);
|
|
||||||
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -134,3 +121,63 @@ UnpackingAttributeCookie::ReadAttributeStat(struct stat* st)
|
|||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
UnpackingAttributeCookie::ReadAttribute(PackageNode* packageNode,
|
||||||
|
PackageNodeAttribute* attribute, off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize)
|
||||||
|
{
|
||||||
|
const BPackageData& data = attribute->Data();
|
||||||
|
if (data.IsEncodedInline()) {
|
||||||
|
// inline data
|
||||||
|
BBufferDataReader dataReader(data.InlineData(), data.CompressedSize());
|
||||||
|
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// data not inline -- open the package
|
||||||
|
Package* package = packageNode->GetPackage();
|
||||||
|
int fd = package->Open();
|
||||||
|
if (fd < 0)
|
||||||
|
RETURN_ERROR(fd);
|
||||||
|
PackageCloser packageCloser(package);
|
||||||
|
|
||||||
|
BFDDataReader dataReader(fd);
|
||||||
|
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
UnpackingAttributeCookie::IndexAttribute(PackageNode* packageNode,
|
||||||
|
AttributeIndexer* indexer)
|
||||||
|
{
|
||||||
|
if (packageNode == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// get the attribute
|
||||||
|
PackageNodeAttribute* attribute = packageNode->FindAttribute(
|
||||||
|
indexer->IndexName());
|
||||||
|
if (attribute == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// create the index cookie
|
||||||
|
void* data;
|
||||||
|
size_t toRead;
|
||||||
|
status_t error = indexer->CreateCookie(packageNode, attribute,
|
||||||
|
attribute->Type(), attribute->Data().UncompressedSize(), data, toRead);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// read the attribute
|
||||||
|
if (toRead > 0) {
|
||||||
|
error = ReadAttribute(packageNode, attribute, 0, data, &toRead);
|
||||||
|
if (error != B_OK) {
|
||||||
|
indexer->DeleteCookie();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute->SetIndexCookie(indexer->Cookie());
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "AttributeCookie.h"
|
#include "AttributeCookie.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeIndexer;
|
||||||
class Package;
|
class Package;
|
||||||
class PackageNode;
|
class PackageNode;
|
||||||
class PackageNodeAttribute;
|
class PackageNodeAttribute;
|
||||||
@ -29,6 +30,13 @@ public:
|
|||||||
size_t* bufferSize);
|
size_t* bufferSize);
|
||||||
virtual status_t ReadAttributeStat(struct stat* st);
|
virtual status_t ReadAttributeStat(struct stat* st);
|
||||||
|
|
||||||
|
static status_t ReadAttribute(PackageNode* packageNode,
|
||||||
|
PackageNodeAttribute* attribute,
|
||||||
|
off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize);
|
||||||
|
static status_t IndexAttribute(PackageNode* packageNode,
|
||||||
|
AttributeIndexer* indexer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PackageNode* fPackageNode;
|
PackageNode* fPackageNode;
|
||||||
Package* fPackage;
|
Package* fPackage;
|
||||||
|
@ -149,6 +149,23 @@ UnpackingDirectory::OpenAttribute(const char* name, int openMode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
UnpackingDirectory::IndexAttribute(AttributeIndexer* indexer)
|
||||||
|
{
|
||||||
|
return UnpackingAttributeCookie::IndexAttribute(fPackageDirectories.Head(),
|
||||||
|
indexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
UnpackingDirectory::IndexCookieForAttribute(const char* name) const
|
||||||
|
{
|
||||||
|
if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
|
||||||
|
return packageDirectory->IndexCookieForAttribute(name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - RootDirectory
|
// #pragma mark - RootDirectory
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ public:
|
|||||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||||
AttributeCookie*& _cookie);
|
AttributeCookie*& _cookie);
|
||||||
|
|
||||||
|
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||||
|
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PackageDirectoryList fPackageDirectories;
|
PackageDirectoryList fPackageDirectories;
|
||||||
};
|
};
|
||||||
|
@ -210,3 +210,20 @@ UnpackingLeafNode::OpenAttribute(const char* name, int openMode,
|
|||||||
return UnpackingAttributeCookie::Open(fPackageNodes.Head(), name, openMode,
|
return UnpackingAttributeCookie::Open(fPackageNodes.Head(), name, openMode,
|
||||||
_cookie);
|
_cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
UnpackingLeafNode::IndexAttribute(AttributeIndexer* indexer)
|
||||||
|
{
|
||||||
|
return UnpackingAttributeCookie::IndexAttribute(fPackageNodes.Head(),
|
||||||
|
indexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
UnpackingLeafNode::IndexCookieForAttribute(const char* name) const
|
||||||
|
{
|
||||||
|
if (PackageLeafNode* packageNode = fPackageNodes.Head())
|
||||||
|
return packageNode->IndexCookieForAttribute(name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,9 @@ public:
|
|||||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||||
AttributeCookie*& _cookie);
|
AttributeCookie*& _cookie);
|
||||||
|
|
||||||
|
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||||
|
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PackageLeafNodeList fPackageNodes;
|
PackageLeafNodeList fPackageNodes;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user