[spip-dev] [Spip-en] File locking on NFS : deadlocks : proposed solution with code

Hi,

Please find below a proposed solution to the file locking issue experience by Thomas from Bouncing Orange (message links below)

The main cause of the locks found (in my opinion) is the fact that the files are stored on an NFS mounted file system. NFS and the locks don’t play nicely.

My code creates ‘hard links’ to the file that is being cached, and the lock is placed on the hard link.
The ‘main’ file is thus never locked.
This code has not been tested in a production environment.
Posted here to get opinions, and potential improvements.

diff attached.

Proposed routines:

function spip_fopen_lock($fichier,$mode,$verrou){
global $lockArray;
$fp = false;
if (file_exists($fichier) and !strpos($fichier,‘session’)) {
// do we already have a lockfile for this file?
if (is_array($lockArray) && in_array($ficher,$lockArray)) {
$fichier = $hardlinkfile;
} else {
// create unique hard link filename
$UUID = time()."_".$_SERVER[‘REMOTE_ADDR’];
$hardlinkfile = dirname($fichier)."/".basename($fichier).$UUID."_lock";
try {
$lock=link($fichier,$hardlinkfile);
} catch (Exception $e) {
return false; }
}
$fp = @fopen($hardlinkfile,$mode);
if ($fp){
$lockArray[$fp]=array(‘hardlinkfile’=>$hardlinkfile,‘originalfile’=>$fichier);
//session_set(‘filelocks’,serialize($lockArray)); }
} else {
$fp = @fopen($fichier,$mode);
}
return ($fp)?$fp:False;
}

function spip_fclose_unlock($handle){
// remove old lock file
global $lockArray;
@fclose($handle);
$result = @unlink($lockArray[$handle][‘hardlinkfile’]);
if ($result){
$lockArray[$handle] = ‘’; // just because I am paranoid.
unset($lockArray[$handle]);
}
}

Messages refer:
http://www.mail-archive.com/spip-en@rezo.net/msg00435.html
http://www.mail-archive.com/spip-en@rezo.net/msg00514.html

flock_hardlink_diff.php (1.98 KB)

Hi,

i'm not sure to understand the intention of your patch as it stores
locks in a global array that can not be shared between concurrent
processus.

Locking file is not a matter of avoiding one processus to write in the
same file in parrallel, but avoiding 2 concurrent processus, each with
no knowledge of the other one, to try to write into same file at the
same time.

NFS and locking is actually a trouble as NFS don't come with locking
feature and this one has to be installed and configured separately.
However, a lot of SPIP website based are running on NFS with no
deadlock.

Runing without locking is not an issue for a website with somme
traffic as corrupted files can be seen due to statistical collision.

The better way is really to have NFS locking feature active and
working, but as a workaround there is a manual locking management
integrated to SPIP :
http://trac.rezo.net/trac/spip/browser/branches/spip-2.0/ecrire/inc/nfslock.php

As you can see it's a bit more complicated than expected.
I think Thomas has tried it but it leads to same trouble with end
locking. Or am I wrong ?

Maybe another way to be considered by Thomas would be using CacheCool plugin
http://www.spip-contrib.net/Cache-Cool,3251

As this plugin delay the cache computation (and writing) in a job
queue with some grant of no concurrency and locking based on sql
delete atomic operation, it could be expected that it will help to
reduce the occurency of deadlocking.

Regards,
Cédric MORIN