Author: axeld Date: 2009-10-20 11:59:09 +0200 (Tue, 20 Oct 2009) New Revision: 33677 Changeset: http://dev.haiku-os.org/changeset/33677/haiku Added: haiku/trunk/src/tests/system/kernel/live_query.cpp Modified: haiku/trunk/src/tests/system/kernel/Jamfile Log: * Added command line application to use live queries. Useful for testing why the new mail count is off that much on mail removal. Modified: haiku/trunk/src/tests/system/kernel/Jamfile =================================================================== --- haiku/trunk/src/tests/system/kernel/Jamfile 2009-10-20 01:45:04 UTC (rev 33676) +++ haiku/trunk/src/tests/system/kernel/Jamfile 2009-10-20 09:59:09 UTC (rev 33677) @@ -11,6 +11,11 @@ SimpleTest fibo_fork : fibo_fork.cpp ; SimpleTest fibo_exec : fibo_exec.cpp ; +SimpleTest live_query : + live_query.cpp + : be +; + SimpleTest lock_node_test : lock_node_test.cpp : be Copied: haiku/trunk/src/tests/system/kernel/live_query.cpp (from rev 33650, haiku/trunk/src/bin/query.cpp) =================================================================== --- haiku/trunk/src/tests/system/kernel/live_query.cpp (rev 0) +++ haiku/trunk/src/tests/system/kernel/live_query.cpp 2009-10-20 09:59:09 UTC (rev 33677) @@ -0,0 +1,283 @@ +/* + * Copyright 2005-2009, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * Ficus Kirkpatrick (ficus@xxxxxxx) + * Jérôme Duval + * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + */ + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include <Application.h> +#include <Entry.h> +#include <NodeMonitor.h> +#include <Path.h> +#include <Query.h> +#include <Volume.h> +#include <VolumeRoster.h> +#include <String.h> + +#include <ObjectList.h> + + +static const uint32 kMsgAddQuery = 'adqu'; + +extern const char *__progname; +static const char *kProgramName = __progname; + +// Option variables. +static bool sAllVolumes = false; // Query all volumes? +static bool sEscapeMetaChars = true; // Escape metacharacters? +static bool sFilesOnly = false; // Show only files? + + +class LiveQuery : public BApplication { +public: + LiveQuery(); + virtual ~LiveQuery(); + + virtual void ArgvReceived(int32 argc, char** argv); + virtual void ReadyToRun(); + + virtual void MessageReceived(BMessage* message); + +private: + void _PrintUsage(); + void _AddQuery(BVolume& volume, + const char* predicate); + void _PerformQuery(BQuery& query); + + BObjectList<BQuery> fQueries; + bool fArgsReceived; +}; + + +LiveQuery::LiveQuery() + : + BApplication("application/x-vnd.test-live-query"), + fQueries(10, true), + fArgsReceived(false) +{ +} + + +LiveQuery::~LiveQuery() +{ +} + + +void +LiveQuery::ArgvReceived(int32 argc, char** argv) +{ + fArgsReceived = true; + + // Which volume do we make the query on? + // Default to the current volume. + char volumePath[B_FILE_NAME_LENGTH]; + strcpy(volumePath, "."); + + // Parse command-line arguments. + int opt; + while ((opt = getopt(argc, argv, "efav:")) != -1) { + switch (opt) { + case 'e': + sEscapeMetaChars = false; + break; + case 'f': + sFilesOnly = true; + break; + case 'a': + sAllVolumes = true; + break; + case 'v': + strncpy(volumePath, optarg, B_FILE_NAME_LENGTH); + break; + + default: + _PrintUsage(); + break; + } + } + + BVolume volume; + + if (!sAllVolumes) { + // Find the volume that the query should be performed on, + // and set the query to it. + BEntry entry(volumePath); + if (entry.InitCheck() != B_OK) { + fprintf(stderr, "%s: \"%s\" is not a valid file\n", kProgramName, + volumePath); + exit(1); + } + + status_t status = entry.GetVolume(&volume); + if (status != B_OK) { + fprintf(stderr, "%s: could not get volume: %s\n", kProgramName, + strerror(status)); + exit(1); + } + + if (!volume.KnowsQuery()) { + fprintf(stderr, "%s: volume containing %s is not query-enabled\n", + kProgramName, volumePath); + } else + _AddQuery(volume, argv[optind]); + } else { + // Okay, we want to query all the disks -- so iterate over + // them, one by one, running the query. + BVolumeRoster volumeRoster; + while (volumeRoster.GetNextVolume(&volume) == B_OK) { + // We don't print errors here -- this will catch /pipe and + // other filesystems we don't care about. + if (volume.KnowsQuery()) + _AddQuery(volume, argv[optind]); + } + } +} + + +void +LiveQuery::ReadyToRun() +{ + if (!fArgsReceived) + _PrintUsage(); +} + + +void +LiveQuery::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgAddQuery: + { + int32 device; + const char* predicate; + if (message->FindInt32("volume", &device) != B_OK + || message->FindString("predicate", &predicate) != B_OK) + break; + + BVolume volume(device); + BQuery* query = new BQuery; + + // Set up the volume and predicate for the query. + query->SetVolume(&volume); + query->SetPredicate(predicate); + query->SetTarget(this); + + fQueries.AddItem(query); + _PerformQuery(*query); + break; + } + + case B_QUERY_UPDATE: + { + int32 what; + message->FindInt32("opcode", &what); + + int32 device; + int64 directory; + int64 node; + const char* name; + message->FindInt32("device", &device); + message->FindInt64("directory", &directory); + message->FindInt64("node", &node); + message->FindString("name", &name); + + switch (what) { + case B_ENTRY_CREATED: + { + printf("CREATED %s\n", name); + break; + } + case B_ENTRY_REMOVED: + printf("REMOVED %s\n", name); + break; + } + break; + } + + default: + BApplication::MessageReceived(message); + break; + } +} + + +void +LiveQuery::_PrintUsage() +{ + printf("usage: %s [ -ef ] [ -a || -v <path-to-volume> ] expression\n" + " -e\t\tdon't escape meta-characters\n" + " -f\t\tshow only files (ie. no directories or symbolic links)\n" + " -a\t\tperform the query on all volumes\n" + " -v <file>\tperform the query on just one volume; <file> can be any\n" + "\t\tfile on that volume. Defaults to the current volume.\n" + " Hint: '%s name=bar' will find files named \"bar\"\n", + kProgramName, kProgramName); + + Quit(); +} + + +void +LiveQuery::_AddQuery(BVolume& volume, const char* predicate) +{ + BMessage add(kMsgAddQuery); + add.AddInt32("volume", volume.Device()); + add.AddString("predicate", predicate); + + PostMessage(&add); +} + + +void +LiveQuery::_PerformQuery(BQuery& query) +{ + status_t status = query.Fetch(); + if (status != B_OK) { + fprintf(stderr, "%s: bad query expression\n", kProgramName); + return; + } + + int32 count = 0; + + BEntry entry; + BPath path; + while (query.GetNextEntry(&entry) == B_OK) { + if (sFilesOnly && !entry.IsFile()) + continue; + + if (entry.GetPath(&path) != B_OK) { + fprintf(stderr, "%s: could not get path for entry\n", kProgramName); + continue; + } + + printf("%s\n", sEscapeMetaChars ? BString().CharacterEscape( + path.Path(), " ()?*&\"'[]^\\~|;!<>*$\t", '\\').String() + : path.Path()); + + count++; + } + + printf("FOUND %ld entries\n", count); +} + + +// #pragma mark - + + +int +main(int argc, char** argv) +{ + LiveQuery query; + query.Run(); + + return 0; +}