AS/400 - Saber si registro está siendo usado.

 
Vista:

Saber si registro está siendo usado.

Publicado por Erick Henríquez (5 intervenciones) el 14/01/2017 18:54:28
Buenos días,

Quisiera de su ayuda para saber cómo puedo saber si un registro está siendo usado cuando le hago un CHAIN a una tabla, es decir, si alguien en mi programa está modificando el registro 1 pero hay otra persona que también quiere modificar el registro 1, lo que sucederá es que al segundo luego de unos segundo le mostrará mensaje de error, entonces yo quiero que siempre se verifique en el CHAIN si es registro está siendo usado, y si lo está mandar un mensaje al usuario, y no aparezca el error del sistema.

Muchas gracias por la ayuda que me puedan brindar.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Juan
Val: 133
Oro
Ha mantenido su posición en AS/400 (en relación al último mes)
Gráfica de AS/400

Saber si registro está siendo usado.

Publicado por Juan (82 intervenciones) el 15/01/2017 12:02:23
Saludos,

Pero no tendrías ese problema, si defines en tu programa el archivo como de ACTUALIZACION el propio programa al ser llamado y al hacerle un chain bloquea el archivo por lo que dos personas no podran entrar en el mismo registro a la vez, el primero que entre lo bloquea, solo se libera al salir del programa o si por código, una vez actualizado utilizas la instrucción UNLOOK ( archivo ).

Juan Pelaez - ISGAL
[email protected]
610 284 683
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Saber si registro está siendo usado.

Publicado por Erick Henríquez (5 intervenciones) el 16/01/2017 16:38:43
Muchas gracias Juan por tu respuesta.

Te omento que el archivo esta como de actualización, y en efecto, el primero que entra lo bloquea, con eso no hay problema, pero cuando el segundo entra, cuando se lee el mismo registro, en el mismo programa, de un mensaje de error, entonces yo quiero controlar ese mensaje de error, que no aparezco el del sistema sino un mensaje controlado, eso es posible? Tendrías por ahí un ejemplo? Por cierto, es un RPG normal, no un ILE.

Muchas gracias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Juan pelaez
Val: 133
Oro
Ha mantenido su posición en AS/400 (en relación al último mes)
Gráfica de AS/400

Saber si registro está siendo usado.

Publicado por Juan pelaez (82 intervenciones) el 16/01/2017 17:04:48
La respuesta es SI, recuerdo hace tiempo haber hecho algo de eso, tendre que buscarlo .....
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Saber si registro está siendo usado.

Publicado por Erick Henríquez (5 intervenciones) el 20/01/2017 00:09:16
Ok, muchas gracias Juan, quedo pendiente!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Juan
Val: 133
Oro
Ha mantenido su posición en AS/400 (en relación al último mes)
Gráfica de AS/400

Saber si registro está siendo usado.

Publicado por Juan (82 intervenciones) el 20/01/2017 08:05:43
Te paso un artículo MUY interesante referente a lo que preguntas .....

Manejar errores en RPG


BIF de realimentación
Una función incorporada (BIF) de realimentación nos indica si una operación se ha ejecutado correctamente. En la Figura 1 pueden verse las BIF de realimentación más habituales utilizadas en RPG de formato libre. Todas estas BIF devuelven un valor indicador *On u *Off. Las BIF normalmente se utilizan en operaciones de E/S.

Figura 1 - BIF de realimentación más habituales

BIF Operaciones
%EOF Read, ReadE, ReadP, ReadPE
%Error Open, Close, Chain, Read, ReadE,
ReadP, ReadPE, Write, Update, Delete,
Commit, RolBk, Test
%Found Chain, Delete, SetLL, SetGT

Se puede escribir %EOF y %Found después de cualquier operación importante. Para comprobar si un registro no se ha encontrado en una operación Chain se escribiría:

chain clave archivo;
if not %found( archivo );
// Manejar condicion de "no se encuentra";
endif;

Tanto la BIF %EOF como %Found permiten utilizar un argumento opcional que define el origen de la realimentación. Si no se escribe ningún argumento, la BIF hace referencia a la última operación en que se haya especificado. Así pues, la BIF %Found siguiente hace referencia a archivo2, no a archivo1:

chain clave1 archivo1;
chain clave2 archivo2;
if not %found( );

La BIF %Error puede escribirse solamente después de una operación que especifique el expansor de error. Para verificar un error en una operación Write, escribiríamos:

write(e) format;
if %error();
// Manejar error
endif;

A diferencia de %EOF y %Found, %Error no tiene ningún argumento para definir el origen de la realimentación. La BIF %Error se escribe inmediatamente después de la operación a la que hace referencia. Verá que %Error es particularmente útil a la hora de comprobar valores válidos antes de convertir un tipo de datos a otro. El código siguiente comprueba una fecha *ISO de un campo entero antes de convertirlo en un tipo fecha:

