xref: /haiku/src/add-ons/kernel/file_systems/packagefs/indices/Query.cpp (revision bb1f240594d1524129ed34853f0c325b1a6a1a43)
11e7416d9SIngo Weinhold /*
21e7416d9SIngo Weinhold  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
31e7416d9SIngo Weinhold  * Distributed under the terms of the MIT License.
41e7416d9SIngo Weinhold  */
51e7416d9SIngo Weinhold 
61e7416d9SIngo Weinhold 
71e7416d9SIngo Weinhold #include "Query.h"
81e7416d9SIngo Weinhold 
91e7416d9SIngo Weinhold #include <file_systems/QueryParser.h>
101e7416d9SIngo Weinhold 
111e7416d9SIngo Weinhold #include "AttributeCookie.h"
121e7416d9SIngo Weinhold #include "Directory.h"
131e7416d9SIngo Weinhold #include "Index.h"
141e7416d9SIngo Weinhold #include "Node.h"
151e7416d9SIngo Weinhold #include "Volume.h"
161e7416d9SIngo Weinhold 
171e7416d9SIngo Weinhold 
181e7416d9SIngo Weinhold // #pragma mark - QueryPolicy
191e7416d9SIngo Weinhold 
201e7416d9SIngo Weinhold 
211e7416d9SIngo Weinhold struct Query::QueryPolicy {
221e7416d9SIngo Weinhold 	typedef Query Context;
231e7416d9SIngo Weinhold 	typedef ::Node Entry;
241e7416d9SIngo Weinhold 	typedef ::Node Node;
253a17bd35SAugustin Cavalier 	typedef void* NodeHolder;
261e7416d9SIngo Weinhold 
271e7416d9SIngo Weinhold 	struct Index {
281e7416d9SIngo Weinhold 		Query*		query;
291e7416d9SIngo Weinhold 		::Index*	index;
301e7416d9SIngo Weinhold 
IndexQuery::QueryPolicy::Index311e7416d9SIngo Weinhold 		Index(Context* context)
321e7416d9SIngo Weinhold 			:
331e7416d9SIngo Weinhold 			query(context)
341e7416d9SIngo Weinhold 		{
351e7416d9SIngo Weinhold 		}
361e7416d9SIngo Weinhold 	};
371e7416d9SIngo Weinhold 
381e7416d9SIngo Weinhold 	struct IndexIterator : ::IndexIterator {
391e7416d9SIngo Weinhold 		::Index*			index;
403a17bd35SAugustin Cavalier 		Entry*				entry;
411e7416d9SIngo Weinhold 
IndexIteratorQuery::QueryPolicy::IndexIterator421e7416d9SIngo Weinhold 		IndexIterator(::Index* index)
431e7416d9SIngo Weinhold 			:
441e7416d9SIngo Weinhold 			index(index)
451e7416d9SIngo Weinhold 		{
461e7416d9SIngo Weinhold 		}
471e7416d9SIngo Weinhold 	};
481e7416d9SIngo Weinhold 
491e7416d9SIngo Weinhold 	static const int32 kMaxFileNameLength = B_FILE_NAME_LENGTH;
501e7416d9SIngo Weinhold 
511e7416d9SIngo Weinhold 	// Entry interface
521e7416d9SIngo Weinhold 
EntryGetParentIDQuery::QueryPolicy531e7416d9SIngo Weinhold 	static ino_t EntryGetParentID(Entry* entry)
541e7416d9SIngo Weinhold 	{
550059775cSAugustin Cavalier 		return entry->GetParentUnchecked()->ID();
561e7416d9SIngo Weinhold 	}
571e7416d9SIngo Weinhold 
EntryGetNodeQuery::QueryPolicy581e7416d9SIngo Weinhold 	static Node* EntryGetNode(Entry* entry)
591e7416d9SIngo Weinhold 	{
601e7416d9SIngo Weinhold 		return entry;
611e7416d9SIngo Weinhold 	}
621e7416d9SIngo Weinhold 
EntryGetNodeIDQuery::QueryPolicy631e7416d9SIngo Weinhold 	static ino_t EntryGetNodeID(Entry* entry)
641e7416d9SIngo Weinhold 	{
651e7416d9SIngo Weinhold 		return entry->ID();
661e7416d9SIngo Weinhold 	}
671e7416d9SIngo Weinhold 
EntryGetNameQuery::QueryPolicy681e7416d9SIngo Weinhold 	static ssize_t EntryGetName(Entry* entry, void* buffer, size_t bufferSize)
691e7416d9SIngo Weinhold 	{
701e7416d9SIngo Weinhold 		const char* name = entry->Name();
711e7416d9SIngo Weinhold 		size_t nameLength = strlen(name);
721e7416d9SIngo Weinhold 		if (nameLength >= bufferSize)
731e7416d9SIngo Weinhold 			return B_BUFFER_OVERFLOW;
741e7416d9SIngo Weinhold 
751e7416d9SIngo Weinhold 		memcpy(buffer, name, nameLength + 1);
761e7416d9SIngo Weinhold 		return nameLength + 1;
771e7416d9SIngo Weinhold 	}
781e7416d9SIngo Weinhold 
EntryGetNameNoCopyQuery::QueryPolicy793a17bd35SAugustin Cavalier 	static const char* EntryGetNameNoCopy(NodeHolder& holder, Entry* entry)
801e7416d9SIngo Weinhold 	{
811e7416d9SIngo Weinhold 		return entry->Name();
821e7416d9SIngo Weinhold 	}
831e7416d9SIngo Weinhold 
841e7416d9SIngo Weinhold 	// Index interface
851e7416d9SIngo Weinhold 
IndexSetToQuery::QueryPolicy861e7416d9SIngo Weinhold 	static status_t IndexSetTo(Index& index, const char* attribute)
871e7416d9SIngo Weinhold 	{
88d07c930cSIngo Weinhold 		index.index = index.query->fVolume->FindIndex(StringKey(attribute));
891e7416d9SIngo Weinhold 		return index.index != NULL ? B_OK : B_ENTRY_NOT_FOUND;
901e7416d9SIngo Weinhold 	}
911e7416d9SIngo Weinhold 
IndexUnsetQuery::QueryPolicy921e7416d9SIngo Weinhold 	static void IndexUnset(Index& index)
931e7416d9SIngo Weinhold 	{
941e7416d9SIngo Weinhold 		index.index = NULL;
951e7416d9SIngo Weinhold 	}
961e7416d9SIngo Weinhold 
IndexGetSizeQuery::QueryPolicy97*bb1f2405SAugustin Cavalier 	static int32 IndexGetSize(Index& index)
981e7416d9SIngo Weinhold 	{
99*bb1f2405SAugustin Cavalier 		return index.index->CountEntries();
1001e7416d9SIngo Weinhold 	}
1011e7416d9SIngo Weinhold 
IndexGetTypeQuery::QueryPolicy1021e7416d9SIngo Weinhold 	static type_code IndexGetType(Index& index)
1031e7416d9SIngo Weinhold 	{
1041e7416d9SIngo Weinhold 		return index.index->Type();
1051e7416d9SIngo Weinhold 	}
1061e7416d9SIngo Weinhold 
IndexGetKeySizeQuery::QueryPolicy1071e7416d9SIngo Weinhold 	static int32 IndexGetKeySize(Index& index)
1081e7416d9SIngo Weinhold 	{
1091e7416d9SIngo Weinhold 		return index.index->KeyLength();
1101e7416d9SIngo Weinhold 	}
1111e7416d9SIngo Weinhold 
IndexCreateIteratorQuery::QueryPolicy1121e7416d9SIngo Weinhold 	static IndexIterator* IndexCreateIterator(Index& index)
1131e7416d9SIngo Weinhold 	{
1141e7416d9SIngo Weinhold 		IndexIterator* iterator = new(std::nothrow) IndexIterator(index.index);
1151e7416d9SIngo Weinhold 		if (iterator == NULL)
1161e7416d9SIngo Weinhold 			return NULL;
1171e7416d9SIngo Weinhold 
1181e7416d9SIngo Weinhold 		if (!index.index->GetIterator(*iterator)) {
1191e7416d9SIngo Weinhold 			delete iterator;
1201e7416d9SIngo Weinhold 			return NULL;
1211e7416d9SIngo Weinhold 		}
1221e7416d9SIngo Weinhold 
1231e7416d9SIngo Weinhold 		return iterator;
1241e7416d9SIngo Weinhold 	}
1251e7416d9SIngo Weinhold 
1261e7416d9SIngo Weinhold 	// IndexIterator interface
1271e7416d9SIngo Weinhold 
IndexIteratorDeleteQuery::QueryPolicy1281e7416d9SIngo Weinhold 	static void IndexIteratorDelete(IndexIterator* indexIterator)
1291e7416d9SIngo Weinhold 	{
1301e7416d9SIngo Weinhold 		delete indexIterator;
1311e7416d9SIngo Weinhold 	}
1321e7416d9SIngo Weinhold 
IndexIteratorFindQuery::QueryPolicy1331e7416d9SIngo Weinhold 	static status_t IndexIteratorFind(IndexIterator* indexIterator,
1341e7416d9SIngo Weinhold 		const void* value, size_t size)
1351e7416d9SIngo Weinhold 	{
1361e7416d9SIngo Weinhold 		if (!indexIterator->index->Find(value, size, *indexIterator))
1371e7416d9SIngo Weinhold 			return B_ENTRY_NOT_FOUND;
1381e7416d9SIngo Weinhold 
1391e7416d9SIngo Weinhold 		return B_OK;
1401e7416d9SIngo Weinhold 	}
1411e7416d9SIngo Weinhold 
IndexIteratorFetchNextEntryQuery::QueryPolicy1423a17bd35SAugustin Cavalier 	static status_t IndexIteratorFetchNextEntry(IndexIterator* indexIterator,
1433a17bd35SAugustin Cavalier 		void* value, size_t* _valueLength, size_t bufferSize, size_t* duplicate)
1441e7416d9SIngo Weinhold 	{
1451e7416d9SIngo Weinhold 		Node* node = indexIterator->Next(value, _valueLength);
1461e7416d9SIngo Weinhold 		if (node == NULL)
1471e7416d9SIngo Weinhold 			return B_ENTRY_NOT_FOUND;
1481e7416d9SIngo Weinhold 
1493a17bd35SAugustin Cavalier 		indexIterator->entry = node;
1501e7416d9SIngo Weinhold 		return B_OK;
1511e7416d9SIngo Weinhold 	}
1521e7416d9SIngo Weinhold 
IndexIteratorGetEntryQuery::QueryPolicy1533a17bd35SAugustin Cavalier 	static status_t IndexIteratorGetEntry(Context* context, IndexIterator* indexIterator,
1543a17bd35SAugustin Cavalier 		NodeHolder& holder, Entry** _entry)
1553a17bd35SAugustin Cavalier 	{
1563a17bd35SAugustin Cavalier 		*_entry = indexIterator->entry;
1573a17bd35SAugustin Cavalier 		return B_OK;
1583a17bd35SAugustin Cavalier 	}
1593a17bd35SAugustin Cavalier 
IndexIteratorSkipDuplicatesQuery::QueryPolicy1603a17bd35SAugustin Cavalier 	static void IndexIteratorSkipDuplicates(IndexIterator* indexIterator)
1613a17bd35SAugustin Cavalier 	{
1623a17bd35SAugustin Cavalier 		// Nothing to do.
1633a17bd35SAugustin Cavalier 	}
1643a17bd35SAugustin Cavalier 
IndexIteratorSuspendQuery::QueryPolicy1651e7416d9SIngo Weinhold 	static void IndexIteratorSuspend(IndexIterator* indexIterator)
1661e7416d9SIngo Weinhold 	{
1671e7416d9SIngo Weinhold 		indexIterator->Suspend();
1681e7416d9SIngo Weinhold 	}
1691e7416d9SIngo Weinhold 
IndexIteratorResumeQuery::QueryPolicy1701e7416d9SIngo Weinhold 	static void IndexIteratorResume(IndexIterator* indexIterator)
1711e7416d9SIngo Weinhold 	{
1721e7416d9SIngo Weinhold 		indexIterator->Resume();
1731e7416d9SIngo Weinhold 	}
1741e7416d9SIngo Weinhold 
1751e7416d9SIngo Weinhold 	// Node interface
1761e7416d9SIngo Weinhold 
NodeGetSizeQuery::QueryPolicy1771e7416d9SIngo Weinhold 	static const off_t NodeGetSize(Node* node)
1781e7416d9SIngo Weinhold 	{
1791e7416d9SIngo Weinhold 		return node->FileSize();
1801e7416d9SIngo Weinhold 	}
1811e7416d9SIngo Weinhold 
NodeGetLastModifiedTimeQuery::QueryPolicy1821e7416d9SIngo Weinhold 	static time_t NodeGetLastModifiedTime(Node* node)
1831e7416d9SIngo Weinhold 	{
1841e7416d9SIngo Weinhold 		return node->ModifiedTime().tv_sec;
1851e7416d9SIngo Weinhold 	}
1861e7416d9SIngo Weinhold 
NodeGetAttributeQuery::QueryPolicy1873a17bd35SAugustin Cavalier 	static status_t NodeGetAttribute(NodeHolder& nodeHolder, Node* node,
1883a17bd35SAugustin Cavalier 		const char* attribute, void* buffer, size_t* _size, int32* _type)
1891e7416d9SIngo Weinhold 	{
1901e7416d9SIngo Weinhold 		// TODO: Creating a cookie is quite a bit of overhead.
1911e7416d9SIngo Weinhold 		AttributeCookie* cookie;
192d07c930cSIngo Weinhold 		status_t error = node->OpenAttribute(StringKey(attribute), O_RDONLY,
193d07c930cSIngo Weinhold 			cookie);
1941e7416d9SIngo Weinhold 		if (error != B_OK)
1951e7416d9SIngo Weinhold 			return error;
1961e7416d9SIngo Weinhold 
1971e7416d9SIngo Weinhold 		error = cookie->ReadAttribute(0, buffer, _size);
1981e7416d9SIngo Weinhold 
1991e7416d9SIngo Weinhold 		// also get the attribute type
2001e7416d9SIngo Weinhold 		if (error == B_OK) {
2011e7416d9SIngo Weinhold 			struct stat st;
2021e7416d9SIngo Weinhold 			error = cookie->ReadAttributeStat(&st);
2031e7416d9SIngo Weinhold 			if (error == B_OK)
2041e7416d9SIngo Weinhold 				*_type = st.st_type;
2051e7416d9SIngo Weinhold 		}
2061e7416d9SIngo Weinhold 
2071e7416d9SIngo Weinhold 		cookie->Close();
2081e7416d9SIngo Weinhold 		delete cookie;
2091e7416d9SIngo Weinhold 
2101e7416d9SIngo Weinhold 		return error;
2111e7416d9SIngo Weinhold 	}
2121e7416d9SIngo Weinhold 
NodeGetFirstReferrerQuery::QueryPolicy2131e7416d9SIngo Weinhold 	static Entry* NodeGetFirstReferrer(Node* node)
2141e7416d9SIngo Weinhold 	{
2151e7416d9SIngo Weinhold 		return node;
2161e7416d9SIngo Weinhold 	}
2171e7416d9SIngo Weinhold 
NodeGetNextReferrerQuery::QueryPolicy2181e7416d9SIngo Weinhold 	static Entry* NodeGetNextReferrer(Node* node, Entry* entry)
2191e7416d9SIngo Weinhold 	{
2201e7416d9SIngo Weinhold 		return NULL;
2211e7416d9SIngo Weinhold 	}
2221e7416d9SIngo Weinhold 
2231e7416d9SIngo Weinhold 	// Volume interface
2241e7416d9SIngo Weinhold 
ContextGetVolumeIDQuery::QueryPolicy2251e7416d9SIngo Weinhold 	static dev_t ContextGetVolumeID(Context* context)
2261e7416d9SIngo Weinhold 	{
2271e7416d9SIngo Weinhold 		return context->fVolume->ID();
2281e7416d9SIngo Weinhold 	}
2291e7416d9SIngo Weinhold };
2301e7416d9SIngo Weinhold 
2311e7416d9SIngo Weinhold 
2321e7416d9SIngo Weinhold // #pragma mark - Query
2331e7416d9SIngo Weinhold 
2341e7416d9SIngo Weinhold 
Query(Volume * volume)2351e7416d9SIngo Weinhold Query::Query(Volume* volume)
2361e7416d9SIngo Weinhold 	:
2371e7416d9SIngo Weinhold 	fVolume(volume),
2381e7416d9SIngo Weinhold 	fImpl(NULL)
2391e7416d9SIngo Weinhold {
2401e7416d9SIngo Weinhold }
2411e7416d9SIngo Weinhold 
2421e7416d9SIngo Weinhold 
~Query()2431e7416d9SIngo Weinhold Query::~Query()
2441e7416d9SIngo Weinhold {
2451e7416d9SIngo Weinhold 	if (fImpl != NULL) {
2461e7416d9SIngo Weinhold 		if ((fImpl->Flags() & B_LIVE_QUERY) != 0)
2471e7416d9SIngo Weinhold 			fVolume->RemoveQuery(this);
2481e7416d9SIngo Weinhold 
2491e7416d9SIngo Weinhold 		delete fImpl;
2501e7416d9SIngo Weinhold 	}
2511e7416d9SIngo Weinhold }
2521e7416d9SIngo Weinhold 
2531e7416d9SIngo Weinhold 
2541e7416d9SIngo Weinhold /*static*/ status_t
Create(Volume * volume,const char * queryString,uint32 flags,port_id port,uint32 token,Query * & _query)2551e7416d9SIngo Weinhold Query::Create(Volume* volume, const char* queryString, uint32 flags,
2561e7416d9SIngo Weinhold 	port_id port, uint32 token, Query*& _query)
2571e7416d9SIngo Weinhold {
2581e7416d9SIngo Weinhold 	Query* query = new(std::nothrow) Query(volume);
2591e7416d9SIngo Weinhold 	if (query == NULL)
2601e7416d9SIngo Weinhold 		return B_NO_MEMORY;
2611e7416d9SIngo Weinhold 
2621e7416d9SIngo Weinhold 	status_t error = query->_Init(queryString, flags, port, token);
2631e7416d9SIngo Weinhold 	if (error != B_OK) {
2641e7416d9SIngo Weinhold 		delete query;
2651e7416d9SIngo Weinhold 		return error;
2661e7416d9SIngo Weinhold 	}
2671e7416d9SIngo Weinhold 
2681e7416d9SIngo Weinhold 	_query = query;
2691e7416d9SIngo Weinhold 	return B_OK;
2701e7416d9SIngo Weinhold }
2711e7416d9SIngo Weinhold 
2721e7416d9SIngo Weinhold 
2731e7416d9SIngo Weinhold status_t
Rewind()2741e7416d9SIngo Weinhold Query::Rewind()
2751e7416d9SIngo Weinhold {
2761e7416d9SIngo Weinhold 	return fImpl->Rewind();
2771e7416d9SIngo Weinhold }
2781e7416d9SIngo Weinhold 
2791e7416d9SIngo Weinhold 
2801e7416d9SIngo Weinhold status_t
GetNextEntry(struct dirent * entry,size_t size)2811e7416d9SIngo Weinhold Query::GetNextEntry(struct dirent* entry, size_t size)
2821e7416d9SIngo Weinhold {
2831e7416d9SIngo Weinhold 	return fImpl->GetNextEntry(entry, size);
2841e7416d9SIngo Weinhold }
2851e7416d9SIngo Weinhold 
2861e7416d9SIngo Weinhold 
2871e7416d9SIngo Weinhold void
LiveUpdate(Node * node,const char * attribute,int32 type,const void * oldKey,size_t oldLength,const void * newKey,size_t newLength)2881e7416d9SIngo Weinhold Query::LiveUpdate(Node* node, const char* attribute, int32 type,
2891e7416d9SIngo Weinhold 	const void* oldKey, size_t oldLength, const void* newKey, size_t newLength)
2901e7416d9SIngo Weinhold {
2911e7416d9SIngo Weinhold 	fImpl->LiveUpdate(node, node, attribute, type, (const uint8*)oldKey,
2921e7416d9SIngo Weinhold 		oldLength, (const uint8*)newKey, newLength);
2931e7416d9SIngo Weinhold }
2941e7416d9SIngo Weinhold 
2951e7416d9SIngo Weinhold 
2961e7416d9SIngo Weinhold status_t
_Init(const char * queryString,uint32 flags,port_id port,uint32 token)2971e7416d9SIngo Weinhold Query::_Init(const char* queryString, uint32 flags, port_id port, uint32 token)
2981e7416d9SIngo Weinhold {
2991e7416d9SIngo Weinhold 	status_t error = QueryImpl::Create(this, queryString, flags, port, token,
3001e7416d9SIngo Weinhold 		fImpl);
3011e7416d9SIngo Weinhold 	if (error != B_OK)
3021e7416d9SIngo Weinhold 		return error;
3031e7416d9SIngo Weinhold 
3041e7416d9SIngo Weinhold 	if ((fImpl->Flags() & B_LIVE_QUERY) != 0)
3051e7416d9SIngo Weinhold 		fVolume->AddQuery(this);
3061e7416d9SIngo Weinhold 
3071e7416d9SIngo Weinhold 	return B_OK;
3081e7416d9SIngo Weinhold }
309