* Implemented a class that can handle Tracker's query files. Only read support

for now.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38767 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-09-21 20:42:13 +00:00
parent 14bf35a2ef
commit 24b218c5a7
3 changed files with 425 additions and 0 deletions

View File

@ -0,0 +1,66 @@
/*
* Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#ifndef _QUERY_FILE_H
#define _QUERY_FILE_H
#include <EntryList.h>
#include <Query.h>
#include <List.h>
#include <String.h>
class BQueryFile : public BEntryList {
public:
BQueryFile(const entry_ref& ref);
BQueryFile(const BEntry& entry);
BQueryFile(const char* path);
BQueryFile(BQuery& query);
virtual ~BQueryFile();
status_t InitCheck() const;
status_t SetTo(const entry_ref& ref);
status_t SetTo(const BEntry& entry);
status_t SetTo(const char* path);
status_t SetTo(BQuery& query);
void Unset();
status_t SetPredicate(const char* predicate);
status_t AddVolume(const BVolume& volume);
status_t AddVolume(dev_t device);
const char* Predicate() const;
int32 CountVolumes() const;
dev_t VolumeAt(int32 index) const;
status_t WriteTo(const entry_ref& ref);
status_t WriteTo(const char* path);
// BEntryList implementation
virtual status_t GetNextEntry(BEntry* entry,
bool traverse = false);
virtual status_t GetNextRef(entry_ref* ref);
virtual int32 GetNextDirents(struct dirent* buffer,
size_t length, int32 count = INT_MAX);
virtual status_t Rewind();
virtual int32 CountEntries();
static const char* MimeType();
private:
status_t _SetQuery(int32 index);
private:
status_t fStatus;
BString fPredicate;
BQuery fQuery;
BList fVolumes;
int32 fCurrentVolumeIndex;
};
#endif // _QUERY_FILE_H

View File

@ -6,6 +6,7 @@ AddSubDirSupportedPlatforms libbe_test ;
UseLibraryHeaders agg ;
UsePrivateHeaders shared libbe ;
UseHeaders [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) servers input ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src kits ] ;
# for RWLockManager only
UsePrivateSystemHeaders ;
@ -19,6 +20,7 @@ StaticLibrary libshared.a :
DragTrackingFilter.cpp
HashString.cpp
Keymap.cpp
QueryFile.cpp
RWLockManager.cpp
SHA256.cpp
ShakeTrackingFilter.cpp

View File

@ -0,0 +1,357 @@
/*
* Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#include <QueryFile.h>
#include <fs_attr.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include "tracker/MimeTypes.h"
#include "tracker/Utilities.h"
// TODO: add write support
// TODO: let Tracker use it?
// TODO: live query support?
const char* kAttrQueryString = "_trk/qrystr";
const char* kAttrQueryVolume = "_trk/qryvol1";
BQueryFile::BQueryFile(const entry_ref& ref)
{
SetTo(ref);
}
BQueryFile::BQueryFile(const BEntry& entry)
{
SetTo(entry);
}
BQueryFile::BQueryFile(const char* path)
{
SetTo(path);
}
BQueryFile::BQueryFile(BQuery& query)
{
SetTo(query);
}
BQueryFile::~BQueryFile()
{
}
status_t
BQueryFile::InitCheck() const
{
return fStatus;
}
status_t
BQueryFile::SetTo(const entry_ref& ref)
{
Unset();
BNode node(&ref);
fStatus = node.InitCheck();
if (fStatus != B_OK)
return fStatus;
ssize_t bytesRead = node.ReadAttrString(kAttrQueryString, &fPredicate);
if (bytesRead < 0)
return fStatus = bytesRead;
bool searchAllVolumes = true;
attr_info info;
if (node.GetAttrInfo(kAttrQueryVolume, &info) == B_OK) {
void* buffer = malloc(info.size);
if (buffer == NULL)
return fStatus = B_NO_MEMORY;
BMessage message;
fStatus = message.Unflatten((const char*)buffer);
if (fStatus == B_OK) {
for (int32 index = 0; index < 100; index++) {
BVolume volume;
status_t status = BPrivate::MatchArchivedVolume(&volume,
&message, index);
if (status == B_OK) {
fStatus = AddVolume(volume);
if (fStatus != B_OK)
break;
searchAllVolumes = false;
} else if (status != B_DEV_BAD_DRIVE_NUM) {
// Volume doesn't seem to be mounted
fStatus = status;
break;
}
}
}
free(buffer);
}
if (searchAllVolumes) {
// add all volumes to query
BVolumeRoster roster;
BVolume volume;
while (roster.GetNextVolume(&volume) == B_OK) {
if (volume.IsPersistent() && volume.KnowsQuery())
AddVolume(volume);
}
}
return fStatus;
}
status_t
BQueryFile::SetTo(const BEntry& entry)
{
entry_ref ref;
fStatus = entry.GetRef(&ref);
if (fStatus != B_OK)
return fStatus;
return SetTo(ref);
}
status_t
BQueryFile::SetTo(const char* path)
{
entry_ref ref;
fStatus = get_ref_for_path(path, &ref);
if (fStatus != B_OK)
return fStatus;
return SetTo(ref);
}
status_t
BQueryFile::SetTo(BQuery& query)
{
Unset();
BString predicate;
query.GetPredicate(&predicate);
fStatus = SetPredicate(predicate.String());
if (fStatus != B_OK)
return fStatus;
return fStatus = AddVolume(query.TargetDevice());
}
void
BQueryFile::Unset()
{
fStatus = B_NO_INIT;
fCurrentVolumeIndex = -1;
fVolumes.MakeEmpty();
fQuery.Clear();
fPredicate = "";
}
status_t
BQueryFile::SetPredicate(const char* predicate)
{
fPredicate = predicate;
return B_OK;
}
status_t
BQueryFile::AddVolume(const BVolume& volume)
{
return fVolumes.AddItem((void*)volume.Device()) ? B_OK : B_NO_MEMORY;
}
status_t
BQueryFile::AddVolume(dev_t device)
{
return fVolumes.AddItem((void*)device) ? B_OK : B_NO_MEMORY;
}
const char*
BQueryFile::Predicate() const
{
return fPredicate.String();
}
int32
BQueryFile::CountVolumes() const
{
return fVolumes.CountItems();
}
dev_t
BQueryFile::VolumeAt(int32 index) const
{
if (index < 0 || index >= fVolumes.CountItems())
return -1;
return (dev_t)fVolumes.ItemAt(index);
}
status_t
BQueryFile::WriteTo(const entry_ref& ref)
{
// TODO: implement
return B_NOT_SUPPORTED;
}
status_t
BQueryFile::WriteTo(const char* path)
{
entry_ref ref;
status_t status = get_ref_for_path(path, &ref);
if (status != B_OK)
return status;
return WriteTo(ref);
}
// #pragma mark - BEntryList implementation
status_t
BQueryFile::GetNextEntry(BEntry* entry, bool traverse)
{
if (fCurrentVolumeIndex == -1) {
// Start with first volume
fCurrentVolumeIndex = 0;
status_t status = _SetQuery(0);
if (status != B_OK)
return status;
}
status_t status = B_ENTRY_NOT_FOUND;
while (fCurrentVolumeIndex < CountVolumes()) {
status = fQuery.GetNextEntry(entry, traverse);
if (status != B_ENTRY_NOT_FOUND)
break;
// Continue with next volume, if any
status = _SetQuery(++fCurrentVolumeIndex);
}
return status;
}
status_t
BQueryFile::GetNextRef(entry_ref* ref)
{
if (fCurrentVolumeIndex == -1) {
// Start with first volume
fCurrentVolumeIndex = 0;
status_t status = _SetQuery(0);
if (status != B_OK)
return status;
}
status_t status = B_ENTRY_NOT_FOUND;
while (fCurrentVolumeIndex < CountVolumes()) {
status = fQuery.GetNextRef(ref);
if (status != B_ENTRY_NOT_FOUND)
break;
// Continue with next volume, if any
status = _SetQuery(++fCurrentVolumeIndex);
}
return status;
}
int32
BQueryFile::GetNextDirents(struct dirent* buffer, size_t length, int32 count)
{
if (fCurrentVolumeIndex == -1) {
// Start with first volume
fCurrentVolumeIndex = 0;
status_t status = _SetQuery(0);
if (status != B_OK)
return status;
}
status_t status = B_ENTRY_NOT_FOUND;
while (fCurrentVolumeIndex < CountVolumes()) {
status = fQuery.GetNextDirents(buffer, length, count);
if (status != B_ENTRY_NOT_FOUND)
break;
// Continue with next volume, if any
status = _SetQuery(++fCurrentVolumeIndex);
}
return status;
}
status_t
BQueryFile::Rewind()
{
fCurrentVolumeIndex = -1;
return B_OK;
}
int32
BQueryFile::CountEntries()
{
// not supported
return -1;
}
/*static*/ const char*
BQueryFile::MimeType()
{
return B_QUERY_MIMETYPE;
}
status_t
BQueryFile::_SetQuery(int32 index)
{
if (fCurrentVolumeIndex >= CountVolumes())
return B_ENTRY_NOT_FOUND;
BVolume volume(VolumeAt(fCurrentVolumeIndex));
fQuery.Clear();
fQuery.SetPredicate(fPredicate.String());
fQuery.SetVolume(&volume);
return fQuery.Fetch();
}