flock and reading file into array

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • deko

    flock and reading file into array

    Do I need to use flock() when reading a file into an array? It's possible that
    the file in question could be open at the time the file('filename' ) request is
    made. I realize flock() is required when opening a file with fopen() when there
    is contention for the file:

    $fp=fopen($ctr, 'w');
    //only write if we can get lock on file
    if (flock($fp, LOCK_EX))
    {
    fwrite($fp, "0");
    flock($fp, LOCK_UN);
    }
    else
    {
    //try again... how???????
    }
    fclose($fp);

    but is it required when reading a file into an array?

    $totals=file('v isinterval');
    $var=explode('| ',$totals[0]);
    $i24h = number_format($ var[0]);
    $i30d = number_format($ var[1]);
    $i365d = number_format($ var[2]);

    also - if the attempt to get a lock on the file fails (in the first example),
    how do I retry?

    Thanks in advance.


  • Drazen Gemic

    #2
    Re: flock and reading file into array

    > but is it required when reading a file into an array?[color=blue]
    >[/color]
    Yes, flock is required in your situation. Using 'file()' does not change
    anything.
    [color=blue]
    > also - if the attempt to get a lock on the file fails (in the first example),
    > how do I retry?
    >[/color]
    I recommend blocking variant of 'flock()'

    DG


    --
    Ask yourself: are you ready for the enterprise ?

    Comment

    • deko

      #3
      Re: flock and reading file into array

      Thanks for the tip - I'll check it out.

      "Drazen Gemic" <dgemic@net.net > wrote in message
      news:pan.2004.0 3.23.14.42.06.1 84631.683@net.n et...[color=blue][color=green]
      > > but is it required when reading a file into an array?
      > >[/color]
      > Yes, flock is required in your situation. Using 'file()' does not change
      > anything.
      >[color=green]
      > > also - if the attempt to get a lock on the file fails (in the first[/color][/color]
      example),[color=blue][color=green]
      > > how do I retry?
      > >[/color]
      > I recommend blocking variant of 'flock()'
      >
      > DG
      >
      >
      > --
      > Ask yourself: are you ready for the enterprise ?[/color]
      not if the only language I've got is php...


      Comment

      • Pedro Graca

        #4
        Re: flock and reading file into array

        deko wrote:[color=blue]
        > Do I need to use flock() when reading a file into an array? It's possible that
        > the file in question could be open at the time the file('filename' ) request is
        > made. I realize flock() is required when opening a file with fopen() when there
        > is contention for the file:
        >
        > $fp=fopen($ctr, 'w');
        > //only write if we can get lock on file
        > if (flock($fp, LOCK_EX))
        > {
        > fwrite($fp, "0");
        > flock($fp, LOCK_UN);
        > }
        > else
        > {
        > //try again... how???????
        > }
        > fclose($fp);
        >
        > but is it required when reading a file into an array?
        >
        > $totals=file('v isinterval');
        > $var=explode('| ',$totals[0]);
        > $i24h = number_format($ var[0]);
        > $i30d = number_format($ var[1]);
        > $i365d = number_format($ var[2]);
        >
        > also - if the attempt to get a lock on the file fails (in the first example),
        > how do I retry?[/color]

        I think you can't flock() a file() operation -- no such indication on
        the manual. Anyway file() just reads the file, it will never write
        anything to it.

        If you're sure the file exists, and file() fails, just wait a few
        microseconds and try again (you can use the same method to retry a lock
        that failed):

        <?php
        $totals = false;
        $num_tries = 10;
        while (($totals === false) && ($num_tries != 0)) {
        $totals = file('visinterv al');
        usleep(100);
        --$num_tries;
        }
        ?>
        --
        USENET would be a better place if everybody read: : mail address :
        http://www.catb.org/~esr/faqs/smart-questions.html : is valid for :
        http://www.netmeister.org/news/learn2quote2.html : "text/plain" :
        http://www.expita.com/nomime.html : to 10K bytes :

        Comment

        • deko

          #5
          Re: flock and reading file into array

          > I think you can't flock() a file() operation -- no such indication on[color=blue]
          > the manual. Anyway file() just reads the file, it will never write
          > anything to it.
          >
          > If you're sure the file exists, and file() fails, just wait a few
          > microseconds and try again (you can use the same method to retry a lock
          > that failed):
          >
          > <?php
          > $totals = false;
          > $num_tries = 10;
          > while (($totals === false) && ($num_tries != 0)) {
          > $totals = file('visinterv al');
          > usleep(100);
          > --$num_tries;
          > }
          > ?>[/color]


          Thanks, that helped. Here's what I've come up with:

          <?php
          $ctr = 'counter';
          $got_it = false;
          $timeout = 10;
          $fp=fopen($ctr, 'w');
          while (($got_it === false) && ($timeout != 0))
          {
          if (flock($fp, LOCK_EX))
          {
          $counter = file($ctr); //do file operation after getting lock
          $curct = each($counter);
          fwrite($fp, "0");
          flock($fp, LOCK_UN);
          fclose($fp);
          $got_it=true;
          }
          else
          {
          usleep(1000);
          --$timeout;
          }
          }
          if (!$got_it)
          {
          $fp=fopen('ctr_ last_update', 'w');
          fwrite($fp,date ("F d Y H:i:s.", fileatime($ctr) ));
          //echo date("F d Y H:i:s", fileatime($ctr) );
          exit;
          }
          ?>

          Seems to work... first, I get a lock on counter - if I can't, then I can't
          update the counter - so log the time of failure and quit. What do you think?
          Also, as for error handling, can you point me to any resources for best
          practices regarding error handling in php?

          thx



          Comment

          • Pedro Graca

            #6
            Re: flock and reading file into array

            deko wrote:[color=blue]
            ><?php
            > $ctr = 'counter';
            > $got_it = false;
            > $timeout = 10;
            > $fp=fopen($ctr, 'w');[/color]

            if ($fp === false) die("Unable to open $ctr for writing.\n");
            [color=blue]
            > while (($got_it === false) && ($timeout != 0))
            > {
            > if (flock($fp, LOCK_EX))
            > {
            > $counter = file($ctr); //do file operation after getting lock[/color]

            # Ah! seems you can lock the file for reading after all :)
            # but you're not testing if the function failed ...

            if ($counter === false) die("Unable to read $ctr.\n");
            [color=blue]
            > $curct = each($counter);[/color]

            # $curct is an array, you're not using it anywhere. Why do this at all?
            [color=blue]
            > fwrite($fp, "0");[/color]

            # not tested for failure. I'd do
            if (!fwrite($fp, "0")) die("Unable to write to $ctr.\n");
            [color=blue]
            > flock($fp, LOCK_UN);[/color]

            # not tested for failure
            [color=blue]
            > fclose($fp);[/color]

            # not tested for failure
            [color=blue]
            > $got_it=true;
            > }
            > else
            > {
            > usleep(1000);
            > --$timeout;
            > }
            > }[/color]
            [color=blue]
            > if (!$got_it)
            > {[/color]

            # $fp is still opened and pointing to $ctr! You never closed it.
            [color=blue]
            > $fp=fopen('ctr_ last_update', 'w');[/color]

            # Are you sure you want to clear the file?
            # ... maybe opening in append mode would be better
            [color=blue]
            > fwrite($fp,date ("F d Y H:i:s.", fileatime($ctr) ));[/color]

            # no locking now? :)
            # anyway, you're not testing the functions for failure.

            # remember to close the file
            if (!fclose($fh)) die("Unable to close $ctr.\n");

            # I do this with error_log() [and never worried about whether it locks
            # the file -- maybe I should]

            # instead of
            # fopen()
            # fwrite()
            # fclose()
            if (!error_log(dat e("F d Y H:i:s.", fileatime($ctr) ), 3, 'ctr_last_updat e')) {
            die("Unable to write error_log.\n");
            }
            [color=blue]
            > //echo date("F d Y H:i:s", fileatime($ctr) );
            > exit;
            > }
            > ?>
            >
            > Seems to work... first, I get a lock on counter - if I can't, then I can't
            > update the counter - so log the time of failure and quit. What do you think?[/color]

            seems ok, though a little short on tests for failure (which you should
            always do)
            [color=blue]
            > Also, as for error handling, can you point me to any resources for best
            > practices regarding error handling in php?[/color]

            Sorry, no. I don't know any.
            --
            USENET would be a better place if everybody read: : mail address :
            http://www.catb.org/~esr/faqs/smart-questions.html : is valid for :
            http://www.netmeister.org/news/learn2quote2.html : "text/plain" :
            http://www.expita.com/nomime.html : to 10K bytes :

            Comment

            • Drazen Gemic

              #7
              Re: flock and reading file into array

              > I think you can't flock() a file() operation -- no such indication on

              'flock()' is just a wrapper for system call(s). To read a file into
              array, a file MUST be open. 'file()' hides that functionality, bu it
              opens file as well.
              [color=blue]
              > the manual. Anyway file() just reads the file, it will never write
              > anything to it.[/color]

              THe problem is that other process might write to file, while reading
              operation takes place. That would lead to inacurate result, and that's
              why 'flock()' is needed.


              --
              Ask yourself: are you ready for the enterprise ?

              Comment

              • deko

                #8
                Re: flock and reading file into array

                > > $ctr = 'counter';[color=blue][color=green]
                > > $got_it = false;
                > > $timeout = 10;
                > > $fp=fopen($ctr, 'w');[/color]
                >
                > if ($fp === false) die("Unable to open $ctr for writing.\n");[/color]

                do I really need this? see revised code below
                [color=blue][color=green]
                > > while (($got_it === false) && ($timeout != 0))
                > > {
                > > if (flock($fp, LOCK_EX))
                > > {
                > > $counter = file($ctr); //do file operation after getting lock[/color]
                >
                > # Ah! seems you can lock the file for reading after all :)[/color]

                yes, but I don't think it matters - as you mentioned before - all this does is
                read - no locks required.
                [color=blue]
                > # but you're not testing if the function failed ...[/color]

                see revised code below
                [color=blue]
                > if ($counter === false) die("Unable to read $ctr.\n");
                >[color=green]
                > > $curct = each($counter);[/color]
                >
                > # $curct is an array, you're not using it anywhere. Why do this at all?[/color]

                $curct is used a bit later in the script

                snip...
                [color=blue]
                > # Are you sure you want to clear the file?[/color]

                yes.
                [color=blue]
                > seems ok, though a little short on tests for failure (which you should
                > always do)[/color]

                Thanks for the detailed post. I appreciate it.


                * I use error_reporting (0) at the top of this script - if the couter breaks,
                I'll know it by watching the output on the html page. I can live with the
                counter being off line for a while.

                * as for tests for failure, isn't that all wrapped up in the last if statement:

                if (!$got_it)
                {
                $fp=fopen('visi nterval_missed' , 'a');
                fwrite($fp,date ("F d Y H:i:s.", fileatime($ctr) ));
                exit; <======= *** bail out here if problems ****
                }


                =========== REVISED CODE =============
                $got_it = false;
                $timeout = 10;
                $viscounter = file($ctr);
                $curct = each($viscounte r);
                $fp=fopen($ctr, 'w');
                while (($got_it === false) && ($timeout != 0))
                {
                if (flock($fp, LOCK_EX))
                {
                fwrite($fp, "0");
                flock($fp, LOCK_UN);
                $got_it = true;
                }
                else
                {
                usleep(100000);
                --$timeout;
                }
                }
                fclose($fp);
                //if cd not get lock after 10 tries (1 sec.),
                //skip this interval and record failure
                if (!$got_it)
                {
                $fp=fopen('visi nterval_missed' , 'a');
                fwrite($fp,date ("F d Y H:i:s.", fileatime($ctr) ));
                exit;
                }


                Comment

                • deko

                  #9
                  Re: flock and reading file into array

                  > THe problem is that other process might write to file, while reading[color=blue]
                  > operation takes place. That would lead to inacurate result, and that's
                  > why 'flock()' is needed.[/color]

                  10-4

                  I know this is a bit of a switch of topics, but I was wondering if you know why
                  I'm getting this error:

                  Warning: Failed opening 'viscount' for inclusion
                  (include_path=' .:/usr/share/pear') in /home/post/public_html/index.php on line
                  69

                  the code is at the bottom of one of the pages in my site and is supposed to call
                  this counter script I've been working on

                  <?php
                  include ('viscount');
                  ?>
                  </body>
                  </html>

                  what is usr/share/pear ???


                  Comment

                  • deko

                    #10
                    Re: flock and reading file into array

                    > I know this is a bit of a switch of topics, but I was wondering if you know
                    why[color=blue]
                    > I'm getting this error:[/color]

                    nevermind.... I figured it out - the problem is I need some sleep...


                    Comment

                    • Pedro Graca

                      #11
                      Re: flock and reading file into array

                      Drazen Gemic wrote:[color=blue][color=green]
                      >> I think you can't flock() a file() operation -- no such indication on[/color]
                      >
                      > 'flock()' is just a wrapper for system call(s). To read a file into
                      > array, a file MUST be open. 'file()' hides that functionality, bu it
                      > opens file as well.
                      >[color=green]
                      >> the manual. Anyway file() just reads the file, it will never write
                      >> anything to it.[/color]
                      >
                      > THe problem is that other process might write to file, while reading
                      > operation takes place. That would lead to inacurate result, and that's
                      > why 'flock()' is needed.[/color]

                      Hmm, I see. Thanks for the info.

                      So, no functions in PHP do file locking internally?

                      Specifically error_log() with a message_type of 3 (append to
                      destination) should be coded with a flock() wrapper, too?

                      --
                      USENET would be a better place if everybody read: : mail address :
                      http://www.catb.org/~esr/faqs/smart-questions.html : is valid for :
                      http://www.netmeister.org/news/learn2quote2.html : "text/plain" :
                      http://www.expita.com/nomime.html : to 10K bytes :

                      Comment

                      • Pedro Graca

                        #12
                        Re: flock and reading file into array

                        deko wrote:[color=blue]
                        > * as for tests for failure, isn't that all wrapped up in the last if statement:[/color]

                        Yes, but this way way you will not know what failed.
                        Could be opening a file, writing to it (disk full?), or maybe even
                        closing it (????).
                        [color=blue]
                        >=========== REVISED CODE =============
                        > $got_it = false;
                        > $timeout = 10;
                        > $viscounter = file($ctr);[/color]

                        file() can fail
                        [color=blue]
                        > $curct = each($viscounte r);
                        > $fp=fopen($ctr, 'w');[/color]

                        fopen() can fail; and then $fp won't be a valid file pointer
                        [color=blue]
                        > while (($got_it === false) && ($timeout != 0))
                        > {
                        > if (flock($fp, LOCK_EX))[/color]

                        Are you sure $fp is a valid file pointer? :)
                        [color=blue]
                        > {
                        > fwrite($fp, "0");
                        > flock($fp, LOCK_UN);
                        > $got_it = true;
                        > }
                        > else
                        > {
                        > usleep(100000);[/color]

                        A tenth of a second seems too large a value
                        [color=blue]
                        > --$timeout;[/color]

                        <nitpicking> get a better name for this variable! </nitpicking>
                        [color=blue]
                        > }
                        > }
                        > fclose($fp);
                        > //if cd not get lock after 10 tries (1 sec.),
                        > //skip this interval and record failure
                        > if (!$got_it)
                        > {
                        > $fp=fopen('visi nterval_missed' , 'a');
                        > fwrite($fp,date ("F d Y H:i:s.", fileatime($ctr) ));
                        > exit;
                        > }[/color]

                        Glad you got it working !
                        --
                        USENET would be a better place if everybody read: : mail address :
                        http://www.catb.org/~esr/faqs/smart-questions.html : is valid for :
                        http://www.netmeister.org/news/learn2quote2.html : "text/plain" :
                        http://www.expita.com/nomime.html : to 10K bytes :

                        Comment

                        • lawrence

                          #13
                          Re: flock and reading file into array

                          Pedro Graca <hexkid@hotpop. com> wrote in message news:<c3q47j$29 i9s3$1@ID-203069.news.uni-berlin.de>...[color=blue]
                          > If you're sure the file exists, and file() fails, just wait a few
                          > microseconds and try again (you can use the same method to retry a lock
                          > that failed):[/color]

                          Well, you should get some info about the file, like the permissions.
                          You can also try a temporary chmod, which will work if PHP created the
                          file, or if you've set the permissions loose. Either way, get some
                          good information about that file, so you can write a good error
                          message. I get what info I can, though I plan to go back and redo this
                          little script so that I give myself a lot more information. I find
                          that as your code grows, having information rich error messages
                          becomes a big time saver.





                          $fp = fopen($fileName , "w+");
                          $success = @fwrite($fp, $fileContent);

                          if ($success) {
                          @fclose($fp);
                          $resultsObject->notes("In incrementVisito rHistory() we successfully
                          updated the log.", "incrementVisit orHistory");
                          } else {
                          $perms = fileperms($file Name);
                          $success2 = chmod($fileName , 0777);
                          if ($success2) {
                          $success3 = @fwrite($fp, $fileContent);
                          @fclose($fp);
                          if ($success3) {
                          $resultsObject->notes("In incrementVisito rHistory(), we
                          successfully updated the log. Some changes to file permissions were
                          necessary.", "incrementVisit orHistory");
                          } else {
                          $resultsObject->error("Error : In incrementVisito rHistory(), we
                          were unable to update the visitor log. The file permissions were:
                          $perms. We tried to change the file permissions, but we failed.",
                          "incrementVisit orHistory");
                          }
                          } else {
                          $resultsObject->error("Error : In incrementVisito rHistory() we were
                          unsuccessful in updating the log. The file permissions were: $perms.
                          We tried to change these permissions but we failed.",
                          "incrementVisit orHistory");
                          }
                          }

                          Comment

                          • lawrence

                            #14
                            Re: flock and reading file into array

                            "deko" <dje422@hotmail .com> wrote in message news:<DG58c.418 53$g_6.31999@ne wssvr25.news.pr odigy.com>...[color=blue][color=green]
                            > > THe problem is that other process might write to file, while reading
                            > > operation takes place. That would lead to inacurate result, and that's
                            > > why 'flock()' is needed.[/color]
                            >
                            > 10-4
                            >
                            > I know this is a bit of a switch of topics, but I was wondering if you know why
                            > I'm getting this error:
                            >
                            > Warning: Failed opening 'viscount' for inclusion
                            > (include_path=' .:/usr/share/pear') in /home/post/public_html/index.php on line
                            > 69
                            >
                            > the code is at the bottom of one of the pages in my site and is supposed to call
                            > this counter script I've been working on
                            >
                            > <?php
                            > include ('viscount');
                            > ?>
                            > </body>
                            > </html>
                            >
                            > what is usr/share/pear ???[/color]

                            Put this command in a blank text file:

                            <?php phpinfo(); ?>

                            Save that as info.php, upload it to your server, and then point your
                            browser at it. I think you'll find that your include path is
                            /usr/share/pear/, which tells you a little about the directory
                            structure of the server that you're dealing with.

                            You can get that specific info with get_include_pat h():


                            Comment

                            • lawrence

                              #15
                              Re: flock and reading file into array

                              Pedro Graca <hexkid@hotpop. com> wrote in message news:<c3qf2b$2b gthg$1@ID-203069.news.uni-berlin.de>...[color=blue]
                              > deko wrote:[color=green]
                              > ><?php
                              > > $ctr = 'counter';
                              > > $got_it = false;
                              > > $timeout = 10;
                              > > $fp=fopen($ctr, 'w');[/color]
                              >
                              > if ($fp === false) die("Unable to open $ctr for writing.\n");
                              >[color=green]
                              > > while (($got_it === false) && ($timeout != 0))
                              > > {
                              > > if (flock($fp, LOCK_EX))
                              > > {
                              > > $counter = file($ctr); //do file operation after getting lock[/color]
                              >
                              > # Ah! seems you can lock the file for reading after all :)
                              > # but you're not testing if the function failed ...
                              >
                              > if ($counter === false) die("Unable to read $ctr.\n");
                              >[color=green]
                              > > $curct = each($counter);[/color]
                              >
                              > # $curct is an array, you're not using it anywhere. Why do this at all?
                              >[color=green]
                              > > fwrite($fp, "0");[/color]
                              >
                              > # not tested for failure. I'd do
                              > if (!fwrite($fp, "0")) die("Unable to write to $ctr.\n");
                              >[color=green]
                              > > flock($fp, LOCK_UN);[/color]
                              >
                              > # not tested for failure
                              >[color=green]
                              > > fclose($fp);[/color]
                              >
                              > # not tested for failure[/color]

                              This is good advice, to test every return, to make no assumptions, but
                              I think you'll only want to use die() if you are writing code for fun,
                              or if you are just practicing. If you're building an application of
                              any scale, you'll need to get organized about your error messages. One
                              simple strategy, that I follow, is to store success messages in one
                              array, and errors in another array. When things go wrong, I can print
                              out both arrays, and then I can see exactly where everything went
                              right, and I can see the exact moment that things start to go wrong.

                              Comment

                              Working...