test(de) *iso int;
if not %error()
fecha = %date( int: *iso );
endif;

Este fragmento de código impedirá un error explosivo en la BIF %Date. No obstante, las BIF de realimentación normalmente no pueden impedir los errores radiactivos. Si no se detecta un error en una operación Chain o Read significa que los campos de entrada mantendrán los valores de la última operación de E/S correcta. En vez de manejar el error, acabarán reutilizándose valores falsos.

Programación a la defensiva
La programación a la defensiva intenta evitar errores o, por lo menos, manejarlos elegantemente si ocurren. Muchas operaciones deben "protegerse" mediante código que evite errores. Esto puede parecer una tarea imponente, pero la breve lista de control de la Figura 2 abarca la mayoría de los errores potenciales. El código "guardián" frecuentemente sólo comprueba condiciones límite.

Figura 2 - Lista de control para programar a la defensiva

• Índice de matriz fuera de límites
• Posición de una subserie fuera de límites
• División por cero
• Truncamiento numérico

Para prevenir errores de índices de una matriz, puede utilizarse la BIF %Elem para verificar que el índice de la matriz hace referencia a un elemento de la matriz:

if idx >= 1 and idx <= %elem( matriz );
elem = matriz( idx );
endif;

Recuerde, por supuesto, que una comprobación de los límites de un índice no garantiza que el elemento de la matriz al que se hace referencia tenga datos válidos.

Para evitar errores de posición de una subserie, utilice la BIF %Len para comprobar que la posición inicial de la subserie es válida:

if pos >= 1 and pos <= %len( serie );
subserie = %subst( serie: pos);
endif;

Para impedir la división por cero, basta con asegurarse de que el divisor no es cero:

if y <> 0;
z = x / y;
endif;


El truncamiento numérico puede prevenirse utilizando definiciones de datos estándar para asignar el tamaño a los campos de forma uniforme:

d x s like( stdInt )
d y s like( stdInt )

y = x;

El código a la defensiva suele evitar los errores explosivos. Todos los ejemplos de este apartado acabarían en un mensaje de excepción si no estuvieran protegidos. Utilice código a la defensiva, siempre que sea posible, para prevenir errores que pueden preverse fácilmente.

Supervisión de errores Hasta ahora hemos visto cómo utilizar las BIF y la programación a la defensiva para evitar o manejar errores evidentes. Sin embargo, no todos los errores son obvios. Veamos un ejemplo sencillo:

z = (a - b) / (c - d);

Es el denominador lo que importa:

if (c - d) <> 0;
z = (a - b) / (c - d);
endif;

Pero este enfoque no es ideal puesto que la operación If sólo se ocupa de la mitad de la asignación. Esto tiene implicaciones en el rendimiento, en la legibilidad y en la facilidad de mantenimiento en el caso de ecuaciones más complejas. De todas formas, la solución anterior podría considerarse aceptable si fuera sólida. Pero no lo es. Pensemos en lo que ocurriría si (a - b) fuera un valor muy grande y (c - d) un valor muy pequeño: puede ocurrir un truncamiento. Y nuestro código a la defensiva no contempla esa posibilidad. Aquí es donde se necesita aplicar el sentido común. Si existe una remota posibilidad de que ocurra un error, entonces contrólelo y corríjalo:

monitor;
z = (a - b) / (c - d);
on-error;
z = 0;
endmon;

Este ejemplo utiliza un grupo monitor para verificar si ocurre un error. Los grupos monitor comprueban la existencia de errores en las operaciones entre la operación Monitor y la primera operación On-Error. Si ocurre un error, el control se le pasa al bloque de código On-Error pertinente. Si todas las operaciones son correctas, el control se le pasa a la operación EndMon. En este caso, el bloque monitor asigna 0 a z si ocurre un error.

Un grupo monitor puede incluir varias sentencias On-Error que verifiquen distintas condiciones de error, además de una sentencia On-Error genérica, como la del ejemplo anterior. El ejemplo siguiente supervisa explícitamente la división por cero (00102) y el truncamiento (00103):

monitor;
z = (a - b) / (c - d);
on-error 00102;
// Manejar división por cero
on-error 00103;
// Manejar truncamiento
on-error;
// Manejar otros errores
endmon;

La sentencia On-Error puede especificar múltiples condiciones de error separadas por un signo de dos puntos o utilizando las palabras reservadas siguientes:

• *Program Detecta las condiciones de excepción de programa 00100 a 00999.
• *File Detecta las condiciones de excepción de archivo 01000 a 09999.
• *All Detecta todas las condiciones de excepción, tanto de programa como de archivo.

