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 09:41 Am, Mike Kluev wrote:

> 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.

Better one: (doesn't use globals - can be used concurently from
threads, uses *2 "slop" factor):

static FSRef *EnsureFolderStackSize(FSRef *stack, long *stackMaxSize,
    long stackSize)
{
    if (*stackMaxSize < stackSize) {
        *stackMaxSize = stackSize*2; // + extra, or *2, or etc.
        stack = (FSRef *)realloc(stack, (*stackMaxSize)*sizeof(*stack));
        // check for NULL;
    }
    return stack;
}

static UInt64 GetFolderSize(const FSRef *fsRef)
{
    UInt64 size = 0;
    UInt32 actCount;
    OSStatus err;
    FSIterator iterator;
    FSCatalogInfo info;
    FSRef *stack = NULL;
    long stackMaxSize = 0;
    long top = 1;
        
    stack = EnsureFolderStackSize(stack, &stackMaxSize, 1);
    // check for NULL
    stack[0] = *fsRef;
    
    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) {
                    stack = EnsureFolderStackSize(stack, &stackMaxSize,
                        ++top + 1); // check for NULL
                }
                else size += info.dataLogicalSize;
            }
            FSCloseIterator(iterator);
        }
    }
    free(stack);
    
    return size;
}

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: Mike Kluev <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.