2012-01-26 15 views
8

Tengo una aplicación móvil que lee un archivo JSON que está almacenado en un servidor Apache. El contenido de ese archivo JSON se regenera (utilizando un script PHP) si algo se cambia a través de una GUI.¿Apache los archivos de bloqueo de lectura antes de servirlos?

Me preocupa que al tratar de sobrescribir el archivo JSON en el medio de Apache, esto pueda causar problemas.

¿Apache obtiene un bloqueo de lectura antes de servir los archivos? Si no, ¿qué pasará si intento escribirlo al mismo tiempo que se sirve?

+0

¿Realmente necesita un archivo 'físico' o puede simplemente falsificar el archivo simplemente emitiendo los contenidos? – PeeHaa

Respuesta

9

No. En sistemas compatibles con POSIX, todos los bloqueos son de todos modos asesores, por lo que incluso si apache obtiene un bloqueo de lectura, el otro proceso podría simplemente escribir el archivo.

Usted puede determinar que 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 

Por lo tanto, puede suceder que el archivo JSON está sólo parcialmente escrito. Para evitar este problema, escriba su archivo JSON en un archivo temporal en el mismo sistema de archivos y utilice el rename atómico para sobrescribir el archivo.

De esta forma, si el open ha tenido éxito, apache continuará publicando el archivo anterior. Si el rename finaliza antes del open, apache obtendrá el archivo nuevo y completo.

Si le preocupa la consistencia (en el caso de un corte de energía, o algo así), también puede llamar al fsync en la aplicación que escribe el archivo JSON antes de cerrarlo.

+0

Si utilicé PHP http://php.net/manual/en/function.flock.php y obtuve un bloqueo de escritura, ¿estaría bien? – cdmckay

+0

@cdmckay No, un bloqueo de escritura no tiene ningún efecto, ya que apache no obtiene un bloqueo de lectura. Extendí la respuesta. En resumen: use ['rename'] (http://php.net/rename). – phihag

+0

Por curiosidad, ¿por qué Apache no las lee? ¿Actuación? – cdmckay

1

Estás pensando en el paradigma incorrecto para las plataformas * nix. Lo que desea son las escrituras de archivos atómicos en el archivo JSON en su secuencia de comandos. Para ello, escriba el archivo en un nombre de archivo temporal único en el directorio de destino y luego use rename() para mover este archivo sobre el antiguo. La operación de mover archivos es atómica. Los procesos asíncronos abrirán el antiguo archivo JSON o el nuevo, pero no un híbrido.

Existen varias formas de construir un nombre de archivo temporal. Consulte los comentarios del usuario de la documentación de PHP en tempnam(). Mi sistema genera una ID única de solicitud, así que solo uso $_SERVER["UNIQUE_ID"] como base.

Cuestiones relacionadas