Observe que las condiciones 00001 a 00099 no pueden supervisarse (puede consultarse la lista completa de condiciones en el Capítulo 5, "File and Program Exceptions/Errors", del manual ILE RPG Reference.

Los grupos monitor pueden anidarse. Si se produce un error dentro de grupos monitor anidados, el grupo más profundo que pueda detectar el error recibirá el control. Los grupos monitor no pueden detectar errores ejecutados en subrutinas independientes. Sin embargo, pueden detectar errores en procedimientos o programas a los que se llama que no detectan sus propios errores pero terminan con la condición 00202: Error en programa o procedimiento llamado. Si un procedimiento supervisa un error, la sentencia On-Error recibe el control. Si un procedimiento no contiene un grupo monitor, el control lo recibe la sentencia On-Error pertinente del procedimiento desde el que se llama.

Los grupos monitor anidados en el mismo procedimiento o en procedimientos anidados pueden añadir complejidad al código y la complejidad probablemente introducirá sus propios errores. Mi consejo es que simplifique. Dé por supuesto que cada procedimiento controlará su propia recuperación de errores.

Asegúrese de que la recuperación del error es completa y de que tiene el efecto buscado. Veamos el ejemplo siguiente:

monitor;
a = x;
b = y;
c = z;
on-error;
// Manejar errores
endmon;

¿Cómo debería manejar el código los errores? Puede ocurrir un error en cualquiera de las asignaciones. Supongamos que el código se ejecuta en un bucle. En la segunda iteración se produce un error en la segunda asignación. A a se le ha asignado un valor. Al asignar el valor de b se ha producido el error. C conserva el valor de la iteración anterior. Una forma de manejar un error es anularlo todo:

monitor;
a = x;
b = y;
c = z;
on-error;
a = 0;
b = 0;
c = 0;
endmon;

Este método funciona bien si a, b y c son dependientes y un error en cualquiera de los campos invalidaría los tres. En cambio, existen dos alternativas. La primera, anular todos los campos de resultados antes de asignarles un valor y utilizar el grupo monitor para detectar la excepción:

a = 0;
b = 0;
c = 0;

monitor;
a = x;
b = y;
c = z;
on-error;
// No hacer nada
endmon;

Este sistema funciona si se quieren asignar variables antes de que se produzca un error. Opcionalmente, el grupo monitor puede dividirse en tres grupos sencillos del tipo:

monitor;
a = x;
on-error;
a = 0;
endmon;

Esta técnica funciona si se quieren realizar las tres asignaciones, independientemente de que se produzcan o no errores. Incluso con un simple bloque de código, hay muchas formas de manejar errores. La estrategia adecuada es la que mejor refleje el propósito del código, pero sea la que sea, asegúrese de que el manejo de errores detecte los errores y se recupere de ellos cuando corresponda. Sobre todo, no oculte los errores:

monitor;
a = x;
on-error;
// No hacer nada
endmon;

Este código empeora las cosas al convertir un error explosivo en uno radiactivo.

Todos los ejemplos de errores de asignación que hemos visto acaban recuperándose asignando un valor por omisión (0). Siempre que sea posible, lo mejor es utilizar un tipo de recuperación de errores que permita que la aplicación siga ejecutándose. Pero, en algunos casos, los errores son tan graves que es necesario someterlos a examen. Eso no significa que el programa tenga que detenerse. Con frecuencia es suficiente con mostrar el error en pantalla, en un informe o en un archivo de registro y, a continuación, recuperarse y continuar con la ejecución.

Cuando se sigue este método, hay que capturar los detalles del error. En el caso de los errores de programa, puede encontrar los detalles en la estructura de datos de estado de programa. Si se trata de errores de E/S, encontrará los detalles en la estructura de datos de información de archivo. Ambas estructuras de datos incluyen subcampos que definen la condición de error, el ID de mensaje correspondiente y otros datos relevantes. Para capturar el error, en la operación On-Error hay que utilizar las palabras reservadas *Program y *File:

monitor;
// Hacer algo
on-error *program;
status = program.status;
on-error *file;
status = fileInfo.status;
endmon;

Hallará más información acerca de las estructuras de datos de información de programa y de archivo en el capítulo 5 de la publicación RPG Reference.

Procedimientos de finalización
Los programas finalizan de forma anómala por muchas razones: un error no verificado puede provocar una excepción; una sesión interactiva puede finalizar anormalmente; un usuario puede cancelar un programa con la opción 2 de Petición de sistema; un usuario puede interrumpir un trabajo; etcétera. ILE ofrece un medio uniforme de manejar todas las formas de finalización anómala. La API CEETRX registra un procedimiento de salida de usuario de finalización de entrada de pila de llamadas (procedimiento de finalización, para abreviar) que se ejecuta cuando la entrada de la pila de llamada finaliza sin devolver un valor a quien ha realizado la llamada. Un procedimiento de finalización permite salir de forma controlada después de una finalización anómala.

El programa ExitProc (Figura 5, incluida en la versión impresa de la revista) ejemplifica cómo utilizar un procedimiento de finalización. Llame al programa con el parámetro "1" para generar una excepción o llámelo con un parámetro "2" y luego seleccione la opción 2 de Petición de sistema para cancelar el programa. En ambos casos, recibirá el mensaje "CleanUp ran" que indica que el procedimiento de finalización se ha ejecutado al acabar el programa.

El programa ExitProc define el prototipo del procedimiento cleanUp que actuará como procedimiento de finalización. El prototipo setExitProcedure define los parámetros de la API CEETRX, que se llama para registrar el procedimiento cleanUp. El sistema llamará al procedimiento cleanUp si el programa finaliza de forma anómala.

Un procedimiento de finalización puede incluir el código que se quiera. El truco está en ser breve y conciso: no se arriesgue a escribir demasiado código, que podría provocar una excepción en el procedimiento de finalización. Lo nor mal es que quiera cerrar archivos, eliminar objetos temporales como por ejemplo espacios de usuario, o enviar un trabajo para que procese un lote de datos. Generalmente es buena idea proteger el código del procedimiento de finalización en bloques monitor. Si quiere obtener más información acerca de los procedimientos de finalización, consulte el apartado "Activation Groups and Control Flow APIs" .

Su turno
El RPG permite muchas formas de manejar errores. En concreto, las BIF de realimentación, las técnicas de programación a la defensiva, la supervisión de errores y los procedimientos de finalización son una base firme para controlar errores. La forma de utilizar esa base está en sus manos y depende de la estructura y propósito del código. El manejo de errores debe ser sencillo. Utilice métodos estándar para reforzar la arquitectura de la aplicación. Procure detectar los errores lo antes posible. Haga de la prevención una prioridad utilizando las BIF de realimentación y el código a la defensiva. Cuando la prevención falle, utilice la supervisión del código como base para la recuperación. Como último recurso, los procedimientos de finalización proporcionan un método de salir de forma controlada después de una anomalía.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar

Saber si registro está siendo usado.

Publicado por Jesús Acuña (17 intervenciones) el 06/02/2017 22:19:19
Debes especificar junto con el CHAIN el ampliador de código (E) para que no caiga el programa por el acceso del segundo usuario. Luego debes verificar si accedió al registro (%FOUND) o si ocurrió errror (%ERROR), en el caso de que haya ocurrido error debes verificar el código de error con %STATUS ( debe ser igual a 01218).

Sería conveniente que abrevies el tiempo de espera por bloqueo de registro con un CL en donde de previo a la ejecución del prog. se ejecuta una alteración temporal OVRDBF ... WAITRCD()

Puedes determinar el usuario que tiene asignado el registro con la estructura de datos de información del programa.

Ahonda esos puntos.

Jesús Acuña
www.cursos-as400.com
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Saber si registro está siendo usado.

Publicado por Juan Antonio (1 intervención) el 28/06/2020 07:27:49
Cuando se hace un 'Chain' a un archivo declarado de "U" (Update) se bloqueará aun cuando no encuentre el registro?

Entiendo que cuando se hace un CHAIN el archivo queda bloqueado y se libera hasta que se realiza una operación/acción (Write, Delete, Update) o hasta que se hace un Unlock al archivo... pero para el ejemplo que describo la diferencia es que no se encuentra el registro en el archivo, aun así el archivo queda bloqueado?

Gracias, Saludos!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Saber si registro está siendo usado.

Publicado por Jesús Acuña (17 intervenciones) el 28/06/2020 18:17:33
Hola Juan, lo primero que debemos distinguir es que una cosa es bloqueo de registro y otra cosa es bloque de objeto (en este caso del archivo).
El bloqueo de registro se produce cuando el archivo es abierto de actualización (hoja F en RPG) y se realiza un acceso a un registro (por READ o CHAIN), el registro quedará bloqueado hasta que lea otro registro, o hasta que acualice el registro o acceda a otro registro o ejecute el comando UNLOCK. Hasta acá estamos hablando de "bloqueo de registro", el archivo no está bloqueado pero si está en uso (como lo estaría por un comando RUNQRY o un DSPPFM) . El hecho que el archivo esté en uso (se haya definido como de actualización o no, en RPG) puede impedir que otro "job" trate de bloquearlo de forma exclusiva, por ejemplo si desde otro trabajo intenta hacer un CLRPFM o un CHGPF (dichos comandos requieren asignación exclusiva) no podrá hacerlo ya que el archivo está en uso (no depende de que el archivo este abierto como de actualización o no, sino por el simple hecho que está en uso)..

Por lo tanto que bloquee un registro no repercute en un bloqueo de archivo.

Espero te ayude el comentario.

Jesús Acuña
www.cursos-as400.com
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar