0

I'm using a very simple script where some users data are stored in a text file beside a database because this file needs to be read by a specific process on the system .

The php expire date update code for a line in the following format like this :

U: w w { enddate=2022-10-18 }

The function code goes like this:

                $date = "enddate=";
                $date .= setExpireDate($duration);
                $Read = file($fileDir);

                foreach ($Read as $LineNum => $line) {
                    $LineParts = explode(' ', $line);
                    if (count($LineParts) == 1) {continue;}
                    if ($LineParts[1] == $username) {
                        $LineParts[4] = $date;
                        $Read[$LineNum] = implode(' ', $LineParts);
                        break;
                    }
                }
                file_put_contents($fileDir, $Read, LOCK_EX);

some users have reported problems , after doing some search i found that the data in the database is updated fine , but the not in the text file as the data is not updated for some users .

as i think it is a file locking problem , that prevents some users under heavy load to write on the file , but the database can handle multiple writes just fine .

So is there anyway to handle the multiple writes on the file at the same time better than this ?

and is there a way to simulate this in php like locking the file by a form submit ?

i tried this :

function lock(){
    $fp = fopen("file.txt", "r+");
    flock($fp, LOCK_EX);

    echo "file is locked <br>";
}

but it is not working at all ,and others can write to the file .

P.S: I know there are a lot of questions about file locking ,but non of the answers did help !

Regards

2
  • 1
    The lock idea is right, but the code that attempts to amend the file has to check for the lock and if it cannot get it, wait until it can, then it has it's chance to amend the file Commented Oct 20, 2022 at 12:19
  • 1
    Another idea might be to use mysql locks as it supports waiting for the lock to be released, see stackoverflow.com/a/72801107/11656450 Commented Oct 20, 2022 at 12:29

1 Answer 1

1

Here is an example of the file locking approach

First you attempt to lock the Lock file, if you can all well and good proceed to edit the real file. If you cannot get a lock you retry until you can.

// this is not the file you are attempting to update, its just the lock file
// it must already exist and its bext if you place it in a specific directory, 
// not accessable from the web.

$fplock = fopen("/some/path/lock.txt", "r+");  

// attempt to get an exclusive lock on the lock file
while ( ! flock($fplock, LOCK_EX) ) {
    // this has failed to get the lock so do nothing but retry, 
    // it should be only milli seconds until the other process finishes
    // and releases the lock
}

// the lock must have been released by the other process when you get here
// or you got a lock on your first attempt and never ran the wait loop
// at this point this script has the lock

$date = "enddate=";
$date .= setExpireDate($duration);
$Read = file($fileDir);

foreach ($Read as $LineNum => $line) {
    $LineParts = explode(' ', $line);
    if (count($LineParts) == 1) {continue;}
    if ($LineParts[1] == $username) {
        $LineParts[4] = $date;
        $Read[$LineNum] = implode(' ', $LineParts);
        break;
    }
}
file_put_contents($fileDir, $Read, LOCK_EX);

/*
closing the lock file has the effect of releasing the lock, or simply finishing this 
script will do the same, but do it yourself as soon as you have finished updating the 
real file, so other process's dont have to wait until the script finishes, 
I assume you may have other code after this
*/

fclose($fplock);

Of course ALL scripts that access the Real File, must also attempt to lock the lock file before accessing the real file, or this all falls down in a mess.

Sign up to request clarification or add additional context in comments.

6 Comments

thanks for the answer , one last thing is there a way to lock the file on the system to test the code , because the lock is released as soon as the script finish as i think and i want to find a way to simulate this , any ideas ? regards
I found a way by using a text editor and it locked the file , but here is the result of testing the script you provided , fopen(file): Failed to open stream: Resource temporarily unavailable , which is ok , but for flock() it shows : Fatal error: Uncaught TypeError: flock(): Argument #1 ($stream) must be of type resource , and the script throw this error and stops ! so is this normal to stop the execution and throw an error ?
one thing to add that the flock() error is because fopen() returned false on the locked file
I ran a CLI script that set the lock and then did a sleep(20), long enough for me to then run the other script and see it waiting and then eventually get access
Dont use ms-word. Write another script to lock and sleep. That is a realistic test, using ms-word is not!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.