Clipper 5.x

Clipper a fondo, solo para entendidos
Por Diego Lucio D'Onofrio

 

(01/Abr) Segunda entrega : Índices .NTX sólidos como la roca.


Bienvenidos a esta segunda entrega, me alegra de que estén aquí ya que esto significa que les ha gustado la primera.
Hoy, sin demasiadas vueltas hablaré sobre las RDD's y los índices NTX.

Las Replaceable Database Drivers (RDDs) en español Manejador reemplazable de bases de datos, son soportadas por Clipper a partir de su versión 5.0
El objetivo de una RDD como su nombre lo indica (reemplazable) es permitir el uso de varios manejadores de bases de datos distintos y simultáneos si es necesario.
Esto permite crear índices con formatos y compatibilidades distintas, por ejemplo los .MDX compatibles con dBase IV, los CDX compatibles con FoxPro y los .DB compatibles con Paradox.

La RDD nativa de Clipper es la "DBFNTX", la cual funciona en forma transparente al programador al punto que ni siquiera hace falta incluir la librería en tiempos de compilación.
Debido a su arquitectura requieren de ciertos métodos especiales de uso cuando se utilicen en programas que trabajan en una red, donde se abren y actualizan simultáneamente por dos o mas estaciones de trabajo.
En la actualidad los índices .NTX tienen fama de volverse inconsistentes con gran facilidad, esto en realidad no es así, solo que hay que tomar ciertas medidas que hasta hoy no figuran detalladas en ningún manual de los que he leído.

En primer lugar voy a nombrar la incompatibilidad con los viejos índices .NTX debido a varios cambios en su estructura el nuevo RDD nativo de Clipper "DBFNTX" no es compatible con los viejos índices de Clipper .NTX a pesar de poseer la misma extensión. El intento de abrir índices creados con versiones anteriores de Clipper 5.0 provocará un error irrecuperable en tiempo de ejecución y rara vez indicará un mensaje relacionado a índices corruptos ó RDD incompatible, por lo que será algo complicado determinar donde se encuentra el problema.

El culpable del 99% de las inconsistencias de los índices .NTX de trabajo en red es el diseño de la RDD que compete al manejo del tiempo de vida de los bloqueos, en pocas palabras a la manera en que se manejan los tiempos de espera.

Es muy común que al tratar de abrir una base de datos en red utilicemos algún control para determinar he informar si esta está bloqueada, por ejemplo:

DbUseArea(.T., [...]
Whil NetErr()
  @... Say "Base en uso exclusivo, reintentando apertura"
DbUseArea(.T., [...]
EndD

De esta manera alentamos a los usuarios a esperar o dar aviso del problema, también es común que al tratar de bloquear una base de datos o un registro se haga algo similar como muestra el siguiente ejemplo:

[...]
Whil !Flock()
  @... Say "Base bloqueada, reintentando..."
EndD
[...]
Whil !Rlock()
  @... Say "Registro #" + AllTrim(Str(RecNo())) + " bloqueado, reintentando..."
EndD
[...]


Este tipo de controles se realizan debido a que si un ordenador que tiene un registro bloqueado se "cuelga" este quedará bloqueado para todas las demás estaciones, cosa que es común en las redes ocupadas por varios usuarios y que también sucede cuando el usuario deja la aplicación en un segundo plano en sistemas multitarea sin suficientes recursos como para mantener la conexión activa, en este caso la mayoría de las redes termina por desconectar al usuario por tiempo de espera agotado "Time Out".

Estos métodos adoptados por los programadores lo que hacen es que el usuario no piense que su máquina se ha colgado y la reinicie provocando así la corrupción de bases de datos, en su lugar si ve que se ha extendido por mucho tiempo el mensaje optan por llamar al administrador de redes quien simplemente busca y desconecta la estación que no está haciendo petición (Request).
Si no existiesen estos mensajes todas las PC's conectadas a la red parecerían estar "colgadas".

Con los índices ocurre algo similar, hay que mostrar un mensaje si se encuentra bloqueado por los mismos motivos, ya que Clipper bloquea el índice después de escribir la base y si lo encuentra bloqueado se queda en espera infinitamente hasta que sea factible bloquearlo con lo cual si el usuario supone que su estación ha dejado de responder y la re inicia provocará sin lugar a dudas la ruptura del índice en cuestión.

Como el bloqueo y desbloqueo de los índices se realiza en forma transparente al programador, hay que determinar la falla en bloqueo utilizando un manejador de errores (errorhandler).

El manejador de errores original devuelve siempre verdadero (.T.) a este error sin mostrar ningún mensaje, cosa que está bien si trabajamos en sistemas monousuarios, pero en redes esto es un verdadero horror.

A continuación muestro un ejemplo de cómo manejar estos errores basándome en el archivo
NTXERR.PRG que viene en los ejemplos de Clipper.

Init Proc InitHandler()
LOCAL bDefError := ErrorBlock( { |err| LockErrHandler( err, bDefError ) } ) 
// Carga en la variable bDefError el manejador de errores actual.
Retu

Static Func LockErrHandler( oErr, bDefError ) // El nuevo manejador.
If ( oErr:genCode == 41) // corresponde al error de bloqueo de índices
  @... Say "Índice bloqueado por otra estación, NO reinicie su PC"
  @... Say "Si el error persiste informe a su administrador de sistemas"
Retu .T.
EndI
Retu ( eval( bDefError, oErr ) ) // Devuelve el control de errores al manejador original.

Si bien este código viene con Clipper no es mencionado por el manual con el énfasis necesario que creo merece, muchas veces es mas fácil migrar a otros RDD's que no necesiten este tipo de manejos pero como verán no es tan complicada la cosa.

La semilla del problema se haya en el momento del bloqueo, para los .NTX el driver bloquea el índice en el momento de accederlo y después de haber escrito la base, no se si esto puede ser llamado "bug" o simplemente una manera de hacer las cosas, pero de lo que si estoy seguro es de no haber encontrado manual, guía o tutorial que lo mencione y siendo un tema tan delicado me pareció coherente incluirlo en esta publicación.

Esta sección sobre CA-Clipper está coordinada íntegramente por Diego Lucio D'Onofrio


la Luna del Guille o... el Guille que está en la Luna... tanto monta...

Estadísticas desde el 01/Nov/2002 23:15