PDA

Ver la Versión Completa : Multiusuario + Buffers = mal negocio...


aprendiz2
10-04-2007, 05:15:57
Hola amigos !!! Ojala alguien pudiese mostrarme una solucion al siguiente problema:

Aparentemente Win... mantiene algunas operaciones de lectura escritura en buffers locales, cuando se esta leyendo / escribiendo a una unidad de red.

Esto es problematico si se esta trabajando en "multiusuario-concurrente" (asi se dice ? ), bueno, donde varios nodos accesan archivos de datos comunes, y toman decisiones basados en estos archivos centrales.

Ejemplo ( como comprobar este problema ):

Asumir que existen 2 PC en red local, y en una PC tenemos la unidad "K:" que se refiere al disco duro en la otra PC.

Si en el OnClick de un boton ponemos:

var F : File of char;
ch : char;
begin
AssignFile( F,'K:\ArchivoX.txt' );
Reset( F ); { Asumimos que ya existe ese archivo y contiene algo..}
Read( F, ch );
CloseFile( F );
end;

Entonces pruebe lo siguiente....

Con una mano, haga clic en el boton periodicamente...
Con la otra mano, ( sin hacer mucho ruido... ) desconecte el cable de red de esta maquina... mientras que con la otra mano usted sigue dando clics al mouse...

Que sucede...?

En teoria, el programa deberia dar un error tan pronto se desconecta el cable, pero no lo hace !!!. Sigue reportando que el archivo se lee correctamente !!!! Pruebelo y me dice...

( tendre un wireless en mi PC sin darme cuenta ? )

Ahora, pruebe cambiar la instruccion read( F,ch ), por un write(F,ch)
y hacemos lo mismo... ( comenzamos con el cable de red conectado, haciendo clics, y sigilosamente desconectamos el cable de red... )

El programa sigue corriendo bien !!!!. ( sera solo en mi PC que sucede esto ? )


Esto no es nada saludable para aplicaciones concurrentes multiusuario...
( a menos que todas esten solo leyendo datos que nunca cambian ! ).

Tambien se aplica a las tablas del BDE...

Asuma que tenemos una tabla en otra PC, y estamos conectados por una red.

Coloquemos la tabla en modo Cache,

y en un boton el Database.ApplyUpdates( ... )
al final del proceso de actualizacion puede ponerle Table1.Close si lo desea, lo cual daria la "ilusion" que realmente termino la transaccion y todo se grabo bien...

Ahora la prueba de fuego...algo diferente a la anterior ( algo drastica )

Mantenga una mano cerca del cable AC que alimenta a su PC.
Haga algun cambio a la tabla, dele clic al boton con el ApplyUpdates,

y despues que el boton haya salido...

desconecte el cabe de AC !!! ( apagado instantaneo ! ).

Ahora verifique la informacion en la otra PC....

Se actualizo ? no !!! permanecio igual !!! El cambio nunca llego. El cambio permance en la maquina fuente por un periodo de tiempo...antes de ser enviado a la otra...

Pruebe diferentes lapsos de tiempo... despues de darle clic al boton.. espere un segundo, o dos... y despues apague la PC... haga la prueba con 3 segundos de diferencia... asi averiguara el lapso de tiempo que se tarda en enviar los datos...

Pruebe con tablas que no estan en Cache.... se sorprendera...

Probando muchas cosas, solo he dado con un Table1.FlushBuffers, lo cual provoca envio instantaneo de la informacion, pero hace las operaciones con las tablas muuuuuuuuuuuy lentas.

En el caso de manejo de archivos en "binario", lo mismo, hay que andar buscando el handle de ese archivo, y llamar a un API de Win.. para hacer un flush... para medio garantizar que los datos lleguen a su destino en tiempo real, o proteste en caso que no se haya podido. Tambien se pone todo sumamente leeeeento...

Como se puede escribir un programa multi-usurario confiable con este comportamiento ? Los buffers son mal negocio en la concurrencia...

Delphi tiene buffers, Win mas buffers, la PC que recibe del otro lado de la red tiene mas buffers y el disco duro ha de tener una buena porcion de buffers tambien... a saber si manejados de buena forma o no...

Alguna buena solucion ?

Muy agradecido !

Lepe
10-04-2007, 10:01:09
Creo recordar que tienes que quitar "la compartición simple de carpetas" en el explorador de windows, herramientas, opciones de carpeta, pestaña Ver. Al tiempo de compartir una carpeta, se tiene la opción de NO cachear dicha unidad localmente.

Saludos

aprendiz2
10-04-2007, 17:47:43
Existe una opcion en las herramientas del Sistema (en XP ), para quitar el cache de todo el disco duro... pero parece que entra en la conocida rutina:

HazParpadearElPunteroUnRato()
PrendeLaLuzDelDiscoDuro( Muchas_Veces)
DesconectaElRaton( Unos_Instantes )
Sleep( 5000 )
HazParecerQueSeHizoAlgo( RefrescarVentana_Lento )
/* Rutina por mejorar en algun futuro */

Chris
16-04-2007, 21:53:09
Los buffers se inventaron exatamente para evitar esas "lentitudes" si tu quieres sacrificar rendimiento por seguridad es cosa tuya, auque siempre debes considerar el rendimiento.
Lo mejor que puedes hacer es implementar una solución mixta, me explico, utilizar la api de windows para "espiar" los cambios realizados por otros usuario a los archivos y tambien para detectar la desconección del cable.

para "espiar" las modificaciones de los archivos puedes implementarlo con un thread con las funciones FindFirstNotification y FindNextNotification y luego de detectar una modificacion notificarle al usuario que "los cambios que ha realizado no han servido de nada porque otro usuario se le ha adelantado, ¿desea descartar los cambios realizados por el otro usuario e imporner los suyos?" no es buena idea, por eso si te fijas en word, este al momento de abrir un documento te notifica que otro usuario lo está utilizando y cualquier modificacion que le vayas a hacer no será guardada, que esperes tu turno hasta que el otro usuario cierre el documento.

Con respecto a los registros de las tablas, puedes implementar algo similar, es más fácil porque mayormente los componente de tablas no permiten que dos usuarios modifique el mismo registro al mismo tiempo.

Detectar si el cable se ha desconectado, no se el nombre del mensaje que no notifica, pero seguramente que existe, sino fijate en WinXP que te notifica cuando el cable de red se ha desconectado.