Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Includes within includes

by msk_0984 (Friar)
on Dec 23, 2006 at 05:02 UTC ( [id://591418]=perlquestion: print w/replies, xml ) Need Help??

msk_0984 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Respected Monks,

        I have been assigned a task to open a File which contains of some lines of code ( rules not much to worry about) and the main ones are the include lines which is nothing but as

include "/opt/netcool/etc/rules/include-snmptrap/adaptec-AdaptecArray +Controller-MIB.include.snmptrap.rules" include "/opt/netcool/etc/rules/include-snmptrap/adaptec-C +IOMIB.include.snmptrap.rules" include "/opt/netcool/etc/rules/include-snmptrap/adaptec-C +YCLONE-MIB.include.snmptrap.rules" include "/opt/netcool/etc/rules/include-snmptrap/allentele +com-ALLENTELECOM-MIB.include.snmptrap.rules"

        So these kind of include statements which consists of path about another device rules file and we have to open this file i.e think we have got the first inlcude statement from the file since its a inlcude statement grep out the complete file path and Open this file and see if it too contins any other inlcude statements in it if it has open them too and if it does not then start BAcking up the File and then agian back track and back up the main file too... So back up all the file ...........

        So what i went for the solution is used up a Recursive type of method but my sir says that IF in the first file there r "n" number of inlcude statements and in the first inlcude statemanet after u open it agiang think there are another "n" inlcude statements then the completxity of the program would be come to order of O(n2) n square so he wants to reduce the complexity to O(n log n) and proposed me to go for THREADS but i did not feel the complexity would be reduced but the Memoru allocation and time complexity would be imporved ....

        So monks i need ur suggestions is there any other idea or we have to go by the recursive on or by the Threaded concpets.

Work Hard Party Harderrr!!
Sushil Kumar

Replies are listed 'Best First'.
Re: Includes within includes
by merlyn (Sage) on Dec 23, 2006 at 05:13 UTC
Re: Includes within includes
by throop (Chaplain) on Dec 23, 2006 at 05:44 UTC
    Sushil,

    Just how many files are reached through this cascade of includes? What's the upper bound — how large is the population of .rules files at your site? And just how fast do you need it to be? I'm currently using an edited version of Module::Dependencies to track the dependencies of a file that, in the end, calls (using include, use, do and backticks) about 55 other files and it takes less than 10 sec on a pentium, and that's while drawing a PostScript graph of all the relationships. Threads sound like overkill to me. If you're having to keep the entire contents of each file in memory and your files are huge (e.g. some combination of Perl code and DATA) then maybe you're getting into some problems, but your recursive approach sounds right to me.

      Hi

      Thanx for ur replies and coming to the topic actually i am working this out in LINUX and here we are using it temporarily for a file which has around 100 include statements and again in each inlcude file there may be around 1 to 10 ranging depinding on the type of device rules file. So here its just parent and a Child level ......

      Firstly we want to test it our for at leat 2 to 3 levels of includes within include files. Coming to the fastness as you said it not a big problem about it will be OK if it takes adequate amount of time.

      i shall also jus give out a sample code which is presently backing up the files which are not having any inlcude statements and also recursively searching for the inlcude into the Depth........

      #!/usr/bin/perl use strict; my $first_path = "/opt/netcool/etc/test.rules"; &srch_include($first_path); my ($incl_full_path , $dir_path, $file_name) ; sub srch_include { my ($main_path) = @_ ; print " First Sub Path : $main_path \n"; open( FH1, "$main_path") or die " Sub1 Error: $! \n "; my @main_file_cont = <FH1>; my $count = 0; foreach my $main_file_line ( @main_file_cont ) { if( $main_file_line =~ /^(\s+)?include\s+"(.*)"$/) { my $count++; $incl_full_path = $2 ; print " Inlcudes :: $incl_full_path \n "; $incl_full_path =~ /(.*\/)(.*)/; $dir_path = $1 ; $file_name = $2; print " Dir : $dir_path File : $file_name \n "; system ("mkdir -p /root/msk/$dir_path"); sleep 2 ; open(CR, ">/root/msk/$incl_full_path") or die " Main + File Error: $! \n"; print CR " @main_file_cont "; close(CR); &srch_include($incl_full_path); } } if($count == 0 ) { #print " $incl_full_path has No includes and lookup \n "; $incl_full_path =~ /(.*\/)(.*)/; $dir_path = $1 ; $file_name = $2; #print " Dir : $dir_path File : $file_name \n " system ("mkdir -p /root/msk/$dir_path"); sleep 2 ; open(CR, ">/root/msk/$incl_full_path") or die " No Includ +e Error: $! \n"; print CR " @main_file_cont "; close(CR); } }
      here i am able to back the files with no inlcude statements and also the files which has inlcudes i am backing up the main file too and then searching and gooing into the depth . So jus check ot out and i shall be waiting for ur replies and thank you very much for ur help....
      Work Hard Party Harderrr!!
      Sushil Kumar
        Are these rules files generated by a program, or have they been hand coded? If the latter, you probably want to check for single quotes around the filename too, rather than just double quotes.

        You've got my $count twice (as strict will warn you.) The value of $count isn't going to make it out of the if statement, so your $count == 0 test will always succeed.

        In your

        $main_file_line =~ /^(\s+)?include\s+"(.*)"$/
        the (\s+)? is obfusciated; \s* is much clearer and efficient.

        Are you sure you don't have any circular dependencies in your include statements? You aren't testing for them. If there is one... well, endless loops take a long time to finish. Also, how do you want to handle the case where there are overlapping dependencies? E.g, A includes B and C; B and C each include D. Do you really want D and its dependencies to be searched twice?

        throop

Re: Includes within includes
by rodion (Chaplain) on Dec 23, 2006 at 14:42 UTC
    First, let me add my votes to those above of merlyn and throop. Recusion is all you need and threads will only complicate the code and confuse those reading it. For example, you've got a "sleep 2;" in your code. If that is there to be "nice" and let other code run. A threaded version might run faster just because it's diluting the effect of the sleep, not because it's any more efficient. If it's there because a delay is needed, you will have to think about this need in the context of multiple threads running simultaneously. You may even have two threads trying to create the same directory at the same time, if the include branches overlap. (You may want to check if the directory exists, before you make it, even in the recursive case.)

    Looking at your code, one big problem stands out with regard to recursion. "FH1" needs to be localized in some way (as you'll see in merlyn's article). I think most people today would do this by putting the file handle in a scaler variable. Just put a

    my $fh1;
    at the top of your srch_include() sub, and replace "FH1" with "$fh1". That should take care of the problem. There are other ways to take care of this. You can localize a file handle with a simple "local *FH1;", but it's an old way of doing things. You can also accomplish what you need just by closing the file handle so that it can be reused. You can use "IO::File" as mentioned in merlyn's article. For me "my $fh1;" is the best of the choices.
Re: Includes within includes
by sgt (Deacon) on Dec 23, 2006 at 16:01 UTC

    Another approach (?) is to generate commands for a simple (?) machine. Depending on the size of the things you want to process, the "machine" can be stopped in one place and started again. If the files don't change, you keep a cache of the commands.

    For example suppose you just want to read all lines of included files in chunks. One obvious command could be 'read file byte-range'. The command generator would start reading a given file and emit a read command when finding the '^include ' line, push a seek command on a internal stack to come back to the file after the include, and start with the included file right away looking for more includes. When done it would process the stack.

    "grep -n '^include '" comes to mind for quick prototyping.

    hth --stephan,

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://591418]
Approved by madbombX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-04-19 23:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found