diff --git a/src/add-ons/kernel/file_systems/packagefs/AttributeIndex.cpp b/src/add-ons/kernel/file_systems/packagefs/AttributeIndex.cpp new file mode 100644 index 0000000000..3488ce32a8 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/AttributeIndex.cpp @@ -0,0 +1,410 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "AttributeIndex.h" + +#include + +#include + +#include +#include + +#include + +#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(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 { + typedef TreeValue Node; + + NodeTree(const TreeDefinition& definition) + : + AVLTree(definition) + { + } +}; + + +// #pragma mark - IteratorList + + +class AttributeIndex::IteratorList : public SinglyLinkedList {}; + + +// #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, + public SinglyLinkedListLinkImpl { +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); +} diff --git a/src/add-ons/kernel/file_systems/packagefs/AttributeIndex.h b/src/add-ons/kernel/file_systems/packagefs/AttributeIndex.h new file mode 100644 index 0000000000..c0e3f1fb58 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/AttributeIndex.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/AttributeIndexer.h b/src/add-ons/kernel/file_systems/packagefs/AttributeIndexer.h new file mode 100644 index 0000000000..f332b29f69 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/AttributeIndexer.h @@ -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 + + +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 diff --git a/src/add-ons/kernel/file_systems/packagefs/IndexedAttributeOwner.cpp b/src/add-ons/kernel/file_systems/packagefs/IndexedAttributeOwner.cpp new file mode 100644 index 0000000000..7e173633ab --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/IndexedAttributeOwner.cpp @@ -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() +{ +} diff --git a/src/add-ons/kernel/file_systems/packagefs/IndexedAttributeOwner.h b/src/add-ons/kernel/file_systems/packagefs/IndexedAttributeOwner.h new file mode 100644 index 0000000000..76bcb91edc --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/IndexedAttributeOwner.h @@ -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 + + +class IndexedAttributeOwner { +public: + virtual ~IndexedAttributeOwner(); + + virtual void UnsetIndexCookie(void* attributeCookie) = 0; +}; + + +#endif // INDEXED_ATTRIBUTE_OWNER_H diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index cc5c5e1d70..d0576a0423 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/Node.cpp b/src/add-ons/kernel/file_systems/packagefs/Node.cpp index 2ed70e2669..f452c913a7 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Node.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Node.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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/Node.h b/src/add-ons/kernel/file_systems/packagefs/Node.h index fce665329e..d7465af16c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Node.h +++ b/src/add-ons/kernel/file_systems/packagefs/Node.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/NodeListener.cpp b/src/add-ons/kernel/file_systems/packagefs/NodeListener.cpp index ae77b4c1dc..d38064ed32 100644 --- a/src/add-ons/kernel/file_systems/packagefs/NodeListener.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/NodeListener.cpp @@ -15,6 +15,13 @@ OldNodeAttributes::~OldNodeAttributes() } +void* +OldNodeAttributes::IndexCookieForAttribute(const char* name) const +{ + return NULL; +} + + // #pragma mark - NodeListener diff --git a/src/add-ons/kernel/file_systems/packagefs/NodeListener.h b/src/add-ons/kernel/file_systems/packagefs/NodeListener.h index 35ab10e19a..1d583acb4b 100644 --- a/src/add-ons/kernel/file_systems/packagefs/NodeListener.h +++ b/src/add-ons/kernel/file_systems/packagefs/NodeListener.h @@ -24,6 +24,7 @@ public: virtual timespec ModifiedTime() const = 0; virtual off_t FileSize() const = 0; + virtual void* IndexCookieForAttribute(const char* name) const; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.cpp b/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.cpp index f4508edb41..173a1daf6a 100644 --- a/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.cpp @@ -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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.h b/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.h index 867ab0741f..c9f348360b 100644 --- a/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.h +++ b/src/add-ons/kernel/file_systems/packagefs/OldUnpackingNodeAttributes.h @@ -19,6 +19,7 @@ public: virtual timespec ModifiedTime() const; virtual off_t FileSize() const; + virtual void* IndexCookieForAttribute(const char* name) const; private: PackageNode* fPackageNode; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp index 7291a0f381..585907afe4 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp @@ -90,3 +90,10 @@ PackageNode::FindAttribute(const char* name) const return NULL; } + + +void +PackageNode::UnsetIndexCookie(void* attributeCookie) +{ + ((PackageNodeAttribute*)attributeCookie)->SetIndexCookie(NULL); +} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNode.h b/src/add-ons/kernel/file_systems/packagefs/PackageNode.h index 1b215ec363..ec6a57fdc5 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNode.h @@ -12,14 +12,16 @@ #include +#include "IndexedAttributeOwner.h" #include "PackageNodeAttribute.h" +class AttributeIndexer; class Package; class PackageDirectory; -class PackageNode : public BReferenceable, +class PackageNode : public BReferenceable, public IndexedAttributeOwner, public SinglyLinkedListLinkImpl { 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 PackageNodeList; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp index e63b578652..cd80d831ac 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp @@ -15,6 +15,7 @@ PackageNodeAttribute::PackageNodeAttribute(uint32 type, : fData(data), fName(NULL), + fIndexCookie(NULL), fType(type) { } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h index f899a04a0c..361dd81647 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h @@ -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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp index 8804dcbd93..714bb7d780 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp @@ -15,6 +15,7 @@ #include +#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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.h b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.h index 9dda846775..8a20257efa 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.h +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.cpp index dad396e1e9..7c70b523b0 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.cpp @@ -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 diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.h b/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.h index ce2b4a8578..bb94156e9a 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingDirectory.h @@ -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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.cpp b/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.cpp index 6504ac718a..80ca1b96a3 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.cpp @@ -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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.h b/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.h index 3ebffbd28b..b9ed5de547 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingLeafNode.h @@ -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; };