2012-07-01 22 views
10

Esperaba usar System.INotify y System.IO.MMap juntos para ver las modificaciones de los archivos y luego realizar rápidamente diffs para enviar parches a través de una red. Sin embargo, en la documentación de System.IO.MMap hay un par de advertencias sobre transparencia referencial:Transparencia referencial y mmap en Haskell

La documentación indica

Sólo es seguro para mmap un archivo si sabe que es el único usuario. De lo contrario, la transparencia referencial puede o no verse comprometida. Lamentablemente, la semántica difiere mucho entre los sistemas operativos.

Los valores que los retornos son Mmap IO ByteString, seguramente cuando se utiliza este valor con putStr Estoy esperando un resultado diferente cada vez? Supongo que el autor quiere decir que el valor podría cambiar durante una operación IO como putStr y bloquearse?

COMIENZO DE LA EDICIÓN: Ahora que lo pienso, supongo que la respuesta a esta parte de la pregunta es algo obvio ... Si el valor cambia en cualquier momento después de que se haya desagrupado, sería problemático.

do 
    v <- mappedValue :: IO ByteString 
    putStr v 
    putStr v -- Expects the same value of v everywhere 

FIN-DE-EDIT

¿No debería ser posible adquirir algún tipo de bloqueo en la región asignada o en el archivo?

Como alternativa, ¿sería posible escribir una función copy :: IO ByteString -> IO ByteString que tome una instantánea del archivo en su estado actual de forma segura?

+0

Me parece que lo que quiere también se puede hacer con un simple par de tubos. – leftaroundabout

+0

Estoy "mirando" los archivos en un directorio de una manera un tanto genérica. Si alguna herramienta los toca, los clientes se actualizan automáticamente. –

+1

¿Realmente no hay una biblioteca mmap que ofrezca algo de tipo 'IO (Ptr Word8)' o similar? –

Respuesta

8

Creo que el autor significa que el valor puede cambiar incluso dentro de una función elevada que puede verse como simple ByteString (sin IO).

El archivo meory asignado es una región de memoria. No tiene mucho sentido copiar su contenido de un lado a otro, por razones de rendimiento (de lo contrario, uno podría hacer simplemente E/S antiguas basadas en secuencias). Entonces el ByteString que está recibiendo es en vivo.

Si desea tener una instantánea, solo use una E/S basada en flujo. Eso es lo que hace la lectura de un archivo: ¡crea una instantánea de archivo en la memoria! Supongo que una alternativa sería usar la interfaz ForeignPtr que no lleva la advertencia de transparencia referencial. No estoy familiarizado con ForeignPtrs así que no puedo garantizar que funcione, pero parece prometedor y lo investigaría.

También puede intentar llamar al map id en su ByteString, pero no se garantiza que obtendrá una copia distinta del original.

El bloqueo obligatorio de archivos, especialmente en Linux, es un desastre que es mejor evitar. El bloqueo de archivo de consulta está bien, excepto que nadie lo está usando, por lo que efectivamente no existe.

+2

Supongo que inconscientemente yo ' Estoy esperando demasiado de mi sistema operativo. Quería tratar el archivo, básicamente, como una memoria caché de memoria compartida muy rápida entre múltiples procesos, permitiendo que el sistema operativo se encargue de enjuagar los cambios en el disco a voluntad. Pensando en ello con más cuidado, creo que parece bastante poco probable que funcione a menos que todos los procesos utilicen explícitamente un mapa de memoria compartida. –

+0

(Ver, esperaba evitar incurrir en la latencia involucrada al tocar el disco físico ...) –