Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

file open - read -write problem

Posted on 2000-02-16
19
187 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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
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 84

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 40 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: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say 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

Suggested Solutions

Title # Comments Views Activity
remove duplicates from the csv file 13 114
syslog unix file 20 76
Executing multiple sybase statements in perl dbi 2 94
parse a file and get data out 11 76
I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
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…

840 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