From 09dad369d73a499a6cc27b38e1ebe7ccc9fe6d0f Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Tue, 1 Oct 2002 07:26:11 +0000 Subject: [PATCH] Updated filesystem traversal code to skip files/devices that don't support attributes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1325 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../private/storage/mime/MimeUpdateThread.h | 7 ++ src/kits/storage/mime/MimeUpdateThread.cpp | 116 +++++++++++++----- 2 files changed, 94 insertions(+), 29 deletions(-) diff --git a/headers/private/storage/mime/MimeUpdateThread.h b/headers/private/storage/mime/MimeUpdateThread.h index 86bc7289ce..551b3b3958 100644 --- a/headers/private/storage/mime/MimeUpdateThread.h +++ b/headers/private/storage/mime/MimeUpdateThread.h @@ -14,6 +14,9 @@ #include #include +#include +#include + struct entry_ref; class BMessage; @@ -37,8 +40,12 @@ protected: const bool fRecursive; const bool fForce; BMessage *fReplyee; + + bool DeviceSupportsAttributes(dev_t device); private: + std::list< std::pair > fAttributeSupportList; + status_t UpdateEntry(const entry_ref *ref); status_t fStatus; diff --git a/src/kits/storage/mime/MimeUpdateThread.cpp b/src/kits/storage/mime/MimeUpdateThread.cpp index 01ba9a8967..8502de06f2 100644 --- a/src/kits/storage/mime/MimeUpdateThread.cpp +++ b/src/kits/storage/mime/MimeUpdateThread.cpp @@ -10,9 +10,11 @@ #include "mime/MimeUpdateThread.h" #include +#include #include #include #include +#include #include @@ -60,6 +62,7 @@ MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, BMessenger */ MimeUpdateThread::~MimeUpdateThread() { + // delete our acquired BMessage if (InitCheck() == B_OK) delete fReplyee; } @@ -110,6 +113,53 @@ MimeUpdateThread::ThreadFunction() find_thread(NULL), err)); } +// DeviceSupportsAttributes +/*! \brief Returns true if the given device supports attributes, false + if not (or if an error occurs while determining). + + Device numbers and their corresponding support info are cached in + a std::list to save unnecessarily \c statvfs()ing devices that have + already been statvfs()ed (which might otherwise happen quite often + for a device that did in fact support attributes). + + \return + - \c true: The device supports attributes + - \c false: The device does not support attributes, or there was an + error while determining +*/ +bool +MimeUpdateThread::DeviceSupportsAttributes(dev_t device) +{ + // See if an entry for this device already exists + std::list< std::pair >::iterator i; + for (i = fAttributeSupportList.begin(); + i != fAttributeSupportList.end(); + i++) + { + if (i->first == device) + return i->second; + } + + bool result = false; + + // If we get here, no such device is yet in our list, + // so we attempt to remedy the situation + BVolume volume; + status_t err = volume.SetTo(device); + if (!err) { + result = volume.KnowsAttr(); + // devices supporting attributes are likely to be queried + // again, devices not supporting attributes are not + std::pair p(device, result); + if (result) + fAttributeSupportList.push_front(p); + else + fAttributeSupportList.push_back(p); + } + + return result; +} + // UpdateEntry /*! \brief Updates the given entry and then recursively updates all the entry's child entries if the entry is a directory and \c fRecursive is true. @@ -120,39 +170,47 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) status_t err = ref ? B_OK : B_BAD_VALUE; bool entryIsDir = false; - // Update this entry - if (!err) { - DoMimeUpdate(ref, &entryIsDir); -// err = DoMimeUpdate(ref, &entryIsDir); -/* BPath path(ref); - printf("Updating '%s'... ", path.Path()); - fflush(stdout); - printf("0x%lx\n", DoMimeUpdate(ref, &entryIsDir)); -*/ - } // Look to see if we're being terminated if (!err && fShouldExit) err = B_CANCELED; - // If we're recursing and this is a directory, update - // each of the directory's children as well - if (!err && fRecursive && entryIsDir) { - BDirectory dir; - err = dir.SetTo(ref); + + // Before we update, make sure this entry lives on a device that supports + // attributes. If not, we skip it and any of its children for + // updates (we don't signal an error, however). + +//BPath path(ref); +//printf("Updating '%s' (%s)... \n", path.Path(), +// (DeviceSupportsAttributes(ref->device) ? "yes" : "no")); + + if (!err + && (device_is_root_device(ref->device) + || DeviceSupportsAttributes(ref->device))) { + // Update this entry if (!err) { - entry_ref childRef; - while (!err) { - err = dir.GetNextRef(&childRef); - if (err) { - // If we've come to the end of the directory listing, - // it's not an error. - if (err == B_ENTRY_NOT_FOUND) - err = B_OK; - break; - } else { - err = UpdateEntry(&childRef); - } - } - } + // R5 appears to ignore whether or not the update succeeds. + DoMimeUpdate(ref, &entryIsDir); + } + // If we're recursing and this is a directory, update + // each of the directory's children as well + if (!err && fRecursive && entryIsDir) { + BDirectory dir; + err = dir.SetTo(ref); + if (!err) { + entry_ref childRef; + while (!err) { + err = dir.GetNextRef(&childRef); + if (err) { + // If we've come to the end of the directory listing, + // it's not an error. + if (err == B_ENTRY_NOT_FOUND) + err = B_OK; + break; + } else { + err = UpdateEntry(&childRef); + } + } + } + } } return err; }