Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: FSDirectorySize code finished



On 31/10/2005 01:35 Am, Laurence Harris wrote:

> On 10/31/05 4:13 PM, Mike Kluev didst favor us with:
> 
>> On Mon, 31 Oct 2005 13:54:57, Laurence Harris <email@hidden> wrote:
>> 
>>> On 10/31/05 12:08 PM, Mike Kluev didst favor us with:
>>> 
>>>> on Sun, 30 Oct 2005 22:09:00, Steve Baxter <email@hidden> wrote:
>>>> 
>>>>> On 30 Oct 2005, at 21:31, Laurence Harris wrote:
>>>>> 
>>>>>> On 10/30/05 4:03 PM, Steve Baxter didst favor us with:
>>>>>> 
>>>>>>> I would use FSRefs by value here rather than storing pointers, i.e.
>>>>>>> store the actual FSRefs in the vector rather than a pointer to a
>>>>>>> FSRef.  The overhead of copying 80 bytes will be so small as to be
>>>>>>> unmeasureable.  You may actually find that the copy overhead is less
>>>>>>> than the malloc() overhead of allocating 80 bytes (but only Shark
>>>>>>> will tell you).
>>>>>>> 
>>>>>> 
>>>>>> Except it's not either/or. If you store pointers, such as is the case
>>>>>> with
>>>>>> a
>>>>>> CF widget or a vector of FSRef pointers, once you allocate the memory for
>>>>>> 80
>>>>>> bytes, you still have to copy the FSRef into the allocated memory.
>>>>> 
>>>>> True, true.
>>>> 
>>>> Or FSGetCatalogInfo[Bulk] could do this copy itself.
>>> 
>>> Not in this context. The FSRefs discussed are the directories returned by
>>> FSGetCatalogInfoBulk which are being stored for retrieval later.
>> 
>> Hmm...
>> 
>> for (count = 0;;) {
>> err = FSGetCatalogInfoBulk(iterator, 1, &actCount, NULL,
>> kFSCatInfoNodeFlags, &info, &fsRefVector[count], NULL, NULL);
>> if (err) break;
>> if (info.nodeFlags & kFSNodeIsDirectoryMask) count++;
>> }
>> Here fsRefVector contains "count" subdirectory FSRefs stored or
>> retrieval later.
> 
> No, it doesn't. It contains "count" subdirectory FSRefs at that point in
> time. The code in question uses FSGetCatalogInfoBulk to iterate over a
> directory adding up file sizes. Directories are pushed onto a stack and
> popped off later after the current folder has been iterated completely
> (which means the contents of the fsRefVector may have changed multiple
> times).
> 
> "Later" in this context means after FSGetCatalogInfoBulk has been called
> repeatedly until it returns errFSNoMoreItems. The FSRef buffer passed to
> FSGetCatalogInfoBulk can't be used to store all the folders found in the
> current directory. Really.

Really? I admit I haven't seen the code in question (becase
attachements do not reach list digests/archives - the good reason
to *not* post attachments here, rather post a little snippet directly
in the message), but from this discussion the below fragment does a
similar thing. It calculates folder size, does it exactly like you
said - directories are pushed onto a stack and popped off later after
the current folder has been iterated completely (though this
particular traversal path is by no means the only possible path for
this task). It uses global stack of fsrefs, reallocates it
infrequently (add some slop factor in EnsureFolderStackSize to make
those reallocations even more rare), doesn't use much memory per item
or per level (doesn't use recursion at all), uses a single catalogInfo
record and a single iteratorRef, etc. And it *doesn't* copy 80 bytes
of fsref from one place to another in the main routine, because
getcatinfobulk in this case stores fsref directly in the right place,
so I don't see why you say it can't be done in this context. Oh, and
yes, feel free changing the routine to calculate both physical and
resource sizes, file counts and whatnot: I didn't show it here to make
the sample shorter. Ditto error checking, add appropriate one of your
choice.

Mike


static FSRef *_stack = NULL;
static long _stackMaxSize = 0;

OSStatus EnsureFolderStackSize(long stackSize)
{
    if (_stackMaxSize < stackSize) {
        _stackMaxSize = stackSize; // + extra, or *2, or etc.
        _stack = (FSRef *)realloc(_stack, _stackMaxSize*sizeof(*_stack));
        // check for NULL;
    }
    return noErr;
}

UInt64 GetFolderStackSize(long top)
{
    UInt64 size = 0;
    UInt32 actCount;
    OSStatus err;
    FSIterator iterator;
    FSCatalogInfo info;
        
    while (top > 0) {
        err = FSOpenIterator(&_stack[--top], kFSIterateFlat, &iterator);
        if (!err) {
            for (;;) {
                err = FSGetCatalogInfoBulk(iterator, 1, &actCount, NULL,
                    kFSCatInfoNodeFlags | kFSCatInfoDataSizes, &info,
                    &_stack[top], NULL, NULL);
                if (err) break;
                
                if (info.nodeFlags & kFSNodeIsDirectoryMask) {
                    EnsureFolderStackSize(++top + 1);
                }
                else size += info.dataLogicalSize;
            }
            FSCloseIterator(iterator);
        }
    }
    
    return size;
}

UInt64 GetFolderSize(const FSRef *fsRef)
{
    OSStatus err;
    
    err = EnsureFolderStackSize(1);
    _stack[0] = *fsRef;
    return GetFolderStackSize(1);
}

Usage: size = GetFolderSize(&fsRef);

Mike

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Carbon-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/carbon-dev/email@hidden

This email sent to email@hidden

References: 
 >Re: FSDirectorySize code finished (From: Laurence Harris <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.