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

Hi All, My apologies for not being here for a while. Thank you all for showing me directions to my concerns. i will now share snippet of my code (which is not working yet). As of now i have five lines in the text file, wherein each perl process has to execute only one line upon meeting the conditions i.e "it should match the line which has the word pending". P.S Somehow when i post this script all the indentation vanishes.apologies for that. My script
use Fcntl qw(:flock :seek); my $myfile = "C:\\ssk\\A.txt"; open(MYFILE, $myfile) or die; undef $/; flock(MYFILE, 1); foreach my $line (<MYFILE>) { $line =~ /(\w*):(\w*):(\w*)/g; my $status = $3; if (($3 ne "done") || ($status ne "inprogress")) { # do nothing } } close MYFILE; open(MYFILE, "+< $myfile") || die; flock(MYFILE, 2); my @content = <MYFILE>; my $inprogress = "inprogress"; foreach my $line (@content) { $line =~ m/(\w*):(\w*):(\w*)/; if ($3 eq "pending") { $line=~ s/pending/inprogress/; seek(MYFILE, 0, SEEK_END); print MYFILE "$line"; splice(@content,0,1); } } close MYFILE; Contents of text file ===================== cmd:doscommand1:pending cmd:doscommand2:pending cmd:doscommand3:pending cmd:doscommand4:pending cmd:doscommand5:pending
Please let me know if i am on the right track, since the script is not working yet.. Do i still need to go ahead with DBMS.

thanks Sachu

Hi All, I have a query in Perl. IS it possible for me to access and modify a single text file through PERL programmes. Can you please provide pointers on how to achieve this. Ok Let me make it more clear ... Let me give you all a brief scenario of what my intentions are. What i am trying to do is,i have to run multiple perl programmes all at once to change the contents of a text file. and the text file would contain 2 things. Test name and status. So as i run multiple perl programmes, i want each prgm to read single line at once and check the status. if the status is pending , change status to inprogress execute that line, and then change the status to done and come out of the programme, else skip to the next line till it finds pending. Just wanted to make sure, this would give access denied error, as the file would be used by another programmes. Hope that helps. Regards, SSK

Replies are listed 'Best First'.
Re: Multiple Acess to a single file
by psini (Deacon) on Aug 29, 2008 at 23:03 UTC

    If I understand correctly, what you want is to concurrently access a single data file from multiple processes.

    I don't think you can do it in any simple way on a plain text file, but you can do it easily with any DBMS, even a simple one as SQLite that doesn't require a database server but stores the entire db in a single file.

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

      Hi All, My apologies for not being here for a while. Thank you all for showing me directions to my concerns. i will now share snippet of my code (which is not working yet). As of now i have five lines in the text file, wherein each perl process has to execute only one line upon meeting the conditions i.e "it should match the line which has the word pending". P.S Somehow when i post this script all the indentation vanishes.apologies for that. My script
      use Fcntl qw(:flock :seek); my $myfile = "C:\\ssk\\A.txt"; open(MYFILE, $myfile) or die; undef $/; flock(MYFILE, 1); foreach my $line (<MYFILE>) { $line =~ /(\w*):(\w*):(\w*)/g; my $status = $3; if (($3 ne "done") || ($status ne "inprogress")) { # do nothing } } close MYFILE; open(MYFILE, "+< $myfile") || die; flock(MYFILE, 2); my @content = <MYFILE>; my $inprogress = "inprogress"; foreach my $line (@content) { $line =~ m/(\w*):(\w*):(\w*)/; if ($3 eq "pending") { $line=~ s/pending/inprogress/; seek(MYFILE, 0, SEEK_END); print MYFILE "$line"; splice(@content,0,1); } } close MYFILE; Contents of text file ===================== cmd:doscommand1:pending cmd:doscommand2:pending cmd:doscommand3:pending cmd:doscommand4:pending cmd:doscommand5:pending

      Please let me know if i am on the right track, since the script is not working yet.. Do i still need to go ahead with DBMS.

      thanks Sachu

Re: Multiple Acess to a single file
by ww (Archbishop) on Aug 29, 2008 at 23:10 UTC
    I think you need to clarify a bit: You seem want to run multiple scripts simultaneously, each of which may (or may not) modify a single list of tests to be run. How many tests? What sort of load does each put on your system(s)? Each test against the same program or data source or each against multiple files or ???

    This has huge potential for mischief, even if you can make it work (or, "work reliably"), and seems unlikely to be faster than using forks or threads for the various tests to be executed.

    In any case (and this is merely a guess based on insufficient information), any bottlenecks are apt to have their roots in disk access and RAM limits.

    And, for the record, please see such topics as How do I post a question effectively? and Markup in the Monastery.
Re: Multiple Acess to a single file
by SilasTheMonk (Chaplain) on Aug 29, 2008 at 23:25 UTC

    Sachu,

    Why do you want to store this state information in a single file? I think the solutions get a lot easier if you look at a broader array of structures.

    First of all in order to do what you are saying you need to use the seek function to move to a particular place in a file. Secondly you would need to make sure that each record (i.e. test status pair) had a fixed length so that you could navigate easily through the file. You would - as you guess - need to deal with the issues of file locking. File locking is operating system specific and that is always best avoided.

    I can see at least three better options:

    • Use a database. You would need a simple table with two columns "test" and "status". I recomend the DBI module for handling databases.
    • Instead of using a single file, use a single directory. Each record would be represented by a single file. I don't like this option - it looks like a lot of work.
    • You could use the DB_File module to create a simple file based database. This makes some effort at solving the locking problem, but by its own admission it is flawed. It would at least work and be fairly easy and not depend on getting your hands on a database.

Re: Multiple Acess to a single file
by shmem (Chancellor) on Aug 29, 2008 at 23:42 UTC
    What i am trying to do is,i have to run multiple perl programmes all at once to change the contents of a text file.

    You seem to be a bit lazy on thinking through the implications of that approach, and want us to do the work. Furthermore, it looks like you have an XY problem.

      Well i did try my bit, but instead of DBMS i tried for simple perl scripting. I would be posting snippet of my code for further view. thanks for your suggestion and help. SSK
Re: Multiple Acess to a single file
by eosbuddy (Scribe) on Aug 29, 2008 at 23:32 UTC
    In addition to the above mentioned choices, there is another elegant one: which is to combine your multiple processes into one program and fire the different functions as different threads perhaps using Thread::Queue.
Re: Multiple Acess to a single file
by hangon (Deacon) on Aug 30, 2008 at 08:15 UTC

    Assuming that your requirement is to use the text file, you have no control over its format, and the lines are not guaranteed to be of equal length, then you cannot do this concurrently. You should be able to accomomplish what you want serially using file locking, but performance may not be acceptable if your file is large. Have each program gain an exclusive lock (see flock), slurp the file, search it and update the line, then rewrite the file and release the lock. Note that all programs that access the file must use flock on it for this to work.