ramfs: Rewrite Query system to use the common Query parser-evaluator.
The common version was also derived from BFS' original implementation, but was genericized during packagefs development, and has more recent fixes and additions. Only lightly tested, but arbitrary-attribute-indexed queries seem to be working just fine.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel file_systems ramfs ;
|
||||
|
||||
UsePrivateKernelHeaders ;
|
||||
UsePrivateHeaders file_systems ;
|
||||
UsePrivateHeaders file_systems storage ;
|
||||
|
||||
DEFINES += DEBUG_APP="\\\"ramfs\\\"" ;
|
||||
|
||||
@@ -13,7 +13,6 @@ KernelAddon ramfs
|
||||
AttributeIndexImpl.cpp
|
||||
AttributeIterator.cpp
|
||||
DataContainer.cpp
|
||||
DebugSupport.cpp
|
||||
Directory.cpp
|
||||
Entry.cpp
|
||||
EntryIterator.cpp
|
||||
@@ -31,7 +30,10 @@ KernelAddon ramfs
|
||||
SizeIndex.cpp
|
||||
SymLink.cpp
|
||||
Volume.cpp
|
||||
|
||||
DebugSupport.cpp
|
||||
QueryParserUtils.cpp
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles DebugSupport.cpp ]
|
||||
SEARCH on [ FGristFiles DebugSupport.cpp QueryParserUtils.cpp ]
|
||||
+= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,115 +15,51 @@
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "Index.h"
|
||||
#include "Stack.h"
|
||||
#include "ramfs.h"
|
||||
|
||||
class Entry;
|
||||
class Equation;
|
||||
class IndexIterator;
|
||||
|
||||
namespace QueryParser {
|
||||
template<typename QueryPolicy> class Query;
|
||||
};
|
||||
|
||||
class Node;
|
||||
class Query;
|
||||
class Term;
|
||||
class Volume;
|
||||
|
||||
|
||||
#define B_QUERY_NON_INDEXED 0x00000002
|
||||
|
||||
|
||||
// Wraps the RAM FS Index to provide the interface required by the Query
|
||||
// implementation. At least most of it.
|
||||
//
|
||||
// IndexWrapper
|
||||
class IndexWrapper {
|
||||
public:
|
||||
IndexWrapper(Volume *volume);
|
||||
|
||||
status_t SetTo(const char *name);
|
||||
void Unset();
|
||||
|
||||
uint32 Type() const;
|
||||
off_t GetSize() const;
|
||||
int32 KeySize() const;
|
||||
|
||||
private:
|
||||
friend class IndexIterator;
|
||||
|
||||
Volume *fVolume;
|
||||
Index *fIndex;
|
||||
};
|
||||
|
||||
// IndexIterator
|
||||
class IndexIterator {
|
||||
public:
|
||||
IndexIterator(IndexWrapper *indexWrapper);
|
||||
|
||||
status_t Find(const uint8 *const key, size_t keyLength);
|
||||
status_t Rewind();
|
||||
status_t GetNextEntry(uint8 *buffer, uint16 *keyLength, size_t bufferSize,
|
||||
Entry **entry);
|
||||
|
||||
private:
|
||||
IndexWrapper *fIndexWrapper;
|
||||
IndexEntryIterator fIterator;
|
||||
bool fInitialized;
|
||||
};
|
||||
|
||||
|
||||
class Expression {
|
||||
public:
|
||||
Expression(char *expr);
|
||||
~Expression();
|
||||
|
||||
status_t InitCheck();
|
||||
const char *Position() const { return fPosition; }
|
||||
Term *Root() const { return fTerm; }
|
||||
|
||||
protected:
|
||||
Term *ParseOr(char **expr);
|
||||
Term *ParseAnd(char **expr);
|
||||
Term *ParseEquation(char **expr);
|
||||
|
||||
bool IsOperator(char **expr,char op);
|
||||
|
||||
private:
|
||||
Expression(const Expression &);
|
||||
Expression &operator=(const Expression &);
|
||||
// no implementation
|
||||
|
||||
char *fPosition;
|
||||
Term *fTerm;
|
||||
};
|
||||
|
||||
class Query : public DoublyLinkedListLinkImpl<Query> {
|
||||
public:
|
||||
Query(Volume *volume, Expression *expression, uint32 flags);
|
||||
~Query();
|
||||
public:
|
||||
~Query();
|
||||
|
||||
status_t Rewind();
|
||||
status_t GetNextEntry(struct dirent *, size_t size);
|
||||
static status_t Create(Volume* volume, const char* queryString,
|
||||
uint32 flags, port_id port, uint32 token,
|
||||
Query*& _query);
|
||||
|
||||
void SetLiveMode(port_id port, int32 token);
|
||||
void LiveUpdate(Entry *entry, Node* node, const char *attribute,
|
||||
int32 type, const uint8 *oldKey, size_t oldLength,
|
||||
const uint8 *newKey, size_t newLength);
|
||||
status_t Rewind();
|
||||
status_t GetNextEntry(struct dirent* entry, size_t size);
|
||||
|
||||
Expression *GetExpression() const { return fExpression; }
|
||||
void LiveUpdate(Entry* entry, Node* node,
|
||||
const char* attribute, int32 type,
|
||||
const void* oldKey, size_t oldLength,
|
||||
const void* newKey, size_t newLength);
|
||||
|
||||
private:
|
||||
// void SendNotification(Entry* entry)
|
||||
private:
|
||||
struct QueryPolicy;
|
||||
friend struct QueryPolicy;
|
||||
typedef QueryParser::Query<QueryPolicy> QueryImpl;
|
||||
|
||||
private:
|
||||
Volume *fVolume;
|
||||
Expression *fExpression;
|
||||
Equation *fCurrent;
|
||||
IndexIterator *fIterator;
|
||||
IndexWrapper fIndex;
|
||||
Stack<Equation *> fStack;
|
||||
private:
|
||||
Query(Volume* volume);
|
||||
|
||||
uint32 fFlags;
|
||||
port_id fPort;
|
||||
int32 fToken;
|
||||
bool fNeedsEntry;
|
||||
status_t _Init(const char* queryString, uint32 flags,
|
||||
port_id port, uint32 token);
|
||||
|
||||
private:
|
||||
Volume* fVolume;
|
||||
QueryImpl* fImpl;
|
||||
};
|
||||
|
||||
|
||||
#endif /* QUERY_H */
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/* Stack - a template stack class (plus some handy methods)
|
||||
*
|
||||
* Copyright 2001-2005, Axel Dörfler, [email protected].
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef KERNEL_UTIL_STACK_H
|
||||
#define KERNEL_UTIL_STACK_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
template<class T> class Stack {
|
||||
public:
|
||||
Stack()
|
||||
:
|
||||
fArray(NULL),
|
||||
fUsed(0),
|
||||
fMax(0)
|
||||
{
|
||||
}
|
||||
|
||||
~Stack()
|
||||
{
|
||||
free(fArray);
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return fUsed == 0;
|
||||
}
|
||||
|
||||
void MakeEmpty()
|
||||
{
|
||||
// could also free the memory
|
||||
fUsed = 0;
|
||||
}
|
||||
|
||||
status_t Push(T value)
|
||||
{
|
||||
if (fUsed >= fMax) {
|
||||
fMax += 16;
|
||||
T *newArray = (T *)realloc(fArray, fMax * sizeof(T));
|
||||
if (newArray == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fArray = newArray;
|
||||
}
|
||||
fArray[fUsed++] = value;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
bool Pop(T *value)
|
||||
{
|
||||
if (fUsed == 0)
|
||||
return false;
|
||||
|
||||
*value = fArray[--fUsed];
|
||||
return true;
|
||||
}
|
||||
|
||||
T *Array()
|
||||
{
|
||||
return fArray;
|
||||
}
|
||||
|
||||
int32 CountItems() const
|
||||
{
|
||||
return fUsed;
|
||||
}
|
||||
|
||||
private:
|
||||
T *fArray;
|
||||
int32 fUsed;
|
||||
int32 fMax;
|
||||
};
|
||||
|
||||
#endif /* KERNEL_UTIL_STACK_H */
|
||||
@@ -2039,33 +2039,17 @@ ramfs_open_query(fs_volume* _volume, const char *queryString, uint32 flags,
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
|
||||
// lock the volume
|
||||
VolumeReadLocker locker(volume);
|
||||
VolumeWriteLocker locker(volume);
|
||||
if (!locker.IsLocked())
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
// parse the query expression
|
||||
Expression *expression = new Expression((char *)queryString);
|
||||
if (expression == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
ObjectDeleter<Expression> expressionDeleter(expression);
|
||||
|
||||
if (expression->InitCheck() < B_OK) {
|
||||
WARN("Could not parse query, stopped at: \"%s\"\n",
|
||||
expression->Position());
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
}
|
||||
|
||||
// create the query
|
||||
Query *query = new Query(volume, expression, flags);
|
||||
if (query == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
expressionDeleter.Detach();
|
||||
Query* query;
|
||||
status_t error = Query::Create(volume, queryString, flags, port, token, query);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// TODO: The Query references an Index, but nothing prevents the Index
|
||||
// from being deleted, while the Query is in existence.
|
||||
|
||||
if (flags & B_LIVE_QUERY)
|
||||
query->SetLiveMode(port, token);
|
||||
|
||||
*_cookie = (void *)query;
|
||||
|
||||
return B_OK;
|
||||
@@ -2090,14 +2074,12 @@ ramfs_free_query_cookie(fs_volume* _volume, void* _cookie)
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
|
||||
// lock the volume
|
||||
VolumeReadLocker locker(volume);
|
||||
VolumeWriteLocker locker(volume);
|
||||
if (!locker.IsLocked())
|
||||
RETURN_ERROR(B_ERROR);
|
||||
|
||||
Query *query = (Query *)_cookie;
|
||||
Expression *expression = query->GetExpression();
|
||||
delete query;
|
||||
delete expression;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user