By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,189 Members | 1,559 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,189 IT Pros & Developers. It's quick & easy.

flock and reading file into array

P: n/a
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('visinterval');
$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.
Jul 17 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
> but is it required when reading a file into an array?
Yes, flock is required in your situation. Using 'file()' does not change
anything.
also - if the attempt to get a lock on the file fails (in the first example),
how do I retry?

I recommend blocking variant of 'flock()'

DG
--
Ask yourself: are you ready for the enterprise ?
Jul 17 '05 #2

P: n/a
Thanks for the tip - I'll check it out.

"Drazen Gemic" <dg****@net.net> wrote in message
news:pa********************************@net.net...
but is it required when reading a file into an array?

Yes, flock is required in your situation. Using 'file()' does not change
anything.
also - if the attempt to get a lock on the file fails (in the first example), how do I retry?

I recommend blocking variant of 'flock()'

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

not if the only language I've got is php...
Jul 17 '05 #3

P: n/a
deko wrote:
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('visinterval');
$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?


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('visinterval');
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 :
Jul 17 '05 #4

P: n/a
> 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('visinterval');
usleep(100);
--$num_tries;
}
?>

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

Jul 17 '05 #5

P: n/a
deko wrote:
<?php
$ctr = 'counter';
$got_it = false;
$timeout = 10;
$fp=fopen($ctr, 'w');
if ($fp === false) die("Unable to open $ctr for writing.\n");
while (($got_it === false) && ($timeout != 0))
{
if (flock($fp, LOCK_EX))
{
$counter = file($ctr); //do file operation after getting lock
# 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");
$curct = each($counter);
# $curct is an array, you're not using it anywhere. Why do this at all?
fwrite($fp, "0");
# not tested for failure. I'd do
if (!fwrite($fp, "0")) die("Unable to write to $ctr.\n");
flock($fp, LOCK_UN);
# not tested for failure
fclose($fp);
# not tested for failure
$got_it=true;
}
else
{
usleep(1000);
--$timeout;
}
} if (!$got_it)
{
# $fp is still opened and pointing to $ctr! You never closed it.
$fp=fopen('ctr_last_update', 'w');
# Are you sure you want to clear the file?
# ... maybe opening in append mode would be better
fwrite($fp,date("F d Y H:i:s.", fileatime($ctr)));
# 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(date("F d Y H:i:s.", fileatime($ctr)), 3, 'ctr_last_update')) {
die("Unable to write error_log.\n");
}
//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?
seems ok, though a little short on tests for failure (which you should
always do)
Also, as for error handling, can you point me to any resources for best
practices regarding error handling in php?


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 :
Jul 17 '05 #6

P: n/a
> 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.
the manual. Anyway file() just reads the file, it will never write
anything to it.


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 ?
Jul 17 '05 #7

P: n/a
> > $ctr = 'counter';
$got_it = false;
$timeout = 10;
$fp=fopen($ctr, 'w');
if ($fp === false) die("Unable to open $ctr for writing.\n");


do I really need this? see revised code below
while (($got_it === false) && ($timeout != 0))
{
if (flock($fp, LOCK_EX))
{
$counter = file($ctr); //do file operation after getting lock


# Ah! seems you can lock the file for reading after all :)


yes, but I don't think it matters - as you mentioned before - all this does is
read - no locks required.
# but you're not testing if the function failed ...
see revised code below
if ($counter === false) die("Unable to read $ctr.\n");
$curct = each($counter);
# $curct is an array, you're not using it anywhere. Why do this at all?


$curct is used a bit later in the script

snip...
# Are you sure you want to clear the file?
yes.
seems ok, though a little short on tests for failure (which you should
always do)


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('visinterval_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($viscounter);
$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('visinterval_missed', 'a');
fwrite($fp,date("F d Y H:i:s.", fileatime($ctr)));
exit;
}
Jul 17 '05 #8

P: n/a
> 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.


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 ???
Jul 17 '05 #9

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


nevermind.... I figured it out - the problem is I need some sleep...
Jul 17 '05 #10

P: n/a
Drazen Gemic wrote:
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.
the manual. Anyway file() just reads the file, it will never write
anything to it.


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.


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 :
Jul 17 '05 #11

P: n/a
deko wrote:
* as for tests for failure, isn't that all wrapped up in the last if statement:
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 (????).
=========== REVISED CODE =============
$got_it = false;
$timeout = 10;
$viscounter = file($ctr);
file() can fail
$curct = each($viscounter);
$fp=fopen($ctr, 'w');
fopen() can fail; and then $fp won't be a valid file pointer
while (($got_it === false) && ($timeout != 0))
{
if (flock($fp, LOCK_EX))
Are you sure $fp is a valid file pointer? :)
{
fwrite($fp, "0");
flock($fp, LOCK_UN);
$got_it = true;
}
else
{
usleep(100000);
A tenth of a second seems too large a value
--$timeout;
<nitpicking> get a better name for this variable! </nitpicking>
}
}
fclose($fp);
//if cd not get lock after 10 tries (1 sec.),
//skip this interval and record failure
if (!$got_it)
{
$fp=fopen('visinterval_missed', 'a');
fwrite($fp,date("F d Y H:i:s.", fileatime($ctr)));
exit;
}


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 :
Jul 17 '05 #12

P: n/a
Pedro Graca <he****@hotpop.com> wrote in message news:<c3*************@ID-203069.news.uni-berlin.de>...
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):


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 incrementVisitorHistory() we successfully
updated the log.", "incrementVisitorHistory");
} else {
$perms = fileperms($fileName);
$success2 = chmod($fileName, 0777);
if ($success2) {
$success3 = @fwrite($fp, $fileContent);
@fclose($fp);
if ($success3) {
$resultsObject->notes("In incrementVisitorHistory(), we
successfully updated the log. Some changes to file permissions were
necessary.", "incrementVisitorHistory");
} else {
$resultsObject->error("Error: In incrementVisitorHistory(), we
were unable to update the visitor log. The file permissions were:
$perms. We tried to change the file permissions, but we failed.",
"incrementVisitorHistory");
}
} else {
$resultsObject->error("Error: In incrementVisitorHistory() we were
unsuccessful in updating the log. The file permissions were: $perms.
We tried to change these permissions but we failed.",
"incrementVisitorHistory");
}
}
Jul 17 '05 #13

P: n/a
"deko" <dj****@hotmail.com> wrote in message news:<DG*******************@newssvr25.news.prodigy .com>...
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.


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


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_path():

http://www.php.net/manual/en/functio...clude-path.php
Jul 17 '05 #14

P: n/a
Pedro Graca <he****@hotpop.com> wrote in message news:<c3*************@ID-203069.news.uni-berlin.de>...
deko wrote:
<?php
$ctr = 'counter';
$got_it = false;
$timeout = 10;
$fp=fopen($ctr, 'w');


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


# 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");
$curct = each($counter);


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


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


# not tested for failure
fclose($fp);


# not tested for failure


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.
Jul 17 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.