I have this program that recurses through a directory structure building
Default.htm files.  The idea here was to quickly generate a bunch of these
things to replace the default index listing you normally see.  The part
that's giving me trouble is the navbar that should have a nested structure
like...

Food
   Fruit
     Apples
     Oranges
     Kiwi
   Vegetables
   Coffee
Critters
Cars
Rocks

So that if you are in /DocRoot/Food/Fruit you would see the above on the
left all properly linked yada yada.  The code I've pasted in does this just
fine (I've removed a bunch of stuff to focus on the real problem) but only
on small directory structures.  When I run it on something with 10 directory
levels, 3 or 4 subdirectories in each one, 20-30 files in each one, it zips
along for a few seconds then grinds to a halt, consumes all my physical
memory and begins swapping like mad.  

I changed things around to not use the joinLists() function and to have
buildIndices() call itself rather than have getLinks call it and it works
fine.  But I don't know why, hence the posting.  Anyone feel like tackling
this?

Thanks!

Peter C.

------------------------------------------
#! perl

use strict;
use warnings;
use File::Copy;
use vars ('$rootDir');

#===========================================================================
====
# Main
#===========================================================================
====
my $baseURL = "engweb";
$rootDir = "d:/inetpub/wwwroot/$baseURL";

buildIndices($rootDir, "/$baseURL") or
        die ("failed trying to build $rootDir\n");

exit 0;

#===========================================================================
====
# Functions
#===========================================================================
====

#---------------------------------------------------------------------------
----
# buildIndices($dir, $parentLinks)
#
# This function takes a document directory and builds the
# Default.htm file for it.
#
sub buildIndices {
        my ($dir, $url, $parentLinks) = @_; #$parentLinks is an array ref.
        my $cwd = (split /\\|\//, $dir)[-1];

        print "currently working on $dir\n";

        local $" = "\n";  #Set the list seperator to a new line.

        #All we want is 2 things, a directory and an html file.
        #Is that too much to ask for?
        copy ("$rootDir\\Default.htm", "$dir\\Default.htm")
                unless -T "$dir\\Default.htm";

        unless (-d $dir and -T "$dir\\Default.htm") {
                print "$dir is not a directory\n" unless -d $dir;
                print "We couldn't put the Default.htm file in $dir\n"
                        unless -T "$dir\\Default.htm";
                return 0;
        }

        my @curLinks = getLinks($dir, $url, $parentLinks);
        #links should have a bunch of '<a href...' strings

        #if we were given a parentLinks array splice these two together.
        # if there were no subdirectories or files splice in an anonymous
        # array that Just says "EMPTY"
        my @links = ($parentLinks and $cwd) ?
                joinLists (@curLinks ? \@curLinks :
                                        ["<DIV STYLE=\"margin:10\">",
"Empty", "</DIV>"],
                                        $parentLinks, $cwd) :
                @curLinks;

        #there's just an inplace edit here...
        #
        #...

        return 1; #one is good
}

#---------------------------------------------------------------------------
----
# getLinks($dir)
#
# loop through the directory entries and build a bunch of '<a href...'
# strings and stuff them in an array.  If the entry is a directory call
# buildIndices($ent) on it.
#
sub getLinks {
        my ($dir, $url, $parentLinks) = @_;
        my @subDirs;
        my @links = ();
        my $link;
        my $ent; #a thing for iterating over directory entries
        my $cwd = (split /\\|\//, $dir)[-1];

        opendir (DH, $dir) or
                logItAndDie("Can't open the directory $rootDir,
status=$!\n");


        while (defined ($ent = readdir(DH))) {
                next if $ent =~ /^\./;  #skip things with leading '.'

                if (-d "$dir/$ent") {
                        #Add some spaces.
                        push @links, "<a
href=\"$url/$ent/Default.htm\">$ent</a><br>";
                        push @subDirs, "$dir/$ent"; #to be used in calls to
buildIndices
                } elsif ($ent  =~ /\.(htm|html|jsp|doc)$/) {
                        if (!($ent =~ /Default/)) {             # Skip the
Default files
                                push @links, "<a
href=\"$url/$ent\">$ent</a><br>";
                        }
                }
        }
        closedir(DH);

        if (@links) {
                unshift @links, "<DIV STYLE=\"margin:10\">";
                push @links, "</DIV>";
        }

        my @completeLinks = ($cwd and $parentLinks) ?
                joinLists (\@links, $parentLinks, $cwd) :
                @links;

        for (@subDirs) {
                buildIndices($_, "$url/" . (split /\\|\//)[-1],
\@completeLinks) 
                        or die;
        }

        return @links;
}

#---------------------------------------------------------------------------
----
# joinLists($subListRef, $masterListRef, $key)
#
# Add a sub list to the right point in the larger master list...
#
sub joinLists {
        my ($subList, $masterList, $key) = @_;

        return map {
                        if (/\Q$key/i) {
                                my $newEnt = $_;        #don't want to taint
the masterlist
                                $newEnt =~ s/\Q$key\E(\/|\\)//i;
                                $newEnt, @$subList;
                        } else {
                                $_
                        }
        } @$masterList if $masterList;
}

#===========================================================================
====
# End Functions
#===========================================================================
====

Reply via email to