Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

file open - read -write problem

Posted on 2000-02-16
19
Medium Priority
?
206 Views
Last Modified: 2010-03-05
I'd like to open file, read file , modify file, rewrite file and then close file.
It is done like this:

if(open(FILE_USERS,"<FILE_USERS"))
{@fileUsers=<FILE_USERS>;
 modifyFile(@fileUsers);
 if(open(FILE_USERS,">FILE_USERS"))
  {print FILE_USERS "$NewFileContent";}
 close(FILE_USERS);
}

This works fine, but when 2 users connect almost simultaneously the problem arise in that way:

1) User 1 reads file
2) User 2 reads file (not supposed until User 2 finish with the file)
3) User 1 modify file
4) User 2 modify file
5) User 1 rerecords and close file
6) User 2 rerecords and close file

So actually User 2 doesn't see modification made to file by user 1 becouse he reads file before it recorded by user 1. And all modification made by user 1 is lost.

Is there any way prevent user 2 read and modify file until User 1 (who opened file first) finished?
0
Comment
Question by:serg111
  • 8
  • 5
  • 4
  • +2
19 Comments
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2528546
If you are on an O/S that supports flock, you can use it, as follows:

if(open(FILE_USERS,"<FILE_USERS"))
{
 flock(FILE_USERS,LOCK_EX);
 @fileUsers=<FILE_USERS>;
 modifyFile(@fileUsers);
 if(open(FILE_USERS,">FILE_USERS"))
  {print FILE_USERS "$NewFileContent";}
 close(FILE_USERS);
 flock(FILE_USERS,LOCK_UN);
}

This works as long as both users are accessing the file through the same script.  I.e. both have to attempt the flock.

Rob

0
 
LVL 3

Expert Comment

by:guadalupe
ID: 2528554
Use the perl flock() command:

flock(FILEHANDLE, 1) #To lock

flock(FILEHANDLE, 0) #To unlock
0
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2528563
BTW: you can read the details in perlfunc, i.e.:

perldoc -f flock

The second argument specifies the type of lock, or action.  Thus, LOCK_EX says lock the filehandle exclusively (i.e. no one else can access it, will it is locked); the LOCK_UN says unlock the filehandle.  This is a blocking lock, so if the flock never gets a lock for whatever reason it will continue waiting indefinitely.

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Author Comment

by:serg111
ID: 2529237
It looks like flock() doesn't work:
I tested following code

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_CLIENTS1, 2);
open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_CLIENTS1, 8);

Both flock returns 1
and both open() successfully opened file.

Regards
0
 
LVL 2

Author Comment

by:serg111
ID: 2529244
Sorry there is misspelling in code it should look like h

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_USERS1, 2);
open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_USERS1, 8);

0
 
LVL 85

Expert Comment

by:ozo
ID: 2529284
Did you open FILE_CLIENTS1?
0
 
LVL 2

Author Comment

by:serg111
ID: 2529304
in both cases open() return 1

Thanks
0
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2529933
You misunderstand the purpose of flock.  It will block indefinitely if called the second time with LOCK_EX (i.e. 2), waiting for someone to unlock the file.  It is an advisory lock, not a real file-system lock.  So, before you try to open a file that might have multiple processes access it, you try to lock it first with flock.  If some other, cooperating, process has a valid flock on the file, your flock will sit and wait.  When it returns, then you are safe to go on and open the file.  Thus, if you try the following, your script will hang:

$iRet=flock(FILE_CLIENTS1, 2);               #  2 (LOCK_EX) here
open(FILE_USERS1,"<$filePath");


$iRet=flock(FILE_CLIENTS1, 2);               #  2 (LOCK_EX) here, also.
open(FILE_USERS2,">>$filePath");

The second will block forever.  It is protecting the file like it should.

Hope this clarifies it for you.

Rob
0
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2529942
Well, if I could get it in the right order, it would help:

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_CLIENTS1, 2);               #  2 (LOCK_EX) here


open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_CLIENTS2, 2);               #  2 (LOCK_EX) here, also.
 

In other words, you may open successfully, but don't mess with it until you get a successful lock.

Rob
0
 
LVL 2

Author Comment

by:serg111
ID: 2531361
OK.
I have tested this code

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_CLIENTS1, 2);
open(FILE_USERS2,"<<$filePath");
$iRet=flock(FILE_CLIENTS2, 2);  

For first time it worked fine (first flock() return 1 and second doesn't return.
But when I call script now first flock() doesn't return. So it looks like it is locked forever. When I added $iRet=flock(FILE_CLIENTS2, 8) it does not help. Is there any way to remove the lock?

0
 

Expert Comment

by:Whitty
ID: 2531371
You should use flock() as follows:

open(FILE_USERS1,"<$filePath");
$retVal=flock(FILE_CLIENTS1, 2);               #  Performs and exclusive lock
# Process file as needed
$retVal=flock(FILE_CLIENTS1, 8);               #  Removes the lock
close(FILE_CLIENTS1);

Although the file is automatically "unlocked" when closed, it is a good idea to manually perform the unlock just to be safe.

Now if the same application is called again, for say the second user, the flock() for the second user will wait until any existing locks are released.

For info, see the Perl Cookbook, pg. 245.

Hope this helps...

Whitty

                       
0
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2531491
Just realized I cut and pasted the wrong code.  The FILEHANDLES don't match up.  

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_USERS1, 2);               #  2 (LOCK_EX) here


open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_USERS2, 2);               #  2 (LOCK_EX) here, also.


 

0
 
LVL 2

Author Comment

by:serg111
ID: 2532117
More:

This code works fine with other files. I'm quite happy with it, but I still have prblem with one file "clients/M" where this code is not working.
I tested this file first and probably it remains locked.

Any ideas please
0
 
LVL 3

Accepted Solution

by:
RobWMartin earned 120 total points
ID: 2532240
Odd that it is stuck like that.  However, to break the lock, you just need to unlink the file.  As root,

cp thefile{,.bak}
rm thefile
cp thefile{.bak,}

Rob
0
 

Expert Comment

by:Whitty
ID: 2532279
Are you implementing an unlock call?

flock(FILE_CLIENTS1, 8);               #  Removes the lock

Whitty
0
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2532502
Don't think that works if some other (rampaging) process has it locked.  If I understand serg111's (current) problem, it's that one of his initial tests with locking still has the file locked somehow(?????)  Requires intervention outside the flock function.

Rob
0
 

Expert Comment

by:Whitty
ID: 2532624
If that is the case, killing the rampaging process would terminate the lock.  Perl's built-in cleanup would handle this by closing any open file handles.  When a file is closed, the lock is automatically terminated (it's just good practice to do it manually prior to the close).

Whitty
0
 
LVL 3

Expert Comment

by:RobWMartin
ID: 2532809
Agreed, but the file removal method above doesn't require serg111 to look for the rampaging process.  I'm still not certain how the file can still be locked.  Unless, serg111 is in bash and did ^Z vs ^C.

????

Rob
0
 

Expert Comment

by:Whitty
ID: 2532836
Good point.  Since serg111 hasn't responded to any of our comments for a while, I assume everything is working now?!?

Whitty
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question