2012-01-26 14 views
8

Ho un'app mobile che legge un file JSON che è memorizzato su un server Apache. I contenuti di quel file JSON vengono rigenerati (usando uno script PHP) se qualcosa viene modificato tramite una GUI.Apache legge i file di blocco prima di servirli?

Sono preoccupato che il tentativo di sovrascrivere il file JSON nel mezzo servito da Apache potrebbe causare problemi.

Apache ottiene un blocco di lettura prima di servire i file? In caso contrario, cosa succederà se provo a scriverlo nello stesso momento in cui viene servito?

+0

Hai davvero bisogno di un file 'fisico' o puoi semplicemente falsificare il file semplicemente emettendo il contenuto? – PeeHaa

risposta

9

No. Sui sistemi POSIX-compatibili, tutti i blocchi sono comunque di consulenza, quindi anche se apache otterrebbe un blocco di lettura, l'altro processo potrebbe semplicemente scrivere il file.

È possibile determinare che con strace:

[pid 7246] open("/var/www/file.json", O_RDONLY|O_CLOEXEC) = 11 
[pid 7246] fcntl(11, F_GETFD)   = 0x1 (flags FD_CLOEXEC) 
[pid 7246] mmap(NULL, 20, PROT_READ, MAP_SHARED, 11, 0) = 0x7f53f93da000 
[pid 7246] munmap(0x7f53f93da000, 20) = 0 
[pid 7246] writev(10, [{"HTTP/1.1 200 OK\r\nDate: Thu, 26 J"}, ...) = 365 
[pid 7246] close(11)     = 0 

Pertanto, può accadere che il file JSON è solo parzialmente scritto. Per evitare questo problema, scrivere il file JSON in un file temporaneo sullo stesso file system e utilizzare l'atomico rename per sovrascrivere il file.

In questo modo, se lo open è riuscito, Apache continuerà a servire il vecchio file. Se lo rename termina prima dello open, apache otterrà il nuovo file completato.

Se si è preoccupati della coerenza (in caso di interruzione di corrente o così), è possibile anche chiamare fsync nell'applicazione che scrive il file JSON prima di chiuderlo.

+0

Se ho usato PHP http://php.net/manual/en/function.flock.php e ottenuto un blocco di scrittura, sarebbe OK? – cdmckay

+0

@cdmckay No, un blocco di scrittura non ha alcun effetto, poiché apache non ottiene un blocco di lettura. Ho esteso la risposta. In breve: usa ['rinomina'] (http://php.net/rename). – phihag

+0

Per curiosità, perché Apache non li legge? Prestazione? – cdmckay

1

Stai pensando al paradigma sbagliato per le piattaforme * nix. Quello che vuoi è la scrittura di file atomici nel file JSON nel tuo script. Lo fai scrivendo il file in un nome di file temporaneo univoco nella directory di destinazione, quindi utilizzando rename() per spostare questo file su quello vecchio. L'operazione di spostamento del file è atomica. I processi asincroni apriranno il vecchio file JSON o quello nuovo ma non un ibrido.

Esistono vari modi per creare un nome file temporaneo. Vedi i commenti degli utenti della documentazione di PHP su tempnam(). Il mio sistema genera un ID univoco della richiesta, quindi uso semplicemente $_SERVER["UNIQUE_ID"] come base.

Problemi correlati