Jump to content

two users accessing same file simultaneously


DoorsRent

Recommended Posts

I have a .txt file I want to let users change through my various php functions (user interface is an html page).  I got it all working, but now I'm starting to think about what may happen if two users try to access the file at the same time.

 

For explanation's sake, the file is simply a list of names.  The user will enter a name into a text box and click either "Add" or "Remove".  The .txt file isn't actually opened until the button is clicked, so it is opened, change is made then closed all in whatever time it takes for the php commands to execute.

 

I know it's unlikely, but it is possible that two people will click their buttons at almost the same time.  How can I deal with this issue?

 

I just started looking into mysql.  Is that the way I should go here?

 

Thank you very much.

Link to comment
Share on other sites

The main problem is if one person opens the file, a second person opens a file, the first person saves his changes to the file, then the second person saves his changes to the file, the changes done by person one are overridden.

 

The simplest way is to lock people out while another person is editing the file, but this can be annoying. All major version control systems have ways of dealing with version conflicts, you may want to look into how successful version control systems like SVN handle conflicts.

Link to comment
Share on other sites

You can use flock() to prevent over writing of data. and for your fopen, just tell it, if it fails to try again, and maybe even a third time. But php is fast enough that just one retry should be enough to get the file after the other data has been written. By the way fclose also closes the lock.

Link to comment
Share on other sites

I've hit a snag with implementing this technique.

 

I've opened the file, locked it then read all the lines into an array.

 

The problem is I need to write the array back to the txt file.  Before I used fopen() I was simply using the file() function then file_put_contents() to put the data back into the text file.

 

The only way I can think of doing this is to close the file then reopen with "w+".  But that will negate the advantages of using fopen() and flock().

 

Any ideas?

Link to comment
Share on other sites

Try r+ as the option.

 

Then how do you actually delete the lines in the file.  What I have is an array that is 1 line shorter than the file.  I need to write the array to the file overwriting everything and then delete what will be the last line in the file since it will be extra.  Or, just completely clear the file before I write it.

Link to comment
Share on other sites

OK, just before creating a new file delete it using unlink(). But this could still allow simultaneous file access, because no lock can be attained, if the file does not exist. I think though at this point it would be better if you clearly stated your objectives for this project then maybe we can give you a complete solution.

Link to comment
Share on other sites

OK, just before creating a new file delete it using unlink(). But this could still allow simultaneous file access, because no lock can be attained, if the file does not exist. I think though at this point it would be better if you clearly stated your objectives for this project then maybe we can give you a complete solution.

 

Objectives:

o Have html page with text box and submit button.  User enters name into text box and clicks submit to remove the name from a .txt file on server.

o Multiple users will be using page and if one clicks "submit" right after another (but before the first one's process is finished) there could be problems.

 

Here's my code where I'm trying to use the flock() function but can't figure out how to write the data back to the file:

<?php

remove_name("bob");

function remove_name($name)
{


$file = fopen("names.txt", "r+");  //open file stream with read/write permission	
while(!flock($file, LOCK_EX));	//wait until we can lock file exclusively, then lock it

$data=fgetcsv($file); //fill names into array

print "Original array: ";
print_r($data);
print "<br>";
for ( $counter = 0; $counter <= count($data); $counter++)
{		
	if ($data[$counter] == $name)	
		unset($data[$counter]); 	//remove name from array		

}

print "Modified array:    ";
print_r($data);
print "<br>";

//write new array back to file while overwriting every other line
//note - array now has fewer elements than lines in file


flock($file, LOCK_UN); // release the lock
fclose($file);

}
?>

 

And my simple text file:

bill,bob,pam,tim,donald,scott

 

One possible solution I've thought of us to create a dummy file that the program must exclusively lock before it can modify the names file (without a lock).  Then I could just use the standard file() function and file_put_contents() function.  Kind of a workaround, but I think that will do the job.

Link to comment
Share on other sites

Well, I got the dummy lock method working.  At least I think so.  I haven't thought of a good way to test that two users (i.e. php processes) aren't accessing the file at the same time.  But, the .txt file is getting updated properly.

 

Code:

<?php

remove_name("bob");

function remove_name($name)
{


$permissions = fopen("permissions.txt", "r+");	//open the permissions file
while(!flock($permissions, LOCK_EX));	//wait until we can lock file exclusively, then lock it


$file = fopen("names.txt", "r+");  //open file stream with read/write permission
$data=fgetcsv($file); //fill names into array

print "Original array: ";
print_r($data);
print "<br>";
for ( $counter = 0; $counter <= count($data); $counter++)
{		
	if ($data[$counter] == $name)	
		unset($data[$counter]); 	//remove name from array		

}

print "Modified array:    ";
print_r($data);
print "<br>";

fclose($file);
unlink("names.txt");
$file = fopen("names.txt","w");
fputcsv($file, $data);	//write the array back to the file

flock($permissions, LOCK_UN); // release the lock
fclose($permissions);
fclose($file);

}
?>

 

I've been trying to wrap my head around mysql the past couple days.  I think I'll take a shot at using that.  It's by far a more functional system, but way overkill right now.  It will make it easier for upgrades to the system in the future though.

 

Thanks a lot for the help WolfRage.

Link to comment
Share on other sites

Although you seem to have a solution, I think there may be a better one. Simply create a while loop that will continue indefinitely (with an exit trigger) as long as the script is unable to change the name of the text file. So, the first script in will change the name and the second script in will wait until the name is changed back. Here is some mock code (not tested).

 

At the very least you need to first put a sleep() call within your while loop as the server will put as much CPU cycles as it can to run that loop. If there was ever a problem with the file that it simply got fubar'd and couldn't be opened you could crash the server. Which is why you should also implement a flag to exit the loop after n iterations to prevent an indefinite loop.

 

$loops = 0;
$file_ready = true; //Flag to determine if file is available

while (!rename('/path/names.txt', '/path/temp_names.txt'))
{
    //After 5 attempts exit the loop
    if ($loops==5)
    {
        $file_ready = false;
        break;
    }
    //Wait one second before trying again
    sleep (1);
}

if ($file_ready)
{
    echo "Unable to access file";
}
else
{
    //Read and write contents to file then rename back to original name

    rename('/path/temp_names.txt', '/path/names.txt');
}

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.