Per lockare i file utilizzeremo la funzione flock, la quale è accetta su qualsiasi sistema UNIX ma anche da Windows, quindi è indipendente dalla piattaforma.
PHP locka i files in maniera advisory ossia se ci si vuole poi nuovamente accedere bisognerà ottenere la medesima modalità di locking, di seguito la sintassi basica.
bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
Ora supponiamo di voler utilizzare il lock su di un file nascosto, che ipotizziamo ci segnali che stiamo facendo delle operazioni su files per quella specifica folder.
// Create lock file, with write permission.
$file_lock = fopen($folder_path.".lock", "w+");
if(isset($file_lock) && !empty($file_lock) ){
/* Test locking functionality: <- flock -x ./.lock sleep 20 -> */
/* LOCK_NB, don't block the script execute. */
$obtain_lock = flock($file_lock, LOCK_EX|LOCK_NB);
if(!$obtain_lock) {
error_log("Not obtain lock-> $file_lock , insert operation inside queue! \n", 0);
}
} else {
error_log("failed to create lock \n", 0);
}
// TO-DO .... Complex Code, with high computational time
/* Close and release .lock file. */
if(isset($file_lock) && !empty($file_lock) ){
error_log("Close lock file: $file_lock .\n", 0);
// flush output before releasing the lock
// fflush($file_lock);
flock($file_lock, LOCK_UN);
fclose($file_lock);
}
Nel codice sopra riportato ma anche allo snippet basico di utilizzo notate LOCK_EX, LOCK_NB queste sono due tipologie di locking sui file.
Le tipologie di lock possono essere:
- 1) LOCK_SH, per acquisire lock condivisi.
- 2) LOCK_EX, per acquisire un lock esclusivo come scrittore.
- 3) LOCK_UN, per rilasciare i lock siano essi condivi o esclusivi.
- 4) LOCK_NB, è un tipo particolare di LOCK_EX che ne permette la scrittura durante il locking.
Nel mio esempio cerco di ottenere un lock esclusivo se però fallisce il LOCK_EX tento ugualmente il LOCK_NB, avrete capito che utilizzo il file come schedulatore e non per scriverci su ottenendo un LOCK_NB. Possiamo anche opzionalmente lanciare un flush sul file lockato prima di lasciarne il lock specialmente qualora esso si sia utilizzato in scrittura.
L’ultimo parametro invece &$wouldblock, passabile per valore è opzionale ed è impostato su 1 se il blocco si blocca (EWOULDBLOCK errno condition), serve dettagliare ulteriormente il logging in caso di errore.
flock, restituisce un booleano true se il lock ha successo, false altrimenti, non a caso è molto comodo inserire l’istruzione flock dentro un if.