/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Query.h"
#include <file_systems/QueryParser.h>
#include "AttributeCookie.h"
#include "Directory.h"
#include "Index.h"
#include "Node.h"
#include "Volume.h"
// #pragma mark - QueryPolicy
struct Query::QueryPolicy {
typedef Query Context;
typedef ::Node Entry;
typedef ::Node Node;
struct Index {
Query* query;
::Index* index;
Index(Context* context)
:
query(context)
{
}
};
struct IndexIterator : ::IndexIterator {
::Index* index;
IndexIterator(::Index* index)
:
index(index)
{
}
};
static const int32 kMaxFileNameLength = B_FILE_NAME_LENGTH;
// Entry interface
static ino_t EntryGetParentID(Entry* entry)
{
return entry->Parent()->ID();
}
static Node* EntryGetNode(Entry* entry)
{
return entry;
}
static ino_t EntryGetNodeID(Entry* entry)
{
return entry->ID();
}
static ssize_t EntryGetName(Entry* entry, void* buffer, size_t bufferSize)
{
const char* name = entry->Name();
size_t nameLength = strlen(name);
if (nameLength >= bufferSize)
return B_BUFFER_OVERFLOW;
memcpy(buffer, name, nameLength + 1);
return nameLength + 1;
}
static const char* EntryGetNameNoCopy(Entry* entry, void* buffer,
size_t bufferSize)
{
return entry->Name();
}
// Index interface
static status_t IndexSetTo(Index& index, const char* attribute)
{
index.index = index.query->fVolume->FindIndex(StringKey(attribute));
return index.index != NULL ? B_OK : B_ENTRY_NOT_FOUND;
}
static void IndexUnset(Index& index)
{
index.index = NULL;
}
static int32 IndexGetWeightedScore(Index& index, int32 score)
{
// should be inversely proportional to the index size; max input score
// is 2048
static const int32 maxFactor = 1024 * 1024;
return score * (maxFactor
/ std::min(maxFactor,
std::max((int32)1, index.index->CountEntries())));
}
static type_code IndexGetType(Index& index)
{
return index.index->Type();
}
static int32 IndexGetKeySize(Index& index)
{
return index.index->KeyLength();
}
static IndexIterator* IndexCreateIterator(Index& index)
{
IndexIterator* iterator = new(std::nothrow) IndexIterator(index.index);
if (iterator == NULL)
return NULL;
if (!index.index->GetIterator(*iterator)) {
delete iterator;
return NULL;
}
return iterator;
}
// IndexIterator interface
static void IndexIteratorDelete(IndexIterator* indexIterator)
{
delete indexIterator;
}
static status_t IndexIteratorFind(IndexIterator* indexIterator,
const void* value, size_t size)
{
if (!indexIterator->index->Find(value, size, *indexIterator))
return B_ENTRY_NOT_FOUND;
return B_OK;
}
static status_t IndexIteratorGetNextEntry(IndexIterator* indexIterator,
void* value, size_t* _valueLength, size_t bufferSize, Entry** _entry)
{
Node* node = indexIterator->Next(value, _valueLength);
if (node == NULL)
return B_ENTRY_NOT_FOUND;
*_entry = node;
return B_OK;
}
static void IndexIteratorSuspend(IndexIterator* indexIterator)
{
indexIterator->Suspend();
}
static void IndexIteratorResume(IndexIterator* indexIterator)
{
indexIterator->Resume();
}
// Node interface
static const off_t NodeGetSize(Node* node)
{
return node->FileSize();
}
static time_t NodeGetLastModifiedTime(Node* node)
{
return node->ModifiedTime().tv_sec;
}
static status_t NodeGetAttribute(Node* node, const char* attribute,
void* buffer, size_t* _size, int32* _type)
{
// TODO: Creating a cookie is quite a bit of overhead.
AttributeCookie* cookie;
status_t error = node->OpenAttribute(StringKey(attribute), O_RDONLY,
cookie);
if (error != B_OK)
return error;
error = cookie->ReadAttribute(0, buffer, _size);
// also get the attribute type
if (error == B_OK) {
struct stat st;
error = cookie->ReadAttributeStat(&st);
if (error == B_OK)
*_type = st.st_type;
}
cookie->Close();
delete cookie;
return error;
}
static Entry* NodeGetFirstReferrer(Node* node)
{
return node;
}
static Entry* NodeGetNextReferrer(Node* node, Entry* entry)
{
return NULL;
}
// Volume interface
static dev_t ContextGetVolumeID(Context* context)
{
return context->fVolume->ID();
}
};
// #pragma mark - Query
Query::Query(Volume* volume)
:
fVolume(volume),
fImpl(NULL)
{
}
Query::~Query()
{
if (fImpl != NULL) {
if ((fImpl->Flags() & B_LIVE_QUERY) != 0)
fVolume->RemoveQuery(this);
delete fImpl;
}
}
/*static*/ status_t
Query::Create(Volume* volume, const char* queryString, uint32 flags,
port_id port, uint32 token, Query*& _query)
{
Query* query = new(std::nothrow) Query(volume);
if (query == NULL)
return B_NO_MEMORY;
status_t error = query->_Init(queryString, flags, port, token);
if (error != B_OK) {
delete query;
return error;
}
_query = query;
return B_OK;
}
status_t
Query::Rewind()
{
return fImpl->Rewind();
}
status_t
Query::GetNextEntry(struct dirent* entry, size_t size)
{
return fImpl->GetNextEntry(entry, size);
}
void
Query::LiveUpdate(Node* node, const char* attribute, int32 type,
const void* oldKey, size_t oldLength, const void* newKey, size_t newLength)
{
fImpl->LiveUpdate(node, node, attribute, type, (const uint8*)oldKey,
oldLength, (const uint8*)newKey, newLength);
}
status_t
Query::_Init(const char* queryString, uint32 flags, port_id port, uint32 token)
{
status_t error = QueryImpl::Create(this, queryString, flags, port, token,
fImpl);
if (error != B_OK)
return error;
if ((fImpl->Flags() & B_LIVE_QUERY) != 0)
fVolume->AddQuery(this);
return B_OK;
}
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: index.