From c1e7c02d9e73fe446a403133a5a4868fa6a0f5e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 19 Oct 2008 13:13:51 +0000 Subject: [PATCH] * If only files are watched, PathHandler::_AddFile() will now notify the target when it was called from a notification function. * This means you'll no longer have to watch (and scan) directories when you're interested in new files alone. Maybe this functionality could be used for other cases as well, or be activated only via an additional flag. Opinions? Stippi? :-) * TRACE() no goes to /dev/dprintf by default, added a bit more trace output. * Automatic whitespace cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28237 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/storage/PathMonitor.cpp | 73 +++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/src/kits/storage/PathMonitor.cpp b/src/kits/storage/PathMonitor.cpp index 36d1815095..7be0f2e575 100644 --- a/src/kits/storage/PathMonitor.cpp +++ b/src/kits/storage/PathMonitor.cpp @@ -28,7 +28,7 @@ #undef TRACE //#define TRACE_PATH_MONITOR #ifdef TRACE_PATH_MONITOR -# define TRACE(x...) printf(x) +# define TRACE(x...) debug_printf(x) #else # define TRACE(x...) ; #endif @@ -51,7 +51,7 @@ struct FileEntry { #if __GNUC__ > 3 bool operator<(const FileEntry& a, const FileEntry& b); - class FileEntryLess : public binary_function + class FileEntryLess : public binary_function { public: bool operator() (const FileEntry& a, const FileEntry& b) const @@ -115,13 +115,13 @@ class PathHandler : public BHandler { void _NotifyTarget(BMessage* message) const; void _NotifyTarget(BMessage* message, const node_ref& nodeRef) const; - status_t _AddDirectory(BEntry& entry); - status_t _AddDirectory(node_ref& nodeRef); + status_t _AddDirectory(BEntry& entry, bool notify = false); + status_t _AddDirectory(node_ref& nodeRef, bool notify = false); status_t _RemoveDirectory(const node_ref& nodeRef, ino_t directoryNode); status_t _RemoveDirectory(BEntry& entry, ino_t directoryNode); bool _HasFile(const node_ref& nodeRef) const; - status_t _AddFile(BEntry& entry); + status_t _AddFile(BEntry& entry, bool notify = false); status_t _RemoveFile(const node_ref& nodeRef); status_t _RemoveFile(BEntry& entry); @@ -206,6 +206,8 @@ PathHandler::PathHandler(const char* path, uint32 flags, BMessenger target, if (fStatus < B_OK) return; + TRACE("PathHandler: %s\n", path); + looper->Lock(); looper->AddHandler(this); looper->Unlock(); @@ -248,18 +250,18 @@ PathHandler::Quit() void PathHandler::Dump() { - printf("WATCHING DIRECTORIES:\n"); + TRACE("WATCHING DIRECTORIES:\n"); DirectorySet::iterator i = fDirectories.begin(); for (; i != fDirectories.end(); i++) { - printf(" %ld:%Ld (%s)\n", i->node.device, i->node.node, i->contained + TRACE(" %ld:%Ld (%s)\n", i->node.device, i->node.node, i->contained ? "contained" : "-"); } - printf("WATCHING FILES:\n"); + TRACE("WATCHING FILES:\n"); FileSet::iterator j = fFiles.begin(); for (; j != fFiles.end(); j++) { - printf(" %ld:%Ld\n", j->ref.device, j->node); + TRACE(" %ld:%Ld\n", j->ref.device, j->node); } } #endif @@ -359,7 +361,7 @@ PathHandler::_EntryCreated(BMessage* message) // a new directory to watch for us if (!entryContained && !_CloserToPath(entry) || parentContained && !_WatchRecursively() - || _AddDirectory(entry) != B_OK + || _AddDirectory(entry, true) != B_OK || _WatchFilesOnly()) notify = parentContained; // NOTE: entry is now toast after _AddDirectory() was called! @@ -445,13 +447,13 @@ PathHandler::_EntryMoved(BMessage* message) // there is a new directory to watch for us if (entryContained || parentContained && !_WatchRecursively()) { - _AddDirectory(entry); + _AddDirectory(entry, true); // NOTE: entry is toast now! } else if (_GetClosest(fPath.Path(), false, nodeRef) == B_OK) { // the new directory might put us even // closer to the path we are after - _AddDirectory(nodeRef); + _AddDirectory(nodeRef, true); } wasAdded = true; @@ -619,6 +621,8 @@ PathHandler::_NotifyTarget(BMessage* message, const node_ref& nodeRef) const BMessage update(*message); update.what = B_PATH_MONITOR; + TRACE("_NotifyTarget(): node ref %ld.%Ld\n", nodeRef.device, nodeRef.node); + WatchedDirectory directory; directory.node = nodeRef; @@ -659,7 +663,7 @@ PathHandler::_NotifyTarget(BMessage* message, const node_ref& nodeRef) const status_t -PathHandler::_AddDirectory(BEntry& entry) +PathHandler::_AddDirectory(BEntry& entry, bool notify) { WatchedDirectory directory; status_t status = entry.GetNodeRef(&directory.node); @@ -669,7 +673,7 @@ PathHandler::_AddDirectory(BEntry& entry) #ifdef TRACE_PATH_MONITOR { BPath path(&entry); - printf(" ADD DIRECTORY %s, %ld:%Ld\n", + TRACE(" ADD DIRECTORY %s, %ld:%Ld\n", path.Path(), directory.node.device, directory.node.node); } #endif @@ -703,10 +707,10 @@ PathHandler::_AddDirectory(BEntry& entry) while (dir.GetNextEntry(&entry) == B_OK) { if (entry.IsDirectory()) { // and here is the recursion: - if (_AddDirectory(entry) != B_OK) + if (_AddDirectory(entry, notify) != B_OK) break; } else if (!_WatchFoldersOnly()) { - if (_AddFile(entry) != B_OK) + if (_AddFile(entry, notify) != B_OK) break; } } @@ -724,7 +728,7 @@ PathHandler::_AddDirectory(BEntry& entry) status_t -PathHandler::_AddDirectory(node_ref& nodeRef) +PathHandler::_AddDirectory(node_ref& nodeRef, bool notify) { BDirectory directory(&nodeRef); status_t status = directory.InitCheck(); @@ -732,7 +736,7 @@ PathHandler::_AddDirectory(node_ref& nodeRef) BEntry entry; status = directory.GetEntry(&entry); if (status == B_OK) - status = _AddDirectory(entry); + status = _AddDirectory(entry, notify); } return status; @@ -799,7 +803,7 @@ PathHandler::_HasFile(const node_ref& nodeRef) const status_t -PathHandler::_AddFile(BEntry& entry) +PathHandler::_AddFile(BEntry& entry, bool notify) { if ((fFlags & (WATCH_NODE_FLAG_MASK & ~B_WATCH_DIRECTORY)) == 0) return B_OK; @@ -807,7 +811,7 @@ PathHandler::_AddFile(BEntry& entry) #ifdef TRACE_PATH_MONITOR { BPath path(&entry); - printf(" ADD FILE %s\n", path.Path()); + TRACE(" ADD FILE %s\n", path.Path()); } #endif @@ -816,9 +820,9 @@ PathHandler::_AddFile(BEntry& entry) if (status != B_OK) return status; - // check if we are already know this file + // check if we already know this file - // TODO: It should be possible to ommit this check if we know it + // TODO: It should be possible to omit this check if we know it // can't be the case (for example when adding subfolders recursively, // although in that case, the API user may still have added this file // independently, so for now, it should be the safest to perform this @@ -835,6 +839,21 @@ PathHandler::_AddFile(BEntry& entry) setEntry.node = nodeRef.node; fFiles.insert(setEntry); + + if (notify && _WatchFilesOnly()) { + // We also notify our target about new files if it's only interested + // in files; it won't be notified about new directories, so it cannot + // know when to search for them. + BMessage update; + update.AddInt32("opcode", B_ENTRY_CREATED); + update.AddInt32("device", nodeRef.device); + update.AddInt64("directory", setEntry.ref.directory); + update.AddString("name", setEntry.ref.name); + update.AddBool("added", true); + + _NotifyTarget(&update, nodeRef); + } + return B_OK; } @@ -887,13 +906,14 @@ BPathMonitor::~BPathMonitor() BPathMonitor::_InitLockerIfNeeded() { static vint32 lock = 0; - + if (sLocker != NULL) return B_OK; while (sLocker == NULL) { if (atomic_add(&lock, 1) == 0) { sLocker = new (nothrow) BLocker("path monitor"); + TRACE("Create PathMonitor locker\n"); if (sLocker == NULL) return B_NO_MEMORY; } @@ -908,7 +928,7 @@ BPathMonitor::_InitLockerIfNeeded() BPathMonitor::_InitLooperIfNeeded() { static vint32 lock = 0; - + if (sLooper != NULL) return B_OK; @@ -916,6 +936,7 @@ BPathMonitor::_InitLooperIfNeeded() if (atomic_add(&lock, 1) == 0) { // first thread initializes the global looper sLooper = new (nothrow) BLooper("PathMonitor looper"); + TRACE("Start PathMonitor looper\n"); if (sLooper == NULL) return B_NO_MEMORY; thread_id thread = sLooper->Run(); @@ -932,6 +953,8 @@ BPathMonitor::_InitLooperIfNeeded() /*static*/ status_t BPathMonitor::StartWatching(const char* path, uint32 flags, BMessenger target) { + TRACE("StartWatching(%s)\n", path); + status_t status = _InitLockerIfNeeded(); if (status != B_OK) return status; @@ -974,6 +997,8 @@ BPathMonitor::StopWatching(const char* path, BMessenger target) if (sLocker == NULL) return B_NO_INIT; + TRACE("StopWatching(%s)\n", path); + BAutolock _(sLocker); WatcherMap::iterator iterator = sWatchers.find(target);