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 =
|
||||
AttributeCookie.cpp
|
||||
AttributeDirectoryCookie.cpp
|
||||
AttributeIndex.cpp
|
||||
AutoPackageAttributes.cpp
|
||||
BlockBufferCacheKernel.cpp
|
||||
DebugSupport.cpp
|
||||
@ -17,6 +18,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
||||
EmptyAttributeDirectoryCookie.cpp
|
||||
GlobalFactory.cpp
|
||||
Index.cpp
|
||||
IndexedAttributeOwner.cpp
|
||||
kernel_interface.cpp
|
||||
LastModifiedIndex.cpp
|
||||
NameIndex.cpp
|
||||
|
@ -77,3 +77,17 @@ Node::SetParent(Directory* 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 AttributeDirectoryCookie;
|
||||
class AttributeIndexer;
|
||||
class Directory;
|
||||
class PackageNode;
|
||||
|
||||
@ -83,6 +84,9 @@ public:
|
||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||
AttributeCookie*& _cookie) = 0;
|
||||
|
||||
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
|
||||
protected:
|
||||
rw_lock fLock;
|
||||
ino_t fID;
|
||||
|
@ -15,6 +15,13 @@ OldNodeAttributes::~OldNodeAttributes()
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
OldNodeAttributes::IndexCookieForAttribute(const char* name) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - NodeListener
|
||||
|
||||
|
||||
|
@ -24,6 +24,7 @@ public:
|
||||
|
||||
virtual timespec ModifiedTime() 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;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
OldUnpackingNodeAttributes::IndexCookieForAttribute(const char* name) const
|
||||
{
|
||||
return fPackageNode != NULL
|
||||
? fPackageNode->IndexCookieForAttribute(name) : NULL;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
|
||||
virtual timespec ModifiedTime() const;
|
||||
virtual off_t FileSize() const;
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
|
||||
private:
|
||||
PackageNode* fPackageNode;
|
||||
|
@ -90,3 +90,10 @@ PackageNode::FindAttribute(const char* name) const
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageNode::UnsetIndexCookie(void* attributeCookie)
|
||||
{
|
||||
((PackageNodeAttribute*)attributeCookie)->SetIndexCookie(NULL);
|
||||
}
|
||||
|
@ -12,14 +12,16 @@
|
||||
|
||||
#include <util/SinglyLinkedList.h>
|
||||
|
||||
#include "IndexedAttributeOwner.h"
|
||||
#include "PackageNodeAttribute.h"
|
||||
|
||||
|
||||
class AttributeIndexer;
|
||||
class Package;
|
||||
class PackageDirectory;
|
||||
|
||||
|
||||
class PackageNode : public BReferenceable,
|
||||
class PackageNode : public BReferenceable, public IndexedAttributeOwner,
|
||||
public SinglyLinkedListLinkImpl<PackageNode> {
|
||||
public:
|
||||
PackageNode(Package* package, mode_t mode);
|
||||
@ -59,6 +61,10 @@ public:
|
||||
|
||||
PackageNodeAttribute* FindAttribute(const char* name) const;
|
||||
|
||||
virtual void UnsetIndexCookie(void* attributeCookie);
|
||||
|
||||
inline void* IndexCookieForAttribute(const char* name) const;
|
||||
|
||||
protected:
|
||||
Package* fPackage;
|
||||
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;
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@ PackageNodeAttribute::PackageNodeAttribute(uint32 type,
|
||||
:
|
||||
fData(data),
|
||||
fName(NULL),
|
||||
fIndexCookie(NULL),
|
||||
fType(type)
|
||||
{
|
||||
}
|
||||
|
@ -29,10 +29,15 @@ public:
|
||||
|
||||
status_t Init(const char* name);
|
||||
|
||||
void SetIndexCookie(void* cookie)
|
||||
{ fIndexCookie = cookie; }
|
||||
void* IndexCookie() const
|
||||
{ return fIndexCookie; }
|
||||
|
||||
protected:
|
||||
BPackageData fData;
|
||||
char* fName;
|
||||
void* fIndexCookie;
|
||||
uint32 fType;
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "AttributeIndexer.h"
|
||||
#include "AutoPackageAttributes.h"
|
||||
#include "DebugSupport.h"
|
||||
#include "GlobalFactory.h"
|
||||
@ -108,21 +109,7 @@ status_t
|
||||
UnpackingAttributeCookie::ReadAttribute(off_t offset, void* buffer,
|
||||
size_t* bufferSize)
|
||||
{
|
||||
const BPackageData& data = fAttribute->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
|
||||
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);
|
||||
return ReadAttribute(fPackageNode, fAttribute, offset, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
@ -134,3 +121,63 @@ UnpackingAttributeCookie::ReadAttributeStat(struct stat* st)
|
||||
|
||||
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"
|
||||
|
||||
|
||||
class AttributeIndexer;
|
||||
class Package;
|
||||
class PackageNode;
|
||||
class PackageNodeAttribute;
|
||||
@ -29,6 +30,13 @@ public:
|
||||
size_t* bufferSize);
|
||||
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:
|
||||
PackageNode* fPackageNode;
|
||||
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
|
||||
|
||||
|
||||
|
@ -34,6 +34,9 @@ public:
|
||||
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||
AttributeCookie*& _cookie);
|
||||
|
||||
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
|
||||
private:
|
||||
PackageDirectoryList fPackageDirectories;
|
||||
};
|
||||
|
@ -210,3 +210,20 @@ UnpackingLeafNode::OpenAttribute(const char* name, int openMode,
|
||||
return UnpackingAttributeCookie::Open(fPackageNodes.Head(), name, openMode,
|
||||
_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,
|
||||
AttributeCookie*& _cookie);
|
||||
|
||||
virtual status_t IndexAttribute(AttributeIndexer* indexer);
|
||||
virtual void* IndexCookieForAttribute(const char* name) const;
|
||||
|
||||
private:
|
||||
PackageLeafNodeList fPackageNodes;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user